BlinkenArea - GitList
Repositories
Blog
Wiki
Blinker
Code
Commits
Branches
Tags
Search
Tree:
1d54735
Branches
Tags
master
Blinker
src
noarch
Player.cpp
typo
Stefan Schuermans
commited
1d54735
at 2011-12-22 22:48:19
Player.cpp
Blame
History
Raw
/* Blinker Copyright 2011 Stefan Schuermans <stefan@blinkenarea.org> Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html a blinkenarea.org project */ #include <list> #include <string> #include <BlinkenLib/BlinkenFrame.h> #include <BlinkenLib/BlinkenMovie.h> #include "Directory.h" #include "File.h" #include "InStreamFile.h" #include "ListTracker.h" #include "ListTracker_impl.h" #include "Mgrs.h" #include "Module.h" #include "OutStreamFile.h" #include "Player.h" #include "PlayerMovie.h" #include "StreamRecv.h" #include "Time.h" #include "TimeCallee.h" namespace Blinker { /** * @brief constructor * @param[in] name module name * @param[in] mgrs managers * @param[in] dirBase base directory */ Player::Player(const std::string &name, Mgrs &mgrs, const Directory &dirBase): Module(name, mgrs, dirBase), m_fileOutStream(dirBase.getFile("outstream"), mgrs.m_streamMgr), m_fileHaltStream(dirBase.getFile("haltstream"), mgrs.m_streamMgr), m_playlistTracker(*this, dirBase.getSubdir("playlist")), m_curValid(false), m_curEntry(m_playlistTracker.m_list.begin()), m_curFrame(0), m_curChange(false), m_halted(false) { // load playlist m_fileHaltStream.setStreamRecv(this); m_playlistTracker.init(); checkCurChanged(); } /// virtual destructor Player::~Player() { // cancel time callback request m_mgrs.m_callMgr.cancelTimeCall(this); // free all movies m_playlistTracker.clear(); m_fileHaltStream.setStreamRecv(NULL); } /// check for update of configuration void Player::updateConfig() { // output stream name file was modified -> re-get output stream if (m_fileOutStream.checkModified()) { m_fileOutStream.update(); sendFrame(); } // halt stream name file was modified -> re-get halt stream if (m_fileHaltStream.checkModified()) m_fileHaltStream.update(); // playlist update m_playlistTracker.updateConfig(); checkCurChanged(); } /** * @brief set current frame * @param[in] stream stream name * @param[in] pFrame current frame (NULL for none) */ void Player::setFrame(const std::string &stream, stBlinkenFrame *pFrame) { // this is coming from the halt stream, which will halt the player // whenever a frame is available on this halt stream // halt stream came to life -> halt player if (pFrame && !m_halted) { m_halted = true; if (m_curValid) { // store remaining frame time m_remainTime = m_nextTime - Time::now(); if (m_remainTime < Time::zero) m_remainTime = Time::zero; } // cancel time call m_mgrs.m_callMgr.cancelTimeCall(this); } // halt stream ended -> continue playing else if (!pFrame && m_halted) { m_halted = false; if (m_curValid) { // determine time for next frame m_nextTime = Time::now() + m_remainTime; // schedule time call m_mgrs.m_callMgr.requestTimeCall(this, m_nextTime); } } (void)stream; // unused } /// callback when requested time reached void Player::timeCall() { // leave if halted if (m_halted) return; // leave if time is not yet ready to next frame if (Time::now() < m_nextTime) { // request call at time for next frame m_mgrs.m_callMgr.requestTimeCall(this, m_nextTime); return; } // go to next frame ++m_curFrame; // process new current frame procFrame(); } /// check if current movie changed and react void Player::checkCurChanged() { // current movie changed if (m_curChange) { m_curChange = false; // go to begin of new current movie and start playing now m_curFrame = 0; m_remainTime = Time::zero; m_nextTime = Time::now(); procFrame(); } // if (m_curChange) } /// process current frame void Player::procFrame() { // movie finished -> next movie // use while loops to handle empty movies / empty playlist m_curValid = true; bool wrapped = false; while (true) { // playlist finished -> re-start from beginning while (m_curEntry == m_playlistTracker.m_list.end()) { m_curEntry = m_playlistTracker.m_list.begin(); m_curFrame = 0; // detect empty playlist or playlist with only empty movies if (wrapped) { m_curValid = false; break; } wrapped = true; } if (!m_curValid) break; // movie not yet finished -> done if (m_curFrame < BlinkenMovieGetFrameCnt(m_curEntry->m_pObj->m_pMovie)) break; // movie finished -> next movie ++m_curEntry; m_curFrame = 0; } // send new frame to stream sendFrame(); // if a frame is there if (m_curValid) { // get frame time and calculate absolute time for next frame stBlinkenFrame *pFrame = BlinkenMovieGetFrame(m_curEntry->m_pObj->m_pMovie, m_curFrame); m_remainTime.fromMs(BlinkenFrameGetDuration(pFrame)); m_nextTime += m_remainTime; // request call at time for next frame if (!m_halted) m_mgrs.m_callMgr.requestTimeCall(this, m_nextTime); } } /// send current frame to output stream void Player::sendFrame() { // frame available -> send it if (m_curValid) { stBlinkenFrame *pFrame = BlinkenMovieGetFrame(m_curEntry->m_pObj->m_pMovie, m_curFrame); m_fileOutStream.setFrame(pFrame); } // no frame available -> send this information else m_fileOutStream.setFrame(NULL); } } // namespace Blinker