/*
- Copyright 2008 Chris Tallon
+ Copyright 2008-2020 Chris Tallon
This file is part of VOMP.
along with VOMP. If not, see <https://www.gnu.org/licenses/>.
*/
-#include "playerradiolive.h"
+#include <stdlib.h>
+#ifndef WIN32
+#include <sys/time.h>
+#endif
+#include <time.h>
#include "defines.h"
#include "log.h"
#include "channel.h"
#include "video.h"
+#include "playerradiolive.h"
+
// ----------------------------------- Called from outside, one offs or info funcs
PlayerRadioLive::PlayerRadioLive(MessageQueue* tmessageQueue, void* tmessageReceiver, ChannelList* tchanList)
-: afeed(this)
+: messageQueue(tmessageQueue), messageReceiver(tmessageReceiver), afeed(this), chanList(tchanList)
{
- 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();
}
int PlayerRadioLive::shutdown()
{
if (!initted) return 0;
- stop();
+ if (state != S_STOP) // FIXME check when this is called and how. This is not thread-sync bullet proof as-is.
+ {
+ logger->log("PlayerRadioLive", Log::DEBUG, "state is not stop, calling");
+ stop();
+ }
initted = false;
delete demuxer;
return 1;
void PlayerRadioLive::go(ULONG index)
{
+ playerThreadMutex.lock();
+
struct PLInstruction i;
i.instruction = I_SETCHANNEL;
i.channelIndex = index;
instructions.push(i);
- threadStart();
+
+ playerThread = std::thread([this]
+ {
+ playerThreadMutex.lock();
+ playerThreadMutex.unlock();
+ threadMethod();
+ });
+ playerThreadMutex.unlock();
}
void PlayerRadioLive::setChannel(ULONG index)
i.channelIndex = index;
instructions.push(i);
logger->log("PlayerRadioLive", Log::DEBUG, "posted setChannel instruction, now %i in queue", instructions.size());
- threadSignalNoLock();
+ playerThreadCond.notify_one();
}
void PlayerRadioLive::stop()
{
logger->log("PlayerRadioLive", Log::DEBUG, "stop");
+ playerThreadMutex.lock();
struct PLInstruction i;
i.instruction = I_STOP;
instructions.push(i);
- threadSignal();
- threadStop();
+ playerThreadCond.notify_one();
+ playerThreadMutex.unlock();
+ playerThread.join();
+ logger->log("PlayerRadioLive", Log::DEBUG, "stop successful");
}
// ----------------------------------- Callback
s.data = data;
s.len = len;
streamChunks.push(s);
- threadSignalNoLock();
+ playerThreadCond.notify_one();
}
else
{
void PlayerRadioLive::threadMethod()
{
+ std::unique_lock<std::mutex> ul(playerThreadMutex, std::defer_lock);
+
while(1)
{
while(!instructions.empty())
logger->log("PlayerRadioLive", Log::DEBUG, "Stopping");
switchState(S_STOP);
checkError();
-
- stopNow = true;
- break;
+ return;
}
}
- if (stopNow) break;
-
while(streamChunks.size())
{
chunkToDemuxer();
}
}
- threadLock();
- threadWaitForSignal(); // unlocks and waits for signal
- threadUnlock();
+ ul.lock();
+ if (!instructions.empty()) { ul.unlock(); continue; }
+ playerThreadCond.wait(ul);
+ ul.unlock();
}
logger->log("PlayerRadioLive", Log::DEBUG, "End of thread");
/*
- Copyright 2008 Chris Tallon
+ Copyright 2008-2020 Chris Tallon
This file is part of VOMP.
#ifndef PLAYERRADIOLIVE_H
#define PLAYERRADIOLIVE_H
-#include <stdio.h>
-#include <stdlib.h>
-#ifndef WIN32
-#include <sys/time.h>
-#endif
-#include <time.h>
+#include <mutex>
+#include <thread>
+#include <condition_variable>
#include <queue>
#include "playerlive.h"
-
-#ifdef WIN32
-#include "threadwin.h"
-#else
-#include "threadp.h"
-#endif
-
#include "callback.h"
#include "defines.h"
#include "afeed.h"
class Log;
class DemuxerTS;
-class PlayerRadioLive : public PlayerLive, public Thread_TYPE, public Callback, public StreamReceiver
+class PlayerRadioLive : public PlayerLive, public Callback, public StreamReceiver
{
public:
PlayerRadioLive(MessageQueue* messageQueue, void* messageReceiver, ChannelList* chanList);
virtual bool* getDemuxerMpegAudioChannels();
virtual bool* getDemuxerAc3AudioChannels();
virtual int getCurrentAudioChannel();
- virtual int *getTeletxtSubtitlePages();
+ virtual int* getTeletxtSubtitlePages();
virtual int getCurrentSubtitleChannel();
void call(void*); // for callback interface
const static UCHAR ASPECT43 = 4;
const static UCHAR ASPECT169 = 5;
const static UCHAR PREBUFFERING = 6;
-
- protected:
- void threadMethod();
private:
MessageQueue* messageQueue;
std::queue<PLInstruction> instructions;
const static UCHAR I_SETCHANNEL = 1;
const static UCHAR I_STOP = 2;
-
+
std::queue<StreamChunk> streamChunks;
-
- bool initted;
- UCHAR state;
+ bool initted{};
+
+ UCHAR state{S_STOP};
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;
+ std::thread playerThread;
+ std::mutex playerThreadMutex;
+ std::condition_variable playerThreadCond;
+ void threadMethod();
+
void clearStreamChunks();
void chunkToDemuxer();
void optimizeInstructionQueue();
};
#endif
-
#ifndef PLAYERVIDEOLIVE_H
#define PLAYERVIDEOLIVE_H
-#include <stdio.h>
-#include <stdlib.h>
-#ifndef WIN32
-#include <sys/time.h>
-#endif
-#include <time.h>
-
#include <mutex>
#include <thread>
#include <condition_variable>
const static UCHAR ASPECT169 = 5;
const static UCHAR PREBUFFERING = 6;
- protected:
- void threadMethod();
-
private:
VFeed vfeed;
AFeed afeed;
std::queue<StreamChunk> streamChunks;
-
std::thread playerThread;
std::mutex playerThreadMutex;
std::condition_variable playerThreadCond;
+ void threadMethod();
const static UCHAR S_STOP = 1;
const static UCHAR S_VIDEOSTARTUP = 2;