, _log (log)
, _prepare_work (new boost::asio::io_service::work (_prepare_service))
, _pending_seek_accurate (false)
+ , _suspended (false)
, _finished (false)
, _died (false)
, _stop_thread (false)
_player_video_connection = _player->Video.connect (bind (&Butler::video, this, _1, _2));
_player_audio_connection = _player->Audio.connect (bind (&Butler::audio, this, _1, _2));
_player_text_connection = _player->Text.connect (bind (&Butler::text, this, _1, _2, _3));
+ _player_may_change_connection = _player->MayChange.connect (bind (&Butler::suspend, this));
_player_changed_connection = _player->Changed.connect (bind (&Butler::return_seek, this, _2));
_player_not_changed_connection = _player->NotChanged.connect (bind (&Butler::return_seek, this, false));
_thread = new boost::thread (bind (&Butler::thread, this));
bool
Butler::should_run () const
{
+ if (_suspended) {
+ return false;
+ }
+
if (_video.size() >= MAXIMUM_VIDEO_READAHEAD * 10) {
/* This is way too big */
throw ProgrammingError
{
boost::mutex::scoped_lock lm (_mutex);
- if (_pending_seek_position) {
- /* Don't store any video while a seek is pending */
+ if (_pending_seek_position || _suspended) {
+ /* Don't store any video in these cases */
return;
}
{
{
boost::mutex::scoped_lock lm (_mutex);
- if (_pending_seek_position || _disable_audio) {
- /* Don't store any audio while a seek is pending, or if audio is disabled */
+ if (_pending_seek_position || _disable_audio || _suspended) {
+ /* Don't store any audio in these cases */
return;
}
}
}
seek_unlocked (seek_to, true);
+ _suspended = false;
_awaiting = seek_to;
}
boost::mutex::scoped_lock lm2 (_buffers_mutex);
_closed_caption.put (make_pair(pt, period));
}
+
+void
+Butler::suspend ()
+{
+ boost::mutex::scoped_lock lm (_mutex);
+ _suspended = true;
+}
void text (PlayerText pt, TextType type, DCPTimePeriod period);
bool should_run () const;
void prepare (boost::weak_ptr<PlayerVideo> video) const;
+ void suspend ();
void return_seek (bool frequent);
void seek_unlocked (DCPTime position, bool accurate);
boost::condition _arrived;
boost::optional<DCPTime> _pending_seek_position;
bool _pending_seek_accurate;
+ bool _suspended;
bool _finished;
bool _died;
bool _stop_thread;
boost::signals2::scoped_connection _player_video_connection;
boost::signals2::scoped_connection _player_audio_connection;
boost::signals2::scoped_connection _player_text_connection;
+ boost::signals2::scoped_connection _player_may_change_connection;
boost::signals2::scoped_connection _player_changed_connection;
boost::signals2::scoped_connection _player_not_changed_connection;
};
Player::Player (shared_ptr<const Film> film, shared_ptr<const Playlist> playlist)
: _film (film)
, _playlist (playlist)
- , _can_run (false)
+ , _suspended (false)
, _ignore_video (false)
, _ignore_audio (false)
, _ignore_text (false)
_last_video_time = DCPTime ();
_last_video_eyes = EYES_BOTH;
_last_audio_time = DCPTime ();
- _can_run = true;
+ _suspended = false;
}
void
until that has happened and we've rebuilt our pieces. Stop pass()
and seek() from working until then.
*/
- _can_run = false;
+ _suspended = true;
}
MayChange ();
Player::playlist_content_not_changed ()
{
/* A possible content change did end up happening for some reason */
- setup_pieces ();
NotChanged ();
}
{
boost::mutex::scoped_lock lm (_mutex);
- if (!_can_run) {
+ if (_suspended) {
/* We can't pass in this state */
return false;
}
{
boost::mutex::scoped_lock lm (_mutex);
- if (!_can_run) {
+ if (_suspended) {
/* We can't seek in this state */
return;
}
boost::optional<DCPTime> content_time_to_dcp (boost::shared_ptr<Content> content, ContentTime t);
+ /* The player's internal state may be about to change such so
+ that its emissions from Video and Audio will suddenly be
+ from an undefined position. Listeners should prepare
+ themselves for this possibility.
+ */
boost::signals2::signal<void ()> MayChange;
- /** Emitted when something has changed such that if we went back and emitted
- * the last frame again it would look different. This is not emitted after
- * a seek.
+ /** The player's internal state has now changed.
*
* The first parameter is what changed.
* The second parameter is true if these signals are currently likely to be frequent.
*/
boost::signals2::signal<void (int, bool)> Changed;
+
+ /** The change suggested by a MayChange did not happen */
boost::signals2::signal<void ()> NotChanged;
/** Emitted when a video frame is ready. These emissions happen in the correct order. */
boost::shared_ptr<const Film> _film;
boost::shared_ptr<const Playlist> _playlist;
- /** We can pass() and seek() */
- bool _can_run;
+ /** true if we are suspended (i.e. pass() and seek() do nothing */
+ bool _suspended;
std::list<boost::shared_ptr<Piece> > _pieces;
/** Size of the image in the DCP (e.g. 1990x1080 for flat) */