]> git.vomp.tv Git - vompclient-marten.git/commitdiff
Add files specific for raspberry pi
authorMarten Richter <marten.richter@freenet.de>
Thu, 17 May 2012 08:13:43 +0000 (10:13 +0200)
committerMarten Richter <marten.richter@freenet.de>
Thu, 17 May 2012 08:13:43 +0000 (10:13 +0200)
24 files changed:
audiovpe.cc [new file with mode: 0644]
audiovpe.h [new file with mode: 0644]
feed.h [new file with mode: 0644]
ledraspberry.cc [new file with mode: 0644]
ledraspberry.h [new file with mode: 0644]
mtdraspberry.cc [new file with mode: 0644]
mtdraspberry.h [new file with mode: 0644]
osdopengl.cc [new file with mode: 0644]
osdopengl.h [new file with mode: 0644]
remotelinux.cc [new file with mode: 0644]
remotelinux.h [new file with mode: 0644]
shaders/generic__vertex_shader.h [new file with mode: 0644]
shaders/osd__frag_shader.h [new file with mode: 0644]
surfaceopengl.cc [new file with mode: 0644]
surfaceopengl.h [new file with mode: 0644]
threadpandroid.cc [new file with mode: 0644]
threadpandroid.h [new file with mode: 0644]
threadsystem.h [new file with mode: 0644]
videovpeogl.cc [new file with mode: 0644]
videovpeogl.h [new file with mode: 0644]
wjpegcomplex.cc [new file with mode: 0644]
wjpegcomplex.h [new file with mode: 0644]
wjpegsimple.cc [new file with mode: 0644]
wjpegsimple.h [new file with mode: 0644]

