along with VOMP. If not, see <https://www.gnu.org/licenses/>.
*/
+#include <stdlib.h>
+#ifndef WIN32
+#include <sys/time.h>
+#endif
+#include <time.h>
+
#include "log.h"
#include "audio.h"
#include "video.h"
}
if (startPTS < endPTS)
- {
lengthSeconds = static_cast<ULONG>((endPTS - startPTS) / 90000);
- }
else
- {
lengthSeconds = static_cast<ULONG>((startPTS - endPTS) / 90000);
- }
return true;
}
return 1;
}
+void PlayerRadioRec::threadStop()
+{
+ playerThreadMutex.lock();
+ threadReqQuit = true;
+ playerThreadCond.notify_one();
+ playerThreadMutex.unlock();
+ playerThread.join();
+}
void PlayerRadioRec::setCurrentFrameNumber(ULONG num)
{
stateLock.unlock();
}
-
void PlayerRadioRec::playpause()
{
if (!initted) return;
stateLock.lock();
- if (state==S_PLAY) {
- switchState(S_PAUSE_P);
- } else {
- switchState(S_PLAY);
- }
+ if (state == S_PLAY)
+ switchState(S_PAUSE_P);
+ else
+ switchState(S_PLAY);
stateLock.unlock();
}
stateLock.lock();
if (state == S_PAUSE_P)
- {
switchState(S_PLAY);
- }
else
- {
switchState(S_PAUSE_P);
- }
stateLock.unlock();
}
void PlayerRadioRec::skipForward(UINT seconds)
{
- stateLock.lock();
+ std::lock_guard<std::mutex> lg(stateLock);
logger->log("PlayerRadioRec", Log::DEBUG, "SKIP FORWARD %i SECONDS", seconds);
ULONG currentSeconds = getCurrentSeconds();
ULONG currentFrame = demuxer->getPacketNum();
- if (currentSeconds == 0) { stateLock.unlock(); return; } // div by zero
- if (currentFrame == 0) { stateLock.unlock(); return; } // Current pos from demuxer is not valid
+ if (currentSeconds == 0) return; // div by zero
+ if (currentFrame == 0) return; // Current pos from demuxer is not valid
ULONG newFrame = currentFrame + (currentFrame * seconds / currentSeconds);
- if (newFrame > lengthFrames) { switchState(S_PLAY); stateLock.unlock(); }
+ if (newFrame > lengthFrames) switchState(S_PLAY);
else switchState(S_JUMP, newFrame);
- stateLock.unlock();
}
void PlayerRadioRec::skipBackward(UINT seconds)
{
- stateLock.lock();
+ std::lock_guard<std::mutex> lg(stateLock);
logger->log("PlayerRadioRec", Log::DEBUG, "SKIP BACKWARD %i SECONDS", seconds);
-
ULONG currentSeconds = getCurrentSeconds();
ULONG currentFrame = demuxer->getPacketNum();
- if (currentSeconds == 0) { stateLock.unlock(); return; } // div by zero
- if (currentFrame == 0) { stateLock.unlock(); return; } // Current pos from demuxer is not valid
+ if (currentSeconds == 0) return; // div by zero
+ if (currentFrame == 0) return; // Current pos from demuxer is not valid
ULONG newFrame;
if (seconds > currentSeconds)
newFrame = currentFrame - (currentFrame * seconds / currentSeconds);
switchState(S_JUMP, newFrame);
- stateLock.unlock();
}
// ----------------------------------- Implementations called events
case S_PLAY: // to S_PLAY
{
startup = true;
-
- audio->reset();
- audio->setStreamType(Audio::MPEG2_PES);
- audio->systemMuteOff();
- demuxer->reset();
-
- // FIXME use restartAtFrame here?
- if (currentFrameNumber > lengthFrames) currentFrameNumber = 0;
- demuxer->setPacketNum(currentFrameNumber);
- state = S_PLAY;
- threadStart();
- logger->log("PlayerRadioRec", Log::DEBUG, "Immediate play");
- afeed.start();
- audio->play();
-
+ restartAtFrame(currentFrameNumber);
return;
}
case S_PAUSE_P: // to S_PAUSE_P
void PlayerRadioRec::restartAtFrame(ULONG newFrame)
{
- afeed.stop();
- threadStop();
+ if (state != S_STOP)
+ {
+ afeed.stop();
+ threadStop();
+ }
+
audio->reset();
audio->setStreamType(Audio::MPEG2_PES);
demuxer->flush();
currentFrameNumber = newFrame;
demuxer->setPacketNum(newFrame);
+
+ state = S_PLAY;
+
+ playerThreadMutex.lock();
+ threadReqQuit = false;
+ playerThread = std::thread([this]
+ {
+ playerThreadMutex.lock();
+ playerThreadMutex.unlock();
+ threadMethod();
+ });
+ playerThreadMutex.unlock();
+
afeed.start();
- threadStart();
audio->play();
audio->systemMuteOff();
audio->doMuting();
void PlayerRadioRec::call(void* /*caller*/)
{
- threadSignalNoLock();
+ // No thread sync
+ playerThreadCond.notify_one();
}
// ----------------------------------- Feed thread
void PlayerRadioRec::threadMethod()
{
- if (state == S_PLAY) threadFeedPlay();
-}
+ if (state != S_PLAY) return;
-void PlayerRadioRec::threadFeedPlay()
-{
ULLONG feedPosition;
UINT thisRead, writeLength, thisWrite, askFor;
time_t lastRescan = time(NULL);
Buffer threadBuffer;
+ std::unique_lock<std::mutex> ul(playerThreadMutex, std::defer_lock);
+
while(1)
{
thisRead = 0;
writeLength = 0;
thisWrite = 0;
- threadCheckExit();
+ if (threadReqQuit) return;
// If we havn't rescanned for a while..
if ((lastRescan + 60) < time(NULL))
startup = false;
}
- threadCheckExit();
+ if (threadReqQuit) return;
while(writeLength < thisRead)
{
if (!thisWrite)
{
// demuxer is full and can't take anymore
- threadLock();
- threadWaitForSignal();
- threadUnlock();
+
+ ul.lock();
+ if (threadReqQuit) { ul.unlock(); return; }
+ playerThreadCond.wait(ul);
+ ul.unlock();
}
- threadCheckExit();
+ if (threadReqQuit) return;
}
threadBuffer.release();
// end of recording
logger->log("PlayerRadioRec", Log::DEBUG, "Recording playback ends");
- threadCheckExit();
+ if (threadReqQuit) return;
Message* m = new Message(); // Must be done after this thread finishes, and must break into master mutex
logger->log("PlayerRadioRec", Log::DEBUG, "Posting message to %p...", messageQueue);
messageQueue->postMessage(m);
}
-
/*
- Copyright 2004-2006 Chris Tallon
+ Copyright 2004-2020 Chris Tallon
This file is part of VOMP.
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.
+ along with VOMP. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef PLAYERRADIOREC_H
#define PLAYERRADIOREC_H
-#include <stdio.h>
-#include <stdlib.h>
-#ifndef WIN32
-#include <sys/time.h>
-#endif
-#include <time.h>
-
+#include <thread>
#include <mutex>
+#include <condition_variable>
-#include "threadsystem.h"
-
-#include "callback.h"
#include "defines.h"
+#include "callback.h"
#include "afeed.h"
class Log;
* I don't know where this comes from but things seem to work.
*/
-class PlayerRadioRec : public Thread_TYPE, public Callback
+class PlayerRadioRec : public Callback
{
public:
PlayerRadioRec(MessageQueue* messageQueue, void* messageReceiver);
const static UCHAR STOP_PLAYBACK = 2;
const static UCHAR STREAM_END = 3;
- protected:
- void threadMethod();
-
private:
void switchState(UCHAR newState, ULONG jumpToFrame=0);
-
- void threadFeedPlay();
- void threadFeedScan();
+ void threadMethod();
void doConnectionLost();
void restartAtFrame(ULONG newFrame);
std::mutex stateLock;
+ std::thread playerThread;
+ std::mutex playerThreadMutex;
+ std::condition_variable playerThreadCond;
+ bool threadReqQuit;
+ void threadStop();
+
ULLONG lengthBytes{};
ULONG lengthFrames{};
ULONG currentFrameNumber{};