]> git.vomp.tv Git - vompclient-marten.git/commitdiff
Change to thread sleep type waits in VDR
authorChris Tallon <chris@vomp.tv>
Sun, 18 Nov 2007 17:14:19 +0000 (17:14 +0000)
committerChris Tallon <chris@vomp.tv>
Sun, 18 Nov 2007 17:14:19 +0000 (17:14 +0000)
eventdispatcher.cc [new file with mode: 0644]
eventdispatcher.h [new file with mode: 0644]
vdr.cc
vdr.h
vdrrequestpacket.cc
vdrrequestpacket.h
vdrresponsepacket.cc
vdrresponsepacket.h

diff --git a/eventdispatcher.cc b/eventdispatcher.cc
new file mode 100644 (file)
index 0000000..08efeb3
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+    Copyright 2007 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    VOMP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "eventdispatcher.h"
+
+EventDispatcher::EventDispatcher()
+{
+#ifndef WIN32
+  pthread_mutex_init(&mutex, NULL);
+#else
+  mutex = CreateMutex(NULL, FALSE, NULL);
+#endif
+}
+
+void EventDispatcher::edRegister(EDReceiver* edr)
+{
+  edLock();
+  receivers.push_back(edr);
+  edUnlock();
+}  
+
+bool EventDispatcher::edFindAndCall(void* userTag)
+{
+  edLock();
+  
+  EDReceiver* edr;
+  EDRL::iterator i;
+  for(i = receivers.begin(); i != receivers.end(); i++)
+  {
+    if (ed_cb_find(*i, userTag))
+    {
+      edr = *i;
+      break; // found (by asking the EventDispatcher implementor to check if userTag is for *i
+    }
+  }
+  
+  if ((i == receivers.end()) || edr->callinprogress || edr->nomorecalls)
+  {
+    edUnlock();
+    return false;
+  }
+  
+  edr->callinprogress = true;
+  edUnlock();  
+  bool edrType = edr->call(userTag);
+  edLock();
+  edr->callinprogress = false;
+
+  if (edrType == false) // it's a multicall
+  {
+    if (edr->nomorecalls) // External has called unRegister - probably the receiver
+    {
+      // wake up the thread waiting in unregister
+      #ifndef WIN32
+      pthread_cond_signal(&edr->cond);
+      #else
+      // FIXME
+      #endif
+    }
+  }
+  else // It's a single call. The receiver should be removed from the list. There will be a thread to wake up
+  {
+    for(i = receivers.begin(); i != receivers.end(); i++)
+    {
+      if (*i == edr)
+      {
+        receivers.erase(i);
+        break;
+      }
+    }
+    if (i == receivers.end()) abort(); // should never happen
+    
+    #ifndef WIN32
+    pthread_cond_signal(&edr->cond);
+    #else
+    // FIXME
+    #endif
+  }
+  
+  edUnlock();
+  return true;
+}
+
+void EventDispatcher::edUnregister(EDReceiver* edr)
+{
+  edLock();
+
+  EDRL::iterator i;
+  for(i = receivers.begin(); i != receivers.end(); i++)
+  {
+    if (*i == edr) break; // found
+  }
+
+  if (i == receivers.end()) abort(); // should never happen
+
+  if (!edr->callinprogress)
+  {
+    receivers.erase(i);
+    edUnlock();
+    return;
+  }
+
+  edr->nomorecalls = true;
+  
+  // edUnlock, wait for callinprogres=false (cond to be signalled), lock  
+#ifndef WIN32
+  pthread_cond_wait(&edr->cond, &mutex);
+#else
+  // FIXME
+#endif
+
+  for(i = receivers.begin(); i != receivers.end(); i++)
+  {
+    if (*i == edr) break; // found
+  }
+
+  if (i == receivers.end()) abort(); // should never happen
+
+  receivers.erase(i);
+  edUnlock();
+}
+
+// ---------------------------------------
+
+void EventDispatcher::edLock()
+{
+#ifndef WIN32
+  pthread_mutex_lock(&mutex);
+#else
+  WaitForSingleObject(mutex, INFINITE);
+#endif
+}
+
+void EventDispatcher::edUnlock()
+{
+#ifndef WIN32
+  pthread_mutex_unlock(&mutex);
+#else
+  ReleaseMutex(mutex);
+#endif
+}
+
+// ---------------------------------------
+
+void EventDispatcher::edSleepThisReceiver(EDReceiver* edr)
+{
+  // For blocking version, not callback version. Call with edLock locked
+  
+#ifndef WIN32
+  pthread_cond_init(&edr->cond, NULL);
+  pthread_cond_wait(&edr->cond, &mutex);
+#else
+  // FIXME
+#endif
+}
+
+// -------------- EDReceiver implementation
+
+EDReceiver::EDReceiver()
+{
+  nomorecalls = false;
+  callinprogress = false;
+}
+
+
diff --git a/eventdispatcher.h b/eventdispatcher.h
new file mode 100644 (file)
index 0000000..9f32160
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+    Copyright 2007 Chris Tallon
+
+    This file is part of VOMP.
+
+    VOMP is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    VOMP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef EVENTDISPATCHER_H
+#define EVENTDISPATCHER_H
+
+#include <stdio.h>
+#include <list>
+
+#ifndef WIN32
+#include "threadp.h"
+#else
+#include "threadwin.h"
+#endif
+
+#include "defines.h"
+
+using namespace std;
+
+
+class EDReceiver //(implementation in eventdispatcher.cc)
+{
+  friend class EventDispatcher;
+
+  public:
+    EDReceiver();
+    virtual ~EDReceiver() {};
+
+  protected:
+    virtual bool call(void* userTag)=0; // Implementor must override this and do the actual call
+                           // return true to have EventDispatcher remove receiver from list after call
+    bool nomorecalls;
+    bool callinprogress;
+  
+#ifndef WIN32    
+    pthread_cond_t cond;
+#else
+    // FIXME
+#endif
+};
+
+class EventDispatcher
+{
+  typedef list<EDReceiver*> EDRL;
+
+  public:
+    EventDispatcher();
+    virtual ~EventDispatcher() {};
+
+  protected:
+    void edRegister(EDReceiver* edr);
+    void edUnregister(EDReceiver* edr);
+    bool edFindAndCall(void* userTag);
+    void edLock();
+    void edUnlock();
+    void edSleepThisReceiver(EDReceiver* edr);
+    
+    // EventDispatcher implementor must override the following. When edFindAndCall is called,
+    // The EventDispatcher class will call ed_cb_find() on each receiver until the implementor
+    // returns true = this is the receiver to call.
+    virtual bool ed_cb_find(EDReceiver* edr, void* userTag)=0;
+    
+  private:
+    EDRL receivers;
+    
+#ifndef WIN32
+    pthread_mutex_t mutex;
+#else
+    HANDLE mutex;
+#endif
+};
+
+#endif
diff --git a/vdr.cc b/vdr.cc
index 00aba3b0e4f744d1dd729e400357748435988656..bfb281dae69f0417782801c7f58defe225558e93 100644 (file)
--- a/vdr.cc
+++ b/vdr.cc
@@ -171,6 +171,7 @@ int VDR::connect()
   if (tcp->connectTo(serverIP, 3024))
   {
     connected = true;
+    threadStart();
     return 1;
   }
   else
