]> git.vomp.tv Git - vompclient.git/commitdiff
Rename class: PlayerLiveRadio to PlayerRadioLive
authorChris Tallon <chris@vomp.tv>
Tue, 3 Mar 2020 21:50:23 +0000 (21:50 +0000)
committerChris Tallon <chris@vomp.tv>
Tue, 3 Mar 2020 21:50:23 +0000 (21:50 +0000)
objects.mk
playerliveradio.cc [deleted file]
playerliveradio.h [deleted file]
playerradiolive.cc [new file with mode: 0644]
playerradiolive.h [new file with mode: 0644]
vvideolivetv.cc

index dd220df912601b47b5757d413c2d243f4b72a2cc..5fa280591c306b47c26b5a72b42aaaf0f5d516a6 100644 (file)
@@ -14,12 +14,12 @@ OBJ_COMMON = command.o tcp.o dsock.o thread.o timers.o i18n.o vdp6.o
              woptionpane.o woptionbox.o wremoteconfig.o wtabbar.o led.o            \
              inputman.o input.o inputudp.o vpicturebanner.o abstractoption.o       \
              eventdispatcher.o vdrrequestpacket.o vdrresponsepacket.o              \
-             vvideolivetv.o vsleeptimer.o playerliveradio.o                        \
+             vvideolivetv.o vsleeptimer.o                                          \
              wprogressbar.o bitmap.o dvbsubtitles.o tfeed.o vteletextview.o        \
              teletextdecodervbiebu.o teletxt/txtfont.o movieinfo.o seriesinfo.o    \
              wmovieview.o wseriesview.o tvmedia.o wtvmedia.o wpictureview.o        \
              osdvector.o surfacevector.o buffer.o                                  \
-             playervideorec.o playervideolive.o
+             playervideorec.o playervideolive.o playerradiolive.o
 
 OBJ_RASPBERRY = main.o threadp.o osdopenvg.o                                       \
                 ledraspberry.o videoomx.o audioomx.o imageomx.o                    \
