$(STRIP) vompclient
install:
- rm -f /diskless/nfs/mvp/vompclient
- cp vompclient /diskless/nfs/mvp
+ rm -f /mnt/auto/defiant/diskless/nfs/mvp/vompclient
+ cp vompclient /mnt/auto/defiant/diskless/nfs/mvp
install-wmp:
rm -f /diskless/nfs/wmvp/vompclient
if (alen)
{
cb.call(this);
+ Log::getInstance()->log("Afeed", Log::DEBUG, "written");
}
else
{
vaudioplayer.o audioplayer.o demuxeraudio.o abstractoption.o \
eventdispatcher.o vdrrequestpacket.o vdrresponsepacket.o \
vvideolivetv.o \
- vvideolive.o vlivebanner.o playerlivetv.o
+ vvideolive.o vlivebanner.o playerlivetv.o playerliveradio.o
--- /dev/null
+/*
+ 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 PLAYERLIVE_H
+#define PLAYERLIVE_H
+
+#include "defines.h"
+
+struct StreamChunk
+{
+ void* data;
+ ULONG len;
+};
+
+struct PLInstruction
+{
+ UCHAR instruction;
+ ULONG channelIndex;
+};
+
+class PlayerLive
+{
+ public:
+ virtual ~PlayerLive() {}
+
+ virtual int init()=0;
+ virtual int shutdown()=0;
+
+ virtual void go(ULONG index)=0;
+ virtual void setChannel(ULONG index)=0;
+ virtual void stop()=0;
+ virtual void setAudioChannel(int newChannel)=0;
+
+ virtual bool* getDemuxerMpegAudioChannels()=0;
+ virtual bool* getDemuxerAc3AudioChannels()=0;
+ virtual int getCurrentAudioChannel()=0;
+};
+
+#endif
+
--- /dev/null
+/*
+ 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, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "playerliveradio.h"
+
+#include "log.h"
+#include "audio.h"
+#include "demuxerts.h"
+#include "vdr.h"
+#include "messagequeue.h"
+#include "remote.h"
+#include "message.h"
+#include "channel.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;
+}
+
+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, 0, 40000))
+ {
+ logger->log("PlayerLiveRadio", Log::ERR, "Demuxer failed to init");
+ shutdown();
+ return 0;
+ }
+
+ afeed.init();
+ audio->stop();
+
+ initted = true;
+ return 1;
+}
+
+int PlayerLiveRadio::shutdown()
+{
+ if (!initted) return 0;
+ stop();
+ initted = false;
+
+ delete demuxer;
+
+#ifdef WIN32
+ CloseHandle(mutex);
+#endif
+
+ return 1;
+}
+
+bool* PlayerLiveRadio::getDemuxerMpegAudioChannels()
+{
+ return demuxer->getmpAudioChannels();
+}
+
+bool* PlayerLiveRadio::getDemuxerAc3AudioChannels()
+{
+ return demuxer->getac3AudioChannels();
+}
+
+int PlayerLiveRadio::getCurrentAudioChannel()
+{
+ return demuxer->getAID();
+}
+
+void PlayerLiveRadio::setAudioChannel(int newChannel)
+{
+ return demuxer->setAID(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);
+ 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(void* data, ULONG len)
+{
+ 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->sync();
+ audio->play();
+ audio->pause();
+
+ demuxer->reset();
+// demuxer->seek();
+
+ 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;
+ }
+ 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();
+ vfeed.stop();
+ afeed.stop();
+ video->stop();
+ video->blank();
+ audio->stop();
+ audio->unPause();
+ audio->reset();
+
+ video->reset();
+ video->sync();
+ video->play();
+ video->pause();
+
+ audio->setStreamType(Audio::MPEG2_PES);
+ audio->sync();
+ audio->play();
+ audio->pause();
+
+ demuxer->reset();
+ demuxer->seek();
+
+ afeed.start();
+ vfeed.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;
+ }
+ }
+ }
+ }
+}
+
+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) optimizeInstructionQueue();
+
+ struct PLInstruction i = instructions.front();
+ instructions.pop();
+
+ if (i.instruction == I_SETCHANNEL)
+ {
+ logger->log("PlayerLiveRadio", Log::DEBUG, "start new stream");
+
+ switchState(S_PREBUFFERING);
+
+ Channel* chan = (*chanList)[i.channelIndex];
+ chan->loadPids();
+
+ if (chan->numAPids > 0)
+ {
+ demuxer->setAID(chan->apids[0].pid);
+ logger->log("PlayerLiveRadio", Log::DEBUG, "Demuxer pids: %u %u", chan->vpid, chan->apids[0].pid);
+ }
+ else
+ {
+ logger->log("PlayerLiveRadio", Log::WARN, "Demuxer no pids!");
+ }
+
+ vdr->streamChannel(chan->number, this);
+ }
+ else if (i.instruction == I_STOP)
+ {
+ logger->log("PlayerLiveRadio", Log::DEBUG, "Stopping");
+ switchState(S_STOP);
+
+ stopNow = true;
+ break;
+ }
+ }
+
+ if (stopNow) break;
+
+ while(streamChunks.size())
+ {
+ chunkToDemuxer();
+
+ if (state == S_PREBUFFERING)
+ {
+ if (++preBufferCount == preBufferAmount)
+ {
+ switchState(S_PLAY);
+ }
+ }
+ }
+
+ threadLock();
+ threadWaitForSignal(); // unlocks and waits for signal
+ threadUnlock();
+ }
+
+ logger->log("PlayerLiveRadio", Log::DEBUG, "End of thread");
+}
+
--- /dev/null
+/*
+ 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, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#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);
+
+ virtual bool* getDemuxerMpegAudioChannels();
+ virtual bool* getDemuxerAc3AudioChannels();
+ virtual int getCurrentAudioChannel();
+
+ void call(void*); // for callback interface
+
+ virtual void streamReceive(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;
+
+ protected:
+ void threadMethod();
+ void threadPostStopCleanup() {};
+
+ private:
+ MessageQueue* messageQueue;
+ void* messageReceiver;
+ Log* logger;
+ Audio* audio;
+ DemuxerTS* demuxer;
+ VDR* vdr;
+ AFeed afeed;
+ ChannelList* chanList;
+
+ queue<PLInstruction> instructions;
+ const static UCHAR I_SETCHANNEL = 1;
+ const static UCHAR I_STOP = 2;
+
+ 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 stopNow;
+ int preBufferCount;
+ const static int preBufferAmount = 3;
+
+ void clearStreamChunks();
+ void chunkToDemuxer();
+ void optimizeInstructionQueue();
+};
+
+#endif
+
void PlayerLiveTV::go(ULONG index)
{
- struct PLTVInstruction i;
+ struct PLInstruction i;
i.instruction = I_SETCHANNEL;
i.channelIndex = index;
instructions.push(i);
void PlayerLiveTV::setChannel(ULONG index)
{
logger->log("PlayerLiveTV", Log::DEBUG, "setChannel");
- struct PLTVInstruction i;
+ struct PLInstruction i;
i.instruction = I_SETCHANNEL;
i.channelIndex = index;
instructions.push(i);
void PlayerLiveTV::stop()
{
logger->log("PlayerLiveTV", Log::DEBUG, "stop");
- struct PLTVInstruction i;
+ struct PLInstruction i;
i.instruction = I_STOP;
instructions.push(i);
threadSignal();
// Currently there are only 2 instruction types, so this is a bit overkill...
- struct PLTVInstruction i;
+ struct PLInstruction i;
while(instructions.size() > 1)
{
i = instructions.front();
{
if (instructions.size() > 1) optimizeInstructionQueue();
- struct PLTVInstruction i = instructions.front();
+ struct PLInstruction i = instructions.front();
instructions.pop();
if (i.instruction == I_SETCHANNEL)
#include <queue>
+#include "playerlive.h"
+
#ifdef WIN32
#include "threadwin.h"
#else
class Log;
class DemuxerTS;
-struct PLTVInstruction
-{
- UCHAR instruction;
- ULONG channelIndex;
-};
-
-struct StreamChunk
-{
- void* data;
- ULONG len;
-};
-
-class PlayerLiveTV : public Thread_TYPE, public Callback, public StreamReceiver
+class PlayerLiveTV : public PlayerLive, public Thread_TYPE, public Callback, public StreamReceiver
{
public:
PlayerLiveTV(MessageQueue* messageQueue, void* messageReceiver, ChannelList* chanList);
virtual ~PlayerLiveTV();
- int init();
- int shutdown();
+ virtual int init();
+ virtual int shutdown();
- void go(ULONG index);
- void setChannel(ULONG index);
- void stop();
- void setAudioChannel(int newChannel);
+ virtual void go(ULONG index);
+ virtual void setChannel(ULONG index);
+ virtual void stop();
+ virtual void setAudioChannel(int newChannel);
- bool* getDemuxerMpegAudioChannels();
- bool* getDemuxerAc3AudioChannels();
- int getCurrentAudioChannel();
+ virtual bool* getDemuxerMpegAudioChannels();
+ virtual bool* getDemuxerAc3AudioChannels();
+ virtual int getCurrentAudioChannel();
void call(void*); // for callback interface
AFeed afeed;
ChannelList* chanList;
- queue<PLTVInstruction> instructions;
+ queue<PLInstruction> instructions;
const static UCHAR I_SETCHANNEL = 1;
const static UCHAR I_STOP = 2;
if (chanList) chan = (Channel*)sl.getCurrentOptionData();
if (chan == NULL) return 2;
- if (chan->type == VDR::VIDEO)
- {
+// if (chan->type == VDR::VIDEO)
+// {
VVideoLiveTV* v = new VVideoLiveTV(chanList, chan->number, this);
boxstack->add(v);
v->go();
+/*
}
else
{
boxstack->update(v);
v->channelChange(VVideoLive::NUMBER, chan->number);
}
-
+*/
return 2;
}
case Remote::BACK:
#include "vchannellist.h"
#include "video.h"
+#include "playerlive.h"
#include "playerlivetv.h"
+#include "playerliveradio.h"
#include "channel.h"
#include "boxstack.h"
#include "colour.h"
eventList = NULL;
videoMode = video->getMode();
- player = new PlayerLiveTV(Command::getInstance(), this, chanList);
+
+ if ((*chanList)[currentChannelIndex]->type == VDR::VIDEO)
+ {
+ player = new PlayerLiveTV(Command::getInstance(), this, chanList);
+ }
+ else
+ {
+ player = new PlayerLiveRadio(Command::getInstance(), this, chanList);
+ }
player->init();
setSize(video->getScreenWidth(), video->getScreenHeight());
class VChannelList;
class BoxStack;
class WTextbox;
-class PlayerLiveTV;
+class PlayerLive;
class VVideoLiveTV : public Boxx, public TimerReceiver
{
BoxStack* boxstack;
VDR* vdr;
Video* video;
- PlayerLiveTV* player;
+ PlayerLive* player;
bool playing;
ChannelList* chanList;
VChannelList* vchannelList;