@@ -181,6 +182,7 @@ int VDR::connect()
 
 void VDR::disconnect()
 {
+  threadCancel();
   if (tcp) delete tcp;
   tcp = NULL;
   connected = false;
@@ -196,42 +198,118 @@ void VDR::setReceiveWindow(size_t size)
 
 void VDR::threadMethod()
 {
+  threadSetKillable();
+  
+  UCHAR* packet;
+  ULONG packetLength;
+  VDR_ResponsePacket* vresp;
+  
+  while(1) 
+  {
+    packet = (UCHAR*)tcp->receivePacket();  // cancellation point
+
+    vresp = new VDR_ResponsePacket();    
+    if (packet)
+    {
+      packetLength = (ULONG)tcp->getDataLength();
+      vresp->set(packet, packetLength);  
+    }
+
+    if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() )
+    {
+      // If edFindAndCall returns true, edr was called and vresp was handed off.
+      // else, delete vresp here.
+      delete vresp;
+    }
+    
+    // Who deletes vresp?
+    // If RR, the individual protocol functions must delete vresp.
+    // If stream, the data and length is taken out in ed_cb_call and vresp is deleted there.
+  }
+}
+
+bool VDR::ed_cb_find(EDReceiver* edr, void* userTag)
+{
+  // edr is a VDR_PacketReceiver object made in VDR::RequestResponse
+  // userTag is a VDR_ResponsePacket made in threadMethod
+
+  VDR_PacketReceiver* vdrpr = (VDR_PacketReceiver*)edr;
+  VDR_ResponsePacket* vresp = (VDR_ResponsePacket*)userTag;
+  
+  // Is vresp for vdrpr ?
+  
+  // Not written yet. will be true
+  if (vdrpr);
+  if (vresp);
+  
+  return true;
 }
 
 VDR_ResponsePacket* VDR::RequestResponse(VDR_RequestPacket* vrp)
 {
   logger->log("VDR", Log::DEBUG, "RR");
-  MUTEX_LOCK(&mutex);
-  
+
   if (!connected)
   {
-    MUTEX_UNLOCK(&mutex);
-    return NULL;
+    VDR_ResponsePacket* vresp = new VDR_ResponsePacket();
+    return vresp; // "no-response" return
   }
 
-  waitingRequestThread = Thread_TYPE::thisThreadID();
+  // ED make new VDR and register
+  // make a VDR_PacketReceiver
+  // - init with serial number of request packet
+
+  VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver();
+  vdrpr->receiverChannel = VDR::CHANNEL_REQUEST_RESPONSE;
+  vdrpr->requestSerialNumber = vrp->getSerial();
+  edRegister(vdrpr);
+  
+  edLock();  
   if ((ULONG)tcp->sendPacket(vrp->getPtr(), vrp->getLen()) != vrp->getLen())
   {
-    disconnect();
-    MUTEX_UNLOCK(&mutex);
-    return NULL;
+    edUnlock();
+    VDR_ResponsePacket* vresp = new VDR_ResponsePacket();
+    return vresp; // "no-response" return
   }
 
-  UCHAR* packet = (UCHAR*)tcp->receivePacket();
-  if (!packet)
-  {
-    disconnect();
-    MUTEX_UNLOCK(&mutex);
-    return NULL;
-  }
-  ULONG packetLength = (ULONG)tcp->getDataLength();
+  // Sleep and block this thread. The sleep unlocks the mutex
+  logger->log("VDR", Log::DEBUG, "RR sleep");
+  edSleepThisReceiver(vdrpr);
+  logger->log("VDR", Log::DEBUG, "RR unsleep");
+    
+  // Woken because a response packet has arrived, mutex will be locked
   
-  MUTEX_UNLOCK(&mutex);
+  edUnlock();
   
-  VDR_ResponsePacket* vresp = new VDR_ResponsePacket();
-  vresp->set(packet, packetLength);  
+  VDR_ResponsePacket* toReturn = vdrpr->save_vresp;
+  delete vdrpr;
+  return toReturn;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+// Here VDR takes a break for the VDR_PacketReceiver helper class
+
+bool VDR_PacketReceiver::call(void* userTag)
+{
+  if (receiverChannel == VDR::CHANNEL_REQUEST_RESPONSE)
+  {
+    // It's a RR. Save vresp and, signal the waiting thread and return.
+    // VDR::RequestResponse will be blocking waiting for this to happen.
+    // That function has a pointer to this object and can read save_vresp.
+    save_vresp = (VDR_ResponsePacket*)userTag;
+    return true; // Signals ED to remove edr from receivers and wake up edr thread
+  }
   
-  return vresp;
+  if (receiverChannel == VDR::CHANNEL_STREAM)
+  {
+    // It's a stream packet.
+    streamReceiver->receiveData(NULL, 0);
+    delete (VDR_ResponsePacket*)userTag;
+    return false;
+  }
+
+  abort(); // unknown receiverChannel, should not happen
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -246,7 +324,7 @@ int VDR::doLogin()
   if (!vrp.copyin((UCHAR*)mactemp, 6)) return 0;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return 0;
+  if (vresp->noResponse()) { delete vresp; return 0; }
 
   ULONG vdrTime = vresp->extractULONG();
   logger->log("VDR", Log::DEBUG, "vdrtime = %lu", vdrTime);
@@ -299,7 +377,7 @@ bool VDR::getRecordingsList(RecMan* recman)
   if (!vrp.init(VDR_GETRECORDINGLIST, true, 0)) return false;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return false;
+  if (vresp->noResponse()) { delete vresp; return false; }
   
   ULONG totalSpace = vresp->extractULONG();
   ULONG freeSpace = vresp->extractULONG();
@@ -334,7 +412,7 @@ int VDR::deleteRecording(char* fileName)
   if (!vrp.addString(fileName)) return 0;
   
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return 0;
+  if (vresp->noResponse()) { delete vresp; return 0; }
   
   int toReturn = (int)vresp->extractULONG();
   delete vresp;
@@ -350,7 +428,7 @@ char* VDR::moveRecording(char* fileName, char* newPath)
   if (!vrp.addString(newPath)) return NULL;
   
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return NULL;
+  if (vresp->noResponse()) { delete vresp; return NULL; }
   
   char* toReturn = NULL;
   int success = (int)vresp->extractULONG();
@@ -370,7 +448,7 @@ ChannelList* VDR::getChannelsList(ULONG type)
   if (!vrp.init(VDR_GETCHANNELLIST, true, 0)) return NULL;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return NULL;
+  if (vresp->noResponse()) { delete vresp; return NULL; }
   
   ChannelList* chanList = new ChannelList();
 
@@ -418,7 +496,7 @@ int VDR::streamChannel(ULONG number)
   if (!vrp.addULONG(number)) return 0;
   
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return 0;
+  if (vresp->noResponse()) { delete vresp; return 0; }
   
   int toReturn = (int)vresp->extractULONG();
   delete vresp;
@@ -432,7 +510,7 @@ int VDR::stopStreaming()
   if (!vrp.init(VDR_STOPSTREAMING, true, 0)) return 0;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return 0;
+  if (vresp->noResponse()) { delete vresp; return 0; }
   
   int toReturn = (int)vresp->extractULONG();
   delete vresp;
@@ -458,7 +536,7 @@ UCHAR* VDR::getBlock(ULLONG position, UINT maxAmount, UINT* amountReceived, ULON
   if (!vrp.addULONG(maxAmount)) return NULL;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return NULL;
+  if (vresp->noResponse()) { delete vresp; return NULL; }
 
   if (vresp->serverError())
   {
@@ -483,7 +561,7 @@ ULLONG VDR::streamRecording(char* fileName, ULONG* totalFrames)
   if (!vrp.addString(fileName)) return 0;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return 0;
+  if (vresp->noResponse()) { delete vresp; return 0; }
   
   ULLONG lengthBytes = vresp->extractULLONG();
   ULONG lengthFrames = vresp->extractULONG();
@@ -502,7 +580,7 @@ ULLONG VDR::positionFromFrameNumber(ULONG frameNumber)
   if (!vrp.addULONG(frameNumber)) return 0;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return 0;
+  if (vresp->noResponse()) { delete vresp; return 0; }
   
   ULLONG position = vresp->extractULLONG();
   delete vresp;
@@ -519,7 +597,7 @@ ULONG VDR::frameNumberFromPosition(ULLONG position)
   if (!vrp.addULLONG(position)) return 0;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return 0;
+  if (vresp->noResponse()) { delete vresp; return 0; }
   
   ULONG framenumber = vresp->extractULONG();
   delete vresp;
@@ -537,7 +615,7 @@ bool VDR::getNextIFrame(ULONG frameNumber, ULONG direction, ULLONG* rfilePositio
   if (!vrp.addULONG(direction)) return false;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return false;
+  if (vresp->noResponse()) { delete vresp; return false; }
   
   if (vresp->serverError())
   {
@@ -575,7 +653,7 @@ EventList* VDR::getChannelSchedule(ULONG number, time_t start, ULONG duration)
   if (!vrp.addULONG(duration)) return NULL;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return NULL;
+  if (vresp->noResponse()) { delete vresp; return NULL; }
   
   // received a ulong(0) - schedules error in the plugin
   if (vresp->serverError())
@@ -613,7 +691,7 @@ int VDR::configSave(const char* section, const char* key, const char* value)
   if (!vrp.addString(value)) return 0;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return 0;
+  if (vresp->noResponse()) { delete vresp; return 0; }
   
   int toReturn = (int)vresp->extractULONG();
   delete vresp;
@@ -629,7 +707,7 @@ char* VDR::configLoad(const char* section, const char* key)
   if (!vrp.addString(key)) return NULL;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return NULL;
+  if (vresp->noResponse()) { delete vresp; return NULL; }
   
   char* toReturn = vresp->extractString();
   delete vresp;
@@ -643,7 +721,7 @@ RecTimerList* VDR::getRecTimersList()
   if (!vrp.init(VDR_GETTIMERS, true, 0)) return NULL;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return NULL;
+  if (vresp->noResponse()) { delete vresp; return NULL; }
 
   RecTimerList* recTimerList = new RecTimerList();
 
@@ -692,7 +770,7 @@ ULONG VDR::setEventTimer(char* timerString)
   if (!vrp.addString(timerString)) return 0;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return 0;
+  if (vresp->noResponse()) { delete vresp; return 0; }
   
   ULONG toReturn = vresp->extractULONG();
   delete vresp;
@@ -707,7 +785,7 @@ RecInfo* VDR::getRecInfo(char* fileName)
   if (!vrp.addString(fileName)) return NULL;
   
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return NULL;
+  if (vresp->noResponse()) { delete vresp; return NULL; }
   
   if (vresp->serverError())
   {
@@ -749,7 +827,7 @@ ULLONG VDR::rescanRecording(ULONG* totalFrames)
   if (!vrp.init(VDR_RESCANRECORDING, true, 0)) return 0;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return 0;
+  if (vresp->noResponse()) { delete vresp; return 0; }
   
   ULLONG lengthBytes = vresp->extractULLONG();
   ULONG lengthFrames = vresp->extractULONG();
@@ -768,7 +846,7 @@ MarkList* VDR::getMarks(char* fileName)
   if (!vrp.addString(fileName)) return NULL;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return NULL;
+  if (vresp->noResponse()) { delete vresp; return NULL; }
   
   if (vresp->serverError())
   {
@@ -799,7 +877,7 @@ void VDR::getChannelPids(Channel* channel)
   if (!vrp.addULONG(channel->number)) return ;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return ;
+  if (vresp->noResponse()) { delete vresp; return ; }
   
   // Format of response
   // vpid
@@ -856,7 +934,7 @@ MediaList* VDR::getMediaList(const char* parent,int mediaType)
   }
     
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return NULL;
+  if (vresp->noResponse()) { delete vresp; return NULL; }
   
   if (vresp->serverError())
   {
@@ -931,7 +1009,7 @@ ULONG VDR::loadImage(const char* fileName, ULONG x, ULONG y)
   if (!vrp.addString(fileName)) return 0;
 
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return 0;
+  if (vresp->noResponse()) { delete vresp; return 0; }
 
   ULONG cmd = vresp->extractULONG();
   ULONG lengthBytes = vresp->extractULONG();
@@ -954,7 +1032,7 @@ int VDR::deleteTimer(RecTimer* delTimer)
   if (!vrp.addULONG(delTimer->stopTime)) return 0; 
    
   VDR_ResponsePacket* vresp = RequestResponse(&vrp);
-  if (!vresp) return 0;
+  if (vresp->noResponse()) { delete vresp; return 0; }
   
   int toReturn = (int)vresp->extractULONG();
   delete vresp;
diff --git a/vdr.h b/vdr.h
index 6fcfe88445384a5a6c810c3ebe56bcb9eb7235c2..68f53ed246051f867581ee16470500c56618044a 100644 (file)
--- a/vdr.h
+++ b/vdr.h
@@ -35,6 +35,7 @@
 #include "rectimer.h"
 #include "mark.h"
 #include "media.h"
+#include "eventdispatcher.h"
 
 class TCP;
 class Log;
@@ -75,13 +76,37 @@ struct ServerSorter
 
 class RecMan;
 
-class VDR
+class StreamReceiver
+{
+  public:
+    void receiveData(void*, ULONG) {};
+};
+
+class VDR_PacketReceiver : public EDReceiver // implementation in vdr.cc
+{
+  public:
+    virtual bool call(void* userTag);
+
+    ULONG receiverChannel;
+    
+    // If receiverChannel == 1:
+    ULONG requestSerialNumber;      // set by RequestResponse, used in ed_cb_find
+    VDR_ResponsePacket* save_vresp; // set by ed_cb_call, used in RequestResponse
+        
+    // If receiverChannel == 2:
+    StreamReceiver* streamReceiver;
+};
+
+class VDR : public Thread_TYPE, public EventDispatcher
 {
 
   public:
     const static ULONG VIDEO = 1;
     const static ULONG RADIO = 2;
   
+    const static ULONG CHANNEL_REQUEST_RESPONSE = 1;
+    const static ULONG CHANNEL_STREAM = 2;
+  
     VDR();
     ~VDR();
     static VDR* getInstance();
@@ -217,7 +242,13 @@ class VDR
     const static ULONG VDR_GETIMAGEBLOCK       = 32;
 
   protected:
+  
+    // Thread
     void threadMethod();
+    void threadPostStopCleanup() {};
+
+    // EventDispatcher
+    virtual bool ed_cb_find(EDReceiver* edr, void* userTag);
 };
 
 #endif
index 125b756283467b6716f5368a7ec229763c143c40..25ce2cbefc7006e09c33c7f27626b94cf93df2bc 100644 (file)
@@ -33,7 +33,7 @@
 ? bytes = rest of packet. depends on packet
 */
 
-ULONG VDR_RequestPacket::serialNumber = 1;
+ULONG VDR_RequestPacket::serialNumberCounter = 1;
 
 VDR_RequestPacket::VDR_RequestPacket()
 {
@@ -41,6 +41,7 @@ VDR_RequestPacket::VDR_RequestPacket()
   bufSize = 0;
   bufUsed = 0;
   lengthSet = false;
+  serialNumber = 0;
 }
 
 VDR_RequestPacket::~VDR_RequestPacket()
@@ -65,8 +66,12 @@ bool VDR_RequestPacket::init(ULONG opcode, bool setUserDataLength, ULONG userDat
   
   buffer = (UCHAR*)malloc(bufSize);
   if (!buffer) return false;
-  *(ULONG*)&buffer[0] = htonl(1);
-  *(ULONG*)&buffer[4] = htonl(serialNumber++);
+  
+  channel = VDR::CHANNEL_REQUEST_RESPONSE;
+  serialNumber = serialNumberCounter++;
+  
+  *(ULONG*)&buffer[0] = htonl(channel);
+  *(ULONG*)&buffer[4] = htonl(serialNumber);
   *(ULONG*)&buffer[8] = htonl(opcode);
   *(ULONG*)&buffer[12] = htonl(userDataLength);
   bufUsed = headerLength;
index 52d2d06f506cdbc7e407de23c47f910cb5b2ec99..3642ba66c7c51e268c0fbde6eac67c537a4c1d25 100644 (file)
@@ -41,14 +41,19 @@ class VDR_RequestPacket
         
     UCHAR* getPtr() { return buffer; }
     ULONG getLen() { return bufUsed; }
+    ULONG getChannel() { return channel; }
+    ULONG getSerial() { return serialNumber; }
     
   private:
-    static ULONG serialNumber;
+    static ULONG serialNumberCounter;
     
     UCHAR* buffer;
     ULONG bufSize;
     ULONG bufUsed;
     bool lengthSet;
+    
+    ULONG channel;
+    ULONG serialNumber;
 
     bool checkExtend(ULONG by);
     
index abf167c23f40665bddefa3ba64e286d1b15fc17f..121a587ddbcfd6f7201a198ad003aa88f8a32695 100644 (file)
@@ -32,7 +32,7 @@ VDR_ResponsePacket::~VDR_ResponsePacket()
 {
   if (getBlockRelease) return; // don't free if it's a getblock
   
-  free(packet);
+  if (packet) free(packet);
 }
 
 void VDR_ResponsePacket::set(UCHAR* tpacket, ULONG tpacketLength)
index b1f6e8efc51f62a0d141272c188c722ed29cd2ee..a750551c23c8d3dd1e5f807357112f61458d0496 100644 (file)
@@ -35,6 +35,7 @@ class VDR_ResponsePacket
     
     void set(UCHAR* packet, ULONG packetLength);
      
+    bool noResponse() { return (packet == NULL); };
     int  serverError();
     ULONG getLength();