std::string calculate_digest () const;
- /* CHANGE_PENDING and CHANGE_CANCELLED may be emitted from any thread; CHANGE_DONE always from GUI thread */
+ /* CHANGE_TYPE_PENDING and CHANGE_TYPE_CANCELLED may be emitted from any thread; CHANGE_TYPE_DONE always from GUI thread */
boost::signals2::signal<void (ChangeType, boost::weak_ptr<Content>, int, bool)> Change;
boost::shared_ptr<VideoContent> video;
void
Playlist::content_change (weak_ptr<const Film> weak_film, ChangeType type, weak_ptr<Content> content, int property, bool frequent)
{
+ /* Make sure we only hear about atomic changes (e.g. a PENDING always with the DONE/CANCELLED)
+ Ignore any DONE/CANCELLED that arrives without a PENDING.
+ */
+ if (_checker.send (type, property)) {
+ return;
+ }
+
shared_ptr<const Film> film = weak_film.lock ();
DCPOMATIC_ASSERT (film);
/*
- Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2018 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
#include "util.h"
#include "frame_rate_change.h"
+#include "atomicity_checker.h"
#include <libcxml/cxml.h>
#include <boost/shared_ptr.hpp>
#include <boost/signals2.hpp>
bool _sequence;
bool _sequencing;
std::list<boost::signals2::connection> _content_connections;
+ AtomicityChecker _checker;
};
#endif
_missing = false;
cxml::Document doc ("SPL");
doc.read_file (path);
+ _id = doc.string_child("Id");
BOOST_FOREACH (cxml::ConstNodePtr i, doc.node_children("Entry")) {
shared_ptr<Content> c = store->get(i->string_child("Digest"));
if (c) {
{
xmlpp::Document doc;
xmlpp::Element* root = doc.create_root_node ("SPL");
+ root->add_child("Id")->add_child_text (_id);
BOOST_FOREACH (SPLEntry i, _spl) {
i.as_xml (root->add_child("Entry"));
}
#define DCPOMATIC_SPL_H
#include "spl_entry.h"
+#include <dcp/util.h>
class ContentStore;
{
public:
SPL ()
- : _missing (false)
+ : _id (dcp::make_uuid())
+ , _missing (false)
{}
void add (SPLEntry e) {
void read (boost::filesystem::path path, ContentStore* store);
void write (boost::filesystem::path path) const;
+ std::string id () const {
+ return _id;
+ }
+
std::string name () const {
return _name;
}
}
private:
+ std::string _id;
std::string _name;
std::vector<SPLEntry> _spl;
/** true if any content was missing when read() was last called on this SPL */
active_text.cc
analyse_audio_job.cc
atmos_mxf_content.cc
+ atomicity_checker.cc
audio_analysis.cc
audio_buffers.cc
audio_content.cc
_viewer->Started.connect (bind(&DOMFrame::playback_started, this, _1));
_viewer->Seeked.connect (bind(&DOMFrame::playback_seeked, this, _1));
_viewer->Stopped.connect (bind(&DOMFrame::playback_stopped, this, _1));
-#ifdef DCPOMATIC_VARIANT_SWAROOP
- _viewer->PositionChanged.connect (bind(&DOMFrame::position_changed, this));
-#endif
_info = new PlayerInformation (_overall_panel, _viewer);
setup_main_sizer (Config::instance()->player_mode());
#ifdef __WXOSX__
setup_screen ();
#ifdef DCPOMATIC_VARIANT_SWAROOP
- if (
- boost::filesystem::is_regular_file(Config::path("position")) &&
- boost::filesystem::is_regular_file(Config::path("spl.xml"))) {
-
- shared_ptr<Film> film (new Film(boost::optional<boost::filesystem::path>()));
- film->read_metadata (Config::path("spl.xml"));
- reset_film (film);
- FILE* f = fopen_boost (Config::path("position"), "r");
- if (f) {
- char buffer[64];
- fscanf (f, "%63s", buffer);
- _viewer->seek (DCPTime(atoi(buffer)), true);
- _viewer->start ();
- fclose (f);
- }
- }
-
+ sc->check_restart ();
#endif
}
- void position_changed ()
- {
- if (!_viewer->playing() || _viewer->position().get() % DCPTime::HZ) {
- return;
- }
-
- FILE* f = fopen_boost (Config::path("position"), "w");
- if (f) {
- string const p = dcp::raw_convert<string> (_viewer->position().get());
- fwrite (p.c_str(), p.length(), 1, f);
- fclose (f);
- }
- }
-
#ifdef DCPOMATIC_VARIANT_SWAROOP
void monitor_checker_state_changed ()
{
return;
}
- _film->write_metadata (Config::path("spl.xml"));
-
if (_viewer->playing ()) {
_viewer->stop ();
}
#include "static_text.h"
#include "lib/player_video.h"
#include "lib/dcp_content.h"
+#include "lib/cross.h"
+#include <dcp/raw_convert.h>
#include <wx/listctrl.h>
#include <wx/progdlg.h>
_spl_view->Bind (wxEVT_LIST_ITEM_SELECTED, boost::bind(&SwaroopControls::spl_selection_changed, this));
_spl_view->Bind (wxEVT_LIST_ITEM_DESELECTED, boost::bind(&SwaroopControls::spl_selection_changed, this));
_viewer->Finished.connect (boost::bind(&SwaroopControls::viewer_finished, this));
+ _viewer->PositionChanged.connect (boost::bind(&SwaroopControls::viewer_position_changed, this));
_refresh_spl_view->Bind (wxEVT_BUTTON, boost::bind(&SwaroopControls::update_playlist_directory, this));
_refresh_content_view->Bind (wxEVT_BUTTON, boost::bind(&ContentView::update, _content_view));
update_playlist_directory ();
}
+void
+SwaroopControls::check_restart ()
+{
+ FILE* f = fopen_boost (Config::path("position"), "r");
+ if (!f) {
+ return;
+ }
+
+ char id[64];
+ int index;
+ int64_t time;
+ fscanf (f, "%63s %d %ld", id, &index, &time);
+
+ for (size_t i = 0; i < _playlists.size(); ++i) {
+ if (_playlists[i].id() == id) {
+ _selected_playlist = i;
+ _selected_playlist_position = index;
+ update_current_content ();
+ _viewer->seek (DCPTime(time), false);
+ }
+ }
+
+ fclose (f);
+}
+
+void
+SwaroopControls::viewer_position_changed ()
+{
+ if (!_selected_playlist || !_viewer->playing() || _viewer->position().get() % DCPTime::HZ) {
+ return;
+ }
+
+ FILE* f = fopen_boost (Config::path("position"), "w");
+ if (f) {
+ string const p = _playlists[*_selected_playlist].id()
+ + " " + dcp::raw_convert<string>(_selected_playlist_position)
+ + " " + dcp::raw_convert<string>(_viewer->position().get());
+
+ fwrite (p.c_str(), p.length(), 1, f);
+ fclose (f);
+ }
+}
+
void
SwaroopControls::started ()
{
return;
}
-
_current_spl_view->DeleteAllItems ();
int N = 0;
void log (wxString s);
void set_film (boost::shared_ptr<Film> film);
+ void check_restart ();
/** This is so that we can tell our parent player to reset the film
when we have created one from a SPL. We could call a method
void setup_sensitivity ();
void config_changed (int);
void viewer_finished ();
+ void viewer_position_changed ();
void reset_film ();
void update_current_content ();
bool can_do_previous ();