_playlist_change_connection = _playlist->Change.connect (bind (&Film::playlist_change, this, _1));
_playlist_order_changed_connection = _playlist->OrderChanged.connect (bind (&Film::playlist_order_changed, this));
_playlist_content_change_connection = _playlist->ContentChange.connect (bind (&Film::playlist_content_change, this, _1, _2, _3, _4));
+ _playlist_length_change_connection = _playlist->LengthChange.connect (bind(&Film::playlist_length_change, this));
if (dir) {
/* Make state.directory a complete path without ..s (where possible)
}
}
+void
+Film::playlist_length_change ()
+{
+ LengthChange ();
+}
+
void
Film::playlist_change (ChangeType type)
{
/** Emitted when some property of our content has changed */
mutable boost::signals2::signal<void (ChangeType, boost::weak_ptr<Content>, int, bool)> ContentChange;
+ /** Emitted when the film's length might have changed; this is not like a normal
+ property as its value is derived from the playlist, so it has its own signal.
+ */
+ mutable boost::signals2::signal<void ()> LengthChange;
+
/** Emitted when we have something important to tell the user */
boost::signals2::signal<void (std::string)> Message;
void playlist_change (ChangeType);
void playlist_order_changed ();
void playlist_content_change (ChangeType type, boost::weak_ptr<Content>, int, bool frequent);
+ void playlist_length_change ();
void maybe_add_content (boost::weak_ptr<Job>, boost::weak_ptr<Content>, bool disable_audio_analysis);
void audio_analysis_finished ();
void check_settings_consistency ();
boost::signals2::scoped_connection _playlist_change_connection;
boost::signals2::scoped_connection _playlist_order_changed_connection;
boost::signals2::scoped_connection _playlist_content_change_connection;
+ boost::signals2::scoped_connection _playlist_length_change_connection;
std::list<boost::signals2::connection> _job_connections;
std::list<boost::signals2::connection> _audio_analysis_connections;
if (changed) {
OrderChanged ();
}
+
+ /* The length might have changed, and that's good enough for this signal */
+ LengthChange ();
}
}
}
Change (CHANGE_TYPE_DONE);
+
+ LengthChange ();
}
void
}
/* This won't change order, so it does not need a sort */
+
+ LengthChange ();
}
void
}
}
+ Change (CHANGE_TYPE_DONE);
+
/* This won't change order, so it does not need a sort */
- Change (CHANGE_TYPE_DONE);
+ LengthChange ();
}
class FrameRateCandidate
/** Emitted when content has been added to or removed from the playlist; implies OrderChanged */
mutable boost::signals2::signal<void (ChangeType)> Change;
mutable boost::signals2::signal<void ()> OrderChanged;
+ /** Emitted when the length might have changed; may sometimes be emitted when it has not */
+ mutable boost::signals2::signal<void ()> LengthChange;
mutable boost::signals2::signal<void (ChangeType, boost::weak_ptr<Content>, int, bool)> ContentChange;
_film = film;
- _video_view->set_film (_film);
_video_view->clear ();
_closed_captions_dialog->clear ();
_player->set_play_referenced ();
_film->Change.connect (boost::bind (&FilmViewer::film_change, this, _1, _2));
+ _film->LengthChange.connect (boost::bind(&FilmViewer::film_length_change, this));
_player->Change.connect (boost::bind (&FilmViewer::player_change, this, _1, _2, _3));
/* Keep about 1 second's worth of history samples */
void
FilmViewer::film_change (ChangeType type, Film::Property p)
{
- if (type == CHANGE_TYPE_DONE && p == Film::AUDIO_CHANNELS) {
+ if (type != CHANGE_TYPE_DONE) {
+ return;
+ }
+
+ if (p == Film::AUDIO_CHANNELS) {
recreate_butler ();
+ } else if (p == Film::VIDEO_FRAME_RATE) {
+ _video_view->set_video_frame_rate (_film->video_frame_rate());
}
}
+void
+FilmViewer::film_length_change ()
+{
+ _video_view->set_length (_film->length());
+}
+
/** Re-get the current frame slowly by seeking */
void
FilmViewer::slow_refresh ()
void film_change (ChangeType, Film::Property);
void recreate_butler ();
void config_changed (Config::Property);
+ void film_length_change ();
dcpomatic::DCPTime time () const;
boost::optional<dcpomatic::DCPTime> audio_time () const;
: VideoView (viewer)
, _vsync_enabled (false)
, _thread (0)
- , _one_shot (false)
{
_canvas = new wxGLCanvas (parent, wxID_ANY, 0, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE);
_canvas->Bind (wxEVT_PAINT, boost::bind(&GLVideoView::paint, this));
_thread = 0;
}
-bool
-GLVideoView::one_shot () const
-{
- boost::mutex::scoped_lock lm (_one_shot_mutex);
- return _one_shot;
-}
-
-void
-GLVideoView::set_one_shot (bool s)
-{
- boost::mutex::scoped_lock lm (_one_shot_mutex);
- _one_shot = s;
-}
-
void
GLVideoView::thread ()
try
_canvas->SetCurrent (*_context);
}
- while (true) {
- if (!film() && !one_shot()) {
- /* XXX: this should be an indefinite wait until
- one of our conditions becomes true.
- */
- dcpomatic_sleep_milliseconds (40);
- continue;
- }
-
- set_one_shot (false);
+ std::cout << "Here we go " << video_frame_rate() << " " << to_string(length()) << "\n";
+ while (true) {
dcpomatic::DCPTime const next = position() + one_video_frame();
- if (next >= film()->length()) {
+ if (next >= length()) {
_viewer->stop ();
_viewer->emit_finished ();
continue;
bool
GLVideoView::display_next_frame (bool non_blocking)
{
- bool const g = get_next_frame (non_blocking);
- set_one_shot (true);
- return g;
+ return get_next_frame (non_blocking);
}
-dcpomatic::DCPTime
-GLVideoView::one_video_frame () const
-{
- return dcpomatic::DCPTime::from_frames (1, film()->video_frame_rate());
-}
-
-
void draw ();
void thread ();
wxGLContext* context () const;
- bool one_shot () const;
- void set_one_shot (bool s);
- dcpomatic::DCPTime one_video_frame () const;
wxGLCanvas* _canvas;
boost::optional<dcp::Size> _size;
bool _vsync_enabled;
boost::thread* _thread;
- mutable boost::mutex _one_shot_mutex;
- bool _one_shot;
};
void
SimpleVideoView::timer ()
{
- if (!film() || !_viewer->playing()) {
+ if (!_viewer->playing()) {
return;
}
display_next_frame (false);
DCPTime const next = _viewer->position() + _viewer->one_video_frame();
- if (next >= film()->length()) {
+ if (next >= length()) {
_viewer->stop ();
_viewer->Finished ();
return;
dcpomatic::DCPTime
VideoView::one_video_frame () const
{
- return dcpomatic::DCPTime::from_frames (1, film()->video_frame_rate());
+ return dcpomatic::DCPTime::from_frames (1, video_frame_rate());
}
/* XXX_b: comment */
#ifdef DCPOMATIC_VARIANT_SWAROOP
, _in_watermark (false)
#endif
+ , _video_frame_rate (0)
{}
virtual ~VideoView () {}
return _player_video.second;
}
- void set_film (boost::shared_ptr<const Film> film) {
+ void set_video_frame_rate (int r) {
boost::mutex::scoped_lock lm (_mutex);
- _film = film;
+ _video_frame_rate = r;
+ }
+
+ void set_length (dcpomatic::DCPTime len) {
+ boost::mutex::scoped_lock lm (_mutex);
+ _length = len;
}
protected:
bool get_next_frame (bool non_blocking);
int time_until_next_frame () const;
dcpomatic::DCPTime one_video_frame () const;
-
- boost::shared_ptr<const Film> film () const {
+ int video_frame_rate () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _video_frame_rate;
+ }
+ dcpomatic::DCPTime length () const {
boost::mutex::scoped_lock lm (_mutex);
- return _film;
+ return _length;
}
FilmViewer* _viewer;
#endif
private:
- boost::shared_ptr<const Film> _film;
+ int _video_frame_rate;
+ dcpomatic::DCPTime _length;
};
#endif