_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));
+ _player_change_connection = _player->Change.connect (bind (&Butler::player_change, this, _1, _3));
_thread = new boost::thread (bind (&Butler::thread, this));
#ifdef DCPOMATIC_LINUX
pthread_setname_np (_thread->native_handle(), "butler");
bool
Butler::should_run () const
{
- if (_suspended) {
- return false;
- }
-
if (_video.size() >= MAXIMUM_VIDEO_READAHEAD * 10) {
/* This is way too big */
throw ProgrammingError
LOG_WARNING ("Butler audio buffers reached %1 frames (video is %2)", _audio.size(), _video.size());
}
- if (_stop_thread || _finished || _died) {
+ if (_stop_thread || _finished || _died || _suspended) {
/* Definitely do not run */
return false;
}
boost::mutex::scoped_lock lm (_mutex);
/* Wait for data if we have none */
- while (_video.empty() && !_finished && !_died) {
+ while (_video.empty() && !_finished && !_died && !_suspended) {
_arrived.wait (lm);
}
}
void
-Butler::return_seek (bool frequent)
+Butler::player_change (ChangeType type, bool frequent)
{
boost::mutex::scoped_lock lm (_mutex);
- if (_died || _pending_seek_position || frequent) {
- return;
- }
- DCPTime seek_to;
- DCPTime next = _video.get().second;
- if (_awaiting && _awaiting > next) {
- /* We have recently done a player_changed seek and our buffers haven't been refilled yet,
- so assume that we're seeking to the same place as last time.
- */
- seek_to = *_awaiting;
- } else {
- seek_to = next;
- }
+ if (type == CHANGE_TYPE_PENDING) {
+ _suspended = true;
+ } else if (type == CHANGE_TYPE_DONE) {
+
+ if (_died || _pending_seek_position || frequent) {
+ return;
+ }
+
+ DCPTime seek_to;
+ DCPTime next = _video.get().second;
+ if (_awaiting && _awaiting > next) {
+ /* We have recently done a player_changed seek and our buffers haven't been refilled yet,
+ so assume that we're seeking to the same place as last time.
+ */
+ seek_to = *_awaiting;
+ } else {
+ seek_to = next;
+ }
- seek_unlocked (seek_to, true);
- _suspended = false;
- _awaiting = seek_to;
+ seek_unlocked (seek_to, true);
+ _suspended = false;
+ _awaiting = seek_to;
+ }
}
void
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 player_change (ChangeType type, bool frequent);
void seek_unlocked (DCPTime position, bool accurate);
boost::shared_ptr<Player> _player;
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;
+ boost::signals2::scoped_connection _player_change_connection;
};
}
void
-Content::signal_changed (int p)
+Content::signal_change (ChangeType c, int p)
{
try {
- emit (boost::bind (boost::ref(Changed), shared_from_this(), p, _change_signals_frequent));
+ if (c == CHANGE_TYPE_PENDING || c == CHANGE_TYPE_CANCELLED) {
+ Change (c, shared_from_this(), p, _change_signals_frequent);
+ } else {
+ emit (boost::bind (boost::ref(Change), c, shared_from_this(), p, _change_signals_frequent));
+ }
} catch (boost::bad_weak_ptr) {
/* This must be during construction; never mind */
}
std::list<UserProperty> user_properties () const;
- /* May be emitted from any thread */
- boost::signals2::signal<void ()> MayChange;
-
- /* Emitted from the GUI thread */
- boost::signals2::signal<void (boost::weak_ptr<Content>, int, bool)> Changed;
-
- /* May be emitted from any thread */
- boost::signals2::signal<void ()> NotChanged;
+ /* CHANGE_PENDING and CHANGE_CANCELLED may be emitted from any thread; CHANGE_DONE always from GUI thread */
+ boost::signals2::signal<void (ChangeType, boost::weak_ptr<Content>, int, bool)> Change;
boost::shared_ptr<VideoContent> video;
boost::shared_ptr<AudioContent> audio;
friend struct audio_sampling_rate_test;
friend class ContentChange;
- void signal_changed (int);
+ void signal_change (ChangeType, int);
std::string _digest;
DCPTime _position;
, _property (p)
, _done (true)
{
- _content->MayChange ();
+ _content->signal_change (CHANGE_TYPE_PENDING, _property);
}
ContentChange::~ContentChange ()
{
if (_done) {
- _content->signal_changed (_property);
+ _content->signal_change (CHANGE_TYPE_DONE, _property);
} else {
- _content->NotChanged ();
+ _content->signal_change (CHANGE_TYPE_CANCELLED, _property);
}
}
{
set_isdcf_date_today ();
- _playlist_changed_connection = _playlist->Changed.connect (bind (&Film::playlist_changed, this));
+ _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_changed_connection = _playlist->ContentChanged.connect (bind (&Film::playlist_content_changed, this, _1, _2, _3));
+ _playlist_content_change_connection = _playlist->ContentChange.connect (bind (&Film::playlist_content_change, this, _1, _2, _3, _4));
if (dir) {
/* Make state.directory a complete path without ..s (where possible)
}
void
-Film::playlist_content_changed (weak_ptr<Content> c, int p, bool frequent)
+Film::playlist_content_change (ChangeType type, weak_ptr<Content> c, int p, bool frequent)
{
+ if (type != CHANGE_TYPE_DONE) {
+ return;
+ }
+
_dirty = true;
if (p == ContentProperty::VIDEO_FRAME_RATE) {
signal_changed (NAME);
}
- emit (boost::bind (boost::ref (ContentChanged), c, p, frequent));
+ emit (boost::bind (boost::ref (ContentChange), type, c, p, frequent));
}
void
-Film::playlist_changed ()
+Film::playlist_change (ChangeType type)
{
- signal_changed (CONTENT);
- signal_changed (NAME);
+ if (type == CHANGE_TYPE_DONE) {
+ signal_changed (CONTENT);
+ signal_changed (NAME);
+ }
}
void
mutable boost::signals2::signal<void (Property)> Changed;
/** Emitted when some property of our content has changed */
- mutable boost::signals2::signal<void (boost::weak_ptr<Content>, int, bool)> ContentChanged;
+ mutable boost::signals2::signal<void (ChangeType, boost::weak_ptr<Content>, int, bool)> ContentChange;
/** Current version number of the state file */
static int const current_state_version;
void signal_changed (Property);
std::string video_identifier () const;
- void playlist_changed ();
+ void playlist_change (ChangeType);
void playlist_order_changed ();
- void playlist_content_changed (boost::weak_ptr<Content>, int, bool frequent);
+ void playlist_content_change (ChangeType type, boost::weak_ptr<Content>, int, bool frequent);
void maybe_add_content (boost::weak_ptr<Job>, boost::weak_ptr<Content>, bool disable_audio_analysis);
void audio_analysis_finished ();
/** film being used as a template, or 0 */
boost::shared_ptr<Film> _template_film;
- boost::signals2::scoped_connection _playlist_changed_connection;
+ boost::signals2::scoped_connection _playlist_change_connection;
boost::signals2::scoped_connection _playlist_order_changed_connection;
- boost::signals2::scoped_connection _playlist_content_changed_connection;
+ boost::signals2::scoped_connection _playlist_content_change_connection;
std::list<boost::signals2::connection> _job_connections;
std::list<boost::signals2::connection> _audio_analysis_connections;
, _shuffler (0)
{
_film_changed_connection = _film->Changed.connect (bind (&Player::film_changed, this, _1));
- _playlist_changed_connection = _playlist->Changed.connect (bind (&Player::playlist_changed, this));
- _playlist_content_may_change_connection = _playlist->ContentMayChange.connect (bind(&Player::playlist_content_may_change, this));
- _playlist_content_changed_connection = _playlist->ContentChanged.connect (bind(&Player::playlist_content_changed, this, _1, _2, _3));
- _playlist_content_not_changed_connection = _playlist->ContentNotChanged.connect (bind(&Player::playlist_content_not_changed, this));
+ _playlist_change_connection = _playlist->Change.connect (bind (&Player::playlist_change, this, _1));
+ _playlist_content_change_connection = _playlist->ContentChange.connect (bind(&Player::playlist_content_change, this, _1, _3, _4));
set_video_container_size (_film->frame_size ());
film_changed (Film::AUDIO_PROCESSOR);
}
void
-Player::playlist_content_may_change ()
+Player::playlist_content_change (ChangeType type, int property, bool frequent)
{
- {
+ if (type == CHANGE_TYPE_PENDING) {
boost::mutex::scoped_lock lm (_mutex);
/* The player content is probably about to change, so we can't carry on
until that has happened and we've rebuilt our pieces. Stop pass()
and seek() from working until then.
*/
_suspended = true;
+ } else if (type == CHANGE_TYPE_DONE) {
+ /* A change in our content has gone through. Re-build our pieces. */
+ setup_pieces ();
}
- MayChange ();
-}
-
-void
-Player::playlist_content_changed (weak_ptr<Content> w, int property, bool frequent)
-{
- /* A change in our content has gone through. Re-build our pieces and signal
- it to anybody that is interested.
- */
-
- shared_ptr<Content> c = w.lock ();
- if (!c) {
- return;
- }
-
- setup_pieces ();
-
- if (
- property == ContentProperty::POSITION ||
- property == ContentProperty::LENGTH ||
- property == ContentProperty::TRIM_START ||
- property == ContentProperty::TRIM_END ||
- property == ContentProperty::PATH ||
- property == VideoContentProperty::FRAME_TYPE ||
- property == VideoContentProperty::COLOUR_CONVERSION ||
- property == AudioContentProperty::STREAMS ||
- property == DCPContentProperty::NEEDS_ASSETS ||
- property == DCPContentProperty::NEEDS_KDM ||
- property == DCPContentProperty::CPL ||
- property == TextContentProperty::COLOUR ||
- property == TextContentProperty::EFFECT ||
- property == TextContentProperty::EFFECT_COLOUR ||
- property == FFmpegContentProperty::SUBTITLE_STREAM ||
- property == FFmpegContentProperty::FILTERS ||
- property == TextContentProperty::LINE_SPACING ||
- property == TextContentProperty::OUTLINE_WIDTH ||
- property == TextContentProperty::Y_SCALE ||
- property == TextContentProperty::FADE_IN ||
- property == TextContentProperty::FADE_OUT ||
- property == ContentProperty::VIDEO_FRAME_RATE ||
- property == TextContentProperty::USE ||
- property == TextContentProperty::X_OFFSET ||
- property == TextContentProperty::Y_OFFSET ||
- property == TextContentProperty::X_SCALE ||
- property == TextContentProperty::FONTS ||
- property == TextContentProperty::TYPE ||
- property == VideoContentProperty::CROP ||
- property == VideoContentProperty::SCALE ||
- property == VideoContentProperty::FADE_IN ||
- property == VideoContentProperty::FADE_OUT
- ) {
-
- Changed (property, frequent);
- }
-}
-
-void
-Player::playlist_content_not_changed ()
-{
- /* A possible content change did end up happening for some reason */
- NotChanged ();
+ Change (type, property, frequent);
}
void
_black_image->make_black ();
}
- Changed (PlayerProperty::VIDEO_CONTAINER_SIZE, false);
+ Change (CHANGE_TYPE_DONE, PlayerProperty::VIDEO_CONTAINER_SIZE, false);
}
void
-Player::playlist_changed ()
+Player::playlist_change (ChangeType type)
{
- setup_pieces ();
- Changed (PlayerProperty::PLAYLIST, false);
+ if (type == CHANGE_TYPE_DONE) {
+ setup_pieces ();
+ }
+ Change (type, PlayerProperty::PLAYLIST, false);
}
void
*/
if (p == Film::CONTAINER) {
- Changed (PlayerProperty::FILM_CONTAINER, false);
+ Change (CHANGE_TYPE_PENDING, PlayerProperty::FILM_CONTAINER, false);
} else if (p == Film::VIDEO_FRAME_RATE) {
/* Pieces contain a FrameRateChange which contains the DCP frame rate,
so we need new pieces here.
*/
+ /* XXX: missing PENDING! */
setup_pieces ();
- Changed (PlayerProperty::FILM_VIDEO_FRAME_RATE, false);
+ Change (CHANGE_TYPE_DONE, PlayerProperty::FILM_VIDEO_FRAME_RATE, false);
} else if (p == Film::AUDIO_PROCESSOR) {
if (_film->audio_processor ()) {
boost::mutex::scoped_lock lm (_mutex);
void
Player::set_dcp_decode_reduction (optional<int> reduction)
{
+ Change (CHANGE_TYPE_PENDING, PlayerProperty::DCP_DECODE_REDUCTION, false);
+
{
boost::mutex::scoped_lock lm (_mutex);
if (reduction == _dcp_decode_reduction) {
+ lm.unlock ();
+ Change (CHANGE_TYPE_CANCELLED, PlayerProperty::DCP_DECODE_REDUCTION, false);
return;
}
setup_pieces_unlocked ();
}
- Changed (PlayerProperty::DCP_DECODE_REDUCTION, false);
+ Change (CHANGE_TYPE_DONE, PlayerProperty::DCP_DECODE_REDUCTION, false);
}
optional<DCPTime>
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;
-
- /** 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;
+ boost::signals2::signal<void (ChangeType, int, bool)> Change;
/** The change suggested by a MayChange did not happen */
boost::signals2::signal<void ()> NotChanged;
void setup_pieces_unlocked ();
void flush ();
void film_changed (Film::Property);
- void playlist_changed ();
- void playlist_content_may_change ();
- void playlist_content_changed (boost::weak_ptr<Content>, int, bool);
- void playlist_content_not_changed ();
+ void playlist_change (ChangeType);
+ void playlist_content_change (ChangeType, int, bool);
std::list<PositionImage> transform_bitmap_texts (std::list<BitmapText>) const;
Frame dcp_to_content_video (boost::shared_ptr<const Piece> piece, DCPTime t) const;
DCPTime content_video_to_dcp (boost::shared_ptr<const Piece> piece, Frame f) const;
boost::shared_ptr<AudioProcessor> _audio_processor;
boost::signals2::scoped_connection _film_changed_connection;
- boost::signals2::scoped_connection _playlist_changed_connection;
- boost::signals2::scoped_connection _playlist_content_may_change_connection;
- boost::signals2::scoped_connection _playlist_content_changed_connection;
- boost::signals2::scoped_connection _playlist_content_not_changed_connection;
+ boost::signals2::scoped_connection _playlist_change_connection;
+ boost::signals2::scoped_connection _playlist_content_change_connection;
};
#endif
}
void
-Playlist::content_may_change ()
+Playlist::content_change (ChangeType type, weak_ptr<Content> content, int property, bool frequent)
{
- ContentMayChange ();
-}
+ if (type == CHANGE_TYPE_DONE) {
+ if (
+ property == ContentProperty::TRIM_START ||
+ property == ContentProperty::TRIM_END ||
+ property == ContentProperty::LENGTH ||
+ property == VideoContentProperty::FRAME_TYPE
+ ) {
+ /* Don't respond to position changes here, as:
+ - sequencing after earlier/later changes is handled by move_earlier/move_later
+ - any other position changes will be timeline drags which should not result in content
+ being sequenced.
+ */
+ maybe_sequence ();
+ }
-void
-Playlist::content_not_changed ()
-{
- ContentNotChanged ();
-}
+ if (
+ property == ContentProperty::POSITION ||
+ property == ContentProperty::LENGTH ||
+ property == ContentProperty::TRIM_START ||
+ property == ContentProperty::TRIM_END) {
-void
-Playlist::content_changed (weak_ptr<Content> content, int property, bool frequent)
-{
- if (
- property == ContentProperty::TRIM_START ||
- property == ContentProperty::TRIM_END ||
- property == ContentProperty::LENGTH ||
- property == VideoContentProperty::FRAME_TYPE
- ) {
- /* Don't respond to position changes here, as:
- - sequencing after earlier/later changes is handled by move_earlier/move_later
- - any other position changes will be timeline drags which should not result in content
- being sequenced.
- */
- maybe_sequence ();
- }
-
- if (
- property == ContentProperty::POSITION ||
- property == ContentProperty::LENGTH ||
- property == ContentProperty::TRIM_START ||
- property == ContentProperty::TRIM_END) {
-
- ContentList old = _content;
- sort (_content.begin(), _content.end(), ContentSorter ());
- if (_content != old) {
- OrderChanged ();
+ ContentList old = _content;
+ sort (_content.begin(), _content.end(), ContentSorter ());
+ if (_content != old) {
+ OrderChanged ();
+ }
}
}
- ContentChanged (content, property, frequent);
+ ContentChange (type, content, property, frequent);
}
void
void
Playlist::add (shared_ptr<Content> c)
{
+ Change (CHANGE_TYPE_PENDING);
_content.push_back (c);
sort (_content.begin(), _content.end(), ContentSorter ());
reconnect ();
- Changed ();
+ Change (CHANGE_TYPE_DONE);
}
void
Playlist::remove (shared_ptr<Content> c)
{
+ Change (CHANGE_TYPE_PENDING);
+
ContentList::iterator i = _content.begin ();
while (i != _content.end() && *i != c) {
++i;
if (i != _content.end ()) {
_content.erase (i);
- Changed ();
+ Change (CHANGE_TYPE_DONE);
+ } else {
+ Change (CHANGE_TYPE_CANCELLED);
}
/* This won't change order, so it does not need a sort */
void
Playlist::remove (ContentList c)
{
+ Change (CHANGE_TYPE_PENDING);
+
BOOST_FOREACH (shared_ptr<Content> i, c) {
ContentList::iterator j = _content.begin ();
while (j != _content.end() && *j != i) {
/* This won't change order, so it does not need a sort */
- Changed ();
+ Change (CHANGE_TYPE_DONE);
}
class FrameRateCandidate
_content_connections.clear ();
BOOST_FOREACH (shared_ptr<Content> i, _content) {
- _content_connections.push_back (i->MayChange.connect(boost::bind(&Playlist::content_may_change, this)));
- _content_connections.push_back (i->Changed.connect(boost::bind(&Playlist::content_changed, this, _1, _2, _3)));
- _content_connections.push_back (i->NotChanged.connect(boost::bind(&Playlist::content_not_changed, this)));
+ _content_connections.push_back (i->Change.connect(boost::bind(&Playlist::content_change, this, _1, _2, _3, _4)));
}
}
range.second = max (range.second, i->end ());
}
+ Change (CHANGE_TYPE_PENDING);
+
DCPTime pos = range.second;
for (int i = 0; i < n; ++i) {
BOOST_FOREACH (shared_ptr<Content> j, c) {
sort (_content.begin(), _content.end(), ContentSorter ());
reconnect ();
- Changed ();
+ Change (CHANGE_TYPE_DONE);
}
void
void repeat (ContentList, int);
/** Emitted when content has been added to or removed from the playlist; implies OrderChanged */
- mutable boost::signals2::signal<void ()> Changed;
+ mutable boost::signals2::signal<void (ChangeType)> Change;
mutable boost::signals2::signal<void ()> OrderChanged;
- mutable boost::signals2::signal<void ()> ContentMayChange;
- /** Emitted when something about a piece of our content has changed;
- * these emissions include when the position of the content changes.
- * Third parameter is true if signals are currently being emitted frequently.
- */
- mutable boost::signals2::signal<void (boost::weak_ptr<Content>, int, bool)> ContentChanged;
- mutable boost::signals2::signal<void ()> ContentNotChanged;
+ mutable boost::signals2::signal<void (ChangeType, boost::weak_ptr<Content>, int, bool)> ContentChange;
private:
- void content_may_change ();
- void content_changed (boost::weak_ptr<Content>, int, bool);
- void content_not_changed ();
+ void content_change (ChangeType, boost::weak_ptr<Content>, int, bool);
void reconnect ();
/** List of content. Kept sorted in position order. */
REELTYPE_BY_LENGTH
};
+enum ChangeType
+{
+ CHANGE_TYPE_PENDING,
+ CHANGE_TYPE_DONE,
+ CHANGE_TYPE_CANCELLED
+};
+
/** Type of captions.
*
* The generally accepted definitions seem to be:
overall_sizer->Layout ();
overall_sizer->SetSizeHints (this);
- _film_connection = film->ContentChanged.connect (boost::bind (&AudioDialog::content_changed, this, _2));
+ _film_connection = film->ContentChange.connect (boost::bind (&AudioDialog::content_change, this, _1, _3));
DCPOMATIC_ASSERT (film->directory());
SetTitle(wxString::Format(_("DCP-o-matic audio - %s"), std_to_wx(film->directory().get().string())));
}
void
-AudioDialog::content_changed (int p)
+AudioDialog::content_change (ChangeType type, int p)
{
+ if (type != CHANGE_TYPE_DONE) {
+ return;
+ }
+
if (p == AudioContentProperty::STREAMS) {
try_to_load_analysis ();
} else if (p == AudioContentProperty::GAIN) {
void set_cursor (boost::optional<DCPTime> time, boost::optional<float> db);
private:
- void content_changed (int);
+ void content_change (ChangeType, int);
void channel_clicked (wxCommandEvent &);
void type_clicked (wxCommandEvent &);
void smoothing_changed ();
update_from_model ();
for (typename List::iterator i = _content.begin(); i != _content.end(); ++i) {
- _connections.push_back ((*i)->Changed.connect (boost::bind (&ContentWidget::model_changed, this, _2)));
+ _connections.push_back ((*i)->Change.connect (boost::bind (&ContentWidget::model_changed, this, _1, _3)));
}
}
}
}
- void model_changed (int property)
+ void model_changed (ChangeType type, int property)
{
- if (property == _property && !_ignore_model_changes) {
+ if (type == CHANGE_TYPE_DONE && property == _property && !_ignore_model_changes) {
update_from_model ();
}
}
}
void
-FilmEditor::film_content_changed (int property)
+FilmEditor::film_content_change (ChangeType type, int property)
{
+ if (type != CHANGE_TYPE_DONE) {
+ return;
+ }
+
ensure_ui_thread ();
if (!_film) {
if (_film) {
_film->Changed.connect (bind (&FilmEditor::film_changed, this, _1));
- _film->ContentChanged.connect (bind (&FilmEditor::film_content_changed, this, _2));
+ _film->ContentChange.connect (bind (&FilmEditor::film_content_change, this, _1, _3));
}
if (_film && _film->directory()) {
/* Handle changes to the model */
void film_changed (Film::Property);
- void film_content_changed (int);
+ void film_content_change (ChangeType type, int);
void set_general_sensitivity (bool);
void active_jobs_changed (boost::optional<std::string>);
_player->set_play_referenced ();
_film->Changed.connect (boost::bind (&FilmViewer::film_changed, this, _1));
- _player->Changed.connect (boost::bind (&FilmViewer::player_changed, this, _1, _2));
+ _player->Change.connect (boost::bind (&FilmViewer::player_change, this, _1, _2, _3));
/* Keep about 1 second's worth of history samples */
_latency_history_count = _film->audio_frame_rate() / _audio_block_size;
}
void
-FilmViewer::player_changed (int property, bool frequent)
+FilmViewer::player_change (ChangeType type, int property, bool frequent)
{
- if (frequent) {
+ if (type != CHANGE_TYPE_DONE || frequent) {
return;
}
if (!c) {
BOOST_FOREACH (int i, _pending_player_changes) {
- player_changed (i, false);
+ player_change (CHANGE_TYPE_DONE, i, false);
}
_pending_player_changes.clear ();
}
void rewind_clicked (wxMouseEvent &);
void back_clicked (wxKeyboardState& s);
void forward_clicked (wxKeyboardState &);
- void player_changed (int, bool);
+ void player_change (ChangeType type, int, bool);
void update_position_label ();
void update_position_slider ();
void get ();
boost::shared_ptr<Film> locked_film = _film.lock ();
if (locked_film) {
_film_changed_connection = locked_film->Changed.connect (boost::bind (&HintsDialog::film_changed, this));
- _film_content_changed_connection = locked_film->ContentChanged.connect (boost::bind (&HintsDialog::film_changed, this));
+ _film_content_changed_connection = locked_film->ContentChange.connect (boost::bind (&HintsDialog::film_content_change, this, _1));
}
_hints->Hint.connect (bind (&HintsDialog::hint, this, _1));
_hints->start ();
}
+void
+HintsDialog::film_content_change (ChangeType type)
+{
+ if (type == CHANGE_TYPE_DONE) {
+ film_changed ();
+ }
+}
+
void
HintsDialog::update ()
{
*/
+#include "lib/types.h"
#include <wx/wx.h>
#include <boost/weak_ptr.hpp>
#include <boost/signals2.hpp>
private:
void film_changed ();
+ void film_content_change (ChangeType type);
void shut_up (wxCommandEvent& ev);
void update ();
void hint (std::string text);
_force_fade_in->Bind (wxEVT_CHECKBOX, bind (&SubtitleAppearanceDialog::setup_sensitivity, this));
_force_fade_out->Bind (wxEVT_CHECKBOX, bind (&SubtitleAppearanceDialog::setup_sensitivity, this));
_effect->Bind (wxEVT_CHOICE, bind (&SubtitleAppearanceDialog::setup_sensitivity, this));
- _content_connection = _content->Changed.connect (bind (&SubtitleAppearanceDialog::setup_sensitivity, this));
+ _content_connection = _content->Change.connect (bind (&SubtitleAppearanceDialog::content_change, this, _1));
setup_sensitivity ();
}
+void
+SubtitleAppearanceDialog::content_change (ChangeType type)
+{
+ if (type == CHANGE_TYPE_DONE) {
+ setup_sensitivity ();
+ }
+}
+
wxCheckBox*
SubtitleAppearanceDialog::set_to (wxWindow* w, int& r)
{
void setup_sensitivity ();
void restore ();
wxCheckBox* set_to (wxWindow* w, int& r);
+ void content_change (ChangeType type);
wxCheckBox* _force_colour;
wxColourPickerCtrl* _colour;
SetMinSize (wxSize (640, 4 * pixels_per_track() + 96));
_film_changed_connection = film->Changed.connect (bind (&Timeline::film_changed, this, _1));
- _film_content_changed_connection = film->ContentChanged.connect (bind (&Timeline::film_content_changed, this, _2, _3));
+ _film_content_change_connection = film->ContentChange.connect (bind (&Timeline::film_content_change, this, _1, _3, _4));
setup_scrollbars ();
_labels_canvas->ShowScrollbars (wxSHOW_SB_NEVER, wxSHOW_SB_NEVER);
}
void
-Timeline::film_content_changed (int property, bool frequent)
+Timeline::film_content_change (ChangeType type, int property, bool frequent)
{
+ if (type != CHANGE_TYPE_DONE) {
+ return;
+ }
+
ensure_ui_thread ();
if (property == AudioContentProperty::STREAMS) {
/*
- Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2018 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
void mouse_moved_select (wxMouseEvent &);
void mouse_moved_zoom (wxMouseEvent &);
void film_changed (Film::Property);
- void film_content_changed (int, bool frequent);
+ void film_content_change (ChangeType type, int, bool frequent);
void resized ();
void assign_tracks ();
void set_position_from_event (wxMouseEvent &);
static int const _minimum_pixels_per_track;
boost::signals2::scoped_connection _film_changed_connection;
- boost::signals2::scoped_connection _film_content_changed_connection;
+ boost::signals2::scoped_connection _film_content_change_connection;
};
, _content (c)
, _selected (false)
{
- _content_connection = c->Changed.connect (bind (&TimelineContentView::content_changed, this, _2));
+ _content_connection = c->Change.connect (bind (&TimelineContentView::content_change, this, _1, _3));
}
dcpomatic::Rect<int>
}
void
-TimelineContentView::content_changed (int p)
+TimelineContentView::content_change (ChangeType type, int p)
{
+ if (type != CHANGE_TYPE_DONE) {
+ return;
+ }
+
ensure_ui_thread ();
if (p == ContentProperty::POSITION || p == ContentProperty::LENGTH) {
#ifndef DCPOMATIC_TIMELINE_CONTENT_VIEW_H
#define DCPOMATIC_TIMELINE_CONTENT_VIEW_H
+#include "lib/types.h"
#include "timeline_view.h"
#include <wx/wx.h>
#include <boost/signals2.hpp>
void do_paint (wxGraphicsContext* gc, std::list<dcpomatic::Rect<int> > overlaps);
int y_pos (int t) const;
- void content_changed (int p);
+ void content_change (ChangeType type, int p);
boost::optional<int> _track;
bool _selected;