+2014-03-07 Carl Hetherington <cth@carlh.net>
+
+ * Add subtitle view.
+
+ 2014-06-26 Carl Hetherington <cth@carlh.net>
+
+ * Version 1.70.1 released.
+
+ 2014-06-26 Carl Hetherington <cth@carlh.net>
+
+ * Support different KDM formulations.
+
+ * Allow override of detected video frame rates.
+
+ * Optimisation of uncertain effect to encoder and server
+ thread handling.
+
+ * Version 1.70.0 released.
+
+ 2014-06-25 Carl Hetherington <cth@carlh.net>
+
+ * Version 1.69.37 released.
+
+ 2014-06-25 Carl Hetherington <cth@carlh.net>
+
+ * Version 1.69.36 released.
+
+ 2014-06-25 Carl Hetherington <cth@carlh.net>
+
+ * Support pixel format 46 in make_black().
+
+ 2014-06-24 Carl Hetherington <cth@carlh.net>
+
+ * Re-assign timeline tracks when things are
+ moved about.
+
2014-06-23 Carl Hetherington <cth@carlh.net>
+ * Try harder to cope with DCP names specified
+ already in CamelCase.
+
* Add option to CC a KDM email, and add
$SCREENS and $CINEMA_NAME as variables
in the email.
LOG_TIMING ("adding to queue of %1", _queue.size ());
_queue.push_back (shared_ptr<DCPVideoFrame> (
new DCPVideoFrame (
- pvf, _video_frames_out, _film->video_frame_rate(),
- _film->j2k_bandwidth(), _film->resolution(), _film->log()
+ pvf,
+ _video_frames_out,
+ _film->video_frame_rate(),
+ _film->j2k_bandwidth(),
+ _film->resolution(),
+ _film->log()
)
));
-
- _condition.notify_all ();
+
+ /* The queue might not be empty any more, so notify anything which is
+ waiting on that.
+ */
+ _empty_condition.notify_all ();
- _have_a_real_frame[pvf->eyes()] = true;
}
if (pvf->eyes() != EYES_LEFT) {
using boost::ends_with;
using boost::starts_with;
using boost::optional;
-using libdcp::Size;
-using libdcp::Signer;
-using libdcp::raw_convert;
+ using boost::is_any_of;
+using dcp::Size;
+using dcp::Signer;
+using dcp::raw_convert;
++using dcp::raw_convert;
#define LOG_GENERAL(...) log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL);
#define LOG_GENERAL_NC(...) log()->log (__VA_ARGS__, Log::TYPE_GENERAL);
return file (p);
}
--/** Find all the DCPs in our directory that can be libdcp::DCP::read() and return details of their CPLs */
++/** Find all the DCPs in our directory that can be dcp::DCP::read() and return details of their CPLs */
vector<CPLSummary>
Film::cpls () const
{
return fit_ratio_within (container()->ratio(), full_frame ());
}
-/** @param from KDM from time in local time.
- * @param to KDM to time in local time.
- */
-libdcp::KDM
+dcp::EncryptedKDM
Film::make_kdm (
- shared_ptr<libdcp::Certificate> target,
+ shared_ptr<dcp::Certificate> target,
boost::filesystem::path cpl_file,
- boost::posix_time::ptime from,
- boost::posix_time::ptime until,
- libdcp::KDM::Formulation formulation
+ dcp::LocalTime from,
- dcp::LocalTime until
++ dcp::LocalTime until,
++ dcp::Formulation formulation
) const
{
- shared_ptr<const Signer> signer = make_signer ();
-
- time_t now = time (0);
- struct tm* tm = localtime (&now);
- string const issue_date = libdcp::tm_to_string (tm);
-
- return libdcp::KDM (cpl_file, signer, target, key (), from, until, "DCP-o-matic", issue_date, formulation);
+ shared_ptr<const dcp::CPL> cpl (new dcp::CPL (cpl_file));
+ return dcp::DecryptedKDM (
+ cpl, from, until, "DCP-o-matic", cpl->content_title_text(), dcp::LocalTime().as_string()
- ).encrypt (make_signer(), target);
++ ).encrypt (make_signer(), target, formulation);
}
-list<libdcp::KDM>
+list<dcp::EncryptedKDM>
Film::make_kdms (
list<shared_ptr<Screen> > screens,
boost::filesystem::path dcp,
- boost::posix_time::ptime from,
- boost::posix_time::ptime until,
- libdcp::KDM::Formulation formulation
+ dcp::LocalTime from,
- dcp::LocalTime until
++ dcp::LocalTime until,
++ dcp::Formulation formulation
) const
{
- list<libdcp::KDM> kdms;
+ list<dcp::EncryptedKDM> kdms;
for (list<shared_ptr<Screen> >::iterator i = screens.begin(); i != screens.end(); ++i) {
- kdms.push_back (make_kdm ((*i)->certificate, dcp, from, until));
+ kdms.push_back (make_kdm ((*i)->certificate, dcp, from, until, formulation));
}
return kdms;
/* Proxies for some Playlist methods */
ContentList content () const;
- Time length () const;
- bool has_subtitles () const;
- OutputVideoFrame best_video_frame_rate () const;
- FrameRateChange active_frame_rate_change (Time) const;
+ DCPTime length () const;
+ int best_video_frame_rate () const;
+ FrameRateChange active_frame_rate_change (DCPTime) const;
- libdcp::KDM
+ dcp::EncryptedKDM
make_kdm (
- boost::shared_ptr<libdcp::Certificate> target,
+ boost::shared_ptr<dcp::Certificate> target,
boost::filesystem::path cpl_file,
- boost::posix_time::ptime from,
- boost::posix_time::ptime until,
- libdcp::KDM::Formulation formulation
+ dcp::LocalTime from,
- dcp::LocalTime until
++ dcp::LocalTime until,
++ dcp::Formulation formulation
) const;
- std::list<libdcp::KDM> make_kdms (
+ std::list<dcp::EncryptedKDM> make_kdms (
std::list<boost::shared_ptr<Screen> >,
boost::filesystem::path cpl_file,
- boost::posix_time::ptime from,
- boost::posix_time::ptime until,
- libdcp::KDM::Formulation formulation
+ dcp::LocalTime from,
- dcp::LocalTime until
++ dcp::LocalTime until,
++ dcp::Formulation formulation
) const;
- libdcp::Key key () const {
+ dcp::Key key () const {
return _key;
}
#include <boost/shared_ptr.hpp>
#include <quickmail.h>
#include <zip.h>
-#include <libdcp/kdm.h>
+#include <dcp/encrypted_kdm.h>
++#include <dcp/types.h>
#include "kdm.h"
#include "cinema.h"
#include "exceptions.h"
shared_ptr<const Film> film,
list<shared_ptr<Screen> > screens,
boost::filesystem::path cpl,
- boost::posix_time::ptime from,
- boost::posix_time::ptime to,
- libdcp::KDM::Formulation formulation
+ dcp::LocalTime from,
- dcp::LocalTime to
++ dcp::LocalTime to,
++ dcp::Formulation formulation
)
{
- list<dcp::EncryptedKDM> kdms = film->make_kdms (screens, cpl, from, to);
- list<libdcp::KDM> kdms = film->make_kdms (screens, cpl, from, to, formulation);
++ list<dcp::EncryptedKDM> kdms = film->make_kdms (screens, cpl, from, to, formulation);
list<ScreenKDM> screen_kdms;
shared_ptr<const Film> film,
list<shared_ptr<Screen> > screens,
boost::filesystem::path cpl,
- boost::posix_time::ptime from,
- boost::posix_time::ptime to,
- libdcp::KDM::Formulation formulation
+ dcp::LocalTime from,
- dcp::LocalTime to
++ dcp::LocalTime to,
++ dcp::Formulation formulation
)
{
- list<ScreenKDM> screen_kdms = make_screen_kdms (film, screens, cpl, from, to);
+ list<ScreenKDM> screen_kdms = make_screen_kdms (film, screens, cpl, from, to, formulation);
list<CinemaKDMs> cinema_kdms;
while (!screen_kdms.empty ()) {
shared_ptr<const Film> film,
list<shared_ptr<Screen> > screens,
boost::filesystem::path cpl,
- boost::posix_time::ptime from,
- boost::posix_time::ptime to,
- libdcp::KDM::Formulation formulation,
+ dcp::LocalTime from,
+ dcp::LocalTime to,
++ dcp::Formulation formulation,
boost::filesystem::path directory
)
{
shared_ptr<const Film> film,
list<shared_ptr<Screen> > screens,
boost::filesystem::path cpl,
- boost::posix_time::ptime from,
- boost::posix_time::ptime to,
- libdcp::KDM::Formulation formulation,
+ dcp::LocalTime from,
+ dcp::LocalTime to,
++ dcp::Formulation formulation,
boost::filesystem::path directory
)
{
shared_ptr<const Film> film,
list<shared_ptr<Screen> > screens,
boost::filesystem::path cpl,
- boost::posix_time::ptime from,
- boost::posix_time::ptime to,
- libdcp::KDM::Formulation formulation
+ dcp::LocalTime from,
- dcp::LocalTime to
++ dcp::LocalTime to,
++ dcp::Formulation formulation
)
{
- list<CinemaKDMs> cinema_kdms = make_cinema_kdms (film, screens, cpl, from, to);
+ list<CinemaKDMs> cinema_kdms = make_cinema_kdms (film, screens, cpl, from, to, formulation);
for (list<CinemaKDMs>::const_iterator i = cinema_kdms.begin(); i != cinema_kdms.end(); ++i) {
boost::shared_ptr<const Film> film,
std::list<boost::shared_ptr<Screen> > screens,
boost::filesystem::path cpl,
- boost::posix_time::ptime from,
- boost::posix_time::ptime to,
- libdcp::KDM::Formulation formulation,
+ dcp::LocalTime from,
+ dcp::LocalTime to,
++ dcp::Formulation formulation,
boost::filesystem::path directory
);
boost::shared_ptr<const Film> film,
std::list<boost::shared_ptr<Screen> > screens,
boost::filesystem::path cpl,
- boost::posix_time::ptime from,
- boost::posix_time::ptime to,
- libdcp::KDM::Formulation formulation,
+ dcp::LocalTime from,
+ dcp::LocalTime to,
++ dcp::Formulation formulation,
boost::filesystem::path directory
);
boost::shared_ptr<const Film> film,
std::list<boost::shared_ptr<Screen> > screens,
boost::filesystem::path cpl,
- boost::posix_time::ptime from,
- boost::posix_time::ptime to,
- libdcp::KDM::Formulation formulation
+ dcp::LocalTime from,
- dcp::LocalTime to
++ dcp::LocalTime to,
++ dcp::Formulation formulation
);
(*next)->set_position (c->position ());
c->set_position (p + c->length_after_trim ());
sort (_content.begin(), _content.end(), ContentSorter ());
-
- Changed ();
}
-
-FrameRateChange
-Playlist::active_frame_rate_change (Time t, int dcp_video_frame_rate) const
-{
- for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
- shared_ptr<const VideoContent> vc = dynamic_pointer_cast<const VideoContent> (*i);
- if (!vc) {
- continue;
- }
-
- if (vc->position() >= t && t < vc->end()) {
- return FrameRateChange (vc->video_frame_rate(), dcp_video_frame_rate);
- }
- }
-
- return FrameRateChange (dcp_video_frame_rate, dcp_video_frame_rate);
-}
list<shared_ptr<Screen> > screens,
boost::filesystem::path dcp,
boost::posix_time::ptime from,
- boost::posix_time::ptime to
+ boost::posix_time::ptime to,
- libdcp::KDM::Formulation formulation
++ dcp::Formulation formulation
)
: Job (f)
, _screens (screens)
*/
#include <boost/filesystem.hpp>
-#include <libdcp/kdm.h>
++#include <dcp/types.h>
#include "job.h"
class Screen;
std::list<boost::shared_ptr<Screen> >,
boost::filesystem::path,
boost::posix_time::ptime,
- boost::posix_time::ptime
+ boost::posix_time::ptime,
- libdcp::KDM::Formulation
++ dcp::Formulation
);
std::string name () const;
boost::filesystem::path _dcp;
boost::posix_time::ptime _from;
boost::posix_time::ptime _to;
- libdcp::KDM::Formulation _formulation;
++ dcp::Formulation _formulation;
};
}
- _worker_condition.notify_all ();
+Server::~Server ()
+{
+ {
+ boost::mutex::scoped_lock lm (_worker_mutex);
+ _terminate = true;
++ _empty_condition.notify_all ();
+ }
+
+ for (vector<boost::thread*>::iterator i = _worker_threads.begin(); i != _worker_threads.end(); ++i) {
+ (*i)->join ();
+ delete *i;
+ }
+
+ _io_service.stop ();
+
+ _broadcast.io_service.stop ();
+ _broadcast.thread->join ();
+}
+
/** @param after_read Filled in with gettimeofday() after reading the input from the network.
* @param after_encode Filled in with gettimeofday() after encoding the image.
*/
{
while (1) {
boost::mutex::scoped_lock lock (_worker_mutex);
- while (_queue.empty ()) {
+ while (_queue.empty () && !_terminate) {
- _worker_condition.wait (lock);
+ _empty_condition.wait (lock);
}
+ if (_terminate) {
+ return;
+ }
+
shared_ptr<Socket> socket = _queue.front ();
_queue.pop_front ();
_broadcast.send_endpoint, boost::bind (&Server::broadcast_received, this)
);
}
- _worker_condition.wait (lock);
+
+void
+Server::start_accept ()
+{
+ if (_terminate) {
+ return;
+ }
+
+ shared_ptr<Socket> socket (new Socket);
+ _acceptor.async_accept (socket->socket (), boost::bind (&Server::handle_accept, this, socket, boost::asio::placeholders::error));
+}
+
+void
+Server::handle_accept (shared_ptr<Socket> socket, boost::system::error_code const & error)
+{
+ if (error) {
+ return;
+ }
+
+ boost::mutex::scoped_lock lock (_worker_mutex);
+
+ /* Wait until the queue has gone down a bit */
+ while (_queue.size() >= _worker_threads.size() * 2 && !_terminate) {
- _worker_condition.notify_all ();
++ _full_condition.wait (lock);
+ }
+
+ _queue.push_back (socket);
++ _empty_condition.notify_all ();
+
+ start_accept ();
+}
+
#define DCPOMATIC_HELLO "Boys, you gotta learn not to talk to nuns that way"
--namespace libdcp {
++namespace dcp {
class Signer;
}
try {
if (d->write_to ()) {
- write_kdm_files (film, d->screens (), d->cpl (), d->from (), d->until (), d->directory ());
+ write_kdm_files (film, d->screens (), d->cpl (), d->from (), d->until (), d->formulation (), d->directory ());
} else {
JobManager::instance()->add (
- shared_ptr<Job> (new SendKDMEmailJob (film, d->screens (), d->cpl (), d->from (), d->until ()))
+ shared_ptr<Job> (new SendKDMEmailJob (film, d->screens (), d->cpl (), d->from (), d->until (), d->formulation ()))
);
}
- } catch (libdcp::NotEncryptedError& e) {
+ } catch (dcp::NotEncryptedError& e) {
error_dialog (this, _("CPL's content is not encrypted."));
} catch (exception& e) {
error_dialog (this, e.what ());
cerr << "Syntax: " << program_name << " [OPTION] [<FILM>]\n"
" -h, --help show this help\n"
" -o, --output output file or directory\n"
- " -f, --valid-from valid from time (e.g. \"2013-09-28 01:41:51\") or \"now\"\n"
- " -t, --valid-to valid to time (e.g. \"2014-09-28 01:41:51\")\n"
+ " -f, --valid-from valid from time (in local time zone) (e.g. \"2013-09-28 01:41:51\") or \"now\"\n"
+ " -t, --valid-to valid to time (in local time zone) (e.g. \"2014-09-28 01:41:51\")\n"
" -d, --valid-duration valid duration (e.g. \"1 day\", \"4 hours\", \"2 weeks\")\n"
+ " --formulation modified-transitional-1, dci-any or dci-specific [default modified-transitional-1]\n"
" -z, --zip ZIP each cinema's KDMs into its own file\n"
" -v, --verbose be verbose\n"
" -c, --cinema specify a cinema, either by name or email address\n"
bool cinemas = false;
string duration_string;
bool verbose = false;
- libdcp::KDM::Formulation formulation = libdcp::KDM::MODIFIED_TRANSITIONAL_1;
++ dcp::Formulation formulation = dcp::MODIFIED_TRANSITIONAL_1;
program_name = argv[0];
case 'v':
verbose = true;
break;
- formulation = libdcp::KDM::MODIFIED_TRANSITIONAL_1;
+ case 'C':
+ if (string (optarg) == "modified-transitional-1") {
- formulation = libdcp::KDM::DCI_ANY;
++ formulation = dcp::MODIFIED_TRANSITIONAL_1;
+ } else if (string (optarg) == "dci-any") {
- formulation = libdcp::KDM::DCI_SPECIFIC;
++ formulation = dcp::DCI_ANY;
+ } else if (string (optarg) == "dci-specific") {
++ formulation = dcp::DCI_SPECIFIC;
+ } else {
+ error ("unrecognised KDM formulation " + formulation);
+ }
}
}
error ("you must specify --output");
}
- shared_ptr<libdcp::Certificate> certificate (new libdcp::Certificate (boost::filesystem::path (certificate_file)));
- libdcp::KDM kdm = film->make_kdm (certificate, cpl, valid_from.get(), valid_to.get(), formulation);
+ shared_ptr<dcp::Certificate> certificate (new dcp::Certificate (boost::filesystem::path (certificate_file)));
- dcp::EncryptedKDM kdm = film->make_kdm (certificate, cpl, valid_from.get(), valid_to.get());
++ dcp::EncryptedKDM kdm = film->make_kdm (certificate, cpl, valid_from.get(), valid_to.get(), formulation);
kdm.as_xml (output);
if (verbose) {
cout << "Generated KDM " << output << " for certificate.\n";
try {
if (zip) {
- write_kdm_zip_files (film, (*i)->screens(), cpl, dcp::LocalTime (valid_from.get()), dcp::LocalTime (valid_to.get()), output);
-
- write_kdm_zip_files (film, (*i)->screens(), cpl, valid_from.get(), valid_to.get(), formulation, output);
++ write_kdm_zip_files (
++ film, (*i)->screens(), cpl, dcp::LocalTime (valid_from.get()), dcp::LocalTime (valid_to.get()), formulation, output
++ );
++
if (verbose) {
cout << "Wrote ZIP files to " << output << "\n";
}
} else {
- write_kdm_files (film, (*i)->screens(), cpl, dcp::LocalTime (valid_from.get()), dcp::LocalTime (valid_to.get()), output);
- write_kdm_files (film, (*i)->screens(), cpl, valid_from.get(), valid_to.get(), formulation, output);
++ write_kdm_files (
++ film, (*i)->screens(), cpl, dcp::LocalTime (valid_from.get()), dcp::LocalTime (valid_to.get()), formulation, output
++ );
++
if (verbose) {
cout << "Wrote KDM files to " << output << "\n";
}
return _write_to->GetValue ();
}
-libdcp::KDM::Formulation
++dcp::Formulation
+ KDMDialog::formulation () const
+ {
+ switch (_type->GetSelection()) {
+ case 0:
- return libdcp::KDM::MODIFIED_TRANSITIONAL_1;
++ return dcp::MODIFIED_TRANSITIONAL_1;
+ case 1:
- return libdcp::KDM::DCI_ANY;
++ return dcp::DCI_ANY;
+ case 2:
- return libdcp::KDM::DCI_SPECIFIC;
++ return dcp::DCI_SPECIFIC;
+ default:
+ assert (false);
+ }
+ }
+
void
KDMDialog::update_cpl_choice ()
{
boost::filesystem::path cpl () const;
boost::filesystem::path directory () const;
bool write_to () const;
- libdcp::KDM::Formulation formulation () const;
++ dcp::Formulation formulation () const;
private:
void add_cinema (boost::shared_ptr<Cinema>);
Refresh ();
}
- setup_pixels_per_time_unit ();
+ void
+ Timeline::playlist_content_changed (int property)
+ {
+ ensure_ui_thread ();
+
+ if (property == ContentProperty::POSITION) {
+ assign_tracks ();
++ setup_pixels_per_second ();
+ Refresh ();
+ }
+ }
+
void
Timeline::assign_tracks ()
{
}
}
- if (new_position < 0) {
- new_position = 0;
+ if (new_position < DCPTime ()) {
+ new_position = DCPTime ();
}
-
+
_down_view->content()->set_position (new_position);
shared_ptr<Film> film = _film.lock ();
*/
-#include <libdcp/raw_convert.h>
++#include <dcp/raw_convert.h>
#include "lib/content.h"
#include "lib/image_content.h"
#include "timing_panel.h"
using std::string;
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
- using boost::lexical_cast;
-using libdcp::raw_convert;
++using dcp::raw_convert;
TimingPanel::TimingPanel (FilmEditor* e)
/* horrid hack for apparent lack of context support with wxWidgets i18n code */
using std::list;
-/* Check that Image::make_black works, and doesn't use values which crash
- sws_scale().
-*/
BOOST_AUTO_TEST_CASE (make_black_test)
{
- libdcp::Size in_size (512, 512);
- libdcp::Size out_size (1024, 1024);
+ dcp::Size in_size (512, 512);
+ dcp::Size out_size (1024, 1024);
list<AVPixelFormat> pix_fmts;
- pix_fmts.push_back (AV_PIX_FMT_RGB24);
+ pix_fmts.push_back (AV_PIX_FMT_RGB24); // 2
pix_fmts.push_back (AV_PIX_FMT_ARGB);
pix_fmts.push_back (AV_PIX_FMT_RGBA);
pix_fmts.push_back (AV_PIX_FMT_ABGR);
conf.check_cfg(package='libopenjpeg', args='--cflags --libs', max_version='1.5.2', mandatory=True)
def static_dcp(conf, static_boost, static_xmlpp, static_xmlsec, static_ssh):
- conf.check_cfg(package='libdcp-1.0', atleast_version='0.92', args='--cflags', uselib_store='DCP', mandatory=True)
- conf.check_cfg(package='libdcp', atleast_version='0.95', args='--cflags', uselib_store='DCP', mandatory=True)
++ conf.check_cfg(package='libdcp-1.0', atleast_version='0.95', args='--cflags', uselib_store='DCP', mandatory=True)
conf.env.DEFINES_DCP = [f.replace('\\', '') for f in conf.env.DEFINES_DCP]
- conf.env.STLIB_DCP = ['dcp', 'asdcp-libdcp', 'kumu-libdcp']
+ conf.env.STLIB_DCP = ['dcp-1.0', 'asdcp-libdcp-1.0', 'kumu-libdcp-1.0']
conf.env.LIB_DCP = ['glibmm-2.4', 'ssl', 'crypto', 'bz2', 'xslt']
if static_boost: