From 2aa0e89d18de29ddc45118b58f12a355f574c92b Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Wed, 20 Dec 2006 15:24:28 +0000 Subject: [PATCH] Line endings fix --- Makefile.nmake | 82 +- audiowin.cc | 578 ++++++------- audiowin.h | 140 ++-- dsallocator.cc | 36 +- dsallocator.h | 14 +- dssourcefilter.cc | 872 ++++++++++---------- dssourcefilter.h | 32 +- dssourcepin.cc | 1138 +++++++++++++------------- dssourcepin.h | 32 +- mutex.cc | 102 +-- mutex.h | 94 +-- objects.mk | 34 +- osdwin.cc | 684 ++++++++-------- osdwin.h | 168 ++-- readme.win | 274 +++---- remotewin.cc | 560 ++++++------- remotewin.h | 122 +-- surfacewin.cc | 540 ++++++------- threadwin.cc | 264 +++--- timers.cc | 722 ++++++++--------- vaudioselector.cc | 462 +++++------ vaudioselector.h | 1 - vepg.cc | 1044 ++++++++++++------------ videowin.cc | 1980 ++++++++++++++++++++++----------------------- videowin.h | 316 ++++---- vompreswin.h | 92 +-- vompwin.rc | 198 ++--- winmain.cc | 1648 ++++++++++++++++++------------------- wtextbox.cc | 136 ++-- wwss.cc | 642 +++++++-------- 30 files changed, 6503 insertions(+), 6504 deletions(-) diff --git a/Makefile.nmake b/Makefile.nmake index d765ef2..013c476 100644 --- a/Makefile.nmake +++ b/Makefile.nmake @@ -1,41 +1,41 @@ -CXXFLAGS_DEV = -g -O0 -Wall -Woverloaded-virtual -Wshadow -Werror -DDEV -D_GNU_SOURCE $(INCLUDES) -CXXFLAGS_REL = /I"$(DXSDK_DIR)\Include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "NEW_DEMUXER" /nologo /EHsc /MD /GS /W3 /c /TP -LDFLAGS = /INCREMENTAL:NO /NOLOGO /NODEFAULTLIB /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /LIBPATH:"$(DXSDK_DIR)\Lib\x86" - -LIBS = Msvcrt.lib Ws2_32.lib shlwapi.lib d3d9.lib d3dx9.lib Iphlpapi.lib Strmiids.lib winmm.lib MSVCPRT.lib kernel32.lib user32.lib gdi32.lib ole32.lib uuid.lib - -CROSSLIBS = - -!include "objects.mk" - - -OBJECTSWIN = winmain.o threadwin.o remotewin.o ledwin.o mtdwin.o videowin.o audiowin.o osdwin.o surfacewin.o dsallocator.o dssourcefilter.o dssourcepin.o - -OBJECTS = $(OBJECTS1) $(OBJECTSWIN) - -#.PHONY: clean fresh all install strip - -default: release #dev - -release:: -CXXFLAGS= $(CXXFLAGS_REL) -release:: vompclient.exe - - - -vompclient.exe: $(OBJECTS) vompwin.res - link $(LDFLAGS) /OUT:"vompclient.exe" $(LIBS) $(OBJECTS) vompwin.res - - - -$(OBJECTS): $*.cc - $(CXX) $(CXXFLAGS) /Fo$*.o $*.cc - -vompwin.res:vompwin.rc - $(RC) /fo"vompwin.res" "vompwin.rc" - -clean: - del *.o - del vompclient.exe - del fonts\*.o - +CXXFLAGS_DEV = -g -O0 -Wall -Woverloaded-virtual -Wshadow -Werror -DDEV -D_GNU_SOURCE $(INCLUDES) +CXXFLAGS_REL = /I"$(DXSDK_DIR)\Include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "NEW_DEMUXER" /nologo /EHsc /MD /GS /W3 /c /TP +LDFLAGS = /INCREMENTAL:NO /NOLOGO /NODEFAULTLIB /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /LIBPATH:"$(DXSDK_DIR)\Lib\x86" + +LIBS = Msvcrt.lib Ws2_32.lib shlwapi.lib d3d9.lib d3dx9.lib Iphlpapi.lib Strmiids.lib winmm.lib MSVCPRT.lib kernel32.lib user32.lib gdi32.lib ole32.lib uuid.lib + +CROSSLIBS = + +!include "objects.mk" + + +OBJECTSWIN = winmain.o threadwin.o remotewin.o ledwin.o mtdwin.o videowin.o audiowin.o osdwin.o surfacewin.o dsallocator.o dssourcefilter.o dssourcepin.o + +OBJECTS = $(OBJECTS1) $(OBJECTSWIN) + +#.PHONY: clean fresh all install strip + +default: release #dev + +release:: +CXXFLAGS= $(CXXFLAGS_REL) +release:: vompclient.exe + + + +vompclient.exe: $(OBJECTS) vompwin.res + link $(LDFLAGS) /OUT:"vompclient.exe" $(LIBS) $(OBJECTS) vompwin.res + + + +$(OBJECTS): $*.cc + $(CXX) $(CXXFLAGS) /Fo$*.o $*.cc + +vompwin.res:vompwin.rc + $(RC) /fo"vompwin.res" "vompwin.rc" + +clean: + del *.o + del vompclient.exe + del fonts\*.o + diff --git a/audiowin.cc b/audiowin.cc index d13127e..7bae0be 100644 --- a/audiowin.cc +++ b/audiowin.cc @@ -1,289 +1,289 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "audiowin.h" -#include "videowin.h" - - - - - -AudioWin::AudioWin() -{ - initted = 0; - firstsynched=false; - winvolume=0; - volume=20; - - - -} - -AudioWin::~AudioWin() -{ - - -} - -int AudioWin::init(UCHAR tstreamType) -{ - if (initted) return 0; - initted = 1; - return 1; -} - -int AudioWin::shutdown() -{ - if (!initted) return 0; - initted = 0; - return 1; -} - -int AudioWin::write(char *buf, int len) -{ - return 0; //write(fdAudio, buf, len); -} - -int AudioWin::setStreamType(UCHAR type) -{ - if (!initted) return 0; - return 1; -} - -int AudioWin::setChannel() -{ - if (!initted) return 0; - return 1; -} - -int AudioWin::setSource() -{ - if (!initted) return 0; - return 1; -} - -int AudioWin::sync() -{ - if (!initted) return 0; - return 1; -} - -int AudioWin::play() -{ - if (!initted) return 0; - firstsynched=false; - return ((VideoWin*)Video::getInstance())->dsplay(); - -} - -int AudioWin::stop() -{ - if (!initted) return 0; - return ((VideoWin*)Video::getInstance())->dsstop(); -} - -int AudioWin::pause() -{ - if (!initted) return 0; - return ((VideoWin*)Video::getInstance())->dspause(); -} - -int AudioWin::unPause() -{ - if (!initted) return 0; - return ((VideoWin*)Video::getInstance())->dsunPause(); -} - -int AudioWin::reset() -{ - - if (!initted){return 0;} - return ((VideoWin*)Video::getInstance())->dsreset(); -} - -int AudioWin::setVolume(int tvolume) -{ - // parameter: 0 for silence, 20 for full - if ((tvolume < 0) || (tvolume > 20)) return 0; - winvolume=((tvolume-20)*100*30)/20; - if (tvolume==0) winvolume=-10000; - ((VideoWin*)Video::getInstance())->SetAudioVolume(winvolume); - - - return 1; -} - -int AudioWin::mute() -{ - if (!initted) return 0; - ((VideoWin*)Video::getInstance())->SetAudioState(false); - ((VideoWin*)Video::getInstance())->SetAudioVolume(-10000); - return 1; -} - -int AudioWin::unMute() -{ - if (!initted) return 0; - ((VideoWin*)Video::getInstance())->SetAudioState(true); - ((VideoWin*)Video::getInstance())->SetAudioVolume(winvolume); - return 1; -} - -void AudioWin::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos) -{ - mediapacket = mplist.front(); -} - -UINT AudioWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos) -{ - DeliverMediaPacket(mediapacket, buffer, samplepos); - if (*samplepos == mediapacket.length) { - *samplepos = 0; - return 1; - } - else return 0; -} - -UINT AudioWin::DeliverMediaPacket(MediaPacket packet, - const UCHAR* buffer, - UINT *samplepos) -{ - - /*First Check, if we have an audio sample*/ - VideoWin *vw=(VideoWin*)Video::getInstance(); - if (!vw->isdsinited()) return 0; - if (vw->InIframemode()) { - samplepos=0; - MILLISLEEP(10); - return 0; //Not in iframe mode! - } - IMediaSample* ms=NULL; - REFERENCE_TIME reftime1=0; - REFERENCE_TIME reftime2=0; - - UINT headerstrip=0; - if (packet.disconti) { - firstsynched=false; - vw->DeliverVideoMediaSample(); - } - - - - /*Inspect PES-Header */ -/* UINT header_length=buffer[(packet.pos_buffer+8)%bufferlength]+8/*is this right*; -*/ - if (*samplepos==0) {//stripheader - headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/; - *samplepos+=headerstrip; - if ( packet.synched ) { - vw->DeliverAudioMediaSample();//write out old data - /* if (packet.presentation_time<0) { //Preroll? - *samplepos=packet.length;//if we have not processed at least one - return packet.length;//synched packet ignore it! - }*/ - - reftime1=packet.presentation_time; - reftime2=reftime1+1; - firstsynched=true; - } else { - if (!firstsynched) {// - *samplepos=packet.length;//if we have not processed at least one - - return packet.length;//synched packet ignore it! - } - } - } - BYTE *ms_buf; - UINT ms_length; - UINT ms_pos; - UINT haveToCopy; - if (!vw->getCurrentAudioMediaSample(&ms) || ms==NULL) {// get the current sample - //samplepos=0; - MILLISLEEP(10); - return *samplepos; - } - ms_pos=ms->GetActualDataLength(); - ms_length=ms->GetSize(); - haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos); - if ((ms_length-ms_pos)<1) { - vw->DeliverAudioMediaSample(); //we are full! - if (!vw->getCurrentAudioMediaSample(&ms) || ms==NULL) {// get the current sample - //samplepos=0; - MILLISLEEP(10); - return *samplepos; - } - ms_pos=ms->GetActualDataLength(); - ms_length=ms->GetSize(); - haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos); - } - ms->GetPointer(&ms_buf); - - if (ms_pos==0) {//will only be changed on first packet - if (packet.disconti) { - ms->SetDiscontinuity(TRUE); - } else { - ms->SetDiscontinuity(FALSE); - } - if (packet.synched) { - ms->SetSyncPoint(TRUE); - ms->SetTime(&reftime1,&reftime2); - - //ms->SetTime(NULL,NULL); - ms->SetMediaTime(NULL, NULL); - if (reftime1<0) ms->SetPreroll(TRUE); - else ms->SetPreroll(FALSE); - }else { - ms->SetSyncPoint(FALSE); - ms->SetTime(NULL,NULL); - ms->SetMediaTime(NULL, NULL); - ms->SetPreroll(FALSE); - // ms->SetSyncPoint(TRUE); - } - } - - - memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy); - ms->SetActualDataLength(haveToCopy+ms_pos); - - *samplepos+=haveToCopy; - - return haveToCopy+headerstrip; - -} - -long long AudioWin::SetStartOffset(long long curreftime, bool *rsync){ - VideoWin *vw=(VideoWin*)Video::getInstance(); - return vw->SetStartAudioOffset(curreftime,rsync); -} - -void AudioWin::ResetTimeOffsets() { - VideoWin *vw=(VideoWin*)Video::getInstance(); - return vw->ResetTimeOffsets(); -} - -#ifdef DEV -int AudioWin::test() -{ - return 0; -} -#endif - - - +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "audiowin.h" +#include "videowin.h" + + + + + +AudioWin::AudioWin() +{ + initted = 0; + firstsynched=false; + winvolume=0; + volume=20; + + + +} + +AudioWin::~AudioWin() +{ + + +} + +int AudioWin::init(UCHAR tstreamType) +{ + if (initted) return 0; + initted = 1; + return 1; +} + +int AudioWin::shutdown() +{ + if (!initted) return 0; + initted = 0; + return 1; +} + +int AudioWin::write(char *buf, int len) +{ + return 0; //write(fdAudio, buf, len); +} + +int AudioWin::setStreamType(UCHAR type) +{ + if (!initted) return 0; + return 1; +} + +int AudioWin::setChannel() +{ + if (!initted) return 0; + return 1; +} + +int AudioWin::setSource() +{ + if (!initted) return 0; + return 1; +} + +int AudioWin::sync() +{ + if (!initted) return 0; + return 1; +} + +int AudioWin::play() +{ + if (!initted) return 0; + firstsynched=false; + return ((VideoWin*)Video::getInstance())->dsplay(); + +} + +int AudioWin::stop() +{ + if (!initted) return 0; + return ((VideoWin*)Video::getInstance())->dsstop(); +} + +int AudioWin::pause() +{ + if (!initted) return 0; + return ((VideoWin*)Video::getInstance())->dspause(); +} + +int AudioWin::unPause() +{ + if (!initted) return 0; + return ((VideoWin*)Video::getInstance())->dsunPause(); +} + +int AudioWin::reset() +{ + + if (!initted){return 0;} + return ((VideoWin*)Video::getInstance())->dsreset(); +} + +int AudioWin::setVolume(int tvolume) +{ + // parameter: 0 for silence, 20 for full + if ((tvolume < 0) || (tvolume > 20)) return 0; + winvolume=((tvolume-20)*100*30)/20; + if (tvolume==0) winvolume=-10000; + ((VideoWin*)Video::getInstance())->SetAudioVolume(winvolume); + + + return 1; +} + +int AudioWin::mute() +{ + if (!initted) return 0; + ((VideoWin*)Video::getInstance())->SetAudioState(false); + ((VideoWin*)Video::getInstance())->SetAudioVolume(-10000); + return 1; +} + +int AudioWin::unMute() +{ + if (!initted) return 0; + ((VideoWin*)Video::getInstance())->SetAudioState(true); + ((VideoWin*)Video::getInstance())->SetAudioVolume(winvolume); + return 1; +} + +void AudioWin::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos) +{ + mediapacket = mplist.front(); +} + +UINT AudioWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos) +{ + DeliverMediaPacket(mediapacket, buffer, samplepos); + if (*samplepos == mediapacket.length) { + *samplepos = 0; + return 1; + } + else return 0; +} + +UINT AudioWin::DeliverMediaPacket(MediaPacket packet, + const UCHAR* buffer, + UINT *samplepos) +{ + + /*First Check, if we have an audio sample*/ + VideoWin *vw=(VideoWin*)Video::getInstance(); + if (!vw->isdsinited()) return 0; + if (vw->InIframemode()) { + samplepos=0; + MILLISLEEP(10); + return 0; //Not in iframe mode! + } + IMediaSample* ms=NULL; + REFERENCE_TIME reftime1=0; + REFERENCE_TIME reftime2=0; + + UINT headerstrip=0; + if (packet.disconti) { + firstsynched=false; + vw->DeliverVideoMediaSample(); + } + + + + /*Inspect PES-Header */ +/* UINT header_length=buffer[(packet.pos_buffer+8)%bufferlength]+8/*is this right*; +*/ + if (*samplepos==0) {//stripheader + headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/; + *samplepos+=headerstrip; + if ( packet.synched ) { + vw->DeliverAudioMediaSample();//write out old data + /* if (packet.presentation_time<0) { //Preroll? + *samplepos=packet.length;//if we have not processed at least one + return packet.length;//synched packet ignore it! + }*/ + + reftime1=packet.presentation_time; + reftime2=reftime1+1; + firstsynched=true; + } else { + if (!firstsynched) {// + *samplepos=packet.length;//if we have not processed at least one + + return packet.length;//synched packet ignore it! + } + } + } + BYTE *ms_buf; + UINT ms_length; + UINT ms_pos; + UINT haveToCopy; + if (!vw->getCurrentAudioMediaSample(&ms) || ms==NULL) {// get the current sample + //samplepos=0; + MILLISLEEP(10); + return *samplepos; + } + ms_pos=ms->GetActualDataLength(); + ms_length=ms->GetSize(); + haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos); + if ((ms_length-ms_pos)<1) { + vw->DeliverAudioMediaSample(); //we are full! + if (!vw->getCurrentAudioMediaSample(&ms) || ms==NULL) {// get the current sample + //samplepos=0; + MILLISLEEP(10); + return *samplepos; + } + ms_pos=ms->GetActualDataLength(); + ms_length=ms->GetSize(); + haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos); + } + ms->GetPointer(&ms_buf); + + if (ms_pos==0) {//will only be changed on first packet + if (packet.disconti) { + ms->SetDiscontinuity(TRUE); + } else { + ms->SetDiscontinuity(FALSE); + } + if (packet.synched) { + ms->SetSyncPoint(TRUE); + ms->SetTime(&reftime1,&reftime2); + + //ms->SetTime(NULL,NULL); + ms->SetMediaTime(NULL, NULL); + if (reftime1<0) ms->SetPreroll(TRUE); + else ms->SetPreroll(FALSE); + }else { + ms->SetSyncPoint(FALSE); + ms->SetTime(NULL,NULL); + ms->SetMediaTime(NULL, NULL); + ms->SetPreroll(FALSE); + // ms->SetSyncPoint(TRUE); + } + } + + + memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy); + ms->SetActualDataLength(haveToCopy+ms_pos); + + *samplepos+=haveToCopy; + + return haveToCopy+headerstrip; + +} + +long long AudioWin::SetStartOffset(long long curreftime, bool *rsync){ + VideoWin *vw=(VideoWin*)Video::getInstance(); + return vw->SetStartAudioOffset(curreftime,rsync); +} + +void AudioWin::ResetTimeOffsets() { + VideoWin *vw=(VideoWin*)Video::getInstance(); + return vw->ResetTimeOffsets(); +} + +#ifdef DEV +int AudioWin::test() +{ + return 0; +} +#endif + + + diff --git a/audiowin.h b/audiowin.h index b297519..788548d 100644 --- a/audiowin.h +++ b/audiowin.h @@ -1,70 +1,70 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef AUDIOWIN_H -#define AUDIOWIN_H - -#include "defines.h" -#include "log.h" -#include "audio.h" - -class AudioWin : public Audio -{ - public: - AudioWin(); - ~AudioWin(); - - int init(UCHAR streamType); - int shutdown(); - - int setStreamType(UCHAR streamType); - int setChannel(); - int setSource(); - int sync(); - int play(); - int stop(); - int pause(); - int unPause(); - int reset(); - int setVolume(int volume); - int mute(); - int unMute(); - int write(char *buf, int len); - - // Writing Data to Audiodevice - virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos); - virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos); - UINT DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, UINT *samplepos); - private: - MediaPacket mediapacket; - public: - virtual long long SetStartOffset(long long curreftime, bool *rsync); - virtual void ResetTimeOffsets(); - -private: - bool firstsynched; - long winvolume; -#ifdef DEV - int test(); -#endif -}; - -#endif - +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef AUDIOWIN_H +#define AUDIOWIN_H + +#include "defines.h" +#include "log.h" +#include "audio.h" + +class AudioWin : public Audio +{ + public: + AudioWin(); + ~AudioWin(); + + int init(UCHAR streamType); + int shutdown(); + + int setStreamType(UCHAR streamType); + int setChannel(); + int setSource(); + int sync(); + int play(); + int stop(); + int pause(); + int unPause(); + int reset(); + int setVolume(int volume); + int mute(); + int unMute(); + int write(char *buf, int len); + + // Writing Data to Audiodevice + virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos); + virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos); + UINT DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, UINT *samplepos); + private: + MediaPacket mediapacket; + public: + virtual long long SetStartOffset(long long curreftime, bool *rsync); + virtual void ResetTimeOffsets(); + +private: + bool firstsynched; + long winvolume; +#ifdef DEV + int test(); +#endif +}; + +#endif + diff --git a/dsallocator.cc b/dsallocator.cc index 37faf2d..eb7b8f9 100644 --- a/dsallocator.cc +++ b/dsallocator.cc @@ -109,23 +109,23 @@ HRESULT STDMETHODCALLTYPE DsAllocator::PresentImage(DWORD_PTR userid,VMR9Present } -HRESULT STDMETHODCALLTYPE DsAllocator::QueryInterface(REFIID refiid,void ** obj){ - if (obj==NULL) return E_POINTER; - - if (refiid==IID_IVMRSurfaceAllocator9) { - *obj=static_cast(this); - AddRef(); - return S_OK; - } else if (refiid==IID_IVMRImagePresenter9) { - *obj=static_cast(this); - AddRef(); - return S_OK; - } - return E_NOINTERFACE; -} - -ULONG STDMETHODCALLTYPE DsAllocator::AddRef(){ - return InterlockedIncrement(&refcount); +HRESULT STDMETHODCALLTYPE DsAllocator::QueryInterface(REFIID refiid,void ** obj){ + if (obj==NULL) return E_POINTER; + + if (refiid==IID_IVMRSurfaceAllocator9) { + *obj=static_cast(this); + AddRef(); + return S_OK; + } else if (refiid==IID_IVMRImagePresenter9) { + *obj=static_cast(this); + AddRef(); + return S_OK; + } + return E_NOINTERFACE; +} + +ULONG STDMETHODCALLTYPE DsAllocator::AddRef(){ + return InterlockedIncrement(&refcount); } ULONG STDMETHODCALLTYPE DsAllocator::Release(){ @@ -137,4 +137,4 @@ ULONG STDMETHODCALLTYPE DsAllocator::Release(){ return ref; } - + diff --git a/dsallocator.h b/dsallocator.h index 05ed4da..32cf553 100644 --- a/dsallocator.h +++ b/dsallocator.h @@ -46,12 +46,12 @@ public: virtual HRESULT STDMETHODCALLTYPE TerminateDevice(DWORD_PTR userid); virtual HRESULT STDMETHODCALLTYPE GetSurface(DWORD_PTR userid,DWORD surfindex,DWORD surfflags, IDirect3DSurface9** surf); virtual HRESULT STDMETHODCALLTYPE AdviseNotify(IVMRSurfaceAllocatorNotify9* allnoty); - - - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID refiid,void ** obj); - virtual ULONG STDMETHODCALLTYPE AddRef(); - virtual ULONG STDMETHODCALLTYPE Release(); - + + + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID refiid,void ** obj); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); + void LostDevice(); protected: @@ -71,4 +71,4 @@ protected: -#endif +#endif diff --git a/dssourcefilter.cc b/dssourcefilter.cc index ff77a0c..13948b7 100644 --- a/dssourcefilter.cc +++ b/dssourcefilter.cc @@ -1,436 +1,436 @@ -/* - Copyright 2004-2006 Marten Richter - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "dssourcefilter.h" - -#define AUDIOPIN_NAME L"Audio" -#define VIDEOPIN_NAME L"Video" - -class DsSFEnumPins: public IEnumPins { -public: - DsSFEnumPins(DsSourcePin* audio,DsSourcePin* video,DsSourceFilter *filt,ULONG pos=0); - virtual ~DsSFEnumPins(); - virtual HRESULT STDMETHODCALLTYPE Next(ULONG numpin,IPin **pins,ULONG *fetched); - virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin); - virtual HRESULT STDMETHODCALLTYPE Reset(); - virtual HRESULT STDMETHODCALLTYPE Clone(IEnumPins **enuma); - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); - virtual ULONG STDMETHODCALLTYPE AddRef(); - virtual ULONG STDMETHODCALLTYPE Release(); -protected: - DsSourcePin* audiopin; - DsSourcePin* videopin; - DsSourceFilter *filter; - ULONG curpos; - volatile long refs; -}; - -DsSFEnumPins::DsSFEnumPins(DsSourcePin* audio,DsSourcePin* video,DsSourceFilter *filt,ULONG pos){ - audiopin=audio; - videopin=video; - curpos=pos; - filter=filt; - filt->AddRef(); - refs=0; - -} - -DsSFEnumPins::~DsSFEnumPins(){ - filter->Release(); - -} - -HRESULT STDMETHODCALLTYPE DsSFEnumPins::Next(ULONG numpin,IPin **pins,ULONG *fetched) { - int i; - if (fetched==NULL) return E_POINTER; - if (pins==NULL) return E_POINTER; - *fetched=0; - - for (i=0;(iAddRef(); pins[i]=(IPin*)audiopin;break; - case 1: videopin->AddRef(); pins[i]=(IPin*)videopin;break; - }; - (*fetched)++; - curpos++; - } - if ((*fetched)!=numpin) return S_FALSE; - return S_OK; -} - -HRESULT STDMETHODCALLTYPE DsSFEnumPins::Skip(ULONG numpin){ - curpos+=numpin; - if (curpos>2) return S_FALSE; - return S_OK; -} -HRESULT STDMETHODCALLTYPE DsSFEnumPins::Reset(){ - curpos=0; - return S_OK; -} -HRESULT STDMETHODCALLTYPE DsSFEnumPins::Clone(IEnumPins **enuma){ - if (enuma==NULL) return E_POINTER; - *enuma=new DsSFEnumPins(audiopin,videopin,filter,curpos); - (*enuma)->AddRef(); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE DsSFEnumPins::QueryInterface(REFIID id,void ** object){ - if (object==NULL) return E_POINTER; - if (id==IID_IUnknown ||id == IID_IEnumPins) { - *object=(IUnknown*)this; - ((IUnknown*)object)->AddRef(); - return NOERROR; - } else { - *object=NULL; - return E_NOINTERFACE; - } -} - - - -ULONG STDMETHODCALLTYPE DsSFEnumPins::AddRef(){ - InterlockedIncrement(&refs); - long tempref=refs; - if (tempref>1) return tempref; - else return 1; -} - -ULONG STDMETHODCALLTYPE DsSFEnumPins::Release(){ - long tempref=InterlockedDecrement(&refs); - - if (tempref==0) { - refs++; - delete this; - return NULL; - } else { - if (tempref>1) return tempref; - else return 1; - } -} - - - - - - - -DsSourceFilter::DsSourceFilter() -{ - //add audio pin - HRESULT res; - audiopin=new DsSourcePin(this,&res,L"Vomp Audio Out",true); - videopin=new DsSourcePin(this,&res,L"Vomp Video Out",false); - filtergraph=NULL; - clock=NULL; - mystate=State_Stopped; - laststart=0; - refs=0; - InitializeCriticalSection(&filterlock); - -} - -DsSourceFilter::~DsSourceFilter() -{ - if (audiopin) delete audiopin; - if (videopin) delete videopin; - if (clock) { - clock->Release(); - clock=NULL; - } - DeleteCriticalSection(&filterlock); - -} - -HRESULT STDMETHODCALLTYPE DsSourceFilter::GetClassID(CLSID *clsid){ - if (clsid==NULL) return E_POINTER; - *clsid=_uuidof(this); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryInterface(REFIID id,void ** object){ - if (object==NULL) return E_POINTER; - if (id==IID_IUnknown) { - *object=(IUnknown*)this; - AddRef(); - return NOERROR; - } else if (id==IID_IBaseFilter) { - *object=(IBaseFilter*)this; - AddRef(); - return NOERROR; - } else if (id==IID_IMediaFilter) { - *object=(IMediaFilter*)this; - AddRef(); - return NOERROR; - }else { - *object=NULL; - return E_NOINTERFACE; - } -} - -ULONG STDMETHODCALLTYPE DsSourceFilter::AddRef(){ - InterlockedIncrement(&refs); - long tempref=refs; - if (tempref>1) return tempref; - else return 1; -} -ULONG STDMETHODCALLTYPE DsSourceFilter::Release(){ - long tempref=InterlockedDecrement(&refs); - - if (tempref==0) { - refs++; - delete this; - return NULL; - } else { - if (tempref>1) return tempref; - else return 1; - } -} - -/*IBaseFilter*/ -HRESULT STDMETHODCALLTYPE DsSourceFilter::EnumPins(IEnumPins **enumar){ - if (enumar==NULL) return E_POINTER; - *enumar=new DsSFEnumPins(audiopin,videopin, this); - (*enumar)->AddRef(); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE DsSourceFilter::FindPin(LPCWSTR iden,IPin **pin){ - if (pin==NULL) return E_POINTER; - EnterCriticalSection(&filterlock); - - if (wcscmp(AUDIOPIN_NAME,iden)==NULL) { - *pin=(IPin*)audiopin; - (*pin)->AddRef(); - LeaveCriticalSection(&filterlock); - return S_OK; - } - if (wcscmp(VIDEOPIN_NAME,iden)==NULL) { - *pin=(IPin*)videopin; - (*pin)->AddRef(); - LeaveCriticalSection(&filterlock); - return S_OK; - } - - *pin=NULL; - LeaveCriticalSection(&filterlock); - return VFW_E_NOT_FOUND; -} -HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryFilterInfo(FILTER_INFO *info){ - if (info==NULL) return E_POINTER; - wcsncpy(info->achName,L"VompWinFilter", sizeof(info->achName)/sizeof(WCHAR)); - info->pGraph=filtergraph; - if (info->pGraph!=NULL) info->pGraph->AddRef(); - return NOERROR; -} - -HRESULT STDMETHODCALLTYPE DsSourceFilter::JoinFilterGraph(IFilterGraph *graph,LPCWSTR name){ - //Should we lock - EnterCriticalSection(&filterlock); - filtergraph=graph; - //filtergraph->AddRef(); - //We ignore the name - LeaveCriticalSection(&filterlock); - - return S_OK; -} -HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryVendorInfo(LPWSTR *vendinf) { - return E_NOTIMPL; -} - - -/*IMediaFilter*/ -HRESULT STDMETHODCALLTYPE DsSourceFilter::GetState(DWORD timeout,FILTER_STATE *state){ - if (state==NULL) return E_POINTER; - EnterCriticalSection(&filterlock); - *state=mystate; - LeaveCriticalSection(&filterlock); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE DsSourceFilter::SetSyncSource(IReferenceClock *uhr){ - EnterCriticalSection(&filterlock); - //MessageBox(0,"Sets ync","",0); - if (clock!=NULL) { - clock->Release(); - } - if (uhr!=NULL) { - uhr->AddRef(); - } - clock=uhr; - LeaveCriticalSection(&filterlock); - - return S_OK; -} -HRESULT STDMETHODCALLTYPE DsSourceFilter::GetSyncSource(IReferenceClock **uhr){ - if (uhr==NULL) return E_POINTER; - EnterCriticalSection(&filterlock); - if (clock!=NULL) clock->AddRef(); - *uhr=clock; - LeaveCriticalSection(&filterlock); - - return S_OK; -} - -HRESULT STDMETHODCALLTYPE DsSourceFilter::Stop(){ - EnterCriticalSection(&filterlock); - HRESULT aphres=S_OK; - HRESULT vphres=S_OK; - - if (audiopin->IsConnected()){ - aphres=audiopin->Inactive(); - } - if (videopin->IsConnected()){ - vphres=videopin->Inactive(); - } - - mystate=State_Stopped; - LeaveCriticalSection(&filterlock); - if (aphres!=S_OK) return aphres; - if (vphres!=S_OK) return vphres; - return S_OK; -} - -HRESULT STDMETHODCALLTYPE DsSourceFilter::Pause(){ - EnterCriticalSection(&filterlock); - HRESULT aphres; - HRESULT vphres; - - if (audiopin->IsConnected()){ - aphres=audiopin->Active(); - if (aphres!=S_OK) { - LeaveCriticalSection(&filterlock); - return aphres; - } - } - if (videopin->IsConnected()){ - vphres=videopin->Active(); - if (vphres!=S_OK) { - LeaveCriticalSection(&filterlock); - return vphres; - } - } - - mystate=State_Paused; - LeaveCriticalSection(&filterlock); - - - return S_OK; -} -HRESULT STDMETHODCALLTYPE DsSourceFilter::Run(REFERENCE_TIME start){ - - HRESULT aphres; - HRESULT vphres; - EnterCriticalSection(&filterlock); - - if (mystate==State_Stopped) { - HRESULT phres=Pause(); - if (phres!=S_OK){ - LeaveCriticalSection(&filterlock); - return phres; - } - } - - laststart=start; - - - if (audiopin->IsConnected()){ - aphres=audiopin->Run(start); - if (aphres!=S_OK) { - LeaveCriticalSection(&filterlock); - return aphres; - } - } - - if (videopin->IsConnected()){ - vphres=videopin->Run(start); - if (vphres!=S_OK) { - LeaveCriticalSection(&filterlock); - return vphres; - } - } - - mystate=State_Running; - LeaveCriticalSection(&filterlock); - - - return S_OK; -} - - - -int DsSourceFilter::GetPinCount() -{ - return 2; //audio and video -} - - - -int DsSourceFilter::getCurrentAudioMediaSample(IMediaSample** ms) -{ - if (!audiopin || !IsActive()) { - return 0; - } - if (audiopin->getCurrentMediaSample(ms)!=S_OK) { - return 0; - } - return 1; -} - -int DsSourceFilter::getCurrentVideoMediaSample(IMediaSample** ms) -{ - if (!videopin || !IsActive()) { - return 0; - } - if (videopin->getCurrentMediaSample(ms)!=S_OK) { - return 0; - } - return 1; -} - -int DsSourceFilter::DeliverAudioMediaSample(IMediaSample* ms) -{ - if (!audiopin || !IsActive()) { - ms->Release(); - return 0; - } - if (audiopin->deliver(ms)!=S_OK) { - ms->Release(); - return 0; - } - ms->Release(); - return 1; - -} - -int DsSourceFilter::DeliverVideoMediaSample(IMediaSample* ms) -{ - if (!videopin || !IsActive()) { - ms->Release(); - return 0; - } - if (videopin->deliver(ms)!=S_OK) { - ms->Release(); - return 0; - } - ms->Release(); - return 1; - -} - - +/* + Copyright 2004-2006 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "dssourcefilter.h" + +#define AUDIOPIN_NAME L"Audio" +#define VIDEOPIN_NAME L"Video" + +class DsSFEnumPins: public IEnumPins { +public: + DsSFEnumPins(DsSourcePin* audio,DsSourcePin* video,DsSourceFilter *filt,ULONG pos=0); + virtual ~DsSFEnumPins(); + virtual HRESULT STDMETHODCALLTYPE Next(ULONG numpin,IPin **pins,ULONG *fetched); + virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin); + virtual HRESULT STDMETHODCALLTYPE Reset(); + virtual HRESULT STDMETHODCALLTYPE Clone(IEnumPins **enuma); + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); +protected: + DsSourcePin* audiopin; + DsSourcePin* videopin; + DsSourceFilter *filter; + ULONG curpos; + volatile long refs; +}; + +DsSFEnumPins::DsSFEnumPins(DsSourcePin* audio,DsSourcePin* video,DsSourceFilter *filt,ULONG pos){ + audiopin=audio; + videopin=video; + curpos=pos; + filter=filt; + filt->AddRef(); + refs=0; + +} + +DsSFEnumPins::~DsSFEnumPins(){ + filter->Release(); + +} + +HRESULT STDMETHODCALLTYPE DsSFEnumPins::Next(ULONG numpin,IPin **pins,ULONG *fetched) { + int i; + if (fetched==NULL) return E_POINTER; + if (pins==NULL) return E_POINTER; + *fetched=0; + + for (i=0;(iAddRef(); pins[i]=(IPin*)audiopin;break; + case 1: videopin->AddRef(); pins[i]=(IPin*)videopin;break; + }; + (*fetched)++; + curpos++; + } + if ((*fetched)!=numpin) return S_FALSE; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSFEnumPins::Skip(ULONG numpin){ + curpos+=numpin; + if (curpos>2) return S_FALSE; + return S_OK; +} +HRESULT STDMETHODCALLTYPE DsSFEnumPins::Reset(){ + curpos=0; + return S_OK; +} +HRESULT STDMETHODCALLTYPE DsSFEnumPins::Clone(IEnumPins **enuma){ + if (enuma==NULL) return E_POINTER; + *enuma=new DsSFEnumPins(audiopin,videopin,filter,curpos); + (*enuma)->AddRef(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSFEnumPins::QueryInterface(REFIID id,void ** object){ + if (object==NULL) return E_POINTER; + if (id==IID_IUnknown ||id == IID_IEnumPins) { + *object=(IUnknown*)this; + ((IUnknown*)object)->AddRef(); + return NOERROR; + } else { + *object=NULL; + return E_NOINTERFACE; + } +} + + + +ULONG STDMETHODCALLTYPE DsSFEnumPins::AddRef(){ + InterlockedIncrement(&refs); + long tempref=refs; + if (tempref>1) return tempref; + else return 1; +} + +ULONG STDMETHODCALLTYPE DsSFEnumPins::Release(){ + long tempref=InterlockedDecrement(&refs); + + if (tempref==0) { + refs++; + delete this; + return NULL; + } else { + if (tempref>1) return tempref; + else return 1; + } +} + + + + + + + +DsSourceFilter::DsSourceFilter() +{ + //add audio pin + HRESULT res; + audiopin=new DsSourcePin(this,&res,L"Vomp Audio Out",true); + videopin=new DsSourcePin(this,&res,L"Vomp Video Out",false); + filtergraph=NULL; + clock=NULL; + mystate=State_Stopped; + laststart=0; + refs=0; + InitializeCriticalSection(&filterlock); + +} + +DsSourceFilter::~DsSourceFilter() +{ + if (audiopin) delete audiopin; + if (videopin) delete videopin; + if (clock) { + clock->Release(); + clock=NULL; + } + DeleteCriticalSection(&filterlock); + +} + +HRESULT STDMETHODCALLTYPE DsSourceFilter::GetClassID(CLSID *clsid){ + if (clsid==NULL) return E_POINTER; + *clsid=_uuidof(this); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryInterface(REFIID id,void ** object){ + if (object==NULL) return E_POINTER; + if (id==IID_IUnknown) { + *object=(IUnknown*)this; + AddRef(); + return NOERROR; + } else if (id==IID_IBaseFilter) { + *object=(IBaseFilter*)this; + AddRef(); + return NOERROR; + } else if (id==IID_IMediaFilter) { + *object=(IMediaFilter*)this; + AddRef(); + return NOERROR; + }else { + *object=NULL; + return E_NOINTERFACE; + } +} + +ULONG STDMETHODCALLTYPE DsSourceFilter::AddRef(){ + InterlockedIncrement(&refs); + long tempref=refs; + if (tempref>1) return tempref; + else return 1; +} +ULONG STDMETHODCALLTYPE DsSourceFilter::Release(){ + long tempref=InterlockedDecrement(&refs); + + if (tempref==0) { + refs++; + delete this; + return NULL; + } else { + if (tempref>1) return tempref; + else return 1; + } +} + +/*IBaseFilter*/ +HRESULT STDMETHODCALLTYPE DsSourceFilter::EnumPins(IEnumPins **enumar){ + if (enumar==NULL) return E_POINTER; + *enumar=new DsSFEnumPins(audiopin,videopin, this); + (*enumar)->AddRef(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSourceFilter::FindPin(LPCWSTR iden,IPin **pin){ + if (pin==NULL) return E_POINTER; + EnterCriticalSection(&filterlock); + + if (wcscmp(AUDIOPIN_NAME,iden)==NULL) { + *pin=(IPin*)audiopin; + (*pin)->AddRef(); + LeaveCriticalSection(&filterlock); + return S_OK; + } + if (wcscmp(VIDEOPIN_NAME,iden)==NULL) { + *pin=(IPin*)videopin; + (*pin)->AddRef(); + LeaveCriticalSection(&filterlock); + return S_OK; + } + + *pin=NULL; + LeaveCriticalSection(&filterlock); + return VFW_E_NOT_FOUND; +} +HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryFilterInfo(FILTER_INFO *info){ + if (info==NULL) return E_POINTER; + wcsncpy(info->achName,L"VompWinFilter", sizeof(info->achName)/sizeof(WCHAR)); + info->pGraph=filtergraph; + if (info->pGraph!=NULL) info->pGraph->AddRef(); + return NOERROR; +} + +HRESULT STDMETHODCALLTYPE DsSourceFilter::JoinFilterGraph(IFilterGraph *graph,LPCWSTR name){ + //Should we lock + EnterCriticalSection(&filterlock); + filtergraph=graph; + //filtergraph->AddRef(); + //We ignore the name + LeaveCriticalSection(&filterlock); + + return S_OK; +} +HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryVendorInfo(LPWSTR *vendinf) { + return E_NOTIMPL; +} + + +/*IMediaFilter*/ +HRESULT STDMETHODCALLTYPE DsSourceFilter::GetState(DWORD timeout,FILTER_STATE *state){ + if (state==NULL) return E_POINTER; + EnterCriticalSection(&filterlock); + *state=mystate; + LeaveCriticalSection(&filterlock); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSourceFilter::SetSyncSource(IReferenceClock *uhr){ + EnterCriticalSection(&filterlock); + //MessageBox(0,"Sets ync","",0); + if (clock!=NULL) { + clock->Release(); + } + if (uhr!=NULL) { + uhr->AddRef(); + } + clock=uhr; + LeaveCriticalSection(&filterlock); + + return S_OK; +} +HRESULT STDMETHODCALLTYPE DsSourceFilter::GetSyncSource(IReferenceClock **uhr){ + if (uhr==NULL) return E_POINTER; + EnterCriticalSection(&filterlock); + if (clock!=NULL) clock->AddRef(); + *uhr=clock; + LeaveCriticalSection(&filterlock); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSourceFilter::Stop(){ + EnterCriticalSection(&filterlock); + HRESULT aphres=S_OK; + HRESULT vphres=S_OK; + + if (audiopin->IsConnected()){ + aphres=audiopin->Inactive(); + } + if (videopin->IsConnected()){ + vphres=videopin->Inactive(); + } + + mystate=State_Stopped; + LeaveCriticalSection(&filterlock); + if (aphres!=S_OK) return aphres; + if (vphres!=S_OK) return vphres; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSourceFilter::Pause(){ + EnterCriticalSection(&filterlock); + HRESULT aphres; + HRESULT vphres; + + if (audiopin->IsConnected()){ + aphres=audiopin->Active(); + if (aphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return aphres; + } + } + if (videopin->IsConnected()){ + vphres=videopin->Active(); + if (vphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return vphres; + } + } + + mystate=State_Paused; + LeaveCriticalSection(&filterlock); + + + return S_OK; +} +HRESULT STDMETHODCALLTYPE DsSourceFilter::Run(REFERENCE_TIME start){ + + HRESULT aphres; + HRESULT vphres; + EnterCriticalSection(&filterlock); + + if (mystate==State_Stopped) { + HRESULT phres=Pause(); + if (phres!=S_OK){ + LeaveCriticalSection(&filterlock); + return phres; + } + } + + laststart=start; + + + if (audiopin->IsConnected()){ + aphres=audiopin->Run(start); + if (aphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return aphres; + } + } + + if (videopin->IsConnected()){ + vphres=videopin->Run(start); + if (vphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return vphres; + } + } + + mystate=State_Running; + LeaveCriticalSection(&filterlock); + + + return S_OK; +} + + + +int DsSourceFilter::GetPinCount() +{ + return 2; //audio and video +} + + + +int DsSourceFilter::getCurrentAudioMediaSample(IMediaSample** ms) +{ + if (!audiopin || !IsActive()) { + return 0; + } + if (audiopin->getCurrentMediaSample(ms)!=S_OK) { + return 0; + } + return 1; +} + +int DsSourceFilter::getCurrentVideoMediaSample(IMediaSample** ms) +{ + if (!videopin || !IsActive()) { + return 0; + } + if (videopin->getCurrentMediaSample(ms)!=S_OK) { + return 0; + } + return 1; +} + +int DsSourceFilter::DeliverAudioMediaSample(IMediaSample* ms) +{ + if (!audiopin || !IsActive()) { + ms->Release(); + return 0; + } + if (audiopin->deliver(ms)!=S_OK) { + ms->Release(); + return 0; + } + ms->Release(); + return 1; + +} + +int DsSourceFilter::DeliverVideoMediaSample(IMediaSample* ms) +{ + if (!videopin || !IsActive()) { + ms->Release(); + return 0; + } + if (videopin->deliver(ms)!=S_OK) { + ms->Release(); + return 0; + } + ms->Release(); + return 1; + +} + + diff --git a/dssourcefilter.h b/dssourcefilter.h index 3535db0..9adb656 100644 --- a/dssourcefilter.h +++ b/dssourcefilter.h @@ -44,27 +44,27 @@ public: /* IUnknown */ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); - virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE AddRef(); virtual ULONG STDMETHODCALLTYPE Release(); /*IPersist*/ - virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *clsid); + virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *clsid); /*IBaseFilter*/ virtual HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **enumar); - virtual HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR iden,IPin **pin); - virtual HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *info); - virtual HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *graph,LPCWSTR name); - virtual HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *vendinf); + virtual HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR iden,IPin **pin); + virtual HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *info); + virtual HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *graph,LPCWSTR name); + virtual HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *vendinf); /*IMediaFilter*/ - virtual HRESULT STDMETHODCALLTYPE GetState(DWORD timeout,FILTER_STATE *state); - virtual HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *uhr); - virtual HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **uhr); - virtual HRESULT STDMETHODCALLTYPE Stop(); - virtual HRESULT STDMETHODCALLTYPE Pause(); - virtual HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME start); - - DsSourcePin *GetAudioPin() {return audiopin;}; - DsSourcePin *GetVideoPin() {return videopin;}; + virtual HRESULT STDMETHODCALLTYPE GetState(DWORD timeout,FILTER_STATE *state); + virtual HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *uhr); + virtual HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **uhr); + virtual HRESULT STDMETHODCALLTYPE Stop(); + virtual HRESULT STDMETHODCALLTYPE Pause(); + virtual HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME start); + + DsSourcePin *GetAudioPin() {return audiopin;}; + DsSourcePin *GetVideoPin() {return videopin;}; protected: @@ -81,4 +81,4 @@ protected: }; -#endif +#endif diff --git a/dssourcepin.cc b/dssourcepin.cc index 5d440a7..a55016e 100644 --- a/dssourcepin.cc +++ b/dssourcepin.cc @@ -1,569 +1,569 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "dssourcepin.h" -#include "dssourcefilter.h" -#include -#include - - -class DsSFEnumMediaTypes: public IEnumMediaTypes { -public: - DsSFEnumMediaTypes(DsSourcePin* papa,ULONG pos=0); - virtual ~DsSFEnumMediaTypes(); - virtual HRESULT STDMETHODCALLTYPE Next(ULONG nummedia, AM_MEDIA_TYPE **pins,ULONG *fetched); - virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin); - virtual HRESULT STDMETHODCALLTYPE Reset(); - virtual HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes **enuma); - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); - virtual ULONG STDMETHODCALLTYPE AddRef(); - virtual ULONG STDMETHODCALLTYPE Release(); -protected: - DsSourcePin* parent; - ULONG curpos; - volatile long refs; -}; - -DsSFEnumMediaTypes::DsSFEnumMediaTypes(DsSourcePin* papa,ULONG pos){ - parent=papa; - curpos=pos; - parent->AddRef(); - refs=0; -} - -DsSFEnumMediaTypes::~DsSFEnumMediaTypes(){ - parent->Release(); -} - -HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Next(ULONG numpin, AM_MEDIA_TYPE **pins,ULONG *fetched) { - int i; - - if (pins==NULL) return E_POINTER; - if (numpin!=1 && fetched==NULL) return E_INVALIDARG; - *fetched=0; - - for (i=0;(iGetMediaType(curpos+i,pins[i])!=S_OK) { - CoTaskMemFree(pins[i]); - pins[i]=NULL; - return S_FALSE; - } curpos++; - if (fetched!=NULL) (*fetched)++; - } - return S_OK; -} - -HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Skip(ULONG numpin){ - curpos+=numpin; - if (curpos>1) return S_FALSE; - return S_OK; -} -HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Reset(){ - curpos=0; - return S_OK; -} -HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Clone(IEnumMediaTypes **enuma){ - if (enuma==NULL) return E_POINTER; - *enuma=new DsSFEnumMediaTypes(parent,curpos); - (*enuma)->AddRef(); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::QueryInterface(REFIID id,void ** object){ - if (object==NULL) return E_POINTER; - if (id==IID_IUnknown ||id == IID_IEnumMediaTypes) { - *object=(IUnknown*)this; - ((IUnknown*)object)->AddRef(); - return NOERROR; - } else { - *object=NULL; - return E_NOINTERFACE; - } -} - - - -ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::AddRef(){ - InterlockedIncrement(&refs); - long tempref=refs; - if (tempref>1) return tempref; - else return 1; -} - -ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::Release(){ - long tempref=InterlockedDecrement(&refs); - - if (tempref==0) { - refs++; - delete this; - return NULL; - } else { - if (tempref>1) return tempref; - else return 1; - } -} - - -void CopyMType(AM_MEDIA_TYPE* dest,const AM_MEDIA_TYPE*source) { - memcpy(dest,source,sizeof(AM_MEDIA_TYPE)); - if (source->pbFormat!=NULL) { - dest->pbFormat=(BYTE*)CoTaskMemAlloc(dest->cbFormat); - memcpy(dest->pbFormat,source->pbFormat,dest->cbFormat); - } -} -void ReleaseMType(AM_MEDIA_TYPE* free) { - if (free->cbFormat!=NULL) CoTaskMemFree(free->pbFormat); - free->pbFormat=NULL; -} - -DsSourcePin::DsSourcePin(DsSourceFilter *pFilter, - HRESULT *phr,LPCWSTR pName,bool audio) -{ - isaudiopin=audio; - m_pFilter=pFilter; - connected=NULL; - connectedinput=NULL; - allocator=NULL; - - - -} - -DsSourcePin::~DsSourcePin() -{ - - - -} - -HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInterface(REFIID id,void ** object){ - if (object==NULL) return E_POINTER; - if (id==IID_IUnknown) { - *object=(IUnknown*)this; - ((IUnknown*)object)->AddRef(); - return NOERROR; - } else if (id==IID_IPin) { - *object=(IPin*)this; - ((IPin*)object)->AddRef(); - return NOERROR; - } else { - *object=NULL; - return E_NOINTERFACE; - } -} - -ULONG STDMETHODCALLTYPE DsSourcePin::AddRef(){ - return m_pFilter->AddRef(); - -} -ULONG STDMETHODCALLTYPE DsSourcePin::Release(){ - return m_pFilter->Release(); -} - - -/*IPin*/ -HRESULT STDMETHODCALLTYPE DsSourcePin::Connect(IPin *pinempf,const AM_MEDIA_TYPE *mtype) { - if (pinempf==NULL) return E_POINTER; - EnterCriticalSection(&m_pFilter->filterlock); - - if (connected!=NULL) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_ALREADY_CONNECTED;} - if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;} - - - bool gotmt=false; - - if (mtype!=NULL) { - if (CheckMediaType(mtype)==S_OK){ - pinempf->AddRef(); - if (pinempf->ReceiveConnection((IPin*)this,mtype)==S_OK) { - CopyMType(&medtype,mtype); - LeaveCriticalSection(&m_pFilter->filterlock); - } else { - LeaveCriticalSection(&m_pFilter->filterlock); - if (mtype->pbFormat!=NULL) CoTaskMemFree(mtype->pbFormat); - pinempf->Release(); - return VFW_E_TYPE_NOT_ACCEPTED; - } - - } else { - LeaveCriticalSection(&m_pFilter->filterlock); - if (mtype->pbFormat!=NULL) CoTaskMemFree(mtype->pbFormat); - return VFW_E_TYPE_NOT_ACCEPTED; - } - CoTaskMemFree(mtype->pbFormat); - }else { - IEnumMediaTypes * emt; - EnumMediaTypes(&emt); - AM_MEDIA_TYPE * emtype; - ULONG fetched=0; - pinempf->AddRef(); - while (emt->Next(1,&emtype,&fetched)==S_OK) { - if (CheckMediaType(emtype)==S_OK){ -/* PIN_INFO pini; - pinempf->QueryPinInfo(&pini); - if (pini.pFilter!=NULL) { - FILTER_INFO filti; - pini.pFilter->QueryFilterInfo(&filti); - - if (filti.pGraph!=NULL) filti.pGraph->Release(); - char buffer[MAX_FILTER_NAME*2]; - wcstombs(buffer,filti.achName,MAX_FILTER_NAME*2); - MessageBox(0,buffer,"Filter",0); - pini.pFilter->Release(); - }*/ - - if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) { - connected=pinempf; - CopyMType(&medtype,emtype); - if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); - - CoTaskMemFree(emtype); - gotmt=true; - break; - } - - } - if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); - CoTaskMemFree(emtype); - } - emt->Release(); - if (gotmt==false) { - pinempf->EnumMediaTypes(&emt); - while (emt->Next(1,&emtype,&fetched)==S_OK) { - if (CheckMediaType(emtype)==S_OK){ - if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) { - connected=pinempf; - CopyMType(&medtype,emtype); - if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); - CoTaskMemFree(emtype); - gotmt=true; - break; - } - - } - if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); - CoTaskMemFree(emtype); - } - emt->Release(); - if (gotmt==false) { - pinempf->Release(); - LeaveCriticalSection(&m_pFilter->filterlock); - return VFW_E_NO_ACCEPTABLE_TYPES; - } - } - } - - if (pinempf->QueryInterface(IID_IMemInputPin,(void**)&connectedinput)!=S_OK) { - LeaveCriticalSection(&m_pFilter->filterlock); - connected->Release(); - connected=NULL; - /* connectedinput->Release(); - connectedinput=NULL;*/ - return VFW_E_NO_TRANSPORT; - } - ALLOCATOR_PROPERTIES eigenall; - ZeroMemory(&eigenall,sizeof(eigenall)); - connectedinput->GetAllocatorRequirements(&eigenall); - if (eigenall.cbAlign==0) eigenall.cbAlign=1; - connectedinput->GetAllocator(&allocator); - if (DecideBufferSize(allocator,&eigenall)==S_OK) { - if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){ - connected=pinempf; - LeaveCriticalSection(&m_pFilter->filterlock); - return S_OK; - } - } - if (allocator!=NULL) allocator->Release(); - allocator=NULL; - - if (CoCreateInstance(CLSID_MemoryAllocator,0,CLSCTX_INPROC_SERVER, - IID_IMemAllocator,(void **)allocator)==S_OK) { - if (DecideBufferSize(allocator,&eigenall)==S_OK) { - if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){ - connected=pinempf; - LeaveCriticalSection(&m_pFilter->filterlock); - return S_OK; - } - } - } - if (allocator!=NULL) allocator->Release(); - allocator=NULL; - connected->Release(); - connected=NULL; - connectedinput->Release(); - connectedinput=NULL; - LeaveCriticalSection(&m_pFilter->filterlock); - return VFW_E_NO_TRANSPORT; - - - - -} -HRESULT STDMETHODCALLTYPE DsSourcePin::ReceiveConnection(IPin *connect, - const AM_MEDIA_TYPE *mtype){ - return VFW_E_TYPE_NOT_ACCEPTED; //We have only output pins -} - HRESULT STDMETHODCALLTYPE DsSourcePin::Disconnect() { - EnterCriticalSection(&m_pFilter->filterlock); - if (connected!=NULL) { - if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;} - /*TODO: Decommit allocator*/ - allocator->Decommit(); - allocator->Release(); - allocator=NULL; - ReleaseMType(&medtype); - connectedinput->Release(); - connectedinput=NULL; - connected->Release(); - connected=NULL; - LeaveCriticalSection(&m_pFilter->filterlock); - return S_OK; - } - LeaveCriticalSection(&m_pFilter->filterlock); - return S_FALSE; - } - - HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectedTo(IPin **pin){ - if (pin==NULL) return E_POINTER; - IPin* pinn=connected; - *pin=pinn; - if (pinn!=NULL) { - pinn->AddRef(); - return S_OK; - } else { - return VFW_E_NOT_CONNECTED; - } - } - HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectionMediaType(AM_MEDIA_TYPE *mtype){ - if (mtype==NULL) return E_POINTER; - if (connected!=NULL){ - CopyMType(mtype,&medtype); - return S_OK; - } else { - ZeroMemory(mtype,sizeof(*mtype)); - return VFW_E_NOT_CONNECTED; - } - } - HRESULT STDMETHODCALLTYPE DsSourcePin::QueryPinInfo(PIN_INFO *info){ - if (info==NULL) return E_POINTER; - info->dir=PINDIR_OUTPUT; - info->pFilter=(IBaseFilter*)m_pFilter; - if (m_pFilter) m_pFilter->AddRef(); - if (isaudiopin) wcscpy(info->achName,L"Audio"); - else wcscpy(info->achName,L"Video"); - return S_OK; - } - - HRESULT STDMETHODCALLTYPE DsSourcePin::QueryDirection(PIN_DIRECTION *dir){ - if (dir==NULL) return E_POINTER; - *dir=PINDIR_OUTPUT; - return S_OK; - } - HRESULT STDMETHODCALLTYPE DsSourcePin::QueryId(LPWSTR *id){ - if (id==NULL) return E_POINTER; - *id=(LPWSTR)CoTaskMemAlloc(12); - if (*id==NULL) return E_OUTOFMEMORY; - - - if (isaudiopin) wcscpy(*id,L"Audio"); - else wcscpy(*id, L"Video"); - return S_OK; - } - HRESULT STDMETHODCALLTYPE DsSourcePin::QueryAccept(const AM_MEDIA_TYPE *mtype) { - if (mtype==NULL) return S_FALSE; - if (CheckMediaType(mtype)==S_OK) return S_OK; - else return S_FALSE; - } - HRESULT STDMETHODCALLTYPE DsSourcePin::EnumMediaTypes(IEnumMediaTypes **enuma){ -if (enuma==NULL) return E_POINTER; - *enuma=new DsSFEnumMediaTypes( this); - (*enuma)->AddRef(); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInternalConnections(IPin **pin,ULONG *numpin){ - return E_NOTIMPL; -} -HRESULT STDMETHODCALLTYPE DsSourcePin::EndOfStream(){ - return E_UNEXPECTED; //we are a output pin! -} - -HRESULT STDMETHODCALLTYPE DsSourcePin::NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate){ - return E_UNEXPECTED;//we are a output pin! -} - -HRESULT DsSourcePin::getCurrentMediaSample(IMediaSample**ms){ - if (allocator!=NULL) return allocator->GetBuffer(ms,NULL,NULL,0); - else return E_NOINTERFACE; -} - -HRESULT DsSourcePin::deliver(IMediaSample * ms){ - //EnterCriticalSection(&m_pFilter->filterlock); - HRESULT hres; - if (connectedinput!=NULL)hres= connectedinput->Receive(ms); - else hres= VFW_E_NOT_CONNECTED; - //LeaveCriticalSection(&m_pFilter->filterlock); - return hres; - -} - -HRESULT DsSourcePin::GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt) -{ - HRESULT hr; - - if (isaudiopin){ - if (iPosition==0) { - ZeroMemory(pmt,sizeof(*pmt)); - pmt->lSampleSize = 1; - pmt->bFixedSizeSamples = TRUE; - pmt->majortype=MEDIATYPE_Audio; - MPEG1WAVEFORMAT wfe; - ZeroMemory(&wfe,sizeof(wfe)); - wfe.wfx.cbSize=22; - wfe.wfx.nSamplesPerSec=48000; - wfe.wfx.nChannels=2; - wfe.wfx.nAvgBytesPerSec=32000; - wfe.wfx.nBlockAlign=768; - wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG; - wfe.wfx.wBitsPerSample=0; - wfe.fwHeadLayer=2; - wfe.dwHeadBitrate=256000; - wfe.fwHeadMode=ACM_MPEG_STEREO; - wfe.fwHeadModeExt=1; - wfe.wHeadEmphasis=1; - wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT; - pmt->subtype=MEDIASUBTYPE_MPEG2_AUDIO; - pmt->formattype=FORMAT_WaveFormatEx; - pmt->cbFormat=sizeof(wfe); - pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe)); - memcpy(pmt->pbFormat,&wfe,sizeof(wfe)); - pmt->lSampleSize=0; - hr=S_OK; - - - } else { - hr=VFW_S_NO_MORE_ITEMS ; - } - } else { - if (iPosition == 0) { - ZeroMemory(pmt,sizeof(*pmt)); - pmt->lSampleSize = 1; - pmt->bFixedSizeSamples = TRUE; - pmt->majortype=MEDIATYPE_Video; - hr=S_OK; - pmt->subtype=MEDIASUBTYPE_MPEG2_VIDEO; - pmt->formattype=FORMAT_MPEG2Video; - - MPEG2VIDEOINFO hdr; - ZeroMemory(&hdr,sizeof(hdr)); - hdr.dwProfile=AM_MPEG2Profile_Main; - hdr.dwLevel=AM_MPEG2Level_Main; - hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader); - hdr.hdr.bmiHeader.biWidth = 720; - hdr.hdr.bmiHeader.biHeight = 568; - pmt->cbFormat=sizeof(hdr); - pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(hdr)); - memcpy(pmt->pbFormat,&hdr,sizeof(hdr)); - - } else { - hr=VFW_S_NO_MORE_ITEMS; - } - } - return hr ; -} - -HRESULT DsSourcePin::Inactive() { - if (allocator!=NULL) return allocator->Decommit(); - return VFW_E_NO_ALLOCATOR; -} - -HRESULT DsSourcePin::Active() { - if (allocator!=NULL) return allocator->Commit(); - return VFW_E_NO_ALLOCATOR; -} - - -HRESULT DsSourcePin::Run(REFERENCE_TIME reftime){ - return NOERROR; -} - -// No description -HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt) -{ - HRESULT res; - - if (isaudiopin) { - bool subtype=false; -#if 0 /* For future demands ac3 */ - subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3); -#endif - subtype=(pmt->subtype==(MEDIASUBTYPE_MPEG2_AUDIO)); - if (pmt->majortype==MEDIATYPE_Audio && subtype) { - res = S_OK ; - } else { - res = S_FALSE ; - } - } else { - if (pmt->majortype==MEDIATYPE_Video && - pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) { - res = S_OK ; - } else { - res = S_FALSE ; - } - } - return res; -} - -HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp){ - HRESULT hr; - - if (pa==NULL)return E_POINTER; - if (all_pp==NULL) return E_POINTER; - if (isaudiopin) { - if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024) - { - //all_pp->cBuffers = 300;//old - all_pp->cBuffers = 10; - all_pp->cbBuffer = 64*1024; - } - } else { - if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024) - { - //all_pp->cBuffers = 300;//old - all_pp->cBuffers = 30; - all_pp->cbBuffer = 64*1024; - } - } - - ALLOCATOR_PROPERTIES all_pp_cur; - hr =pa->SetProperties(all_pp,&all_pp_cur); - if (FAILED(hr)) - { - return hr; - } - if (all_pp_cur.cbBuffer*all_pp_cur.cBuffers < all_pp->cBuffers*all_pp->cbBuffer) - { - return E_FAIL; - } - - return S_OK; -} - - +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "dssourcepin.h" +#include "dssourcefilter.h" +#include +#include + + +class DsSFEnumMediaTypes: public IEnumMediaTypes { +public: + DsSFEnumMediaTypes(DsSourcePin* papa,ULONG pos=0); + virtual ~DsSFEnumMediaTypes(); + virtual HRESULT STDMETHODCALLTYPE Next(ULONG nummedia, AM_MEDIA_TYPE **pins,ULONG *fetched); + virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin); + virtual HRESULT STDMETHODCALLTYPE Reset(); + virtual HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes **enuma); + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); +protected: + DsSourcePin* parent; + ULONG curpos; + volatile long refs; +}; + +DsSFEnumMediaTypes::DsSFEnumMediaTypes(DsSourcePin* papa,ULONG pos){ + parent=papa; + curpos=pos; + parent->AddRef(); + refs=0; +} + +DsSFEnumMediaTypes::~DsSFEnumMediaTypes(){ + parent->Release(); +} + +HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Next(ULONG numpin, AM_MEDIA_TYPE **pins,ULONG *fetched) { + int i; + + if (pins==NULL) return E_POINTER; + if (numpin!=1 && fetched==NULL) return E_INVALIDARG; + *fetched=0; + + for (i=0;(iGetMediaType(curpos+i,pins[i])!=S_OK) { + CoTaskMemFree(pins[i]); + pins[i]=NULL; + return S_FALSE; + } curpos++; + if (fetched!=NULL) (*fetched)++; + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Skip(ULONG numpin){ + curpos+=numpin; + if (curpos>1) return S_FALSE; + return S_OK; +} +HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Reset(){ + curpos=0; + return S_OK; +} +HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Clone(IEnumMediaTypes **enuma){ + if (enuma==NULL) return E_POINTER; + *enuma=new DsSFEnumMediaTypes(parent,curpos); + (*enuma)->AddRef(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::QueryInterface(REFIID id,void ** object){ + if (object==NULL) return E_POINTER; + if (id==IID_IUnknown ||id == IID_IEnumMediaTypes) { + *object=(IUnknown*)this; + ((IUnknown*)object)->AddRef(); + return NOERROR; + } else { + *object=NULL; + return E_NOINTERFACE; + } +} + + + +ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::AddRef(){ + InterlockedIncrement(&refs); + long tempref=refs; + if (tempref>1) return tempref; + else return 1; +} + +ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::Release(){ + long tempref=InterlockedDecrement(&refs); + + if (tempref==0) { + refs++; + delete this; + return NULL; + } else { + if (tempref>1) return tempref; + else return 1; + } +} + + +void CopyMType(AM_MEDIA_TYPE* dest,const AM_MEDIA_TYPE*source) { + memcpy(dest,source,sizeof(AM_MEDIA_TYPE)); + if (source->pbFormat!=NULL) { + dest->pbFormat=(BYTE*)CoTaskMemAlloc(dest->cbFormat); + memcpy(dest->pbFormat,source->pbFormat,dest->cbFormat); + } +} +void ReleaseMType(AM_MEDIA_TYPE* free) { + if (free->cbFormat!=NULL) CoTaskMemFree(free->pbFormat); + free->pbFormat=NULL; +} + +DsSourcePin::DsSourcePin(DsSourceFilter *pFilter, + HRESULT *phr,LPCWSTR pName,bool audio) +{ + isaudiopin=audio; + m_pFilter=pFilter; + connected=NULL; + connectedinput=NULL; + allocator=NULL; + + + +} + +DsSourcePin::~DsSourcePin() +{ + + + +} + +HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInterface(REFIID id,void ** object){ + if (object==NULL) return E_POINTER; + if (id==IID_IUnknown) { + *object=(IUnknown*)this; + ((IUnknown*)object)->AddRef(); + return NOERROR; + } else if (id==IID_IPin) { + *object=(IPin*)this; + ((IPin*)object)->AddRef(); + return NOERROR; + } else { + *object=NULL; + return E_NOINTERFACE; + } +} + +ULONG STDMETHODCALLTYPE DsSourcePin::AddRef(){ + return m_pFilter->AddRef(); + +} +ULONG STDMETHODCALLTYPE DsSourcePin::Release(){ + return m_pFilter->Release(); +} + + +/*IPin*/ +HRESULT STDMETHODCALLTYPE DsSourcePin::Connect(IPin *pinempf,const AM_MEDIA_TYPE *mtype) { + if (pinempf==NULL) return E_POINTER; + EnterCriticalSection(&m_pFilter->filterlock); + + if (connected!=NULL) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_ALREADY_CONNECTED;} + if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;} + + + bool gotmt=false; + + if (mtype!=NULL) { + if (CheckMediaType(mtype)==S_OK){ + pinempf->AddRef(); + if (pinempf->ReceiveConnection((IPin*)this,mtype)==S_OK) { + CopyMType(&medtype,mtype); + LeaveCriticalSection(&m_pFilter->filterlock); + } else { + LeaveCriticalSection(&m_pFilter->filterlock); + if (mtype->pbFormat!=NULL) CoTaskMemFree(mtype->pbFormat); + pinempf->Release(); + return VFW_E_TYPE_NOT_ACCEPTED; + } + + } else { + LeaveCriticalSection(&m_pFilter->filterlock); + if (mtype->pbFormat!=NULL) CoTaskMemFree(mtype->pbFormat); + return VFW_E_TYPE_NOT_ACCEPTED; + } + CoTaskMemFree(mtype->pbFormat); + }else { + IEnumMediaTypes * emt; + EnumMediaTypes(&emt); + AM_MEDIA_TYPE * emtype; + ULONG fetched=0; + pinempf->AddRef(); + while (emt->Next(1,&emtype,&fetched)==S_OK) { + if (CheckMediaType(emtype)==S_OK){ +/* PIN_INFO pini; + pinempf->QueryPinInfo(&pini); + if (pini.pFilter!=NULL) { + FILTER_INFO filti; + pini.pFilter->QueryFilterInfo(&filti); + + if (filti.pGraph!=NULL) filti.pGraph->Release(); + char buffer[MAX_FILTER_NAME*2]; + wcstombs(buffer,filti.achName,MAX_FILTER_NAME*2); + MessageBox(0,buffer,"Filter",0); + pini.pFilter->Release(); + }*/ + + if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) { + connected=pinempf; + CopyMType(&medtype,emtype); + if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); + + CoTaskMemFree(emtype); + gotmt=true; + break; + } + + } + if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); + CoTaskMemFree(emtype); + } + emt->Release(); + if (gotmt==false) { + pinempf->EnumMediaTypes(&emt); + while (emt->Next(1,&emtype,&fetched)==S_OK) { + if (CheckMediaType(emtype)==S_OK){ + if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) { + connected=pinempf; + CopyMType(&medtype,emtype); + if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); + CoTaskMemFree(emtype); + gotmt=true; + break; + } + + } + if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat); + CoTaskMemFree(emtype); + } + emt->Release(); + if (gotmt==false) { + pinempf->Release(); + LeaveCriticalSection(&m_pFilter->filterlock); + return VFW_E_NO_ACCEPTABLE_TYPES; + } + } + } + + if (pinempf->QueryInterface(IID_IMemInputPin,(void**)&connectedinput)!=S_OK) { + LeaveCriticalSection(&m_pFilter->filterlock); + connected->Release(); + connected=NULL; + /* connectedinput->Release(); + connectedinput=NULL;*/ + return VFW_E_NO_TRANSPORT; + } + ALLOCATOR_PROPERTIES eigenall; + ZeroMemory(&eigenall,sizeof(eigenall)); + connectedinput->GetAllocatorRequirements(&eigenall); + if (eigenall.cbAlign==0) eigenall.cbAlign=1; + connectedinput->GetAllocator(&allocator); + if (DecideBufferSize(allocator,&eigenall)==S_OK) { + if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){ + connected=pinempf; + LeaveCriticalSection(&m_pFilter->filterlock); + return S_OK; + } + } + if (allocator!=NULL) allocator->Release(); + allocator=NULL; + + if (CoCreateInstance(CLSID_MemoryAllocator,0,CLSCTX_INPROC_SERVER, + IID_IMemAllocator,(void **)allocator)==S_OK) { + if (DecideBufferSize(allocator,&eigenall)==S_OK) { + if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){ + connected=pinempf; + LeaveCriticalSection(&m_pFilter->filterlock); + return S_OK; + } + } + } + if (allocator!=NULL) allocator->Release(); + allocator=NULL; + connected->Release(); + connected=NULL; + connectedinput->Release(); + connectedinput=NULL; + LeaveCriticalSection(&m_pFilter->filterlock); + return VFW_E_NO_TRANSPORT; + + + + +} +HRESULT STDMETHODCALLTYPE DsSourcePin::ReceiveConnection(IPin *connect, + const AM_MEDIA_TYPE *mtype){ + return VFW_E_TYPE_NOT_ACCEPTED; //We have only output pins +} + HRESULT STDMETHODCALLTYPE DsSourcePin::Disconnect() { + EnterCriticalSection(&m_pFilter->filterlock); + if (connected!=NULL) { + if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;} + /*TODO: Decommit allocator*/ + allocator->Decommit(); + allocator->Release(); + allocator=NULL; + ReleaseMType(&medtype); + connectedinput->Release(); + connectedinput=NULL; + connected->Release(); + connected=NULL; + LeaveCriticalSection(&m_pFilter->filterlock); + return S_OK; + } + LeaveCriticalSection(&m_pFilter->filterlock); + return S_FALSE; + } + + HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectedTo(IPin **pin){ + if (pin==NULL) return E_POINTER; + IPin* pinn=connected; + *pin=pinn; + if (pinn!=NULL) { + pinn->AddRef(); + return S_OK; + } else { + return VFW_E_NOT_CONNECTED; + } + } + HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectionMediaType(AM_MEDIA_TYPE *mtype){ + if (mtype==NULL) return E_POINTER; + if (connected!=NULL){ + CopyMType(mtype,&medtype); + return S_OK; + } else { + ZeroMemory(mtype,sizeof(*mtype)); + return VFW_E_NOT_CONNECTED; + } + } + HRESULT STDMETHODCALLTYPE DsSourcePin::QueryPinInfo(PIN_INFO *info){ + if (info==NULL) return E_POINTER; + info->dir=PINDIR_OUTPUT; + info->pFilter=(IBaseFilter*)m_pFilter; + if (m_pFilter) m_pFilter->AddRef(); + if (isaudiopin) wcscpy(info->achName,L"Audio"); + else wcscpy(info->achName,L"Video"); + return S_OK; + } + + HRESULT STDMETHODCALLTYPE DsSourcePin::QueryDirection(PIN_DIRECTION *dir){ + if (dir==NULL) return E_POINTER; + *dir=PINDIR_OUTPUT; + return S_OK; + } + HRESULT STDMETHODCALLTYPE DsSourcePin::QueryId(LPWSTR *id){ + if (id==NULL) return E_POINTER; + *id=(LPWSTR)CoTaskMemAlloc(12); + if (*id==NULL) return E_OUTOFMEMORY; + + + if (isaudiopin) wcscpy(*id,L"Audio"); + else wcscpy(*id, L"Video"); + return S_OK; + } + HRESULT STDMETHODCALLTYPE DsSourcePin::QueryAccept(const AM_MEDIA_TYPE *mtype) { + if (mtype==NULL) return S_FALSE; + if (CheckMediaType(mtype)==S_OK) return S_OK; + else return S_FALSE; + } + HRESULT STDMETHODCALLTYPE DsSourcePin::EnumMediaTypes(IEnumMediaTypes **enuma){ +if (enuma==NULL) return E_POINTER; + *enuma=new DsSFEnumMediaTypes( this); + (*enuma)->AddRef(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInternalConnections(IPin **pin,ULONG *numpin){ + return E_NOTIMPL; +} +HRESULT STDMETHODCALLTYPE DsSourcePin::EndOfStream(){ + return E_UNEXPECTED; //we are a output pin! +} + +HRESULT STDMETHODCALLTYPE DsSourcePin::NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate){ + return E_UNEXPECTED;//we are a output pin! +} + +HRESULT DsSourcePin::getCurrentMediaSample(IMediaSample**ms){ + if (allocator!=NULL) return allocator->GetBuffer(ms,NULL,NULL,0); + else return E_NOINTERFACE; +} + +HRESULT DsSourcePin::deliver(IMediaSample * ms){ + //EnterCriticalSection(&m_pFilter->filterlock); + HRESULT hres; + if (connectedinput!=NULL)hres= connectedinput->Receive(ms); + else hres= VFW_E_NOT_CONNECTED; + //LeaveCriticalSection(&m_pFilter->filterlock); + return hres; + +} + +HRESULT DsSourcePin::GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt) +{ + HRESULT hr; + + if (isaudiopin){ + if (iPosition==0) { + ZeroMemory(pmt,sizeof(*pmt)); + pmt->lSampleSize = 1; + pmt->bFixedSizeSamples = TRUE; + pmt->majortype=MEDIATYPE_Audio; + MPEG1WAVEFORMAT wfe; + ZeroMemory(&wfe,sizeof(wfe)); + wfe.wfx.cbSize=22; + wfe.wfx.nSamplesPerSec=48000; + wfe.wfx.nChannels=2; + wfe.wfx.nAvgBytesPerSec=32000; + wfe.wfx.nBlockAlign=768; + wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG; + wfe.wfx.wBitsPerSample=0; + wfe.fwHeadLayer=2; + wfe.dwHeadBitrate=256000; + wfe.fwHeadMode=ACM_MPEG_STEREO; + wfe.fwHeadModeExt=1; + wfe.wHeadEmphasis=1; + wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT; + pmt->subtype=MEDIASUBTYPE_MPEG2_AUDIO; + pmt->formattype=FORMAT_WaveFormatEx; + pmt->cbFormat=sizeof(wfe); + pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe)); + memcpy(pmt->pbFormat,&wfe,sizeof(wfe)); + pmt->lSampleSize=0; + hr=S_OK; + + + } else { + hr=VFW_S_NO_MORE_ITEMS ; + } + } else { + if (iPosition == 0) { + ZeroMemory(pmt,sizeof(*pmt)); + pmt->lSampleSize = 1; + pmt->bFixedSizeSamples = TRUE; + pmt->majortype=MEDIATYPE_Video; + hr=S_OK; + pmt->subtype=MEDIASUBTYPE_MPEG2_VIDEO; + pmt->formattype=FORMAT_MPEG2Video; + + MPEG2VIDEOINFO hdr; + ZeroMemory(&hdr,sizeof(hdr)); + hdr.dwProfile=AM_MPEG2Profile_Main; + hdr.dwLevel=AM_MPEG2Level_Main; + hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader); + hdr.hdr.bmiHeader.biWidth = 720; + hdr.hdr.bmiHeader.biHeight = 568; + pmt->cbFormat=sizeof(hdr); + pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(hdr)); + memcpy(pmt->pbFormat,&hdr,sizeof(hdr)); + + } else { + hr=VFW_S_NO_MORE_ITEMS; + } + } + return hr ; +} + +HRESULT DsSourcePin::Inactive() { + if (allocator!=NULL) return allocator->Decommit(); + return VFW_E_NO_ALLOCATOR; +} + +HRESULT DsSourcePin::Active() { + if (allocator!=NULL) return allocator->Commit(); + return VFW_E_NO_ALLOCATOR; +} + + +HRESULT DsSourcePin::Run(REFERENCE_TIME reftime){ + return NOERROR; +} + +// No description +HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt) +{ + HRESULT res; + + if (isaudiopin) { + bool subtype=false; +#if 0 /* For future demands ac3 */ + subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3); +#endif + subtype=(pmt->subtype==(MEDIASUBTYPE_MPEG2_AUDIO)); + if (pmt->majortype==MEDIATYPE_Audio && subtype) { + res = S_OK ; + } else { + res = S_FALSE ; + } + } else { + if (pmt->majortype==MEDIATYPE_Video && + pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) { + res = S_OK ; + } else { + res = S_FALSE ; + } + } + return res; +} + +HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp){ + HRESULT hr; + + if (pa==NULL)return E_POINTER; + if (all_pp==NULL) return E_POINTER; + if (isaudiopin) { + if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024) + { + //all_pp->cBuffers = 300;//old + all_pp->cBuffers = 10; + all_pp->cbBuffer = 64*1024; + } + } else { + if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024) + { + //all_pp->cBuffers = 300;//old + all_pp->cBuffers = 30; + all_pp->cbBuffer = 64*1024; + } + } + + ALLOCATOR_PROPERTIES all_pp_cur; + hr =pa->SetProperties(all_pp,&all_pp_cur); + if (FAILED(hr)) + { + return hr; + } + if (all_pp_cur.cbBuffer*all_pp_cur.cBuffers < all_pp->cBuffers*all_pp->cbBuffer) + { + return E_FAIL; + } + + return S_OK; +} + + diff --git a/dssourcepin.h b/dssourcepin.h index 2871592..8b023d3 100644 --- a/dssourcepin.h +++ b/dssourcepin.h @@ -46,22 +46,22 @@ public: HRESULT Run(REFERENCE_TIME reftime); /*IPin*/ - virtual HRESULT STDMETHODCALLTYPE Connect(IPin *pinempf,const AM_MEDIA_TYPE *mtype); - virtual HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *connect,const AM_MEDIA_TYPE *mtype); - virtual HRESULT STDMETHODCALLTYPE Disconnect(); - virtual HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pin); - virtual HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *mtype); - virtual HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *info); - virtual HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *dir); - virtual HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *id); - virtual HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *mtype); - virtual HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **enuma); - virtual HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **pin,ULONG *numpin); - virtual HRESULT STDMETHODCALLTYPE EndOfStream(); - virtual HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate); + virtual HRESULT STDMETHODCALLTYPE Connect(IPin *pinempf,const AM_MEDIA_TYPE *mtype); + virtual HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *connect,const AM_MEDIA_TYPE *mtype); + virtual HRESULT STDMETHODCALLTYPE Disconnect(); + virtual HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pin); + virtual HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *mtype); + virtual HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *info); + virtual HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *dir); + virtual HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *id); + virtual HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *mtype); + virtual HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **enuma); + virtual HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **pin,ULONG *numpin); + virtual HRESULT STDMETHODCALLTYPE EndOfStream(); + virtual HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate); /* IUnknown */ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); - virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE AddRef(); virtual ULONG STDMETHODCALLTYPE Release(); virtual HRESULT STDMETHODCALLTYPE BeginFlush(){return E_UNEXPECTED;}; virtual HRESULT STDMETHODCALLTYPE EndFlush(){return E_UNEXPECTED;}; @@ -70,7 +70,7 @@ public: protected: - virtual HRESULT CheckMediaType(const AM_MEDIA_TYPE *pmt); + virtual HRESULT CheckMediaType(const AM_MEDIA_TYPE *pmt); bool isaudiopin; DsSourceFilter *m_pFilter; @@ -86,4 +86,4 @@ protected: -#endif +#endif diff --git a/mutex.cc b/mutex.cc index 1017180..3ad8ca6 100644 --- a/mutex.cc +++ b/mutex.cc @@ -1,51 +1,51 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "mutex.h" - -Mutex::Mutex() { -#ifndef WIN32 - pthread_mutex_init(&my_mutex, NULL); -#else - my_mutex=CreateMutex(NULL,FALSE,NULL); -#endif -} - -Mutex::~Mutex() { -#ifdef WIN32 - CloseHandle(my_mutex); -#endif -} - -void Mutex::Lock() { -#ifndef WIN32 - pthread_mutex_lock(&my_mutex); -#else - WaitForSingleObject(my_mutex, INFINITE ); -#endif -} - -void Mutex::Unlock() { -#ifndef WIN32 - pthread_mutex_unlock(&my_mutex); -#else - ReleaseMutex(my_mutex); -#endif -} - +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "mutex.h" + +Mutex::Mutex() { +#ifndef WIN32 + pthread_mutex_init(&my_mutex, NULL); +#else + my_mutex=CreateMutex(NULL,FALSE,NULL); +#endif +} + +Mutex::~Mutex() { +#ifdef WIN32 + CloseHandle(my_mutex); +#endif +} + +void Mutex::Lock() { +#ifndef WIN32 + pthread_mutex_lock(&my_mutex); +#else + WaitForSingleObject(my_mutex, INFINITE ); +#endif +} + +void Mutex::Unlock() { +#ifndef WIN32 + pthread_mutex_unlock(&my_mutex); +#else + ReleaseMutex(my_mutex); +#endif +} + diff --git a/mutex.h b/mutex.h index d989da8..882e18b 100644 --- a/mutex.h +++ b/mutex.h @@ -1,47 +1,47 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef MUTEX_H -#define MUTEX_H - -#ifndef WIN32 -#include -#else -#include -#include -#endif - - - -class Mutex -{ -public: - Mutex(); - ~Mutex(); - void Lock(); - void Unlock(); -protected: -#ifndef WIN32 - pthread_mutex_t my_mutex; -#else - HANDLE my_mutex; -#endif -}; -#endif +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef MUTEX_H +#define MUTEX_H + +#ifndef WIN32 +#include +#else +#include +#include +#endif + + + +class Mutex +{ +public: + Mutex(); + ~Mutex(); + void Lock(); + void Unlock(); +protected: +#ifndef WIN32 + pthread_mutex_t my_mutex; +#else + HANDLE my_mutex; +#endif +}; +#endif diff --git a/objects.mk b/objects.mk index 08cf8f8..a63c9d9 100644 --- a/objects.mk +++ b/objects.mk @@ -1,17 +1,17 @@ -OBJECTS1 = command.o log.o tcp.o dsock.o thread.o timers.o i18n.o mutex.o \ - message.o messagequeue.o udp.o \ - vdr.o recman.o recording.o recinfo.o channel.o rectimer.o event.o \ - directory.o mark.o \ - player.o playerradio.o vfeed.o afeed.o \ - demuxer.o demuxervdr.o demuxerts.o stream.o draintarget.o \ - viewman.o box.o region.o colour.o view.o \ - vinfo.o vquestion.o vwallpaper.o vrecordinglist.o vlivebanner.o \ - vmute.o vvolume.o voptions.o \ - vtimerlist.o vtimeredit.o voptionsmenu.o vrecordingmenu.o \ - vchannellist.o vwelcome.o vvideolive.o vvideorec.o vepgsettimer.o \ - vchannelselect.o vserverselect.o vconnect.o vepg.o vrecmove.o \ - vradiorec.o vaudioselector.o \ - widget.o wselectlist.o wjpeg.o wsymbol.o wbutton.o \ - woptionbox.o wtextbox.o wwss.o \ - fonts/helvB24.o fonts/helvB18.o \ - remote.o led.o mtd.o video.o audio.o osd.o surface.o +OBJECTS1 = command.o log.o tcp.o dsock.o thread.o timers.o i18n.o mutex.o \ + message.o messagequeue.o udp.o \ + vdr.o recman.o recording.o recinfo.o channel.o rectimer.o event.o \ + directory.o mark.o \ + player.o playerradio.o vfeed.o afeed.o \ + demuxer.o demuxervdr.o demuxerts.o stream.o draintarget.o \ + viewman.o box.o region.o colour.o view.o \ + vinfo.o vquestion.o vwallpaper.o vrecordinglist.o vlivebanner.o \ + vmute.o vvolume.o voptions.o \ + vtimerlist.o vtimeredit.o voptionsmenu.o vrecordingmenu.o \ + vchannellist.o vwelcome.o vvideolive.o vvideorec.o vepgsettimer.o \ + vchannelselect.o vserverselect.o vconnect.o vepg.o vrecmove.o \ + vradiorec.o vaudioselector.o \ + widget.o wselectlist.o wjpeg.o wsymbol.o wbutton.o \ + woptionbox.o wtextbox.o wwss.o \ + fonts/helvB24.o fonts/helvB18.o \ + remote.o led.o mtd.o video.o audio.o osd.o surface.o diff --git a/osdwin.cc b/osdwin.cc index 58cf1ef..9896779 100644 --- a/osdwin.cc +++ b/osdwin.cc @@ -1,342 +1,342 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - -#include "osdwin.h" -#include "mtd.h" -#include "videowin.h" -#include "surfacewin.h" - -#include "dsallocator.h" - - -//This is stuff for rendering the OSD - - -OsdWin::OsdWin() -{ - d3d=NULL; - d3ddevice=NULL; - d3dvb=NULL; - d3drtsurf=NULL; - external_driving=false; - dsallocator=NULL; - filter_type=D3DTEXF_NONE; - lastrendertime=timeGetTime(); - event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL); - d3dmutex = CreateMutex(NULL,FALSE,NULL); - -} - -OsdWin::~OsdWin() -{ - if (initted) shutdown(); - CloseHandle(event); - CloseHandle(d3dmutex); -} - -int OsdWin::getFD() -{ - if (!initted) return 0; - return fdOsd; -} - -int OsdWin::init(void* device) -{ - if (initted) return 0; - Video* video = Video::getInstance(); - //First Create Direct 3D Object - d3d=Direct3DCreate9(D3D_SDK_VERSION); - if (!d3d) - { - Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 object!"); - return 0; - } - // then create the Device - D3DPRESENT_PARAMETERS d3dparas; - ZeroMemory(&d3dparas,sizeof(d3dparas)); - d3dparas.BackBufferWidth=video->getScreenWidth(); - d3dparas.BackBufferHeight=video->getScreenHeight(); - d3dparas.Windowed=TRUE; - d3dparas.SwapEffect=D3DSWAPEFFECT_COPY; - if (d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,*((HWND*) device), - D3DCREATE_SOFTWARE_VERTEXPROCESSING |D3DCREATE_MULTITHREADED,&d3dparas,&d3ddevice)!=D3D_OK) { - Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 device!"); - return 0; - } - d3ddevice->GetRenderTarget(0,&d3drtsurf); - - if (!InitVertexBuffer()) { - Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 vertex buf!"); - return 0; - } - /* We have to determine which kind of filtering is supported*/ - D3DCAPS9 caps; - d3ddevice->GetDeviceCaps(&caps); - filter_type=D3DTEXF_NONE; - if ( ((caps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFPOINT)!=0) - && ((caps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFPOINT)!=0)) { - filter_type=D3DTEXF_POINT; - } - if ( ((caps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFLINEAR)!=0) - && ((caps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)!=0)) { - filter_type=D3DTEXF_LINEAR; - } - - //Now we will create the Screen - screen = new SurfaceWin(Surface::SCREEN); - SetEvent(event);//Now all devices are ready - screen->create(video->getScreenWidth(), video->getScreenHeight()); - screen->display(); - initted = 1; // must set this here or create surface won't work - - return 1; -} - - -int OsdWin::InitVertexBuffer() { - Video* video = Video::getInstance(); - FLOAT texx=((float)video->getScreenWidth())/1024.f; - FLOAT texy=((float)video->getScreenHeight())/1024.f; - D3DCOLOR osdcolor=D3DCOLOR_RGBA(255,255,255,255); - osdvertices[0].c=osdcolor; - osdvertices[0].x=0.f-0.5f; - osdvertices[0].y=0.f-0.5f; - osdvertices[0].z=0.5f; - osdvertices[0].rhw=1.f; - osdvertices[0].u=0.f; - osdvertices[0].v=0.f; - osdvertices[1].c=osdcolor; - osdvertices[1].x=((float)video->getScreenWidth())-0.5f;-0.5f; - osdvertices[1].y=0.f-0.5f; - osdvertices[1].z=0.5f; - osdvertices[1].u=texx; - osdvertices[1].v=0.f; - osdvertices[1].rhw=1.f; - osdvertices[2].c=osdcolor; - osdvertices[2].x=((float)video->getScreenWidth())-0.5f; - osdvertices[2].y=((float)video->getScreenHeight())-0.5f; - osdvertices[2].z=0.5f; - osdvertices[2].rhw=1.f; - osdvertices[2].u=texx; - osdvertices[2].v=texy; - osdvertices[3].c=osdcolor; - osdvertices[3].x=0.f-0.5f; - osdvertices[3].y=((float)video->getScreenHeight())-0.5f; - osdvertices[3].z=0; - osdvertices[3].rhw=1.f; - osdvertices[3].u=0.f; - osdvertices[3].v=texy; - if (d3dvb) { - d3dvb->Release(); - d3dvb=NULL; - } - if (d3ddevice->CreateVertexBuffer(4*sizeof(OSDVERTEX),0,D3DFVF_OSDVERTEX,D3DPOOL_MANAGED, - &d3dvb,NULL)!=D3D_OK) { - return 0; - } - void *pvertex=NULL; - if (d3dvb->Lock(0,sizeof(osdvertices),&pvertex,0)!=D3D_OK) { - return 0; - } - memcpy(pvertex,osdvertices,sizeof(osdvertices)); - d3dvb->Unlock(); - return 1; -} - -int OsdWin::shutdown() -{ - if (!initted) return 0; - initted = 0; - d3drtsurf->Release(); - d3ddevice->Release(); - d3d->Release(); - - return 1; -} - -void OsdWin::screenShot(char* fileName) -{ - screen->screenShot(fileName); -} - -// This function is called from the WinMain function in order to get Screen updates -void OsdWin::Render() -{ - if (!initted) return ; - if (external_driving) { - Sleep(5); //Sleep for 5 ms, in order to avoid blocking the other threads - } else { - DWORD time1=timeGetTime(); - if ((time1-lastrendertime)>50) {//10 fps for OSD updates are enough, avoids tearing - InternalRendering(NULL); - lastrendertime=timeGetTime(); - } else { - Sleep(5); - - } - - } -} - -void OsdWin::RenderDS(LPDIRECT3DSURFACE9 present){ - if (!initted) return; - if (external_driving) { - InternalRendering(present); - } -} - - -void OsdWin::InternalRendering(LPDIRECT3DSURFACE9 present){ - WaitForSingleObject(event,INFINITE); - WaitForSingleObject(d3dmutex,INFINITE); - BeginPainting(); - if (external_driving) { - //Copy video to Backbuffer - if (present!=NULL) { - VideoWin* video =(VideoWin*) Video::getInstance(); - /*calculating destination rect */ - RECT destrect={0,0,video->getScreenWidth(),video->getScreenHeight()}; - UCHAR mode=video->getMode(); - switch (mode) { - case Video::EIGHTH: - destrect.right=destrect.right/2; - destrect.bottom=destrect.bottom/2; - case Video::QUARTER: - destrect.right=destrect.right/2+video->getPosx()*2; - destrect.bottom=destrect.bottom/2+video->getPosy()*2; - destrect.left=video->getPosx()*2; - destrect.top=video->getPosy()*2; - d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0); - break; - }; - D3DSURFACE_DESC surf_desc; - present->GetDesc(&surf_desc);//for chop sides - RECT sourcerect= {0,0,surf_desc.Width,surf_desc.Height}; - if (video->getPseudoTVsize()==Video::ASPECT4X3 - && video->getMode()==Video::NORMAL - && video->getAspectRatio()==Video::ASPECT16X9) { - unsigned int correction=((double) (surf_desc.Width))*4.*9./3./16.; - sourcerect.left=(surf_desc.Width-correction)/2; - sourcerect.right=sourcerect.left+correction; - } - d3ddevice->StretchRect(present,&sourcerect,d3drtsurf ,&destrect,filter_type); - } - } else { - VideoWin* video =(VideoWin*) Video::getInstance(); - //Clear Background - if (!video->isVideoOn()) d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0); - } - //Drawing the OSD - if (d3ddevice->BeginScene()==D3D_OK) { - d3ddevice->SetStreamSource(0,d3dvb,0,sizeof(OSDVERTEX)); - d3ddevice->SetFVF(D3DFVF_OSDVERTEX); - d3ddevice->SetTexture(0,((SurfaceWin*)screen)->getD3dtexture()); - //d3ddevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP,D3DTOP_MODULATE); - d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE); - d3ddevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA); - d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - d3ddevice->SetRenderState(D3DRS_LIGHTING,FALSE); - - - d3ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN,0,2); - d3ddevice->EndScene(); - //Show it to the user! - if (d3ddevice->Present(NULL,NULL,NULL,NULL)==D3DERR_DEVICELOST){ - EndPainting(); - DoLost(); - } - EndPainting(); - } - ReleaseMutex(d3dmutex); - if (!external_driving) { - Sleep(4);//The User can wait for 4 milliseconds to see his changes - } -} - -void OsdWin::DoLost(){ - Log::getInstance()->log("OSD", Log::WARN, "Direct3D Device Lost! Reobtaining..."); - ResetEvent(event); - if (external_driving && dsallocator!=NULL) { - dsallocator->LostDevice(); //Propagate the information through DS - } - //First we free up all resources - Video* video = Video::getInstance(); - ((SurfaceWin*)screen)->ReleaseSurface(); - d3drtsurf->Release(); - d3dvb->Release(); - d3dvb=NULL; - D3DPRESENT_PARAMETERS d3dparas; - ZeroMemory(&d3dparas,sizeof(d3dparas)); - d3dparas.BackBufferWidth=video->getScreenWidth(); - d3dparas.BackBufferHeight=video->getScreenHeight(); - d3dparas.Windowed=TRUE; - d3dparas.SwapEffect=D3DSWAPEFFECT_COPY; - if (d3ddevice->Reset(&d3dparas)!=D3D_OK){ - return; - } - screen->create(video->getScreenWidth(), video->getScreenHeight()); - screen->display(); - d3ddevice->GetRenderTarget(0,&d3drtsurf); - InitVertexBuffer(); - //Redraw Views, Chris could you add a member function to viewman, so that - // I can cause it to completely redraw the Views? - // Otherwise the OSD would be distorted after Device Lost - - SetEvent(event); - -} -LPDIRECT3DDEVICE9 OsdWin::getD3dDev() { - WaitForSingleObject(event,INFINITE);//We will only return if we are initted - return d3ddevice; -} - -LPDIRECT3D9 OsdWin::getD3d() { - WaitForSingleObject(event,INFINITE);//We will only return if we are initted - return d3d; -} - -void OsdWin::BeginPainting() {//We synchronize calls to d3d between different threads - WaitForSingleObject(d3dmutex,INFINITE); -} - -void OsdWin::EndPainting() { - ReleaseMutex(d3dmutex); -} - -void OsdWin::setExternalDriving(DsAllocator* dsall) { - if (dsall==NULL) { - external_driving=false; - dsallocator=NULL; - return; - } - WaitForSingleObject(event,INFINITE);//We will only return if we are initted - dsallocator=dsall; - external_driving=true; -} - -void OsdWin::Blank() { - WaitForSingleObject(event,INFINITE); - BeginPainting(); - d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0); - EndPainting(); -} - +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "osdwin.h" +#include "mtd.h" +#include "videowin.h" +#include "surfacewin.h" + +#include "dsallocator.h" + + +//This is stuff for rendering the OSD + + +OsdWin::OsdWin() +{ + d3d=NULL; + d3ddevice=NULL; + d3dvb=NULL; + d3drtsurf=NULL; + external_driving=false; + dsallocator=NULL; + filter_type=D3DTEXF_NONE; + lastrendertime=timeGetTime(); + event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL); + d3dmutex = CreateMutex(NULL,FALSE,NULL); + +} + +OsdWin::~OsdWin() +{ + if (initted) shutdown(); + CloseHandle(event); + CloseHandle(d3dmutex); +} + +int OsdWin::getFD() +{ + if (!initted) return 0; + return fdOsd; +} + +int OsdWin::init(void* device) +{ + if (initted) return 0; + Video* video = Video::getInstance(); + //First Create Direct 3D Object + d3d=Direct3DCreate9(D3D_SDK_VERSION); + if (!d3d) + { + Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 object!"); + return 0; + } + // then create the Device + D3DPRESENT_PARAMETERS d3dparas; + ZeroMemory(&d3dparas,sizeof(d3dparas)); + d3dparas.BackBufferWidth=video->getScreenWidth(); + d3dparas.BackBufferHeight=video->getScreenHeight(); + d3dparas.Windowed=TRUE; + d3dparas.SwapEffect=D3DSWAPEFFECT_COPY; + if (d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,*((HWND*) device), + D3DCREATE_SOFTWARE_VERTEXPROCESSING |D3DCREATE_MULTITHREADED,&d3dparas,&d3ddevice)!=D3D_OK) { + Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 device!"); + return 0; + } + d3ddevice->GetRenderTarget(0,&d3drtsurf); + + if (!InitVertexBuffer()) { + Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 vertex buf!"); + return 0; + } + /* We have to determine which kind of filtering is supported*/ + D3DCAPS9 caps; + d3ddevice->GetDeviceCaps(&caps); + filter_type=D3DTEXF_NONE; + if ( ((caps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFPOINT)!=0) + && ((caps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFPOINT)!=0)) { + filter_type=D3DTEXF_POINT; + } + if ( ((caps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFLINEAR)!=0) + && ((caps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)!=0)) { + filter_type=D3DTEXF_LINEAR; + } + + //Now we will create the Screen + screen = new SurfaceWin(Surface::SCREEN); + SetEvent(event);//Now all devices are ready + screen->create(video->getScreenWidth(), video->getScreenHeight()); + screen->display(); + initted = 1; // must set this here or create surface won't work + + return 1; +} + + +int OsdWin::InitVertexBuffer() { + Video* video = Video::getInstance(); + FLOAT texx=((float)video->getScreenWidth())/1024.f; + FLOAT texy=((float)video->getScreenHeight())/1024.f; + D3DCOLOR osdcolor=D3DCOLOR_RGBA(255,255,255,255); + osdvertices[0].c=osdcolor; + osdvertices[0].x=0.f-0.5f; + osdvertices[0].y=0.f-0.5f; + osdvertices[0].z=0.5f; + osdvertices[0].rhw=1.f; + osdvertices[0].u=0.f; + osdvertices[0].v=0.f; + osdvertices[1].c=osdcolor; + osdvertices[1].x=((float)video->getScreenWidth())-0.5f;-0.5f; + osdvertices[1].y=0.f-0.5f; + osdvertices[1].z=0.5f; + osdvertices[1].u=texx; + osdvertices[1].v=0.f; + osdvertices[1].rhw=1.f; + osdvertices[2].c=osdcolor; + osdvertices[2].x=((float)video->getScreenWidth())-0.5f; + osdvertices[2].y=((float)video->getScreenHeight())-0.5f; + osdvertices[2].z=0.5f; + osdvertices[2].rhw=1.f; + osdvertices[2].u=texx; + osdvertices[2].v=texy; + osdvertices[3].c=osdcolor; + osdvertices[3].x=0.f-0.5f; + osdvertices[3].y=((float)video->getScreenHeight())-0.5f; + osdvertices[3].z=0; + osdvertices[3].rhw=1.f; + osdvertices[3].u=0.f; + osdvertices[3].v=texy; + if (d3dvb) { + d3dvb->Release(); + d3dvb=NULL; + } + if (d3ddevice->CreateVertexBuffer(4*sizeof(OSDVERTEX),0,D3DFVF_OSDVERTEX,D3DPOOL_MANAGED, + &d3dvb,NULL)!=D3D_OK) { + return 0; + } + void *pvertex=NULL; + if (d3dvb->Lock(0,sizeof(osdvertices),&pvertex,0)!=D3D_OK) { + return 0; + } + memcpy(pvertex,osdvertices,sizeof(osdvertices)); + d3dvb->Unlock(); + return 1; +} + +int OsdWin::shutdown() +{ + if (!initted) return 0; + initted = 0; + d3drtsurf->Release(); + d3ddevice->Release(); + d3d->Release(); + + return 1; +} + +void OsdWin::screenShot(char* fileName) +{ + screen->screenShot(fileName); +} + +// This function is called from the WinMain function in order to get Screen updates +void OsdWin::Render() +{ + if (!initted) return ; + if (external_driving) { + Sleep(5); //Sleep for 5 ms, in order to avoid blocking the other threads + } else { + DWORD time1=timeGetTime(); + if ((time1-lastrendertime)>50) {//10 fps for OSD updates are enough, avoids tearing + InternalRendering(NULL); + lastrendertime=timeGetTime(); + } else { + Sleep(5); + + } + + } +} + +void OsdWin::RenderDS(LPDIRECT3DSURFACE9 present){ + if (!initted) return; + if (external_driving) { + InternalRendering(present); + } +} + + +void OsdWin::InternalRendering(LPDIRECT3DSURFACE9 present){ + WaitForSingleObject(event,INFINITE); + WaitForSingleObject(d3dmutex,INFINITE); + BeginPainting(); + if (external_driving) { + //Copy video to Backbuffer + if (present!=NULL) { + VideoWin* video =(VideoWin*) Video::getInstance(); + /*calculating destination rect */ + RECT destrect={0,0,video->getScreenWidth(),video->getScreenHeight()}; + UCHAR mode=video->getMode(); + switch (mode) { + case Video::EIGHTH: + destrect.right=destrect.right/2; + destrect.bottom=destrect.bottom/2; + case Video::QUARTER: + destrect.right=destrect.right/2+video->getPosx()*2; + destrect.bottom=destrect.bottom/2+video->getPosy()*2; + destrect.left=video->getPosx()*2; + destrect.top=video->getPosy()*2; + d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0); + break; + }; + D3DSURFACE_DESC surf_desc; + present->GetDesc(&surf_desc);//for chop sides + RECT sourcerect= {0,0,surf_desc.Width,surf_desc.Height}; + if (video->getPseudoTVsize()==Video::ASPECT4X3 + && video->getMode()==Video::NORMAL + && video->getAspectRatio()==Video::ASPECT16X9) { + unsigned int correction=((double) (surf_desc.Width))*4.*9./3./16.; + sourcerect.left=(surf_desc.Width-correction)/2; + sourcerect.right=sourcerect.left+correction; + } + d3ddevice->StretchRect(present,&sourcerect,d3drtsurf ,&destrect,filter_type); + } + } else { + VideoWin* video =(VideoWin*) Video::getInstance(); + //Clear Background + if (!video->isVideoOn()) d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0); + } + //Drawing the OSD + if (d3ddevice->BeginScene()==D3D_OK) { + d3ddevice->SetStreamSource(0,d3dvb,0,sizeof(OSDVERTEX)); + d3ddevice->SetFVF(D3DFVF_OSDVERTEX); + d3ddevice->SetTexture(0,((SurfaceWin*)screen)->getD3dtexture()); + //d3ddevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP,D3DTOP_MODULATE); + d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE); + d3ddevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA); + d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + d3ddevice->SetRenderState(D3DRS_LIGHTING,FALSE); + + + d3ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN,0,2); + d3ddevice->EndScene(); + //Show it to the user! + if (d3ddevice->Present(NULL,NULL,NULL,NULL)==D3DERR_DEVICELOST){ + EndPainting(); + DoLost(); + } + EndPainting(); + } + ReleaseMutex(d3dmutex); + if (!external_driving) { + Sleep(4);//The User can wait for 4 milliseconds to see his changes + } +} + +void OsdWin::DoLost(){ + Log::getInstance()->log("OSD", Log::WARN, "Direct3D Device Lost! Reobtaining..."); + ResetEvent(event); + if (external_driving && dsallocator!=NULL) { + dsallocator->LostDevice(); //Propagate the information through DS + } + //First we free up all resources + Video* video = Video::getInstance(); + ((SurfaceWin*)screen)->ReleaseSurface(); + d3drtsurf->Release(); + d3dvb->Release(); + d3dvb=NULL; + D3DPRESENT_PARAMETERS d3dparas; + ZeroMemory(&d3dparas,sizeof(d3dparas)); + d3dparas.BackBufferWidth=video->getScreenWidth(); + d3dparas.BackBufferHeight=video->getScreenHeight(); + d3dparas.Windowed=TRUE; + d3dparas.SwapEffect=D3DSWAPEFFECT_COPY; + if (d3ddevice->Reset(&d3dparas)!=D3D_OK){ + return; + } + screen->create(video->getScreenWidth(), video->getScreenHeight()); + screen->display(); + d3ddevice->GetRenderTarget(0,&d3drtsurf); + InitVertexBuffer(); + //Redraw Views, Chris could you add a member function to viewman, so that + // I can cause it to completely redraw the Views? + // Otherwise the OSD would be distorted after Device Lost + + SetEvent(event); + +} +LPDIRECT3DDEVICE9 OsdWin::getD3dDev() { + WaitForSingleObject(event,INFINITE);//We will only return if we are initted + return d3ddevice; +} + +LPDIRECT3D9 OsdWin::getD3d() { + WaitForSingleObject(event,INFINITE);//We will only return if we are initted + return d3d; +} + +void OsdWin::BeginPainting() {//We synchronize calls to d3d between different threads + WaitForSingleObject(d3dmutex,INFINITE); +} + +void OsdWin::EndPainting() { + ReleaseMutex(d3dmutex); +} + +void OsdWin::setExternalDriving(DsAllocator* dsall) { + if (dsall==NULL) { + external_driving=false; + dsallocator=NULL; + return; + } + WaitForSingleObject(event,INFINITE);//We will only return if we are initted + dsallocator=dsall; + external_driving=true; +} + +void OsdWin::Blank() { + WaitForSingleObject(event,INFINITE); + BeginPainting(); + d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0); + EndPainting(); +} + diff --git a/osdwin.h b/osdwin.h index 05505e3..1323758 100644 --- a/osdwin.h +++ b/osdwin.h @@ -1,84 +1,84 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef OSDWIN_H -#define OSDWIN_H - -#include - -#include "osd.h" -#include "defines.h" -#include "log.h" -#include -#include - -struct OSDVERTEX -{ - FLOAT x,y,z,rhw; - DWORD c; - FLOAT u,v; -}; - -#define D3DFVF_OSDVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE| D3DFVF_TEX1) - -class DsAllocator; - -class OsdWin : public Osd -{ - public: - OsdWin(); - ~OsdWin(); - - int init(void* device); - int shutdown(); - - int getFD(); - - void screenShot(char* fileName); - - LPDIRECT3DDEVICE9 getD3dDev() ; - LPDIRECT3D9 getD3d() ; - // This function is called from the WinMain function in order to get Screen updates - void Render(); - void RenderDS(LPDIRECT3DSURFACE9 present); - void BeginPainting(); - void EndPainting(); - void setExternalDriving(DsAllocator* dsall); - void Blank(); -private: - LPDIRECT3D9 d3d; - LPDIRECT3DDEVICE9 d3ddevice; - LPDIRECT3DVERTEXBUFFER9 d3dvb; - LPDIRECT3DSURFACE9 d3drtsurf; - DsAllocator* dsallocator; - // This indicates, that currently a video is played, thus the osd updates are driven by the Directshow Filtersystem - bool external_driving; - HANDLE d3dmutex; - DWORD lastrendertime; - void InternalRendering(LPDIRECT3DSURFACE9 present); - void DoLost(); - int InitVertexBuffer(); - OSDVERTEX osdvertices[4]; - HANDLE event; - D3DTEXTUREFILTERTYPE filter_type; -}; - -#endif - +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef OSDWIN_H +#define OSDWIN_H + +#include + +#include "osd.h" +#include "defines.h" +#include "log.h" +#include +#include + +struct OSDVERTEX +{ + FLOAT x,y,z,rhw; + DWORD c; + FLOAT u,v; +}; + +#define D3DFVF_OSDVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE| D3DFVF_TEX1) + +class DsAllocator; + +class OsdWin : public Osd +{ + public: + OsdWin(); + ~OsdWin(); + + int init(void* device); + int shutdown(); + + int getFD(); + + void screenShot(char* fileName); + + LPDIRECT3DDEVICE9 getD3dDev() ; + LPDIRECT3D9 getD3d() ; + // This function is called from the WinMain function in order to get Screen updates + void Render(); + void RenderDS(LPDIRECT3DSURFACE9 present); + void BeginPainting(); + void EndPainting(); + void setExternalDriving(DsAllocator* dsall); + void Blank(); +private: + LPDIRECT3D9 d3d; + LPDIRECT3DDEVICE9 d3ddevice; + LPDIRECT3DVERTEXBUFFER9 d3dvb; + LPDIRECT3DSURFACE9 d3drtsurf; + DsAllocator* dsallocator; + // This indicates, that currently a video is played, thus the osd updates are driven by the Directshow Filtersystem + bool external_driving; + HANDLE d3dmutex; + DWORD lastrendertime; + void InternalRendering(LPDIRECT3DSURFACE9 present); + void DoLost(); + int InitVertexBuffer(); + OSDVERTEX osdvertices[4]; + HANDLE event; + D3DTEXTUREFILTERTYPE filter_type; +}; + +#endif + diff --git a/readme.win b/readme.win index 86854b5..d3f676c 100644 --- a/readme.win +++ b/readme.win @@ -1,137 +1,137 @@ -Readme For Windows Port of Vomp-Client -====================================== - -This file contains notes regarding the Windows port of Vomp. -Please read it carefully. - -License and Homepage -==================== - -The source code of vomp client is released under the General Public License (GPL). -For further information consult the vomp homepage: -http://www.loggytronic.com -or vomp on SourceForge (including the source code on cvs): -http://sourceforge.net/projects/vomp - -Requirements -============ - -The vomp client on Windows requires: - -* Windows 2000 or later -* Windows XP for full remote control support -* DirectX 8 graphics card (some older cards might work also) -* A DirectShow MPEG2 decoder, which supports Video Mixing Renderer 9 (VMR-9), - mostly included within DVD software player -* A network connection to the vompserver computer - -Compatibility List for MPEG2 Decoders -===================================== - -Compatible MPEG2 decoders: -* Cyberlink PowerDVD 5 (build 2214 and later, look for the update at cyberlinks webpage) -* Cyberlink PowerDVD 6 -* Cyberlink PowerDVD 7 -* Nero Showtime 2 (from Nero Suite 6) -* MPV Decoder Filter -* Ulead MovieFactory 5 (Intervideo Filter shipped within) - -Incompatible MPEG2 decoders: -* Cyberlink PowerDVD 4 -* MainConcept Video Decoder version 1.0.0.38 (comes with some Hauppauge software) - -These lists are provided without any warranty. -These lists will be extended, please report success or failure with your decoder -at the forum at http://www.loggytronic.com . - -Remote Control Buttons Reference -================================ - -This table shows the Hauppauge MediaMVP remote control buttons and their -corresponding Windows keyboard assignments: - -MediaMVP Button | Keyboard Shortcut -----------------*------------------ -VOLUMEUP | F10 -VOLUMEDOWN | F9 -CHANNELUP | "+", Ctrl+"+", Page down -CHANNELDOWN | Insert, Ctrl+Insert, Page up -0 | 0 -1 | 1 -2 | 2 -3 | 3 -4 | 4 -5 | 5 -6 | 6 -7 | 7 -8 | 8 -9 | 9 -POWER | Esc, Alt+F4 -GO | j -BACK | Backspace -MENU | m -RED | r -GREEN | g -YELLOW | y -BLUE | b -MUTE | F8 -RADIO | Not implemented -REVERSE | Shift + Control + B -PLAY | Shift + P -FORWARD | Shift + Control + F -RECORD | Ctrl + R -STOP | Ctrl + S -PAUSE | Ctrl + P -SKIPBACK | Ctrl + B -SKIPFORWARD | Ctrl + F -OK | Space, Return -FULL | Not implemented -TV | Not implemented -VIDEOS | Not implemented -MUSIC | Not implemented -PICTURES | Not implemented -GUIDE | Not implemented -UP | UP -DOWN | DOWN -LEFT | LEFT -RIGHT | RIGHT -PREVCHANNEL | Not implemented -STAR | * -HASH | Not implemented - -Use Alt-Enter to toggle full screen mode. - -Remote Controls tested with vomp on windows -=========================================== - -Compatible -========== -* AR Remote Control MCE (1040050, X10), [All buttons recognized, except POWER] - -Note: Remote Controls for Windows should work also for most buttons, -however full remote control support is restricted to Windows XP and above. -If buttons of your remote control are not supported, please post a message -in the forum at http://www.loggytronic.com and we will add them to vomp. - - - -Usage -===== -Start the client executable and enjoy, you should not have to configure -anything if you met the requirements above. - -Log file -======== - -To obtain a log file, please execute the following command in the directory -of the vomp for windows in a shell: - -vompclient.exe > vomp.log - -Firewall -======== -If vomp for Windows stops at "Locating server" or "Connecting to VDR", -please configure your firewall so that vomp for windows can communicate -with the vompserver on port 3024 (UDP and TCP). - - +Readme For Windows Port of Vomp-Client +====================================== + +This file contains notes regarding the Windows port of Vomp. +Please read it carefully. + +License and Homepage +==================== + +The source code of vomp client is released under the General Public License (GPL). +For further information consult the vomp homepage: +http://www.loggytronic.com +or vomp on SourceForge (including the source code on cvs): +http://sourceforge.net/projects/vomp + +Requirements +============ + +The vomp client on Windows requires: + +* Windows 2000 or later +* Windows XP for full remote control support +* DirectX 8 graphics card (some older cards might work also) +* A DirectShow MPEG2 decoder, which supports Video Mixing Renderer 9 (VMR-9), + mostly included within DVD software player +* A network connection to the vompserver computer + +Compatibility List for MPEG2 Decoders +===================================== + +Compatible MPEG2 decoders: +* Cyberlink PowerDVD 5 (build 2214 and later, look for the update at cyberlinks webpage) +* Cyberlink PowerDVD 6 +* Cyberlink PowerDVD 7 +* Nero Showtime 2 (from Nero Suite 6) +* MPV Decoder Filter +* Ulead MovieFactory 5 (Intervideo Filter shipped within) + +Incompatible MPEG2 decoders: +* Cyberlink PowerDVD 4 +* MainConcept Video Decoder version 1.0.0.38 (comes with some Hauppauge software) + +These lists are provided without any warranty. +These lists will be extended, please report success or failure with your decoder +at the forum at http://www.loggytronic.com . + +Remote Control Buttons Reference +================================ + +This table shows the Hauppauge MediaMVP remote control buttons and their +corresponding Windows keyboard assignments: + +MediaMVP Button | Keyboard Shortcut +----------------*------------------ +VOLUMEUP | F10 +VOLUMEDOWN | F9 +CHANNELUP | "+", Ctrl+"+", Page down +CHANNELDOWN | Insert, Ctrl+Insert, Page up +0 | 0 +1 | 1 +2 | 2 +3 | 3 +4 | 4 +5 | 5 +6 | 6 +7 | 7 +8 | 8 +9 | 9 +POWER | Esc, Alt+F4 +GO | j +BACK | Backspace +MENU | m +RED | r +GREEN | g +YELLOW | y +BLUE | b +MUTE | F8 +RADIO | Not implemented +REVERSE | Shift + Control + B +PLAY | Shift + P +FORWARD | Shift + Control + F +RECORD | Ctrl + R +STOP | Ctrl + S +PAUSE | Ctrl + P +SKIPBACK | Ctrl + B +SKIPFORWARD | Ctrl + F +OK | Space, Return +FULL | Not implemented +TV | Not implemented +VIDEOS | Not implemented +MUSIC | Not implemented +PICTURES | Not implemented +GUIDE | Not implemented +UP | UP +DOWN | DOWN +LEFT | LEFT +RIGHT | RIGHT +PREVCHANNEL | Not implemented +STAR | * +HASH | Not implemented + +Use Alt-Enter to toggle full screen mode. + +Remote Controls tested with vomp on windows +=========================================== + +Compatible +========== +* AR Remote Control MCE (1040050, X10), [All buttons recognized, except POWER] + +Note: Remote Controls for Windows should work also for most buttons, +however full remote control support is restricted to Windows XP and above. +If buttons of your remote control are not supported, please post a message +in the forum at http://www.loggytronic.com and we will add them to vomp. + + + +Usage +===== +Start the client executable and enjoy, you should not have to configure +anything if you met the requirements above. + +Log file +======== + +To obtain a log file, please execute the following command in the directory +of the vomp for windows in a shell: + +vompclient.exe > vomp.log + +Firewall +======== +If vomp for Windows stops at "Locating server" or "Connecting to VDR", +please configure your firewall so that vomp for windows can communicate +with the vompserver on port 3024 (UDP and TCP). + + diff --git a/remotewin.cc b/remotewin.cc index 28d6abd..879142f 100644 --- a/remotewin.cc +++ b/remotewin.cc @@ -1,280 +1,280 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "remotewin.h" -#include "vompreswin.h" - - -RemoteWin::RemoteWin() -{ - initted = 0; - curevent=NA_NONE; - signal=false; -} - -RemoteWin::~RemoteWin() -{ -} - -int RemoteWin::init(char* devName) -{ - if (initted) return 0; - initted = 1; - event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL); - - - return 1; -} - -int RemoteWin::shutdown() -{ - if (!initted) return 0; - CloseHandle(event); - initted = 0; - return 1; -} - -UCHAR RemoteWin::getButtonPress(int waitType) -{ - /* how = 0 - block - how = 1 - start new wait - how = 2 - continue wait - how = 3 - no wait - */ - DWORD wait; - - if (curevent!=NA_NONE) { - UCHAR temp=curevent; - curevent=NA_NONE; - return temp; - } - if (waitType==3) { - return NA_NONE; - } - if (waitType==0) { - wait=INFINITE; - } else { //We do not distingish between 2 and 3 - wait=1000; - - } - WaitForSingleObject(event,wait); - ResetEvent(event); - if (curevent==NA_NONE) { - if (signal) { - signal=false; - return NA_SIGNAL; //Since we have no signals on windows, we simulate this - } else { - return NA_NONE; - } - } - UCHAR temp2=curevent; - curevent=NA_NONE; - return temp2; - -} - -void RemoteWin::clearBuffer() -{ -} - -int RemoteWin::ReceiveButtonVK(UINT button) { - UCHAR pb=NA_NONE; - //should we use a translation table ? No APPCOMMAND iS DWORD! - switch (button) { //Processing VK_Messages - case VK_DOWN: - pb=DOWN; break; - case VK_RETURN: - case VK_SPACE: - pb=OK;break; - case VK_LEFT: - pb=LEFT;break; - case '9': - case VK_NUMPAD9: - pb=NINE;break; - case '8': - case VK_NUMPAD8: - pb=EIGHT;break; - case '7': - case VK_NUMPAD7: - pb=SEVEN;break; - case '6': - case VK_NUMPAD6: - pb=SIX;break; - case '5': - case VK_NUMPAD5: - pb=FIVE;break; - case '4': - case VK_NUMPAD4: - pb=FOUR;break; - case '3': - case VK_NUMPAD3: - pb=THREE;break; - case '2': - case VK_NUMPAD2: - pb=TWO;break; - case '1': - case VK_NUMPAD1: - pb=ONE;break; - case '0': - case VK_NUMPAD0: - pb=ZERO;break; - case VK_RIGHT: - pb=RIGHT;break; - case VK_UP: - pb=UP;break; - case VK_MULTIPLY: - pb=STAR;break; - case 'J'://j for JUMP TO instead of go to - pb=GO;break; - //case VK_ESCAPE: - // pb=POWER;break; - case VK_BACK: - pb=BACK;break; - case 'M': - pb=MENU;break; - case 'R': - pb=RED;break; - case 'G': - pb=GREEN;break; - case 'Y': - pb=YELLOW;break; - case 'B': - pb=BLUE; break; - - - }; //All other commands are process via APPCOMMAND_MESSAGES - if (pb==NA_NONE) return 0; - curevent=pb; - //PulseEvent(event); - SetEvent(event); - return 1; -} - -int RemoteWin::ReceiveButtonAP(UINT button) { - UCHAR pb=NA_NONE; - //should we use a translation table ? No APPCOMMAND iS DWORD! - switch (button) { //Processing VK_Messages - case APPCOMMAND_BROWSER_BACKWARD: - pb=BACK;break; - case APPCOMMAND_MEDIA_CHANNEL_DOWN: - pb=CHANNELDOWN;break; - case APPCOMMAND_MEDIA_CHANNEL_UP: - pb=CHANNELUP;break; - case APPCOMMAND_MEDIA_FAST_FORWARD: - pb=FORWARD;break; - case APPCOMMAND_VOLUME_MUTE: - pb=MUTE;break; - case APPCOMMAND_MEDIA_PAUSE: - pb=PAUSE;break; - case APPCOMMAND_MEDIA_PLAY: - pb=PLAY;break; - case APPCOMMAND_MEDIA_RECORD: - pb=RECORD;break; - case APPCOMMAND_MEDIA_PREVIOUSTRACK: - pb=SKIPBACK;break; - case APPCOMMAND_MEDIA_REWIND: - pb=REVERSE;break; - case APPCOMMAND_MEDIA_NEXTTRACK: - pb=SKIPFORWARD;break; - case APPCOMMAND_MEDIA_STOP: - pb=STOP;break; - case APPCOMMAND_VOLUME_DOWN: - pb=VOLUMEDOWN;break; - case APPCOMMAND_VOLUME_UP: - pb=VOLUMEUP;break; - case VOMP_YELLOW: - pb=YELLOW; break; - case VOMP_BLUE: - pb=BLUE;break; - case VOMP_RED: - pb=RED;break; - case VOMP_GREEN: - pb=GREEN;break; - case VOMP_ENTER: - pb=OK;break; - case VOMP_CANCEL: - pb=BACK;break; - case VOMP_UP: - pb=UP;break; - case VOMP_DOWN: - pb=DOWN;break; - case VOMP_LEFT: - pb=LEFT;break; - case VOMP_RIGHT: - pb=RIGHT;break; - }; - if (pb==NA_NONE) return 0; - curevent=pb; - //PulseEvent(event); - SetEvent(event); - return 1; -} - -int RemoteWin::ReceiveButtonRI(UINT button) { - UCHAR pb=NA_NONE; - //Raw Input - /* Note Codes above 0x29c are not listed in the specs on usb.org - therefore they are used by try, they might be device dependent - thus please supply codes of your remote control */ - switch (button) { //Processing VK_Messages - case 0x35c: //Green - pb=GREEN;break; - case 0x35b: //Red - pb=RED;break; - case 0x35d: //Yellow - pb=YELLOW;break; - case 0x35e: //Blue - pb=BLUE;break; - case 0x30d: //MCE Button, used for Menu - pb=MENU;break; - case 0x348: //Record Television - pb=RECORD;break; - case 0x28d: //Attach File Mmh, how should we assign this - pb=NA_NONE;break; - case 0x325: //Playback Televison - pb=PLAY;break; - case 0x324: //Playback DVD - pb=PLAY;break; - case 0x209: //Properties - case 0x35a: //Teletext? - pb=OK;break; - - - }; - if (pb==NA_NONE) return 0; - curevent=pb; - //PulseEvent(event); - SetEvent(event); - return 1; -} - -void RemoteWin::Signal() { - signal=true; - //PulseEvent(event); - SetEvent(event); -} - -void RemoteWin::SendPower() -{ - - curevent=POWER; - SetEvent(event); -} - +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "remotewin.h" +#include "vompreswin.h" + + +RemoteWin::RemoteWin() +{ + initted = 0; + curevent=NA_NONE; + signal=false; +} + +RemoteWin::~RemoteWin() +{ +} + +int RemoteWin::init(char* devName) +{ + if (initted) return 0; + initted = 1; + event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL); + + + return 1; +} + +int RemoteWin::shutdown() +{ + if (!initted) return 0; + CloseHandle(event); + initted = 0; + return 1; +} + +UCHAR RemoteWin::getButtonPress(int waitType) +{ + /* how = 0 - block + how = 1 - start new wait + how = 2 - continue wait + how = 3 - no wait + */ + DWORD wait; + + if (curevent!=NA_NONE) { + UCHAR temp=curevent; + curevent=NA_NONE; + return temp; + } + if (waitType==3) { + return NA_NONE; + } + if (waitType==0) { + wait=INFINITE; + } else { //We do not distingish between 2 and 3 + wait=1000; + + } + WaitForSingleObject(event,wait); + ResetEvent(event); + if (curevent==NA_NONE) { + if (signal) { + signal=false; + return NA_SIGNAL; //Since we have no signals on windows, we simulate this + } else { + return NA_NONE; + } + } + UCHAR temp2=curevent; + curevent=NA_NONE; + return temp2; + +} + +void RemoteWin::clearBuffer() +{ +} + +int RemoteWin::ReceiveButtonVK(UINT button) { + UCHAR pb=NA_NONE; + //should we use a translation table ? No APPCOMMAND iS DWORD! + switch (button) { //Processing VK_Messages + case VK_DOWN: + pb=DOWN; break; + case VK_RETURN: + case VK_SPACE: + pb=OK;break; + case VK_LEFT: + pb=LEFT;break; + case '9': + case VK_NUMPAD9: + pb=NINE;break; + case '8': + case VK_NUMPAD8: + pb=EIGHT;break; + case '7': + case VK_NUMPAD7: + pb=SEVEN;break; + case '6': + case VK_NUMPAD6: + pb=SIX;break; + case '5': + case VK_NUMPAD5: + pb=FIVE;break; + case '4': + case VK_NUMPAD4: + pb=FOUR;break; + case '3': + case VK_NUMPAD3: + pb=THREE;break; + case '2': + case VK_NUMPAD2: + pb=TWO;break; + case '1': + case VK_NUMPAD1: + pb=ONE;break; + case '0': + case VK_NUMPAD0: + pb=ZERO;break; + case VK_RIGHT: + pb=RIGHT;break; + case VK_UP: + pb=UP;break; + case VK_MULTIPLY: + pb=STAR;break; + case 'J'://j for JUMP TO instead of go to + pb=GO;break; + //case VK_ESCAPE: + // pb=POWER;break; + case VK_BACK: + pb=BACK;break; + case 'M': + pb=MENU;break; + case 'R': + pb=RED;break; + case 'G': + pb=GREEN;break; + case 'Y': + pb=YELLOW;break; + case 'B': + pb=BLUE; break; + + + }; //All other commands are process via APPCOMMAND_MESSAGES + if (pb==NA_NONE) return 0; + curevent=pb; + //PulseEvent(event); + SetEvent(event); + return 1; +} + +int RemoteWin::ReceiveButtonAP(UINT button) { + UCHAR pb=NA_NONE; + //should we use a translation table ? No APPCOMMAND iS DWORD! + switch (button) { //Processing VK_Messages + case APPCOMMAND_BROWSER_BACKWARD: + pb=BACK;break; + case APPCOMMAND_MEDIA_CHANNEL_DOWN: + pb=CHANNELDOWN;break; + case APPCOMMAND_MEDIA_CHANNEL_UP: + pb=CHANNELUP;break; + case APPCOMMAND_MEDIA_FAST_FORWARD: + pb=FORWARD;break; + case APPCOMMAND_VOLUME_MUTE: + pb=MUTE;break; + case APPCOMMAND_MEDIA_PAUSE: + pb=PAUSE;break; + case APPCOMMAND_MEDIA_PLAY: + pb=PLAY;break; + case APPCOMMAND_MEDIA_RECORD: + pb=RECORD;break; + case APPCOMMAND_MEDIA_PREVIOUSTRACK: + pb=SKIPBACK;break; + case APPCOMMAND_MEDIA_REWIND: + pb=REVERSE;break; + case APPCOMMAND_MEDIA_NEXTTRACK: + pb=SKIPFORWARD;break; + case APPCOMMAND_MEDIA_STOP: + pb=STOP;break; + case APPCOMMAND_VOLUME_DOWN: + pb=VOLUMEDOWN;break; + case APPCOMMAND_VOLUME_UP: + pb=VOLUMEUP;break; + case VOMP_YELLOW: + pb=YELLOW; break; + case VOMP_BLUE: + pb=BLUE;break; + case VOMP_RED: + pb=RED;break; + case VOMP_GREEN: + pb=GREEN;break; + case VOMP_ENTER: + pb=OK;break; + case VOMP_CANCEL: + pb=BACK;break; + case VOMP_UP: + pb=UP;break; + case VOMP_DOWN: + pb=DOWN;break; + case VOMP_LEFT: + pb=LEFT;break; + case VOMP_RIGHT: + pb=RIGHT;break; + }; + if (pb==NA_NONE) return 0; + curevent=pb; + //PulseEvent(event); + SetEvent(event); + return 1; +} + +int RemoteWin::ReceiveButtonRI(UINT button) { + UCHAR pb=NA_NONE; + //Raw Input + /* Note Codes above 0x29c are not listed in the specs on usb.org + therefore they are used by try, they might be device dependent + thus please supply codes of your remote control */ + switch (button) { //Processing VK_Messages + case 0x35c: //Green + pb=GREEN;break; + case 0x35b: //Red + pb=RED;break; + case 0x35d: //Yellow + pb=YELLOW;break; + case 0x35e: //Blue + pb=BLUE;break; + case 0x30d: //MCE Button, used for Menu + pb=MENU;break; + case 0x348: //Record Television + pb=RECORD;break; + case 0x28d: //Attach File Mmh, how should we assign this + pb=NA_NONE;break; + case 0x325: //Playback Televison + pb=PLAY;break; + case 0x324: //Playback DVD + pb=PLAY;break; + case 0x209: //Properties + case 0x35a: //Teletext? + pb=OK;break; + + + }; + if (pb==NA_NONE) return 0; + curevent=pb; + //PulseEvent(event); + SetEvent(event); + return 1; +} + +void RemoteWin::Signal() { + signal=true; + //PulseEvent(event); + SetEvent(event); +} + +void RemoteWin::SendPower() +{ + + curevent=POWER; + SetEvent(event); +} + diff --git a/remotewin.h b/remotewin.h index 7fe280f..d203794 100644 --- a/remotewin.h +++ b/remotewin.h @@ -1,61 +1,61 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef REMOTEWIN_H -#define REMOTEWIN_H - -#include - -#include "defines.h" -#include "log.h" -#include "remote.h" - -#define _WIN32_WINNT 0x501 -#include -#include - - - -class RemoteWin : public Remote -{ - public: - RemoteWin(); - ~RemoteWin(); - - int init(char *devName); - int shutdown(); - int getDevice(); - UCHAR getButtonPress(int how); - void clearBuffer(); - void Signal(); - int ReceiveButtonVK(UINT button);//Windows Message from WND_PROC - int ReceiveButtonAP(UINT button); - int ReceiveButtonRI(UINT button); - void SendPower(); - - private: - int initted; - bool signal; - UCHAR curevent; - HANDLE event; -}; - -#endif - +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef REMOTEWIN_H +#define REMOTEWIN_H + +#include + +#include "defines.h" +#include "log.h" +#include "remote.h" + +#define _WIN32_WINNT 0x501 +#include +#include + + + +class RemoteWin : public Remote +{ + public: + RemoteWin(); + ~RemoteWin(); + + int init(char *devName); + int shutdown(); + int getDevice(); + UCHAR getButtonPress(int how); + void clearBuffer(); + void Signal(); + int ReceiveButtonVK(UINT button);//Windows Message from WND_PROC + int ReceiveButtonAP(UINT button); + int ReceiveButtonRI(UINT button); + void SendPower(); + + private: + int initted; + bool signal; + UCHAR curevent; + HANDLE event; +}; + +#endif + diff --git a/surfacewin.cc b/surfacewin.cc index e6b486a..bec6c0e 100644 --- a/surfacewin.cc +++ b/surfacewin.cc @@ -1,270 +1,270 @@ -/* - Copyright 2006 Marten Richter - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "surfacewin.h" -#include "osdwin.h" -#include - -SurfaceWin::SurfaceWin(int id) -: Surface(id) -{ - d3dtexture=NULL; - d3dsurface=NULL; - sheight=swidth=0; - event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL); -} - -SurfaceWin::~SurfaceWin() -{ - if (d3dsurface) d3dsurface->Release(); - if (d3dtexture) d3dtexture->Release(); - CloseHandle(event); -} - -int SurfaceWin::create(UINT width, UINT height) -{ - LPDIRECT3DDEVICE9 d3ddev=((OsdWin*)(Osd::getInstance()))->getD3dDev(); - while (true) { - if (screen==this) { - if (d3ddev->CreateTexture(1024,1024,0,0,D3DFMT_A8R8G8B8, - // Does every adapter with alpha blending support this? - D3DPOOL_DEFAULT,&d3dtexture ,NULL)!=D3D_OK) { - MILLISLEEP(50);//wait maybe next time it will work - continue; - } - if (d3dtexture->GetSurfaceLevel(0,&d3dsurface)!=D3D_OK) { - d3dtexture->Release(); - d3dtexture=NULL; - MILLISLEEP(50); - continue; - } - } else { - HRESULT hres; - if (hres=d3ddev->CreateOffscreenPlainSurface(width,height,D3DFMT_A8R8G8B8, - D3DPOOL_SYSTEMMEM,&d3dsurface,NULL)!=D3D_OK) { - MILLISLEEP(50);//wait maybe next time it will work - continue; - } - - } - sheight=height; - swidth=width; - /* If someone does high performance Animations on the OSD, we have to change the types - of surface in order to address these performance issues, if we have only very few updates - per second this would be fast enough !*/ - break; - } - SetEvent(event); - return 1; -} - -void SurfaceWin::display() -{ -} - -int SurfaceWin::fillblt(int x, int y, int width, int height, unsigned int c) -{ - WaitForSingleObject(event,INFINITE); //since this might be called before surface - //allocation we will wait in this case, hopefully without deadlocks - OsdWin* osd=((OsdWin*)(Osd::getInstance())); - - if (!d3dsurface) { - return 0; //why does this happen - } - - LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev(); - - if (screen==this) { - //This should not happen! - return 0; - - } else { - osd->BeginPainting(); - D3DLOCKED_RECT lockrect; - int cx,cy,cwidth,cheight; - cx=min(max(x,0),swidth-1); - cy=min(max(y,0),sheight-1); - cwidth=min(width,swidth-x); - cheight=min(height,sheight-y); - RECT rect={cx,cy,cwidth,cheight}; - - if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) { - return 0; - } - unsigned int line; - unsigned int column; - for (line=0;lineUnlockRect()!=D3D_OK) { - osd->EndPainting(); - return 0; - } - osd->EndPainting(); - } - - return 0; -} - -void SurfaceWin::drawPixel(int x, int y, unsigned int c) -{ - //FixMe: locking for every single Pixel will be painfully slow - WaitForSingleObject(event,INFINITE); //since this might be called before surface - //allocation we will wait in this case, hopefully without deadlocks - if (!d3dsurface) { - return; //why does this happen - } - OsdWin* osd=((OsdWin*)(Osd::getInstance())); - LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev(); - if (x>=swidth || y>=sheight) return; //do not draw outside the surface - if (screen==this) { - //This should not happen! - return ; - - } else { - osd->BeginPainting(); - D3DLOCKED_RECT lockrect; - RECT rect={x,y,x+1,y+1}; - if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) { - osd->EndPainting(); - return ; - } - unsigned int*row=(unsigned int*)(((char*)lockrect.pBits)); - row[0]=c; - if (d3dsurface->UnlockRect()!=D3D_OK) { - osd->EndPainting(); - return ; - } - osd->EndPainting(); - } - -} - -void SurfaceWin::drawHorzLine(int x1, int x2, int y, unsigned int c) -{ - fillblt(x1, y, x2-x1, 1, c); -} - -void SurfaceWin::drawVertLine(int x, int y1, int y2, unsigned int c) -{ - fillblt(x, y1, 1, y2-y1, c); -} - -int SurfaceWin::updateToScreen(int sx, int sy, int w, int h, int dx, int dy) // FIXME new, replace others with this FIXME -{ - WaitForSingleObject(event,INFINITE); //since this might be called before surface - //allocation we will wait in this case, hopefully without deadlocks - if (!d3dsurface) { - return 0; //why does this happen - } - OsdWin* osd=((OsdWin*)(Osd::getInstance())); - LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev(); - LPDIRECT3DSURFACE9 screensurface=((SurfaceWin*)screen)->getD3dsurface(); - if (!screensurface) return 0; - RECT sourcerect={sx,sy,sx+w,sy+h}; - POINT destpoint={dx,dy}; - osd->BeginPainting(); - if (d3ddev->UpdateSurface(d3dsurface,&sourcerect,screensurface,&destpoint)!=D3D_OK) { - Log::getInstance()->log("Surface", Log::DEBUG, "Could not update to Screen!"); - osd->EndPainting(); - return 0; - } - osd->EndPainting(); - return 0; -} - -int SurfaceWin::blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy) -{ - //I don't see code using this function, so I skip it, since it is a MVP specific interface - return 0; -} - -void SurfaceWin::screenShot(char* fileName) -{ - //Isn't this for debugging only, so I won't implement it yet -} - -void SurfaceWin::readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b) -{ - //Isn't this for debugging only, so I won't implement it yet -} -void SurfaceWin::ReleaseSurface() -{ - ResetEvent(event); - LPDIRECT3DSURFACE9 temp_surf=d3dsurface; - LPDIRECT3DTEXTURE9 temp_text=d3dtexture; - d3dsurface=NULL; - d3dtexture=NULL; - sheight=swidth=0; - if (temp_surf) temp_surf->Release(); - if (temp_text) temp_text->Release(); -} - -void SurfaceWin::drawJpeg(char *fileName,DWORD x, DWORD y,DWORD *width, DWORD *height){ - WaitForSingleObject(event,INFINITE); //since this might be called before surface - //allocation we will wait in this case, hopefully without deadlocks - if (!d3dsurface) { - return ; //why does this happen - } - OsdWin* osd=((OsdWin*)(Osd::getInstance())); - - - D3DXIMAGE_INFO image_inf; - osd->BeginPainting(); -// D3DXGetImageInfoFromFile(fileName,&image_inf); - D3DXGetImageInfoFromResource(NULL,fileName,&image_inf); - RECT dest_rec={x,y,x+image_inf.Width, - y+image_inf.Height}; -/* if (D3DXLoadSurfaceFromFile( - d3dsurface, - NULL, - &dest_rec, - fileName, - NULL, - D3DX_FILTER_NONE, - 0, - &image_inf)!=D3D_OK) { - Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!"); - - }*/ - if (D3DXLoadSurfaceFromResource( - d3dsurface, - NULL, - &dest_rec, - NULL, - fileName, - NULL, - D3DX_FILTER_NONE, - 0, - &image_inf)!=D3D_OK) { - Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!"); - - } - osd->EndPainting(); - *width=image_inf.Width; - *height=image_inf.Height; - -} - - +/* + Copyright 2006 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "surfacewin.h" +#include "osdwin.h" +#include + +SurfaceWin::SurfaceWin(int id) +: Surface(id) +{ + d3dtexture=NULL; + d3dsurface=NULL; + sheight=swidth=0; + event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL); +} + +SurfaceWin::~SurfaceWin() +{ + if (d3dsurface) d3dsurface->Release(); + if (d3dtexture) d3dtexture->Release(); + CloseHandle(event); +} + +int SurfaceWin::create(UINT width, UINT height) +{ + LPDIRECT3DDEVICE9 d3ddev=((OsdWin*)(Osd::getInstance()))->getD3dDev(); + while (true) { + if (screen==this) { + if (d3ddev->CreateTexture(1024,1024,0,0,D3DFMT_A8R8G8B8, + // Does every adapter with alpha blending support this? + D3DPOOL_DEFAULT,&d3dtexture ,NULL)!=D3D_OK) { + MILLISLEEP(50);//wait maybe next time it will work + continue; + } + if (d3dtexture->GetSurfaceLevel(0,&d3dsurface)!=D3D_OK) { + d3dtexture->Release(); + d3dtexture=NULL; + MILLISLEEP(50); + continue; + } + } else { + HRESULT hres; + if (hres=d3ddev->CreateOffscreenPlainSurface(width,height,D3DFMT_A8R8G8B8, + D3DPOOL_SYSTEMMEM,&d3dsurface,NULL)!=D3D_OK) { + MILLISLEEP(50);//wait maybe next time it will work + continue; + } + + } + sheight=height; + swidth=width; + /* If someone does high performance Animations on the OSD, we have to change the types + of surface in order to address these performance issues, if we have only very few updates + per second this would be fast enough !*/ + break; + } + SetEvent(event); + return 1; +} + +void SurfaceWin::display() +{ +} + +int SurfaceWin::fillblt(int x, int y, int width, int height, unsigned int c) +{ + WaitForSingleObject(event,INFINITE); //since this might be called before surface + //allocation we will wait in this case, hopefully without deadlocks + OsdWin* osd=((OsdWin*)(Osd::getInstance())); + + if (!d3dsurface) { + return 0; //why does this happen + } + + LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev(); + + if (screen==this) { + //This should not happen! + return 0; + + } else { + osd->BeginPainting(); + D3DLOCKED_RECT lockrect; + int cx,cy,cwidth,cheight; + cx=min(max(x,0),swidth-1); + cy=min(max(y,0),sheight-1); + cwidth=min(width,swidth-x); + cheight=min(height,sheight-y); + RECT rect={cx,cy,cwidth,cheight}; + + if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) { + return 0; + } + unsigned int line; + unsigned int column; + for (line=0;lineUnlockRect()!=D3D_OK) { + osd->EndPainting(); + return 0; + } + osd->EndPainting(); + } + + return 0; +} + +void SurfaceWin::drawPixel(int x, int y, unsigned int c) +{ + //FixMe: locking for every single Pixel will be painfully slow + WaitForSingleObject(event,INFINITE); //since this might be called before surface + //allocation we will wait in this case, hopefully without deadlocks + if (!d3dsurface) { + return; //why does this happen + } + OsdWin* osd=((OsdWin*)(Osd::getInstance())); + LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev(); + if (x>=swidth || y>=sheight) return; //do not draw outside the surface + if (screen==this) { + //This should not happen! + return ; + + } else { + osd->BeginPainting(); + D3DLOCKED_RECT lockrect; + RECT rect={x,y,x+1,y+1}; + if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) { + osd->EndPainting(); + return ; + } + unsigned int*row=(unsigned int*)(((char*)lockrect.pBits)); + row[0]=c; + if (d3dsurface->UnlockRect()!=D3D_OK) { + osd->EndPainting(); + return ; + } + osd->EndPainting(); + } + +} + +void SurfaceWin::drawHorzLine(int x1, int x2, int y, unsigned int c) +{ + fillblt(x1, y, x2-x1, 1, c); +} + +void SurfaceWin::drawVertLine(int x, int y1, int y2, unsigned int c) +{ + fillblt(x, y1, 1, y2-y1, c); +} + +int SurfaceWin::updateToScreen(int sx, int sy, int w, int h, int dx, int dy) // FIXME new, replace others with this FIXME +{ + WaitForSingleObject(event,INFINITE); //since this might be called before surface + //allocation we will wait in this case, hopefully without deadlocks + if (!d3dsurface) { + return 0; //why does this happen + } + OsdWin* osd=((OsdWin*)(Osd::getInstance())); + LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev(); + LPDIRECT3DSURFACE9 screensurface=((SurfaceWin*)screen)->getD3dsurface(); + if (!screensurface) return 0; + RECT sourcerect={sx,sy,sx+w,sy+h}; + POINT destpoint={dx,dy}; + osd->BeginPainting(); + if (d3ddev->UpdateSurface(d3dsurface,&sourcerect,screensurface,&destpoint)!=D3D_OK) { + Log::getInstance()->log("Surface", Log::DEBUG, "Could not update to Screen!"); + osd->EndPainting(); + return 0; + } + osd->EndPainting(); + return 0; +} + +int SurfaceWin::blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy) +{ + //I don't see code using this function, so I skip it, since it is a MVP specific interface + return 0; +} + +void SurfaceWin::screenShot(char* fileName) +{ + //Isn't this for debugging only, so I won't implement it yet +} + +void SurfaceWin::readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b) +{ + //Isn't this for debugging only, so I won't implement it yet +} +void SurfaceWin::ReleaseSurface() +{ + ResetEvent(event); + LPDIRECT3DSURFACE9 temp_surf=d3dsurface; + LPDIRECT3DTEXTURE9 temp_text=d3dtexture; + d3dsurface=NULL; + d3dtexture=NULL; + sheight=swidth=0; + if (temp_surf) temp_surf->Release(); + if (temp_text) temp_text->Release(); +} + +void SurfaceWin::drawJpeg(char *fileName,DWORD x, DWORD y,DWORD *width, DWORD *height){ + WaitForSingleObject(event,INFINITE); //since this might be called before surface + //allocation we will wait in this case, hopefully without deadlocks + if (!d3dsurface) { + return ; //why does this happen + } + OsdWin* osd=((OsdWin*)(Osd::getInstance())); + + + D3DXIMAGE_INFO image_inf; + osd->BeginPainting(); +// D3DXGetImageInfoFromFile(fileName,&image_inf); + D3DXGetImageInfoFromResource(NULL,fileName,&image_inf); + RECT dest_rec={x,y,x+image_inf.Width, + y+image_inf.Height}; +/* if (D3DXLoadSurfaceFromFile( + d3dsurface, + NULL, + &dest_rec, + fileName, + NULL, + D3DX_FILTER_NONE, + 0, + &image_inf)!=D3D_OK) { + Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!"); + + }*/ + if (D3DXLoadSurfaceFromResource( + d3dsurface, + NULL, + &dest_rec, + NULL, + fileName, + NULL, + D3DX_FILTER_NONE, + 0, + &image_inf)!=D3D_OK) { + Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!"); + + } + osd->EndPainting(); + *width=image_inf.Width; + *height=image_inf.Height; + +} + + diff --git a/threadwin.cc b/threadwin.cc index 4d1daf7..e0c24c4 100644 --- a/threadwin.cc +++ b/threadwin.cc @@ -1,132 +1,132 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "threadwin.h" - -// Undeclared functions, only for use in this file to start the thread -DWORD WINAPI threadInternalStart(void *arg) -{ - Thread *t = (Thread *)arg; - t->threadInternalStart2(); - return 0; -} - -int ThreadWin::threadStart() -{ - threadCond = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL); - if (threadCond == NULL) return 0; - threadCondMutex = CreateMutex(NULL,FALSE,NULL); - if (threadCondMutex == NULL) - { - CloseHandle(threadCond); - return 0; - } - - threadActive = 1; - DWORD threadId; - pthread = CreateThread(NULL, 0, threadInternalStart, (void*)this,0, &threadId); - if (pthread == NULL) - { - CloseHandle(threadCond); - CloseHandle(threadCondMutex); - return 0; - } - return 1; -} - -void ThreadWin::threadStop() -{ - threadActive = 0; - // Signal thread here in case it's waiting - threadSignal(); - WaitForSingleObject(pthread, INFINITE); - this->threadPostStopCleanup(); -} - -void ThreadWin::threadCancel() -{ - threadActive = 0; - //TerminateThread(pthread, 0); - threadSignalNoLock(); - WaitForSingleObject(pthread, INFINITE); - this->threadPostStopCleanup(); -} - -void ThreadWin::threadCheckExit() -{ - if (!threadActive) ExitThread(NULL); -} - -void ThreadWin::threadLock() -{ - WaitForSingleObject(threadCondMutex, INFINITE); -} - -void ThreadWin::threadUnlock() -{ - ReleaseMutex(threadCondMutex); -} - -void ThreadWin::threadSignal() -{ - WaitForSingleObject(threadCondMutex, INFINITE); - // PulseEvent(threadCond); - SetEvent(threadCond); - ReleaseMutex(threadCondMutex); -} - -void ThreadWin::threadSignalNoLock() -{ -// PulseEvent(threadCond); - SetEvent(threadCond); -} - -void ThreadWin::threadWaitForSignal() -{ - threadUnlock(); - WaitForSingleObject(threadCond,INFINITE); - ResetEvent(threadCond); - threadLock(); -} - -void ThreadWin::threadWaitForSignalTimed(struct timespec* ts) -{ - threadUnlock(); - HANDLE handles[2] ={threadCond, NULL}; - LARGE_INTEGER duration; - duration.QuadPart=(((LONGLONG)ts->tv_sec)*1000LL*1000LL*10LL+((LONGLONG)ts->tv_nsec)/100LL)+WINDOWS_TIME_BASE_OFFSET; - SYSTEMTIME debug; - FILETIME debugfile; - GetSystemTime(&debug); - SystemTimeToFileTime(&debug,&debugfile); - - handles[1]=CreateWaitableTimer(NULL,TRUE,NULL); - SetWaitableTimer(handles[1], &duration, 0, NULL, NULL, 0); - WaitForMultipleObjects(2,handles,FALSE,INFINITE); - ResetEvent(threadCond); - CloseHandle(handles[1]); - threadLock(); -} - -void ThreadWin::threadSetKillable() -{ - //WIN32:Ignore or use a separate Event Object to simulate this -} - +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "threadwin.h" + +// Undeclared functions, only for use in this file to start the thread +DWORD WINAPI threadInternalStart(void *arg) +{ + Thread *t = (Thread *)arg; + t->threadInternalStart2(); + return 0; +} + +int ThreadWin::threadStart() +{ + threadCond = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL); + if (threadCond == NULL) return 0; + threadCondMutex = CreateMutex(NULL,FALSE,NULL); + if (threadCondMutex == NULL) + { + CloseHandle(threadCond); + return 0; + } + + threadActive = 1; + DWORD threadId; + pthread = CreateThread(NULL, 0, threadInternalStart, (void*)this,0, &threadId); + if (pthread == NULL) + { + CloseHandle(threadCond); + CloseHandle(threadCondMutex); + return 0; + } + return 1; +} + +void ThreadWin::threadStop() +{ + threadActive = 0; + // Signal thread here in case it's waiting + threadSignal(); + WaitForSingleObject(pthread, INFINITE); + this->threadPostStopCleanup(); +} + +void ThreadWin::threadCancel() +{ + threadActive = 0; + //TerminateThread(pthread, 0); + threadSignalNoLock(); + WaitForSingleObject(pthread, INFINITE); + this->threadPostStopCleanup(); +} + +void ThreadWin::threadCheckExit() +{ + if (!threadActive) ExitThread(NULL); +} + +void ThreadWin::threadLock() +{ + WaitForSingleObject(threadCondMutex, INFINITE); +} + +void ThreadWin::threadUnlock() +{ + ReleaseMutex(threadCondMutex); +} + +void ThreadWin::threadSignal() +{ + WaitForSingleObject(threadCondMutex, INFINITE); + // PulseEvent(threadCond); + SetEvent(threadCond); + ReleaseMutex(threadCondMutex); +} + +void ThreadWin::threadSignalNoLock() +{ +// PulseEvent(threadCond); + SetEvent(threadCond); +} + +void ThreadWin::threadWaitForSignal() +{ + threadUnlock(); + WaitForSingleObject(threadCond,INFINITE); + ResetEvent(threadCond); + threadLock(); +} + +void ThreadWin::threadWaitForSignalTimed(struct timespec* ts) +{ + threadUnlock(); + HANDLE handles[2] ={threadCond, NULL}; + LARGE_INTEGER duration; + duration.QuadPart=(((LONGLONG)ts->tv_sec)*1000LL*1000LL*10LL+((LONGLONG)ts->tv_nsec)/100LL)+WINDOWS_TIME_BASE_OFFSET; + SYSTEMTIME debug; + FILETIME debugfile; + GetSystemTime(&debug); + SystemTimeToFileTime(&debug,&debugfile); + + handles[1]=CreateWaitableTimer(NULL,TRUE,NULL); + SetWaitableTimer(handles[1], &duration, 0, NULL, NULL, 0); + WaitForMultipleObjects(2,handles,FALSE,INFINITE); + ResetEvent(threadCond); + CloseHandle(handles[1]); + threadLock(); +} + +void ThreadWin::threadSetKillable() +{ + //WIN32:Ignore or use a separate Event Object to simulate this +} + diff --git a/timers.cc b/timers.cc index 2980105..b6674df 100755 --- a/timers.cc +++ b/timers.cc @@ -1,361 +1,361 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "timers.h" - -Timers* Timers::instance = NULL; - -Timers::Timers() -{ - if (instance) return; - instance = this; - initted = false; -} - -Timers::~Timers() -{ - instance = NULL; -} - -Timers* Timers::getInstance() -{ - return instance; -} - -int Timers::init() -{ - if (initted) return 0; - initted = true; - logger = Log::getInstance(); - - threadLock(); // lock here, the thread loop will unlock and wait - //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 1"); - if (!threadStart()) - { - shutdown(); - return 0; - } - - return 1; -} - -int Timers::shutdown() -{ - if (!initted) return 0; - initted = false; - - logger->log("Timers", Log::DEBUG, "Timers shutdown start"); - - threadStop(); - - TimerList::iterator i; - UINT numTimers = timerList.size(); - while(numTimers) - { - i = timerList.begin(); - delete *i; - timerList.pop_front(); - --numTimers; - } - - logger->log("Timers", Log::DEBUG, "Timers shutdown end"); - - return 1; -} - -int Timers::setTimerT(TimerReceiver* client, int clientReference, long int requestedTime, long int requestedTimeNSEC) -{ - if (!initted) return 0; - - logger->log("Timers", Log::DEBUG, "Starting set timer 1"); - - //logger->log("Timers", Log::DEBUG, "Waiting for LOCK -TIMERS- MUTEX 2"); - threadLock(); - - // Check that this timer is not already in the list - TimerList::iterator i; - Timer* currentTimer = NULL; - for(i = timerList.begin(); i != timerList.end(); i++) - { - currentTimer = *i; - if ((currentTimer->client == client) && (currentTimer->clientReference == clientReference)) - { - // Overwrite an existing timer - currentTimer->requestedTime.tv_sec = requestedTime; - currentTimer->requestedTime.tv_nsec = requestedTimeNSEC; - resetThreadFlag = true; - threadSignalNoLock(); - - //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 2 (b)"); - threadUnlock(); - return 0; - } - } - - Timer* t = new Timer(); - t->client = client; - t->clientReference = clientReference; - t->requestedTime.tv_sec = requestedTime; - t->requestedTime.tv_nsec = requestedTimeNSEC; - - //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 2"); - timerList.push_back(t); - resetThreadFlag = true; - threadSignalNoLock(); - //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 2"); - threadUnlock(); - - logger->log("Timers", Log::DEBUG, "Timer set for %p ref %i", client, clientReference); - - return 1; -} - -int Timers::setTimerD(TimerReceiver* client, int clientReference, long int requestedSecs, long int requestedNSecs) -{ - struct timespec currentTime; - -#ifndef WIN32 - clock_gettime(CLOCK_REALTIME, ¤tTime); -#else - SYSTEMTIME systime; - __int64 filetime; - __int64 test; - GetSystemTime(&systime); - SystemTimeToFileTime(&systime,(FILETIME*)&filetime); - currentTime.tv_sec=(filetime-WINDOWS_TIME_BASE_OFFSET)/(10*1000*1000); - //#error "Hier gibt was zu tun!" - currentTime.tv_nsec=((filetime-WINDOWS_TIME_BASE_OFFSET)%(10*1000*1000))*100; -#endif - - long int requestedTime; - long int requestedTimeNSEC; - - requestedTime = currentTime.tv_sec + requestedSecs; - requestedTimeNSEC = currentTime.tv_nsec + requestedNSecs; - if (requestedTimeNSEC > 999999999) - { - ++requestedTime; - requestedTimeNSEC -= 1000000000; - logger->log("Timers", Log::DEBUG, "Second rollover - CHECK FIXME"); - } - - return setTimerT(client, clientReference, requestedTime, requestedTimeNSEC); -} - -int Timers::cancelTimer(TimerReceiver* client, int clientReference) -{ - if (!initted) return 0; - - logger->log("Timers", Log::DEBUG, "Starting cancel timer %p %i, list size = %i", client, clientReference, timerList.size()); - - //logger->log("Timers", Log::DEBUG, "Waiting for LOCK -TIMERS- MUTEX 4"); - threadLock(); - //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 4"); - TimerList::iterator i; - Timer* currentTimer = NULL; - for(i = timerList.begin(); i != timerList.end(); i++) - { - currentTimer = *i; - //logger->log("Timers", Log::DEBUG, "I: %p %i : %p %i", client, clientReference, currentTimer->client, currentTimer->clientReference); - if ((currentTimer->client == client) && (currentTimer->clientReference == clientReference)) - { - timerList.erase(i); - logger->log("Timers", Log::DEBUG, "Removed timer for %p ref %i", client, clientReference); - break; - // At this point currentTimer is not in the list but might still be nextTimer in the thread - } - } - if (i == timerList.end()) - { - // no timer found - logger->log("Timers", Log::DEBUG, "No timer found in cancelTimer %p ref %i", client, clientReference); - //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 4"); - threadUnlock(); - return 0; - } - - resetThreadFlag = true; - threadSignalNoLock(); - //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 4"); - threadUnlock(); - - - return 1; -} - -void Timers::threadMethod() -{ - struct timespec nextTime; - Timer* nextTimer = NULL; - resetThreadFlag = true; - - // locked here - - while(1) - { - if (resetThreadFlag) - { - resetThreadFlag = false; - - // Work out the next Timer - - nextTime.tv_sec = 0; - nextTime.tv_nsec = 0; - nextTimer = NULL; - - TimerList::iterator i; - Timer* currentTimer = NULL; - for(i = timerList.begin(); i != timerList.end(); i++) - { - currentTimer = *i; - if (!nextTimer) - { - nextTime.tv_sec = currentTimer->requestedTime.tv_sec; - nextTime.tv_nsec = currentTimer->requestedTime.tv_nsec; - nextTimer = currentTimer; - } - else - { - if (currentTimer->requestedTime.tv_sec < nextTime.tv_sec) - { - nextTime.tv_sec = currentTimer->requestedTime.tv_sec; - nextTime.tv_nsec = currentTimer->requestedTime.tv_nsec; - nextTimer = currentTimer; - } - else if (currentTimer->requestedTime.tv_sec == nextTime.tv_sec) - { - if (currentTimer->requestedTime.tv_nsec < nextTime.tv_nsec) - { - nextTime.tv_sec = currentTimer->requestedTime.tv_sec; - nextTime.tv_nsec = currentTimer->requestedTime.tv_nsec; - nextTimer = currentTimer; - } - } - } - } - } - - if (nextTimer) - { -//## logger->log("Timers", Log::DEBUG, "List size: %i. nextTimerClient: %p/%i. nextTime.tv_sec: %li. nextTime.tv_nsec: %li", timerList.size(), nextTimer->client, nextTimer->clientReference, nextTime.tv_sec, nextTime.tv_nsec); - - - //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX (1)"); - threadWaitForSignalTimed(&nextTime); - //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 5"); - - // unlocks in the wait - } - else - { - //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX (2)"); - threadWaitForSignal(); - //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 6"); - // unlocks in the wait - } - - // ok. we have been signalled or the time has run out - // This only gets signalled if it is to reset or die - - // First check for die.. - threadCheckExit(); // exiting thread with mutex locked - - // Check for reset.. - // This can be caused by an addition or deletion to the list - if (resetThreadFlag || (nextTimer == NULL)) continue; - - // timer ran out - - Log::getInstance()->log("Timers", Log::DEBUG, "Timer firing for client %p ref %i", nextTimer->client, nextTimer->clientReference); - - // send this timer to the timer receiver, via the command message queue - // so that the gui mutex is locked when it happens - - Message* m = new Message(); // Timer call, must be injected into master mutex (this is generated outside the mutex) - m->from = this; - m->to = nextTimer->client; - m->message = Message::TIMER; - m->parameter = nextTimer->clientReference; - - if (!Command::getInstance()->postMessageIfNotBusy(m)) - { - // GUI mutex was locked - // abort this timer delivery - it might be trying to be deleted! - delete m; - - // now unlock the timers mutex for a fraction of a second - // in case the gui thread is waiting on the timers mutex - threadUnlock(); - //logger->log("Timers", Log::DEBUG, "un-LOCKED -TIMERS- MUTEX (3)"); - //printf("\n\n\n WOOOOO \n\n\n The anti deadlock code is working!!! \n\n\n"); - MILLISLEEP(20); // 10ms - too long? too short? - //logger->log("Timers", Log::DEBUG, "Waiting for LOCK -TIMERS- MUTEX 7"); - threadLock(); - //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 7"); - resetThreadFlag = true; - } - else - { - // timer was delivered - timerList.remove(nextTimer); - delete nextTimer; - nextTimer = NULL; - resetThreadFlag = true; - } - } -} - -/* - -Avoiding deadlock using the timer class... - -Situation: - -timer condwait finishes -timers is about to fire a timer -timers locks timers-mutex - - user presses a button - command locks gui-mutex - -timers tries to get gui-mutex - - view receives button - view wants to delete itself - view tries to deletetimer - goes into delete timer - waits on timers mutex - -- deadlock - - -Solution: - -timers tries to get gui mutex -if mutex is locked already abort -unlock timers mutex -wait a fraction of time -(allow other thread to lock timers mutex) -lock timers mutex -set reset flag to recalculate -- if timer has been cancelled next timer will be calced -- if timer has not been cancelled it will be called next - -*/ +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "timers.h" + +Timers* Timers::instance = NULL; + +Timers::Timers() +{ + if (instance) return; + instance = this; + initted = false; +} + +Timers::~Timers() +{ + instance = NULL; +} + +Timers* Timers::getInstance() +{ + return instance; +} + +int Timers::init() +{ + if (initted) return 0; + initted = true; + logger = Log::getInstance(); + + threadLock(); // lock here, the thread loop will unlock and wait + //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 1"); + if (!threadStart()) + { + shutdown(); + return 0; + } + + return 1; +} + +int Timers::shutdown() +{ + if (!initted) return 0; + initted = false; + + logger->log("Timers", Log::DEBUG, "Timers shutdown start"); + + threadStop(); + + TimerList::iterator i; + UINT numTimers = timerList.size(); + while(numTimers) + { + i = timerList.begin(); + delete *i; + timerList.pop_front(); + --numTimers; + } + + logger->log("Timers", Log::DEBUG, "Timers shutdown end"); + + return 1; +} + +int Timers::setTimerT(TimerReceiver* client, int clientReference, long int requestedTime, long int requestedTimeNSEC) +{ + if (!initted) return 0; + + logger->log("Timers", Log::DEBUG, "Starting set timer 1"); + + //logger->log("Timers", Log::DEBUG, "Waiting for LOCK -TIMERS- MUTEX 2"); + threadLock(); + + // Check that this timer is not already in the list + TimerList::iterator i; + Timer* currentTimer = NULL; + for(i = timerList.begin(); i != timerList.end(); i++) + { + currentTimer = *i; + if ((currentTimer->client == client) && (currentTimer->clientReference == clientReference)) + { + // Overwrite an existing timer + currentTimer->requestedTime.tv_sec = requestedTime; + currentTimer->requestedTime.tv_nsec = requestedTimeNSEC; + resetThreadFlag = true; + threadSignalNoLock(); + + //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 2 (b)"); + threadUnlock(); + return 0; + } + } + + Timer* t = new Timer(); + t->client = client; + t->clientReference = clientReference; + t->requestedTime.tv_sec = requestedTime; + t->requestedTime.tv_nsec = requestedTimeNSEC; + + //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 2"); + timerList.push_back(t); + resetThreadFlag = true; + threadSignalNoLock(); + //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 2"); + threadUnlock(); + + logger->log("Timers", Log::DEBUG, "Timer set for %p ref %i", client, clientReference); + + return 1; +} + +int Timers::setTimerD(TimerReceiver* client, int clientReference, long int requestedSecs, long int requestedNSecs) +{ + struct timespec currentTime; + +#ifndef WIN32 + clock_gettime(CLOCK_REALTIME, ¤tTime); +#else + SYSTEMTIME systime; + __int64 filetime; + __int64 test; + GetSystemTime(&systime); + SystemTimeToFileTime(&systime,(FILETIME*)&filetime); + currentTime.tv_sec=(filetime-WINDOWS_TIME_BASE_OFFSET)/(10*1000*1000); + //#error "Hier gibt was zu tun!" + currentTime.tv_nsec=((filetime-WINDOWS_TIME_BASE_OFFSET)%(10*1000*1000))*100; +#endif + + long int requestedTime; + long int requestedTimeNSEC; + + requestedTime = currentTime.tv_sec + requestedSecs; + requestedTimeNSEC = currentTime.tv_nsec + requestedNSecs; + if (requestedTimeNSEC > 999999999) + { + ++requestedTime; + requestedTimeNSEC -= 1000000000; + logger->log("Timers", Log::DEBUG, "Second rollover - CHECK FIXME"); + } + + return setTimerT(client, clientReference, requestedTime, requestedTimeNSEC); +} + +int Timers::cancelTimer(TimerReceiver* client, int clientReference) +{ + if (!initted) return 0; + + logger->log("Timers", Log::DEBUG, "Starting cancel timer %p %i, list size = %i", client, clientReference, timerList.size()); + + //logger->log("Timers", Log::DEBUG, "Waiting for LOCK -TIMERS- MUTEX 4"); + threadLock(); + //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 4"); + TimerList::iterator i; + Timer* currentTimer = NULL; + for(i = timerList.begin(); i != timerList.end(); i++) + { + currentTimer = *i; + //logger->log("Timers", Log::DEBUG, "I: %p %i : %p %i", client, clientReference, currentTimer->client, currentTimer->clientReference); + if ((currentTimer->client == client) && (currentTimer->clientReference == clientReference)) + { + timerList.erase(i); + logger->log("Timers", Log::DEBUG, "Removed timer for %p ref %i", client, clientReference); + break; + // At this point currentTimer is not in the list but might still be nextTimer in the thread + } + } + if (i == timerList.end()) + { + // no timer found + logger->log("Timers", Log::DEBUG, "No timer found in cancelTimer %p ref %i", client, clientReference); + //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 4"); + threadUnlock(); + return 0; + } + + resetThreadFlag = true; + threadSignalNoLock(); + //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 4"); + threadUnlock(); + + + return 1; +} + +void Timers::threadMethod() +{ + struct timespec nextTime; + Timer* nextTimer = NULL; + resetThreadFlag = true; + + // locked here + + while(1) + { + if (resetThreadFlag) + { + resetThreadFlag = false; + + // Work out the next Timer + + nextTime.tv_sec = 0; + nextTime.tv_nsec = 0; + nextTimer = NULL; + + TimerList::iterator i; + Timer* currentTimer = NULL; + for(i = timerList.begin(); i != timerList.end(); i++) + { + currentTimer = *i; + if (!nextTimer) + { + nextTime.tv_sec = currentTimer->requestedTime.tv_sec; + nextTime.tv_nsec = currentTimer->requestedTime.tv_nsec; + nextTimer = currentTimer; + } + else + { + if (currentTimer->requestedTime.tv_sec < nextTime.tv_sec) + { + nextTime.tv_sec = currentTimer->requestedTime.tv_sec; + nextTime.tv_nsec = currentTimer->requestedTime.tv_nsec; + nextTimer = currentTimer; + } + else if (currentTimer->requestedTime.tv_sec == nextTime.tv_sec) + { + if (currentTimer->requestedTime.tv_nsec < nextTime.tv_nsec) + { + nextTime.tv_sec = currentTimer->requestedTime.tv_sec; + nextTime.tv_nsec = currentTimer->requestedTime.tv_nsec; + nextTimer = currentTimer; + } + } + } + } + } + + if (nextTimer) + { +//## logger->log("Timers", Log::DEBUG, "List size: %i. nextTimerClient: %p/%i. nextTime.tv_sec: %li. nextTime.tv_nsec: %li", timerList.size(), nextTimer->client, nextTimer->clientReference, nextTime.tv_sec, nextTime.tv_nsec); + + + //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX (1)"); + threadWaitForSignalTimed(&nextTime); + //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 5"); + + // unlocks in the wait + } + else + { + //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX (2)"); + threadWaitForSignal(); + //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 6"); + // unlocks in the wait + } + + // ok. we have been signalled or the time has run out + // This only gets signalled if it is to reset or die + + // First check for die.. + threadCheckExit(); // exiting thread with mutex locked + + // Check for reset.. + // This can be caused by an addition or deletion to the list + if (resetThreadFlag || (nextTimer == NULL)) continue; + + // timer ran out + + Log::getInstance()->log("Timers", Log::DEBUG, "Timer firing for client %p ref %i", nextTimer->client, nextTimer->clientReference); + + // send this timer to the timer receiver, via the command message queue + // so that the gui mutex is locked when it happens + + Message* m = new Message(); // Timer call, must be injected into master mutex (this is generated outside the mutex) + m->from = this; + m->to = nextTimer->client; + m->message = Message::TIMER; + m->parameter = nextTimer->clientReference; + + if (!Command::getInstance()->postMessageIfNotBusy(m)) + { + // GUI mutex was locked + // abort this timer delivery - it might be trying to be deleted! + delete m; + + // now unlock the timers mutex for a fraction of a second + // in case the gui thread is waiting on the timers mutex + threadUnlock(); + //logger->log("Timers", Log::DEBUG, "un-LOCKED -TIMERS- MUTEX (3)"); + //printf("\n\n\n WOOOOO \n\n\n The anti deadlock code is working!!! \n\n\n"); + MILLISLEEP(20); // 10ms - too long? too short? + //logger->log("Timers", Log::DEBUG, "Waiting for LOCK -TIMERS- MUTEX 7"); + threadLock(); + //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 7"); + resetThreadFlag = true; + } + else + { + // timer was delivered + timerList.remove(nextTimer); + delete nextTimer; + nextTimer = NULL; + resetThreadFlag = true; + } + } +} + +/* + +Avoiding deadlock using the timer class... + +Situation: + +timer condwait finishes +timers is about to fire a timer +timers locks timers-mutex + + user presses a button + command locks gui-mutex + +timers tries to get gui-mutex + + view receives button + view wants to delete itself + view tries to deletetimer + goes into delete timer + waits on timers mutex + +- deadlock + + +Solution: + +timers tries to get gui mutex +if mutex is locked already abort +unlock timers mutex +wait a fraction of time +(allow other thread to lock timers mutex) +lock timers mutex +set reset flag to recalculate +- if timer has been cancelled next timer will be calced +- if timer has not been cancelled it will be called next + +*/ diff --git a/vaudioselector.cc b/vaudioselector.cc index a310df0..a277d8b 100644 --- a/vaudioselector.cc +++ b/vaudioselector.cc @@ -1,231 +1,231 @@ -/* - Copyright 2006 Chris Tallon, Marten Richter - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "vaudioselector.h" - -VAudioSelector::VAudioSelector(void* tparent, bool* availableAudioChannels, int currentAudioChannel, RecInfo* recInfo) -{ - Log::getInstance()->log("VAS", Log::DEBUG, "%i", currentAudioChannel); - - parent = tparent; - - create(200, 120); - -// setTitleText(tr("Audio")); -// setTitleBarOn(1); -// setTitleBarColour(Colour::TITLEBARBACKGROUND); - - sl.setSurface(surface); - sl.setSurfaceOffset(40, 30); - sl.setDimensions(area.w - 45, area.h - 30); - - // Load data from availableAudioChannels, currentAudioChannel and recInfo - - int i; - - for (i = 0; i < PES_AUDIO_MAXCHANNELS; i++) - { - if (availableAudioChannels[i]) - { - AudioChannel* ac = new AudioChannel(); - ac->type = 0; - ac->name = NULL; - ac->pestype = PES_AUDIO_START + i; - acl.push_back(ac); - } - } - - unsigned char numchan_recinfo = recInfo->numComponents; - unsigned char numchan_siz = acl.size(); - int mp_audcounter = 0; - int ac3_counter = 0; - int ac3_offset = 0; - - for (i = 0; i < numchan_siz; i++) - { - AudioChannel* ac = acl[i]; - if (ac) - { - if (ac->type==0) - { - ac3_offset++; - } - } - } - - unsigned char type; - char* lang; - char* description; - int type_int; - - for (i = 0; i < numchan_recinfo; i++) - { - if (recInfo->streams[i] != 2) continue; //not an audio component - type = recInfo->types[i]; - lang = recInfo->languages[i]; - description = recInfo->descriptions[i]; - AudioChannel* ac = NULL; - type_int = 0; - - switch (type) - { - case 1: //mpaudio mono - case 3: //mpaudio stereo - if (mp_audcounter < numchan_siz) ac = acl[mp_audcounter]; - type_int = 0; - break; - case 5: //ac3 - if (ac3_counter + ac3_offset < numchan_siz) ac = acl[ac3_counter + ac3_offset]; - type_int = 1; - break; - } - - if (ac) - { - if (ac->type == type_int) - { - if (description && (strlen(description) > 0)) - { - ac->name = new char[strlen(description)+1]; - strcpy(ac->name, description); - } - else if (lang && (strlen(lang) > 0)) - { - ac->name = new char[strlen(lang)+1]; - strcpy(ac->name, lang); - } - } - } - - switch (type_int) - { - case 0: //mpaudio - mp_audcounter++; - break; - case 1: //ac3 - ac3_counter++; - break; - } - } - - // Now do display - - char tempString[300]; - int audioChannelListSize = acl.size(); - - if (audioChannelListSize) - { - for(i = 0; i < audioChannelListSize; i++) - { - AudioChannel* ac = acl[i]; - - if (ac->name) - { - sl.addOption(ac->name, (ULONG)ac, (ac->pestype == currentAudioChannel)); - } - else - { - SNPRINTF(tempString, 299, "%lu", (ULONG)(ac->pestype - PES_AUDIO_START)); - sl.addOption(tempString, (ULONG)ac, (ac->pestype == currentAudioChannel)); - } - } - } - else - { - sl.addOption(tr("No audio channel data available"), 0, 1); - } -} - -VAudioSelector::~VAudioSelector() -{ - int audioChannelListSize = acl.size(); - for(int i = 0; i < audioChannelListSize; i++) - { - delete acl[i]; - } - acl.clear(); - - sl.clear(); - - Message* m = new Message(); - m->from = this; - m->to = parent; - m->message = Message::CHILD_CLOSE; - Command::getInstance()->postMessageNoLock(m); -} - -void VAudioSelector::draw() -{ - View::draw(); - rectangle(0, 0, area.w, 30, Colour::TITLEBARBACKGROUND); - drawText(tr("Audio"), 45, 5, Colour::LIGHTTEXT); - - sl.setBackgroundColour(backgroundColour); - sl.draw(); -} - -int VAudioSelector::handleCommand(int command) -{ - switch (command) - { - case Remote::BACK: - case Remote::OK: - case Remote::GREEN: - { - return 4; - } - case Remote::DF_UP: - case Remote::UP: - { - sl.up(); - sl.draw(); - - ViewMan::getInstance()->updateView(this); - - Message* m = new Message(); - m->from = this; - m->to = parent; - m->message = Message::AUDIO_CHANGE_CHANNEL; - m->parameter = ((AudioChannel*)sl.getCurrentOptionData())->pestype; - Command::getInstance()->postMessageNoLock(m); - - return 2; - } - case Remote::DF_DOWN: - case Remote::DOWN: - { - sl.down(); - sl.draw(); - - ViewMan::getInstance()->updateView(this); - - Message* m = new Message(); - m->from = this; - m->to = parent; - m->message = Message::AUDIO_CHANGE_CHANNEL; - m->parameter = ((AudioChannel*)sl.getCurrentOptionData())->pestype; - Command::getInstance()->postMessageNoLock(m); - - return 2; - } - } - - return 0; -} +/* + Copyright 2006 Chris Tallon, Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "vaudioselector.h" + +VAudioSelector::VAudioSelector(void* tparent, bool* availableAudioChannels, int currentAudioChannel, RecInfo* recInfo) +{ + Log::getInstance()->log("VAS", Log::DEBUG, "%i", currentAudioChannel); + + parent = tparent; + + create(200, 120); + +// setTitleText(tr("Audio")); +// setTitleBarOn(1); +// setTitleBarColour(Colour::TITLEBARBACKGROUND); + + sl.setSurface(surface); + sl.setSurfaceOffset(40, 30); + sl.setDimensions(area.w - 45, area.h - 30); + + // Load data from availableAudioChannels, currentAudioChannel and recInfo + + int i; + + for (i = 0; i < PES_AUDIO_MAXCHANNELS; i++) + { + if (availableAudioChannels[i]) + { + AudioChannel* ac = new AudioChannel(); + ac->type = 0; + ac->name = NULL; + ac->pestype = PES_AUDIO_START + i; + acl.push_back(ac); + } + } + + unsigned char numchan_recinfo = recInfo->numComponents; + unsigned char numchan_siz = acl.size(); + int mp_audcounter = 0; + int ac3_counter = 0; + int ac3_offset = 0; + + for (i = 0; i < numchan_siz; i++) + { + AudioChannel* ac = acl[i]; + if (ac) + { + if (ac->type==0) + { + ac3_offset++; + } + } + } + + unsigned char type; + char* lang; + char* description; + int type_int; + + for (i = 0; i < numchan_recinfo; i++) + { + if (recInfo->streams[i] != 2) continue; //not an audio component + type = recInfo->types[i]; + lang = recInfo->languages[i]; + description = recInfo->descriptions[i]; + AudioChannel* ac = NULL; + type_int = 0; + + switch (type) + { + case 1: //mpaudio mono + case 3: //mpaudio stereo + if (mp_audcounter < numchan_siz) ac = acl[mp_audcounter]; + type_int = 0; + break; + case 5: //ac3 + if (ac3_counter + ac3_offset < numchan_siz) ac = acl[ac3_counter + ac3_offset]; + type_int = 1; + break; + } + + if (ac) + { + if (ac->type == type_int) + { + if (description && (strlen(description) > 0)) + { + ac->name = new char[strlen(description)+1]; + strcpy(ac->name, description); + } + else if (lang && (strlen(lang) > 0)) + { + ac->name = new char[strlen(lang)+1]; + strcpy(ac->name, lang); + } + } + } + + switch (type_int) + { + case 0: //mpaudio + mp_audcounter++; + break; + case 1: //ac3 + ac3_counter++; + break; + } + } + + // Now do display + + char tempString[300]; + int audioChannelListSize = acl.size(); + + if (audioChannelListSize) + { + for(i = 0; i < audioChannelListSize; i++) + { + AudioChannel* ac = acl[i]; + + if (ac->name) + { + sl.addOption(ac->name, (ULONG)ac, (ac->pestype == currentAudioChannel)); + } + else + { + SNPRINTF(tempString, 299, "%lu", (ULONG)(ac->pestype - PES_AUDIO_START)); + sl.addOption(tempString, (ULONG)ac, (ac->pestype == currentAudioChannel)); + } + } + } + else + { + sl.addOption(tr("No audio channel data available"), 0, 1); + } +} + +VAudioSelector::~VAudioSelector() +{ + int audioChannelListSize = acl.size(); + for(int i = 0; i < audioChannelListSize; i++) + { + delete acl[i]; + } + acl.clear(); + + sl.clear(); + + Message* m = new Message(); + m->from = this; + m->to = parent; + m->message = Message::CHILD_CLOSE; + Command::getInstance()->postMessageNoLock(m); +} + +void VAudioSelector::draw() +{ + View::draw(); + rectangle(0, 0, area.w, 30, Colour::TITLEBARBACKGROUND); + drawText(tr("Audio"), 45, 5, Colour::LIGHTTEXT); + + sl.setBackgroundColour(backgroundColour); + sl.draw(); +} + +int VAudioSelector::handleCommand(int command) +{ + switch (command) + { + case Remote::BACK: + case Remote::OK: + case Remote::GREEN: + { + return 4; + } + case Remote::DF_UP: + case Remote::UP: + { + sl.up(); + sl.draw(); + + ViewMan::getInstance()->updateView(this); + + Message* m = new Message(); + m->from = this; + m->to = parent; + m->message = Message::AUDIO_CHANGE_CHANNEL; + m->parameter = ((AudioChannel*)sl.getCurrentOptionData())->pestype; + Command::getInstance()->postMessageNoLock(m); + + return 2; + } + case Remote::DF_DOWN: + case Remote::DOWN: + { + sl.down(); + sl.draw(); + + ViewMan::getInstance()->updateView(this); + + Message* m = new Message(); + m->from = this; + m->to = parent; + m->message = Message::AUDIO_CHANGE_CHANNEL; + m->parameter = ((AudioChannel*)sl.getCurrentOptionData())->pestype; + Command::getInstance()->postMessageNoLock(m); + + return 2; + } + } + + return 0; +} diff --git a/vaudioselector.h b/vaudioselector.h index 5a5c9ea..1904b53 100644 --- a/vaudioselector.h +++ b/vaudioselector.h @@ -66,4 +66,3 @@ class VAudioSelector : public View }; #endif - \ No newline at end of file diff --git a/vepg.cc b/vepg.cc index 85e1ddd..cdd783f 100644 --- a/vepg.cc +++ b/vepg.cc @@ -1,42 +1,42 @@ -/* - Copyright 2005 Brian Walton - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -/* - vepg presents a 2 dimensional electronic programme guide with channels down - the y axis and time along the x axis. - Programmes are layed on the x axis as alterate coloured blocks with as much - of the programme title as will fit inside the block shown as text. - Up and down commands step through the channels whilst left and right commands - move through the programmes of the currently selected channel. - When a programme is selected, it highlights in the grid and full programe details - (start time, title and description) are displayed in an area at te top left of the screen. - Any currently programmed timers will display in the grid and in the orogramme detail window as red - It is possible to select a programme to be recorded by pressing the record button. - The video stream currently being viewed is shown as quarter screen in the top right. -*/ - -#include "vepg.h" +/* + Copyright 2005 Brian Walton + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + vepg presents a 2 dimensional electronic programme guide with channels down + the y axis and time along the x axis. + Programmes are layed on the x axis as alterate coloured blocks with as much + of the programme title as will fit inside the block shown as text. + Up and down commands step through the channels whilst left and right commands + move through the programmes of the currently selected channel. + When a programme is selected, it highlights in the grid and full programe details + (start time, title and description) are displayed in an area at te top left of the screen. + Any currently programmed timers will display in the grid and in the orogramme detail window as red + It is possible to select a programme to be recorded by pressing the record button. + The video stream currently being viewed is shown as quarter screen in the top right. +*/ + +#include "vepg.h" VEpg* VEpg::instance = NULL; - -VEpg::VEpg(VVideoLive* v, UINT currentChannel) -{ + +VEpg::VEpg(VVideoLive* v, UINT currentChannel) +{ instance = this; // PAL / NTSC sizes ----------------------- @@ -71,322 +71,322 @@ VEpg::VEpg(VVideoLive* v, UINT currentChannel) } // initialise variables and pointers - viewman = ViewMan::getInstance(); + viewman = ViewMan::getInstance(); videoLive = v; eventList = NULL; chanList = VDR::getInstance()->getChannelsList(VDR::VIDEO); //TODO want to be able to display video and radio together e = 0; - - for(UINT listIndex = 0; listIndex < gridRows; listIndex++) - { - // initialise array of pointers to eventlist structures - eventLista[listIndex] = NULL; - } - - // Create pallet on which to paint our epg view and position it in centre of screen. - // Need to reduce size to deal with overscanning TVs. - - create(xsize, ysize); - setScreenPos(xpos, ypos); - - // beautify - Colour transparent = Colour(0, 0, 0, 0); - setBackgroundColour(transparent); - - progTitle.setSurface(surface); - progTitle.setSurfaceOffset(0,0); - progTitle.setDimensions(300,(Surface::getFontHeight() + 4) * 2 + 16); //paragraph line seperation is 4 pixels - progTitle.setBackgroundColour(Colour::TITLEBARBACKGROUND); + + for(UINT listIndex = 0; listIndex < gridRows; listIndex++) + { + // initialise array of pointers to eventlist structures + eventLista[listIndex] = NULL; + } + + // Create pallet on which to paint our epg view and position it in centre of screen. + // Need to reduce size to deal with overscanning TVs. + + create(xsize, ysize); + setScreenPos(xpos, ypos); + + // beautify + Colour transparent = Colour(0, 0, 0, 0); + setBackgroundColour(transparent); + + progTitle.setSurface(surface); + progTitle.setSurfaceOffset(0,0); + progTitle.setDimensions(300,(Surface::getFontHeight() + 4) * 2 + 16); //paragraph line seperation is 4 pixels + progTitle.setBackgroundColour(Colour::TITLEBARBACKGROUND); progTitle.setTextPos(5, 16); progTitle.setGap(4); - progInfo.setSurface(surface); - progInfo.setSurfaceOffset(0, progTitle.getOffsetY() + progTitle.getHeight()); - progInfo.setDimensions(300,((Surface::getFontHeight() + 4) * summaryLines) + summaryLowerPadding); + progInfo.setSurface(surface); + progInfo.setSurfaceOffset(0, progTitle.getOffsetY() + progTitle.getHeight()); + progInfo.setDimensions(300,((Surface::getFontHeight() + 4) * summaryLines) + summaryLowerPadding); progInfo.setGap(4); - chanName.setSurface(surface); - chanName.setDimensions(510, (Surface::getFontHeight() + 4)); - chanName.setSurfaceOffset(305, chanNameYpos); - chanName.setBackgroundColour(Colour(0, 0, 0, 90)); + chanName.setSurface(surface); + chanName.setDimensions(510, (Surface::getFontHeight() + 4)); + chanName.setSurfaceOffset(305, chanNameYpos); + chanName.setBackgroundColour(Colour(0, 0, 0, 90)); - // create area to display list of channels - chanListbox.setSurface(surface); // add channel list - chanListbox.setSurfaceOffset(0, progInfo.getOffsetY() + progInfo.getHeight() + Surface::getFontHeight() + 8); // position channel list - chanListbox.setDimensions(150, ((Surface::getFontHeight() + 2) * gridRows) + 5); //listbox line seperation is 2 pixels + // create area to display list of channels + chanListbox.setSurface(surface); // add channel list + chanListbox.setSurfaceOffset(0, progInfo.getOffsetY() + progInfo.getHeight() + Surface::getFontHeight() + 8); // position channel list + chanListbox.setDimensions(150, ((Surface::getFontHeight() + 2) * gridRows) + 5); //listbox line seperation is 2 pixels chanListbox.setGap(2); - // populate channel list + // populate channel list if (chanList) { - Channel* chan; - int first = 1; - for (UINT i = 0; i < chanList->size(); i++) - { - chan = (*chanList)[i]; - if (i == currentChannel) - first = 1; - chan->index = chanListbox.addOption(chan->name, 0, first); - first = 0; - } + Channel* chan; + int first = 1; + for (UINT i = 0; i < chanList->size(); i++) + { + chan = (*chanList)[i]; + if (i == currentChannel) + first = 1; + chan->index = chanListbox.addOption(chan->name, 0, first); + first = 0; + } chanName.setText((*chanList)[chanListbox.getCurrentOption()]->name); } - listTop = chanListbox.getTopOption(); - chanListbox.draw(); // doing this to allow chanListbox.getBottomOption() in updateEventList() to work - time(<ime); // set ltime to now - ltime = prevHour(<ime); // set ltime to previous hour TODO make this half hour? - time(&selTime); // set selTime to now - updateEventList(); // get list of programmes -} - -VEpg::~VEpg() -{ + listTop = chanListbox.getTopOption(); + chanListbox.draw(); // doing this to allow chanListbox.getBottomOption() in updateEventList() to work + time(<ime); // set ltime to now + ltime = prevHour(<ime); // set ltime to previous hour TODO make this half hour? + time(&selTime); // set selTime to now + updateEventList(); // get list of programmes +} + +VEpg::~VEpg() +{ instance = NULL; - for(UINT listIndex = 0; listIndex < gridRows; listIndex++) - { - if (eventLista[listIndex]) - { - (eventLista)[listIndex]->clear(); - delete eventLista[listIndex]; - } - } - // delete [] eventLista; - - // destroy dynamically allocated memory -} + for(UINT listIndex = 0; listIndex < gridRows; listIndex++) + { + if (eventLista[listIndex]) + { + (eventLista)[listIndex]->clear(); + delete eventLista[listIndex]; + } + } + // delete [] eventLista; + + // destroy dynamically allocated memory +} VEpg* VEpg::getInstance() { return instance; } - -void VEpg::setInfo(Event* event) -{ - time_t t; - struct tm* btime; // to hold programme start and end time - char timeString[9]; // to hold programme start and end time - int length = strlen(event->title); // calculate length of programme title string - char* title = new char[length + 15]; // create string to hold start time, end time and programme title - btime = localtime((time_t*)&event->time); //get programme start time + +void VEpg::setInfo(Event* event) +{ + time_t t; + struct tm* btime; // to hold programme start and end time + char timeString[9]; // to hold programme start and end time + int length = strlen(event->title); // calculate length of programme title string + char* title = new char[length + 15]; // create string to hold start time, end time and programme title + btime = localtime((time_t*)&event->time); //get programme start time #ifndef _MSC_VER strftime(timeString, 9, "%0H:%0M - ", btime); // and format it as hh:mm - #else strftime(timeString, 9, "%H:%M - ", btime); // and format it as hh:mm - #endif - strcpy(title, timeString); // put it in our buffer - t = event->time + event->duration; //get programme end time - btime = localtime(&t); + strcpy(title, timeString); // put it in our buffer + t = event->time + event->duration; //get programme end time + btime = localtime(&t); #ifndef _MSC_VER strftime(timeString, 7, "%0H:%0M ", btime); // and format it as hh:mm - #else strftime(timeString, 7, "%H:%M ", btime); // and format it as hh:mm - #endif - strcat(title, timeString); // put it in our buffer - strcat(title, event->title); // then add the programme title - progTitle.setText(title); // sput this sring in our text box - length = strlen(event->description); - char* info = new char[length + 1]; // create programme detail string - strcpy(info, event->description); - progInfo.setText(info); // show programme detail string -// destroy dynamically allocated memory - delete[] info; - delete[] title; -} - -void VEpg::draw() -{ - View::draw(); // draw pallet - - // Moved all the dynamic data drawing to a seperate function - - // Display the status and key stuff at the bottom - int keyx = chanListbox.getOffsetX(); - int keyy = chanListbox.getOffsetY() + chanListbox.getHeight() + 2; - rectangle(keyx, keyy, 605, Surface::getFontHeight() * 2 + 14, Colour(100, 100, 100, 255)); - - WSymbol w; - w.setSurface(surface); - - w.nextSymbol = WSymbol::LEFTARROW; - w.setSurfaceOffset(keyx + 1, keyy + 20); - w.draw(); - - w.nextSymbol = WSymbol::UP; - w.setSurfaceOffset(keyx + 26, keyy + 3); - w.draw(); - - w.nextSymbol = WSymbol::DOWN; - w.setSurfaceOffset(keyx + 26, keyy + 36); - w.draw(); - - w.nextSymbol = WSymbol::RIGHTARROW; - w.setSurfaceOffset(keyx + 50, keyy + 20); - w.draw(); - - drawText(tr("OK"), keyx + 18, keyy + 20, Colour::LIGHTTEXT); - - rectangle(keyx + 72, keyy + 4, 104, Surface::getFontHeight() + 2, Colour(200, 0, 0, 255)); - drawText(tr("Page up"), keyx + 74, keyy + 5, Colour::LIGHTTEXT); - - rectangle(keyx + 72, keyy + Surface::getFontHeight() + 8, 104, Surface::getFontHeight() + 2, Colour(0, 200, 0, 255)); - drawText(tr("Page down"), keyx + 74, keyy + Surface::getFontHeight() + 9, Colour::LIGHTTEXT); - - rectangle(keyx + 180, keyy + 4, 104, Surface::getFontHeight() + 2, Colour(200, 200, 0, 255)); - drawText(tr("-24 hours"), keyx + 182, keyy + 5, Colour::LIGHTTEXT); - - rectangle(keyx + 180, keyy + Surface::getFontHeight() + 8, 104, Surface::getFontHeight() + 2, Colour(0, 0, 200, 255)); - drawText(tr("+24 hours"), keyx + 182, keyy + Surface::getFontHeight() + 9, Colour::LIGHTTEXT); - - rectangle(keyx + 290, keyy + 4, 180, Surface::getFontHeight() + 2, Colour(180, 180, 180, 255)); - drawText(tr("Guide / Back: Close"), keyx + 292 , keyy + 5, Colour::LIGHTTEXT); - - rectangle(keyx + 290, keyy + Surface::getFontHeight() + 8, 180, Surface::getFontHeight() + 2, Colour(180, 180, 180, 255)); - Colour red = Colour(130, 0, 0); - drawText(tr("Rec: Set timer"), keyx + 292, keyy + Surface::getFontHeight() + 9, red); - - rectangle(keyx + 474, keyy + 4, 128, Surface::getFontHeight() + 2, Colour(180, 180, 180, 255)); - w.nextSymbol = WSymbol::PLAY; - w.setSurfaceOffset(keyx + 476, keyy + 5); - w.draw(); - drawText(tr("Sel channel"), keyx + 496, keyy + 5, Colour::LIGHTTEXT); - - rectangle(keyx + 474, keyy + Surface::getFontHeight() + 8, 128, Surface::getFontHeight() + 2, Colour(180, 180, 180, 255)); - drawText(tr("Go: Preview"), keyx + 476, keyy + Surface::getFontHeight() + 9, Colour::LIGHTTEXT); - - // Draw all the dynamic data - drawData(); -} - -void VEpg::drawData() -{ - // Not doing View::draw() every time causes - // things not to be cleared off the surface properly - // So, blank out the data area first - - rectangle( - chanListbox.getOffsetX(), - chanListbox.getOffsetY() - Surface::getFontHeight() - 3, - 155 + WINDOW_WIDTH * MINUTE_SCALE, - chanListbox.getHeight() + Surface::getFontHeight() + 3, - Colour::BLACK); - - chanListbox.draw(); - drawgrid(); - chanName.draw(); // TODO this should be dealt with by vvideolive - progTitle.draw(); - progInfo.draw(); + strcat(title, timeString); // put it in our buffer + strcat(title, event->title); // then add the programme title + progTitle.setText(title); // sput this sring in our text box + length = strlen(event->description); + char* info = new char[length + 1]; // create programme detail string + strcpy(info, event->description); + progInfo.setText(info); // show programme detail string +// destroy dynamically allocated memory + delete[] info; + delete[] title; } - -int VEpg::handleCommand(int command) -{ - switch(command) - { - case Remote::DF_UP: - case Remote::UP: - { // cursor up the channel list - chanListbox.up(); - drawData(); - viewman->updateView(this); - return 2; - } - case Remote::DF_DOWN: - case Remote::DOWN: - { // cursor down the channel list - chanListbox.down(); - drawData(); - viewman->updateView(this); - return 2; - } - case Remote::DF_LEFT: - case Remote::LEFT: - { // cursor left through time - selTime = thisEvent.time - 1; - drawData(); - viewman->updateView(this); - return 2; - } - case Remote::DF_RIGHT: - case Remote::RIGHT: - { - // cursor right through time - selTime = thisEvent.time + thisEvent.duration; - drawData(); - viewman->updateView(this); - return 2; - } - case Remote::RED: - { - // cursor up one page - chanListbox.pageUp(); - drawData(); - viewman->updateView(this); - return 2; - } - case Remote::GREEN: - { - // cursor down one page - chanListbox.pageDown(); - drawData(); - viewman->updateView(this); - return 2; - } - case Remote::BLUE: - { - // step forward 24 hours - selTime += 24 * 60 * 60; - drawData(); - viewman->updateView(this); - return 2; - } - case Remote::YELLOW: - { - // step forward 24 hours - selTime -= 24 * 60 * 60; - drawData(); - viewman->updateView(this); - return 2; - } - case Remote::RECORD: - { +void VEpg::draw() +{ + View::draw(); // draw pallet + + // Moved all the dynamic data drawing to a seperate function + + // Display the status and key stuff at the bottom + int keyx = chanListbox.getOffsetX(); + int keyy = chanListbox.getOffsetY() + chanListbox.getHeight() + 2; + rectangle(keyx, keyy, 605, Surface::getFontHeight() * 2 + 14, Colour(100, 100, 100, 255)); + + WSymbol w; + w.setSurface(surface); + + w.nextSymbol = WSymbol::LEFTARROW; + w.setSurfaceOffset(keyx + 1, keyy + 20); + w.draw(); + + w.nextSymbol = WSymbol::UP; + w.setSurfaceOffset(keyx + 26, keyy + 3); + w.draw(); + + w.nextSymbol = WSymbol::DOWN; + w.setSurfaceOffset(keyx + 26, keyy + 36); + w.draw(); + + w.nextSymbol = WSymbol::RIGHTARROW; + w.setSurfaceOffset(keyx + 50, keyy + 20); + w.draw(); + + drawText(tr("OK"), keyx + 18, keyy + 20, Colour::LIGHTTEXT); + + rectangle(keyx + 72, keyy + 4, 104, Surface::getFontHeight() + 2, Colour(200, 0, 0, 255)); + drawText(tr("Page up"), keyx + 74, keyy + 5, Colour::LIGHTTEXT); + + rectangle(keyx + 72, keyy + Surface::getFontHeight() + 8, 104, Surface::getFontHeight() + 2, Colour(0, 200, 0, 255)); + drawText(tr("Page down"), keyx + 74, keyy + Surface::getFontHeight() + 9, Colour::LIGHTTEXT); + + rectangle(keyx + 180, keyy + 4, 104, Surface::getFontHeight() + 2, Colour(200, 200, 0, 255)); + drawText(tr("-24 hours"), keyx + 182, keyy + 5, Colour::LIGHTTEXT); + + rectangle(keyx + 180, keyy + Surface::getFontHeight() + 8, 104, Surface::getFontHeight() + 2, Colour(0, 0, 200, 255)); + drawText(tr("+24 hours"), keyx + 182, keyy + Surface::getFontHeight() + 9, Colour::LIGHTTEXT); + + rectangle(keyx + 290, keyy + 4, 180, Surface::getFontHeight() + 2, Colour(180, 180, 180, 255)); + drawText(tr("Guide / Back: Close"), keyx + 292 , keyy + 5, Colour::LIGHTTEXT); + + rectangle(keyx + 290, keyy + Surface::getFontHeight() + 8, 180, Surface::getFontHeight() + 2, Colour(180, 180, 180, 255)); + Colour red = Colour(130, 0, 0); + drawText(tr("Rec: Set timer"), keyx + 292, keyy + Surface::getFontHeight() + 9, red); + + rectangle(keyx + 474, keyy + 4, 128, Surface::getFontHeight() + 2, Colour(180, 180, 180, 255)); + w.nextSymbol = WSymbol::PLAY; + w.setSurfaceOffset(keyx + 476, keyy + 5); + w.draw(); + drawText(tr("Sel channel"), keyx + 496, keyy + 5, Colour::LIGHTTEXT); + + rectangle(keyx + 474, keyy + Surface::getFontHeight() + 8, 128, Surface::getFontHeight() + 2, Colour(180, 180, 180, 255)); + drawText(tr("Go: Preview"), keyx + 476, keyy + Surface::getFontHeight() + 9, Colour::LIGHTTEXT); + + // Draw all the dynamic data + drawData(); +} + +void VEpg::drawData() +{ + // Not doing View::draw() every time causes + // things not to be cleared off the surface properly + // So, blank out the data area first + + rectangle( + chanListbox.getOffsetX(), + chanListbox.getOffsetY() - Surface::getFontHeight() - 3, + 155 + WINDOW_WIDTH * MINUTE_SCALE, + chanListbox.getHeight() + Surface::getFontHeight() + 3, + Colour::BLACK); + + chanListbox.draw(); + drawgrid(); + chanName.draw(); // TODO this should be dealt with by vvideolive + progTitle.draw(); + progInfo.draw(); +} + + +int VEpg::handleCommand(int command) +{ + switch(command) + { + case Remote::DF_UP: + case Remote::UP: + { // cursor up the channel list + chanListbox.up(); + drawData(); + viewman->updateView(this); + return 2; + } + case Remote::DF_DOWN: + case Remote::DOWN: + { // cursor down the channel list + chanListbox.down(); + drawData(); + viewman->updateView(this); + return 2; + } + case Remote::DF_LEFT: + case Remote::LEFT: + { // cursor left through time + selTime = thisEvent.time - 1; + drawData(); + viewman->updateView(this); + return 2; + } + case Remote::DF_RIGHT: + case Remote::RIGHT: + { + // cursor right through time + selTime = thisEvent.time + thisEvent.duration; + drawData(); + viewman->updateView(this); + return 2; + } + case Remote::RED: + { + // cursor up one page + chanListbox.pageUp(); + drawData(); + viewman->updateView(this); + return 2; + } + case Remote::GREEN: + { + // cursor down one page + chanListbox.pageDown(); + drawData(); + viewman->updateView(this); + return 2; + } + case Remote::BLUE: + { + // step forward 24 hours + selTime += 24 * 60 * 60; + drawData(); + viewman->updateView(this); + return 2; + } + case Remote::YELLOW: + { + // step forward 24 hours + selTime -= 24 * 60 * 60; + drawData(); + viewman->updateView(this); + return 2; + } + case Remote::RECORD: + { if (!chanList) return 2; Log::getInstance()->log("VEPG", Log::DEBUG, "ID %lu TIME %lu DURATION %lu TITLE %s", thisEvent.id, thisEvent.time, thisEvent.duration, thisEvent.title); VEpgSetTimer* vs = new VEpgSetTimer(&thisEvent, (*chanList)[chanListbox.getCurrentOption()]); vs->draw(); viewman->add(vs); viewman->updateView(vs); - return 2; - } - case Remote::PLAY: - case Remote::GO: - case Remote::OK: + return 2; + } + case Remote::PLAY: + case Remote::GO: + case Remote::OK: { if (!chanList) return 2; - // select programme and display menu TODO currently just changes to selected channel + // select programme and display menu TODO currently just changes to selected channel videoLive->channelChange(VVideoLive::NUMBER, (*chanList)[chanListbox.getCurrentOption()]->number); - if(command == Remote::GO) - return 2; - // GO just changes channel in preview, PLAY changes channel and returns to normal TV - } - case Remote::BACK: - case Remote::GUIDE: - { - // return to normal TV mode - if (videoLive) // ptr check done in case being tested from videorec - { + if(command == Remote::GO) + return 2; + // GO just changes channel in preview, PLAY changes channel and returns to normal TV + } + case Remote::BACK: + case Remote::GUIDE: + { + // return to normal TV mode + if (videoLive) // ptr check done in case being tested from videorec + { Message* m = new Message(); // Must be done after this view deleted m->from = this; m->to = videoLive; m->message = Message::EPG_CLOSE; Command::getInstance()->postMessageNoLock(m); } - return 4; - } + return 4; + } case Remote::CHANNELUP: { videoLive->channelChange(VVideoLive::OFFSET, VVideoLive::UP); @@ -397,229 +397,229 @@ int VEpg::handleCommand(int command) videoLive->channelChange(VVideoLive::OFFSET, VVideoLive::DOWN); return 2; } - } - // stop command getting to any more views - return 1; -} - -void VEpg::drawgrid() // redraws grid and select programme -{ - // draw the grid of programmes - char timeString[20]; - time_t t; - time(&t); // set t = now - if(selTime < t) - selTime = t; // don't allow cursor in the past - if(listTop != chanListbox.getTopOption()) - { - // chanListbox has scrolled TODO speed up by changing only rows that have changed - listTop = chanListbox.getTopOption(); - updateEventList(); - } - if ((selTime >= ltime + WINDOW_WIDTH * 60) || (selTime <= ltime)) - { - // we have cursored back before left time of window - //TODO check that this and above don't happen together - ltime = prevHour(&selTime); - updateEventList(); - } - // draw time scale - t = ltime; - struct tm* tms; - tms = localtime(&t); - strftime(timeString, 19, "%a %e %b", tms); - int timey = chanListbox.getOffsetY() - Surface::getFontHeight() - 3; - int timex = 135; - drawTextRJ(timeString, timex - 10, timey, Colour::LIGHTTEXT); // print date - strftime(timeString, 19, "%H:%M", tms); - drawText(timeString, timex, timey, Colour::LIGHTTEXT); // print left time - rectangle(155, timey + Surface::getFontHeight(), 2, 7, Colour(255, 255, 255, 255)); - t = t + 3600; - tms = localtime(&t); - strftime(timeString, 19, "%H:%M", tms); - drawText(timeString, timex + 180, timey, Colour::LIGHTTEXT); // print middle time - rectangle(335, timey + Surface::getFontHeight(), 2, 7, Colour(255, 255, 255, 255)); - t = t + 3600; - tms = localtime(&t); - strftime(timeString, 19, "%H:%M", tms); - drawText(timeString, timex + 360, timey, Colour::LIGHTTEXT); // print right time - rectangle(515, timey + Surface::getFontHeight(), 2, 7, Colour(255, 255, 255, 255)); - // pointer to selTime - rectangle(155 + (selTime - ltime) / 20, timey + Surface::getFontHeight(), 2, 7, Colour(255, 50, 50, 255)); - - // TODO should the above two comditional statements be combined to avoid calling updateEventList() twice? - Event* event; - Event noevent; // an event to use if there are gaps in the epg - thisEvent.setdescription(tr("There are no programme details available for this period")); - thisEvent.duration = WINDOW_WIDTH * 60; - thisEvent.time = ltime; - thisEvent.settitle(tr("No programme details")); - thisEvent.id = 0; - bool swapColour = FALSE; // alternate cell colour - bool currentRow = FALSE; - int y = chanListbox.getOffsetY() + 5; // vertical position of cell - Colour bg, fg; // background colour of cells in grid - // for each displayed channel, find programmes that fall in 2.5 hour time window - for(UINT listIndex = 0; listIndex < gridRows; listIndex++) - { - if (listTop + (int)listIndex >= chanListbox.getBottomOption()) - continue; // ensure nothing populates grid below last channel - currentRow = (listTop + (int)listIndex == chanListbox.getCurrentOption()); - noevent.time = ltime; - noevent.duration = WINDOW_WIDTH * 60; - noevent.settitle(""); - paintCell(&noevent, y, Colour::NOPROGRAMME, Colour::LIGHTTEXT); // fill row with no programme colour to be painted ove with valid programmes - if (currentRow) - { - thisEvent.setdescription(tr("There are no programme details available for this period")); - thisEvent.duration = WINDOW_WIDTH * 60; - thisEvent.time = ltime; - thisEvent.settitle(tr("No programme details")); - thisEvent.id = 0; - } - if (eventLista[listIndex]) - { - sort(eventLista[listIndex]->begin(), eventLista[listIndex]->end(), EventSorter()); - for(e = 0; e < (eventLista[listIndex])->size(); e++) // step through events for this channel - { - fg = Colour::LIGHTTEXT; - event = (*eventLista[listIndex])[e]; - if (event) - { - UINT end = event->time + event->duration; // programme end time - if(event->time >= UINT(ltime) + (WINDOW_WIDTH * 60)) // programme starts after RHS of window - continue; // that's enough of this channel's events - if(end <= UINT(ltime)) // programme ends before LHS of window - continue; // this event is before the window - let's try the next event - // this event is one we are interested in - bg = (swapColour)?Colour::PROGRAMMEA:Colour::PROGRAMMEB; // alternate cell colour - swapColour = !swapColour; // it wil be the other colour next time - if(event->time <= UINT(selTime) && end > UINT(selTime) && currentRow) - { - // this is the selected programme - thisEvent.setdescription(event->description); - thisEvent.duration = event->duration; - thisEvent.time = event->time; - thisEvent.settitle(event->title); - thisEvent.id = event->id; - if(thisEvent.id == 0) - thisEvent.id = 1; - bg = Colour::SELECTHIGHLIGHT; // highlight cell - fg = Colour::DARKTEXT; - } - else - { - if (currentRow && thisEvent.id == 0) - { - if (end <= UINT(selTime) && end > UINT(thisEvent.time)) - thisEvent.time = end; - if (event->time > UINT(selTime) && event->time < thisEvent.time + thisEvent.duration) - thisEvent.duration = event->time - thisEvent.time; - } - } - paintCell(event, y, bg, fg); - } - } - } - else - { - // no event list for this channel. Already painted noevent colour so just highlight if selected - if (currentRow) - { - bg = Colour::SELECTHIGHLIGHT; // highlight cell - fg = Colour::DARKTEXT; - paintCell(&thisEvent, y, bg, fg); - } - else - { - bg = Colour::NOPROGRAMME; - fg = Colour::LIGHTTEXT; - noevent.settitle(tr("No programme details")); - paintCell(&noevent, y, bg, fg); - } - } - y += Surface::getFontHeight() + 2; - } - setInfo(&thisEvent); -} - -void VEpg::updateEventList() -{ + } + // stop command getting to any more views + return 1; +} + +void VEpg::drawgrid() // redraws grid and select programme +{ + // draw the grid of programmes + char timeString[20]; + time_t t; + time(&t); // set t = now + if(selTime < t) + selTime = t; // don't allow cursor in the past + if(listTop != chanListbox.getTopOption()) + { + // chanListbox has scrolled TODO speed up by changing only rows that have changed + listTop = chanListbox.getTopOption(); + updateEventList(); + } + if ((selTime >= ltime + WINDOW_WIDTH * 60) || (selTime <= ltime)) + { + // we have cursored back before left time of window + //TODO check that this and above don't happen together + ltime = prevHour(&selTime); + updateEventList(); + } + // draw time scale + t = ltime; + struct tm* tms; + tms = localtime(&t); + strftime(timeString, 19, "%a %e %b", tms); + int timey = chanListbox.getOffsetY() - Surface::getFontHeight() - 3; + int timex = 135; + drawTextRJ(timeString, timex - 10, timey, Colour::LIGHTTEXT); // print date + strftime(timeString, 19, "%H:%M", tms); + drawText(timeString, timex, timey, Colour::LIGHTTEXT); // print left time + rectangle(155, timey + Surface::getFontHeight(), 2, 7, Colour(255, 255, 255, 255)); + t = t + 3600; + tms = localtime(&t); + strftime(timeString, 19, "%H:%M", tms); + drawText(timeString, timex + 180, timey, Colour::LIGHTTEXT); // print middle time + rectangle(335, timey + Surface::getFontHeight(), 2, 7, Colour(255, 255, 255, 255)); + t = t + 3600; + tms = localtime(&t); + strftime(timeString, 19, "%H:%M", tms); + drawText(timeString, timex + 360, timey, Colour::LIGHTTEXT); // print right time + rectangle(515, timey + Surface::getFontHeight(), 2, 7, Colour(255, 255, 255, 255)); + // pointer to selTime + rectangle(155 + (selTime - ltime) / 20, timey + Surface::getFontHeight(), 2, 7, Colour(255, 50, 50, 255)); + + // TODO should the above two comditional statements be combined to avoid calling updateEventList() twice? + Event* event; + Event noevent; // an event to use if there are gaps in the epg + thisEvent.setdescription(tr("There are no programme details available for this period")); + thisEvent.duration = WINDOW_WIDTH * 60; + thisEvent.time = ltime; + thisEvent.settitle(tr("No programme details")); + thisEvent.id = 0; + bool swapColour = FALSE; // alternate cell colour + bool currentRow = FALSE; + int y = chanListbox.getOffsetY() + 5; // vertical position of cell + Colour bg, fg; // background colour of cells in grid + // for each displayed channel, find programmes that fall in 2.5 hour time window + for(UINT listIndex = 0; listIndex < gridRows; listIndex++) + { + if (listTop + (int)listIndex >= chanListbox.getBottomOption()) + continue; // ensure nothing populates grid below last channel + currentRow = (listTop + (int)listIndex == chanListbox.getCurrentOption()); + noevent.time = ltime; + noevent.duration = WINDOW_WIDTH * 60; + noevent.settitle(""); + paintCell(&noevent, y, Colour::NOPROGRAMME, Colour::LIGHTTEXT); // fill row with no programme colour to be painted ove with valid programmes + if (currentRow) + { + thisEvent.setdescription(tr("There are no programme details available for this period")); + thisEvent.duration = WINDOW_WIDTH * 60; + thisEvent.time = ltime; + thisEvent.settitle(tr("No programme details")); + thisEvent.id = 0; + } + if (eventLista[listIndex]) + { + sort(eventLista[listIndex]->begin(), eventLista[listIndex]->end(), EventSorter()); + for(e = 0; e < (eventLista[listIndex])->size(); e++) // step through events for this channel + { + fg = Colour::LIGHTTEXT; + event = (*eventLista[listIndex])[e]; + if (event) + { + UINT end = event->time + event->duration; // programme end time + if(event->time >= UINT(ltime) + (WINDOW_WIDTH * 60)) // programme starts after RHS of window + continue; // that's enough of this channel's events + if(end <= UINT(ltime)) // programme ends before LHS of window + continue; // this event is before the window - let's try the next event + // this event is one we are interested in + bg = (swapColour)?Colour::PROGRAMMEA:Colour::PROGRAMMEB; // alternate cell colour + swapColour = !swapColour; // it wil be the other colour next time + if(event->time <= UINT(selTime) && end > UINT(selTime) && currentRow) + { + // this is the selected programme + thisEvent.setdescription(event->description); + thisEvent.duration = event->duration; + thisEvent.time = event->time; + thisEvent.settitle(event->title); + thisEvent.id = event->id; + if(thisEvent.id == 0) + thisEvent.id = 1; + bg = Colour::SELECTHIGHLIGHT; // highlight cell + fg = Colour::DARKTEXT; + } + else + { + if (currentRow && thisEvent.id == 0) + { + if (end <= UINT(selTime) && end > UINT(thisEvent.time)) + thisEvent.time = end; + if (event->time > UINT(selTime) && event->time < thisEvent.time + thisEvent.duration) + thisEvent.duration = event->time - thisEvent.time; + } + } + paintCell(event, y, bg, fg); + } + } + } + else + { + // no event list for this channel. Already painted noevent colour so just highlight if selected + if (currentRow) + { + bg = Colour::SELECTHIGHLIGHT; // highlight cell + fg = Colour::DARKTEXT; + paintCell(&thisEvent, y, bg, fg); + } + else + { + bg = Colour::NOPROGRAMME; + fg = Colour::LIGHTTEXT; + noevent.settitle(tr("No programme details")); + paintCell(&noevent, y, bg, fg); + } + } + y += Surface::getFontHeight() + 2; + } + setInfo(&thisEvent); +} + +void VEpg::updateEventList() +{ if (!chanList) return; - Channel* chan; - for(UINT listIndex = 0; listIndex < gridRows; listIndex++) - { - if(listTop + listIndex >= UINT(chanListbox.getBottomOption())) - continue; - chan = (*chanList)[listTop + listIndex]; - - eventLista[listIndex] = VDR::getInstance()->getChannelSchedule(chan->number, ltime - 1, WINDOW_WIDTH * 60 + 2); // ltime - 1 to get prog before window (allows cursor left past ltime). + 2 to get prog after window - } -} - -void VEpg::setCurrentChannel(char* chname) -{ - chanName.setText(chname); - chanName.draw(); - viewman->updateView(this); -} - -void VEpg::paintCell(Event* event, int yOffset, Colour bg, Colour fg) -{ - int w, x, y, h; + Channel* chan; + for(UINT listIndex = 0; listIndex < gridRows; listIndex++) + { + if(listTop + listIndex >= UINT(chanListbox.getBottomOption())) + continue; + chan = (*chanList)[listTop + listIndex]; + + eventLista[listIndex] = VDR::getInstance()->getChannelSchedule(chan->number, ltime - 1, WINDOW_WIDTH * 60 + 2); // ltime - 1 to get prog before window (allows cursor left past ltime). + 2 to get prog after window + } +} + +void VEpg::setCurrentChannel(char* chname) +{ + chanName.setText(chname); + chanName.draw(); + viewman->updateView(this); +} + +void VEpg::paintCell(Event* event, int yOffset, Colour bg, Colour fg) +{ + int w, x, y, h; w = x = 0; // keep compiler happy - y =yOffset; - h = Surface::getFontHeight(); // TODO if want border around text, need to increae this and wselectlist line height - UINT end = event->time + event->duration; // programme end time - if(event->time <= UINT(ltime) && end > UINT(ltime)) // spans start of displayed window - { - x = 155; // LHS of window - if (end > (UINT(ltime) + (WINDOW_WIDTH * 60))) - w = WINDOW_WIDTH * MINUTE_SCALE; // spans full 2 hour window - else - w = MINUTE_SCALE * (event->time + event->duration - ltime ) / 60; // get width of remaining programme - } - if((event->time >= UINT(ltime)) && (event->time <= UINT(ltime) + (WINDOW_WIDTH * 60))) // starts within window - { - x = 155 + (MINUTE_SCALE * (event->time - ltime) / 60); - w = MINUTE_SCALE * event->duration / 60; - //if (w > 155 + MINUTE_SCALE * WINDOW_WIDTH -x) - // w = w + x - 155 - MINUTE_SCALE * WINDOW_WIDTH; // ends outside window - } - if (w > 155 + WINDOW_WIDTH * MINUTE_SCALE - x) - w = 155 + WINDOW_WIDTH * MINUTE_SCALE -x; // limit cells to RHS of window - rectangle(x, y, w, h, bg); - char* tt = new char[strlen(event->title) + 1]; - strcpy (tt, event->title); - int textWidth = 0; - for (UINT textPos = 0; textPos < strlen(tt); textPos++) - { - int thisCharWidth = surface->getCharWidth(tt[textPos]); - if (textWidth + thisCharWidth > w) // text will not fit in cell - { - textWidth = textPos; - break; - } - textWidth += thisCharWidth; - } - char* tT = new char[textWidth]; - if(textWidth > 1) - { - strncpy(tT, tt, textWidth - 1); - tT[textWidth - 1] = '\0'; - surface->drawText(tT, x+2, y, fg.rgba()); - } - delete tT; - -} - -time_t VEpg::prevHour(time_t* t) -{ - struct tm* tms; - tms = localtime(t); - tms->tm_sec = 0; - tms->tm_min = 0; - return mktime(tms); -} - + y =yOffset; + h = Surface::getFontHeight(); // TODO if want border around text, need to increae this and wselectlist line height + UINT end = event->time + event->duration; // programme end time + if(event->time <= UINT(ltime) && end > UINT(ltime)) // spans start of displayed window + { + x = 155; // LHS of window + if (end > (UINT(ltime) + (WINDOW_WIDTH * 60))) + w = WINDOW_WIDTH * MINUTE_SCALE; // spans full 2 hour window + else + w = MINUTE_SCALE * (event->time + event->duration - ltime ) / 60; // get width of remaining programme + } + if((event->time >= UINT(ltime)) && (event->time <= UINT(ltime) + (WINDOW_WIDTH * 60))) // starts within window + { + x = 155 + (MINUTE_SCALE * (event->time - ltime) / 60); + w = MINUTE_SCALE * event->duration / 60; + //if (w > 155 + MINUTE_SCALE * WINDOW_WIDTH -x) + // w = w + x - 155 - MINUTE_SCALE * WINDOW_WIDTH; // ends outside window + } + if (w > 155 + WINDOW_WIDTH * MINUTE_SCALE - x) + w = 155 + WINDOW_WIDTH * MINUTE_SCALE -x; // limit cells to RHS of window + rectangle(x, y, w, h, bg); + char* tt = new char[strlen(event->title) + 1]; + strcpy (tt, event->title); + int textWidth = 0; + for (UINT textPos = 0; textPos < strlen(tt); textPos++) + { + int thisCharWidth = surface->getCharWidth(tt[textPos]); + if (textWidth + thisCharWidth > w) // text will not fit in cell + { + textWidth = textPos; + break; + } + textWidth += thisCharWidth; + } + char* tT = new char[textWidth]; + if(textWidth > 1) + { + strncpy(tT, tt, textWidth - 1); + tT[textWidth - 1] = '\0'; + surface->drawText(tT, x+2, y, fg.rgba()); + } + delete tT; + +} + +time_t VEpg::prevHour(time_t* t) +{ + struct tm* tms; + tms = localtime(t); + tms->tm_sec = 0; + tms->tm_min = 0; + return mktime(tms); +} + diff --git a/videowin.cc b/videowin.cc index 14d0566..c27268e 100644 --- a/videowin.cc +++ b/videowin.cc @@ -1,990 +1,990 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "videowin.h" -#include "log.h" -#include "dssourcefilter.h" -#include "dsallocator.h" -#include "vdr.h" -#include "osdwin.h" - -void AdjustWindow(); - - - -VideoWin::VideoWin() -{ - dsinited=false; - dsgraphbuilder=NULL; - dsmediacontrol=NULL; - dsvmrrenderer=NULL; - dsrefclock=NULL; - dsmediafilter=NULL; - dsbasicaudio=NULL; - sourcefilter=NULL; - allocatorvmr=NULL; - cr_time=0; - dsvmrsurfnotify=NULL; - filtermutex=CreateMutex(NULL,FALSE,NULL); - offsetnotset=true; - offsetvideonotset=true; - offsetaudionotset=true; - startoffset=0; - lastrefaudiotime=0; - lastrefvideotime=0; - lastreftimeRT=0; - lastreftimePTS=0; - firstsynched=false; - cur_audio_media_sample=NULL; - cur_video_media_sample=NULL; - videoon=true; - audioon=true; - pseudotvsize=0; - videoposx=0; - videoposy=0; - iframemode=false;//We are not in Iframe mode at begining - - - -} - -VideoWin::~VideoWin() -{ - CleanupDS(); - CloseHandle(filtermutex); - - - - instance = NULL; -} - -int VideoWin::init(UCHAR tformat) -{ - if (initted) return 0; - - initted = 1; - tvsize=Video::ASPECT16X9; //Internally Vomp should think we are a 16:9 TV - videoposx=0; - videoposy=0; - - if (!setFormat(tformat)){ shutdown(); return 0; } - return 1; -} - -int VideoWin::setTVsize(UCHAR ttvsize) -{ - pseudotvsize=ttvsize; - return 1; -} - -int VideoWin::setDefaultAspect() -{ - return setAspectRatio(Video::ASPECT4X3); -} - -int VideoWin::shutdown() -{ - if (!initted) return 0; - initted = 0; - return 1; -} - -int VideoWin::setFormat(UCHAR tformat) -{ - if (!initted) return 0; - if ((tformat != PAL) && (tformat != NTSC)) return 0; - format = tformat; - if (format == NTSC) - { - screenWidth = 720; - screenHeight = 480; - } - if (format == PAL) - { - screenWidth = 720; - screenHeight = 576; - } - - return 1; -} - -int VideoWin::setConnection(UCHAR tconnection) -{ - if (!initted) return 0; - if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0; - connection = tconnection; - - return 1; -} - -int VideoWin::setAspectRatio(UCHAR taspectRatio) -{ - if (!initted) return 0; - if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0; - aspectRatio = taspectRatio; - AdjustWindow(); - return 1; -} - -int VideoWin::setMode(UCHAR tmode) -{ - if (!initted) return 0; - - //if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode - - if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH) - && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0; - mode = tmode; - videoposx=0; - videoposy=0; - AdjustWindow(); - - return 1; -} - -int VideoWin::signalOff() -{ - return 1; -} - -int VideoWin::signalOn() -{ - return 1; -} - -int VideoWin::setSource() -{ - if (!initted) return 0; - - return 1; -} - -int VideoWin::setPosition(int x, int y) -{ - if (!initted) return 0; - if (mode==QUARTER || mode==EIGHTH) { - videoposx=x; - videoposy=y; - } - return 1; -} - -int VideoWin::sync() -{ - if (!initted) return 0; - - return 1; -} - -#ifdef DS_DEBUG // This stuff would not included in vomp due to lincemse restrcitions -#include "dshelper.h" -#endif - -#define DO_VIDEO - -int VideoWin::play() -{ - if (!initted) return 0; - return 1; -} - -int VideoWin::dsplay() -{ - if (!initted) return 0; - CleanupDS(); - - //Build filter graph - HRESULT hres; -//So this is the real code, this prevents the feeder from calling noexisting objects! - WaitForSingleObject(filtermutex,INFINITE); - if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER, - IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) { - ReleaseMutex(filtermutex); - return 0; - } - #ifdef DS_DEBUG - AddToRot(dsgraphbuilder,&graphidentifier); - #endif - //This is just a try to see if building the graph works -// dsgraphbuilder->RenderFile(L"D:\\Projekte\\VTP Client\\test.mpa" ,NULL); - - firstsynched=false; - sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data - // to DirectShow - if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!"); - ReleaseMutex(filtermutex); - CleanupDS(); - return 0; - } - //if (audioon) { - if (hres=dsgraphbuilder->Render((IPin*)sourcefilter->GetAudioPin()/*audio*/)!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!"); - ReleaseMutex(filtermutex); - CleanupDS(); - return 0; - } - //} -#ifdef DO_VIDEO - if (videoon) { - //We alloc the vmr9 as next step - if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0, - CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!"); - ReleaseMutex(filtermutex); - CleanupDS(); - - } - /*VMR 9 stuff**/ - if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK) { - ReleaseMutex(filtermutex); - CleanupDS(); - Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!"); - - return 0; - } - IVMRFilterConfig9* vmrfilconfig; - if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK) { - ReleaseMutex(filtermutex); - CleanupDS(); - Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!"); - return 0; - } - vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless); - vmrfilconfig->Release(); - - if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,(void**)& dsvmrsurfnotify)!=S_OK) { - ReleaseMutex(filtermutex); - CleanupDS(); - Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!"); - - return 0; - } - allocatorvmr=new DsAllocator(); - dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr); - allocatorvmr->AdviseNotify(dsvmrsurfnotify); - - - - - /*VMR 9 stuff end */ - IFilterGraph2*fg2=NULL; - if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!"); - ReleaseMutex(filtermutex); - CleanupDS(); - return 0; - } - if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*/, - AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL)!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!"); - fg2->Release(); - ReleaseMutex(filtermutex); - CleanupDS(); - return 0; - } - fg2->Release(); - } -#endif - if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER, - IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) { - return 0; - } - - dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter); - HRESULT hresdeb=dsmediafilter->SetSyncSource(dsrefclock); - - dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol); - dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio); - dsinited=true; - //MILLISLEEP(100); - - hresdeb=dsmediacontrol->Run(); - iframemode=false;//exit iframe mode - ReleaseMutex(filtermutex); - return 1; -} - -int VideoWin::EnterIframePlayback() -{ - if (!initted) return 0; - CleanupDS(); - //So this is the real code, this prevents the feeder from calling noexisting objects! - WaitForSingleObject(filtermutex,INFINITE); - iframemode=true;//enter iframe mode - //Build filter graph - HRESULT hres; - if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER, - IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) { - ReleaseMutex(filtermutex); - return 0; - } -#ifdef DS_DEBUG - AddToRot(dsgraphbuilder,&graphidentifier); -#endif - - //firstsynched=false; - sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data - // to DirectShow - if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!"); - ReleaseMutex(filtermutex); - CleanupDS(); - return 0; - } -#ifdef DO_VIDEO - if (videoon) { - //We alloc the vmr9 as next step - if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0, - CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!"); - ReleaseMutex(filtermutex); - CleanupDS(); - return 0; - } - /*VMR 9 stuff**/ - if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!"); - ReleaseMutex(filtermutex); - CleanupDS(); - return 0; - } - IVMRFilterConfig9* vmrfilconfig; - if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK) { - ReleaseMutex(filtermutex); - CleanupDS(); - Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!"); - - return 0; - } - vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless); - vmrfilconfig->Release(); - - if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,(void**)& dsvmrsurfnotify)!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!"); - ReleaseMutex(filtermutex); - CleanupDS(); - return 0; - } - allocatorvmr=new DsAllocator(); - dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr); - allocatorvmr->AdviseNotify(dsvmrsurfnotify); - - /*VMR 9 stuff end */ - IFilterGraph2*fg2=NULL; - if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!"); - ReleaseMutex(filtermutex); - CleanupDS(); - return 0; - } - if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*/, - AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL)!=S_OK) { - Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!"); - fg2->Release(); - ReleaseMutex(filtermutex); - CleanupDS(); - return 0; - } - fg2->Release(); - } -#endif -/* if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER, - IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) { - return 0; - }*/ - - dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter); - dsmediafilter->SetSyncSource(/*dsrefclock*/NULL); //Run as fast as you can! - - dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol); - dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio); - dsinited=true; - - - dsmediacontrol->Run(); - ReleaseMutex(filtermutex); - return 1; - -} - -int VideoWin::dsstop() -{ - if (!initted) return 0; - - CleanupDS(); - - - return 1; -} - -int VideoWin::stop() -{ - if (!initted) return 0; - - - return 1; -} - -int VideoWin::reset() -{ - if (!initted) return 0; - - - return 1; -} - -int VideoWin::dsreset() -{ - if (!initted) return 0; - videoposx=0; - videoposy=0; - iframemode=false;//exit iframe mode - CleanupDS(); - - return 1; -} - -int VideoWin::dspause() -{ - if (!initted) return 0; - WaitForSingleObject(filtermutex,INFINITE); - if (dsmediacontrol) dsmediacontrol->Pause(); - ReleaseMutex(filtermutex); - return 1; -} - -int VideoWin::pause() -{ - if (!initted) return 0; - - return 1; -} - -int VideoWin::unPause() // FIXME get rid - same as play!! -{//No on windows this is not the same, I don't get rid of! - if (!initted) return 0; - return 1; -} - -int VideoWin::dsunPause() // FIXME get rid - same as play!! -{//No on windows this is not the same, I don't get rid of! - if (!initted) return 0; - WaitForSingleObject(filtermutex,INFINITE); - if (dsmediacontrol) dsmediacontrol->Run(); - ReleaseMutex(filtermutex); - - return 1; -} - -int VideoWin::fastForward() -{ - if (!initted) return 0; - - return 1; -} - -int VideoWin::unFastForward() -{ - if (!initted) return 0; - - return 1; -} - -int VideoWin::attachFrameBuffer() -{ - if (!initted) return 0; - return 1; -} - -int VideoWin::blank(void) -{ - ((OsdWin*)Osd::getInstance())->Blank(); - return 1; -} - -ULLONG VideoWin::getCurrentTimestamp() -{ - REFERENCE_TIME startoffset; - REFERENCE_TIME ncr_time; - if (iframemode) return 0; //Not in iframe mode! - if (!dsrefclock || !sourcefilter) return 0; - FILTER_STATE state; - sourcefilter->GetState(10,&state); - - if (state==State_Running) dsrefclock->GetTime(&cr_time); - ncr_time=cr_time; - startoffset=sourcefilter->getStartOffset(); - ncr_time-=startoffset; - ncr_time-=lastreftimeRT; - /* ULLONG result=frameNumberToTimecode( - VDR::getInstance()->frameNumberFromPosition(lastreftimeBYTE));*/ - ULLONG result=lastreftimePTS; - result+=(ULLONG)(ncr_time/10000LL*90LL); - return result; - -} - -ULONG VideoWin::timecodeToFrameNumber(ULLONG timecode) -{ - if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25); - else return (ULONG)(((double)timecode / (double)90000) * (double)30); -} - -ULLONG VideoWin::frameNumberToTimecode(ULONG framenumber) -{ - if (format == PAL) return (ULLONG)(((double)framenumber * (double)90000) / (double)25); - else return (ULLONG)(((double)framenumber * (double)90000) / (double)30); -} - -void VideoWin::CleanupDS() -{ - WaitForSingleObject(filtermutex,INFINITE); - dsinited=false; - if (dsmediacontrol)dsmediacontrol->Stop(); - if (cur_audio_media_sample) { - cur_audio_media_sample->Release(); - cur_audio_media_sample=NULL; - } - if (cur_video_media_sample) { - cur_video_media_sample->Release(); - cur_video_media_sample=NULL; - } - if (dsbasicaudio) { - dsbasicaudio->Release(); - dsbasicaudio=NULL; - } - if (dsvmrsurfnotify) { - dsvmrsurfnotify->Release(); - dsvmrsurfnotify=NULL; - } - if (dsvmrrenderer) { - dsvmrrenderer->Release(); - dsvmrrenderer=NULL; - } - - if (allocatorvmr) { - allocatorvmr->Release(); - allocatorvmr=NULL; - } - - if (dsrefclock) { - dsrefclock->Release(); - dsrefclock=NULL; - } - if (dsmediafilter) { - dsmediafilter->Release(); - dsmediafilter=NULL; - } - - - - if (dsmediacontrol) { - dsmediacontrol->Stop(); - dsmediacontrol->Release(); - dsmediacontrol=NULL; - } - if (dsgraphbuilder){ -#ifdef DS_DEBUG - RemoveFromRot(graphidentifier); -#endif - dsgraphbuilder->Release(); - dsgraphbuilder=NULL; - - sourcefilter=NULL; //The Graph Builder destroys our SourceFilter - } - ReleaseMutex(filtermutex); - -} - -void VideoWin::PrepareMediaSample(const MediaPacketList& mplist, - UINT samplepos) -{ - mediapacket = mplist.front(); -} - -UINT VideoWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos) -{ - DeliverMediaPacket(mediapacket, buffer, samplepos); - if (*samplepos == mediapacket.length) { - *samplepos = 0; - return 1; - } - else return 0; -} - -UINT VideoWin::DeliverMediaPacket(MediaPacket packet, - const UCHAR* buffer, - UINT *samplepos) -{ - /*First Check, if we have an audio sample*/ - if (!isdsinited()) return 0; -#ifdef DO_VIDEO - if (!videoon) { - *samplepos+=packet.length; - MILLISLEEP(0); //yet not implemented//bad idea - return packet.length; - } - /*First Check, if we have an audio sample*/ - if (iframemode) { - samplepos=0; - MILLISLEEP(10); - return 0; //Not in iframe mode! - } - IMediaSample* ms=NULL; - REFERENCE_TIME reftime1=0; - REFERENCE_TIME reftime2=0; - - UINT headerstrip=0; - if (packet.disconti) { - firstsynched=false; - DeliverVideoMediaSample(); - - } - - - /*Inspect PES-Header */ - - if (*samplepos==0) {//stripheader - headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/; - *samplepos+=headerstrip; - if ( packet.synched ) { - DeliverVideoMediaSample();//write out old data - /* if (packet.presentation_time<0) { //Preroll? - *samplepos=packet.length;//if we have not processed at least one - return packet.length;//synched packet ignore it! - }*/ - - reftime1=packet.presentation_time; - reftime2=reftime1+1; - firstsynched=true; - } else { - if (!firstsynched) {// - *samplepos=packet.length;//if we have not processed at least one - return packet.length;//synched packet ignore it! - } - } - } - BYTE *ms_buf; - UINT ms_length; - UINT ms_pos; - UINT haveToCopy; - - if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample - samplepos=0; - MILLISLEEP(10); - return 0; - } - ms_pos=ms->GetActualDataLength(); - ms_length=ms->GetSize(); - haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos); - if ((ms_length-ms_pos)<1) { - DeliverVideoMediaSample(); //we are full! - if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample - samplepos=0; - MILLISLEEP(10); - return 0; - } - ms_pos=ms->GetActualDataLength(); - ms_length=ms->GetSize(); - haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos); - } - ms->GetPointer(&ms_buf); - - - if (ms_pos==0) {//will only be changed on first packet - if (packet.disconti) { - ms->SetDiscontinuity(TRUE); - } else { - ms->SetDiscontinuity(FALSE); - } - if (packet.synched) { - ms->SetSyncPoint(TRUE); - ms->SetTime(&reftime1,&reftime2); - //ms->SetTime(NULL,NULL); - ms->SetMediaTime(NULL, NULL); - if (reftime1<0) ms->SetPreroll(TRUE); - else ms->SetPreroll(FALSE); - /*Timecode handling*/ - lastreftimeRT=reftime1; - lastreftimePTS=packet.pts; - - }else { - ms->SetSyncPoint(FALSE); - ms->SetTime(NULL,NULL); - ms->SetMediaTime(NULL, NULL); - ms->SetPreroll(FALSE); - - // ms->SetSyncPoint(TRUE); - } - } - - - memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy); - ms->SetActualDataLength(haveToCopy+ms_pos); - - *samplepos+=haveToCopy; - - return haveToCopy+headerstrip; - -#else - - *samplepos+=packet.length; - MILLISLEEP(0); //yet not implemented//bad idea - return packet.length; -#endif -} - -int VideoWin::getCurrentAudioMediaSample(IMediaSample** ms) -{ - //WaitForSingleObject(filtermutex,INFINITE); - if (!sourcefilter){ - // ReleaseMutex(filtermutex); - return 0; - } - if (cur_audio_media_sample) { - *ms=cur_audio_media_sample;//already open - return 1; - } - if (!sourcefilter->getCurrentAudioMediaSample(ms)) { - // ReleaseMutex(filtermutex); - } - if (*ms) (*ms)->SetActualDataLength(0); - cur_audio_media_sample=*ms; - //Don't release the mutex before deliver - return 1; -} - -int VideoWin::getCurrentVideoMediaSample(IMediaSample** ms) -{ - //WaitForSingleObject(filtermutex,INFINITE); - if (!sourcefilter){ - // ReleaseMutex(filtermutex); - return 0; - } - if (cur_video_media_sample) { - *ms=cur_video_media_sample;//already open - return 1; - } - if (!sourcefilter->getCurrentVideoMediaSample(ms)) { - // ReleaseMutex(filtermutex); - } - if (*ms) (*ms)->SetActualDataLength(0); - - cur_video_media_sample=*ms; - //Don't release the mutex before deliver - return 1; -} - -int VideoWin::DeliverAudioMediaSample(){ - if (cur_audio_media_sample) { - sourcefilter->DeliverAudioMediaSample(cur_audio_media_sample); - cur_audio_media_sample=NULL; - } - //ReleaseMutex(filtermutex); - return 1; -} - -int VideoWin::DeliverVideoMediaSample(){ - if (cur_video_media_sample) { - sourcefilter->DeliverVideoMediaSample(cur_video_media_sample); - cur_video_media_sample=NULL; - } - //ReleaseMutex(filtermutex); - return 1; -} - -long long VideoWin::SetStartOffset(long long curreftime, bool *rsync) -{ - *rsync=false; - if (offsetnotset) { - startoffset=curreftime;//offset is set for audio - offsetnotset=false; - offsetvideonotset=false; - - - } else { - if (offsetvideonotset) { - offsetvideonotset=false; - *rsync=true; - } else { - if ( (curreftime-lastrefvideotime)>10000000LL - || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync - startoffset+=curreftime-lastrefvideotime; - lastrefaudiotime+=curreftime-lastrefvideotime; - //*rsync=true; - offsetaudionotset=true; - - } - } - - } - - lastrefvideotime=curreftime; - - return startoffset; - -} - -long long VideoWin::SetStartAudioOffset(long long curreftime, bool *rsync) -{ - *rsync=false; - if (offsetnotset) { - startoffset=curreftime; - offsetnotset=false; - offsetaudionotset=false; - }else { - if (offsetaudionotset) { - offsetaudionotset=false; - *rsync=true; - } else { - if ( (curreftime-lastrefaudiotime)>10000000LL - || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync - startoffset+=curreftime-lastrefaudiotime; - lastrefvideotime+=curreftime-lastrefaudiotime; - //*rsync=true; - offsetvideonotset=true; - - } - } - - } - lastrefaudiotime=curreftime; - return startoffset; - -} -void VideoWin::ResetTimeOffsets() { - offsetnotset=true; //called from demuxer - offsetvideonotset=true; - offsetaudionotset=true; - startoffset=0; - lastrefaudiotime=0; - lastrefvideotime=0; - lastreftimeRT=0; - lastreftimePTS=0; - - -} - -void VideoWin::SetAudioVolume(long volume) -{ - if (dsbasicaudio) dsbasicaudio->put_Volume(volume); -} - -void VideoWin::displayIFrame(const UCHAR* buffer, UINT length) -{ - if (!iframemode) EnterIframePlayback(); - - if (!isdsinited()) return ; -#ifdef DO_VIDEO - IMediaSample* ms=NULL; - REFERENCE_TIME reftime1=0; - REFERENCE_TIME reftime2=0; - if (!videoon) return; - - if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample - MILLISLEEP(10); - return ; - } - BYTE *ms_buf; - DWORD ms_length; - ms->GetPointer(&ms_buf); - ms_length=ms->GetSize(); - - /*First Check, if we have an video sample*/ - DWORD read_pos = 0, write_pos = 0; - DWORD pattern, packet_length; - DWORD headerstrip=0; - bool first=true; - if (length < 4) return ; - //Now we strip the pes header - pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]); - while (read_pos + 7 <= length) - { - pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos+3]; - if (pattern < 0x000001E0 || pattern > 0x000001EF) - read_pos++; - else - { - headerstrip=buffer[read_pos+8]+9/*is this right*/; - packet_length = ((buffer[read_pos+4] << 8) | (buffer[read_pos+5])) + 6; - if (read_pos + packet_length > length) - read_pos = length; - else - { - if ((write_pos+packet_length-headerstrip)>ms_length) { - if (first) {ms->SetSyncPoint(TRUE);first=false;} - else ms->SetSyncPoint(FALSE); - ms->SetTime(NULL,NULL); - ms->SetMediaTime(NULL, NULL); - ms->SetActualDataLength(write_pos); - DeliverVideoMediaSample(); - - if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample - MILLISLEEP(10); - return ; - } - write_pos=0; - ms_length=ms->GetSize(); - ms->GetPointer(&ms_buf); - } - if (packet_length-headerstrip>0) { - memcpy(ms_buf+write_pos, buffer+read_pos+headerstrip, packet_length-headerstrip); - write_pos += packet_length-headerstrip; - } - read_pos += packet_length; - - pattern = (buffer[read_pos] << 16) | (buffer[read_pos+1] << 8) - | (buffer[read_pos+2]); - } - } - } - - if (first) {ms->SetSyncPoint(TRUE);first=false;} - else ms->SetSyncPoint(FALSE); - ms->SetTime(NULL,NULL); - ms->SetMediaTime(NULL, NULL); - ms->SetActualDataLength(write_pos); - DeliverVideoMediaSample(); - -#else - - // *samplepos+=packet.length; - MILLISLEEP(0); //yet not implemented//bad idea - return ; -#endif -} - - -#ifdef DEV -int VideoWin::test() -{ - return 0; -} - -int VideoWin::test2() -{ - return 0; -} -#endif - - - - +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "videowin.h" +#include "log.h" +#include "dssourcefilter.h" +#include "dsallocator.h" +#include "vdr.h" +#include "osdwin.h" + +void AdjustWindow(); + + + +VideoWin::VideoWin() +{ + dsinited=false; + dsgraphbuilder=NULL; + dsmediacontrol=NULL; + dsvmrrenderer=NULL; + dsrefclock=NULL; + dsmediafilter=NULL; + dsbasicaudio=NULL; + sourcefilter=NULL; + allocatorvmr=NULL; + cr_time=0; + dsvmrsurfnotify=NULL; + filtermutex=CreateMutex(NULL,FALSE,NULL); + offsetnotset=true; + offsetvideonotset=true; + offsetaudionotset=true; + startoffset=0; + lastrefaudiotime=0; + lastrefvideotime=0; + lastreftimeRT=0; + lastreftimePTS=0; + firstsynched=false; + cur_audio_media_sample=NULL; + cur_video_media_sample=NULL; + videoon=true; + audioon=true; + pseudotvsize=0; + videoposx=0; + videoposy=0; + iframemode=false;//We are not in Iframe mode at begining + + + +} + +VideoWin::~VideoWin() +{ + CleanupDS(); + CloseHandle(filtermutex); + + + + instance = NULL; +} + +int VideoWin::init(UCHAR tformat) +{ + if (initted) return 0; + + initted = 1; + tvsize=Video::ASPECT16X9; //Internally Vomp should think we are a 16:9 TV + videoposx=0; + videoposy=0; + + if (!setFormat(tformat)){ shutdown(); return 0; } + return 1; +} + +int VideoWin::setTVsize(UCHAR ttvsize) +{ + pseudotvsize=ttvsize; + return 1; +} + +int VideoWin::setDefaultAspect() +{ + return setAspectRatio(Video::ASPECT4X3); +} + +int VideoWin::shutdown() +{ + if (!initted) return 0; + initted = 0; + return 1; +} + +int VideoWin::setFormat(UCHAR tformat) +{ + if (!initted) return 0; + if ((tformat != PAL) && (tformat != NTSC)) return 0; + format = tformat; + if (format == NTSC) + { + screenWidth = 720; + screenHeight = 480; + } + if (format == PAL) + { + screenWidth = 720; + screenHeight = 576; + } + + return 1; +} + +int VideoWin::setConnection(UCHAR tconnection) +{ + if (!initted) return 0; + if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0; + connection = tconnection; + + return 1; +} + +int VideoWin::setAspectRatio(UCHAR taspectRatio) +{ + if (!initted) return 0; + if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0; + aspectRatio = taspectRatio; + AdjustWindow(); + return 1; +} + +int VideoWin::setMode(UCHAR tmode) +{ + if (!initted) return 0; + + //if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode + + if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH) + && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0; + mode = tmode; + videoposx=0; + videoposy=0; + AdjustWindow(); + + return 1; +} + +int VideoWin::signalOff() +{ + return 1; +} + +int VideoWin::signalOn() +{ + return 1; +} + +int VideoWin::setSource() +{ + if (!initted) return 0; + + return 1; +} + +int VideoWin::setPosition(int x, int y) +{ + if (!initted) return 0; + if (mode==QUARTER || mode==EIGHTH) { + videoposx=x; + videoposy=y; + } + return 1; +} + +int VideoWin::sync() +{ + if (!initted) return 0; + + return 1; +} + +#ifdef DS_DEBUG // This stuff would not included in vomp due to lincemse restrcitions +#include "dshelper.h" +#endif + +#define DO_VIDEO + +int VideoWin::play() +{ + if (!initted) return 0; + return 1; +} + +int VideoWin::dsplay() +{ + if (!initted) return 0; + CleanupDS(); + + //Build filter graph + HRESULT hres; +//So this is the real code, this prevents the feeder from calling noexisting objects! + WaitForSingleObject(filtermutex,INFINITE); + if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER, + IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) { + ReleaseMutex(filtermutex); + return 0; + } + #ifdef DS_DEBUG + AddToRot(dsgraphbuilder,&graphidentifier); + #endif + //This is just a try to see if building the graph works +// dsgraphbuilder->RenderFile(L"D:\\Projekte\\VTP Client\\test.mpa" ,NULL); + + firstsynched=false; + sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data + // to DirectShow + if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) { + Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!"); + ReleaseMutex(filtermutex); + CleanupDS(); + return 0; + } + //if (audioon) { + if (hres=dsgraphbuilder->Render((IPin*)sourcefilter->GetAudioPin()/*audio*/)!=S_OK) { + Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering audio!"); + ReleaseMutex(filtermutex); + CleanupDS(); + return 0; + } + //} +#ifdef DO_VIDEO + if (videoon) { + //We alloc the vmr9 as next step + if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0, + CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK) { + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!"); + ReleaseMutex(filtermutex); + CleanupDS(); + + } + /*VMR 9 stuff**/ + if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK) { + ReleaseMutex(filtermutex); + CleanupDS(); + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!"); + + return 0; + } + IVMRFilterConfig9* vmrfilconfig; + if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK) { + ReleaseMutex(filtermutex); + CleanupDS(); + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!"); + return 0; + } + vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless); + vmrfilconfig->Release(); + + if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,(void**)& dsvmrsurfnotify)!=S_OK) { + ReleaseMutex(filtermutex); + CleanupDS(); + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!"); + + return 0; + } + allocatorvmr=new DsAllocator(); + dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr); + allocatorvmr->AdviseNotify(dsvmrsurfnotify); + + + + + /*VMR 9 stuff end */ + IFilterGraph2*fg2=NULL; + if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!=S_OK) { + Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!"); + ReleaseMutex(filtermutex); + CleanupDS(); + return 0; + } + if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*/, + AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL)!=S_OK) { + Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!"); + fg2->Release(); + ReleaseMutex(filtermutex); + CleanupDS(); + return 0; + } + fg2->Release(); + } +#endif + if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER, + IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) { + return 0; + } + + dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter); + HRESULT hresdeb=dsmediafilter->SetSyncSource(dsrefclock); + + dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol); + dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio); + dsinited=true; + //MILLISLEEP(100); + + hresdeb=dsmediacontrol->Run(); + iframemode=false;//exit iframe mode + ReleaseMutex(filtermutex); + return 1; +} + +int VideoWin::EnterIframePlayback() +{ + if (!initted) return 0; + CleanupDS(); + //So this is the real code, this prevents the feeder from calling noexisting objects! + WaitForSingleObject(filtermutex,INFINITE); + iframemode=true;//enter iframe mode + //Build filter graph + HRESULT hres; + if (hres=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER, + IID_IGraphBuilder,(void**)&dsgraphbuilder)!=S_OK) { + ReleaseMutex(filtermutex); + return 0; + } +#ifdef DS_DEBUG + AddToRot(dsgraphbuilder,&graphidentifier); +#endif + + //firstsynched=false; + sourcefilter=new DsSourceFilter(); //Creating our Source filter for pushing Data + // to DirectShow + if (hres=dsgraphbuilder->AddFilter(sourcefilter,L"Vomp Win Source Filter")!=S_OK) { + Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Vomp Source Filter!"); + ReleaseMutex(filtermutex); + CleanupDS(); + return 0; + } +#ifdef DO_VIDEO + if (videoon) { + //We alloc the vmr9 as next step + if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0, + CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK) { + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!"); + ReleaseMutex(filtermutex); + CleanupDS(); + return 0; + } + /*VMR 9 stuff**/ + if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK) { + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!"); + ReleaseMutex(filtermutex); + CleanupDS(); + return 0; + } + IVMRFilterConfig9* vmrfilconfig; + if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK) { + ReleaseMutex(filtermutex); + CleanupDS(); + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!"); + + return 0; + } + vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless); + vmrfilconfig->Release(); + + if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,(void**)& dsvmrsurfnotify)!=S_OK) { + Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!"); + ReleaseMutex(filtermutex); + CleanupDS(); + return 0; + } + allocatorvmr=new DsAllocator(); + dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr); + allocatorvmr->AdviseNotify(dsvmrsurfnotify); + + /*VMR 9 stuff end */ + IFilterGraph2*fg2=NULL; + if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!=S_OK) { + Log::getInstance()->log("VideoWin", Log::WARN , "Failed querying for FilterGraph2 Interface!"); + ReleaseMutex(filtermutex); + CleanupDS(); + return 0; + } + if (hres=fg2->RenderEx((IPin*)sourcefilter->GetVideoPin()/*video*/, + AM_RENDEREX_RENDERTOEXISTINGRENDERERS,NULL)!=S_OK) { + Log::getInstance()->log("VideoWin", Log::WARN , "Failed rendering Video!"); + fg2->Release(); + ReleaseMutex(filtermutex); + CleanupDS(); + return 0; + } + fg2->Release(); + } +#endif +/* if (hres=CoCreateInstance(CLSID_SystemClock,NULL,CLSCTX_INPROC_SERVER, + IID_IReferenceClock,(void**)&dsrefclock)!=S_OK) { + return 0; + }*/ + + dsgraphbuilder->QueryInterface(IID_IMediaFilter,(void **) &dsmediafilter); + dsmediafilter->SetSyncSource(/*dsrefclock*/NULL); //Run as fast as you can! + + dsgraphbuilder->QueryInterface(IID_IMediaControl,(void **) &dsmediacontrol); + dsgraphbuilder->QueryInterface(IID_IBasicAudio,(void **) &dsbasicaudio); + dsinited=true; + + + dsmediacontrol->Run(); + ReleaseMutex(filtermutex); + return 1; + +} + +int VideoWin::dsstop() +{ + if (!initted) return 0; + + CleanupDS(); + + + return 1; +} + +int VideoWin::stop() +{ + if (!initted) return 0; + + + return 1; +} + +int VideoWin::reset() +{ + if (!initted) return 0; + + + return 1; +} + +int VideoWin::dsreset() +{ + if (!initted) return 0; + videoposx=0; + videoposy=0; + iframemode=false;//exit iframe mode + CleanupDS(); + + return 1; +} + +int VideoWin::dspause() +{ + if (!initted) return 0; + WaitForSingleObject(filtermutex,INFINITE); + if (dsmediacontrol) dsmediacontrol->Pause(); + ReleaseMutex(filtermutex); + return 1; +} + +int VideoWin::pause() +{ + if (!initted) return 0; + + return 1; +} + +int VideoWin::unPause() // FIXME get rid - same as play!! +{//No on windows this is not the same, I don't get rid of! + if (!initted) return 0; + return 1; +} + +int VideoWin::dsunPause() // FIXME get rid - same as play!! +{//No on windows this is not the same, I don't get rid of! + if (!initted) return 0; + WaitForSingleObject(filtermutex,INFINITE); + if (dsmediacontrol) dsmediacontrol->Run(); + ReleaseMutex(filtermutex); + + return 1; +} + +int VideoWin::fastForward() +{ + if (!initted) return 0; + + return 1; +} + +int VideoWin::unFastForward() +{ + if (!initted) return 0; + + return 1; +} + +int VideoWin::attachFrameBuffer() +{ + if (!initted) return 0; + return 1; +} + +int VideoWin::blank(void) +{ + ((OsdWin*)Osd::getInstance())->Blank(); + return 1; +} + +ULLONG VideoWin::getCurrentTimestamp() +{ + REFERENCE_TIME startoffset; + REFERENCE_TIME ncr_time; + if (iframemode) return 0; //Not in iframe mode! + if (!dsrefclock || !sourcefilter) return 0; + FILTER_STATE state; + sourcefilter->GetState(10,&state); + + if (state==State_Running) dsrefclock->GetTime(&cr_time); + ncr_time=cr_time; + startoffset=sourcefilter->getStartOffset(); + ncr_time-=startoffset; + ncr_time-=lastreftimeRT; + /* ULLONG result=frameNumberToTimecode( + VDR::getInstance()->frameNumberFromPosition(lastreftimeBYTE));*/ + ULLONG result=lastreftimePTS; + result+=(ULLONG)(ncr_time/10000LL*90LL); + return result; + +} + +ULONG VideoWin::timecodeToFrameNumber(ULLONG timecode) +{ + if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25); + else return (ULONG)(((double)timecode / (double)90000) * (double)30); +} + +ULLONG VideoWin::frameNumberToTimecode(ULONG framenumber) +{ + if (format == PAL) return (ULLONG)(((double)framenumber * (double)90000) / (double)25); + else return (ULLONG)(((double)framenumber * (double)90000) / (double)30); +} + +void VideoWin::CleanupDS() +{ + WaitForSingleObject(filtermutex,INFINITE); + dsinited=false; + if (dsmediacontrol)dsmediacontrol->Stop(); + if (cur_audio_media_sample) { + cur_audio_media_sample->Release(); + cur_audio_media_sample=NULL; + } + if (cur_video_media_sample) { + cur_video_media_sample->Release(); + cur_video_media_sample=NULL; + } + if (dsbasicaudio) { + dsbasicaudio->Release(); + dsbasicaudio=NULL; + } + if (dsvmrsurfnotify) { + dsvmrsurfnotify->Release(); + dsvmrsurfnotify=NULL; + } + if (dsvmrrenderer) { + dsvmrrenderer->Release(); + dsvmrrenderer=NULL; + } + + if (allocatorvmr) { + allocatorvmr->Release(); + allocatorvmr=NULL; + } + + if (dsrefclock) { + dsrefclock->Release(); + dsrefclock=NULL; + } + if (dsmediafilter) { + dsmediafilter->Release(); + dsmediafilter=NULL; + } + + + + if (dsmediacontrol) { + dsmediacontrol->Stop(); + dsmediacontrol->Release(); + dsmediacontrol=NULL; + } + if (dsgraphbuilder){ +#ifdef DS_DEBUG + RemoveFromRot(graphidentifier); +#endif + dsgraphbuilder->Release(); + dsgraphbuilder=NULL; + + sourcefilter=NULL; //The Graph Builder destroys our SourceFilter + } + ReleaseMutex(filtermutex); + +} + +void VideoWin::PrepareMediaSample(const MediaPacketList& mplist, + UINT samplepos) +{ + mediapacket = mplist.front(); +} + +UINT VideoWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos) +{ + DeliverMediaPacket(mediapacket, buffer, samplepos); + if (*samplepos == mediapacket.length) { + *samplepos = 0; + return 1; + } + else return 0; +} + +UINT VideoWin::DeliverMediaPacket(MediaPacket packet, + const UCHAR* buffer, + UINT *samplepos) +{ + /*First Check, if we have an audio sample*/ + if (!isdsinited()) return 0; +#ifdef DO_VIDEO + if (!videoon) { + *samplepos+=packet.length; + MILLISLEEP(0); //yet not implemented//bad idea + return packet.length; + } + /*First Check, if we have an audio sample*/ + if (iframemode) { + samplepos=0; + MILLISLEEP(10); + return 0; //Not in iframe mode! + } + IMediaSample* ms=NULL; + REFERENCE_TIME reftime1=0; + REFERENCE_TIME reftime2=0; + + UINT headerstrip=0; + if (packet.disconti) { + firstsynched=false; + DeliverVideoMediaSample(); + + } + + + /*Inspect PES-Header */ + + if (*samplepos==0) {//stripheader + headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/; + *samplepos+=headerstrip; + if ( packet.synched ) { + DeliverVideoMediaSample();//write out old data + /* if (packet.presentation_time<0) { //Preroll? + *samplepos=packet.length;//if we have not processed at least one + return packet.length;//synched packet ignore it! + }*/ + + reftime1=packet.presentation_time; + reftime2=reftime1+1; + firstsynched=true; + } else { + if (!firstsynched) {// + *samplepos=packet.length;//if we have not processed at least one + return packet.length;//synched packet ignore it! + } + } + } + BYTE *ms_buf; + UINT ms_length; + UINT ms_pos; + UINT haveToCopy; + + if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample + samplepos=0; + MILLISLEEP(10); + return 0; + } + ms_pos=ms->GetActualDataLength(); + ms_length=ms->GetSize(); + haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos); + if ((ms_length-ms_pos)<1) { + DeliverVideoMediaSample(); //we are full! + if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample + samplepos=0; + MILLISLEEP(10); + return 0; + } + ms_pos=ms->GetActualDataLength(); + ms_length=ms->GetSize(); + haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos); + } + ms->GetPointer(&ms_buf); + + + if (ms_pos==0) {//will only be changed on first packet + if (packet.disconti) { + ms->SetDiscontinuity(TRUE); + } else { + ms->SetDiscontinuity(FALSE); + } + if (packet.synched) { + ms->SetSyncPoint(TRUE); + ms->SetTime(&reftime1,&reftime2); + //ms->SetTime(NULL,NULL); + ms->SetMediaTime(NULL, NULL); + if (reftime1<0) ms->SetPreroll(TRUE); + else ms->SetPreroll(FALSE); + /*Timecode handling*/ + lastreftimeRT=reftime1; + lastreftimePTS=packet.pts; + + }else { + ms->SetSyncPoint(FALSE); + ms->SetTime(NULL,NULL); + ms->SetMediaTime(NULL, NULL); + ms->SetPreroll(FALSE); + + // ms->SetSyncPoint(TRUE); + } + } + + + memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy); + ms->SetActualDataLength(haveToCopy+ms_pos); + + *samplepos+=haveToCopy; + + return haveToCopy+headerstrip; + +#else + + *samplepos+=packet.length; + MILLISLEEP(0); //yet not implemented//bad idea + return packet.length; +#endif +} + +int VideoWin::getCurrentAudioMediaSample(IMediaSample** ms) +{ + //WaitForSingleObject(filtermutex,INFINITE); + if (!sourcefilter){ + // ReleaseMutex(filtermutex); + return 0; + } + if (cur_audio_media_sample) { + *ms=cur_audio_media_sample;//already open + return 1; + } + if (!sourcefilter->getCurrentAudioMediaSample(ms)) { + // ReleaseMutex(filtermutex); + } + if (*ms) (*ms)->SetActualDataLength(0); + cur_audio_media_sample=*ms; + //Don't release the mutex before deliver + return 1; +} + +int VideoWin::getCurrentVideoMediaSample(IMediaSample** ms) +{ + //WaitForSingleObject(filtermutex,INFINITE); + if (!sourcefilter){ + // ReleaseMutex(filtermutex); + return 0; + } + if (cur_video_media_sample) { + *ms=cur_video_media_sample;//already open + return 1; + } + if (!sourcefilter->getCurrentVideoMediaSample(ms)) { + // ReleaseMutex(filtermutex); + } + if (*ms) (*ms)->SetActualDataLength(0); + + cur_video_media_sample=*ms; + //Don't release the mutex before deliver + return 1; +} + +int VideoWin::DeliverAudioMediaSample(){ + if (cur_audio_media_sample) { + sourcefilter->DeliverAudioMediaSample(cur_audio_media_sample); + cur_audio_media_sample=NULL; + } + //ReleaseMutex(filtermutex); + return 1; +} + +int VideoWin::DeliverVideoMediaSample(){ + if (cur_video_media_sample) { + sourcefilter->DeliverVideoMediaSample(cur_video_media_sample); + cur_video_media_sample=NULL; + } + //ReleaseMutex(filtermutex); + return 1; +} + +long long VideoWin::SetStartOffset(long long curreftime, bool *rsync) +{ + *rsync=false; + if (offsetnotset) { + startoffset=curreftime;//offset is set for audio + offsetnotset=false; + offsetvideonotset=false; + + + } else { + if (offsetvideonotset) { + offsetvideonotset=false; + *rsync=true; + } else { + if ( (curreftime-lastrefvideotime)>10000000LL + || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync + startoffset+=curreftime-lastrefvideotime; + lastrefaudiotime+=curreftime-lastrefvideotime; + //*rsync=true; + offsetaudionotset=true; + + } + } + + } + + lastrefvideotime=curreftime; + + return startoffset; + +} + +long long VideoWin::SetStartAudioOffset(long long curreftime, bool *rsync) +{ + *rsync=false; + if (offsetnotset) { + startoffset=curreftime; + offsetnotset=false; + offsetaudionotset=false; + }else { + if (offsetaudionotset) { + offsetaudionotset=false; + *rsync=true; + } else { + if ( (curreftime-lastrefaudiotime)>10000000LL + || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync + startoffset+=curreftime-lastrefaudiotime; + lastrefvideotime+=curreftime-lastrefaudiotime; + //*rsync=true; + offsetvideonotset=true; + + } + } + + } + lastrefaudiotime=curreftime; + return startoffset; + +} +void VideoWin::ResetTimeOffsets() { + offsetnotset=true; //called from demuxer + offsetvideonotset=true; + offsetaudionotset=true; + startoffset=0; + lastrefaudiotime=0; + lastrefvideotime=0; + lastreftimeRT=0; + lastreftimePTS=0; + + +} + +void VideoWin::SetAudioVolume(long volume) +{ + if (dsbasicaudio) dsbasicaudio->put_Volume(volume); +} + +void VideoWin::displayIFrame(const UCHAR* buffer, UINT length) +{ + if (!iframemode) EnterIframePlayback(); + + if (!isdsinited()) return ; +#ifdef DO_VIDEO + IMediaSample* ms=NULL; + REFERENCE_TIME reftime1=0; + REFERENCE_TIME reftime2=0; + if (!videoon) return; + + if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample + MILLISLEEP(10); + return ; + } + BYTE *ms_buf; + DWORD ms_length; + ms->GetPointer(&ms_buf); + ms_length=ms->GetSize(); + + /*First Check, if we have an video sample*/ + DWORD read_pos = 0, write_pos = 0; + DWORD pattern, packet_length; + DWORD headerstrip=0; + bool first=true; + if (length < 4) return ; + //Now we strip the pes header + pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]); + while (read_pos + 7 <= length) + { + pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos+3]; + if (pattern < 0x000001E0 || pattern > 0x000001EF) + read_pos++; + else + { + headerstrip=buffer[read_pos+8]+9/*is this right*/; + packet_length = ((buffer[read_pos+4] << 8) | (buffer[read_pos+5])) + 6; + if (read_pos + packet_length > length) + read_pos = length; + else + { + if ((write_pos+packet_length-headerstrip)>ms_length) { + if (first) {ms->SetSyncPoint(TRUE);first=false;} + else ms->SetSyncPoint(FALSE); + ms->SetTime(NULL,NULL); + ms->SetMediaTime(NULL, NULL); + ms->SetActualDataLength(write_pos); + DeliverVideoMediaSample(); + + if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample + MILLISLEEP(10); + return ; + } + write_pos=0; + ms_length=ms->GetSize(); + ms->GetPointer(&ms_buf); + } + if (packet_length-headerstrip>0) { + memcpy(ms_buf+write_pos, buffer+read_pos+headerstrip, packet_length-headerstrip); + write_pos += packet_length-headerstrip; + } + read_pos += packet_length; + + pattern = (buffer[read_pos] << 16) | (buffer[read_pos+1] << 8) + | (buffer[read_pos+2]); + } + } + } + + if (first) {ms->SetSyncPoint(TRUE);first=false;} + else ms->SetSyncPoint(FALSE); + ms->SetTime(NULL,NULL); + ms->SetMediaTime(NULL, NULL); + ms->SetActualDataLength(write_pos); + DeliverVideoMediaSample(); + +#else + + // *samplepos+=packet.length; + MILLISLEEP(0); //yet not implemented//bad idea + return ; +#endif +} + + +#ifdef DEV +int VideoWin::test() +{ + return 0; +} + +int VideoWin::test2() +{ + return 0; +} +#endif + + + + diff --git a/videowin.h b/videowin.h index 7e85644..8fbb07c 100644 --- a/videowin.h +++ b/videowin.h @@ -1,158 +1,158 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef VIDEOWIN_H -#define VIDEOWIN_H - -#include -#include -#include -#include -#include -#include - -#include "defines.h" -#include "video.h" - -//#define DS_DEBUG - -class DsSourceFilter; -class DsAllocator; - -class VideoWin : public Video -{ - public: - VideoWin(); - ~VideoWin(); - - int init(UCHAR format); - int shutdown(); - - int setFormat(UCHAR format); - int setConnection(UCHAR connection); - int setAspectRatio(UCHAR aspectRatio); // This one does the pin 8 scart widescreen switching - UCHAR getAspectRatio(){return aspectRatio;}; - UCHAR getMode(){return mode;}; - UCHAR getPseudoTVsize() {return pseudotvsize;}; - int setMode(UCHAR mode); - int setTVsize(UCHAR size); // Is the TV a widescreen? - int setDefaultAspect(); - int setSource(); - int setPosition(int x, int y); - int sync(); - int play(); - int dsplay(); - bool InIframemode() {return iframemode;}; - int stop(); - int dsstop(); - int pause(); - int dspause(); - int unPause(); - int dsunPause(); - int fastForward(); - int unFastForward(); - int reset(); - int dsreset(); - int blank(); - int signalOn(); - int signalOff(); - int attachFrameBuffer(); // What does this do? - ULONG timecodeToFrameNumber(ULLONG timecode); - ULLONG frameNumberToTimecode(ULONG framenumber); - ULLONG getCurrentTimestamp(); - - //Writing Data to Videodevice - virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos); - virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos); - UINT DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, UINT *samplepos); - private: - MediaPacket mediapacket; - public: - - int getCurrentAudioMediaSample(IMediaSample** ms); - int DeliverAudioMediaSample(); - - int getCurrentVideoMediaSample(IMediaSample** ms); - int DeliverVideoMediaSample(); - - virtual long long SetStartOffset(long long curreftime, bool *rsync); - long long SetStartAudioOffset(long long curreftime, bool *rsync); - virtual void ResetTimeOffsets(); - - void SetAudioState(bool state){audioon=state;}; - void SetAudioVolume(long volume); - - void turnVideoOn(){videoon=true;}; - void turnVideoOff(){videoon=false;}; - - virtual void displayIFrame(const UCHAR* buffer, UINT length); - - unsigned int getPosx() {return videoposx;}; - unsigned int getPosy() {return videoposy;}; - bool isVideoOn() {return videoon;}; - bool isdsinited() {return dsinited;}; - -#ifdef DEV - int test(); - int test2(); -#endif -private: - int EnterIframePlayback(); - IMediaControl* dsmediacontrol; - - IGraphBuilder* dsgraphbuilder; - IMediaSample* cur_audio_media_sample; - IMediaSample* cur_video_media_sample; - IBaseFilter* dsvmrrenderer; - IVMRSurfaceAllocatorNotify9 *dsvmrsurfnotify; - IReferenceClock *dsrefclock; - IMediaFilter* dsmediafilter; - IBasicAudio* dsbasicaudio; - REFERENCE_TIME cr_time; - - DsSourceFilter* sourcefilter; - DsAllocator* allocatorvmr; - HANDLE filtermutex; - void CleanupDS(); - bool offsetnotset; - bool offsetvideonotset; - bool offsetaudionotset; - long long startoffset; - long long lastrefvideotime; - long long lastrefaudiotime; - bool dsinited; - bool firstsynched; - bool audioon; - bool videoon; - bool iframemode; - UCHAR pseudotvsize; - REFERENCE_TIME lastreftimeRT; - ULLONG lastreftimePTS; - unsigned int videoposx; - unsigned int videoposy; -#ifdef DS_DEBUG - DWORD graphidentifier; -#endif -}; - -#endif - - - +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef VIDEOWIN_H +#define VIDEOWIN_H + +#include +#include +#include +#include +#include +#include + +#include "defines.h" +#include "video.h" + +//#define DS_DEBUG + +class DsSourceFilter; +class DsAllocator; + +class VideoWin : public Video +{ + public: + VideoWin(); + ~VideoWin(); + + int init(UCHAR format); + int shutdown(); + + int setFormat(UCHAR format); + int setConnection(UCHAR connection); + int setAspectRatio(UCHAR aspectRatio); // This one does the pin 8 scart widescreen switching + UCHAR getAspectRatio(){return aspectRatio;}; + UCHAR getMode(){return mode;}; + UCHAR getPseudoTVsize() {return pseudotvsize;}; + int setMode(UCHAR mode); + int setTVsize(UCHAR size); // Is the TV a widescreen? + int setDefaultAspect(); + int setSource(); + int setPosition(int x, int y); + int sync(); + int play(); + int dsplay(); + bool InIframemode() {return iframemode;}; + int stop(); + int dsstop(); + int pause(); + int dspause(); + int unPause(); + int dsunPause(); + int fastForward(); + int unFastForward(); + int reset(); + int dsreset(); + int blank(); + int signalOn(); + int signalOff(); + int attachFrameBuffer(); // What does this do? + ULONG timecodeToFrameNumber(ULLONG timecode); + ULLONG frameNumberToTimecode(ULONG framenumber); + ULLONG getCurrentTimestamp(); + + //Writing Data to Videodevice + virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos); + virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos); + UINT DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, UINT *samplepos); + private: + MediaPacket mediapacket; + public: + + int getCurrentAudioMediaSample(IMediaSample** ms); + int DeliverAudioMediaSample(); + + int getCurrentVideoMediaSample(IMediaSample** ms); + int DeliverVideoMediaSample(); + + virtual long long SetStartOffset(long long curreftime, bool *rsync); + long long SetStartAudioOffset(long long curreftime, bool *rsync); + virtual void ResetTimeOffsets(); + + void SetAudioState(bool state){audioon=state;}; + void SetAudioVolume(long volume); + + void turnVideoOn(){videoon=true;}; + void turnVideoOff(){videoon=false;}; + + virtual void displayIFrame(const UCHAR* buffer, UINT length); + + unsigned int getPosx() {return videoposx;}; + unsigned int getPosy() {return videoposy;}; + bool isVideoOn() {return videoon;}; + bool isdsinited() {return dsinited;}; + +#ifdef DEV + int test(); + int test2(); +#endif +private: + int EnterIframePlayback(); + IMediaControl* dsmediacontrol; + + IGraphBuilder* dsgraphbuilder; + IMediaSample* cur_audio_media_sample; + IMediaSample* cur_video_media_sample; + IBaseFilter* dsvmrrenderer; + IVMRSurfaceAllocatorNotify9 *dsvmrsurfnotify; + IReferenceClock *dsrefclock; + IMediaFilter* dsmediafilter; + IBasicAudio* dsbasicaudio; + REFERENCE_TIME cr_time; + + DsSourceFilter* sourcefilter; + DsAllocator* allocatorvmr; + HANDLE filtermutex; + void CleanupDS(); + bool offsetnotset; + bool offsetvideonotset; + bool offsetaudionotset; + long long startoffset; + long long lastrefvideotime; + long long lastrefaudiotime; + bool dsinited; + bool firstsynched; + bool audioon; + bool videoon; + bool iframemode; + UCHAR pseudotvsize; + REFERENCE_TIME lastreftimeRT; + ULLONG lastreftimePTS; + unsigned int videoposx; + unsigned int videoposy; +#ifdef DS_DEBUG + DWORD graphidentifier; +#endif +}; + +#endif + + + diff --git a/vompreswin.h b/vompreswin.h index fdb13b9..904fb00 100644 --- a/vompreswin.h +++ b/vompreswin.h @@ -1,46 +1,46 @@ - -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef VOMPRESWIN_H -#define _WIN32_WINNT 0x501 - -#include -#include -#define VOMPACCELERATOR 1 -#define VOMPMENU 2 -#define VOMP_FULL_SCREEN 101 -#define VOMP_YELLOW 102 -#define VOMP_BLUE 103 -#define VOMP_RED 104 -#define VOMP_GREEN 105 -#define VOMP_ENTER 106 -#define VOMP_CANCEL 107 -#define VOMP_UP 108 -#define VOMP_DOWN 109 -#define VOMP_LEFT 110 -#define VOMP_RIGHT 111 -#define VOMP_CURSORUPDATE 112 -#define VOMP_TOPMOST 113 - - -#define VOMPRESWIN_H -#endif - + +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef VOMPRESWIN_H +#define _WIN32_WINNT 0x501 + +#include +#include +#define VOMPACCELERATOR 1 +#define VOMPMENU 2 +#define VOMP_FULL_SCREEN 101 +#define VOMP_YELLOW 102 +#define VOMP_BLUE 103 +#define VOMP_RED 104 +#define VOMP_GREEN 105 +#define VOMP_ENTER 106 +#define VOMP_CANCEL 107 +#define VOMP_UP 108 +#define VOMP_DOWN 109 +#define VOMP_LEFT 110 +#define VOMP_RIGHT 111 +#define VOMP_CURSORUPDATE 112 +#define VOMP_TOPMOST 113 + + +#define VOMPRESWIN_H +#endif + diff --git a/vompwin.rc b/vompwin.rc index 80c0db5..40f2dd5 100644 --- a/vompwin.rc +++ b/vompwin.rc @@ -1,99 +1,99 @@ - - -#include "vompreswin.h" - - - -//1 TEXTINCLUDE -//BEGIN -// "#include ""winsock2.h""\r\n" -// "#include ""vompreswin.h""\r\n" -// "\0" -//END - - - - - -VOMPACCELERATOR ACCELERATORS -BEGIN - VK_INSERT, APPCOMMAND_MEDIA_CHANNEL_DOWN, VIRTKEY, CONTROL, - NOINVERT - VK_INSERT, APPCOMMAND_MEDIA_CHANNEL_DOWN, VIRTKEY, NOINVERT - VK_NEXT, APPCOMMAND_MEDIA_CHANNEL_DOWN, VIRTKEY, NOINVERT - VK_OEM_PLUS, APPCOMMAND_MEDIA_CHANNEL_UP, VIRTKEY, CONTROL, NOINVERT - VK_OEM_PLUS, APPCOMMAND_MEDIA_CHANNEL_UP, VIRTKEY, NOINVERT - VK_PRIOR, APPCOMMAND_MEDIA_CHANNEL_UP, VIRTKEY, NOINVERT - "F", APPCOMMAND_MEDIA_FAST_FORWARD, VIRTKEY, SHIFT, CONTROL, NOINVERT - "B", APPCOMMAND_MEDIA_REWIND, VIRTKEY, SHIFT, CONTROL, NOINVERT - VK_F8, APPCOMMAND_VOLUME_MUTE, VIRTKEY, NOINVERT - "P", APPCOMMAND_MEDIA_PAUSE, VIRTKEY, CONTROL, NOINVERT - "P", APPCOMMAND_MEDIA_PLAY, VIRTKEY, SHIFT, CONTROL, - NOINVERT - "R", APPCOMMAND_MEDIA_RECORD, VIRTKEY, CONTROL, NOINVERT - "B", APPCOMMAND_MEDIA_PREVIOUSTRACK, VIRTKEY, CONTROL, - NOINVERT - "F", APPCOMMAND_MEDIA_NEXTTRACK, VIRTKEY, CONTROL, NOINVERT - "S", APPCOMMAND_MEDIA_STOP, VIRTKEY, CONTROL, NOINVERT - VK_F9, APPCOMMAND_VOLUME_DOWN, VIRTKEY, NOINVERT - VK_F10, APPCOMMAND_VOLUME_UP, VIRTKEY, NOINVERT - VK_RETURN, VOMP_FULL_SCREEN, VIRTKEY, ALT, NOINVERT -END - -vdr.jpg RCDATA other\vdr.jpg -wallpaperNTSC.jpg RCDATA other\wallpaperNTSC.jpg -wallpaperPAL.jpg RCDATA other\wallpaperPAL.jpg - -VOMPMENU MENU -BEGIN - POPUP "Dummy" - BEGIN - MENUITEM "&Play \t Shift+Ctrl+P", APPCOMMAND_MEDIA_PLAY - MENUITEM "Pause\t Ctrl+P", APPCOMMAND_MEDIA_PAUSE - MENUITEM "&Stop\tCtrl+S", APPCOMMAND_MEDIA_STOP - MENUITEM "Record\tCtrl+R", APPCOMMAND_MEDIA_RECORD - MENUITEM SEPARATOR - MENUITEM "Rewind\t Shift+Ctrl+B", APPCOMMAND_MEDIA_REWIND - MENUITEM "Fast Forward\t Shift+Ctrl+F", APPCOMMAND_MEDIA_FAST_FORWARD - MENUITEM SEPARATOR - MENUITEM "Skip Backward\tCtrl+B", APPCOMMAND_MEDIA_PREVIOUSTRACK - MENUITEM "Skip Forward\tCtrl+F", APPCOMMAND_MEDIA_NEXTTRACK - MENUITEM SEPARATOR - POPUP "&Menu" - BEGIN - MENUITEM "&OK\tEnter", VOMP_ENTER - MENUITEM "&Cancel\t Backspace", VOMP_CANCEL - MENUITEM SEPARATOR - MENUITEM "&Up", VOMP_UP - MENUITEM "&Down", VOMP_DOWN - MENUITEM SEPARATOR - MENUITEM "&Left", VOMP_LEFT - MENUITEM "&Right", VOMP_RIGHT - END - MENUITEM SEPARATOR - POPUP "Volume" - BEGIN - MENUITEM "Volume &Up\tF10", APPCOMMAND_VOLUME_UP - MENUITEM "Volume &Down\t F9", APPCOMMAND_VOLUME_DOWN - MENUITEM "Volume &Mute\tF8", APPCOMMAND_VOLUME_MUTE - END - MENUITEM SEPARATOR - POPUP "&Buttons" - BEGIN - MENUITEM "&Yellow", VOMP_YELLOW - MENUITEM "&Blue", VOMP_BLUE - MENUITEM "&Green", VOMP_GREEN - MENUITEM "&Red", VOMP_RED - END - MENUITEM SEPARATOR - MENUITEM "Channel &Up\t Page Up", APPCOMMAND_MEDIA_CHANNEL_UP - MENUITEM "Channel &Down\t Page Down", APPCOMMAND_MEDIA_CHANNEL_DOWN - MENUITEM SEPARATOR - MENUITEM "&Fullscreen\t Alt+Enter", VOMP_FULL_SCREEN - MENUITEM SEPARATOR - MENUITEM "&Always on Top", VOMP_TOPMOST - END -END - - - + + +#include "vompreswin.h" + + + +//1 TEXTINCLUDE +//BEGIN +// "#include ""winsock2.h""\r\n" +// "#include ""vompreswin.h""\r\n" +// "\0" +//END + + + + + +VOMPACCELERATOR ACCELERATORS +BEGIN + VK_INSERT, APPCOMMAND_MEDIA_CHANNEL_DOWN, VIRTKEY, CONTROL, + NOINVERT + VK_INSERT, APPCOMMAND_MEDIA_CHANNEL_DOWN, VIRTKEY, NOINVERT + VK_NEXT, APPCOMMAND_MEDIA_CHANNEL_DOWN, VIRTKEY, NOINVERT + VK_OEM_PLUS, APPCOMMAND_MEDIA_CHANNEL_UP, VIRTKEY, CONTROL, NOINVERT + VK_OEM_PLUS, APPCOMMAND_MEDIA_CHANNEL_UP, VIRTKEY, NOINVERT + VK_PRIOR, APPCOMMAND_MEDIA_CHANNEL_UP, VIRTKEY, NOINVERT + "F", APPCOMMAND_MEDIA_FAST_FORWARD, VIRTKEY, SHIFT, CONTROL, NOINVERT + "B", APPCOMMAND_MEDIA_REWIND, VIRTKEY, SHIFT, CONTROL, NOINVERT + VK_F8, APPCOMMAND_VOLUME_MUTE, VIRTKEY, NOINVERT + "P", APPCOMMAND_MEDIA_PAUSE, VIRTKEY, CONTROL, NOINVERT + "P", APPCOMMAND_MEDIA_PLAY, VIRTKEY, SHIFT, CONTROL, + NOINVERT + "R", APPCOMMAND_MEDIA_RECORD, VIRTKEY, CONTROL, NOINVERT + "B", APPCOMMAND_MEDIA_PREVIOUSTRACK, VIRTKEY, CONTROL, + NOINVERT + "F", APPCOMMAND_MEDIA_NEXTTRACK, VIRTKEY, CONTROL, NOINVERT + "S", APPCOMMAND_MEDIA_STOP, VIRTKEY, CONTROL, NOINVERT + VK_F9, APPCOMMAND_VOLUME_DOWN, VIRTKEY, NOINVERT + VK_F10, APPCOMMAND_VOLUME_UP, VIRTKEY, NOINVERT + VK_RETURN, VOMP_FULL_SCREEN, VIRTKEY, ALT, NOINVERT +END + +vdr.jpg RCDATA other\vdr.jpg +wallpaperNTSC.jpg RCDATA other\wallpaperNTSC.jpg +wallpaperPAL.jpg RCDATA other\wallpaperPAL.jpg + +VOMPMENU MENU +BEGIN + POPUP "Dummy" + BEGIN + MENUITEM "&Play \t Shift+Ctrl+P", APPCOMMAND_MEDIA_PLAY + MENUITEM "Pause\t Ctrl+P", APPCOMMAND_MEDIA_PAUSE + MENUITEM "&Stop\tCtrl+S", APPCOMMAND_MEDIA_STOP + MENUITEM "Record\tCtrl+R", APPCOMMAND_MEDIA_RECORD + MENUITEM SEPARATOR + MENUITEM "Rewind\t Shift+Ctrl+B", APPCOMMAND_MEDIA_REWIND + MENUITEM "Fast Forward\t Shift+Ctrl+F", APPCOMMAND_MEDIA_FAST_FORWARD + MENUITEM SEPARATOR + MENUITEM "Skip Backward\tCtrl+B", APPCOMMAND_MEDIA_PREVIOUSTRACK + MENUITEM "Skip Forward\tCtrl+F", APPCOMMAND_MEDIA_NEXTTRACK + MENUITEM SEPARATOR + POPUP "&Menu" + BEGIN + MENUITEM "&OK\tEnter", VOMP_ENTER + MENUITEM "&Cancel\t Backspace", VOMP_CANCEL + MENUITEM SEPARATOR + MENUITEM "&Up", VOMP_UP + MENUITEM "&Down", VOMP_DOWN + MENUITEM SEPARATOR + MENUITEM "&Left", VOMP_LEFT + MENUITEM "&Right", VOMP_RIGHT + END + MENUITEM SEPARATOR + POPUP "Volume" + BEGIN + MENUITEM "Volume &Up\tF10", APPCOMMAND_VOLUME_UP + MENUITEM "Volume &Down\t F9", APPCOMMAND_VOLUME_DOWN + MENUITEM "Volume &Mute\tF8", APPCOMMAND_VOLUME_MUTE + END + MENUITEM SEPARATOR + POPUP "&Buttons" + BEGIN + MENUITEM "&Yellow", VOMP_YELLOW + MENUITEM "&Blue", VOMP_BLUE + MENUITEM "&Green", VOMP_GREEN + MENUITEM "&Red", VOMP_RED + END + MENUITEM SEPARATOR + MENUITEM "Channel &Up\t Page Up", APPCOMMAND_MEDIA_CHANNEL_UP + MENUITEM "Channel &Down\t Page Down", APPCOMMAND_MEDIA_CHANNEL_DOWN + MENUITEM SEPARATOR + MENUITEM "&Fullscreen\t Alt+Enter", VOMP_FULL_SCREEN + MENUITEM SEPARATOR + MENUITEM "&Always on Top", VOMP_TOPMOST + END +END + + + diff --git a/winmain.cc b/winmain.cc index af85f89..94a584a 100644 --- a/winmain.cc +++ b/winmain.cc @@ -1,829 +1,829 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#ifdef WIN32 -#include -#include -#include -#include - -#define _WIN32_WINNT 0x501 -#include -#include - -#include "vompreswin.h" - -#include "defines.h" -#include "log.h" -#include "remotewin.h" -#include "ledwin.h" -#include "mtdwin.h" -#include "timers.h" -#include "videowin.h" -#include "audiowin.h" -#include "vdr.h" -#include "osdwin.h" -#include "viewman.h" -#include "command.h" - -void sighandler(int signalReceived); -void shutdown(int code); - -// Global variables -------------------------------------------------------------------------------------------------- -int debugEnabled = 0; -Log* logger; -Remote* remote; -Mtd* mtd; -Led* led; -Osd* osd; -Timers* timers; -ViewMan* viewman; -Command* command; -VDR* vdr; -Video* video; -Audio* audio; -bool wnd_fullscreen=false; -bool wnd_topmost=false; -RECT wnd_fs_rect={20,20,768+20,576+20}; -RECT wnd_fs_rect_client={0,0,768,576}; -//OSVERSIONINFO windows_ver; //attempt to distigsh windows versions -bool remotefnc=false; -HINSTANCE hinstance; -bool cmenu=false; - -HMODULE user32dll; -typedef UINT (WINAPI *GETRAWINPUTDATAFNC) (HRAWINPUT,UINT,LPVOID,PUINT,UINT); -typedef UINT (WINAPI *REGISTERRAWINPUTDEVICEFNC) (PCRAWINPUTDEVICE,UINT,UINT); - -GETRAWINPUTDATAFNC dynGetRawInputData=NULL; -REGISTERRAWINPUTDEVICEFNC dynRegisterRawInputDevices=NULL; - -DWORD lastmousemove; - +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifdef WIN32 +#include +#include +#include +#include + +#define _WIN32_WINNT 0x501 +#include +#include + +#include "vompreswin.h" + +#include "defines.h" +#include "log.h" +#include "remotewin.h" +#include "ledwin.h" +#include "mtdwin.h" +#include "timers.h" +#include "videowin.h" +#include "audiowin.h" +#include "vdr.h" +#include "osdwin.h" +#include "viewman.h" +#include "command.h" + +void sighandler(int signalReceived); +void shutdown(int code); + +// Global variables -------------------------------------------------------------------------------------------------- +int debugEnabled = 0; +Log* logger; +Remote* remote; +Mtd* mtd; +Led* led; +Osd* osd; +Timers* timers; +ViewMan* viewman; +Command* command; +VDR* vdr; +Video* video; +Audio* audio; +bool wnd_fullscreen=false; +bool wnd_topmost=false; +RECT wnd_fs_rect={20,20,768+20,576+20}; +RECT wnd_fs_rect_client={0,0,768,576}; +//OSVERSIONINFO windows_ver; //attempt to distigsh windows versions +bool remotefnc=false; +HINSTANCE hinstance; +bool cmenu=false; + +HMODULE user32dll; +typedef UINT (WINAPI *GETRAWINPUTDATAFNC) (HRAWINPUT,UINT,LPVOID,PUINT,UINT); +typedef UINT (WINAPI *REGISTERRAWINPUTDEVICEFNC) (PCRAWINPUTDEVICE,UINT,UINT); + +GETRAWINPUTDATAFNC dynGetRawInputData=NULL; +REGISTERRAWINPUTDEVICEFNC dynRegisterRawInputDevices=NULL; + +DWORD lastmousemove; + void MILLISLEEP(ULONG a) { Sleep(a); -} - -DWORD WINAPI commandthreadStart(void *arg) -{ - command->run(); - return 0; -} - -void LoadRemoteFunctions() { - user32dll=LoadLibrary("user32.dll"); - if (user32dll!=NULL) { - dynGetRawInputData=(GETRAWINPUTDATAFNC)GetProcAddress(user32dll,"GetRawInputData"); - if (dynGetRawInputData!=NULL) { - dynRegisterRawInputDevices=(REGISTERRAWINPUTDEVICEFNC)GetProcAddress(user32dll,"RegisterRawInputDevices"); - if (dynRegisterRawInputDevices!=NULL) { - remotefnc=true; - } - } - } -} - -bool InitApp(HINSTANCE hinst,int cmdshow); - -HWND win_main;//global window handle -HWND win;//global child window handle -HACCEL acc; - -#define ERROR_MSG(str) MessageBox(win_main,str,"Error!",MB_OK|MB_ICONWARNING) -INT WINAPI WinMain( HINSTANCE hinst , HINSTANCE previnst, LPSTR cmdline, int cmdshow) -{ - hinstance=hinst; - //On Windows we have to init a window, we use DXUT - LoadRemoteFunctions(); - if (!InitApp(hinst,cmdshow)) return false; - //Starting Network support - WSADATA wsadat; - int result = WSAStartup(MAKEWORD(2,2),&wsadat); - if (result!=NO_ERROR) { - ERROR_MSG("Initialising WinSocked: Error at WSAStartup()\n"); - return 0; - } - - result= CoInitializeEx(NULL,COINIT_MULTITHREADED );//Initialize COM for DirectShow - if (result!=S_OK) { - ERROR_MSG("Initialising COM: Error at Coinitialize()\n"); - return 0; - } - - - - - // Init global vars ------------------------------------------------------------------------------------------------ - - logger = new Log(); - remote = new RemoteWin(); - mtd = new MtdWin(); - led = new LedWin(); - timers = new Timers(); - osd = new OsdWin(); - vdr = new VDR(); - video = new VideoWin(); - audio = new AudioWin(); - viewman = new ViewMan(); - command = new Command(); - - if (!logger || !remote || !mtd || !led || !osd || !video || !audio || !viewman || !command) - { - ERROR_MSG("Could not create objects. Memory problems?\n"); - shutdown(1); - WSACleanup(); - return 0; - } - - // Get logging module started -------------------------------------------------------------------------------------- - - if (!logger->init(Log::DEBUG, "vompwin.log", true)) - { - ERROR_MSG("Could not initialise log object. Aborting.\n"); - shutdown(1); - WSACleanup(); - return 0; - } - - logger->log("Core", Log::INFO, "Starting up..."); - - - - // Init modules ---------------------------------------------------------------------------------------------------- - int success; - - success = remote->init("/dev/rawir"); - if (success) - { - logger->log("Core", Log::INFO, "Remote module initialised"); - } - else - { - logger->log("Core", Log::EMERG, "Remote module failed to initialise"); - shutdown(1); - WSACleanup(); - return 0; - } - - success = led->init(0); - if (success) - { - logger->log("Core", Log::INFO, "LED module initialised"); - } - else - { - logger->log("Core", Log::EMERG, "LED module failed to initialise"); - shutdown(1); - WSACleanup(); - return 0; - } - - success = mtd->init("/dev/mtd1"); - if (success) - { - logger->log("Core", Log::INFO, "Mtd module initialised"); - } - else - { - logger->log("Core", Log::EMERG, "Mtd module failed to initialise"); - shutdown(1); - WSACleanup(); - return 0; - } - - success = timers->init(); - if (success) - { - logger->log("Core", Log::INFO, "Timers module initialised"); - } - else - { - logger->log("Core", Log::EMERG, "Timers module failed to initialise"); - shutdown(1); - WSACleanup(); - return 0; - } - - UCHAR videoFormat = (UCHAR)mtd->getPALorNTSC(); - if (videoFormat == Video::PAL) logger->log("Core", Log::INFO, "Read from MTD: PAL 720x576"); - else if (videoFormat == Video::NTSC) logger->log("Core", Log::INFO, "Read from MTD: NTSC 720x480"); - else logger->log("Core", Log::INFO, "No help from MTD. Assuming NTSC 720x480"); - - success = video->init(videoFormat); - if (success) - { - logger->log("Core", Log::INFO, "Video module initialised"); - } - else - { - logger->log("Core", Log::EMERG, "Video module failed to initialise"); - shutdown(1); - WSACleanup(); - return 0; - } - - success = osd->init((void*)&win); - if (success) - { - logger->log("Core", Log::INFO, "OSD module initialised"); - } - else - { - logger->log("Core", Log::EMERG, "OSD module failed to initialise"); - shutdown(1); - WSACleanup(); - return 0; - } - - success = audio->init(Audio::MPEG2_PES); - if (success) - { - logger->log("Core", Log::INFO, "Audio module initialised"); - } - else - { - logger->log("Core", Log::EMERG, "Audio module failed to initialise"); - shutdown(1); - WSACleanup(); - return 0; - } - - success = vdr->init(3024); - if (success) - { - logger->log("Core", Log::INFO, "VDR module initialised"); - } - else - { - logger->log("Core", Log::EMERG, "VDR module failed to initialise"); - shutdown(1); - WSACleanup(); - return 0; - } - - success = viewman->init(); - if (success) - { - logger->log("Core", Log::INFO, "ViewMan module initialised"); - } - else - { - logger->log("Core", Log::EMERG, "ViewMan module failed to initialise"); - shutdown(1); - WSACleanup(); - return 0; - } - - success = command->init(); - if (success) - { - logger->log("Core", Log::INFO, "Command module initialised"); - } - else - { - logger->log("Core", Log::EMERG, "Command module failed to initialise"); - shutdown(1); - WSACleanup(); - return 0; - } - - // Other init ------------------------------------------------------------------------------------------------------ - - logger->log("Core", Log::NOTICE, "Startup successful"); - - // Run main loop --------------------------------------------------------------------------------------------------- - - // Ok, all major device components and other bits are loaded and ready - lastmousemove=timeGetTime(); - HANDLE commandthread; - commandthread= CreateThread(NULL, 0, commandthreadStart, NULL,0, - NULL); - MSG message; - message.message=WM_NULL; - bool run=true; - while(run && WaitForSingleObject(commandthread,0)==WAIT_TIMEOUT) { - if (PeekMessage(&message, NULL, 0,0,PM_REMOVE)!=0) { - if (TranslateAccelerator(win_main,acc,&message)==NULL) { - TranslateMessage(&message); - DispatchMessage(&message); - switch (message.message) { - case WM_QUIT: - run=false; //TODO post exit to command Messages - }; - } - } else { - //Render - ((OsdWin*)osd)->Render(); - } - } - // When that returns quit ------------------------------------------------------------------------------------------ - WaitForSingleObject(commandthread,INFINITE); - shutdown(0); - WSACleanup(); - if (user32dll) FreeModule(user32dll); - return 0; - -} - - - -void CalculateWindowSize(RECT * size,ULONG size_mode) { - - DWORD width, height; - DWORD adjheight,adjwidth; - if (!wnd_fullscreen) { - DWORD flags =WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU - |WS_MINIMIZEBOX | WS_SIZEBOX |WS_MAXIMIZEBOX; - RECT wnted={50,50,150,150}; - AdjustWindowRect(&wnted,flags ,false); - adjwidth=-wnted.left+wnted.right-100; - adjheight=-wnted.top+wnted.bottom-100; - } else { - adjwidth=adjheight=0; - } - width=size->right-size->left-adjwidth; - height=size->bottom-size->top-adjheight; - UCHAR mode=video->getMode(); - UCHAR aspect=((VideoWin*)video)->getAspectRatio(); - UCHAR tvsize=((VideoWin*)video)->getPseudoTVsize(); - double aspectrt=4./3.; - if (tvsize==Video::ASPECT16X9) { - if (aspect==Video::ASPECT16X9) { - aspectrt=4./3.; //looks strange, but it is a 16:9 tv - } else if (aspect==Video::ASPECT4X3) { - aspectrt=4./3./(16./9.)*(4./3.); //I hope this is correct - } - } else if (tvsize==Video::ASPECT4X3) { - if (aspect==Video::ASPECT16X9) { - if (mode!=Video::NORMAL) { - aspectrt=16./9.; - } else { - aspectrt=4./3.; - } - } else if (aspect==Video::ASPECT4X3) { - aspectrt=4./3.; - } - } - if (!wnd_fullscreen) { - switch (size_mode) { - case WMSZ_BOTTOM: - case WMSZ_BOTTOMRIGHT: - case WMSZ_TOP: - case WMSZ_TOPRIGHT: - width=(ULONG)(((double)height)*aspectrt); - size->right=size->left+width+adjwidth; - break; - case WMSZ_BOTTOMLEFT: - case WMSZ_TOPLEFT: - width=(ULONG)(((double)height)*aspectrt); - size->left=size->right-width-adjwidth; - break; - case WMSZ_LEFT: - case WMSZ_RIGHT: - height=(ULONG)(((double)width)/aspectrt); - size->bottom=size->top+height+adjheight; - break; - } - MoveWindow(win,0,0,width,height,TRUE); - } else { - RECT newrect={0,0,width,height}; - DWORD newlength; - if ((ULONG)(((double)height)*aspectrt)>width) { - newlength=(ULONG)(((double)width)/aspectrt); - newrect.top+=(height-newlength)/2; - newrect.bottom-=(height-newlength); - } else { - newlength=(ULONG)(((double)height)*aspectrt); - newrect.left+=(width-newlength)/2; - newrect.right-=(width-newlength); - } - MoveWindow(win,newrect.left,newrect.top,newrect.right,newrect.bottom,TRUE); - } - -} - -void AdjustWindow() { - if (!wnd_fullscreen) { - RECT winrect; - GetWindowRect(win_main,&winrect); - CalculateWindowSize(&winrect,WMSZ_BOTTOM); - MoveWindow(win_main,winrect.left, - winrect.top,winrect.right-winrect.left,winrect.bottom-winrect.top,true); - } else { - RECT winrect; - GetWindowRect(win_main,&winrect); - CalculateWindowSize(&winrect,WMSZ_BOTTOM); - - } -} - -void ToggleFullscreen() { - if (wnd_fullscreen) { - wnd_fullscreen=false; - SetWindowLong(win_main,GWL_STYLE,WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU - |WS_MINIMIZEBOX | WS_SIZEBOX |WS_MAXIMIZEBOX); - SetWindowPos(win_main,NULL,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); - - SetWindowPos(win_main,wnd_topmost?HWND_TOPMOST:HWND_TOP,wnd_fs_rect.left,wnd_fs_rect.top, - wnd_fs_rect.right-wnd_fs_rect.left, - wnd_fs_rect.bottom-wnd_fs_rect.top, - SWP_DRAWFRAME | SWP_FRAMECHANGED); - MoveWindow(win,wnd_fs_rect_client.left,wnd_fs_rect_client.top, - wnd_fs_rect_client.right-wnd_fs_rect_client.left, - wnd_fs_rect_client.bottom-wnd_fs_rect_client.top,TRUE); - AdjustWindow(); - } else { - GetWindowRect(win_main,&wnd_fs_rect); - GetWindowRect(win,&wnd_fs_rect_client); - SetWindowLong(win_main,GWL_STYLE,WS_VISIBLE | WS_POPUP ); - SetWindowPos(win_main,NULL,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); - HMONITOR monitor=MonitorFromWindow(win_main,MONITOR_DEFAULTTONEAREST); - MONITORINFO moninfo; - moninfo.cbSize=sizeof(moninfo); - wnd_fullscreen=true; - if (!GetMonitorInfo(monitor,&moninfo)) return ; - SetWindowPos(win_main,wnd_topmost?HWND_TOPMOST:HWND_TOP,moninfo.rcMonitor.left,moninfo.rcMonitor.top, - moninfo.rcMonitor.right,moninfo.rcMonitor.bottom,SWP_FRAMECHANGED); - - AdjustWindow(); - - } - - -} - -void ToggleTopmost() { - wnd_topmost=!wnd_topmost; - SetWindowPos(win_main,wnd_topmost?HWND_TOPMOST:HWND_NOTOPMOST,0,0, - 0,0,SWP_NOMOVE | SWP_NOSIZE); -} - -void CursorUpdate() { - POINT cursorpos; - GetCursorPos(&cursorpos); - HWND asswind; - asswind=WindowFromPoint(cursorpos); - if (asswind!=win_main && asswind!=win) { - return ; //not our responsibility - } - if ((timeGetTime()-lastmousemove)<4000 || cmenu) { - SetCursor(LoadCursor(NULL,IDC_ARROW)); - } else { - SetCursor(NULL); - } -} - -bool ContextMenu(HWND wind,int x,int y) { - POINT p={x,y}; - RECT clientrect; - ScreenToClient(wind,&p); - GetClientRect(wind,&clientrect); - if (!PtInRect(&clientrect,p)) return false; - ClientToScreen(wind,&p); - HMENU menu; - HMENU popup; - menu=LoadMenu(hinstance,MAKEINTRESOURCE(VOMPMENU)); - popup=GetSubMenu(menu,0); - if (wnd_fullscreen) { - CheckMenuItem(popup,VOMP_FULL_SCREEN,MF_BYCOMMAND|MF_CHECKED); - } else { - CheckMenuItem(popup,VOMP_FULL_SCREEN,MF_BYCOMMAND|MF_UNCHECKED); - } - if (wnd_topmost) { - CheckMenuItem(popup,VOMP_TOPMOST,MF_BYCOMMAND|MF_CHECKED); - } else { - CheckMenuItem(popup,VOMP_TOPMOST,MF_BYCOMMAND|MF_UNCHECKED); - } - cmenu=true; - TrackPopupMenu(popup,TPM_RIGHTBUTTON|TPM_LEFTALIGN,x,y,0,wind, NULL); - cmenu=false; - - - DestroyMenu(menu); - return true; -} - -LONG FAR PASCAL WindowProc(HWND wind, UINT msg, WPARAM wparam, LPARAM lparam) -{ - - switch (msg) { - case WM_DESTROY: { - //TODO: call command - logger->log("Core", Log::NOTICE, "Window closed, shutting down..."); - - ((RemoteWin*)Remote::getInstance())->SendPower(); - PostQuitMessage(0); - }break; - case WM_SIZING: { - CalculateWindowSize((RECT*) lparam,wparam); - return TRUE; - }break; - case WM_SIZE: { - int width = LOWORD(lparam); - int height = HIWORD(lparam); - //Call device - } - break; - case WM_PAINT: - RECT r; - PAINTSTRUCT ps; - if (GetUpdateRect(wind, &r, FALSE)) { - BeginPaint(wind, &ps); - //Call Painting Mechanism - EndPaint(wind, &ps); - } - break; - case WM_KEYDOWN: - if (((RemoteWin*)remote)->ReceiveButtonVK(wparam)) { - return 0L; //We process that Key - } else { - return DefWindowProc(wind, msg, wparam, lparam); - } - - break; - case WM_APPCOMMAND: - if (((RemoteWin*)remote)->ReceiveButtonAP(GET_APPCOMMAND_LPARAM(lparam))){ - return TRUE; //yes we process that message - } else { - return DefWindowProc(wind, msg, wparam, lparam); - } - - break; - case WM_INPUT: - if (remotefnc ) { - //only on XP! - LPRAWINPUT lpit; - UINT risize; - dynGetRawInputData((HRAWINPUT)lparam,RID_INPUT,NULL,&risize,sizeof(RAWINPUTHEADER)); - lpit=(LPRAWINPUT)malloc(risize); - dynGetRawInputData((HRAWINPUT)lparam,RID_INPUT,lpit,&risize,sizeof(RAWINPUTHEADER)); - - if (lpit->header.dwType==RIM_TYPEHID && lpit->data.hid.dwSizeHid>=2) { - DWORD button=lpit->data.hid.bRawData[1] | (lpit->data.hid.bRawData[0]<< 8); - if (((RemoteWin*)remote)->ReceiveButtonRI(button)){ - free(lpit); - return 0; //yes we process that message - } - } - free(lpit); - } - return DefWindowProc(wind, msg, wparam, lparam); - - - break; - case WM_COMMAND: - if (LOWORD(wparam)==VOMP_FULL_SCREEN) { - ToggleFullscreen(); - return 0; - } - if (LOWORD(wparam)==VOMP_TOPMOST) { - ToggleTopmost(); - return 0; - } - if (((RemoteWin*)remote)->ReceiveButtonAP(LOWORD(wparam))){ - return 0; //yes we process that message - } else { - return DefWindowProc(wind, msg, wparam, lparam); - } - - break; - case WM_SETCURSOR: - if (((HANDLE)wparam)==win) { - CursorUpdate(); - return 1; - } else { - return DefWindowProc(wind, msg, wparam, lparam); - } - break; - case WM_SYSCOMMAND: - if (wparam==SC_MAXIMIZE) { - ToggleFullscreen(); - return 0; - } else if (wparam==SC_SCREENSAVE || wparam==SC_MONITORPOWER) { - return 0; - } else { - return DefWindowProc(wind,msg,wparam, lparam); - } - break; - case WM_MOUSEMOVE: - lastmousemove=timeGetTime(); - SetCursor(LoadCursor(NULL,IDC_ARROW)); - SetTimer(wind,VOMP_CURSORUPDATE,4500,NULL); - return 0; - //return DefWindowProc(wind,msg,wparam, lparam); - break; - case WM_TIMER: - if (wparam==VOMP_CURSORUPDATE) { - CursorUpdate(); - return 0; - } - return DefWindowProc(wind, msg, wparam, lparam); - - break; - case WM_CONTEXTMENU: - if (!ContextMenu(wind,GET_X_LPARAM(lparam),GET_Y_LPARAM(lparam))) { - return DefWindowProc(wind, msg, wparam, lparam); - } else { - return 0; - } - - default: - return DefWindowProc(wind, msg, wparam, lparam); - } - return 0L; -} - - -bool InitApp(HINSTANCE hinst,int cmdshow) { - /* main window */ - WNDCLASS wcs; - DWORD flags; - wcs.style = CS_HREDRAW | CS_VREDRAW; - wcs.lpfnWndProc = WindowProc; - wcs.cbClsExtra = 0; - wcs.cbWndExtra = sizeof(DWORD); - wcs.hInstance = hinst; - wcs.hIcon = NULL; - wcs.hCursor = NULL; - wcs.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); - wcs.lpszMenuName = NULL; - wcs.lpszClassName = "vomp"; - acc=LoadAccelerators(hinst,MAKEINTRESOURCE(VOMPACCELERATOR)); - if (!RegisterClass(&wcs)) - return false; - flags =WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU - |WS_MINIMIZEBOX | WS_SIZEBOX |WS_MAXIMIZEBOX; - RECT wnted={50,50,768+50,576+50}; - AdjustWindowRect(&wnted,flags ,false); - win_main=CreateWindow("vomp","VOMP on Windows",flags, CW_USEDEFAULT,CW_USEDEFAULT, - wnted.right-wnted.left,wnted.bottom-wnted.top,NULL,NULL,hinst,NULL); - if (!win_main) - return FALSE; - ShowWindow(win_main,SW_SHOWNORMAL); - UpdateWindow(win_main); - /* in order to handle letterboxing we use a child window */ - WNDCLASS child_wcs; - child_wcs.style = CS_HREDRAW | CS_VREDRAW; - child_wcs.lpfnWndProc = WindowProc; - child_wcs.cbClsExtra = 0; - child_wcs.cbWndExtra = sizeof(DWORD); - child_wcs.hInstance = hinst; - child_wcs.hIcon = NULL; - child_wcs.hCursor = NULL; - child_wcs.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); - child_wcs.lpszMenuName = NULL; - child_wcs.lpszClassName = "vomp_playback"; - if (!RegisterClass(&child_wcs)) - return false; - - win=CreateWindow("vomp_playback","Vomp Playback Window",WS_VISIBLE | WS_CHILD |WS_CLIPCHILDREN, - 0,0,768,576,win_main,NULL,hinst,NULL); - if (!win) - return FALSE; - ShowWindow(win,SW_SHOWNORMAL); - UpdateWindow(win); - if (remotefnc) {//at least windows XP - /* We want to support MCE Remote controls*/ - RAWINPUTDEVICE remote_control_data[4]; - ZeroMemory(remote_control_data,sizeof(remote_control_data)); - remote_control_data[0].usUsagePage=0xFFBC; - remote_control_data[0].usUsage=0x88; - remote_control_data[0].dwFlags=0; - remote_control_data[1].usUsagePage=0x0C; - remote_control_data[1].usUsage=0x80; - remote_control_data[1].dwFlags=0; - remote_control_data[2].usUsagePage=0x0C; - remote_control_data[2].usUsage=0x01; - remote_control_data[2].dwFlags=0; - remote_control_data[3].usUsagePage=0x01; - remote_control_data[3].usUsage=0x80; - remote_control_data[3].dwFlags=0; - if (dynRegisterRawInputDevices(remote_control_data,4,sizeof(remote_control_data[0]))!=TRUE) { - MessageBox(0,"Registering remote control failed!","Aborting!",0); - return FALSE; - } - - } - return TRUE; -} - - - - - -// ------------------------------------------------------------------------------------------------------------------- - -void shutdown(int code) -{ - if (viewman) - { - viewman->shutdown(); - delete viewman; - logger->log("Core", Log::NOTICE, "ViewMan module shut down"); - } - - if (command) // shut down command here in case views have posted messages - { - command->shutdown(); - delete command; - logger->log("Core", Log::NOTICE, "Command module shut down"); - } - - if (vdr) - { - vdr->shutdown(); - delete vdr; - logger->log("Core", Log::NOTICE, "VDR module shut down"); - } - - if (osd) - { - osd->shutdown(); - delete osd; - logger->log("Core", Log::NOTICE, "OSD module shut down"); - } - - if (audio) - { - audio->shutdown(); - delete audio; - logger->log("Core", Log::NOTICE, "Audio module shut down"); - } - - if (video) - { - video->shutdown(); - delete video; - logger->log("Core", Log::NOTICE, "Video module shut down"); - } - - if (timers) - { - timers->shutdown(); - delete timers; - logger->log("Core", Log::NOTICE, "Timers module shut down"); - } - - if (mtd) - { - mtd->shutdown(); - delete mtd; - logger->log("Core", Log::NOTICE, "MTD module shut down"); - } - - if (led) - { - led->shutdown(); - delete led; - logger->log("Core", Log::NOTICE, "LED module shut down"); - } - - if (remote) - { - remote->shutdown(); - delete remote; - logger->log("Core", Log::NOTICE, "Remote module shut down"); - } - - if (logger) - { - logger->log("Core", Log::NOTICE, "Log module shutting down... bye!\n\n"); - logger->shutdown(); - delete logger; - } - ExitProcess(0); - -} - -// ------------------------------------------------------------------------------------------------------------------- - -ULLONG ntohll(ULLONG a) -{ - return htonll(a); -} - -ULLONG htonll(ULLONG a) -{ - return (((ULLONG)htonl((ULONG)((a<<32)>> 32))<<32) - |(ULONG)htonl(((ULONG) (a >> 32)))); -} -#endif +} + +DWORD WINAPI commandthreadStart(void *arg) +{ + command->run(); + return 0; +} + +void LoadRemoteFunctions() { + user32dll=LoadLibrary("user32.dll"); + if (user32dll!=NULL) { + dynGetRawInputData=(GETRAWINPUTDATAFNC)GetProcAddress(user32dll,"GetRawInputData"); + if (dynGetRawInputData!=NULL) { + dynRegisterRawInputDevices=(REGISTERRAWINPUTDEVICEFNC)GetProcAddress(user32dll,"RegisterRawInputDevices"); + if (dynRegisterRawInputDevices!=NULL) { + remotefnc=true; + } + } + } +} + +bool InitApp(HINSTANCE hinst,int cmdshow); + +HWND win_main;//global window handle +HWND win;//global child window handle +HACCEL acc; + +#define ERROR_MSG(str) MessageBox(win_main,str,"Error!",MB_OK|MB_ICONWARNING) +INT WINAPI WinMain( HINSTANCE hinst , HINSTANCE previnst, LPSTR cmdline, int cmdshow) +{ + hinstance=hinst; + //On Windows we have to init a window, we use DXUT + LoadRemoteFunctions(); + if (!InitApp(hinst,cmdshow)) return false; + //Starting Network support + WSADATA wsadat; + int result = WSAStartup(MAKEWORD(2,2),&wsadat); + if (result!=NO_ERROR) { + ERROR_MSG("Initialising WinSocked: Error at WSAStartup()\n"); + return 0; + } + + result= CoInitializeEx(NULL,COINIT_MULTITHREADED );//Initialize COM for DirectShow + if (result!=S_OK) { + ERROR_MSG("Initialising COM: Error at Coinitialize()\n"); + return 0; + } + + + + + // Init global vars ------------------------------------------------------------------------------------------------ + + logger = new Log(); + remote = new RemoteWin(); + mtd = new MtdWin(); + led = new LedWin(); + timers = new Timers(); + osd = new OsdWin(); + vdr = new VDR(); + video = new VideoWin(); + audio = new AudioWin(); + viewman = new ViewMan(); + command = new Command(); + + if (!logger || !remote || !mtd || !led || !osd || !video || !audio || !viewman || !command) + { + ERROR_MSG("Could not create objects. Memory problems?\n"); + shutdown(1); + WSACleanup(); + return 0; + } + + // Get logging module started -------------------------------------------------------------------------------------- + + if (!logger->init(Log::DEBUG, "vompwin.log", true)) + { + ERROR_MSG("Could not initialise log object. Aborting.\n"); + shutdown(1); + WSACleanup(); + return 0; + } + + logger->log("Core", Log::INFO, "Starting up..."); + + + + // Init modules ---------------------------------------------------------------------------------------------------- + int success; + + success = remote->init("/dev/rawir"); + if (success) + { + logger->log("Core", Log::INFO, "Remote module initialised"); + } + else + { + logger->log("Core", Log::EMERG, "Remote module failed to initialise"); + shutdown(1); + WSACleanup(); + return 0; + } + + success = led->init(0); + if (success) + { + logger->log("Core", Log::INFO, "LED module initialised"); + } + else + { + logger->log("Core", Log::EMERG, "LED module failed to initialise"); + shutdown(1); + WSACleanup(); + return 0; + } + + success = mtd->init("/dev/mtd1"); + if (success) + { + logger->log("Core", Log::INFO, "Mtd module initialised"); + } + else + { + logger->log("Core", Log::EMERG, "Mtd module failed to initialise"); + shutdown(1); + WSACleanup(); + return 0; + } + + success = timers->init(); + if (success) + { + logger->log("Core", Log::INFO, "Timers module initialised"); + } + else + { + logger->log("Core", Log::EMERG, "Timers module failed to initialise"); + shutdown(1); + WSACleanup(); + return 0; + } + + UCHAR videoFormat = (UCHAR)mtd->getPALorNTSC(); + if (videoFormat == Video::PAL) logger->log("Core", Log::INFO, "Read from MTD: PAL 720x576"); + else if (videoFormat == Video::NTSC) logger->log("Core", Log::INFO, "Read from MTD: NTSC 720x480"); + else logger->log("Core", Log::INFO, "No help from MTD. Assuming NTSC 720x480"); + + success = video->init(videoFormat); + if (success) + { + logger->log("Core", Log::INFO, "Video module initialised"); + } + else + { + logger->log("Core", Log::EMERG, "Video module failed to initialise"); + shutdown(1); + WSACleanup(); + return 0; + } + + success = osd->init((void*)&win); + if (success) + { + logger->log("Core", Log::INFO, "OSD module initialised"); + } + else + { + logger->log("Core", Log::EMERG, "OSD module failed to initialise"); + shutdown(1); + WSACleanup(); + return 0; + } + + success = audio->init(Audio::MPEG2_PES); + if (success) + { + logger->log("Core", Log::INFO, "Audio module initialised"); + } + else + { + logger->log("Core", Log::EMERG, "Audio module failed to initialise"); + shutdown(1); + WSACleanup(); + return 0; + } + + success = vdr->init(3024); + if (success) + { + logger->log("Core", Log::INFO, "VDR module initialised"); + } + else + { + logger->log("Core", Log::EMERG, "VDR module failed to initialise"); + shutdown(1); + WSACleanup(); + return 0; + } + + success = viewman->init(); + if (success) + { + logger->log("Core", Log::INFO, "ViewMan module initialised"); + } + else + { + logger->log("Core", Log::EMERG, "ViewMan module failed to initialise"); + shutdown(1); + WSACleanup(); + return 0; + } + + success = command->init(); + if (success) + { + logger->log("Core", Log::INFO, "Command module initialised"); + } + else + { + logger->log("Core", Log::EMERG, "Command module failed to initialise"); + shutdown(1); + WSACleanup(); + return 0; + } + + // Other init ------------------------------------------------------------------------------------------------------ + + logger->log("Core", Log::NOTICE, "Startup successful"); + + // Run main loop --------------------------------------------------------------------------------------------------- + + // Ok, all major device components and other bits are loaded and ready + lastmousemove=timeGetTime(); + HANDLE commandthread; + commandthread= CreateThread(NULL, 0, commandthreadStart, NULL,0, + NULL); + MSG message; + message.message=WM_NULL; + bool run=true; + while(run && WaitForSingleObject(commandthread,0)==WAIT_TIMEOUT) { + if (PeekMessage(&message, NULL, 0,0,PM_REMOVE)!=0) { + if (TranslateAccelerator(win_main,acc,&message)==NULL) { + TranslateMessage(&message); + DispatchMessage(&message); + switch (message.message) { + case WM_QUIT: + run=false; //TODO post exit to command Messages + }; + } + } else { + //Render + ((OsdWin*)osd)->Render(); + } + } + // When that returns quit ------------------------------------------------------------------------------------------ + WaitForSingleObject(commandthread,INFINITE); + shutdown(0); + WSACleanup(); + if (user32dll) FreeModule(user32dll); + return 0; + +} + + + +void CalculateWindowSize(RECT * size,ULONG size_mode) { + + DWORD width, height; + DWORD adjheight,adjwidth; + if (!wnd_fullscreen) { + DWORD flags =WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU + |WS_MINIMIZEBOX | WS_SIZEBOX |WS_MAXIMIZEBOX; + RECT wnted={50,50,150,150}; + AdjustWindowRect(&wnted,flags ,false); + adjwidth=-wnted.left+wnted.right-100; + adjheight=-wnted.top+wnted.bottom-100; + } else { + adjwidth=adjheight=0; + } + width=size->right-size->left-adjwidth; + height=size->bottom-size->top-adjheight; + UCHAR mode=video->getMode(); + UCHAR aspect=((VideoWin*)video)->getAspectRatio(); + UCHAR tvsize=((VideoWin*)video)->getPseudoTVsize(); + double aspectrt=4./3.; + if (tvsize==Video::ASPECT16X9) { + if (aspect==Video::ASPECT16X9) { + aspectrt=4./3.; //looks strange, but it is a 16:9 tv + } else if (aspect==Video::ASPECT4X3) { + aspectrt=4./3./(16./9.)*(4./3.); //I hope this is correct + } + } else if (tvsize==Video::ASPECT4X3) { + if (aspect==Video::ASPECT16X9) { + if (mode!=Video::NORMAL) { + aspectrt=16./9.; + } else { + aspectrt=4./3.; + } + } else if (aspect==Video::ASPECT4X3) { + aspectrt=4./3.; + } + } + if (!wnd_fullscreen) { + switch (size_mode) { + case WMSZ_BOTTOM: + case WMSZ_BOTTOMRIGHT: + case WMSZ_TOP: + case WMSZ_TOPRIGHT: + width=(ULONG)(((double)height)*aspectrt); + size->right=size->left+width+adjwidth; + break; + case WMSZ_BOTTOMLEFT: + case WMSZ_TOPLEFT: + width=(ULONG)(((double)height)*aspectrt); + size->left=size->right-width-adjwidth; + break; + case WMSZ_LEFT: + case WMSZ_RIGHT: + height=(ULONG)(((double)width)/aspectrt); + size->bottom=size->top+height+adjheight; + break; + } + MoveWindow(win,0,0,width,height,TRUE); + } else { + RECT newrect={0,0,width,height}; + DWORD newlength; + if ((ULONG)(((double)height)*aspectrt)>width) { + newlength=(ULONG)(((double)width)/aspectrt); + newrect.top+=(height-newlength)/2; + newrect.bottom-=(height-newlength); + } else { + newlength=(ULONG)(((double)height)*aspectrt); + newrect.left+=(width-newlength)/2; + newrect.right-=(width-newlength); + } + MoveWindow(win,newrect.left,newrect.top,newrect.right,newrect.bottom,TRUE); + } + +} + +void AdjustWindow() { + if (!wnd_fullscreen) { + RECT winrect; + GetWindowRect(win_main,&winrect); + CalculateWindowSize(&winrect,WMSZ_BOTTOM); + MoveWindow(win_main,winrect.left, + winrect.top,winrect.right-winrect.left,winrect.bottom-winrect.top,true); + } else { + RECT winrect; + GetWindowRect(win_main,&winrect); + CalculateWindowSize(&winrect,WMSZ_BOTTOM); + + } +} + +void ToggleFullscreen() { + if (wnd_fullscreen) { + wnd_fullscreen=false; + SetWindowLong(win_main,GWL_STYLE,WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU + |WS_MINIMIZEBOX | WS_SIZEBOX |WS_MAXIMIZEBOX); + SetWindowPos(win_main,NULL,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); + + SetWindowPos(win_main,wnd_topmost?HWND_TOPMOST:HWND_TOP,wnd_fs_rect.left,wnd_fs_rect.top, + wnd_fs_rect.right-wnd_fs_rect.left, + wnd_fs_rect.bottom-wnd_fs_rect.top, + SWP_DRAWFRAME | SWP_FRAMECHANGED); + MoveWindow(win,wnd_fs_rect_client.left,wnd_fs_rect_client.top, + wnd_fs_rect_client.right-wnd_fs_rect_client.left, + wnd_fs_rect_client.bottom-wnd_fs_rect_client.top,TRUE); + AdjustWindow(); + } else { + GetWindowRect(win_main,&wnd_fs_rect); + GetWindowRect(win,&wnd_fs_rect_client); + SetWindowLong(win_main,GWL_STYLE,WS_VISIBLE | WS_POPUP ); + SetWindowPos(win_main,NULL,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); + HMONITOR monitor=MonitorFromWindow(win_main,MONITOR_DEFAULTTONEAREST); + MONITORINFO moninfo; + moninfo.cbSize=sizeof(moninfo); + wnd_fullscreen=true; + if (!GetMonitorInfo(monitor,&moninfo)) return ; + SetWindowPos(win_main,wnd_topmost?HWND_TOPMOST:HWND_TOP,moninfo.rcMonitor.left,moninfo.rcMonitor.top, + moninfo.rcMonitor.right,moninfo.rcMonitor.bottom,SWP_FRAMECHANGED); + + AdjustWindow(); + + } + + +} + +void ToggleTopmost() { + wnd_topmost=!wnd_topmost; + SetWindowPos(win_main,wnd_topmost?HWND_TOPMOST:HWND_NOTOPMOST,0,0, + 0,0,SWP_NOMOVE | SWP_NOSIZE); +} + +void CursorUpdate() { + POINT cursorpos; + GetCursorPos(&cursorpos); + HWND asswind; + asswind=WindowFromPoint(cursorpos); + if (asswind!=win_main && asswind!=win) { + return ; //not our responsibility + } + if ((timeGetTime()-lastmousemove)<4000 || cmenu) { + SetCursor(LoadCursor(NULL,IDC_ARROW)); + } else { + SetCursor(NULL); + } +} + +bool ContextMenu(HWND wind,int x,int y) { + POINT p={x,y}; + RECT clientrect; + ScreenToClient(wind,&p); + GetClientRect(wind,&clientrect); + if (!PtInRect(&clientrect,p)) return false; + ClientToScreen(wind,&p); + HMENU menu; + HMENU popup; + menu=LoadMenu(hinstance,MAKEINTRESOURCE(VOMPMENU)); + popup=GetSubMenu(menu,0); + if (wnd_fullscreen) { + CheckMenuItem(popup,VOMP_FULL_SCREEN,MF_BYCOMMAND|MF_CHECKED); + } else { + CheckMenuItem(popup,VOMP_FULL_SCREEN,MF_BYCOMMAND|MF_UNCHECKED); + } + if (wnd_topmost) { + CheckMenuItem(popup,VOMP_TOPMOST,MF_BYCOMMAND|MF_CHECKED); + } else { + CheckMenuItem(popup,VOMP_TOPMOST,MF_BYCOMMAND|MF_UNCHECKED); + } + cmenu=true; + TrackPopupMenu(popup,TPM_RIGHTBUTTON|TPM_LEFTALIGN,x,y,0,wind, NULL); + cmenu=false; + + + DestroyMenu(menu); + return true; +} + +LONG FAR PASCAL WindowProc(HWND wind, UINT msg, WPARAM wparam, LPARAM lparam) +{ + + switch (msg) { + case WM_DESTROY: { + //TODO: call command + logger->log("Core", Log::NOTICE, "Window closed, shutting down..."); + + ((RemoteWin*)Remote::getInstance())->SendPower(); + PostQuitMessage(0); + }break; + case WM_SIZING: { + CalculateWindowSize((RECT*) lparam,wparam); + return TRUE; + }break; + case WM_SIZE: { + int width = LOWORD(lparam); + int height = HIWORD(lparam); + //Call device + } + break; + case WM_PAINT: + RECT r; + PAINTSTRUCT ps; + if (GetUpdateRect(wind, &r, FALSE)) { + BeginPaint(wind, &ps); + //Call Painting Mechanism + EndPaint(wind, &ps); + } + break; + case WM_KEYDOWN: + if (((RemoteWin*)remote)->ReceiveButtonVK(wparam)) { + return 0L; //We process that Key + } else { + return DefWindowProc(wind, msg, wparam, lparam); + } + + break; + case WM_APPCOMMAND: + if (((RemoteWin*)remote)->ReceiveButtonAP(GET_APPCOMMAND_LPARAM(lparam))){ + return TRUE; //yes we process that message + } else { + return DefWindowProc(wind, msg, wparam, lparam); + } + + break; + case WM_INPUT: + if (remotefnc ) { + //only on XP! + LPRAWINPUT lpit; + UINT risize; + dynGetRawInputData((HRAWINPUT)lparam,RID_INPUT,NULL,&risize,sizeof(RAWINPUTHEADER)); + lpit=(LPRAWINPUT)malloc(risize); + dynGetRawInputData((HRAWINPUT)lparam,RID_INPUT,lpit,&risize,sizeof(RAWINPUTHEADER)); + + if (lpit->header.dwType==RIM_TYPEHID && lpit->data.hid.dwSizeHid>=2) { + DWORD button=lpit->data.hid.bRawData[1] | (lpit->data.hid.bRawData[0]<< 8); + if (((RemoteWin*)remote)->ReceiveButtonRI(button)){ + free(lpit); + return 0; //yes we process that message + } + } + free(lpit); + } + return DefWindowProc(wind, msg, wparam, lparam); + + + break; + case WM_COMMAND: + if (LOWORD(wparam)==VOMP_FULL_SCREEN) { + ToggleFullscreen(); + return 0; + } + if (LOWORD(wparam)==VOMP_TOPMOST) { + ToggleTopmost(); + return 0; + } + if (((RemoteWin*)remote)->ReceiveButtonAP(LOWORD(wparam))){ + return 0; //yes we process that message + } else { + return DefWindowProc(wind, msg, wparam, lparam); + } + + break; + case WM_SETCURSOR: + if (((HANDLE)wparam)==win) { + CursorUpdate(); + return 1; + } else { + return DefWindowProc(wind, msg, wparam, lparam); + } + break; + case WM_SYSCOMMAND: + if (wparam==SC_MAXIMIZE) { + ToggleFullscreen(); + return 0; + } else if (wparam==SC_SCREENSAVE || wparam==SC_MONITORPOWER) { + return 0; + } else { + return DefWindowProc(wind,msg,wparam, lparam); + } + break; + case WM_MOUSEMOVE: + lastmousemove=timeGetTime(); + SetCursor(LoadCursor(NULL,IDC_ARROW)); + SetTimer(wind,VOMP_CURSORUPDATE,4500,NULL); + return 0; + //return DefWindowProc(wind,msg,wparam, lparam); + break; + case WM_TIMER: + if (wparam==VOMP_CURSORUPDATE) { + CursorUpdate(); + return 0; + } + return DefWindowProc(wind, msg, wparam, lparam); + + break; + case WM_CONTEXTMENU: + if (!ContextMenu(wind,GET_X_LPARAM(lparam),GET_Y_LPARAM(lparam))) { + return DefWindowProc(wind, msg, wparam, lparam); + } else { + return 0; + } + + default: + return DefWindowProc(wind, msg, wparam, lparam); + } + return 0L; +} + + +bool InitApp(HINSTANCE hinst,int cmdshow) { + /* main window */ + WNDCLASS wcs; + DWORD flags; + wcs.style = CS_HREDRAW | CS_VREDRAW; + wcs.lpfnWndProc = WindowProc; + wcs.cbClsExtra = 0; + wcs.cbWndExtra = sizeof(DWORD); + wcs.hInstance = hinst; + wcs.hIcon = NULL; + wcs.hCursor = NULL; + wcs.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wcs.lpszMenuName = NULL; + wcs.lpszClassName = "vomp"; + acc=LoadAccelerators(hinst,MAKEINTRESOURCE(VOMPACCELERATOR)); + if (!RegisterClass(&wcs)) + return false; + flags =WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU + |WS_MINIMIZEBOX | WS_SIZEBOX |WS_MAXIMIZEBOX; + RECT wnted={50,50,768+50,576+50}; + AdjustWindowRect(&wnted,flags ,false); + win_main=CreateWindow("vomp","VOMP on Windows",flags, CW_USEDEFAULT,CW_USEDEFAULT, + wnted.right-wnted.left,wnted.bottom-wnted.top,NULL,NULL,hinst,NULL); + if (!win_main) + return FALSE; + ShowWindow(win_main,SW_SHOWNORMAL); + UpdateWindow(win_main); + /* in order to handle letterboxing we use a child window */ + WNDCLASS child_wcs; + child_wcs.style = CS_HREDRAW | CS_VREDRAW; + child_wcs.lpfnWndProc = WindowProc; + child_wcs.cbClsExtra = 0; + child_wcs.cbWndExtra = sizeof(DWORD); + child_wcs.hInstance = hinst; + child_wcs.hIcon = NULL; + child_wcs.hCursor = NULL; + child_wcs.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + child_wcs.lpszMenuName = NULL; + child_wcs.lpszClassName = "vomp_playback"; + if (!RegisterClass(&child_wcs)) + return false; + + win=CreateWindow("vomp_playback","Vomp Playback Window",WS_VISIBLE | WS_CHILD |WS_CLIPCHILDREN, + 0,0,768,576,win_main,NULL,hinst,NULL); + if (!win) + return FALSE; + ShowWindow(win,SW_SHOWNORMAL); + UpdateWindow(win); + if (remotefnc) {//at least windows XP + /* We want to support MCE Remote controls*/ + RAWINPUTDEVICE remote_control_data[4]; + ZeroMemory(remote_control_data,sizeof(remote_control_data)); + remote_control_data[0].usUsagePage=0xFFBC; + remote_control_data[0].usUsage=0x88; + remote_control_data[0].dwFlags=0; + remote_control_data[1].usUsagePage=0x0C; + remote_control_data[1].usUsage=0x80; + remote_control_data[1].dwFlags=0; + remote_control_data[2].usUsagePage=0x0C; + remote_control_data[2].usUsage=0x01; + remote_control_data[2].dwFlags=0; + remote_control_data[3].usUsagePage=0x01; + remote_control_data[3].usUsage=0x80; + remote_control_data[3].dwFlags=0; + if (dynRegisterRawInputDevices(remote_control_data,4,sizeof(remote_control_data[0]))!=TRUE) { + MessageBox(0,"Registering remote control failed!","Aborting!",0); + return FALSE; + } + + } + return TRUE; +} + + + + + +// ------------------------------------------------------------------------------------------------------------------- + +void shutdown(int code) +{ + if (viewman) + { + viewman->shutdown(); + delete viewman; + logger->log("Core", Log::NOTICE, "ViewMan module shut down"); + } + + if (command) // shut down command here in case views have posted messages + { + command->shutdown(); + delete command; + logger->log("Core", Log::NOTICE, "Command module shut down"); + } + + if (vdr) + { + vdr->shutdown(); + delete vdr; + logger->log("Core", Log::NOTICE, "VDR module shut down"); + } + + if (osd) + { + osd->shutdown(); + delete osd; + logger->log("Core", Log::NOTICE, "OSD module shut down"); + } + + if (audio) + { + audio->shutdown(); + delete audio; + logger->log("Core", Log::NOTICE, "Audio module shut down"); + } + + if (video) + { + video->shutdown(); + delete video; + logger->log("Core", Log::NOTICE, "Video module shut down"); + } + + if (timers) + { + timers->shutdown(); + delete timers; + logger->log("Core", Log::NOTICE, "Timers module shut down"); + } + + if (mtd) + { + mtd->shutdown(); + delete mtd; + logger->log("Core", Log::NOTICE, "MTD module shut down"); + } + + if (led) + { + led->shutdown(); + delete led; + logger->log("Core", Log::NOTICE, "LED module shut down"); + } + + if (remote) + { + remote->shutdown(); + delete remote; + logger->log("Core", Log::NOTICE, "Remote module shut down"); + } + + if (logger) + { + logger->log("Core", Log::NOTICE, "Log module shutting down... bye!\n\n"); + logger->shutdown(); + delete logger; + } + ExitProcess(0); + +} + +// ------------------------------------------------------------------------------------------------------------------- + +ULLONG ntohll(ULLONG a) +{ + return htonll(a); +} + +ULLONG htonll(ULLONG a) +{ + return (((ULLONG)htonl((ULONG)((a<<32)>> 32))<<32) + |(ULONG)htonl(((ULONG) (a >> 32)))); +} +#endif diff --git a/wtextbox.cc b/wtextbox.cc index 1d2deed..66696ff 100644 --- a/wtextbox.cc +++ b/wtextbox.cc @@ -1,68 +1,68 @@ -/* - Copyright 2005 Brian Walton - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "wtextbox.h" - -WTextbox::WTextbox() -{ - int fontHeight = Surface::getFontHeight(); - setDimensions(70, fontHeight); - setDimensions(100,100); - text = NULL; - foreColour = Colour::LIGHTTEXT; - backColour = Colour::VIEWBACKGROUND; - textX = 5; - textY = 2; -} - -WTextbox::~WTextbox() -{ - if (text) delete[] text; //TODO is this needed? -} - -void WTextbox::setText(char* takeText) -{ - int length = strlen(takeText); - text = new char[length + 1]; - strcpy(text, takeText); -} - -void WTextbox::setBackgroundColour(Colour bcolour) -{ - backColour = bcolour; -} - -void WTextbox::setForegroundColour(Colour fcolour) -{ - foreColour = fcolour; -} - -void WTextbox::draw() -{ - fillColour(backColour); - if (text) - drawPara(text, textX, textY, foreColour); -} - -void WTextbox::setTextPos(int x, int y) -{ - textX = x; - textY = y; -} +/* + Copyright 2005 Brian Walton + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "wtextbox.h" + +WTextbox::WTextbox() +{ + int fontHeight = Surface::getFontHeight(); + setDimensions(70, fontHeight); + setDimensions(100,100); + text = NULL; + foreColour = Colour::LIGHTTEXT; + backColour = Colour::VIEWBACKGROUND; + textX = 5; + textY = 2; +} + +WTextbox::~WTextbox() +{ + if (text) delete[] text; //TODO is this needed? +} + +void WTextbox::setText(char* takeText) +{ + int length = strlen(takeText); + text = new char[length + 1]; + strcpy(text, takeText); +} + +void WTextbox::setBackgroundColour(Colour bcolour) +{ + backColour = bcolour; +} + +void WTextbox::setForegroundColour(Colour fcolour) +{ + foreColour = fcolour; +} + +void WTextbox::draw() +{ + fillColour(backColour); + if (text) + drawPara(text, textX, textY, foreColour); +} + +void WTextbox::setTextPos(int x, int y) +{ + textX = x; + textY = y; +} diff --git a/wwss.cc b/wwss.cc index f1a6bb1..25bfa73 100644 --- a/wwss.cc +++ b/wwss.cc @@ -1,321 +1,321 @@ -/* - Copyright 2006 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "wwss.h" - -Wwss::Wwss() -{ - format = Video::NTSC; -} - -Wwss::~Wwss() -{ -} - -void Wwss::setFormat(UCHAR tformat) -{ - format = tformat; -} - -UINT Wwss::gcd(UINT a, UINT b) -{ - UINT t; - while (b != 0) - { - t = b; - b = a % b; - a = t; - } - return a; -} - -UINT Wwss::lcm(UINT a, UINT b) -{ - return (a / gcd(a, b)) * b; -} - -void Wwss::setWide(bool twide) -{ - wide = twide; -} - -void Wwss::draw() -{ - if (format == Video::PAL) drawPAL(); -// else if (format == Video::NTSC) drawNTSC(); -} - -void Wwss::drawPAL() -{ - // The aspect43 and aspect169 codes are not what they should be according to the docs, but these are what work... - // (1 = 111000, = 0 000111) - static UCHAR runIn[] = {1,1,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1}; // 29 pos 0 - static UCHAR startCode[] = {0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,1}; // 24 pos 29 - static UCHAR aspect43[] = {0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0}; // = 0001 4:3 full frame // 24 pos 53 - static UCHAR aspect169[] = {1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,0,1,1,1}; // = 1110 16:9 anamorphic // 24 pos 53 - static UCHAR theRest[] = {0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1, // 60 pos 77 - 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1, - 0,0,0,1,1,1,0,0,0,1,1,1}; - /* - Real PAL pixel frequency: 13.5 MHz - WSS element frequency: 5 MHz - = 2.7 pal pixels per wss element - * 137 wss elements = 369.9 pal pixels (total code width) (round to 370..) - - There is also a 11us gap at the start of the pal raster, but since I don't really have any - idea where our 720 pixels start in the raster I can't calculate an offset. - - PAL line 23 seems to be MVP line 6. - */ - - const UINT Ns = 137; // Num pix src - const UINT Nd = 370; // Num pix dst 359->395 does something. not the right thing, but something. - UINT Nl = lcm(Ns, Nd); // Num pix in lcm - UINT Ss = Nl / Ns; // Source split (how many lcm px = 1 src px) - UINT Sd = Nl / Nd; // Dst split - UCHAR src[Ns]; - - memcpy(&src[0], runIn, 29); - memcpy(&src[29], startCode, 24); - if (wide) memcpy(&src[53], aspect169, 24); - else memcpy(&src[53], aspect43, 24); - memcpy(&src[77], theRest, 60); - - float dst[Nd]; - UINT lcmpxbase = 0; - - for(UINT t = 0; t < Nd; t++) // for every destination pixel - { - dst[t] = 0; - for(UINT lcmpx = lcmpxbase; lcmpx < (lcmpxbase + Sd); lcmpx++) - { - if (src[lcmpx / Ss]) dst[t] += (float)1/Sd; - } - lcmpxbase += Sd; - } - - Colour c; - UINT value; - - for(UINT q = 0; q < Nd; q++) - { - value = (UINT)(dst[q] * 182); // Apparently this is a better number than 255 for the colour value - c.set(value, value, value); - drawPixel(q, 6, c); - } -} - -void Wwss::drawNTSC() -{ -/* - static UCHAR startCode[] = {1,0,0,0,0,0,0}; - static UCHAR aspect43[] = {0}; - static UCHAR aspect169[] = {1}; - static UCHAR theRest[] = {0,0,0,0,0,0,0,0}; - static UCHAR crc43[] = {0,0,0,0,0,0}; - static UCHAR crc169[] = {0,0,1,1,0,0}; -*/ - /* - Real NTSC pixel frequency: 13.5 MHz - WSS bit frequency: 447.443125 kHz - = 30.1714 NTSC pixels per wss bit - * 22 wss bits = 663.7715 NTSC pixels (total code width) (round to 664..) - - There is also a 11.2us gap at the start of the pal raster, but since I don't really have any - idea where our 720 pixels start in the raster I can't calculate an offset. - - PAL line 23 seems to be MVP line 6. - */ - - const UINT Ns = 22; // Num pix src - const UINT Nd = 664; // Num pix dst -// const UINT Nd = 518; // Num pix dst - UINT Nl = lcm(Ns, Nd); // Num pix in lcm - UINT Ss = Nl / Ns; // Source split (how many lcm px = 1 src px) - UINT Sd = Nl / Nd; // Dst split -// UCHAR src[Ns]; - -/* - memcpy(&src[0], startCode, 7); - if (wide) memcpy(&src[7], aspect169, 1); - else memcpy(&src[7], aspect43, 1); - memcpy(&src[8], theRest, 8); - if (wide) memcpy(&src[16], crc169, 6); - else memcpy(&src[16], crc43, 6); -*/ - -static UCHAR src[22] = {1,0, 0,0,0,0,1,1, 0,0,0,0, 0,0,0,0, 0,0,1,0,0,1 }; - - - float dst[Nd]; - UINT lcmpxbase = 0; - - for(UINT t = 0; t < Nd; t++) // for every destination pixel - { - dst[t] = 0; - for(UINT lcmpx = lcmpxbase; lcmpx < (lcmpxbase + Sd); lcmpx++) - { - if (src[lcmpx / Ss]) dst[t] += (float)1/Sd; - } - lcmpxbase += Sd; - } - - Colour c; - UINT value; - -// This one is the real one -/* - for(UINT q = 0; q < Nd; q++) - { - value = (UINT)(dst[q] * 182); // Apparently this is a better number than 255 for the colour value - c.set(value, value, value); - drawPixel(q, 6, c); - } -*/ - -// This one is testing active -for(int yy = 0; yy < 100; yy++) -{ - for(UINT q = 0; q < Nd; q++) - { - value = (UINT)(dst[q] * 182); // Apparently this is a better number than 255 for the colour value - c.set(value, value, value); - drawPixel(q+0, yy, c); - } -} - - - -} - -/* -x6 + x + 1 - -1x6 + 0x5 + 0x4 + 0x3 + 0x2 + 1x1 + 1x0 -= -1 0 0 0 0 1 1 -= -1000011 -key width = 6 - -static UCHAR startCode[] = {1,0}; -static UCHAR aspect43[] = {0,0}; -static UCHAR aspect169[] = {1,0}; -static UCHAR theRest[] = {0,0,0,0,0,0,0,0,0,0,0,0}; -static UCHAR crc43[] = {0,0,0,0,0,0}; -static UCHAR crc169[] = {0,0,1,0,0,1}; - -Message 4:3 - -1000000000000000 - -Message 4:3 augmented - -1000000000000000000000 - -Key - -1000011 - - -Ho ho, polynomial long division. Yeeeeaaahhh I remember -doing *that*. Of course I do. If you know of a faster, -easier, more reliable way of doing this, please let me know. - - - 100 - ________________________ -1000011 ) 1000000000000000000000 - 1000011 - ------- - 0000110 - 0000000 - ------- - 0001100 - - - - - - -Message 16:9 - -1010000000000000 - -Message 4:3 augmented - -1010000000000000000000 - -Key - -1000011 - - 1010011110100011 - ________________________ -1000011 ) 1010000000000000000000 - 1000011 - ------- - 0100110 - 0000000 - ------- - 1001100 - 1000011 - ------- - 0011110 - 0000000 - ------- - 0111100 - 0000000 - ------- - 1111000 - 1000011 - ------- - 1110110 - 1000011 - ------- - 1101010 - 1000011 - ------- - 1010010 - 1000011 - ------- - 0100010 - 0000000 - ------- - 1000100 - 1000011 - ------- - 0001110 - 0000000 - ------- - 0011100 - 0000000 - ------- - 0111000 - 0000000 - ------- - 1110000 - 1000011 - ------- - 1100110 - 1000011 - ------- - 100101 -*/ +/* + Copyright 2006 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "wwss.h" + +Wwss::Wwss() +{ + format = Video::NTSC; +} + +Wwss::~Wwss() +{ +} + +void Wwss::setFormat(UCHAR tformat) +{ + format = tformat; +} + +UINT Wwss::gcd(UINT a, UINT b) +{ + UINT t; + while (b != 0) + { + t = b; + b = a % b; + a = t; + } + return a; +} + +UINT Wwss::lcm(UINT a, UINT b) +{ + return (a / gcd(a, b)) * b; +} + +void Wwss::setWide(bool twide) +{ + wide = twide; +} + +void Wwss::draw() +{ + if (format == Video::PAL) drawPAL(); +// else if (format == Video::NTSC) drawNTSC(); +} + +void Wwss::drawPAL() +{ + // The aspect43 and aspect169 codes are not what they should be according to the docs, but these are what work... + // (1 = 111000, = 0 000111) + static UCHAR runIn[] = {1,1,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1}; // 29 pos 0 + static UCHAR startCode[] = {0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,1}; // 24 pos 29 + static UCHAR aspect43[] = {0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0}; // = 0001 4:3 full frame // 24 pos 53 + static UCHAR aspect169[] = {1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,0,1,1,1}; // = 1110 16:9 anamorphic // 24 pos 53 + static UCHAR theRest[] = {0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1, // 60 pos 77 + 0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1, + 0,0,0,1,1,1,0,0,0,1,1,1}; + /* + Real PAL pixel frequency: 13.5 MHz + WSS element frequency: 5 MHz + = 2.7 pal pixels per wss element + * 137 wss elements = 369.9 pal pixels (total code width) (round to 370..) + + There is also a 11us gap at the start of the pal raster, but since I don't really have any + idea where our 720 pixels start in the raster I can't calculate an offset. + + PAL line 23 seems to be MVP line 6. + */ + + const UINT Ns = 137; // Num pix src + const UINT Nd = 370; // Num pix dst 359->395 does something. not the right thing, but something. + UINT Nl = lcm(Ns, Nd); // Num pix in lcm + UINT Ss = Nl / Ns; // Source split (how many lcm px = 1 src px) + UINT Sd = Nl / Nd; // Dst split + UCHAR src[Ns]; + + memcpy(&src[0], runIn, 29); + memcpy(&src[29], startCode, 24); + if (wide) memcpy(&src[53], aspect169, 24); + else memcpy(&src[53], aspect43, 24); + memcpy(&src[77], theRest, 60); + + float dst[Nd]; + UINT lcmpxbase = 0; + + for(UINT t = 0; t < Nd; t++) // for every destination pixel + { + dst[t] = 0; + for(UINT lcmpx = lcmpxbase; lcmpx < (lcmpxbase + Sd); lcmpx++) + { + if (src[lcmpx / Ss]) dst[t] += (float)1/Sd; + } + lcmpxbase += Sd; + } + + Colour c; + UINT value; + + for(UINT q = 0; q < Nd; q++) + { + value = (UINT)(dst[q] * 182); // Apparently this is a better number than 255 for the colour value + c.set(value, value, value); + drawPixel(q, 6, c); + } +} + +void Wwss::drawNTSC() +{ +/* + static UCHAR startCode[] = {1,0,0,0,0,0,0}; + static UCHAR aspect43[] = {0}; + static UCHAR aspect169[] = {1}; + static UCHAR theRest[] = {0,0,0,0,0,0,0,0}; + static UCHAR crc43[] = {0,0,0,0,0,0}; + static UCHAR crc169[] = {0,0,1,1,0,0}; +*/ + /* + Real NTSC pixel frequency: 13.5 MHz + WSS bit frequency: 447.443125 kHz + = 30.1714 NTSC pixels per wss bit + * 22 wss bits = 663.7715 NTSC pixels (total code width) (round to 664..) + + There is also a 11.2us gap at the start of the pal raster, but since I don't really have any + idea where our 720 pixels start in the raster I can't calculate an offset. + + PAL line 23 seems to be MVP line 6. + */ + + const UINT Ns = 22; // Num pix src + const UINT Nd = 664; // Num pix dst +// const UINT Nd = 518; // Num pix dst + UINT Nl = lcm(Ns, Nd); // Num pix in lcm + UINT Ss = Nl / Ns; // Source split (how many lcm px = 1 src px) + UINT Sd = Nl / Nd; // Dst split +// UCHAR src[Ns]; + +/* + memcpy(&src[0], startCode, 7); + if (wide) memcpy(&src[7], aspect169, 1); + else memcpy(&src[7], aspect43, 1); + memcpy(&src[8], theRest, 8); + if (wide) memcpy(&src[16], crc169, 6); + else memcpy(&src[16], crc43, 6); +*/ + +static UCHAR src[22] = {1,0, 0,0,0,0,1,1, 0,0,0,0, 0,0,0,0, 0,0,1,0,0,1 }; + + + float dst[Nd]; + UINT lcmpxbase = 0; + + for(UINT t = 0; t < Nd; t++) // for every destination pixel + { + dst[t] = 0; + for(UINT lcmpx = lcmpxbase; lcmpx < (lcmpxbase + Sd); lcmpx++) + { + if (src[lcmpx / Ss]) dst[t] += (float)1/Sd; + } + lcmpxbase += Sd; + } + + Colour c; + UINT value; + +// This one is the real one +/* + for(UINT q = 0; q < Nd; q++) + { + value = (UINT)(dst[q] * 182); // Apparently this is a better number than 255 for the colour value + c.set(value, value, value); + drawPixel(q, 6, c); + } +*/ + +// This one is testing active +for(int yy = 0; yy < 100; yy++) +{ + for(UINT q = 0; q < Nd; q++) + { + value = (UINT)(dst[q] * 182); // Apparently this is a better number than 255 for the colour value + c.set(value, value, value); + drawPixel(q+0, yy, c); + } +} + + + +} + +/* +x6 + x + 1 + +1x6 + 0x5 + 0x4 + 0x3 + 0x2 + 1x1 + 1x0 += +1 0 0 0 0 1 1 += +1000011 +key width = 6 + +static UCHAR startCode[] = {1,0}; +static UCHAR aspect43[] = {0,0}; +static UCHAR aspect169[] = {1,0}; +static UCHAR theRest[] = {0,0,0,0,0,0,0,0,0,0,0,0}; +static UCHAR crc43[] = {0,0,0,0,0,0}; +static UCHAR crc169[] = {0,0,1,0,0,1}; + +Message 4:3 + +1000000000000000 + +Message 4:3 augmented + +1000000000000000000000 + +Key + +1000011 + + +Ho ho, polynomial long division. Yeeeeaaahhh I remember +doing *that*. Of course I do. If you know of a faster, +easier, more reliable way of doing this, please let me know. + + + 100 + ________________________ +1000011 ) 1000000000000000000000 + 1000011 + ------- + 0000110 + 0000000 + ------- + 0001100 + + + + + + +Message 16:9 + +1010000000000000 + +Message 4:3 augmented + +1010000000000000000000 + +Key + +1000011 + + 1010011110100011 + ________________________ +1000011 ) 1010000000000000000000 + 1000011 + ------- + 0100110 + 0000000 + ------- + 1001100 + 1000011 + ------- + 0011110 + 0000000 + ------- + 0111100 + 0000000 + ------- + 1111000 + 1000011 + ------- + 1110110 + 1000011 + ------- + 1101010 + 1000011 + ------- + 1010010 + 1000011 + ------- + 0100010 + 0000000 + ------- + 1000100 + 1000011 + ------- + 0001110 + 0000000 + ------- + 0011100 + 0000000 + ------- + 0111000 + 0000000 + ------- + 1110000 + 1000011 + ------- + 1100110 + 1000011 + ------- + 100101 +*/ -- 2.39.2