diff --git a/audiovpe.cc b/audiovpe.cc
new file mode 100644 (file)
index 0000000..1957b74
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+    Copyright 2004-2005 Chris Tallon, 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#include "audiovpe.h"
+#include "videovpeogl.h"
+#include "log.h"
+
+AudioVPE::AudioVPE()
+{
+  if (instance) return;
+  initted = 0;
+  lastpacketnum=-1;
+  currentpacketnum=-1;
+  streamType = 0;
+  volume = 20;
+  muted = 0;
+  lastAType = MPTYPE_MPEG_AUDIO;
+}
+
+AudioVPE::~AudioVPE()
+{
+}
+
+int AudioVPE::init(UCHAR tstreamType)
+{
+  if (initted) return 0;
+  initted = 1;
+
+// // if ((fdAudio = open("/dev/adec_mpg", O_RDWR | O_NONBLOCK)) < 0) return 0;
+ // if ((fdAudio = open("/dev/adec_mpg", O_WRONLY)) < 0) return 0;
+
+  streamType = tstreamType;
+
+  if (!initAllParams())
+  {
+    shutdown();
+    return 0;
+  }
+
+  unMute();
+
+  // Set the volume variable to what the hardware is set at now
+  int hwvol = -1;
+/*  int hwvolFail = ioctl(fdAudio, AV_GET_AUD_VOLUME, &hwvol);
+  if (!hwvolFail)
+  {
+    volume = 20 - ((hwvol >> 16) & 0xFF);
+    if ((volume < 0) || (volume > 20)) volume = 20;
+  }*/
+
+  return 1;
+}
+
+int AudioVPE::initAllParams()
+{
+  return (setStreamType(streamType) && setChannel() && setSource());
+}
+
+int AudioVPE::shutdown()
+{
+  if (!initted) return 0;
+  initted = 0;
+  //close(fdAudio);
+  return 1;
+}
+
+int AudioVPE::setStreamType(UCHAR type)
+{
+  if (!initted) return 0;
+
+ // if (ioctl(fdAudio, AV_SET_AUD_STREAMTYPE, type) != 0) return 0;
+  return 1;
+}
+
+int AudioVPE::setChannel()
+{
+  if (!initted) return 0;
+
+ // if (ioctl(fdAudio, AV_SET_AUD_CHANNEL, 0) != 0) return 0;
+  return 1;
+}
+
+int AudioVPE::setSource()
+{
+  if (!initted) return 0;
+
+ // if (ioctl(fdAudio, AV_SET_AUD_SRC, 1) != 0) return 0;
+  return 1;
+}
+
+int AudioVPE::sync()
+{
+  if (!initted) return 0;
+
+ // if (ioctl(fdAudio, AV_SET_AUD_SYNC, 2) != 0) return 0;
+  return 1;
+}
+
+int AudioVPE::play()
+{
+  if (!initted) return 0;
+  lastpacketnum=-1;
+  currentpacketnum=-1;
+  ((VideoVPEOGL*) Video::getInstance())->initMuxer();
+
+  //if (ioctl(fdAudio, AV_SET_AUD_PLAY, 0) != 0) return 0;
+  return 1;
+}
+
+int AudioVPE::stop()
+{
+  if (!initted) return 0;
+  ((VideoVPEOGL*) Video::getInstance())->deinitMuxer();
+
+  //if (ioctl(fdAudio, AV_SET_AUD_RESET, 0x11) != 0) return 0;
+  return 1;
+}
+
+int AudioVPE::mute()
+{
+  if (!initted) return 0;
+
+//  if (ioctl(fdAudio, AV_SET_AUD_MUTE, 1) != 0) return 0;
+  Log::getInstance()->log("Audio", Log::DEBUG, "MUTE MUTE MUTE");
+
+  muted = 1;
+  return 1;
+}
+
+int AudioVPE::unMute()
+{
+  if (!initted) return 0;
+
+//  if (ioctl(fdAudio, AV_SET_AUD_MUTE, 0) != 0) return 0;
+  Log::getInstance()->log("Audio", Log::DEBUG, "MUTE OFF OFF OFF");
+
+  muted = 0;
+  return 1;
+}
+
+int AudioVPE::pause()
+{
+  if (!initted) return 0;
+
+ // if (ioctl(fdAudio, AV_SET_AUD_PAUSE, 1) != 0) return 0;
+  return 1;
+}
+
+int AudioVPE::unPause()
+{
+  if (!initted) return 0;
+
+ // if (ioctl(fdAudio, AV_SET_AUD_UNPAUSE, 1) != 0) return 0;
+  return 1;
+}
+
+int AudioVPE::reset()
+{
+  if (!initted) return 0;
+//test();
+  Log::getInstance()->log("Audio", Log::DEBUG, "reset called");
+  ((VideoVPEOGL*) Video::getInstance())->deinitMuxer();
+
+//  if (ioctl(fdAudio, AV_SET_AUD_RESET, 0x11) != 0) return 0;
+//  Log::getInstance()->log("Audio", Log::DEBUG, "reset back");
+ // if (ioctl(fdAudio, AV_SET_AUD_PLAY, 0) != 0) return 0;
+
+  doMuting();
+  return 1;
+}
+
+int AudioVPE::setVolume(int tvolume)
+{
+  // parameter: 0 for silence, 20 for full
+  if ((tvolume < 0) || (tvolume > 20)) return 0;
+
+// volume = 2 * (20 - volume);
+// Right, that one was rubbish... 0-10 were almost
+// inaudible, 11-20 did what should have been done
+// over the whole 0-20 range
+
+  tvolume = 20 - tvolume;
+
+  audio_volume Avolume;
+  Avolume.frontleft = tvolume + Aoffset.frontleft;
+  Avolume.frontright = tvolume + Aoffset.frontright;
+  Avolume.rearleft = tvolume + Aoffset.rearleft;
+  Avolume.rearright = tvolume + Aoffset.rearright;
+  Avolume.center = tvolume + Aoffset.center;
+  Avolume.lfe = tvolume + Aoffset.lfe;
+
+//  if (ioctl(fdAudio, AV_SET_AUD_VOLUME, &Avolume) != 0) return 0;
+
+//  unsigned long vol = (tvolume << 24) | (tvolume << 16);
+//
+//  Log::getInstance()->log("Audio", Log::DEBUG, "%lx", vol);
+//  Log::getInstance()->log("Audio", Log::DEBUG, "%i", tvolume);
+
+//  if (ioctl(fdAudio, AV_SET_AUD_VOLUME, &vol) != 0) return 0;
+  return 1;
+}
+
+#ifdef DEV
+int AudioVPE::test()
+{
+//  ULLONG stc = 0;
+//  return ioctl(fdAudio, AV_SET_AUD_STC, &stc);
+
+/*  aud_sync_parms_t a;
+  a.parm1 = 0;
+  a.parm2 = 0;
+*/
+//  int b = ioctl(fdAudio, AV_SET_AUD_DISABLE_SYNC, &a);
+
+
+  /*OK*/ //printf("Audio sync disable = %i\n", b);
+
+  return 1;
+
+
+}
+#endif
+
+void AudioVPE::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
+{
+  packet = mplist.front();
+}
+
+UINT AudioVPE::DeliverMediaSample(UCHAR* buffer, UINT* samplepos)
+{/*
+       VideoVPEOGL *video=(VideoVPEOGL*)Video::getInstance();
+       //Log::getInstance()->log("Audio", Log::DEBUG, "lastpacket %d lastbuddypacket %d currentpacket %d",lastpacketnum,video->getLastPacketNum(),packet.index);
+       currentpacketnum=packet.index;
+  if (lastpacketnum!=-1 && packet.index-1!=lastpacketnum && packet.index-1>video->getLastPacketNum()) return 0; //Not in order
+
+  //format pes
+  switch (packet.type) {
+         case MPTYPE_MPEG_AUDIO:
+                buffer[packet.pos_buffer + 3]=0xc0; break;
+         case MPTYPE_AC3:
+                 buffer[packet.pos_buffer +buffer[packet.pos_buffer+8]+9]=0x80;
+                 buffer[packet.pos_buffer + 3]=0xbd; break;
+                 break;
+         default:
+         case MPTYPE_AC3_PRE13://Not tested no recording availiable
+                 buffer[packet.pos_buffer + 3]=0xbd; break;
+                 break;
+  };
+
+   if (packet.type!=lastAType && lastpacketnum!=-1){//Format Change //Push data out !
+      video->deinitMuxer();
+         lastAType=packet.type;
+         video->initMuxer();
+  }
+  lastAType=packet.type;
+
+
+ /* Mutex *mutex=video->getMuxMutex();
+  mutex->Lock();
+  FILE *muxout=video->getMuxFile();
+  if (!muxout) {mutex->Unlock(); return 0;}*
+  int written=0;
+  //written=fwrite(buffer + packet.pos_buffer,1,packet.length,muxout);
+  written=video->WriteOutTS(buffer + packet.pos_buffer,packet.length,packet.type);
+  lastpacketnum=packet.index;
+  
+  //mutex->Unlock();
+
+   //Log::getInstance()->log("Audio", Log::DEBUG, "wrote %d bytes to mux",written);
+  
+  if (written == (int)packet.length) { *samplepos = 0; return 1;}
+  if (written <= 0) {
+         return 0;
+  }
+  *samplepos = written;*/
+  // Handle a partial write. Is this possible? Should we bother? No!
+  return 1;
+}
+
+void AudioVPE::ResetTimeOffsets()
+{
+}
diff --git a/audiovpe.h b/audiovpe.h
new file mode 100644 (file)
index 0000000..b9be7ac
--- /dev/null
@@ -0,0 +1,84 @@
+/*\r
+    Copyright 2004-2005 Chris Tallon, 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+*/\r
+\r
+#ifndef AUDIOVPE_H\r
+#define AUDIOVPE_H\r
+\r
+#include <stdio.h>\r
+#include <unistd.h>\r
+#include <fcntl.h>\r
+#include <sys/ioctl.h>\r
+\r
+#include "defines.h"\r
+#include "audio.h"\r
+\r
+\r
+\r
+\r
+\r
+class AudioVPE : public Audio\r
+{\r
+  public:\r
+    AudioVPE();\r
+    virtual ~AudioVPE();\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
+    bool supportsAc3() { return true; }\r
+\r
+    //Writing Data to Audiodevice\r
+    virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);\r
+    virtual UINT DeliverMediaSample(UCHAR* buffer, UINT *samplepos);\r
+    virtual long long SetStartOffset(long long curreftime, bool *rsync) { return 0; };\r
+    virtual void ResetTimeOffsets();\r
+\r
+       int getLastPacketNum() {return lastpacketnum;}; \r
+       int getCurrentPacketNum(){return currentpacketnum;};\r
+       UCHAR getLastAType() {return lastAType;}\r
+\r
+#ifdef DEV\r
+    int test();\r
+#endif\r
+\r
+  private:\r
+    int initAllParams();\r
+    UCHAR streamType;\r
+       UCHAR lastAType;\r
+    int lastpacketnum;\r
+       int currentpacketnum;\r
+\r
+    MediaPacket packet;\r
+    UINT packetpos;\r
+};\r
+\r
+#endif\r
diff --git a/feed.h b/feed.h
new file mode 100644 (file)
index 0000000..5f6c14b
--- /dev/null
+++ b/feed.h
@@ -0,0 +1,29 @@
+/*\r
+    Copyright 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+*/\r
+\r
+#ifndef FEED_H\r
+#define FEED_H\r
+\r
+class Feed{\r
+public:\r
+       virtual void SignalFeeder()=0;\r
+};\r
+\r
+#endif\r
diff --git a/ledraspberry.cc b/ledraspberry.cc
new file mode 100644 (file)
index 0000000..bda573a
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+    Copyright 2004-2005 Chris Tallon, 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#include "ledraspberry.h"
+
+LedRaspberry::LedRaspberry()
+{
+  initted = 0;
+}
+
+LedRaspberry::~LedRaspberry()
+{
+}
+
+int LedRaspberry::init(int tdevice)
+{
+  if (initted) return 0;
+  initted = 1;
+  return 1;
+}
+
+int LedRaspberry::shutdown()
+{
+  if (!initted) return 0;
+  initted = 0;
+  return 1;
+}
+
+int LedRaspberry::on()
+{
+  if (!initted) return 0;
+  return 0;
+}
+
+int LedRaspberry::off()
+{
+  if (!initted) return 0;
+  return 0;
+}
diff --git a/ledraspberry.h b/ledraspberry.h
new file mode 100644 (file)
index 0000000..6e394cb
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+    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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#ifndef LEDRASPBERRY_H
+#define LEDRASPBERRY_H
+
+#include <stdio.h>
+
+#include "led.h"
+
+class LedRaspberry : public Led
+{
+  public:
+    LedRaspberry();
+    virtual ~LedRaspberry();
+
+    int init(int device);
+    int shutdown();
+
+    int on();
+    int off();
+
+  private:
+    int initted;
+};
+
+#endif
diff --git a/mtdraspberry.cc b/mtdraspberry.cc
new file mode 100644 (file)
index 0000000..c46abff
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    VOMP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with VOMP; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#include "mtdraspberry.h"
+#include "video.h"
+
+MtdRaspberry::MtdRaspberry()
+{
+  initted = 0;
+}
+
+MtdRaspberry::~MtdRaspberry()
+{
+}
+
+int MtdRaspberry::init()
+{
+  if (initted) return 0;
+  initted = 1;
+  return 1;
+}
+
+int MtdRaspberry::shutdown()
+{
+  if (!initted) return 0;
+  initted = 0;
+  return 1;
+}
+
+short MtdRaspberry::getPALorNTSC()
+{
+  return Video::PAL; //Fixme!
+}
+
diff --git a/mtdraspberry.h b/mtdraspberry.h
new file mode 100644 (file)
index 0000000..5a80854
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+    Copyright 2004-2005 Chris Tallon, 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#ifndef MTDRASPBERRY_H
+#define MTDRASPBERRY_H
+
+#include "mtd.h"
+
+class MtdRaspberry: public Mtd {
+public:
+       MtdRaspberry();
+       virtual ~MtdRaspberry();
+
+       virtual int init();
+       virtual int shutdown();
+
+       virtual short getPALorNTSC();
+
+private:
+       int initted;
+};
+
+#endif
+
diff --git a/osdopengl.cc b/osdopengl.cc
new file mode 100644 (file)
index 0000000..27008d0
--- /dev/null
@@ -0,0 +1,677 @@
+/*\r
+    Copyright 2004-2005 Chris Tallon, 2006,2011-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+*/\r
+\r
+\r
+#include "osdopengl.h"\r
+#include "mtd.h"\r
+#include "videovpeogl.h"\r
+#include "surfaceopengl.h"\r
+\r
+\r
+#include "message.h"\r
+#include "command.h"\r
+\r
+#include "shaders/generic__vertex_shader.h"\r
+#include "shaders/osd__frag_shader.h"\r
+\r
+#define  BACKBUFFER_WIDTH 1920\r
+#define  BACKBUFFER_HEIGHT 1080\r
+\r
+\r
+\r
+long long getTimeMS() {\r
+       struct timespec ts;\r
+       clock_gettime(CLOCK_MONOTONIC, &ts);\r
+       return ts.tv_sec*1000+ts.tv_nsec/1000000LL;\r
+}\r
+\r
+\r
+\r
+OsdOpenGL::OsdOpenGL()\r
+{\r
+  glmutex.Lock();\r
+\r
+  external_driving=false;\r
+\r
+  lastrendertime=getTimeMS();\r
+  display_height=0;\r
+  display_width=0;\r
+  osd_shader=0;\r
+  gen_shader=0;\r
+  osd_program=0;\r
+\r
+\r
+  \r
+}\r
+\r
+OsdOpenGL::~OsdOpenGL()\r
+{\r
+\r
+  if (initted) \r
+  {\r
+         threadStop();\r
+               shutdown();\r
+  }\r
+\r
+\r
+  glmutex.Unlock();\r
+}\r
+\r
+int OsdOpenGL::getFD()\r
+{\r
+  if (!initted) return 0;\r
+  return fdOsd;\r
+}\r
+\r
+Surface * OsdOpenGL::createNewSurface() {\r
+       return (Surface*)new SurfaceOpenGL();\r
+}\r
+\r
+int OsdOpenGL::init(void* device)\r
+{\r
+  if (initted) return 0;\r
+  Video* video = Video::getInstance();\r
+   //window=*((HWND*)device);\r
+  \r
+   // May be this device specific part should go to a device specific child class\r
+\r
+   //init broadcom chipset (Move to video?)\r
+   bcm_host_init();\r
+\r
+   //First get connection to egl\r
+   egl_display=eglGetDisplay(EGL_DEFAULT_DISPLAY);\r
+\r
+   if (egl_display==EGL_NO_DISPLAY) {\r
+          Log::getInstance()->log("OSD", Log::WARN, "Could not get egl display!",eglGetError());\r
+          return 0;\r
+   }\r
+\r
+   if (eglInitialize(egl_display, NULL, NULL)==EGL_FALSE) {\r
+          Log::getInstance()->log("OSD", Log::WARN, "Initialising display failed! %d",eglGetError());\r
+          return 0;\r
+   }\r
+\r
+   const EGLint attributs[]={\r
+                EGL_RED_SIZE,8,EGL_GREEN_SIZE, 8,EGL_BLUE_SIZE, 8,EGL_ALPHA_SIZE, 8,\r
+         EGL_SURFACE_TYPE, EGL_WINDOW_BIT,\r
+         EGL_CONFORMANT, EGL_OPENGL_ES2_BIT,\r
+         EGL_NONE\r
+   }; // Here, we might have to select the resolution!\r
+\r
+   EGLConfig ourconfig; //maybe accept more configs?\r
+   EGLint number;\r
+\r
+   if (eglChooseConfig(egl_display, attributs, &ourconfig, 1, &number)==EGL_FALSE) {\r
+          Log::getInstance()->log("OSD", Log::WARN, "Choosing egl config failed! %d",eglGetError());\r
+          return 0;\r
+   }\r
+\r
+   const EGLint attr_context[]={\r
+                  EGL_CONTEXT_CLIENT_VERSION,2,\r
+          EGL_NONE\r
+      };\r
+\r
+   egl_context=eglCreateContext(egl_display,ourconfig,EGL_NO_CONTEXT,attr_context);\r
+   if (egl_context==EGL_NO_CONTEXT) {\r
+          Log::getInstance()->log("OSD", Log::WARN, "Creating egl context failed! %d",eglGetError());\r
+          return 0;\r
+   }\r
+\r
+   // warning broadcom specific, get display size!\r
+   display_width=display_height=0;\r
+   if (graphics_get_display_size(0, &display_width, &display_height)<0) {\r
+          Log::getInstance()->log("OSD", Log::WARN, "Getting display size failed! (BCM API) ");\r
+          return 0;\r
+   }\r
+   Log::getInstance()->log("OSD", Log::NOTICE, "Displaysize is %d x %d ",display_width, display_height);\r
+   VC_RECT_T dst_rect ={0,0,display_width,display_height};\r
+   VC_RECT_T src_rect={0,0,display_width<<16,display_height<<16};\r
+   DISPMANX_DISPLAY_HANDLE_T bcm_display;\r
+   DISPMANX_ELEMENT_HANDLE_T bcm_element;\r
+   DISPMANX_UPDATE_HANDLE_T  bcm_update;\r
+\r
+\r
+   bcm_display=vc_dispmanx_display_open(0);\r
+   bcm_update=vc_dispmanx_update_start(0);\r
+   bcm_element=vc_dispmanx_element_add(bcm_update,bcm_display,\r
+         0,&dst_rect, 0,\r
+         &src_rect,DISPMANX_PROTECTION_NONE,0, 0, (DISPMANX_TRANSFORM_T) 0);\r
+\r
+   vc_dispmanx_update_submit_sync(bcm_update);\r
+   static EGL_DISPMANX_WINDOW_T nativewindow;\r
+   nativewindow.element=bcm_element;\r
+   nativewindow.height=display_height;\r
+   nativewindow.width=display_width;\r
+\r
+   egl_surface = eglCreateWindowSurface(egl_display,ourconfig, &nativewindow,NULL );\r
+   if (egl_surface==EGL_NO_SURFACE) {\r
+          Log::getInstance()->log("OSD", Log::WARN, "Creating egl window surface failed!");\r
+          return 0;\r
+   }\r
+\r
+   if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) {\r
+          Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed");\r
+                  return 0;\r
+   }\r
+   // Test stuff\r
+\r
+\r
+\r
+  //Now we will create the Screen\r
+  screen = (Surface*) new SurfaceOpenGL(Surface::SCREEN);\r
+\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
+  //glGenBuffers(1, &vB);\r
+  //glGenBuffers(1, &iB);\r
+\r
+  //Preparing the Shaders\r
+\r
+  gen_shader=CreateShader(generic_vertex_shader, GL_VERTEX_SHADER);\r
+  osd_shader=CreateShader(osd_frag_shader, GL_FRAGMENT_SHADER);\r
+\r
+\r
+  osd_program=glCreateProgram();\r
+  if (osd_program==0) {\r
+         Log::getInstance()->log("OSD", Log::WARN, "Creating glsl program failed!%d",glGetError());\r
+      return 0;\r
+  }\r
+  glAttachShader(osd_program,gen_shader);\r
+  glAttachShader(osd_program,osd_shader);\r
+  glBindAttribLocation(osd_program,0,"vec_pos");\r
+  glBindAttribLocation(osd_program,1,"tex_coord");\r
+\r
+  osd_sampler_loc=glGetUniformLocation(osd_program,"texture");\r
+\r
+  glLinkProgram(osd_program);\r
+  GLint link_status;\r
+  glGetShaderiv(osd_program,GL_LINK_STATUS, &link_status);\r
+\r
+  if (!link_status) {\r
+         char buffer[1024];\r
+         glGetProgramInfoLog(osd_program,1024,NULL,buffer);\r
+         Log::getInstance()->log("OSD", Log::WARN, "Compiling Programm failed!");\r
+         Log::getInstance()->log("OSD", Log::WARN, "%s",buffer);\r
+         glDeleteProgram(osd_program);\r
+         return 0;\r
+  }\r
+\r
+  glClearColor(0.0f,0.0f,0.0f,1.f);\r
+\r
+  eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );\r
+  glmutex.Unlock();\r
+  threadStart();\r
+\r
+  return 1;\r
+}\r
+\r
+\r
+GLuint OsdOpenGL::CreateShader(const GLchar * source, GLenum type)\r
+{\r
+       GLuint ret_shad=0;\r
+\r
+       ret_shad=glCreateShader(type);\r
+       if (ret_shad==0 ) {\r
+               Log::getInstance()->log("OSD", Log::WARN, "Creating Shader failed! %d",glGetError());\r
+               return 0;\r
+       }\r
+       glShaderSource(ret_shad,1,&source,NULL);\r
+       glCompileShader(ret_shad);\r
+       GLint comp_status;\r
+       glGetShaderiv(ret_shad,GL_COMPILE_STATUS, &comp_status);\r
+\r
+       if (!comp_status) {\r
+               char buffer[1024];\r
+               Log::getInstance()->log("OSD", Log::WARN, "Compiling Shader failed!");\r
+               glGetShaderInfoLog(ret_shad,1024,NULL,buffer);\r
+               Log::getInstance()->log("OSD", Log::WARN, "%s",buffer);\r
+               glDeleteShader(ret_shad);\r
+               return 0;\r
+       }\r
+       return ret_shad;\r
+}\r
+\r
+       \r
+void OsdOpenGL::InitVertexBuffer(float  scalex,float scaley)\r
+{\r
+  Video* video=Video::getInstance();\r
+  float texx=((float)video->getScreenWidth())/1024.f;\r
+  float texy=((float)video->getScreenHeight())/1024.f;\r
+  OSDCOLOR osdcolor={1.f,1.f,1.f,1.f};\r
+\r
+ // osdvertices[0].c=osdcolor;\r
+  osdvertices[0].x= (scalex);\r
+  osdvertices[0].y=-scaley;\r
+  osdvertices[0].z=0.5;\r
+  osdvertices[0].u=texx;\r
+  osdvertices[0].v=texy;\r
+ // osdvertices[1].c=osdcolor;\r
+  osdvertices[1].x=(scalex);\r
+  osdvertices[1].y=(scaley);\r
+  osdvertices[1].z=0.5f;\r
+  osdvertices[1].u=texx;\r
+  osdvertices[1].v=0.f;\r
+  //  osdvertices[0].c=osdcolor;\r
+  osdvertices[2].x=(-scalex);\r
+  osdvertices[2].y=-scaley;\r
+  osdvertices[2].z=0.5f;\r
+  osdvertices[2].u=0.f;\r
+  osdvertices[2].v=texy;\r
+ // osdvertices[3].c=osdcolor;\r
+  osdvertices[3].x=-scalex;\r
+  osdvertices[3].y=(scaley);\r
+  osdvertices[3].z=0.5f;\r
+  osdvertices[3].u=0.f;\r
+  osdvertices[3].v=0.f;\r
+  \r
+  osdindices[0]=0;\r
+  osdindices[1]=1;\r
+  osdindices[2]=2;\r
+  osdindices[3]=0;\r
+  osdindices[4]=2;\r
+  osdindices[5]=3;\r
+\r
+\r
+\r
+\r
+ // glBindBuffer(GL_ARRAY_BUFFER, vB);\r
+ // glBufferData(GL_ARRAY_BUFFER, sizeof(osdvertices), osdvertices, GL_STATIC_DRAW);\r
+\r
+\r
+ // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iB);\r
+  //glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(osdindices), osdindices, GL_STATIC_DRAW);\r
+\r
+\r
+\r
+  return;\r
+}\r
+\r
+int OsdOpenGL::shutdown()\r
+{\r
+  if (!initted) return 0;\r
+  initted = 0;\r
+\r
+\r
+  if (osd_shader!=0) glDeleteShader(osd_shader);\r
+  if (gen_shader!=0) glDeleteShader(gen_shader);\r
+  if (osd_program!=0) glDeleteProgram(osd_program);\r
+\r
+  glClear(GL_COLOR_BUFFER_BIT);\r
+  eglSwapBuffers(egl_display, egl_surface);\r
+  eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );\r
+  eglDestroySurface(egl_display,egl_surface);\r
+  eglDestroyContext(egl_display,egl_context);\r
+  eglTerminate(egl_display );\r
+\r
+  return 1;\r
+}\r
+\r
+void OsdOpenGL::screenShot(const char* fileName)\r
+{\r
+  screen->screenShot(fileName);\r
+}\r
+\r
+void OsdOpenGL::threadMethod()\r
+{\r
+       // We have to claim the gl context for this thread\r
+       //glmutex.Lock();\r
+\r
+       //glmutex.Unlock();\r
+       while (true)\r
+       {\r
+               unsigned int waittime=10;\r
+               if (initted){\r
+               //      if (evrstate==EVR_pres_off || evrstate==EVR_pres_pause)\r
+               //      {\r
+                               Render();\r
+                               //TODO get surfaces from Video object\r
+       /*              } else if (evrstate==EVR_pres_started)\r
+                       {\r
+                               LPDIRECT3DSURFACE9 surf;\r
+                               if (dsallocator) dsallocator->GetNextSurface(&surf,&waittime);\r
+                               if (surf==NULL)\r
+                               {\r
+                                       Render();\r
+                               }\r
+                               else\r
+                               {\r
+                                       RenderDS(surf);\r
+                                       surf->Release();\r
+                                       if (dsallocator) dsallocator->DiscardSurfaceandgetWait(&waittime);\r
+                               }\r
+                       }*/\r
+               }\r
+               threadCheckExit();\r
+               if (waittime!=0) MILLISLEEP(min(10,waittime));\r
+               //Sleep(1);\r
+       }\r
+       //eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );\r
+}\r
+\r
+\r
+void OsdOpenGL::threadPostStopCleanup()\r
+{\r
+       //Doing nothing\r
+       //goo;\r
+}\r
+\r
+\r
+// This function is called from the WinMain function in order to get Screen updates\r
+void OsdOpenGL::Render()\r
+{\r
+       if (!initted) return ;\r
+       if (external_driving) {\r
+        long long time1=getTimeMS();\r
+\r
+               if ((time1-lastrendertime)>200) {//5 fps for OSD updates are enough, avoids tearing\r
+                       InternalRendering(NULL);\r
+                       lastrendertime=getTimeMS();\r
+        } else {\r
+                  //Sleep(5); //Sleep for 5 ms, in order to avoid blocking the other threads\r
+        }\r
+       } else {\r
+               struct timespec ts;\r
+               clock_gettime(CLOCK_MONOTONIC, &ts);\r
+               long long time1=ts.tv_sec*1000+ts.tv_nsec/1000000LL;\r
+               if ((time1-lastrendertime)>50) {//10 fps for OSD updates are enough, avoids tearing\r
+                       InternalRendering(NULL);\r
+                       lastrendertime=getTimeMS();\r
+               } else {\r
+                       //Sleep(5);\r
+               \r
+               }\r
+               \r
+       }\r
+}\r
+\r
+void OsdOpenGL::RenderDS(GLuint  present){\r
+       if (!initted) return; \r
+       if (external_driving) {\r
+               InternalRendering(present);\r
+               lastrendertime=getTimeMS();\r
+       }\r
+}\r
+\r
+\r
+void OsdOpenGL::InternalRendering(GLuint  present){\r
+    BeginPainting();\r
+  /*  HRESULT losty=d3ddevice->TestCooperativeLevel();\r
+    if (losty==D3DERR_DEVICELOST) {\r
+        //Sleep(10);\r
+               EndPainting();\r
+        return; //Device Lost\r
+    }\r
+    if (losty==D3DERR_DEVICENOTRESET){\r
+          EndPainting();\r
+       DoLost();\r
+       return;\r
+    }\r
+       WaitForSingleObject(event,INFINITE);\r
+       */\r
+   \r
+       \r
+/*\r
+    LPDIRECT3DSURFACE9 targetsurf;\r
+       if (swappy)\r
+       {\r
+               targetsurf=swapsurf;\r
+               d3ddevice->SetRenderTarget(0,swapsurf);//Stupid VMR manipulates the render target\r
+       } \r
+       else\r
+       {\r
+               targetsurf=d3drtsurf;\r
+               d3ddevice->SetRenderTarget(0,d3drtsurf);//Stupid VMR manipulates the render target\r
+       }\r
+       D3DSURFACE_DESC targetdesc;\r
+       targetsurf->GetDesc(&targetdesc);\r
+\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()* targetdesc.Width,\r
+                               /*video->getScreenHeight()*targetdesc.Height};\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,targetsurf ,&destrect,filter_type);\r
+\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
+\r
+\r
+       //InitVertexBuffer(display_width,display_height);\r
+    InitVertexBuffer(1.f,1.f);\r
+\r
+\r
+       glViewport(0, 0, display_width,display_height);\r
+\r
+       glClear(GL_COLOR_BUFFER_BIT);\r
+       glUseProgram(osd_program);\r
+\r
+       glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), osdvertices);\r
+       glEnableVertexAttribArray(0);\r
+       glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), &(osdvertices[0].u));\r
+       glEnableVertexAttribArray(1);\r
+\r
+\r
+\r
+\r
+       glActiveTexture(GL_TEXTURE0);\r
+       glBindTexture(GL_TEXTURE_2D,((SurfaceOpenGL*)screen)->getTexture());\r
+\r
+       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);\r
+       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);\r
+\r
+       glUniform1i(osd_sampler_loc,0);\r
+\r
+       glEnable(GL_BLEND);\r
+       glBlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,GL_ZERO,GL_ONE);\r
+\r
+/*     glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX),\r
+                       (GLvoid*)(((char*)osdvertices)+3*sizeof(GLfloat)));\r
+       glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX),\r
+                       (GLvoid*)(((char*)osdvertices)+3*sizeof(GLfloat)+sizeof(OSDCOLOR)));*/\r
+       //glDisable(GL_LIGHTING);\r
+       //glEnable(GL_TEXTURE_2D);\r
+       //glEnable(GL_BLEND);\r
+    //glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
+    //glDepthFunc(GL_ALWAYS);\r
+    //glDisable(GL_DEPTH_TEST);\r
+    //glDisable(GL_STENCIL_TEST);\r
+    //glDisable(GL_CULL_FACE);\r
+\r
+\r
+\r
+/*\r
+       glActiveTexture(GL_TEXTURE0);\r
+       glBindTexture(GL_TEXTURE_2D,((SurfaceOpenGL*)screen)->getTexture());\r
+       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);\r
+       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);*/\r
+//     glUniform1i(mTextureUniformHandle, present);\r
+\r
+\r
+\r
+       glDrawArrays(GL_TRIANGLE_STRIP, 0,  4);\r
+\r
+       //glDrawElements(GL_TRIANGLES, sizeof(osdindices)/sizeof(osdindices[0]), GL_UNSIGNED_BYTE, 0);\r
+\r
+\r
+\r
+\r
+/*     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), 0);\r
+       glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX),\r
+                               (GLvoid*)(3*sizeof(GLfloat)));\r
+       glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX),\r
+                       (GLvoid*)(3*sizeof(GLfloat)+sizeof(OSDCOLOR)));*/\r
+\r
+       //glDisable(GL_BLEND);\r
+       //glDisable(GL_TEXTURE_2D);\r
+       \r
+       //Show it to the user!\r
+       eglSwapBuffers(egl_display, egl_surface);\r
+\r
+       EndPainting();\r
+\r
+       \r
+//     if (!external_driving) {\r
+//             Sleep(4);//The User can wait for 4 milliseconds to see his changes\r
+//     }\r
+}\r
+\r
+bool OsdOpenGL::DoLost(){\r
+       /*\r
+       Log::getInstance()->log("OSD", Log::WARN, "Direct3D Device Lost! Reobtaining...");\r
+       ResetEvent(event);\r
+       if (external_driving && dsallocator!=NULL) {\r
+               dsallocator->LostDevice(d3ddevice,d3d); //Propagate the information through DS\r
+       }\r
+       //First we free up all resources\r
+       Video* video = Video::getInstance();\r
+       ((SurfaceWin*)screen)->ReleaseSurface();\r
+       if (d3drtsurf) d3drtsurf->Release();\r
+    d3drtsurf=NULL;\r
+       D3DPRESENT_PARAMETERS d3dparas;\r
+       ZeroMemory(&d3dparas,sizeof(d3dparas));\r
+       d3dparas.BackBufferWidth=BACKBUFFER_WIDTH;\r
+       d3dparas.BackBufferHeight=BACKBUFFER_HEIGHT;\r
+       d3dparas.Windowed=TRUE;\r
+       d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;\r
+\r
+       if (swapsurf) {swapsurf->Release();swapsurf=NULL;};\r
+       if (swappy) {swappy->Release();swappy=NULL;};\r
+\r
+       if (d3ddevice->Reset(&d3dparas)!=D3D_OK){\r
+               return false;\r
+       }\r
+    d3ddevice->GetRenderTarget(0,&d3drtsurf);\r
+       if (d3ddevman) d3ddevman->ResetDevice(d3ddevice,dxvatoken);\r
+       //InitVertexBuffer();\r
+    //Redraw Views, Chris could you add a member function to BoxStack, so that\r
+       // I can cause it to completely redraw the Views?\r
+       // Otherwise the OSD would be distorted after Device Lost\r
+       // FIXME\r
+       \r
+       SetEvent(event);\r
+\r
+\r
+       screen->create(video->getScreenWidth(), video->getScreenHeight());\r
+       screen->display();*/\r
+       \r
+       return true;\r
+\r
+}\r
+\r
+\r
+void OsdOpenGL::BeginPainting() {//We synchronize calls to d3d between different threads\r
+       glmutex.Lock();\r
+       if (initted) {\r
+               if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) {\r
+                       Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed in thread %d",eglGetError());\r
+                       return;\r
+               }\r
+       }\r
+}\r
+\r
+void OsdOpenGL::EndPainting() {\r
+       eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );\r
+       glmutex.Unlock();\r
+}\r
+\r
+void OsdOpenGL::setExternalDriving(/*DsAllocator* dsall,*/unsigned int  width, unsigned height) {\r
+       /*\r
+       if (swappy)\r
+       {\r
+               BeginPainting();\r
+               d3ddevice->StretchRect(swapsurf,NULL,d3drtsurf,NULL,filter_type);\r
+               LPDIRECT3DSWAPCHAIN9 temp=swappy;\r
+               LPDIRECT3DSURFACE9 tempsurf=swapsurf;\r
+               swappy=NULL;\r
+               swapsurf=NULL;\r
+               EndPainting();\r
+               tempsurf->Release();\r
+               temp->Release();\r
+       }\r
+\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
+       BeginPainting();\r
+\r
+       if (width>BACKBUFFER_WIDTH || height>BACKBUFFER_HEIGHT) \r
+       {\r
+               D3DPRESENT_PARAMETERS d3dparas;\r
+               ZeroMemory(&d3dparas,sizeof(d3dparas));\r
+               d3dparas.BackBufferWidth=width;\r
+               d3dparas.BackBufferHeight=height;\r
+               d3dparas.Windowed=TRUE;\r
+               d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;\r
+               if (d3ddevice->CreateAdditionalSwapChain(&d3dparas,&swappy)!=D3D_OK){\r
+                       Log::getInstance()->log("OSD", Log::WARN, "Could not create Swap Chain!");\r
+                       //return 0;\r
+               } else {\r
+                       swappy->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&swapsurf);\r
+               }\r
+        Log::getInstance()->log("OSD", Log::INFO, "Create Additional Swap Chain %d %d!",width,height);\r
+       }\r
+\r
+       dsallocator=dsall;\r
+       external_driving=true;\r
+       \r
+       EndPainting();*/\r
+}\r
+\r
+void OsdOpenGL::Blank() {\r
+       BeginPainting();\r
+       glClearColor(0.15f, 0.25f, 0.35f, 1.0f); // change this to black after testing\r
+       glClear( GL_COLOR_BUFFER_BIT );\r
+       glClear( GL_DEPTH_BUFFER_BIT );\r
+       EndPainting();\r
+}\r
diff --git a/osdopengl.h b/osdopengl.h
new file mode 100644 (file)
index 0000000..0e9d08e
--- /dev/null
@@ -0,0 +1,133 @@
+/*\r
+    Copyright 2004-2005 Chris Tallon, 2006,2011-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+*/\r
+\r
+#ifndef OSDOPENGL_H\r
+#define OSDOPENGL_H\r
+\r
+#include <stdio.h>\r
+\r
+#include <bcm_host.h>\r
+\r
+#include <GLES2/gl2.h>\r
+#include <EGL/egl.h>\r
+#include <EGL/eglext.h>\r
+\r
+#include "osd.h"\r
+#include "defines.h"\r
+#include "log.h"\r
+#include "threadp.h"\r
+#include "mutex.h"\r
+\r
+\r
+\r
+\r
+\r
+\r
+struct OSDCOLOR{\r
+       GLfloat r;\r
+       GLfloat g;\r
+       GLfloat b;\r
+       GLfloat a;\r
+};\r
+\r
+\r
+struct OSDVERTEX {\r
+       GLfloat x;\r
+       GLfloat y;\r
+       GLfloat z;\r
+/*     OSDCOLOR c;*/\r
+       GLfloat u;\r
+       GLfloat v;\r
+};\r
+\r
+\r
+\r
+\r
+\r
+\r
+class OsdOpenGL : public Osd, public Thread_TYPE\r
+{\r
+  public:\r
+    OsdOpenGL();\r
+    virtual ~OsdOpenGL();\r
+\r
+    int init(void* device);\r
+    int shutdown();\r
+\r
+    int getFD();\r
+\r
+    void screenShot(const char* fileName);\r
+\r
+    Surface * createNewSurface();\r
+\r
+\r
+\r
+\r
+       // This function is called from the threadMethod function in order to get Screen updates\r
+       void Render();\r
+       void RenderDS(GLuint  present);\r
+       void BeginPainting();\r
+       void EndPainting();\r
+\r
+       void setExternalDriving(/*DsAllocator* dsall,*/ unsigned int width, unsigned int height);\r
+       void Blank();\r
+\r
+\r
+\r
+\r
+private:\r
+\r
+       //Maybe move the following stuff to a generic opengl object also for boosting DCT etc.\r
+\r
+   GLuint CreateShader(const GLchar * source, GLenum type);\r
+\r
+       void threadMethod();\r
+    void threadPostStopCleanup();\r
+\r
+       // This indicates, that currently a video is played, thus the osd updates are driven by the Videosystem\r
+       bool external_driving;\r
+       Mutex glmutex;\r
+       long long  lastrendertime;\r
+       void InternalRendering(GLuint present);\r
+       bool DoLost();\r
+       void InitVertexBuffer(float  scalex,float scaley);\r
+       OSDVERTEX osdvertices[4];\r
+       GLubyte osdindices[6];\r
+\r
+\r
+       GLuint osd_shader;\r
+       GLuint gen_shader;\r
+\r
+       GLuint osd_program;\r
+\r
+       GLint osd_sampler_loc;\r
+\r
+        /* BCM specific */\r
+\r
+    uint32_t display_height;\r
+       uint32_t display_width;\r
+\r
+       EGLDisplay egl_display;\r
+       EGLSurface egl_surface;\r
+       EGLContext egl_context;\r
+\r
+};\r
+\r
+#endif\r
diff --git a/remotelinux.cc b/remotelinux.cc
new file mode 100644 (file)
index 0000000..93517da
--- /dev/null
@@ -0,0 +1,636 @@
+/*
+    Copyright 2004-2005 Chris Tallon; 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#include "remotelinux.h"
+#include "i18n.h"
+#include <linux/input.h>
+#include <sys/types.h>
+
+
+#include <errno.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+
+
+
+#define W_G_HCW(type,code) ( (((ULLONG)(type))<<32) | code)
+
+#define W_HCW_KC 1 /* key code as defined by kernel for keyboard and remotes through /dev/input */
+#define W_HCW_CEC 2 /* HDMI_CEC */
+#define W_HCW_LIRC 3 /* remote control LIRC*/
+
+
+RemoteLinux::RemoteLinux()
+{
+  initted = 0;
+  curevent=0;
+  hascurevent=false;
+  signal=false;
+  tv.tv_sec = 0;
+  tv.tv_usec = 0;
+
+}
+
+RemoteLinux::~RemoteLinux()
+{
+       for (unsigned int i=0; i<devices.size();i++) {
+               close(devices[i]);
+       }
+}
+
+#define test_bit(input,b)  ((1 << ((b) % 8))&(input)[b / 8] )
+
+
+int RemoteLinux::init(char* devName)
+{
+  if (initted) return 0;
+  initted = 1;
+
+  InitKeymap();
+
+  for (int eventid=0;eventid<100;eventid++){
+         char buffer[1024];
+         sprintf(buffer,"/dev/input/event%d",eventid);
+
+
+         struct stat test_buf;
+         if (stat(buffer,&test_buf)==0) {
+                 Log::getInstance()->log("Remote", Log::NOTICE, "Probe /dev/input/event%d",eventid);
+                 // file exists
+                 unsigned long ev_type=0;
+                 int new_fd=open(buffer,O_RDONLY);
+                 if (new_fd<0) {
+                         Log::getInstance()->log("Remote", Log::NOTICE, "Can not open /dev/input/event%d",eventid);
+                         continue;
+                 }
+                 if (ioctl(new_fd, EVIOCGBIT(0, EV_MAX), &ev_type) < 0) {
+                         Log::getInstance()->log("Remote", Log::NOTICE, "Ioctl failed /dev/input/event%d %d",eventid,errno);
+                     close(new_fd);
+                 }
+                 //Now test if it generates keyboard presses
+                 if (test_bit((char*)&ev_type , EV_KEY)) {
+                         Log::getInstance()->log("Remote", Log::NOTICE, "Add /dev/input/event%d to List",eventid);
+                         devices.push_back(new_fd);
+                 } else {
+                         close(new_fd);
+                 }
+
+
+
+
+         }
+
+  }
+
+
+
+
+  return 1;
+}
+
+int RemoteLinux::shutdown()
+{
+  if (!initted) return 0;
+
+  initted = 0;
+  return 1;
+}
+
+UCHAR RemoteLinux::getButtonPress(int waitType)
+{
+         /* how = 0 - block
+            how = 1 - start new wait
+            how = 2 - continue wait
+            how = 3 - no wait
+         */
+
+
+         struct timeval* passToSelect = NULL;
+         int retval;
+         fd_set readfds;
+
+         if (waitType == 0)
+         {
+           passToSelect = NULL;
+         }
+         else if (waitType == 1)
+         {
+           tv.tv_sec = 1;
+           tv.tv_usec = 000000;
+           passToSelect = &tv;
+         }
+         else if (waitType == 2)
+         {
+           if ((tv.tv_sec == 0) && (tv.tv_usec == 0))  // protection in case timer = 0
+           {
+             tv.tv_sec = 1;
+             tv.tv_usec = 000000;
+           }
+           passToSelect = &tv;
+         }
+         else if (waitType == 3)
+         {
+           tv.tv_sec = 0;
+           tv.tv_usec = 0;
+           passToSelect = &tv;
+         }
+         FD_ZERO(&readfds);
+
+         int maxfd=0;
+         for (int i=0; i<devices.size();i++) {
+                 int cur_fd=devices[i];
+                 maxfd=max(cur_fd,maxfd);
+                 FD_SET(cur_fd, &readfds);
+         }
+
+
+
+         retval = select(maxfd + 1, &readfds, NULL, NULL, &tv);
+         // 0 = nothing happened
+         // 1 = data arrived (actually num of descriptors that changed)
+         // other value = signal or error
+         if (retval == 0) return NA_NONE;
+         if (retval == -1) return NA_SIGNAL;
+
+
+         for (int i=0; i<devices.size();i++) {
+                         int cur_fd=devices[i];
+                         if (FD_ISSET(cur_fd, &readfds)) {
+                               struct input_event ev;
+                               int count = read(cur_fd, &ev, sizeof(ev));
+                               if (count==sizeof(ev)) {
+                                       if (ev.type==EV_KEY && ev.value==1) {
+                                               return (UCHAR) TranslateHWC(W_G_HCW(W_HCW_KC,ev.code));
+                                       }
+                               }
+
+                         }
+
+         }
+
+         return NA_UNKNOWN;
+  
+}
+
+void RemoteLinux::clearBuffer()
+{
+         while(getButtonPress(3) != NA_NONE);
+}
+
+UCHAR RemoteLinux::TranslateHWCFixed(ULLONG code)
+{
+    switch (code) 
+    {
+    case W_G_HCW(W_HCW_KC,KEY_DOWN):
+        return DOWN;
+    case W_G_HCW(W_HCW_KC,KEY_UP):
+        return UP;
+    case W_G_HCW(W_HCW_KC,KEY_LEFT):
+        return LEFT;
+    case W_G_HCW(W_HCW_KC,KEY_RIGHT):
+        return RIGHT;
+    case W_G_HCW(W_HCW_KC,KEY_M):
+        return MENU;
+    case W_G_HCW(W_HCW_KC,KEY_BACKSPACE):
+        return BACK;
+    case W_G_HCW(W_HCW_KC,KEY_ENTER):
+    case W_G_HCW(W_HCW_KC,KEY_SPACE):
+    case W_G_HCW(W_HCW_KC,KEY_OK):
+        return OK;
+    case POWER:
+        return POWER;
+    default:
+        return NA_UNKNOWN;
+    };
+}
+
+const char*RemoteLinux::HardcodedTranslateStr(UCHAR command)
+{
+    switch (command) 
+    {
+    case DOWN:
+        return tr("Down");
+    case UP:
+        return tr("Up");
+    case LEFT:
+        return tr("Left");
+    case RIGHT:
+        return tr("Right");
+    case MENU:
+        return tr("M");
+    case BACK:
+        return tr("Backspace, Back");
+    case OK:
+        return tr("Return, Space");
+    default:
+        return NULL;
+    };
+    
+}
+
+
+void RemoteLinux::InitHWCListwithDefaults()
+{
+    //Processing VK_Messages
+    translist[W_G_HCW(W_HCW_KC,KEY_9)] = NINE;
+    translist[W_G_HCW(W_HCW_KC,KEY_8)] = EIGHT;
+    translist[W_G_HCW(W_HCW_KC,KEY_7)] = SEVEN;
+    translist[W_G_HCW(W_HCW_KC,KEY_6)] = SIX;
+    translist[W_G_HCW(W_HCW_KC,KEY_5)] = FIVE;
+    translist[W_G_HCW(W_HCW_KC,KEY_4)] = FOUR;
+    translist[W_G_HCW(W_HCW_KC,KEY_3)] = THREE;
+    translist[W_G_HCW(W_HCW_KC,KEY_2)] = TWO;
+    translist[W_G_HCW(W_HCW_KC,KEY_1)] = ONE;
+    translist[W_G_HCW(W_HCW_KC,KEY_0)] = ZERO;
+    translist[W_G_HCW(W_HCW_KC,KEY_KPDOT)] = STAR;
+   // translist[W_G_HCW(W_HCW_KC,KEY_#)] = HASH;
+
+    translist[W_G_HCW(W_HCW_KC,KEY_KP9)] = NINE;
+    translist[W_G_HCW(W_HCW_KC,KEY_KP8)] = EIGHT;
+    translist[W_G_HCW(W_HCW_KC,KEY_KP7)] = SEVEN;
+    translist[W_G_HCW(W_HCW_KC,KEY_KP6)] = SIX;
+    translist[W_G_HCW(W_HCW_KC,KEY_KP5)] = FIVE;
+    translist[W_G_HCW(W_HCW_KC,KEY_KP4)] = FOUR;
+    translist[W_G_HCW(W_HCW_KC,KEY_KP3)] = THREE;
+    translist[W_G_HCW(W_HCW_KC,KEY_KP2)] = TWO;
+    translist[W_G_HCW(W_HCW_KC,KEY_KP1)] = ONE;
+    translist[W_G_HCW(W_HCW_KC,KEY_KP0)] = ZERO;
+
+    translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_9)] = NINE;
+       translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_8)] = EIGHT;
+       translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_7)] = SEVEN;
+       translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_6)] = SIX;
+       translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_5)] = FIVE;
+       translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_4)] = FOUR;
+       translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_3)] = THREE;
+       translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_2)] = TWO;
+       translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_1)] = ONE;
+       translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_0)] = ZERO;
+       translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_STAR)] = STAR;
+       translist[W_G_HCW(W_HCW_KC,KEY_NUMERIC_POUND)] = HASH;
+
+
+    translist[W_G_HCW(W_HCW_KC,KEY_J)] = GO; //j for JUMP TO instead of go to
+    translist[W_G_HCW(W_HCW_KC,KEY_R)] = RED;
+    translist[W_G_HCW(W_HCW_KC,KEY_G)] = GREEN;
+    translist[W_G_HCW(W_HCW_KC,KEY_Y)] = YELLOW;
+    translist[W_G_HCW(W_HCW_KC,KEY_B)] = BLUE;
+    //Processing Remote Style Messages
+    translist[W_G_HCW(W_HCW_KC,KEY_GREEN)] = GREEN;
+    translist[W_G_HCW(W_HCW_KC,KEY_RED)] = RED;
+    translist[W_G_HCW(W_HCW_KC,KEY_YELLOW)] = YELLOW;
+    translist[W_G_HCW(W_HCW_KC,KEY_BLUE)] = BLUE;
+    translist[W_G_HCW(W_HCW_KC,KEY_MENU)] = MENU;
+
+    translist[W_G_HCW(W_HCW_KC,KEY_RECORD)] = RECORD;
+    translist[W_G_HCW(W_HCW_KC,KEY_PLAY)] = PLAY; //Playback Televison
+    translist[W_G_HCW(W_HCW_KC,KEY_PAUSE)] = PAUSE;
+    translist[W_G_HCW(W_HCW_KC,KEY_STOP)] = STOP;
+    translist[W_G_HCW(W_HCW_KC,KEY_PLAYPAUSE)] = PLAYPAUSE;
+    translist[W_G_HCW(W_HCW_KC,KEY_P)] = PLAYPAUSE;
+    translist[W_G_HCW(W_HCW_KC,KEY_NEXT)] = SKIPFORWARD;
+    translist[W_G_HCW(W_HCW_KC,KEY_PREVIOUS)] = SKIPBACK;
+    translist[W_G_HCW(W_HCW_KC,KEY_FORWARD)] = FORWARD;
+    translist[W_G_HCW(W_HCW_KC,KEY_BACK)] = REVERSE;
+    translist[W_G_HCW(W_HCW_KC,KEY_MUTE)] = MUTE;
+    translist[W_G_HCW(W_HCW_KC,KEY_F9)] = VOLUMEUP;
+    translist[W_G_HCW(W_HCW_KC,KEY_F10)] = VOLUMEDOWN;
+    translist[W_G_HCW(W_HCW_KC,KEY_VOLUMEUP)] = VOLUMEUP;
+    translist[W_G_HCW(W_HCW_KC,KEY_VOLUMEDOWN)] = VOLUMEDOWN;
+    translist[W_G_HCW(W_HCW_KC,KEY_CHANNELUP)] = CHANNELUP;
+    translist[W_G_HCW(W_HCW_KC,KEY_CHANNELDOWN)] = CHANNELDOWN;
+    translist[W_G_HCW(W_HCW_KC,KEY_PAGEUP)] = CHANNELUP;
+    translist[W_G_HCW(W_HCW_KC,KEY_PAGEDOWN)] = CHANNELDOWN;
+
+
+}
+
+#define NAMETRICK(pre, code) linux_keymap[pre ## code]=  #code
+//extracte from linux/input.h
+
+static const char * linux_keymap[KEY_MAX+1];
+
+void RemoteLinux::InitKeymap()
+{
+       for (int i=0;i<KEY_MAX+1;i++) {
+               linux_keymap[i]=NULL;
+       }
+       NAMETRICK(KEY_,RESERVED);
+       NAMETRICK(KEY_,ESC);
+       NAMETRICK(KEY_,1);
+       NAMETRICK(KEY_,2);
+       NAMETRICK(KEY_,3);
+       NAMETRICK(KEY_,4);
+       NAMETRICK(KEY_,5);
+       NAMETRICK(KEY_,6);
+       NAMETRICK(KEY_,7);
+       NAMETRICK(KEY_,8);
+       NAMETRICK(KEY_,9);
+       NAMETRICK(KEY_,0);
+       NAMETRICK(KEY_,MINUS);
+       NAMETRICK(KEY_,EQUAL);
+       NAMETRICK(KEY_,BACKSPACE);
+       NAMETRICK(KEY_,TAB);
+       NAMETRICK(KEY_,Q);
+       NAMETRICK(KEY_,W);
+       NAMETRICK(KEY_,E);
+       NAMETRICK(KEY_,R);
+       NAMETRICK(KEY_,T);
+       NAMETRICK(KEY_,Y);
+       NAMETRICK(KEY_,U);
+       NAMETRICK(KEY_,I);
+       NAMETRICK(KEY_,O);
+       NAMETRICK(KEY_,P);
+       NAMETRICK(KEY_,LEFTBRACE);
+       NAMETRICK(KEY_,RIGHTBRACE);
+       NAMETRICK(KEY_,ENTER);
+       NAMETRICK(KEY_,LEFTCTRL);
+       NAMETRICK(KEY_,A);
+       NAMETRICK(KEY_,S);
+       NAMETRICK(KEY_,D);
+       NAMETRICK(KEY_,F);
+       NAMETRICK(KEY_,G);
+       NAMETRICK(KEY_,H);
+       NAMETRICK(KEY_,J);
+       NAMETRICK(KEY_,K);
+       NAMETRICK(KEY_,L);
+       NAMETRICK(KEY_,SEMICOLON);
+       NAMETRICK(KEY_,APOSTROPHE);
+       NAMETRICK(KEY_,GRAVE);
+       NAMETRICK(KEY_,LEFTSHIFT);
+       NAMETRICK(KEY_,BACKSLASH);
+       NAMETRICK(KEY_,Z);
+       NAMETRICK(KEY_,X);
+       NAMETRICK(KEY_,C);
+       NAMETRICK(KEY_,V);
+       NAMETRICK(KEY_,B);
+       NAMETRICK(KEY_,N);
+       NAMETRICK(KEY_,M);
+       NAMETRICK(KEY_,COMMA);
+       NAMETRICK(KEY_,DOT);
+       NAMETRICK(KEY_,SLASH);
+       NAMETRICK(KEY_,RIGHTSHIFT);
+       NAMETRICK(KEY_,KPASTERISK);
+       NAMETRICK(KEY_,LEFTALT);
+       NAMETRICK(KEY_,SPACE);
+       NAMETRICK(KEY_,CAPSLOCK);
+       NAMETRICK(KEY_,F1);
+       NAMETRICK(KEY_,F2);
+       NAMETRICK(KEY_,F3);
+       NAMETRICK(KEY_,F4);
+       NAMETRICK(KEY_,F5);
+       NAMETRICK(KEY_,F6);
+       NAMETRICK(KEY_,F7);
+       NAMETRICK(KEY_,F8);
+       NAMETRICK(KEY_,F9);
+       NAMETRICK(KEY_,F10);
+       NAMETRICK(KEY_,NUMLOCK);
+       NAMETRICK(KEY_,SCROLLLOCK);
+       NAMETRICK(KEY_,KP7);
+       NAMETRICK(KEY_,KP8);
+       NAMETRICK(KEY_,KP9);
+       NAMETRICK(KEY_,KPMINUS);
+       NAMETRICK(KEY_,KP4);
+       NAMETRICK(KEY_,KP5);
+       NAMETRICK(KEY_,KP6);
+       NAMETRICK(KEY_,KPPLUS);
+       NAMETRICK(KEY_,KP1);
+       NAMETRICK(KEY_,KP2);
+       NAMETRICK(KEY_,KP3);
+       NAMETRICK(KEY_,KP0);
+       NAMETRICK(KEY_,KPDOT);
+       NAMETRICK(KEY_,F11);
+       NAMETRICK(KEY_,F12);
+       NAMETRICK(KEY_,KPENTER);
+       NAMETRICK(KEY_,RIGHTCTRL);
+       NAMETRICK(KEY_,KPSLASH);
+       NAMETRICK(KEY_,SYSRQ);
+       NAMETRICK(KEY_,RIGHTALT);
+       NAMETRICK(KEY_,LINEFEED);
+       NAMETRICK(KEY_,HOME);
+       NAMETRICK(KEY_,UP);
+       NAMETRICK(KEY_,PAGEUP);
+       NAMETRICK(KEY_,LEFT);
+       NAMETRICK(KEY_,RIGHT);
+       NAMETRICK(KEY_,END);
+       NAMETRICK(KEY_,DOWN);
+       NAMETRICK(KEY_,PAGEDOWN);
+       NAMETRICK(KEY_,INSERT);
+       NAMETRICK(KEY_,DELETE);
+       NAMETRICK(KEY_,MACRO);
+       NAMETRICK(KEY_,MUTE);
+       NAMETRICK(KEY_,VOLUMEDOWN);
+       NAMETRICK(KEY_,VOLUMEUP);
+       NAMETRICK(KEY_,POWER);
+       NAMETRICK(KEY_,KPEQUAL);
+       NAMETRICK(KEY_,KPPLUSMINUS);
+       NAMETRICK(KEY_,PLAY);
+       NAMETRICK(KEY_,PAUSE);
+       NAMETRICK(KEY_,SCALE);
+       NAMETRICK(KEY_,KPCOMMA);
+       NAMETRICK(KEY_,YEN);
+       NAMETRICK(KEY_,LEFTMETA);
+       NAMETRICK(KEY_,RIGHTMETA);
+       NAMETRICK(KEY_,COMPOSE);
+       NAMETRICK(KEY_,STOP);
+       NAMETRICK(KEY_,AGAIN);
+       NAMETRICK(KEY_,PROPS);
+       NAMETRICK(KEY_,UNDO);
+       NAMETRICK(KEY_,FRONT);
+       NAMETRICK(KEY_,COPY);
+       NAMETRICK(KEY_,OPEN);
+       NAMETRICK(KEY_,PASTE);
+       NAMETRICK(KEY_,FIND);
+       NAMETRICK(KEY_,CUT);
+       NAMETRICK(KEY_,HELP);
+       NAMETRICK(KEY_,MENU);
+       NAMETRICK(KEY_,CALC);
+       NAMETRICK(KEY_,SETUP);
+       NAMETRICK(KEY_,SLEEP);
+       NAMETRICK(KEY_,WAKEUP);
+       NAMETRICK(KEY_,FILE);
+       NAMETRICK(KEY_,SENDFILE);
+       NAMETRICK(KEY_,DELETEFILE);
+       NAMETRICK(KEY_,XFER);
+       NAMETRICK(KEY_,PROG1);
+       NAMETRICK(KEY_,PROG2);
+       NAMETRICK(KEY_,WWW);
+       NAMETRICK(KEY_,MSDOS);
+       NAMETRICK(KEY_,COFFEE);
+       NAMETRICK(KEY_,DIRECTION);
+       NAMETRICK(KEY_,CYCLEWINDOWS);
+       NAMETRICK(KEY_,MAIL);
+       NAMETRICK(KEY_,BOOKMARKS);
+       NAMETRICK(KEY_,COMPUTER);
+       NAMETRICK(KEY_,BACK);
+       NAMETRICK(KEY_,FORWARD);
+       NAMETRICK(KEY_,CLOSECD);
+       NAMETRICK(KEY_,EJECTCD);
+       NAMETRICK(KEY_,EJECTCLOSECD);
+       NAMETRICK(KEY_,NEXTSONG);
+       NAMETRICK(KEY_,PLAYPAUSE);
+       NAMETRICK(KEY_,PREVIOUSSONG);
+       NAMETRICK(KEY_,STOPCD);
+       NAMETRICK(KEY_,RECORD);
+       NAMETRICK(KEY_,REWIND);
+       NAMETRICK(KEY_,PHONE);
+       NAMETRICK(KEY_,ISO);
+       NAMETRICK(KEY_,CONFIG);
+       NAMETRICK(KEY_,HOMEPAGE);
+       NAMETRICK(KEY_,REFRESH);
+       NAMETRICK(KEY_,EXIT);
+       NAMETRICK(KEY_,MOVE);
+       NAMETRICK(KEY_,EDIT);
+       NAMETRICK(KEY_,SCROLLUP);
+       NAMETRICK(KEY_,SCROLLDOWN);
+       NAMETRICK(KEY_,KPLEFTPAREN);
+       NAMETRICK(KEY_,KPRIGHTPAREN);
+       NAMETRICK(KEY_,NEW);
+       NAMETRICK(KEY_,REDO);
+       NAMETRICK(KEY_,OK);
+       NAMETRICK(KEY_,SELECT);
+       NAMETRICK(KEY_,GOTO);
+       NAMETRICK(KEY_,CLEAR);
+       NAMETRICK(KEY_,POWER2);
+       NAMETRICK(KEY_,OPTION);
+       NAMETRICK(KEY_,INFO);
+       NAMETRICK(KEY_,TIME);
+       NAMETRICK(KEY_,VENDOR);
+       NAMETRICK(KEY_,ARCHIVE);
+       NAMETRICK(KEY_,PROGRAM);
+       NAMETRICK(KEY_,CHANNEL);
+       NAMETRICK(KEY_,FAVORITES);
+       NAMETRICK(KEY_,EPG);
+       NAMETRICK(KEY_,PVR);
+       NAMETRICK(KEY_,MHP);
+       NAMETRICK(KEY_,LANGUAGE);
+       NAMETRICK(KEY_,TITLE);
+       NAMETRICK(KEY_,SUBTITLE);
+       NAMETRICK(KEY_,ANGLE);
+       NAMETRICK(KEY_,ZOOM);
+       NAMETRICK(KEY_,MODE);
+       NAMETRICK(KEY_,KEYBOARD);
+       NAMETRICK(KEY_,SCREEN);
+       NAMETRICK(KEY_,RED);
+       NAMETRICK(KEY_,GREEN);
+       NAMETRICK(KEY_,YELLOW);
+       NAMETRICK(KEY_,BLUE);
+       NAMETRICK(KEY_,CHANNELUP);
+       NAMETRICK(KEY_,CHANNELDOWN);
+       NAMETRICK(KEY_,FIRST);
+       NAMETRICK(KEY_,LAST);
+       NAMETRICK(KEY_,AB);
+       NAMETRICK(KEY_,NEXT);
+       NAMETRICK(KEY_,RESTART);
+       NAMETRICK(KEY_,SLOW);
+       NAMETRICK(KEY_,SHUFFLE);
+       NAMETRICK(KEY_,BREAK);
+       NAMETRICK(KEY_,PREVIOUS);
+       NAMETRICK(KEY_,DIGITS);
+       NAMETRICK(KEY_,TEEN);
+       NAMETRICK(KEY_,TWEN);
+       NAMETRICK(KEY_,VIDEOPHONE);
+       NAMETRICK(KEY_,GAMES);
+       NAMETRICK(KEY_,ZOOMIN);
+       NAMETRICK(KEY_,ZOOMOUT);
+       NAMETRICK(KEY_,ZOOMRESET);
+       NAMETRICK(KEY_,DOLLAR);
+       NAMETRICK(KEY_,EURO);
+       NAMETRICK(KEY_,FRAMEBACK);
+       NAMETRICK(KEY_,FRAMEFORWARD);
+       NAMETRICK(KEY_,CONTEXT_MENU);
+       NAMETRICK(KEY_,MEDIA_REPEAT);
+       NAMETRICK(KEY_,NUMERIC_0);
+       NAMETRICK(KEY_,NUMERIC_1);
+       NAMETRICK(KEY_,NUMERIC_2);
+       NAMETRICK(KEY_,NUMERIC_3);
+       NAMETRICK(KEY_,NUMERIC_4);
+       NAMETRICK(KEY_,NUMERIC_5);
+       NAMETRICK(KEY_,NUMERIC_6);
+       NAMETRICK(KEY_,NUMERIC_7);
+       NAMETRICK(KEY_,NUMERIC_8);
+       NAMETRICK(KEY_,NUMERIC_9);
+       NAMETRICK(KEY_,NUMERIC_STAR);
+       NAMETRICK(KEY_,NUMERIC_POUND);
+
+
+
+}
+
+
+
+char* RemoteLinux::HCWDesc(unsigned long long hcw)
+{
+    //Determine type
+    unsigned int type =  hcw >> 32;
+    char *rt=NULL;
+    switch(type)
+    {
+    case W_HCW_KC:{
+       unsigned int vk=(ULONG)hcw;
+        rt=new char[10];
+        const char *desc=linux_keymap[vk];
+        if (desc) {
+               strncpy(rt,desc,9);
+        } else {
+               sprintf(rt,"0x%x",vk);
+        }
+                  }break;
+                  //TODO
+  /*  case W_HCW_CEC:{
+        ULONG ch=(ULONG)hcw;
+        ULONG scancode=OemKeyScan(ch);
+  
+        rt=new char[10];
+        GetKeyNameText(scancode << 16,rt,10); 
+                  }break;
+    case W_HCW_LIRC:{
+        ULONG ri=(ULONG)hcw;
+        rt=new char[10];
+        sprintf(rt,"R: %X",ri);
+                  }break;*/
+
+    };
+    return rt;
+}
+
+
+
+
+
+
+
+/*
+void RemoteLinux::Signal() {
+       signal=true;
+       //PulseEvent(event);
+       SetEvent(event);
+}
+
+void RemoteLinux::SendPower()
+{
+
+       curevent=POWER;
+    hascurevent=true;
+       SetEvent(event);
+}*/
+
diff --git a/remotelinux.h b/remotelinux.h
new file mode 100644 (file)
index 0000000..c4f3ffa
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+    Copyright 2004-2005 Chris Tallon; 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#ifndef REMOTELINUX_H
+#define REMOTELINUX_H
+
+#include <stdio.h>
+
+#include "defines.h"
+#include "log.h"
+#include "remote.h"
+
+#include <vector>
+
+
+
+
+
+class RemoteLinux : public Remote
+{
+  public:
+    RemoteLinux();
+    virtual ~RemoteLinux();
+
+    int init(char *devName);
+    int shutdown();
+    int getDevice();
+    UCHAR getButtonPress(int how);
+    void clearBuffer();
+  //  void Signal();
+
+//     void SendPower();
+    void InitHWCListwithDefaults();
+    const char*HardcodedTranslateStr(UCHAR command);
+    char* HCWDesc(ULLONG hcw);
+    
+
+
+  private: 
+    int initted;
+       bool signal;
+       UCHAR curevent;
+    bool hascurevent;
+
+    UCHAR TranslateHWCFixed(ULLONG code);
+    void InitKeymap();
+    vector<int> devices;
+    struct timeval tv;
+
+};
+
+#endif
+
diff --git a/shaders/generic__vertex_shader.h b/shaders/generic__vertex_shader.h
new file mode 100644 (file)
index 0000000..e5f1ac5
--- /dev/null
@@ -0,0 +1,33 @@
+/*\r
+    Copyright 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+*/\r
+\r
+#ifndef OSD_GEN_SHADER_H\r
+#define OSD_GEN_SHADER_H\r
+\r
+const GLchar generic_vertex_shader[] =\r
+               "attribute vec4 vec_pos;\n"\r
+               "attribute vec2 tex_coord;\n"\r
+               "varying vec2 out_texCoord;\n"\r
+               "void main()\n"\r
+               "{\n"\r
+               " gl_Position=vec_pos;\n"\r
+               " out_texCoord=tex_coord;\n"\r
+               "}\n";\r
+#endif\r
diff --git a/shaders/osd__frag_shader.h b/shaders/osd__frag_shader.h
new file mode 100644 (file)
index 0000000..50421e8
--- /dev/null
@@ -0,0 +1,44 @@
+/*\r
+    Copyright 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+*/\r
+\r
+#ifndef OSD_FRAG_SHADER_H\r
+#define OSD_FRAG_SHADER_H\r
+\r
+const GLchar osd_frag_shader[] =\r
+               "precision mediump float;\n"\r
+               "uniform sampler2D texture;"\r
+               "varying vec2 out_texCoord;\n"\r
+               "void main()\n"\r
+               "{\n"\r
+       //      " vec4 temp=vec4(0.3,0.4,0.5,0.5);\n"\r
+       //      " temp.r=0.6;\n"\r
+               " gl_FragColor=texture2D(texture,out_texCoord);\n"\r
+       //      " temp.r=temp2.r;\n"\r
+       //      " temp.b=temp2.b;\n"\r
+       //      "gl_FragColor=temp;\n"\r
+               "}\n";\r
+#endif\r
+//"vec4 temp=vec4(0.3,0.4,0.5);\n"\r
+//     "temp.a=1.0f;\n"\r
+//     " gl_FragColor.r=texture2D(texture,out_texCoord.st).r;\n"\r
+//     " gl_FragColor.b=0.2f;\n"\r
+//     " gl_FragColor.g=0.2f;\n"\r
+//     "gl_FragColor.a=0.5f;\n"\r
+//"gl_FragColor=vec4(0.3,0.4,0.5,0.5);\n"\r
diff --git a/surfaceopengl.cc b/surfaceopengl.cc
new file mode 100644 (file)
index 0000000..034b782
--- /dev/null
@@ -0,0 +1,366 @@
+/*\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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+*/\r
+\r
+#include <stdlib.h>\r
+\r
+#include "surfaceopengl.h"\r
+#include "osdopengl.h"\r
+#include "bitmap.h"\r
+#include "log.h"\r
+#include "mutex.h"\r
+\r
+inline unsigned int InternalColour(unsigned int c){\r
+       return (c &0x000000FF)<<16 |\r
+                                         (c &0x0000FF00) |\r
+                                         (c &0x00FF0000)>>16 |\r
+                                         (c &0xFF000000);\r
+}\r
+\r
+SurfaceOpenGL::SurfaceOpenGL(int id)\r
+: Surface(id)\r
+{\r
+       gltexture=0;\r
+  data=NULL;\r
+  sheight=swidth=0;\r
+//  fastdraw=false;\r
+  srf_mutex.Lock();\r
+}\r
+\r
+SurfaceOpenGL::~SurfaceOpenGL()\r
+{\r
+       srf_mutex.Lock();\r
+       if (data) {\r
+               free(data);\r
+               data=NULL;\r
+       } else {\r
+               glDeleteTextures(1,&gltexture);\r
+       }\r
+       srf_mutex.Unlock();\r
+}\r
+\r
+int SurfaceOpenGL::create(UINT width, UINT height)\r
+{\r
+       OsdOpenGL* osd=((OsdOpenGL*)(Osd::getInstance()));\r
+       //osd->BeginPainting();\r
+\r
+\r
+       if (this == screen) { // We do not need locking here, since the osd calls this\r
+               sheight = 64;\r
+               swidth = 64;\r
+               while (sheight < height) { // should be a power of 2\r
+                       sheight *= 2;\r
+               }\r
+               while (swidth < width) { // should be a power of 2\r
+                       swidth *= 2;\r
+               }\r
+               glGenTextures(1, &gltexture);\r
+\r
+               glBindTexture(GL_TEXTURE_2D, gltexture);\r
+\r
+               void *image = malloc(sheight * swidth * 4);\r
+               memset(image, 0, sheight * swidth * 4);\r
+       /*      for (int i=0;i< sheight * swidth * 4; i++) { //fill it with garbage, useful for debugging\r
+                       ((char*)image)[i]=i%255;\r
+               }*/\r
+               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, swidth, sheight, 0, GL_RGBA,\r
+                               GL_UNSIGNED_BYTE, image);\r
+\r
+       } else {\r
+               sheight = height;\r
+               swidth = width;\r
+               data=(char*)malloc(sizeof(uint32_t)*width*height);\r
+       }\r
+\r
+\r
+       //osd->EndPainting();\r
+       srf_mutex.Unlock();\r
+       return 1;\r
+}\r
+\r
+void SurfaceOpenGL::display()\r
+{\r
+}\r
+\r
+int SurfaceOpenGL::fillblt(int x, int y, int width, int height, unsigned int c) {\r
+       srf_mutex.Lock();\r
+       //since this might be called before surface\r
+       //allocation we will wait in this case, hopefully without deadlocks\r
+       if (screen == this || !data ) {\r
+               //This should not happen!\r
+               srf_mutex.Unlock();\r
+               return 0;\r
+\r
+       }\r
+       /*   OsdWin* osd=((OsdWin*)(Osd::getInstance()));\r
+\r
+        osd->BeginPainting();\r
+\r
+        glViewport(0,0,swidth,sheight);*/\r
+\r
+       //osd->EndPainting();\r
+       srf_mutex.Unlock();\r
+\r
+       unsigned int my_c=InternalColour(c);\r
+\r
+       int iheight=height;\r
+       if (height+y>sheight) iheight=sheight-y;\r
+       int iwidth=width;\r
+    if (width+x>swidth) iwidth=swidth-y;\r
+\r
+       unsigned int line;\r
+       unsigned int column;\r
+       for (line = y; line < (iheight + y); line++) {\r
+               uint32_t *row = ((unsigned int*) (((char*) data) + (swidth * line + x)\r
+                               * sizeof(uint32_t)));\r
+               for (column = 0; column < iwidth; column++) {\r
+                       row[column] = my_c;\r
+               }\r
+       }\r
+\r
+/*     if (d3dsurface->UnlockRect() != D3D_OK) {\r
+               osd->EndPainting();\r
+               return 0;\r
+       }\r
+       osd->EndPainting();*/\r
+\r
+       return 0;\r
+}\r
+\r
+\r
+void SurfaceOpenGL::startFastDraw(){\r
+       srf_mutex.Lock();\r
+\r
+}\r
+void SurfaceOpenGL::endFastDraw(){\r
+       srf_mutex.Unlock();\r
+ }\r
+\r
+void SurfaceOpenGL::drawPixel(int x, int y, Colour & colour, bool fastdraw) {\r
+  int c = (  (0xFF000000         )\r
+             | (colour.red    << 16)\r
+             | (colour.green  <<  8)\r
+             | (colour.blue        ) );\r
+\r
+    drawPixel(x, y, c, fastdraw);\r
+  }\r
+\r
+void SurfaceOpenGL::drawPixel(int x, int y, unsigned int c, bool fastdraw) {\r
+       //FixMe: locking for every single Pixel will be painfully slow\r
+       if (screen == this) {\r
+               //This should not happen!\r
+               return ;\r
+       }\r
+       if (!data) {\r
+               return; //why does this happen\r
+       }\r
+       //OsdWin* osd;\r
+       if (!fastdraw) {\r
+               srf_mutex.Lock(); //since this might be called before surface\r
+       }\r
+       //allocation we will wait in this case, hopefully without deadlocks\r
+\r
+       //osd = ((OsdWin*) (Osd::getInstance()));\r
+\r
+       if (x >= swidth || y >= sheight)\r
+               return; //do not draw outside the surface\r
+\r
+       unsigned int my_c=InternalColour(c);\r
+\r
+       unsigned int*row = (unsigned int*) (((char*) data + (swidth * y + x)\r
+                       * sizeof(uint32_t)));\r
+       row[0] = my_c;\r
+\r
+       if (!fastdraw) {\r
+               srf_mutex.Unlock(); //since this might be called before surface\r
+       }\r
+\r
+}\r
+\r
+void SurfaceOpenGL::drawHorzLine(int x1, int x2, int y, unsigned int c)\r
+{\r
+   fillblt(x1, y, x2-x1, 1, c);\r
+}\r
+\r
+void SurfaceOpenGL::drawVertLine(int x, int y1, int y2, unsigned int c)\r
+{\r
+  fillblt(x, y1, 1, y2-y1, c);\r
+}\r
+\r
+void SurfaceOpenGL::drawBitmap(int x, int y, const Bitmap& bm)\r
+{\r
+  // Temporary code? Draw one pixel at a time using drawPixel()\r
+  startFastDraw();\r
+  for (UINT j = 0; j < bm.getHeight(); ++j)\r
+    for (UINT i = 0; i < bm.getWidth(); ++i)\r
+      drawPixel(x+i, y+j, bm.getColour(i,j),true);\r
+  endFastDraw();\r
+}\r
+\r
+int SurfaceOpenGL::updateToScreen(int sx, int sy, int w, int h, int dx, int dy) // FIXME new, replace others with this FIXME\r
+{\r
+       srf_mutex.Lock();//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
+  OsdOpenGL* osd=((OsdOpenGL*)(Osd::getInstance()));\r
+\r
+  GLuint screengltexture=((SurfaceOpenGL*)screen)->getTexture();\r
+\r
+  osd->BeginPainting();\r
+  glBindTexture(GL_TEXTURE_2D, screengltexture);\r
+  //Log::getInstance()->log("Surface", Log::WARN, "UTS Mark3 %d",glGetError());\r
+\r
+  for (int y=0;y<h;y++) { //hopefully this is not too slow\r
+         glTexSubImage2D(GL_TEXTURE_2D,0,dx,(dy+y),w,1,GL_RGBA,GL_UNSIGNED_BYTE,\r
+                         data+((y+sy)*swidth+sx)*sizeof(uint32_t));\r
+        // Log::getInstance()->log("Surface", Log::WARN, "UTS Mark43 %d",glGetError());\r
+\r
+  }\r
+  //Log::getInstance()->log("Surface", Log::WARN, "UTS Mark4 %d",glGetError());\r
+  osd->EndPainting();\r
+  srf_mutex.Unlock();\r
+  return 0;\r
+}\r
+\r
+int SurfaceOpenGL::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 SurfaceOpenGL::screenShot(const char* fileName)\r
+{\r
+  //Isn't this for debugging only, so I won't implement it yet\r
+}\r
+\r
+void SurfaceOpenGL::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
+\r
+\r
+void SurfaceOpenGL::drawJpeg(const char *fileName,int x, int y,int *width, int *height){\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 ; //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
+void SurfaceOpenGL::drawJpeg(char *buffer,ULONG buflength,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
+  D3DXGetImageInfoFromFileInMemory((void*)buffer,buflength,&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
+  if (D3DXLoadSurfaceFromFileInMemory(\r
+    d3dsurface,\r
+    NULL,\r
+    &dest_rec,\r
+    (void*)buffer,\r
+    buflength,\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
diff --git a/surfaceopengl.h b/surfaceopengl.h
new file mode 100644 (file)
index 0000000..6bec52a
--- /dev/null
@@ -0,0 +1,70 @@
+/*\r
+    Copyright 2006, 2011-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+*/\r
+\r
+#ifndef SURFACEOPENGL_H\r
+#define SURFACEOPENGL_H\r
+\r
+#include "defines.h"\r
+#include "surface.h"\r
+#include "mutex.h"\r
+#include <GLES2/gl2.h>\r
+\r
+class SurfaceOpenGL : public Surface\r
+{\r
+  public:\r
+    SurfaceOpenGL(int id = 0);\r
+    virtual ~SurfaceOpenGL();\r
+\r
+    int create(UINT width, UINT height);\r
+    void display();\r
+\r
+    void startFastDraw();\r
+    void endFastDraw();\r
+\r
+    int fillblt(int x, int y, int width, int height, unsigned int c);\r
+    void drawPixel(int x, int y, Colour& c, bool fastdraw=false);\r
+    void drawPixel(int x, int y, unsigned int c, bool fastdraw=false);\r
+    void drawHorzLine(int x1, int x2, int y, unsigned int c);\r
+    void drawVertLine(int x, int y1, int y2, unsigned int c);\r
+    void drawBitmap(int x, int y, const Bitmap& bm);\r
+    int updateToScreen(int sx, int sy, int w, int h, int dx, int dy);\r
+    void readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b);\r
+    void screenShot(const char* fileName);\r
+  void ReleaseSurface();\r
+    int blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy);\r
+  void drawJpeg(const char *fileName,int x, int y,int *width, int *height);\r
+/*  void drawJpeg(char *buffer,ULONG buflength,DWORD x, DWORD y,DWORD *width, DWORD *height);*/\r
+\r
+    GLuint getTexture() {return gltexture;};\r
+\r
+\r
+\r
+  private:\r
+    GLuint  gltexture;\r
+    UINT sheight,swidth;\r
+    char * data;\r
+\r
+\r
+\r
+    Mutex srf_mutex;\r
+\r
+};\r
+\r
+#endif\r
diff --git a/threadpandroid.cc b/threadpandroid.cc
new file mode 100644 (file)
index 0000000..693286a
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+    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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#include "threadpandroid.h"
+#include "log.h"
+
+// Undeclared functions, only for use in this file to start the thread
+void threadPAndroidInternalStart(void *arg)
+{
+  // I don't want signals
+  sigset_t sigs;
+  sigfillset(&sigs);
+  pthread_sigmask(SIG_BLOCK, &sigs, NULL);
+
+  Thread *t = (Thread *)arg;
+  t->threadInternalStart2();
+}
+
+int ThreadPAndroid ::threadStart()
+{
+  pthread_cond_init(&threadCond, NULL);
+  pthread_cond_init(&threadKillable, NULL);
+  pthread_mutex_init(&threadCondMutex, NULL);
+
+  threadActive = 1;
+  killable=false;
+  if (pthread_create(&pthread, NULL, (void*(*)(void*))threadPAndroidInternalStart, (void *)this) == -1) return 0;
+  return 1;
+}
+
+void ThreadPAndroid ::threadStop()
+{
+  threadActive = 0;
+  // Signal thread here in case it's waiting
+  threadSignal();
+  pthread_join(pthread, NULL);
+  this->threadPostStopCleanup();
+}
+
+
+void ThreadPAndroid ::threadCancel()
+{
+  threadActive = 0;
+  threadSignalNoLock();
+  if (killable) pthread_cond_wait(&threadKillable,&threadCondMutex);
+ // pthread_cancel(pthread);
+  pthread_join(pthread, NULL);
+  this->threadPostStopCleanup();
+}
+
+
+
+void ThreadPAndroid ::threadCheckExit()
+{
+  if (!threadActive) {
+         pthread_cond_signal(&threadKillable);
+         pthread_exit(NULL);
+  }
+}
+
+void ThreadPAndroid ::threadLock()
+{
+  pthread_mutex_lock(&threadCondMutex);
+}
+
+void ThreadPAndroid ::threadUnlock()
+{
+  pthread_mutex_unlock(&threadCondMutex);
+}
+
+void ThreadPAndroid ::threadSignal()
+{
+  pthread_mutex_lock(&threadCondMutex);
+  pthread_cond_signal(&threadCond);
+  pthread_mutex_unlock(&threadCondMutex);
+}
+
+void ThreadPAndroid ::threadSignalNoLock()
+{
+  pthread_cond_signal(&threadCond);
+}
+
+void ThreadPAndroid ::threadWaitForSignal()
+{
+  pthread_cond_wait(&threadCond, &threadCondMutex);
+}
+
+void ThreadPAndroid ::threadWaitForSignalTimed(struct timespec* ts)
+{
+  pthread_cond_timedwait(&threadCond, &threadCondMutex, ts);
+}
+
+void ThreadPAndroid ::threadSetKillable()
+{
+  //pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+  //pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+       killable=true;
+       pthread_cond_signal(&threadKillable);
+}
+
+
+pthread_t ThreadPAndroid ::getThreadID() // returns the ID of this thread
+{
+  return pthread;
+}
+
+// Static functions
+
+void ThreadPAndroid ::threadSuicide()
+{
+  if(!pthread_detach(pthread_self()))
+  {
+    MILLISLEEP(1000);
+    if(!pthread_detach(pthread_self()))
+    {
+      MILLISLEEP(1000);
+      pthread_detach(pthread_self());
+    }
+  }
+
+  pthread_exit(NULL);
+}
+
+pthread_t ThreadPAndroid ::thisThreadID() // returns the ID of the calling thread
+{
+  return pthread_self();
+}
diff --git a/threadpandroid.h b/threadpandroid.h
new file mode 100644 (file)
index 0000000..955bde1
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+    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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#ifndef THREADPANDROID_H
+#define THREADPANDROID_H
+
+#include <pthread.h>
+#include <signal.h>
+
+#include "defines.h"
+#include "thread.h"
+
+class ThreadPAndroid : public Thread
+{
+  protected:
+    // Override this method in derived classes
+    virtual void threadMethod()=0;
+    virtual void threadPostStopCleanup()=0;
+
+    // Methods to use from outside the thread
+    int threadStart();    // start the thread. threadMethod() will be called in derived class
+    void threadStop();    // stop the thread nicely. thread will be stopped when it next calls threadCheckExit()
+    void threadCancel();  // stop thread immediately. thread will be stopped at the next cancellation point
+    void threadSignal();  // releases a thread that has called threadWaitForSignal
+    void threadSignalNoLock();  // same as above but without locking guarantees. probably not a good idea.
+
+    // Methods to use from inside the thread
+    void threadSetKillable();    // allows threadCancel() to work
+    void threadCheckExit();      // terminates thread if threadStop() has been called
+    void threadWaitForSignal();  // pauses thread until threadSignal() is called
+    void threadWaitForSignalTimed(struct timespec*);  // pauses thread until threadSignal() is called or timer expires
+    void threadLock();           // locks the mutex used for internal cond/signal stuff
+    void threadUnlock();         // unlocks.
+
+    // Internal bits and pieces
+
+    pthread_t pthread;
+    pthread_cond_t threadCond;
+    pthread_cond_t threadKillable;
+    pthread_mutex_t threadCondMutex;
+
+  public:
+    pthread_t getThreadID();    // returns the ID of the thread represented by this object
+
+
+    static pthread_t thisThreadID();    // Self identification - returns ID of calling thread
+    static void threadSuicide();        // Self termination
+    bool killable;
+};
+
+#endif
diff --git a/threadsystem.h b/threadsystem.h
new file mode 100644 (file)
index 0000000..cddc15f
--- /dev/null
@@ -0,0 +1,29 @@
+/*\r
+    Copyright 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+*/\r
+\r
+#ifndef WIN32\r
+#ifdef __ANDROID__\r
+#include "threadpandroid.h"\r
+#else\r
+#include "threadp.h"\r
+#endif\r
+#else\r
+#include "threadwin.h"\r
+#endif\r
diff --git a/videovpeogl.cc b/videovpeogl.cc
new file mode 100644 (file)
index 0000000..418a7bb
--- /dev/null
@@ -0,0 +1,769 @@
+/*
+    Copyright 2004-2005 Chris Tallon, 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#include "videovpeogl.h"
+#include "audiovpe.h"
+#include "mtdraspberry.h"
+#include "demuxer.h"
+// temp
+#include "log.h"
+
+
+
+//taken from libsi
+//taken and adapted from libdtv, (c) Rolf Hakenes
+// CRC32 lookup table for polynomial 0x04c11db7
+unsigned int crc_table[256] = {
+   0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
+   0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+   0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
+   0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+   0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
+   0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+   0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
+   0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+   0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
+   0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+   0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+   0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+   0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
+   0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+   0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
+   0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+   0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
+   0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+   0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
+   0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+   0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+   0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+   0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
+   0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+   0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
+   0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+   0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
+   0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+   0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
+   0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+   0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+   0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+   0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
+   0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+   0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
+   0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+   0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
+   0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+   0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
+   0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+   0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+   0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+   0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};
+
+unsigned int crc32 (const char *d, int len, unsigned int crc)
+{
+   register int i;
+   const unsigned char *u=(unsigned char*)d; // Saves '& 0xff'
+
+   for (i=0; i<len; i++)
+      crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *u++)];
+
+   return crc;
+}
+
+
+
+VideoVPEOGL::VideoVPEOGL()
+{
+  if (instance) return;
+  muxout=NULL;
+  muxnumber=0;
+  lastpacketnum=-1;
+  audioconti=videoconti=0;
+  pmtversion=patversion=0;
+  
+}
+
+VideoVPEOGL::~VideoVPEOGL()
+{
+  instance = NULL;
+}
+
+int VideoVPEOGL::init(UCHAR tformat)
+{
+  if (initted) return 0;
+  initted = 1;
+
+//  if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
+
+  if (!setFormat(tformat))           { shutdown(); return 0; }
+  if (!setConnection(COMPOSITERGB))  { shutdown(); return 0; }
+  if (!setAspectRatio(ASPECT4X3))    { shutdown(); return 0; }
+  if (!setMode(NORMAL))              { shutdown(); return 0; }
+  if (!setSource())                  { shutdown(); return 0; }
+  if (!attachFrameBuffer())          { shutdown(); return 0; }
+
+  setTVsize(ASPECT4X3);
+
+/*  if (format == PAL) setLetterboxBorder("38");
+  else setLetterboxBorder("31");*/
+
+  stop();
+
+
+  return 1;
+}
+
+
+
+int VideoVPEOGL::setTVsize(UCHAR ttvsize)
+{
+/*  tvsize = ttvsize;
+
+  // Override the aspect ratio usage, temporarily use to set the video chip mode
+  if (!setAspectRatio(tvsize))       { shutdown(); return 0; }
+  close(fdVideo);
+  if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
+  if (!setSource())                  { shutdown(); return 0; }
+  if (!attachFrameBuffer())          { shutdown(); return 0; }
+
+  // Reopening the fd causes the scart aspect line to go back to 4:3
+  // Set this again to the same as the tv screen size
+  if (!setAspectRatio(tvsize))       { shutdown(); return 0; }
+
+  // mode == LETTERBOX is invalid if the TV is widescreen
+  if (tvsize == ASPECT16X9) setMode(NORMAL);
+*/
+  return 1;
+}
+
+int VideoVPEOGL::setDefaultAspect()
+{
+  return setAspectRatio(tvsize);
+}
+
+int VideoVPEOGL::shutdown()
+{
+  if (!initted) return 0;
+  initted = 0;
+//  close(fdVideo);
+  return 1;
+}
+
+
+int VideoVPEOGL::setFormat(UCHAR tformat)
+{
+  if (!initted) return 0;
+  if ((tformat != PAL) && (tformat != NTSC)) return 0;
+  format = tformat;
+
+//  if (ioctl(fdVideo, AV_SET_VID_DISP_FMT, format) != 0) return 0;
+
+  if (format == NTSC)
+  {
+    screenWidth = 720;
+    screenHeight = 480;
+  }
+  if (format == PAL)
+  {
+    screenWidth = 720;
+    screenHeight = 576;
+  }
+
+  return 1;
+}
+
+int VideoVPEOGL::setConnection(UCHAR tconnection)
+{
+  if (!initted) return 0;
+  if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0;
+  connection = tconnection;
+
+//  if (ioctl(fdVideo, AV_SET_VID_OUTPUT, connection) != 0) return 0;
+  return 1;
+}
+
+int VideoVPEOGL::setAspectRatio(UCHAR taspectRatio)
+{
+  if (!initted) return 0;
+  if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0;
+  aspectRatio = taspectRatio;
+
+  Log::getInstance()->log("Video", Log::DEBUG, "Setting aspect to %i", aspectRatio);
+
+//  if (ioctl(fdVideo, AV_SET_VID_RATIO, aspectRatio) != 0) return 0;
+  return 1;
+}
+
+int VideoVPEOGL::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;
+
+//  if (ioctl(fdVideo, AV_SET_VID_MODE, mode) != 0) return 0;
+  return 1;
+}
+
+int VideoVPEOGL::signalOff()
+{
+//  if (ioctl(fdVideo, AV_SET_VID_DENC, 0) != 0) return 0;
+  return 1;
+}
+
+int VideoVPEOGL::signalOn()
+{
+//  if (ioctl(fdVideo, AV_SET_VID_DENC, 1) != 0) return 0;
+  return 1;
+}
+
+int VideoVPEOGL::setSource()
+{
+  if (!initted) return 0;
+
+  // What does this do...
+//  if (ioctl(fdVideo, AV_SET_VID_SRC, 1) != 0) return 0;
+  return 1;
+}
+
+int VideoVPEOGL::setPosition(int x, int y)
+{
+  if (!initted) return 0;
+
+//  vid_pos_regs_t pos_d;
+//  pos_d.x = x;
+//  pos_d.y = y;
+
+/*  vid_pos_regs_t pos_d;
+
+  memset(&pos_d, 0, sizeof(pos_d));
+
+  pos_d.dest.y = y;
+  pos_d.dest.x = x;
+/*
+typedef struct {
+  int w;
+  int h;
+  int scale;
+  int x1;
+  int y;
+  int x;
+  int y2;
+  int x3;
+  int y3;
+  int x4;
+  int y4;
+} vid_pos_regs_t;
+*/
+
+/*
+  pos_d.w = 100;
+  pos_d.h = 30;
+  pos_d.scale = 2;
+  pos_d.x1 = 0;
+  pos_d.y = 100;            // Top left X
+  pos_d.x = 50;            // Top left Y
+  pos_d.y2 = 30;
+  pos_d.x3 = 60;
+  pos_d.y3 = 90;
+  pos_d.x4 = 120;
+  pos_d.y4 = 150;
+*/
+
+//  if (ioctl(fdVideo, AV_SET_VID_POSITION, &pos_d) != 0) return 0;
+  return 1;
+}
+
+int VideoVPEOGL::sync()
+{
+  if (!initted) return 0;
+
+//  if (ioctl(fdVideo, AV_SET_VID_SYNC, 2) != 0) return 0;
+  return 1;
+}
+
+void VideoVPEOGL::initMuxer(bool iframe)
+{
+       char buffer[1024];
+       lastpacketnum=-1;
+       iframemode=iframe;
+  if (muxout) return;
+  sprintf(buffer,"/share/dev/muxout%d.ts",muxnumber);
+  filemutex.Lock(); 
+  audioconti=videoconti=0;
+  muxout=fopen(buffer,"wb");
+  filemutex.Unlock();
+  WriteOutPATPMT();
+  Log::getInstance()->log("Video", Log::DEBUG, 
+              "Create file %s with result %d",buffer,muxout);
+}
+
+void VideoVPEOGL::deinitMuxer()
+{
+  if (muxout)
+  {
+         filemutex.Lock();
+         FILE*temp=muxout;
+         muxout=NULL;
+         audioconti=videoconti=0;
+         filemutex.Unlock();
+         Log::getInstance()->log("Video", Log::DEBUG, 
+              "Close mux");
+
+         fclose(temp);
+         muxnumber++;
+  }
+}
+
+
+int VideoVPEOGL::play()
+{
+  if (!initted) return 0;
+
+  
+
+//  if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
+  return 1;
+}
+
+int VideoVPEOGL::stop()
+{
+  if (!initted) return 0;
+
+  
+
+//  if (ioctl(fdVideo, AV_SET_VID_STOP, 0) != 0) return 0;
+  return 1;
+}
+
+int VideoVPEOGL::reset()
+{
+  if (!initted) return 0;
+//  if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0;
+  return 1;
+}
+
+int VideoVPEOGL::pause()
+{
+  if (!initted) return 0;
+
+//  if (ioctl(fdVideo, AV_SET_VID_PAUSE, 0) != 0) return 0;
+  return 1;
+}
+
+int VideoVPEOGL::unPause() // FIXME get rid - same as play!!
+{
+  if (!initted) return 0;
+//  if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
+  return 1;
+}
+
+int VideoVPEOGL::fastForward()
+{
+  if (!initted) return 0;
+
+//  if (ioctl(fdVideo, AV_SET_VID_FFWD, 1) != 0) return 0;
+  return 1;
+}
+
+int VideoVPEOGL::unFastForward()
+{
+  if (!initted) return 0;
+
+//  if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0; // don't need this.
+
+ //// if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
+  return 1;
+}
+
+int VideoVPEOGL::attachFrameBuffer()
+{
+  if (!initted) return 0;
+
+//  if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
+  return 1;
+}
+
+int VideoVPEOGL::blank(void)
+{
+//  if (ioctl(fdVideo, AV_SET_VID_FB, 1) != 0) return 0;
+//  if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
+  return 1;
+}
+
+ULLONG VideoVPEOGL::getCurrentTimestamp()
+{
+/*  sync_data_t timestamps;
+  if (ioctl(fdVideo, AV_GET_VID_TIMESTAMPS, &timestamps) == 0)
+  {
+    // FIXME are these the right way around?
+
+    timestamps.stc = (timestamps.stc >> 31 ) | (timestamps.stc & 1);
+    timestamps.pts = (timestamps.pts >> 31 ) | (timestamps.pts & 1);
+
+    return timestamps.stc;
+  }
+  else
+  {
+    return 0;
+  }*/
+  return 0;
+}
+
+ULONG VideoVPEOGL::timecodeToFrameNumber(ULLONG timecode)
+{
+  if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
+  else               return (ULONG)(((double)timecode / (double)90000) * (double)30);
+}
+
+#ifdef DEV
+int VideoVPEOGL::test()
+{
+  return 0;
+
+//  ULLONG stc = 0;
+//  return ioctl(fdVideo, AV_SET_VID_STC, &stc);
+/*
+ // reset();
+  return 1;
+*/
+}
+
+int VideoVPEOGL::test2()
+{
+  return 0;
+}
+#endif
+
+void VideoVPEOGL::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
+{
+  mediapacket = mplist.front();
+}
+
+UINT VideoVPEOGL::DeliverMediaSample(UCHAR* buffer, UINT* samplepos)
+{
+  if (!muxout) return 0; 
+  
+  AudioVPE *audio=((AudioVPE*)audio->getInstance());
+ // Log::getInstance()->log("Video", Log::DEBUG, "lastpacket %d lastbuddypacket %d currentpacket %d",lastpacketnum,audio->getLastPacketNum(),mediapacket.index);
+  //format pes
+  switch (mediapacket.type) {
+         case MPTYPE_VIDEO_MPEG2:
+                 h264=false;
+                 buffer[mediapacket.pos_buffer + 3]=0xe0; break;
+         case MPTYPE_VIDEO_H264:
+                 h264=true;
+                 buffer[mediapacket.pos_buffer + 3]=0xe0; break;
+  };
+  
+  
+  if (lastpacketnum!=-1 && mediapacket.index-1!=lastpacketnum && mediapacket.index-1>audio->getLastPacketNum() && mediapacket.index>audio->getCurrentPacketNum()) {
+         Log::getInstance()->log("Video", Log::DEBUG, "Packet not in order, packet num %d, lastpacketnum %d, audio lastpacketnum %d",mediapacket.index,lastpacketnum,audio->getLastPacketNum());
+         return 0; //Not in order
+  }
+  
+
+/*  filemutex.Lock();
+  int written=fwrite(buffer + mediapacket.pos_buffer,1,mediapacket.length,muxout);*/
+  if (mediapacket.synched) WriteOutPATPMT();
+
+  int written=WriteOutTS(buffer + mediapacket.pos_buffer,mediapacket.length, mediapacket.type);
+  lastpacketnum=mediapacket.index;
+  //filemutex.Unlock();
+  //Log::getInstance()->log("Video", Log::DEBUG, "wrote %d bytes to mux",written);
+  
+
+  if (written == (int)mediapacket.length) { *samplepos = 0; return 1;}
+  if (written <= 0) {
+         return 0;
+  }
+  *samplepos = written;
+  // Handle a partial write. Is this possible? Should we bother? No!
+  return 1;
+}
+/*
+
+int VideoVPEOGL::WriteOutPCR(ULLONG pts)
+{
+       unsigned char ts_buffer[188];
+       unsigned char ts_crc[4];
+       unsigned char conti;
+       memset(ts_buffer,0xFF,188);
+
+       conti=videoconti;
+       ts_buffer[0]=0x47; //TS_SYNC
+       ts_buffer[1]=0x40; //Payload_start
+       ts_buffer[2]=100; 
+       ts_buffer[3]=0x20| conti;
+       ts_buffer[4]=183;
+       ts_buffer[5]=0x10; //PCR!
+
+               
+       
+    int tocopy=length;
+       unsigned char *dest=buffer;
+    filemutex.Lock();
+    unsigned int outlength=184;
+       while (tocopy>=outlength) {
+               
+               ts_buffer[3]=0x10 | conti;
+               fwrite(ts_buffer,1,4,muxout); //Header out
+
+               fwrite(dest,1, outlength,muxout);
+       
+
+               dest+=outlength;
+               tocopy-=outlength;
+               conti++;
+               conti&=0x0F;
+               ts_buffer[1]=0x00; //Payload_start
+       }
+       if (tocopy>0) {
+               ts_buffer[3]=0x30 | conti;//we have an adpation field
+               fwrite(ts_buffer,1,4,muxout); //Header out
+               unsigned char adaptionfield[2]={outlength-tocopy-1,0x00};
+               if (tocopy<183) fwrite(adaptionfield,1,2,muxout);
+               else fwrite(adaptionfield,1,1,muxout);
+               unsigned char paddy=0xFF;
+               if (outlength>tocopy+2) {
+                       for (int i=0;i<(outlength-tocopy-2);i++) fwrite(&paddy,1,1,muxout);
+               }
+               fwrite(dest,1,tocopy,muxout);
+       }
+       
+       
+       conti++;
+       conti&=0x0F;
+       filemutex.Unlock();
+
+       
+               videoconti=conti; 
+       
+}*/
+
+int VideoVPEOGL::WriteOutTS(const unsigned char *buffer,int length, int type)
+{
+       unsigned char ts_buffer[4];
+       unsigned char ts_crc[4];
+       unsigned char conti;
+       ts_buffer[0]=0x47; //TS_SYNC
+       ts_buffer[1]=0x40; //Payload_start
+       switch (type) {
+        case MPTYPE_VIDEO_MPEG2:
+        case MPTYPE_VIDEO_H264:
+               conti=videoconti;
+               ts_buffer[2]=100; break;
+               
+       case  MPTYPE_MPEG_AUDIO: 
+               conti=audioconti;
+               ts_buffer[2]=101; break;
+       case  MPTYPE_AC3:
+       case MPTYPE_AC3_PRE13:
+               conti=audioconti;
+               ts_buffer[2]=102; break;
+       default:
+               return 0; break; //????
+       };
+    int tocopy=length;
+       const unsigned char *dest=buffer;
+    filemutex.Lock();
+    unsigned int outlength=184;
+       while (tocopy>=outlength) {
+               
+               ts_buffer[3]=0x10 | conti;
+               fwrite(ts_buffer,1,4,muxout); //Header out
+
+               fwrite(dest,1, outlength,muxout);
+       
+
+               dest+=outlength;
+               tocopy-=outlength;
+               conti++;
+               conti&=0x0F;
+               ts_buffer[1]=0x00; //Payload_start
+       }
+       if (tocopy>0) {
+               ts_buffer[3]=0x30 | conti;//we have an adpation field
+               fwrite(ts_buffer,1,4,muxout); //Header out
+               unsigned char adaptionfield[2]={outlength-tocopy-1,0x00};
+               if (tocopy<183) fwrite(adaptionfield,1,2,muxout);
+               else fwrite(adaptionfield,1,1,muxout);
+               unsigned char paddy=0xFF;
+               if (outlength>tocopy+2) {
+                       for (int i=0;i<(outlength-tocopy-2);i++) fwrite(&paddy,1,1,muxout);
+               }
+               fwrite(dest,1,tocopy,muxout);
+       }
+       
+       
+       conti++;
+       conti&=0x0F;
+       filemutex.Unlock();
+
+       switch (type) {
+        case MPTYPE_VIDEO_MPEG2:
+         case MPTYPE_VIDEO_H264:
+               videoconti=conti; break;
+               
+       case  MPTYPE_MPEG_AUDIO: 
+       case  MPTYPE_AC3: 
+       case MPTYPE_AC3_PRE13:
+               audioconti=conti;
+               break;
+       };
+       return length;
+       
+}
+
+void VideoVPEOGL::WriteOutPATPMT()
+{
+       unsigned char ts_buffer[188];
+       //PAT
+       memset(ts_buffer,0xFF,188);
+       ts_buffer[0]=0x47; //TS_SYNC
+       ts_buffer[1]=0x40; //Payload_start
+       ts_buffer[2]=0x00; 
+       ts_buffer[3]=0x10;
+       ts_buffer[4]=0x00;
+       ts_buffer[5]=0x00;//table id
+       ts_buffer[6]=0xB0; //Section syntax
+       ts_buffer[7]=13; //Section length
+       ts_buffer[8]=0x80;//PSID
+       ts_buffer[9]=0x08;//PSID lo 
+       ts_buffer[10]=0xC1 | (patversion << 1);
+       ts_buffer[11]=0x00;//section numbrt
+       ts_buffer[12]=0x00;
+       ts_buffer[13]=0x00; //hi program number
+       ts_buffer[14]=98; 
+       ts_buffer[15]=0xe0; 
+       ts_buffer[16]=98;
+       int crc =crc32((const char *)ts_buffer+5, 12, 0xFFFFFFFF);
+       int i = 0;
+       ts_buffer[17] = crc >> 24;
+       ts_buffer[18] = crc >> 16;
+       ts_buffer[19] = crc >> 8;
+       ts_buffer[20] = crc;
+       patversion++;
+       patversion&=0x1F;
+       filemutex.Lock();
+       fwrite(ts_buffer,1,188,muxout); //Header out
+       filemutex.Unlock();
+
+       //PMT
+       memset(ts_buffer,0xFF,188);
+       ts_buffer[0]=0x47; //TS_SYNC
+       ts_buffer[1]=0x40; //Payload_start
+       ts_buffer[2]=98; 
+       ts_buffer[3]=0x10;
+       ts_buffer[4]=0x00;
+       ts_buffer[5]=0x02;//table id
+       ts_buffer[6]=0xB0; //Section syntax
+       ts_buffer[7]=23; //Section length
+       ts_buffer[8]=0x00;//PSID
+       ts_buffer[9]=98;//PSID lo 
+       ts_buffer[10]=0xC1 | (pmtversion << 1);
+       ts_buffer[11]=0x00;//section numbrt
+       ts_buffer[12]=0x00;
+       ts_buffer[13]=0xE0 | 0x1F;
+       ts_buffer[14]=0xFF;//Video is pcr 
+       ts_buffer[15]=0xF0;//dummy 
+       ts_buffer[16]=0x00; //program info
+    //Video
+
+       if (h264) 
+       {
+               ts_buffer[17] = 0x1B; // stream type video
+       }
+       else
+       {
+               ts_buffer[17] = 0x02; // stream type video
+       }
+    ts_buffer[18] = 0xE0; //
+       ts_buffer[19]=100; //Video pid 
+       ts_buffer[20]= 0xF0; // 
+    ts_buffer[21]= 0x00; //
+       // audio
+       int add_length=0;
+       unsigned char atype=((AudioVPE*)Audio::getInstance())->getLastAType();
+       switch (atype) {
+       default:
+       case  MPTYPE_MPEG_AUDIO: 
+               ts_buffer[22] = 0x04; // stream type audio
+               ts_buffer[23] = 0xE0; //
+               ts_buffer[24]=101; //Audio pid 
+               ts_buffer[25]= 0xF0; // 
+               ts_buffer[26]= 0x00; //
+       break;
+       case  MPTYPE_AC3: 
+       case MPTYPE_AC3_PRE13:
+               ts_buffer[22] = 0x06; // stream type private
+               ts_buffer[23] = 0xE0; //
+               ts_buffer[24]=102; //ac3
+               ts_buffer[25]= 0xF0; // 
+               ts_buffer[26]= 0x03; //
+               ts_buffer[27] = 0x6A;
+               ts_buffer[28] = 0x01; // length
+               ts_buffer[29] = 0x00;
+               ts_buffer[7]+=3;
+               add_length=3;
+               break;
+       };
+       crc =crc32((const char *)ts_buffer+5, 22+add_length, 0xFFFFFFFF);
+       ts_buffer[27+add_length] = crc >> 24;
+       ts_buffer[28+add_length] = crc >> 16;
+       ts_buffer[29+add_length] = crc >> 8;
+       ts_buffer[30+add_length] = crc;
+       pmtversion++;
+       pmtversion&=0x1F;
+       filemutex.Lock();
+       fwrite(ts_buffer,1,188,muxout); //Header out
+       filemutex.Unlock();
+
+
+       
+}
+
+
+void VideoVPEOGL::ResetTimeOffsets()
+{
+}
+
+bool VideoVPEOGL::displayIFrame(const UCHAR* buffer, UINT length)
+{
+  //write(fdVideo, buffer, length);
+       if (!iframemode) EnterIframePlayback();
+       WriteOutTS(buffer,length, h264?MPTYPE_VIDEO_H264 :MPTYPE_VIDEO_MPEG2 );
+  lastpacketnum=-1;
+  return true;
+}
+
+int VideoVPEOGL::EnterIframePlayback()
+{
+       deinitMuxer();
+       initMuxer(true);
+       return 0;
+}
+
diff --git a/videovpeogl.h b/videovpeogl.h
new file mode 100644 (file)
index 0000000..f554ad4
--- /dev/null
@@ -0,0 +1,113 @@
+/*\r
+    Copyright 2004-2005 Chris Tallon 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+*/\r
+\r
+\r
+#ifndef VIDEOVPEOGL_H\r
+#define VIDEOVPEOGL_H\r
+\r
+#include "mutex.h"\r
+\r
+#include <stdio.h>\r
+#include <unistd.h>\r
+#include <fcntl.h>\r
+#include <sys/ioctl.h>\r
+#include <string.h>\r
+\r
+#include <stdint.h>\r
+\r
+#include "defines.h"\r
+#include "video.h"\r
+\r
+#define WRITE_PACKETS 16\r
+#define WRITE_LENGTH (32*1024)\r
+\r
+\r
+class VideoVPEOGL : public Video\r
+{\r
+  public:\r
+    VideoVPEOGL();\r
+    virtual ~VideoVPEOGL();\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
+    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 stop();\r
+    int pause();\r
+    int unPause();\r
+    int fastForward();\r
+    int unFastForward();\r
+    int reset();\r
+    int blank();\r
+    int signalOn();\r
+    int signalOff();\r
+    int attachFrameBuffer(); // What does this do?\r
+    ULONG timecodeToFrameNumber(ULLONG timecode);\r
+    ULLONG getCurrentTimestamp();\r
+    bool displayIFrame(const UCHAR* buffer, UINT length);\r
+\r
+    // Writing Data to Videodevice\r
+    virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);\r
+    virtual UINT DeliverMediaSample(UCHAR* buffer, UINT* samplepos);\r
+    virtual long long SetStartOffset(long long curreftime, bool *rsync)\r
+    { return 0; };\r
+    virtual void ResetTimeOffsets();\r
+\r
+       virtual bool supportsh264(){return true;};\r
+\r
+       int WriteOutTS(const unsigned char *buffer,int length, int type);\r
+       void WriteOutPATPMT();\r
+\r
+\r
+       Mutex *getMuxMutex() {return &filemutex;}; //File must be pointer of pointer Thread safety!\r
+       FILE *getMuxFile() {return muxout;}; //File must be pointer of pointer Thread safety!\r
+       void initMuxer(bool iframe=false);\r
+       void deinitMuxer();\r
+\r
+       int getLastPacketNum() {return lastpacketnum;}; \r
+#ifdef DEV\r
+    int test();\r
+    int test2();\r
+#endif\r
+\r
+  private:\r
+          int EnterIframePlayback();\r
+          bool iframemode;\r
+       \r
+         FILE* muxout;\r
+         int muxnumber;\r
+         Mutex filemutex;\r
+         int lastpacketnum;\r
+         unsigned char audioconti,videoconti;\r
+         unsigned int patversion,pmtversion;\r
+    \r
+       MediaPacket mediapacket;\r
+};\r
+\r
+#endif\r
diff --git a/wjpegcomplex.cc b/wjpegcomplex.cc
new file mode 100644 (file)
index 0000000..b0a58f6
--- /dev/null
@@ -0,0 +1,892 @@
+/*\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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+*/\r
+#include "boxx.h"\r
+#include "wjpegcomplex.h"\r
+#include <setjmp.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+\r
+#ifndef WIN32\r
+#include <unistd.h>\r
+#else\r
+\r
+#endif\r
+\r
+#include "i18n.h"\r
+#include "log.h"\r
+#include "surface.h"\r
+\r
+#ifndef __ANDROID__\r
+extern "C"\r
+{\r
+  #include <jpeglib.h>\r
+}\r
+#endif\r
+\r
+#ifndef __ANDROID__\r
+//#define USE_BUFFER\r
+//#define EXTENDED_JPEGLIB\r
+\r
+//a struct to store user data for the jpeg decompressor\r
+class jpegUserData{\r
+  public:\r
+    WJpeg::JpegControl * ctl;\r
+    JpegReader *reader;\r
+    jpegUserData() {\r
+      ctl=NULL;\r
+      reader=NULL;\r
+      }\r
+  };\r
+\r
+//the scale factors supported by the jpeg lib\r
+\r
+struct scale{\r
+  UINT num;\r
+  UINT denom;\r
+};\r
+\r
+\r
+struct scale jpegFactors[]={\r
+#ifndef EXTENDED_JPEGLIB\r
+  {1,1},{1,2},{1,4},{1,8}\r
+#else\r
+  {1,1},{7,8},{3,4},{5,8},{1,2},{3,8},{1,4},{1,8}\r
+#endif\r
+};\r
+#endif\r
+\r
+#ifdef WIN32\r
+#define LocalReader WindowsResourceJpegReader\r
+class WindowsResourceJpegReader: public JpegReader {\r
+  public:\r
+  virtual ULONG initRead(const char *filename);\r
+  virtual ULONG readChunk(ULONG offset,ULONG len,char **buf);\r
+  virtual ULONG getSize();\r
+  virtual ~WindowsResourceJpegReader();\r
+protected:\r
+  HGLOBAL hres;\r
+  LPVOID buffer;\r
+  DWORD size;\r
+};\r
+\r
+ULONG WindowsResourceJpegReader::initRead(const char *filename)\r
+{\r
+    HRSRC res=FindResource(NULL,filename,RT_RCDATA);\r
+    hres=LoadResource(NULL,res);\r
+    buffer=LockResource(hres);\r
+    size=SizeofResource(NULL,res);\r
+    //CloseHandle(hres);\r
+    return size;\r
+}\r
+\r
+ ULONG WindowsResourceJpegReader::readChunk(ULONG offset,ULONG len,char **buf)\r
+{\r
+    if (offset>size) return 0;\r
+    ULONG toread=min(size-offset,len);\r
+    char* buffy=(char*)malloc(toread);\r
+    memcpy(buffy,((char*)buffer)+offset,toread);\r
+    *buf=buffy;\r
+    return toread;\r
+}\r
+\r
+ WindowsResourceJpegReader::~WindowsResourceJpegReader(){\r
+    buffer=NULL;\r
+    size=0;\r
+    FreeResource(hres);\r
+ }\r
+\r
+ ULONG WindowsResourceJpegReader::getSize(){\r
+   return (ULONG)size;\r
+}\r
+#else\r
+\r
+#define LocalReader LocalJpegReader\r
+class LocalJpegReader: public JpegReader {\r
+  public:\r
+  virtual ULONG initRead(const char *filename);\r
+  virtual ULONG readChunk(ULONG offset,ULONG len,char **buf);\r
+  virtual ~LocalJpegReader();\r
+  virtual ULONG getSize();\r
+  LocalJpegReader();\r
+protected:\r
+  FILE *file;\r
+  ULONG size;\r
+};\r
+\r
+LocalJpegReader::LocalJpegReader(){\r
+  file=NULL;\r
+  size=0;\r
+}\r
+\r
+ULONG LocalJpegReader::initRead(const char *filename)\r
+{\r
+    if (file) fclose(file);\r
+    size=0;\r
+    file=fopen(filename,"r");\r
+    if (file) {\r
+      struct stat st;\r
+      if (fstat(fileno(file), &st) != 0) return 0;\r
+      size= st.st_size;\r
+      return size;\r
+    }\r
+    Log::getInstance()->log("WJepg", Log::ERR, "localReader unable to open File %s", filename);\r
+    return 0;\r
+}\r
+\r
+ULONG LocalJpegReader::readChunk(ULONG offset,ULONG len,char **buf)\r
+{\r
+   *buf=NULL;\r
+   ULONG bread=0;\r
+   if (file) {\r
+     ULLONG cpos=ftell(file);\r
+     if (offset != cpos) {\r
+      fseek(file,offset-cpos,SEEK_CUR);\r
+     }\r
+     if (offset != (ULONG)ftell(file)) {\r
+       Log::getInstance()->log("WJepg", Log::ERR, "readChunk pos = %lu not available", offset);\r
+     }\r
+     else {\r
+       *buf=(char *)malloc(len);\r
+       if ( ! (*buf)) {\r
+         Log::getInstance()->log("WJepg", Log::ERR, "readChunk pos = %lu not available", offset);\r
+       }\r
+       else {\r
+         bread=fread(*buf,1,len,file);\r
+       }\r
+     }\r
+   }\r
+   return bread;\r
+}\r
+\r
+LocalJpegReader::~LocalJpegReader(){\r
+  if (file) fclose(file);\r
+  file=NULL;\r
+}\r
+ULONG LocalJpegReader::getSize(){\r
+  return size;\r
+}\r
+#endif\r
+\r
+#ifndef __ANDROID__\r
+/*----------------------------------------------------------------\r
+  the jpeg lib routines\r
+  ----------------------------------------------------------------\r
+ */\r
+\r
+extern "C" {\r
+\r
+\r
+struct my_error_mgr {\r
+  struct jpeg_error_mgr pub;    /* "public" fields */\r
+\r
+  jmp_buf setjmp_buffer;        /* for return to caller */\r
+};\r
+\r
+typedef struct my_error_mgr * my_error_ptr;\r
+\r
+/*\r
+ * Here's the routine that will replace the standard error_exit method:\r
+ */\r
+\r
+METHODDEF(void)\r
+my_error_exit (j_common_ptr cinfo)\r
+{\r
+  /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */\r
+  my_error_ptr myerr = (my_error_ptr) cinfo->err;\r
+\r
+  /* Always display the message. */\r
+  /* We could postpone this until after returning, if we chose. */\r
+  (*cinfo->err->output_message) (cinfo);\r
+  /* Return control to the setjmp point */\r
+  longjmp(myerr->setjmp_buffer, 1);\r
+}\r
+\r
+ULONG jpeg_call_reader(ULONG offset,ULONG size,char ** buf,void *cb) {\r
+  jpegUserData *user=(jpegUserData *)cb;\r
+  return user->reader->readChunk(offset,size,buf);\r
+}\r
+//the memory buffer reader for the jpeg lib\r
+//taken from jdatasrc.c\r
+\r
+#include "jinclude.h"\r
+#include "jpeglib.h"\r
+#include "jerror.h"\r
+\r
+\r
+typedef struct {\r
+  struct jpeg_source_mgr pub;   /* public fields */\r
+\r
+  JOCTET * buffer;              /* start of buffer */\r
+  boolean start_of_file;        /* have we gotten any data yet? */\r
+  void * userdata;              /* used for callback */\r
+  ULONG offset;\r
+} my_source_mgr;\r
+\r
+typedef my_source_mgr * my_src_ptr;\r
+\r
+#define INPUT_BUF_SIZE  (64*4096)       /* choose an efficiently fread'able size */\r
+\r
+\r
+/*\r
+ * Initialize source --- called by jpeg_read_header\r
+ * before any data is actually read.\r
+ */\r
+\r
+METHODDEF(void)\r
+linit_source (j_decompress_ptr cinfo)\r
+{\r
+  my_src_ptr src = (my_src_ptr) cinfo->src;\r
+\r
+  /* We reset the empty-input-file flag for each image,\r
+   * but we don't clear the input buffer.\r
+   * This is correct behavior for reading a series of images from one source.\r
+   */\r
+  src->start_of_file = TRUE;\r
+  src->offset=0;\r
+}\r
+\r
+\r
+/*\r
+ * Fill the input buffer --- called whenever buffer is emptied.\r
+ *\r
+ * In typical applications, this should read fresh data into the buffer\r
+ * (ignoring the current state of next_input_byte & bytes_in_buffer),\r
+ * reset the pointer & count to the start of the buffer, and return TRUE\r
+ * indicating that the buffer has been reloaded.  It is not necessary to\r
+ * fill the buffer entirely, only to obtain at least one more byte.\r
+ *\r
+ * There is no such thing as an EOF return.  If the end of the file has been\r
+ * reached, the routine has a choice of ERREXIT() or inserting fake data into\r
+ * the buffer.  In most cases, generating a warning message and inserting a\r
+ * fake EOI marker is the best course of action --- this will allow the\r
+ * decompressor to output however much of the image is there.  However,\r
+ * the resulting error message is misleading if the real problem is an empty\r
+ * input file, so we handle that case specially.\r
+ *\r
+ * In applications that need to be able to suspend compression due to input\r
+ * not being available yet, a FALSE return indicates that no more data can be\r
+ * obtained right now, but more may be forthcoming later.  In this situation,\r
+ * the decompressor will return to its caller (with an indication of the\r
+ * number of scanlines it has read, if any).  The application should resume\r
+ * decompression after it has loaded more data into the input buffer.  Note\r
+ * that there are substantial restrictions on the use of suspension --- see\r
+ * the documentation.\r
+ *\r
+ * When suspending, the decompressor will back up to a convenient restart point\r
+ * (typically the start of the current MCU). next_input_byte & bytes_in_buffer\r
+ * indicate where the restart point will be if the current call returns FALSE.\r
+ * Data beyond this point must be rescanned after resumption, so move it to\r
+ * the front of the buffer rather than discarding it.\r
+ */\r
+\r
+METHODDEF(boolean)\r
+lfill_input_buffer (j_decompress_ptr cinfo)\r
+{\r
+  my_src_ptr src = (my_src_ptr) cinfo->src;\r
+  size_t nbytes;\r
+  if (src->buffer) free(src->buffer);\r
+  src->buffer=NULL;\r
+  nbytes = jpeg_call_reader(src->offset, INPUT_BUF_SIZE,(char **)&(src->buffer), src->userdata);\r
+\r
+  if (nbytes <= 0) {\r
+    WARNMS(cinfo, JWRN_JPEG_EOF);\r
+    src->buffer =  (JOCTET *)malloc(2);\r
+    src->buffer[0] = (JOCTET) 0xFF;\r
+    src->buffer[1] = (JOCTET) JPEG_EOI;\r
+    nbytes = 2;\r
+\r
+  }\r
+  src->offset+=nbytes;\r
+\r
+  src->pub.next_input_byte = src->buffer;\r
+  src->pub.bytes_in_buffer = nbytes;\r
+  src->start_of_file = FALSE;\r
+\r
+  return TRUE;\r
+}\r
+\r
+\r
+/*\r
+ * Skip data --- used to skip over a potentially large amount of\r
+ * uninteresting data (such as an APPn marker).\r
+ *\r
+ * Writers of suspendable-input applications must note that skip_input_data\r
+ * is not granted the right to give a suspension return.  If the skip extends\r
+ * beyond the data currently in the buffer, the buffer can be marked empty so\r
+ * that the next read will cause a fill_input_buffer call that can suspend.\r
+ * Arranging for additional bytes to be discarded before reloading the input\r
+ * buffer is the application writer's problem.\r
+ */\r
+\r
+METHODDEF(void)\r
+lskip_input_data (j_decompress_ptr cinfo, long num_bytes)\r
+{\r
+  my_src_ptr src = (my_src_ptr) cinfo->src;\r
+\r
+  /* Just a dumb implementation for now.  Could use fseek() except\r
+   * it doesn't work on pipes.  Not clear that being smart is worth\r
+   * any trouble anyway --- large skips are infrequent.\r
+   */\r
+  if (num_bytes > 0) {\r
+    while (num_bytes > (long) src->pub.bytes_in_buffer) {\r
+      num_bytes -= (long) src->pub.bytes_in_buffer;\r
+      (void) lfill_input_buffer(cinfo);\r
+      /* note we assume that fill_input_buffer will never return FALSE,\r
+       * so suspension need not be handled.\r
+       */\r
+    }\r
+    src->pub.next_input_byte += (size_t) num_bytes;\r
+    src->pub.bytes_in_buffer -= (size_t) num_bytes;\r
+  }\r
+}\r
+\r
+\r
+/*\r
+ * An additional method that can be provided by data source modules is the\r
+ * resync_to_restart method for error recovery in the presence of RST markers.\r
+ * For the moment, this source module just uses the default resync method\r
+ * provided by the JPEG library.  That method assumes that no backtracking\r
+ * is possible.\r
+ */\r
+\r
+\r
+/*\r
+ * Terminate source --- called by jpeg_finish_decompress\r
+ * after all data has been read.  Often a no-op.\r
+ *\r
+ * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding\r
+ * application must deal with any cleanup that should happen even\r
+ * for error exit.\r
+ */\r
+\r
+METHODDEF(void)\r
+lterm_source (j_decompress_ptr cinfo)\r
+{\r
+  /* no work necessary here */\r
+}\r
+\r
+\r
+/*\r
+ * Prepare for input from a stdio stream.\r
+ * The caller must have already opened the stream, and is responsible\r
+ * for closing it after finishing decompression.\r
+ */\r
+\r
+extern "C" void\r
+jpeg_memio_src (j_decompress_ptr cinfo, void * userdata)\r
+{\r
+  my_src_ptr src;\r
+\r
+  /* The source object and input buffer are made permanent so that a series\r
+   * of JPEG images can be read from the same file by calling jpeg_stdio_src\r
+   * only before the first one.  (If we discarded the buffer at the end of\r
+   * one image, we'd likely lose the start of the next one.)\r
+   * This makes it unsafe to use this manager and a different source\r
+   * manager serially with the same JPEG object.  Caveat programmer.\r
+   */\r
+  if (cinfo->src == NULL) {     /* first time for this JPEG object? */\r
+    cinfo->src = (struct jpeg_source_mgr *)\r
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,\r
+                                  SIZEOF(my_source_mgr));\r
+    src = (my_src_ptr) cinfo->src;\r
+    src->buffer = NULL;\r
+  }\r
+\r
+  src = (my_src_ptr) cinfo->src;\r
+  src->pub.init_source = linit_source;\r
+  src->pub.fill_input_buffer = lfill_input_buffer;\r
+  src->pub.skip_input_data = lskip_input_data;\r
+  src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */\r
+  src->pub.term_source = lterm_source;\r
+  src->userdata=userdata;\r
+  src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */\r
+  src->pub.next_input_byte = NULL; /* until buffer loaded */\r
+  src->offset=0;\r
+  src->userdata=userdata;\r
+  if (src->buffer) {\r
+     free(src->buffer);\r
+     src->buffer=NULL;\r
+     }\r
+}\r
+/* cleanup to be called before cleanup of cinfo*/\r
+extern "C" void\r
+jpeg_memio_cleanup (j_decompress_ptr cinfo) {\r
+  my_src_ptr src=(my_src_ptr)cinfo->src;\r
+  Log::getInstance()->log("BJpeg", Log::DEBUG, "cleanup src, src=%p, buf=%p",src,(src?src->buffer:0));\r
+  if (src && src->buffer) {\r
+    free(src->buffer);\r
+    src->buffer=NULL;\r
+    }\r
+}\r
+\r
+//taken from mvpmc\r
+//http://git.mvpmc.org/cgi-bin/gitweb.cgi?p=mvpmc.git;a=blob_plain;h=02d4354c0cbbed802a9aa1478918a49fcbf61d00;f=libs/libwidget/image_jpeg.c\r
+\r
+#define GET2BYTES(cinfo, V, swap, offset) do { \\r
+                if (cinfo->src->bytes_in_buffer == 0) (*mysrc->pub.fill_input_buffer)(cinfo); \\r
+                cinfo->src->bytes_in_buffer--; \\r
+                V = (*cinfo->src->next_input_byte++) << (swap?0:8); \\r
+                if (cinfo->src->bytes_in_buffer == 0) (*mysrc->pub.fill_input_buffer)(cinfo); \\r
+                cinfo->src->bytes_in_buffer--; \\r
+                V += (*cinfo->src->next_input_byte++) << (swap?8:0); \\r
+                offset += 2; } while(0) \r
+\r
+#define GET4BYTES(cinfo, V, swap, offset) do { \\r
+                if (cinfo->src->bytes_in_buffer == 0) (*mysrc->pub.fill_input_buffer)(cinfo); \\r
+                cinfo->src->bytes_in_buffer--; \\r
+                V = (*cinfo->src->next_input_byte++) << (swap?0:24); \\r
+                if (cinfo->src->bytes_in_buffer == 0) (*mysrc->pub.fill_input_buffer)(cinfo); \\r
+                cinfo->src->bytes_in_buffer--; \\r
+                V += (*cinfo->src->next_input_byte++) << (swap?8:16); \\r
+                if (cinfo->src->bytes_in_buffer == 0) (*mysrc->pub.fill_input_buffer)(cinfo); \\r
+                cinfo->src->bytes_in_buffer--; \\r
+                V += (*cinfo->src->next_input_byte++) << (swap?16:8); \\r
+                if (cinfo->src->bytes_in_buffer == 0) (*mysrc->pub.fill_input_buffer)(cinfo); \\r
+                cinfo->src->bytes_in_buffer--; \\r
+                V += (*cinfo->src->next_input_byte++) << (swap?24:0); \\r
+                offset += 4; } while(0)\r
+\r
+static boolean\r
+get_exif_orient (j_decompress_ptr cinfo)\r
+/* Get the Exif orientation info */\r
+{\r
+        unsigned int tmp, offset, length, numtags;\r
+        int orient=-1;\r
+        jpegUserData * ud=0;\r
+        boolean swap;\r
+        orient = 1;\r
+        offset = 0;\r
+        my_src_ptr mysrc = (my_src_ptr) cinfo->src;\r
+\r
+        /* marker length */\r
+        GET2BYTES(cinfo, length, 0, offset);\r
+        if (length<8) goto err;\r
+        /* Exif header */\r
+        GET4BYTES(cinfo, tmp, 0, offset);\r
+        if (tmp != 0x45786966) goto err;\r
+        GET2BYTES(cinfo, tmp, 0, offset);\r
+        if (tmp != 0x0000) goto err;\r
+        /* Byte-order */\r
+        GET2BYTES(cinfo, tmp, 0, offset);\r
+        if (tmp == 0x4949) swap = 1;\r
+        else if (tmp == 0x4d4d) swap = 0;\r
+        else goto err;\r
+        GET2BYTES(cinfo, tmp, swap, offset);\r
+        if (tmp != 0x002A) goto err;\r
+        /* offset to first IFD */\r
+        GET4BYTES(cinfo, tmp, swap, offset);\r
+        offset += tmp-8;\r
+        (*mysrc->pub.skip_input_data)(cinfo, tmp-8);\r
+        /* number of tags in IFD */\r
+        GET2BYTES(cinfo, numtags, swap, offset);\r
+        if (numtags == 0) goto err;\r
+        \r
+        /* Search for Orientation Tag in IFD0 */\r
+        for (;;) {\r
+                if (offset > length-12) goto err;\r
+                GET2BYTES(cinfo, tmp, swap, offset);\r
+                if (tmp == 0x0112) break; /* found Orientation Tag */\r
+                if (--numtags == 0) goto err;\r
+                offset += 10;\r
+                (*mysrc->pub.skip_input_data)(cinfo, 10);\r
+        }\r
+        offset += 6;\r
+        (*mysrc->pub.skip_input_data)(cinfo, 6);\r
+        GET2BYTES(cinfo, orient, swap, offset);\r
+        if( orient==0 || orient>8 ) orient = 1;\r
+        \r
+        Log::getInstance()->log("WJpeg", Log::DEBUG, "read exif orientation %u", orient);\r
+        ud=(jpegUserData *)(mysrc->userdata);\r
+        switch(orient) {\r
+          case 3:\r
+            ud->ctl->exifRotation=WJpeg::ROT_180;\r
+            break;\r
+          case 6:\r
+            ud->ctl->exifRotation=WJpeg::ROT_90;\r
+            break;\r
+          case 8:\r
+            ud->ctl->exifRotation=WJpeg::ROT_270;\r
+            break;\r
+        }\r
+\r
+err:\r
+        (*mysrc->pub.skip_input_data)(cinfo, length-offset);\r
+        return TRUE;\r
+}\r
+}\r
+#endif\r
+/*----------------------------------------------------------------\r
+  the implementation\r
+  ----------------------------------------------------------------\r
+ */\r
+\r
+\r
+WJpegComplex::WJpegComplex(){\r
+  reader=NULL;\r
+  owningReader=false;\r
+  errbuf[0]=0;\r
+}\r
+\r
+WJpegComplex::~WJpegComplex() {\r
+  if (owningReader && reader) delete reader;\r
+}\r
+\r
+int WJpegComplex::init(const char* tfileName)\r
+{\r
+  if (owningReader && reader) delete reader;\r
+  errbuf[0]=0; //clean error state\r
+  LocalReader *myreader=new LocalReader();\r
+  reader=myreader;\r
+  owningReader=true;\r
+  ULONG psize=myreader->initRead(tfileName);\r
+  if (psize == 0) {\r
+    delete reader;\r
+    reader=NULL;\r
+    owningReader=false;\r
+    SNPRINTF(errbuf,200,"unable to open %s",tfileName);\r
+    return 0;\r
+  }\r
+  return 1;\r
+}\r
+\r
+\r
+\r
+\r
+bool WJpegComplex::hasError() {\r
+  return (errbuf[0] != 0);\r
+}\r
+void WJpegComplex::draw()\r
+{\r
+  bool ok=false;\r
+  JpegControl ctl;\r
+  if (reader) {\r
+    Region myRegion;\r
+    Surface *sfc=getSurface(myRegion);\r
+    myRegion.w=area.w;\r
+    myRegion.h=area.h;\r
+    ctl.area=myRegion;\r
+    ctl.enlarge=true;\r
+    if (drawJpeg(&ctl,sfc,reader,backgroundColour) ) ok=true;\r
+  }\r
+  else {\r
+    SNPRINTF(errbuf,200,"jpeg reader not initialized");\r
+  }\r
+  if (! ok) {\r
+    drawTextCentre(tr("Jpeg ERROR"), 240, 170, Colour::LIGHTTEXT);\r
+    if (errbuf[0] != 0) drawTextCentre(errbuf,240,200, Colour::LIGHTTEXT);\r
+    if (ctl.error[0] != 0) drawTextCentre(ctl.error,240,230, Colour::LIGHTTEXT);\r
+  }\r
+}\r
+\r
+\r
+\r
+/**\r
+  the main drawing function\r
+  this will read the pciture via the reader\r
+  and draw directly into the surface\r
+  it will compute an appropriate scale and set the infos in the\r
+  JpegControl structure\r
+**/  \r
+\r
+#ifndef __ANDROID__\r
+\r
+bool WJpegComplex::drawJpeg(JpegControl * ctl,Surface * sfc,JpegReader *rdr, Colour & backgroundColour) {\r
+  Log* logger = Log::getInstance();\r
+  if (! rdr || ! sfc) {\r
+    logger->log("BJpeg", Log::ERR, "JPEG error rdr=NULL or sfc=NULL");\r
+    return false;\r
+  }\r
+  logger->log("BJpeg", Log::DEBUG, "draw Jpeg Started sfc=%p, rdr=%p",sfc,rdr);\r
+  unsigned char* buffer =NULL;\r
+  struct jpeg_decompress_struct cinfo;\r
+  struct my_error_mgr jerr;\r
+  cinfo.err = jpeg_std_error(&jerr.pub);\r
+  jerr.pub.error_exit = my_error_exit;\r
+  /* Establish the setjmp return context for my_error_exit to use. */\r
+  if (setjmp(jerr.setjmp_buffer)) {\r
+    /* If we get here, the JPEG code has signaled an error.\r
+     * We need to clean up the JPEG object, close the input file, and return.\r
+     */\r
+    if (rdr) jpeg_memio_cleanup(&cinfo);\r
+    jpeg_destroy_decompress(&cinfo);\r
+    logger->log("BJpeg", Log::ERR, "JPEG error");\r
+    if (buffer) free(buffer);\r
+    return false;\r
+  }\r
+  jpegUserData userdata;\r
+  int xpos=0;\r
+  int ypos=0;\r
+  jpeg_create_decompress(&cinfo);\r
+  userdata.reader=rdr;\r
+  userdata.ctl=ctl;\r
+  ctl->exifRotation=ROT_0;\r
+  ctl->error[0]=0;\r
+  ctl->exifDate[0]=0;\r
+  //create the input for the jpeg lib\r
+  jpeg_memio_src(&cinfo,(void *)(&userdata));\r
+  //processor for EXIF data\r
+  jpeg_set_marker_processor(&cinfo, JPEG_APP0+1, get_exif_orient);\r
+  //read in header info\r
+  jpeg_read_header(&cinfo, TRUE);\r
+  ctl->picw=cinfo.image_width;\r
+  ctl->pich=cinfo.image_height;\r
+  ctl->compressedSize=rdr->getSize();\r
+  //now we have important info available in ctl (pictuerw,h, exif orientation,size)\r
+  //compute rotation due to the defined enum values we can simply add them\r
+  ctl->finalRotation=(enum Rotation)((ctl->rotation+ctl->exifRotation)%4);\r
+  logger->log("BJpeg", Log::DEBUG, "JPEG read header w=%i h=%i, rot=%i", ctl->picw,ctl->pich,ctl->finalRotation);\r
+  //now we have to compute the scale\r
+  //input: ctl->picw,ctl->pich,ctl->finalRotation,ctl->mode,ctl->scaleAmount, ctl->scaleafter\r
+  //       list of available jpeg scale factors\r
+  //out:   scalenum,scaledenom,scaleafter\r
+\r
+  UINT picturew=ctl->picw;\r
+  UINT pictureh=ctl->pich;\r
+  switch (ctl->finalRotation){\r
+    case ROT_90:\r
+    case ROT_270:\r
+      pictureh=ctl->picw;\r
+      picturew=ctl->pich;\r
+      break;\r
+    default:\r
+      break;\r
+  }\r
+  UINT scalenum=1;\r
+  UINT scaledenom=1;\r
+  UINT scaleafter=1;\r
+  if (! ctl->enlarge) {\r
+    //scale - compute the factors to fit 100%\r
+    int scalew=1000*picturew/ctl->area.w;\r
+    int scaleh=1000*pictureh/ctl->area.h;\r
+    int scale=scaleh;\r
+    if (scalew > scaleh) scale=scalew;\r
+\r
+    //OK now find out which is the optimal setting\r
+    //rule: find settings being nearest to:\r
+    //   mode=LETTER - smaller or equal screen size (i.e. scale*scalefactor <= 1000)\r
+    //   mode=CROP   - bigger or equal screen size (i.e. scale *scalefactor>= 1000)\r
+    //   mode=CROPPERCENT - smaller or equal screensize*scaleamount (i.e. scale*scalefactor<= 1000*scaleamount)\r
+    //                      scaleamount is in % - so in reality we use scaleamount*10 instead scaleamount*1000\r
+    //the scalefactor computes as scalenum/(scaledenom*scaleafter)\r
+    scaledenom=8;\r
+    int minDiff=1000;\r
+    logger->log("BJpeg", Log::DEBUG, "start scaling screenw=%u, screenh=%u, pw=%u,ph=%u, scale=%d, mode=%d, %%=%u, after=%u",\r
+       ctl->area.w,ctl->area.h,picturew,pictureh,scale,(int)ctl->mode,ctl->scaleAmount, ctl->scaleafter); \r
+    for (UINT j=0;j<sizeof(jpegFactors)/sizeof(jpegFactors[0]);j++) {\r
+      for (UINT sa=1;sa<=ctl->scaleafter;sa++) {\r
+        int curf=(scale*jpegFactors[j].num)/(jpegFactors[j].denom*sa);\r
+        bool setThis=false;\r
+        logger->log("BJpeg", Log::DEBUG, "testing scale curf=%d,num=%u,denom=%u,after=%u,minDiff=%d", \r
+            curf,jpegFactors[j].num,jpegFactors[j].denom,sa,minDiff);\r
+        switch(ctl->mode) {\r
+          case CROP:\r
+            if (curf >= 1000 && curf < (minDiff +1000)) {\r
+              setThis=true;\r
+              minDiff=curf-1000;\r
+            }\r
+            break;\r
+          case LETTER:\r
+            if (curf <= 1000 && curf > (1000-minDiff)) {\r
+              setThis=true;\r
+              minDiff=1000-curf;\r
+            }\r
+            break;\r
+          case CROPPERCENT:\r
+            if (curf <= 10*(int)ctl->scaleAmount ) {\r
+              int abs=curf-1000;\r
+              if (abs < 0) abs=-abs;\r
+              if (abs < minDiff) {\r
+                   setThis=true;\r
+                   minDiff=abs;\r
+              }\r
+            }\r
+            break;\r
+        }\r
+        if (setThis) {\r
+          logger->log("BJpeg", Log::DEBUG, "testing scale curf=%d,take this",curf);\r
+          scalenum=jpegFactors[j].num;\r
+          scaledenom=jpegFactors[j].denom;\r
+          scaleafter=sa;\r
+        }\r
+      }\r
+    }\r
+    ctl->scale=100*scalenum/(scaledenom*scaleafter);\r
+\r
+    logger->log("BJpeg", Log::DEBUG, "JPEG scaling found scale=%i num=%i denom=%i after=%i result=%i scale=%i%% ",\r
+        scale,scalenum,scaledenom,scaleafter,scale*ctl->scale/100,ctl->scale);\r
+\r
+    cinfo.scale_denom=scaledenom;\r
+    cinfo.scale_num=scalenum;\r
+    }\r
+  else\r
+  {\r
+    //set drawing area according to picture\r
+    ctl->area.w=ctl->picw;\r
+    ctl->area.h=ctl->pich;\r
+  }\r
+\r
+  //now we know the scaling\r
+  //compute the scaled size and position\r
+\r
+  jpeg_start_decompress(&cinfo);\r
+  //picturew/h is now the output width from the decompressor and afterscaler\r
+  //this is unrotated \r
+  picturew=cinfo.output_width;\r
+  pictureh=cinfo.output_height;\r
+  if (scaleafter > 1) {\r
+    picturew=picturew/scaleafter;\r
+    pictureh=pictureh/scaleafter;\r
+  }\r
+  //if our image is smaller - center it\r
+  if (! ctl->enlarge) {\r
+    if (ctl->finalRotation == ROT_90 || ctl->finalRotation == ROT_270) {\r
+      int dim=pictureh;\r
+      xpos=(((int)ctl->area.w)-dim)/2;\r
+      dim=picturew;\r
+      ypos=(((int)ctl->area.h)-dim)/2;\r
+    } else {\r
+      int dim=picturew;\r
+      xpos=(((int)ctl->area.w)-dim)/2;\r
+      dim=pictureh;\r
+      ypos=(((int)ctl->area.h)-dim)/2;\r
+    }\r
+    if (xpos <0) xpos=0;\r
+    if (ypos <0) ypos=0;\r
+  }\r
+  xpos+=ctl->area.x;\r
+  ypos+=ctl->area.y;\r
+  //remember the jpeg dimensions for computing the buffer\r
+  UINT jpegwidth=cinfo.output_width;\r
+  UINT jpegheight=cinfo.output_height;\r
+  logger->log("BJpeg", Log::DEBUG, "JPEG startup done pw=%i ph=%i, xo=%i,yo=%i, jw=%i, jh=%i, rot=%d", \r
+      picturew, pictureh,xpos,ypos,jpegwidth,jpegheight,(int)ctl->finalRotation*90);\r
+\r
+  //fill the background\r
+  sfc->fillblt(ctl->area.x,ctl->area.y,ctl->area.w,ctl->area.h,backgroundColour.rgba());\r
+\r
+  //line len in bytes (3 bytes per Pixel) - for buffer (can be bigger then surface)\r
+  int linelen=jpegwidth*3;\r
+#ifdef USE_BUFFER\r
+  // MAKE THE 2D ARRAY\r
+  buffer = (unsigned char*)malloc(jpegheight * linelen);\r
+  logger->log("BJpeg", Log::DEBUG, "Buffer allocated at %p, lines = %i linelen = %i", buffer, jpegheight, linelen);\r
+  if (buffer == NULL) {\r
+    if (rdr) jpeg_memio_cleanup(&cinfo);\r
+    jpeg_destroy_decompress(&cinfo);\r
+    logger->log("BJpeg", Log::ERR, "JPEG error - no room for buffer");\r
+    SNPRINTF(ctl->error,100,"no room for buffer");\r
+    return false;\r
+  }\r
+#endif\r
+\r
+#ifndef USE_BUFFER\r
+  //unsigned char lbuf[linelen];\r
+  unsigned char *lbuf=new unsigned char[linelen*scaleafter];\r
+  unsigned char * ptr=lbuf;\r
+  UINT outy=0;\r
+#else\r
+  unsigned char * ptr=buffer;\r
+#endif\r
+\r
+  int rowsread = 0;\r
+\r
+  Colour c;\r
+  sfc->startFastDraw();//Tell the surface, that we will draw a lot of pixel,\r
+  //so that performance, can be optimized\r
+  logger->log("BJpeg", Log::DEBUG, "start drawing ");\r
+  UINT colincr=0;\r
+  //factors to base 1024\r
+  UINT fac=1024;\r
+  if (scaleafter > 1) {\r
+     colincr=3*scaleafter-3;\r
+     fac=1024/(scaleafter*scaleafter);\r
+     }\r
+  logger->log("BJpeg", Log::DEBUG, "jpeg  draw scale %d image: %u %u, picture: %u %u", scaleafter,picturew,pictureh,jpegwidth,jpegheight);\r
+  while (cinfo.output_scanline < jpegheight)\r
+  {\r
+//  logger->log("BJpeg", Log::DEBUG, "%i", rowsread);\r
+    rowsread += jpeg_read_scanlines(&cinfo,&ptr,1);\r
+#ifdef USE_BUFFER\r
+    ptr+=linelen;\r
+#else\r
+    if (scaleafter > 1) {\r
+      if (rowsread % scaleafter != scaleafter-1) {\r
+        //this simple approach wold maybe forget scaleafter -1 lines at the end...\r
+        ptr+=linelen;\r
+        continue;\r
+      }\r
+      ptr=lbuf;\r
+    }\r
+    drawLine(sfc,ctl->finalRotation,ptr,scaleafter,picturew,pictureh,xpos,ypos,outy,linelen,colincr,scaleafter,fac);\r
+    outy++;\r
+    \r
+#endif\r
+  }\r
+  sfc->endFastDraw();\r
+\r
+  logger->log("BJpeg", Log::DEBUG, "Done all jpeg_read");\r
+\r
+  jpeg_finish_decompress(&cinfo);\r
+  jpeg_memio_cleanup(&cinfo);\r
+  jpeg_destroy_decompress(&cinfo);\r
+\r
+  logger->log("BJpeg", Log::DEBUG, "jpeg shutdown done");\r
+  rdr->drawingDone();\r
+\r
+#ifdef USE_BUFFER\r
+  UINT y;\r
+  //Tell the surface, that we will draw a lot of pixel,\r
+  //so that performance, can be optimized\r
+  sfc->startFastDraw();\r
+  logger->log("BJpeg", Log::DEBUG, "jpeg start buffer draw" );\r
+  unsigned char* p=buffer; //start of first row\r
+  UINT rowincr=linelen*scaleafter;\r
+  //for simplicity omit last line to avoid running out of buffer\r
+  for (y = 0; y < pictureh-1 ;y++)\r
+  {\r
+    drawLine(sfc,ctl->finalRotation,p,scaleafter,picturew,pictureh,xpos,ypos,y,linelen,colincr,scaleafter,fac);\r
+    p+=rowincr;\r
+  }\r
+  sfc->endFastDraw();\r
+  logger->log("BJpeg", Log::DEBUG, "end draw");\r
+  free(buffer);\r
+#else\r
+  delete[] lbuf;\r
+#endif\r
+  logger->log("BJpeg", Log::DEBUG, "deleted buffer");\r
+  return true;\r
+}\r
+\r
+\r
+#else\r
+bool WJpegComplex::drawJpeg(JpegControl * ctl,Surface * sfc,JpegReader *rdr, Colour & backgroundColour) {\r
+       return true;\r
+}\r
+#endif\r
+\r
+//get my own surface\r
+Surface * WJpegComplex::getSurface(Region & r) {\r
+  r.x=getRootBoxOffsetX();\r
+  r.y=getRootBoxOffsetY();\r
+  r.w=area.w;\r
+  r.h=area.h;\r
+  return Boxx::getSurface();\r
+}\r
+\r
diff --git a/wjpegcomplex.h b/wjpegcomplex.h
new file mode 100644 (file)
index 0000000..06f9ebd
--- /dev/null
@@ -0,0 +1,236 @@
+/*\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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+*/\r
+\r
+#ifndef WJPEGCOMPLEX_H\r
+#define WJPEGCOMPLEX_H\r
+\r
+// This is the complex jpeg readeing stuff not supported on all plattforms\r
+\r
+\r
+#include <stdio.h>\r
+#include <malloc.h>\r
+\r
+#ifdef WIN32\r
+\r
+#include <winsock2.h>\r
+#include <windows.h>\r
+\r
+\r
+//#define NEED_FAR_POINTERS\r
+#define XMD_H //workaround some compiling issues\r
+#endif\r
+\r
+class Surface;\r
+class Boxx;\r
+\r
+//a reader to be implemented by the caller\r
+class JpegReader {\r
+  public:\r
+  //read the next chunk of jpeg data\r
+  //offset - from start of file\r
+  //len I buf len (max bytes to read)\r
+  //return read len, 0 on EOF, -1 on error, *buf set to buffer\r
+  //will be released with free(!!!) after decoding\r
+  virtual ULONG readChunk(ULONG offset,ULONG len,char **buf)=0;\r
+  //a callback when the drawing is complete\r
+  //the implementation is optional\r
+  virtual void drawingDone(){};\r
+  //get the size of the current picture\r
+  virtual ULONG getSize(){ return 0;}\r
+  virtual ~JpegReader(){};\r
+};\r
+class WJpegComplex : public WJpeg\r
+{\r
+  public:\r
+  \r
+    // temp for boxx\r
+    void setDimensions(int width, int height) {area.w=width;area.h=height;};\r
+  \r
+  \r
+    WJpegComplex();\r
+    virtual ~WJpegComplex();\r
+    //old style usage - load local file\r
+    //the sequence is init(filename), draw\r
+    //the new usage is drawJpeg (with having the right offsets computed)\r
+    int init(const char* fileName);\r
+    void draw();\r
+\r
+    bool hasError();\r
+    \r
+    //mode for scaling pictures\r
+    enum ScaleMode {\r
+        LETTER=0,\r
+        CROP=1,\r
+        CROPPERCENT=2};\r
+    //rotations\r
+    enum Rotation{\r
+     ROT_0=0,\r
+     ROT_90=1,\r
+     ROT_180=2,\r
+     ROT_270=3\r
+    };\r
+    //jpeg info \r
+    struct JpegControl {\r
+      public:\r
+      //the available drawing area\r
+      Region area;\r
+      bool enlarge;\r
+      //the maximum allowed scale factor after decompress\r
+      UINT scaleafter;\r
+      //the scale mode\r
+      enum ScaleMode mode;\r
+      //the size value if scaleMode==cropPercent\r
+      //%of the drawing area size\r
+      UINT  scaleAmount;\r
+      //the rotation (user defined as input)\r
+      //if exif rotation is found this will be added\r
+      enum Rotation rotation;\r
+\r
+      //paremeters filled during Jpeg parsing\r
+      enum Rotation exifRotation;\r
+      char exifDate[30];\r
+      char error[100];\r
+      UINT picw;\r
+      UINT pich;\r
+      ULONG compressedSize;\r
+\r
+      //parameters computed to display picture\r
+      enum Rotation finalRotation;\r
+      //scale in %\r
+      UINT scale;\r
+      JpegControl() {\r
+        area.x=0;\r
+        area.y=0;\r
+        area.w=0;\r
+        area.h=0;\r
+        enlarge=false;\r
+        scaleafter=3;\r
+        scaleAmount=110;\r
+        mode=CROPPERCENT;\r
+        rotation=ROT_0;\r
+        exifRotation=ROT_0;\r
+        finalRotation=ROT_0;\r
+        exifDate[0]='\0';\r
+        error[0]='\0';\r
+        picw=0;\r
+        pich=0;\r
+        compressedSize=0;\r
+        scale=100;\r
+      }\r
+    };\r
+\r
+    //the standalone drawing function\r
+    //this will draw into the provided surface\r
+    //the reader has to be initialized before\r
+    //calling this function does not need a WJpeg being instantiated\r
+    //it simply draws into the surface\r
+    bool static drawJpeg(JpegControl * control, Surface* sfc, JpegReader *rdr, Colour & backgroundColour);\r
+\r
+  private:\r
+    //our drawPixel with considers rotation\r
+    /* handle picture rotation\r
+       90: xr=h-y\r
+           yr=x\r
+       180:xr=w-x\r
+           yr=h-y\r
+       270:xr=y\r
+           yr=w-x\r
+    */\r
+#ifndef __ANDROID__\r
+    inline static void  drawPixel(Surface * sfc,enum Rotation rotate,int x, int y,int w,int h,int xpos, int ypos,Colour c){\r
+    int xb=0;\r
+    int yb=0;\r
+    switch(rotate) {\r
+       case ROT_0:\r
+          xb=x;\r
+          yb=y;\r
+          break;\r
+       case ROT_90:\r
+          xb=h-y;\r
+          yb=x;\r
+          break;\r
+       case ROT_180:\r
+          xb=w-x;\r
+          yb=h-y;\r
+          break;\r
+       case ROT_270:\r
+          xb=y;\r
+          yb=w-x;\r
+          break;\r
+       }\r
+       xb+=xpos;\r
+       yb+=ypos;\r
+       if (xb < 0 || yb < 0 ) {\r
+         return;\r
+       }\r
+       sfc->drawPixel((UINT)xb,(UINT)yb,c,true);\r
+    }\r
+\r
+    /**\r
+      draw a line of pixels coming from the decompressor\r
+      if scaleafter > 1 we draw that many lines (numlines is the# lines in the buffer)\r
+      picturew is the resulting width of the picture\r
+    **/  \r
+    inline static void drawLine(Surface *sfc,enum Rotation rotate, unsigned char *cp,UINT scaleafter,UINT picturew,UINT pictureh, \r
+        UINT xpos, UINT ypos, UINT outy, UINT linelen,UINT pixeloffset, UINT numlines, UINT fac) {\r
+      Colour c;\r
+      for (UINT x = 0; x < picturew; x++)\r
+      {\r
+        if (scaleafter > 1 ) {\r
+           //boxfilter scalefactor*scalefactor\r
+           //take 0...scalefactor pixels in x and y direction\r
+           for (int colornum=0;colornum<3;colornum++) {\r
+             UINT comp=0;\r
+             unsigned char * accp=cp;\r
+             for (UINT rows=0;rows<scaleafter;rows++) {\r
+               unsigned char * pp=accp;\r
+               for (UINT cols=0;cols<scaleafter;cols++) {\r
+                 comp+=(UINT)*pp;\r
+                 if (pp-accp < (int)linelen-3) pp+=3;\r
+                 }\r
+               if (rows < numlines) accp+=linelen;\r
+               }\r
+             comp=(comp*fac) >> 10;\r
+             if (colornum == 0) c.red=comp;\r
+             if (colornum == 1) c.green=comp;\r
+             if (colornum == 2) c.blue=comp;\r
+             cp++;\r
+           }\r
+          \r
+        }\r
+        else {\r
+          c.red = *cp;cp++;\r
+          c.green = *cp;cp++;\r
+          c.blue = *cp;cp++;\r
+        }\r
+        cp+=pixeloffset;\r
+        drawPixel(sfc,rotate,x, outy, picturew,pictureh,xpos,ypos,c);\r
+      }\r
+    }\r
+#endif\r
+    //find my own surface and fill the area with my x and y offset within\r
+    Surface * getSurface(Region &a);\r
+\r
+    JpegReader *reader;\r
+    bool owningReader;\r
+    char errbuf[200];\r
+};\r
+\r
+#endif\r
diff --git a/wjpegsimple.cc b/wjpegsimple.cc
new file mode 100644 (file)
index 0000000..04095d1
--- /dev/null
@@ -0,0 +1,66 @@
+/*\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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+*/\r
+#include "boxx.h"\r
+#include "wjpegsimple.h"\r
+#include <setjmp.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+\r
+\r
+\r
+#include "i18n.h"\r
+#include "log.h"\r
+#include "surface.h"\r
+\r
+\r
+\r
+\r
+WJpegSimple::WJpegSimple(){\r
+\r
+}\r
+\r
+WJpegSimple::~WJpegSimple() {\r
+\r
+}\r
+\r
+int WJpegSimple::init(const char* tfileName)\r
+{\r
+       fileName=tfileName;\r
+\r
+  return 1;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+void WJpegSimple::draw()\r
+{\r
+         int width,height;\r
+         width=height=1;\r
+         drawJpeg(fileName,0,0,&width,&height);//This should went into the abstract base classes?\r
+         //Windows has a problem with the leading / fixme\r
+         setDimensions(width, height);\r
+\r
+}\r
+\r
+\r
+\r
+\r
diff --git a/wjpegsimple.h b/wjpegsimple.h
new file mode 100644 (file)
index 0000000..21bf4dc
--- /dev/null
@@ -0,0 +1,50 @@
+/*\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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+*/\r
+\r
+#ifndef WJPEGSIMPLE_H\r
+#define WJPEGSIMPLE_H\r
+\r
+#include <stdio.h>\r
+#include <malloc.h>\r
+#include "wjpeg.h"\r
+\r
+\r
+class WJpegSimple : public WJpeg\r
+{\r
+public:\r
+  \r
+    // temp for boxx\r
+    void setDimensions(int width, int height) {area.w=width;area.h=height;};\r
+  \r
+  \r
+    WJpegSimple();\r
+    virtual ~WJpegSimple();\r
+    // Only old style usage - load local file\r
+\r
+    int init(const char* fileName);\r
+    void draw();\r
+\r
+private:\r
+   const char* fileName;\r
+\r
+\r
+};\r
+\r
+#endif\r