]> git.vomp.tv Git - vompclient-marten.git/commitdiff
Line endings fix
authorChris Tallon <chris@vomp.tv>
Wed, 20 Dec 2006 15:24:28 +0000 (15:24 +0000)
committerChris Tallon <chris@vomp.tv>
Wed, 20 Dec 2006 15:24:28 +0000 (15:24 +0000)
30 files changed:
Makefile.nmake
audiowin.cc
audiowin.h
dsallocator.cc
dsallocator.h
dssourcefilter.cc
dssourcefilter.h
dssourcepin.cc
dssourcepin.h
mutex.cc
mutex.h
objects.mk
osdwin.cc
osdwin.h
readme.win
remotewin.cc
remotewin.h
surfacewin.cc
threadwin.cc
timers.cc
vaudioselector.cc
vaudioselector.h
vepg.cc
videowin.cc
videowin.h
vompreswin.h
vompwin.rc
winmain.cc
wtextbox.cc
wwss.cc

index d765ef25ba69b2e773afba46436cb6375190c581..013c4768257bb6f0835be524f9afef7b1fc9feb8 100644 (file)
@@ -1,41 +1,41 @@
-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
+
index d13127ecd87722b1bb5e87bdc0e150b8b6ae598e..7bae0bea2f35e19016fdd04eda5a3cbbe4091f5f 100644 (file)
-/*\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
+
+
+
index b297519f77d0f8d115d1d0f6d646c2cd8a74ca00..788548df45507b7449bd296746e2a5973c09abc3 100644 (file)
@@ -1,70 +1,70 @@
-/*\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
+
index 37faf2db6d50abe0df3f82f49b173c3ba0a0dbd7..eb7b8f90aea11cf627e02862e5caf651203fb613 100644 (file)
@@ -109,23 +109,23 @@ HRESULT STDMETHODCALLTYPE DsAllocator::PresentImage(DWORD_PTR userid,VMR9Present
 
 }
 
-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(){
@@ -137,4 +137,4 @@ ULONG STDMETHODCALLTYPE DsAllocator::Release(){
        return ref;
 }
 
-\r
+
index 05ed4da771efa50ab04b5e24b6d30ba72fa3d8fd..32cf5531b036873a50ad16682fe07c600da84bdf 100644 (file)
@@ -46,12 +46,12 @@ public:
        virtual HRESULT STDMETHODCALLTYPE TerminateDevice(DWORD_PTR userid); 
        virtual HRESULT STDMETHODCALLTYPE GetSurface(DWORD_PTR userid,DWORD surfindex,DWORD surfflags, IDirect3DSurface9** surf);
        virtual HRESULT STDMETHODCALLTYPE AdviseNotify(IVMRSurfaceAllocatorNotify9* allnoty);
-       \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:
@@ -71,4 +71,4 @@ protected:
 
 
 
-#endif\r
+#endif
index ff77a0c884a8bb0031901fbb7b4d136e822f572b..13948b738afff3a0724d3a0310ccd0a154d5bd9e 100644 (file)
-/*\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;
+
+}
+
+
index 3535db04384ca0db00a0a60b53894b6ae0ef77a5..9adb656a287b5a4d18d3be9b26c2adce5dcce973 100644 (file)
@@ -44,27 +44,27 @@ public:
 
 /* 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:
@@ -81,4 +81,4 @@ protected:
 
 };
 
-#endif\r
+#endif
index 5d440a7c71d8c7c81ceea7bcbc77e6224832c9b3..a55016ee2d77da5b99d1f188cd067d09d3cb56f4 100644 (file)
-/*\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;
+}
+
+
index 2871592d199566aa86be303e46d4ceed02db2a0b..8b023d395a8512c1a67291e7c227d98c8c74113b 100644 (file)
@@ -46,22 +46,22 @@ public:
        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;};
@@ -70,7 +70,7 @@ public:
 
 
 protected:
-       virtual  HRESULT CheckMediaType(const AM_MEDIA_TYPE *pmt);\r
+       virtual  HRESULT CheckMediaType(const AM_MEDIA_TYPE *pmt);
 
        bool isaudiopin;
        DsSourceFilter *m_pFilter;      
@@ -86,4 +86,4 @@ protected:
 
 
 
-#endif\r
+#endif
index 10171808fe37c128b3a37d9199d1086358fb7549..3ad8ca69c7fcece72b0490129100adf22b1a7a52 100644 (file)
--- a/mutex.cc
+++ b/mutex.cc
@@ -1,51 +1,51 @@
-/*\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
+}
+
diff --git a/mutex.h b/mutex.h
index d989da8025aa30dea8d50dca926b702997b5d89b..882e18b974d6ec702cd3dfceab412409ecadbb8d 100644 (file)
--- a/mutex.h
+++ b/mutex.h
@@ -1,47 +1,47 @@
-/*\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
index 08cf8f809c1d6c8965b06181ce047c14c3d2a5d2..a63c9d9a2f79fd74afb320ab9c2be135b1fddb0c 100644 (file)
@@ -1,17 +1,17 @@
-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
index 58cf1efea99384d9d9d9b949a540861b5b6c8252..9896779ae18d7e68d843913a44703fbe684fd040 100644 (file)
--- a/osdwin.cc
+++ b/osdwin.cc
-/*\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();
+}
+
index 05505e36c3ac767cd01e1db2fb657ee2c3618cd7..13237583ea60210db8dc870adf839199b4da58db 100644 (file)
--- a/osdwin.h
+++ b/osdwin.h
@@ -1,84 +1,84 @@
-/*\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
+
index 86854b5fb77a22c8dfe950efa643d43165e74ab5..d3f676c99244b8d87979a0ac1ef47fcafbeb3fa1 100644 (file)
-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).
+
+
index 28d6abd4a918c7beb088e2964067930992a8f957..879142fb046b15a3e1ae0ee8c6f9ccf36cfd3818 100644 (file)
-/*\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);
+}
+
index 7fe280f0d755d7e5b0a29f686a1171060dcc12cf..d203794c4e8f7a24a09ba27230872d2bc2dec1c0 100644 (file)
@@ -1,61 +1,61 @@
-/*\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
+
index e6b486a43d8ce20abe557c7fe4dd2f7f3d2a59ef..bec6c0eba07aed2dfd841232f76f655727bf0b3f 100644 (file)
-/*\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;
+
+}
+
+
index 4d1daf796b875dc7bf95c2a36120d2680c6fab17..e0c24c4e91d45dad8586aee80ffbde57ab6997ca 100644 (file)
-/*\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
+}
+
index 2980105841a803f4f44d4ad13a42785f8101ae78..b6674df3479585c50d6d0f78c20bcd13ea5f0f29 100755 (executable)
--- a/timers.cc
+++ b/timers.cc
-/*\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, &currentTime);\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, &currentTime);
+#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
+
+*/
index a310df0ac6de4ac738315e470acb0301294eca2f..a277d8b4f6375d4f5f401bc4f77a5931ff168d4d 100644 (file)
-/*\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;
+}
index 5a5c9ea018af4ca92f8cf3d19d19ef59235156d4..1904b53e215d84d59ce5e00a7f3616f6fc679665 100644 (file)
@@ -66,4 +66,3 @@ class VAudioSelector : public View
 };
 
 #endif
-\r
\ No newline at end of file
diff --git a/vepg.cc b/vepg.cc
index 85e1ddde7344a98b500a606e7b569e29fd934a5b..cdd783f4cb57ec881bf41f12fe8c0c746503d593 100644 (file)
--- a/vepg.cc
+++ b/vepg.cc
@@ -1,42 +1,42 @@
-/*\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 -----------------------
@@ -71,322 +71,322 @@ VEpg::VEpg(VVideoLive* v, UINT currentChannel)
   }
 
   // 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(&ltime); // set ltime to now\r
-  ltime = prevHour(&ltime); // 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(&ltime); // set ltime to now
+  ltime = prevHour(&ltime); // 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);
@@ -397,229 +397,229 @@ int VEpg::handleCommand(int command)
       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);
+}
+
index 14d056607a4d5545a04ef57c2fc20112b7a6669b..c27268ecd3ed1cfad0434630f32974a1a3e4826e 100644 (file)
-/*\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
+
+
+
+
index 7e8564424658996de6b1219fee045a1c778cc897..8fbb07cfccd3171c686417d4b1fc8221d6f5c504 100644 (file)
-/*\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
+
+
+
index fdb13b971d3e5b875f5ab326740163febd017427..904fb00520d2ef4fd25dcbf6d3f60f977db8353e 100644 (file)
@@ -1,46 +1,46 @@
-\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
+
index 80c0db55a20cfe15ad3c34e41be682c7f2add915..40f2dd557b6ab58e115087117b648759200ec319 100644 (file)
@@ -1,99 +1,99 @@
-\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
+
+
+
index af85f899da0ab719ca32169ddfb029cfca932a73..94a584a589f922ce87dffddb92a05136a0d01f70 100644 (file)
-/*\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
index 1d2deed5153871300027d947108b59eba147cf84..66696ffea8b9d3067b113c07b5568c581adc9ef7 100644 (file)
@@ -1,68 +1,68 @@
-/*\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;
+}
diff --git a/wwss.cc b/wwss.cc
index f1a6bb116fdad00be745f8d63faf9545d1777690..25bfa739b74a7ac07aa27d278d810e971fa2e5ba 100644 (file)
--- a/wwss.cc
+++ b/wwss.cc
-/*\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
+*/