diff --git a/playerliveradio.cc b/playerliveradio.cc
deleted file mode 100644 (file)
index 648dab8..0000000
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
-    Copyright 2008 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, see <https://www.gnu.org/licenses/>.
-*/
-
-#include "playerliveradio.h"
-
-#include "defines.h"
-#include "log.h"
-#include "audio.h"
-#include "demuxerts.h"
-#include "vdr.h"
-#include "messagequeue.h"
-#include "input.h"
-#include "message.h"
-#include "channel.h"
-#include "video.h"
-
-// ----------------------------------- Called from outside, one offs or info funcs
-
-PlayerLiveRadio::PlayerLiveRadio(MessageQueue* tmessageQueue, void* tmessageReceiver, ChannelList* tchanList)
-: afeed(this)
-{
-  messageQueue = tmessageQueue;
-  messageReceiver = tmessageReceiver;
-  chanList = tchanList;
-  
-  audio = Audio::getInstance();
-  logger = Log::getInstance();
-  vdr = VDR::getInstance();
-  initted = false;
-
-  stopNow = false;
-  state = S_STOP;
-  Video::getInstance()->turnVideoOff();
-}
-
-PlayerLiveRadio::~PlayerLiveRadio()
-{
-  if (initted) shutdown();
-}
-
-int PlayerLiveRadio::init()
-{
-  if (initted) return 0;
-
-  demuxer = new DemuxerTS();
-  if (!demuxer) return 0;
-  if (!demuxer->init(this, audio, NULL, NULL, 0, 200000, 0))
-  {
-    logger->log("PlayerLiveRadio", Log::ERR, "Demuxer failed to init");
-    shutdown();
-    return 0;
-  }
-
-  audio->stop();
-
-  initted = true;
-  return 1;
-}
-
-int PlayerLiveRadio::shutdown()
-{
-  if (!initted) return 0;
-  stop();
-  initted = false;
-  delete demuxer;
-  return 1;
-}
-
-bool* PlayerLiveRadio::getDemuxerMpegAudioChannels()
-{
-  return demuxer->getmpAudioChannels();
-}
-
-bool* PlayerLiveRadio::getDemuxerAc3AudioChannels()
-{
-  return demuxer->getac3AudioChannels();
-}
-
-int PlayerLiveRadio::getCurrentAudioChannel()
-{
-  return demuxer->getAID();
-}
-
-int* PlayerLiveRadio::getTeletxtSubtitlePages()
-{
-  return NULL;
-}
-
-int PlayerLiveRadio::getCurrentSubtitleChannel()
-{
-  return demuxer->getSubID();
-}
-
-void PlayerLiveRadio::setAudioChannel(int newChannel, int type, int streamtype)
-{
-  demuxer->setAID(newChannel, type, streamtype, true);
-}
-
-void PlayerLiveRadio::setSubtitleChannel(int newChannel)
-{
-  demuxer->setSubID(newChannel);
-}
-
-// ----------------------------------- Externally called events
-
-void PlayerLiveRadio::go(ULONG index)
-{
-  struct PLInstruction i;
-  i.instruction = I_SETCHANNEL;
-  i.channelIndex = index;
-  instructions.push(i);
-  threadStart();
-}
-
-void PlayerLiveRadio::setChannel(ULONG index)
-{
-  logger->log("PlayerLiveRadio", Log::DEBUG, "setChannel");
-  struct PLInstruction i;
-  i.instruction = I_SETCHANNEL;
-  i.channelIndex = index;
-  instructions.push(i);  
-  logger->log("PlayerLiveRadio", Log::DEBUG, "posted setChannel instruction, now %i in queue", instructions.size());
-  threadSignalNoLock();
-}
-
-void PlayerLiveRadio::stop()
-{
-  logger->log("PlayerLiveRadio", Log::DEBUG, "stop");
-  struct PLInstruction i;
-  i.instruction = I_STOP;
-  instructions.push(i);
-  threadSignal();
-  threadStop();
-}
-
-// ----------------------------------- Callback
-
-void PlayerLiveRadio::call(void* /*caller*/)
-{
-}
-
-// -----------------------------------
-
-void PlayerLiveRadio::streamReceive(ULONG flag, void* data, ULONG len)
-{
-  // Flag:
-  // 0 = normal stream packet
-  // 1 = stream end
-  // 2 = connection lost
-
-  if (flag == 1)
-  {
-    if (data) abort();
-    
-    Message* m = new Message();
-    m->from = this;
-    m->to = messageReceiver;
-    m->message = Message::PLAYER_EVENT;
-    m->parameter = PlayerLiveRadio::STREAM_END;
-    messageQueue->postMessage(m);
-  }
-  
-  if (streamChunks.size() < 11)
-  {
-    StreamChunk s;
-    s.data = data;
-    s.len = len;
-    streamChunks.push(s);
-    threadSignalNoLock();
-  }
-  else
-  {
-    // Too many chunks in streamChunks, drop this chunk
-    free(data);
-    logger->log("PlayerLiveRadio", Log::WARN, "Dropped chunk");
-  }
-}
-
-void PlayerLiveRadio::clearStreamChunks()
-{
-  while(streamChunks.size())
-  {
-    logger->log("PlayerLiveRadio", Log::DEBUG, "Dropping chunk from old stream");
-    struct StreamChunk s = streamChunks.front();
-    streamChunks.pop();
-    free(s.data);
-  }
-}
-
-void PlayerLiveRadio::chunkToDemuxer()
-{
-  StreamChunk s = streamChunks.front();
-  streamChunks.pop();
-  //logger->log("PlayerLiveRadio", Log::DEBUG, "About to call demuxer with %p %lu", s.data, s.len);
-  /*int a =*/ demuxer->put((UCHAR*)s.data, s.len);
-  //logger->log("PlayerLiveRadio", Log::DEBUG, "put %i to demuxer", a);
-  free(s.data);  
-}
-
-void PlayerLiveRadio::switchState(UCHAR newState)
-{
-  logger->log("PlayerLiveRadio", Log::DEBUG, "Switch from state %u to state %u", state, newState);
-
-  switch(state)
-  {
-    case S_STOP:   // FROM S_STOP
-    {
-      switch(newState)
-      {
-        case S_PREBUFFERING:
-        {
-          audio->stop();
-          audio->unPause();
-          audio->reset();
-          audio->setStreamType(Audio::MPEG2_PES);
-          audio->systemMuteOff();      
-          audio->doMuting();              
-          audio->play();
-          audio->pause();
-          demuxer->reset();
-          afeed.start();
-          
-          state = newState;
-          preBufferCount = 0;
-          return;
-        }
-        default:
-        {
-          logger->log("PlayerLiveRadio", Log::EMERG, "Thread called state %u to state %u which is not supported", state, newState);
-          abort();
-          break;
-        }
-      }
-    }
-
-    case S_PREBUFFERING:    // FROM S_PREBUFFERING
-    {
-      switch(newState)
-      {
-        case S_PLAY:
-        {
-          audio->unPause();
-          state = newState;
-          return;
-        }
-        case S_STOP:
-        {
-          vdr->stopStreaming();
-          clearStreamChunks();
-          afeed.stop();
-          audio->stop();
-          audio->reset();
-          state = newState;
-          return;        
-        }
-        case S_PREBUFFERING:
-        {
-          vdr->stopStreaming();
-          clearStreamChunks();
-          afeed.stop();
-          audio->stop();
-          audio->reset();
-          audio->play();
-          audio->pause();
-          demuxer->reset();
-          afeed.start();
-
-          state = newState;
-          preBufferCount = 0;
-          return;        
-        }
-        default:
-        {
-          logger->log("PlayerLiveRadio", Log::EMERG, "Thread called state %u to state %u which is not supported", state, newState);
-          abort();
-          break;
-        }        
-      }
-    }
-    
-    case S_PLAY:     // FROM S_PLAY
-    {
-      switch(newState)
-      {
-        case S_STOP:
-        { 
-          vdr->stopStreaming();
-          clearStreamChunks();
-          afeed.stop();
-          audio->stop();
-          audio->reset();
-          state = newState;
-          return;
-        }
-        case S_PREBUFFERING: // IS THIS HOW IT WORKS?
-        {
-          vdr->stopStreaming();
-          clearStreamChunks();
-          afeed.stop();
-          audio->stop();
-          audio->reset();
-          audio->play();
-          audio->pause();
-          demuxer->reset();
-          afeed.start();
-
-          state = newState;
-          preBufferCount = 0;
-          return;
-        }
-        default:
-        {
-          logger->log("PlayerLiveRadio", Log::EMERG, "Thread called state %u to state %u which is not supported", state, newState);
-          abort();
-          break;
-        }        
-      }
-    }    
-  }  
-}
-
-bool PlayerLiveRadio::checkError()
-{
-  if (!vdr->isConnected())
-  {
-    switchState(S_STOP);
-    
-    Message* m = new Message();
-    m->from = this;
-    m->to = messageReceiver;
-    m->message = Message::PLAYER_EVENT;
-    m->parameter = PlayerLiveRadio::CONNECTION_LOST;
-    messageQueue->postMessage(m);
-    
-    return true;
-  }   
-  return false;
-}
-
-void PlayerLiveRadio::optimizeInstructionQueue()
-{
-  // Walk the list
-  
-  // Currently there are only 2 instruction types, so this is a bit overkill...
-
-  struct PLInstruction i;
-  while(instructions.size() > 1)
-  {
-    i = instructions.front();
-    if (i.instruction == I_SETCHANNEL)
-    {
-      instructions.pop();  // if this is the first of more than 1 command, currently it cannot possibly be relevant
-    }
-    else if (i.instruction == I_STOP)
-    {
-      return; // return here and ensure the next instruction will be stop
-    }
-  }
-}
-
-void PlayerLiveRadio::threadMethod()
-{
-  while(1)
-  {
-    while(!instructions.empty())
-    {
-      if (instructions.size() > 1)
-      {
-        logger->log("PlayerLiveRadio", Log::DEBUG, "Should optimise");
-        optimizeInstructionQueue();
-      }
-
-      struct PLInstruction i = instructions.front();
-      instructions.pop();
-    
-      if (i.instruction == I_SETCHANNEL)
-      {
-        logger->log("PlayerLiveRadio", Log::DEBUG, "start new stream");
-
-        switchState(S_PREBUFFERING);
-
-        if (!checkError())
-        {
-          Channel* chan = (*chanList)[i.channelIndex];
-          chan->loadPids();
-
-          bool found=false;
-
-          if (chan->numAPids > 0) 
-          {
-            ULONG j = 0;
-            while (j < chan->numAPids && !found)
-            {
-              if (Audio::getInstance()->streamTypeSupported(chan->apids[j].type))
-              {
-                demuxer->setAID(chan->apids[j].pid, 0, chan->apids[j].type, true);
-                audio->setStreamType(Audio::MPEG2_PES);
-                logger->log("PlayerLiveRadio", Log::DEBUG, "Demuxer pids: %u %u %u", chan->vpid, chan->apids[j].pid, chan->apids[j].type);
-                found = true;
-              }
-              j++;
-            }
-          }
-
-          if (!found)
-          {
-            if (chan->numDPids > 0 && audio->maysupportAc3())
-            {
-              ULONG j = 0;
-              while (j < chan->numDPids && !found)
-              {
-                if (Audio::getInstance()->streamTypeSupported(chan->dpids[j].type))
-                {
-                  demuxer->setAID(chan->dpids[j].pid, 1, chan->dpids[j].type, true);
-                  audio->setStreamType(Audio::MPEG2_PES);
-                  logger->log("PlayerLiveRadio", Log::DEBUG, "Demuxer pids: %u %u (ac3) %u", chan->vpid, chan->dpids[j].pid, chan->dpids[j].type);
-                  found=true;
-                }
-                j++;
-              }
-            }
-            else
-            {
-              logger->log("PlayerLiveRadio", Log::WARN, "Demuxer no pids!");
-            }
-          }
-
-          int streamSuccess = vdr->streamChannel(chan->number, this);
-          if (!checkError() && !streamSuccess)
-          {      
-            Message* m = new Message();
-            m->from = this;
-            m->to = messageReceiver;
-            m->message = Message::PLAYER_EVENT;
-            m->parameter = PlayerLiveRadio::STREAM_END;
-            messageQueue->postMessage(m);
-          }
-        }
-      }
-      else if (i.instruction == I_STOP)
-      {
-        logger->log("PlayerLiveRadio", Log::DEBUG, "Stopping");
-        switchState(S_STOP);
-        checkError();
-
-        stopNow = true;
-        break;
-      }
-    }
-
-    if (stopNow) break;
-
-    while(streamChunks.size())
-    {
-      chunkToDemuxer();
-
-      if (state == S_PREBUFFERING)
-      {
-        ++preBufferCount;
-        ULONG percentDone = (ULONG)(preBufferCount / (float)preBufferAmount * 100);
-        logger->log("PlayerLiveRadio", Log::DEBUG, "Prebuffering %lu%%", percentDone);
-        
-        Message* m = new Message();
-        m->from = this;
-        m->to = messageReceiver;
-        m->message = Message::PLAYER_EVENT;
-        m->parameter = PlayerLiveRadio::PREBUFFERING;
-        m->tag = percentDone;
-        messageQueue->postMessage(m);
-
-        if (preBufferCount == preBufferAmount)
-        {
-          switchState(S_PLAY);
-          checkError();
-        }
-      }
-    }
-    
-    threadLock();
-    threadWaitForSignal(); // unlocks and waits for signal
-    threadUnlock();
-  }
-
-  logger->log("PlayerLiveRadio", Log::DEBUG, "End of thread");
-}
diff --git a/playerliveradio.h b/playerliveradio.h
deleted file mode 100644 (file)
index 2b7f67c..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
-    Copyright 2008 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, see <https://www.gnu.org/licenses/>.
-*/
-
-#ifndef PLAYERLIVERADIO_H
-#define PLAYERLIVERADIO_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#ifndef WIN32
-#include <sys/time.h>
-#endif
-#include <time.h>
-
-#include <queue>
-
-#include "playerlive.h"
-
-#ifdef WIN32
-#include "threadwin.h"
-#else
-#include "threadp.h"
-#endif
-
-#include "callback.h"
-#include "defines.h"
-#include "afeed.h"
-#include "vdr.h"
-
-class MessageQueue;
-class Audio;
-class Log;
-class DemuxerTS;
-
-class PlayerLiveRadio : public PlayerLive, public Thread_TYPE, public Callback, public StreamReceiver
-{
-  public:
-    PlayerLiveRadio(MessageQueue* messageQueue, void* messageReceiver, ChannelList* chanList);
-    virtual ~PlayerLiveRadio();
-
-    virtual int init();
-    virtual int shutdown();
-
-    virtual void go(ULONG index);
-    virtual void setChannel(ULONG index);
-    virtual void stop();
-    virtual void setAudioChannel(int newChannel, int type,int streamtype);
-    virtual void setSubtitleChannel(int newChannel);
-
-    virtual bool* getDemuxerMpegAudioChannels();
-    virtual bool* getDemuxerAc3AudioChannels();
-    virtual int getCurrentAudioChannel();
-    virtual int *getTeletxtSubtitlePages();
-    virtual int getCurrentSubtitleChannel();
-
-    void call(void*); // for callback interface
-
-    virtual void streamReceive(ULONG, void*, ULONG); // stream receiver interface
-    
-    // Player events
-
-    // FIXME so far this just duplicates the old system + the wss
-
-    const static UCHAR CONNECTION_LOST = 1;
-    const static UCHAR STOP_PLAYBACK = 2;
-    const static UCHAR STREAM_END = 3;
-    const static UCHAR ASPECT43 = 4;
-    const static UCHAR ASPECT169 = 5;
-    const static UCHAR PREBUFFERING = 6;
-    
-  protected:
-    void threadMethod();
-
-  private:
-    MessageQueue* messageQueue;
-    void* messageReceiver;
-    Log* logger;
-    Audio* audio;
-    DemuxerTS* demuxer;
-    VDR* vdr;
-    AFeed afeed;
-    ChannelList* chanList;
-
-    std::queue<PLInstruction> instructions;
-    const static UCHAR I_SETCHANNEL = 1;
-    const static UCHAR I_STOP = 2;
-    
-    std::queue<StreamChunk> streamChunks;
-    
-    bool initted;
-
-    UCHAR state;
-    const static UCHAR S_STOP = 1;
-    const static UCHAR S_PREBUFFERING = 2;
-    const static UCHAR S_PLAY = 3;
-    void switchState(UCHAR newState);
-    bool checkError();
-
-    bool stopNow;
-    int preBufferCount;
-    const static int preBufferAmount = 3;
-
-    void clearStreamChunks();
-    void chunkToDemuxer();
-    void optimizeInstructionQueue();
-};
-
-#endif
-
diff --git a/playerradiolive.cc b/playerradiolive.cc
new file mode 100644 (file)
index 0000000..8caaa2e
--- /dev/null
@@ -0,0 +1,502 @@
+/*
+    Copyright 2008 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "playerradiolive.h"
+
+#include "defines.h"
+#include "log.h"
+#include "audio.h"
+#include "demuxerts.h"
+#include "vdr.h"
+#include "messagequeue.h"
+#include "input.h"
+#include "message.h"
+#include "channel.h"
+#include "video.h"
+
+// ----------------------------------- Called from outside, one offs or info funcs
+
+PlayerRadioLive::PlayerRadioLive(MessageQueue* tmessageQueue, void* tmessageReceiver, ChannelList* tchanList)
+: afeed(this)
+{
+  messageQueue = tmessageQueue;
+  messageReceiver = tmessageReceiver;
+  chanList = tchanList;
+  
+  audio = Audio::getInstance();
+  logger = Log::getInstance();
+  vdr = VDR::getInstance();
+  initted = false;
+
+  stopNow = false;
+  state = S_STOP;
+  Video::getInstance()->turnVideoOff();
+}
+
+PlayerRadioLive::~PlayerRadioLive()
+{
+  if (initted) shutdown();
+}
+
+int PlayerRadioLive::init()
+{
+  if (initted) return 0;
+
+  demuxer = new DemuxerTS();
+  if (!demuxer) return 0;
+  if (!demuxer->init(this, audio, NULL, NULL, 0, 200000, 0))
+  {
+    logger->log("PlayerRadioLive", Log::ERR, "Demuxer failed to init");
+    shutdown();
+    return 0;
+  }
+
+  audio->stop();
+
+  initted = true;
+  return 1;
+}
+
+int PlayerRadioLive::shutdown()
+{
+  if (!initted) return 0;
+  stop();
+  initted = false;
+  delete demuxer;
+  return 1;
+}
+
+bool* PlayerRadioLive::getDemuxerMpegAudioChannels()
+{
+  return demuxer->getmpAudioChannels();
+}
+
+bool* PlayerRadioLive::getDemuxerAc3AudioChannels()
+{
+  return demuxer->getac3AudioChannels();
+}
+
+int PlayerRadioLive::getCurrentAudioChannel()
+{
+  return demuxer->getAID();
+}
+
+int* PlayerRadioLive::getTeletxtSubtitlePages()
+{
+  return NULL;
+}
+
+int PlayerRadioLive::getCurrentSubtitleChannel()
+{
+  return demuxer->getSubID();
+}
+
+void PlayerRadioLive::setAudioChannel(int newChannel, int type, int streamtype)
+{
+  demuxer->setAID(newChannel, type, streamtype, true);
+}
+
+void PlayerRadioLive::setSubtitleChannel(int newChannel)
+{
+  demuxer->setSubID(newChannel);
+}
+
+// ----------------------------------- Externally called events
+
+void PlayerRadioLive::go(ULONG index)
+{
+  struct PLInstruction i;
+  i.instruction = I_SETCHANNEL;
+  i.channelIndex = index;
+  instructions.push(i);
+  threadStart();
+}
+
+void PlayerRadioLive::setChannel(ULONG index)
+{
+  logger->log("PlayerRadioLive", Log::DEBUG, "setChannel");
+  struct PLInstruction i;
+  i.instruction = I_SETCHANNEL;
+  i.channelIndex = index;
+  instructions.push(i);  
+  logger->log("PlayerRadioLive", Log::DEBUG, "posted setChannel instruction, now %i in queue", instructions.size());
+  threadSignalNoLock();
+}
+
+void PlayerRadioLive::stop()
+{
+  logger->log("PlayerRadioLive", Log::DEBUG, "stop");
+  struct PLInstruction i;
+  i.instruction = I_STOP;
+  instructions.push(i);
+  threadSignal();
+  threadStop();
+}
+
+// ----------------------------------- Callback
+
+void PlayerRadioLive::call(void* /*caller*/)
+{
+}
+
+// -----------------------------------
+
+void PlayerRadioLive::streamReceive(ULONG flag, void* data, ULONG len)
+{
+  // Flag:
+  // 0 = normal stream packet
+  // 1 = stream end
+  // 2 = connection lost
+
+  if (flag == 1)
+  {
+    if (data) abort();
+    
+    Message* m = new Message();
+    m->from = this;
+    m->to = messageReceiver;
+    m->message = Message::PLAYER_EVENT;
+    m->parameter = PlayerRadioLive::STREAM_END;
+    messageQueue->postMessage(m);
+  }
+  
+  if (streamChunks.size() < 11)
+  {
+    StreamChunk s;
+    s.data = data;
+    s.len = len;
+    streamChunks.push(s);
+    threadSignalNoLock();
+  }
+  else
+  {
+    // Too many chunks in streamChunks, drop this chunk
+    free(data);
+    logger->log("PlayerRadioLive", Log::WARN, "Dropped chunk");
+  }
+}
+
+void PlayerRadioLive::clearStreamChunks()
+{
+  while(streamChunks.size())
+  {
+    logger->log("PlayerRadioLive", Log::DEBUG, "Dropping chunk from old stream");
+    struct StreamChunk s = streamChunks.front();
+    streamChunks.pop();
+    free(s.data);
+  }
+}
+
+void PlayerRadioLive::chunkToDemuxer()
+{
+  StreamChunk s = streamChunks.front();
+  streamChunks.pop();
+  //logger->log("PlayerRadioLive", Log::DEBUG, "About to call demuxer with %p %lu", s.data, s.len);
+  /*int a =*/ demuxer->put((UCHAR*)s.data, s.len);
+  //logger->log("PlayerRadioLive", Log::DEBUG, "put %i to demuxer", a);
+  free(s.data);  
+}
+
+void PlayerRadioLive::switchState(UCHAR newState)
+{
+  logger->log("PlayerRadioLive", Log::DEBUG, "Switch from state %u to state %u", state, newState);
+
+  switch(state)
+  {
+    case S_STOP:   // FROM S_STOP
+    {
+      switch(newState)
+      {
+        case S_PREBUFFERING:
+        {
+          audio->stop();
+          audio->unPause();
+          audio->reset();
+          audio->setStreamType(Audio::MPEG2_PES);
+          audio->systemMuteOff();      
+          audio->doMuting();              
+          audio->play();
+          audio->pause();
+          demuxer->reset();
+          afeed.start();
+          
+          state = newState;
+          preBufferCount = 0;
+          return;
+        }
+        default:
+        {
+          logger->log("PlayerRadioLive", Log::EMERG, "Thread called state %u to state %u which is not supported", state, newState);
+          abort();
+          break;
+        }
+      }
+    }
+
+    case S_PREBUFFERING:    // FROM S_PREBUFFERING
+    {
+      switch(newState)
+      {
+        case S_PLAY:
+        {
+          audio->unPause();
+          state = newState;
+          return;
+        }
+        case S_STOP:
+        {
+          vdr->stopStreaming();
+          clearStreamChunks();
+          afeed.stop();
+          audio->stop();
+          audio->reset();
+          state = newState;
+          return;        
+        }
+        case S_PREBUFFERING:
+        {
+          vdr->stopStreaming();
+          clearStreamChunks();
+          afeed.stop();
+          audio->stop();
+          audio->reset();
+          audio->play();
+          audio->pause();
+          demuxer->reset();
+          afeed.start();
+
+          state = newState;
+          preBufferCount = 0;
+          return;        
+        }
+        default:
+        {
+          logger->log("PlayerRadioLive", Log::EMERG, "Thread called state %u to state %u which is not supported", state, newState);
+          abort();
+          break;
+        }        
+      }
+    }
+    
+    case S_PLAY:     // FROM S_PLAY
+    {
+      switch(newState)
+      {
+        case S_STOP:
+        { 
+          vdr->stopStreaming();
+          clearStreamChunks();
+          afeed.stop();
+          audio->stop();
+          audio->reset();
+          state = newState;
+          return;
+        }
+        case S_PREBUFFERING: // IS THIS HOW IT WORKS?
+        {
+          vdr->stopStreaming();
+          clearStreamChunks();
+          afeed.stop();
+          audio->stop();
+          audio->reset();
+          audio->play();
+          audio->pause();
+          demuxer->reset();
+          afeed.start();
+
+          state = newState;
+          preBufferCount = 0;
+          return;
+        }
+        default:
+        {
+          logger->log("PlayerRadioLive", Log::EMERG, "Thread called state %u to state %u which is not supported", state, newState);
+          abort();
+          break;
+        }        
+      }
+    }    
+  }  
+}
+
+bool PlayerRadioLive::checkError()
+{
+  if (!vdr->isConnected())
+  {
+    switchState(S_STOP);
+    
+    Message* m = new Message();
+    m->from = this;
+    m->to = messageReceiver;
+    m->message = Message::PLAYER_EVENT;
+    m->parameter = PlayerRadioLive::CONNECTION_LOST;
+    messageQueue->postMessage(m);
+    
+    return true;
+  }   
+  return false;
+}
+
+void PlayerRadioLive::optimizeInstructionQueue()
+{
+  // Walk the list
+  
+  // Currently there are only 2 instruction types, so this is a bit overkill...
+
+  struct PLInstruction i;
+  while(instructions.size() > 1)
+  {
+    i = instructions.front();
+    if (i.instruction == I_SETCHANNEL)
+    {
+      instructions.pop();  // if this is the first of more than 1 command, currently it cannot possibly be relevant
+    }
+    else if (i.instruction == I_STOP)
+    {
+      return; // return here and ensure the next instruction will be stop
+    }
+  }
+}
+
+void PlayerRadioLive::threadMethod()
+{
+  while(1)
+  {
+    while(!instructions.empty())
+    {
+      if (instructions.size() > 1)
+      {
+        logger->log("PlayerRadioLive", Log::DEBUG, "Should optimise");
+        optimizeInstructionQueue();
+      }
+
+      struct PLInstruction i = instructions.front();
+      instructions.pop();
+    
+      if (i.instruction == I_SETCHANNEL)
+      {
+        logger->log("PlayerRadioLive", Log::DEBUG, "start new stream");
+
+        switchState(S_PREBUFFERING);
+
+        if (!checkError())
+        {
+          Channel* chan = (*chanList)[i.channelIndex];
+          chan->loadPids();
+
+          bool found=false;
+
+          if (chan->numAPids > 0) 
+          {
+            ULONG j = 0;
+            while (j < chan->numAPids && !found)
+            {
+              if (Audio::getInstance()->streamTypeSupported(chan->apids[j].type))
+              {
+                demuxer->setAID(chan->apids[j].pid, 0, chan->apids[j].type, true);
+                audio->setStreamType(Audio::MPEG2_PES);
+                logger->log("PlayerRadioLive", Log::DEBUG, "Demuxer pids: %u %u %u", chan->vpid, chan->apids[j].pid, chan->apids[j].type);
+                found = true;
+              }
+              j++;
+            }
+          }
+
+          if (!found)
+          {
+            if (chan->numDPids > 0 && audio->maysupportAc3())
+            {
+              ULONG j = 0;
+              while (j < chan->numDPids && !found)
+              {
+                if (Audio::getInstance()->streamTypeSupported(chan->dpids[j].type))
+                {
+                  demuxer->setAID(chan->dpids[j].pid, 1, chan->dpids[j].type, true);
+                  audio->setStreamType(Audio::MPEG2_PES);
+                  logger->log("PlayerRadioLive", Log::DEBUG, "Demuxer pids: %u %u (ac3) %u", chan->vpid, chan->dpids[j].pid, chan->dpids[j].type);
+                  found=true;
+                }
+                j++;
+              }
+            }
+            else
+            {
+              logger->log("PlayerRadioLive", Log::WARN, "Demuxer no pids!");
+            }
+          }
+
+          int streamSuccess = vdr->streamChannel(chan->number, this);
+          if (!checkError() && !streamSuccess)
+          {      
+            Message* m = new Message();
+            m->from = this;
+            m->to = messageReceiver;
+            m->message = Message::PLAYER_EVENT;
+            m->parameter = PlayerRadioLive::STREAM_END;
+            messageQueue->postMessage(m);
+          }
+        }
+      }
+      else if (i.instruction == I_STOP)
+      {
+        logger->log("PlayerRadioLive", Log::DEBUG, "Stopping");
+        switchState(S_STOP);
+        checkError();
+
+        stopNow = true;
+        break;
+      }
+    }
+
+    if (stopNow) break;
+
+    while(streamChunks.size())
+    {
+      chunkToDemuxer();
+
+      if (state == S_PREBUFFERING)
+      {
+        ++preBufferCount;
+        ULONG percentDone = (ULONG)(preBufferCount / (float)preBufferAmount * 100);
+        logger->log("PlayerRadioLive", Log::DEBUG, "Prebuffering %lu%%", percentDone);
+        
+        Message* m = new Message();
+        m->from = this;
+        m->to = messageReceiver;
+        m->message = Message::PLAYER_EVENT;
+        m->parameter = PlayerRadioLive::PREBUFFERING;
+        m->tag = percentDone;
+        messageQueue->postMessage(m);
+
+        if (preBufferCount == preBufferAmount)
+        {
+          switchState(S_PLAY);
+          checkError();
+        }
+      }
+    }
+    
+    threadLock();
+    threadWaitForSignal(); // unlocks and waits for signal
+    threadUnlock();
+  }
+
+  logger->log("PlayerRadioLive", Log::DEBUG, "End of thread");
+}
diff --git a/playerradiolive.h b/playerradiolive.h
new file mode 100644 (file)
index 0000000..6ee6e02
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+    Copyright 2008 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef PLAYERRADIOLIVE_H
+#define PLAYERRADIOLIVE_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef WIN32
+#include <sys/time.h>
+#endif
+#include <time.h>
+
+#include <queue>
+
+#include "playerlive.h"
+
+#ifdef WIN32
+#include "threadwin.h"
+#else
+#include "threadp.h"
+#endif
+
+#include "callback.h"
+#include "defines.h"
+#include "afeed.h"
+#include "vdr.h"
+
+class MessageQueue;
+class Audio;
+class Log;
+class DemuxerTS;
+
+class PlayerRadioLive : public PlayerLive, public Thread_TYPE, public Callback, public StreamReceiver
+{
+  public:
+    PlayerRadioLive(MessageQueue* messageQueue, void* messageReceiver, ChannelList* chanList);
+    virtual ~PlayerRadioLive();
+
+    virtual int init();
+    virtual int shutdown();
+
+    virtual void go(ULONG index);
+    virtual void setChannel(ULONG index);
+    virtual void stop();
+    virtual void setAudioChannel(int newChannel, int type,int streamtype);
+    virtual void setSubtitleChannel(int newChannel);
+
+    virtual bool* getDemuxerMpegAudioChannels();
+    virtual bool* getDemuxerAc3AudioChannels();
+    virtual int getCurrentAudioChannel();
+    virtual int *getTeletxtSubtitlePages();
+    virtual int getCurrentSubtitleChannel();
+
+    void call(void*); // for callback interface
+
+    virtual void streamReceive(ULONG, void*, ULONG); // stream receiver interface
+    
+    // Player events
+
+    // FIXME so far this just duplicates the old system + the wss
+
+    const static UCHAR CONNECTION_LOST = 1;
+    const static UCHAR STOP_PLAYBACK = 2;
+    const static UCHAR STREAM_END = 3;
+    const static UCHAR ASPECT43 = 4;
+    const static UCHAR ASPECT169 = 5;
+    const static UCHAR PREBUFFERING = 6;
+    
+  protected:
+    void threadMethod();
+
+  private:
+    MessageQueue* messageQueue;
+    void* messageReceiver;
+    Log* logger;
+    Audio* audio;
+    DemuxerTS* demuxer;
+    VDR* vdr;
+    AFeed afeed;
+    ChannelList* chanList;
+
+    std::queue<PLInstruction> instructions;
+    const static UCHAR I_SETCHANNEL = 1;
+    const static UCHAR I_STOP = 2;
+    
+    std::queue<StreamChunk> streamChunks;
+    
+    bool initted;
+
+    UCHAR state;
+    const static UCHAR S_STOP = 1;
+    const static UCHAR S_PREBUFFERING = 2;
+    const static UCHAR S_PLAY = 3;
+    void switchState(UCHAR newState);
+    bool checkError();
+
+    bool stopNow;
+    int preBufferCount;
+    const static int preBufferAmount = 3;
+
+    void clearStreamChunks();
+    void chunkToDemuxer();
+    void optimizeInstructionQueue();
+};
+
+#endif
+
index 2c9178ea8e1927418244de8d5d5d4a7366a5e231..a33241799a8808df7278f4285d55a2bf6b876f1f 100644 (file)
@@ -24,7 +24,7 @@
 #include "audio.h"
 #include "playerlive.h"
 #include "playervideolive.h"
-#include "playerliveradio.h"
+#include "playerradiolive.h"
 #include "channel.h"
 #include "boxstack.h"
 #include "colour.h"
@@ -94,7 +94,7 @@ VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, V
   else
   {
     streamType = VDR::RADIO;
-    player = new PlayerLiveRadio(Command::getInstance(), this, chanList);
+    player = new PlayerRadioLive(Command::getInstance(), this, chanList);
   }
   player->init();