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