From: Carl Hetherington Date: Mon, 29 Sep 2014 12:49:54 +0000 (+0100) Subject: Merge master. X-Git-Tag: v2.0.48~575 X-Git-Url: https://git.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=391d85619ac19a2a93696ddc35c222eb9bb5d9d6;hp=-c Merge master. --- 391d85619ac19a2a93696ddc35c222eb9bb5d9d6 diff --combined ChangeLog index 57ec197ea,f676d6b99..a8927a547 --- a/ChangeLog +++ b/ChangeLog @@@ -1,11 -1,11 +1,19 @@@ +2014-09-22 Carl Hetherington + + * Version 2.0.11 released. + +2014-09-18 Carl Hetherington + + * Version 2.0.10 released. + + 2014-09-28 Carl Hetherington + + * Version 1.73.8 released. + + 2014-09-28 Carl Hetherington + + * Add a few key shortcuts. + 2014-09-16 Carl Hetherington * Version 1.73.7 released. @@@ -28,19 -28,6 +36,19 @@@ 2014-09-12 Carl Hetherington + * Version 2.0.9 released. + +2014-09-12 Carl Hetherington + + * Add "re-examine" option to content context menu (#339). + +2014-09-11 Carl Hetherington + + * Restore encoding optimisations for still-image sources. + + * Add option to re-make signing chain with specified organisation, + common names etc. (#354) + * Allow separate X and Y scale for subtitles (#337). 2014-09-10 Carl Hetherington @@@ -50,38 -37,17 +58,38 @@@ * Fix hidden advanced preferences button in some locales. -2014-09-08 Carl Hetherington + * Version 2.0.8 released. + +2014-09-10 Carl Hetherington + + * Fix loading of 1.x films. + + * Fix crash on audio analysis in some cases. + +2014-09-09 Carl Hetherington + + * Version 2.0.7 released. + +2014-09-09 Carl Hetherington + + * Version 2.0.6 released. + +2014-09-09 Carl Hetherington - * Version 1.73.4 released. + * Fix missing OS X dependencies. + + * Use a different directory for DCP-o-matic 2 + configuration (not the same as 1.x). 2014-09-08 Carl Hetherington - * Fix failure to load Targa files. + * Version 2.0.5 released. -2014-09-07 Carl Hetherington + * Fix hidden advanced preferences button in some locales. - * Version 1.73.3 released. +2014-09-08 Carl Hetherington + + * Fix failure to load Targa files. 2014-09-07 Carl Hetherington @@@ -90,6 -56,10 +98,6 @@@ * Fix a few bad fuzzy translations from the preferences dialog. -2014-09-03 Carl Hetherington - - * Version 1.73.2 released. - 2014-09-03 Carl Hetherington * Fix server certificate downloads on OS X (#376). @@@ -118,33 -88,6 +126,33 @@@ 2014-08-29 Carl Hetherington + * Version 2.0.4 released. + +2014-08-24 Carl Hetherington + + * Version 2.0.3 released. + +2014-08-24 Carl Hetherington + + * Version 2.0.2 released. + +2014-08-06 Carl Hetherington + + * Version 2.0.1 released. + +2014-07-15 Carl Hetherington + + * A variety of changes were made on the 2.0 branch + but not documented in the ChangeLog. Most sigificantly: + + - DCP import + - Creation of DCPs with proper XML subtitles + - Import of .srt and .xml subtitles + - Audio processing framework (with some basic processors). + +2014-03-07 Carl Hetherington + + * Add subtitle view. * Some improvements to the manual. 2014-08-26 Carl Hetherington @@@ -175,7 -118,6 +183,7 @@@ * Attempt to fix random crashes on OS X (especially during encodes) thought to be caused by multiple threads using (different) stringstreams at the same time; see src/lib/safe_stringstream. +>>>>>>> origin/master 2014-08-09 Carl Hetherington @@@ -240,7 -182,6 +248,7 @@@ 2014-07-10 Carl Hetherington * Version 1.72.2 released. +>>>>>>> origin/master 2014-07-10 Carl Hetherington diff --combined src/lib/writer.cc index a023d5cd2,5af1aea1e..6262525c8 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@@ -19,32 -19,25 +19,32 @@@ #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "writer.h" #include "compose.hpp" #include "film.h" #include "ratio.h" #include "log.h" -#include "dcp_video_frame.h" +#include "dcp_video.h" #include "dcp_content_type.h" -#include "player.h" #include "audio_mapping.h" #include "config.h" #include "job.h" #include "cross.h" +#include "audio_buffers.h" #include "md5_digester.h" +#include "encoded_data.h" #include "version.h" #include "i18n.h" @@@ -52,6 -45,7 +52,7 @@@ #define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL); #define LOG_TIMING(...) _film->log()->microsecond_log (String::compose (__VA_ARGS__), Log::TYPE_TIMING); #define LOG_WARNING_NC(...) _film->log()->log (__VA_ARGS__, Log::TYPE_WARNING); + #define LOG_ERROR(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_ERROR); /* OS X strikes again */ #undef set_key @@@ -63,7 -57,6 +64,7 @@@ using std::list using std::cout; using boost::shared_ptr; using boost::weak_ptr; +using boost::dynamic_pointer_cast; int const Writer::_maximum_frames_in_memory = Config::instance()->num_local_encoding_threads() + 4; @@@ -78,6 -71,7 +79,6 @@@ Writer::Writer (shared_ptr , _last_written_eyes (EYES_RIGHT) , _full_written (0) , _fake_written (0) - , _repeat_written (0) , _pushed_to_disk (0) { /* Remove any old DCP */ @@@ -95,39 -89,36 +96,39 @@@ */ if (_film->three_d ()) { - _picture_asset.reset (new libdcp::StereoPictureAsset (_film->internal_video_mxf_dir (), _film->internal_video_mxf_filename ())); + _picture_mxf.reset (new dcp::StereoPictureMXF (dcp::Fraction (_film->video_frame_rate (), 1))); } else { - _picture_asset.reset (new libdcp::MonoPictureAsset (_film->internal_video_mxf_dir (), _film->internal_video_mxf_filename ())); + _picture_mxf.reset (new dcp::MonoPictureMXF (dcp::Fraction (_film->video_frame_rate (), 1))); } - _picture_asset->set_edit_rate (_film->video_frame_rate ()); - _picture_asset->set_size (_film->frame_size ()); - _picture_asset->set_interop (_film->interop ()); + _picture_mxf->set_size (_film->frame_size ()); if (_film->encrypted ()) { - _picture_asset->set_key (_film->key ()); + _picture_mxf->set_key (_film->key ()); } - _picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0); + _picture_mxf_writer = _picture_mxf->start_write ( + _film->internal_video_mxf_dir() / _film->internal_video_mxf_filename(), + _film->interop() ? dcp::INTEROP : dcp::SMPTE, + _first_nonexistant_frame > 0 + ); if (_film->audio_channels ()) { - _sound_asset.reset (new libdcp::SoundAsset (_film->directory (), _film->audio_mxf_filename ())); - _sound_asset->set_edit_rate (_film->video_frame_rate ()); - _sound_asset->set_channels (_film->audio_channels ()); - _sound_asset->set_sampling_rate (_film->audio_frame_rate ()); - _sound_asset->set_interop (_film->interop ()); + _sound_mxf.reset (new dcp::SoundMXF (dcp::Fraction (_film->video_frame_rate(), 1), _film->audio_frame_rate (), _film->audio_channels ())); if (_film->encrypted ()) { - _sound_asset->set_key (_film->key ()); + _sound_mxf->set_key (_film->key ()); } - - /* Write the sound asset into the film directory so that we leave the creation + + /* Write the sound MXF into the film directory so that we leave the creation of the DCP directory until the last minute. */ - _sound_asset_writer = _sound_asset->start_write (); + _sound_mxf_writer = _sound_mxf->start_write (_film->directory() / _film->audio_mxf_filename(), _film->interop() ? dcp::INTEROP : dcp::SMPTE); + } + + /* Check that the signer is OK if we need one */ + if (_film->is_signed() && !Config::instance()->signer()->valid ()) { + throw InvalidSignerError (); } _thread = new boost::thread (boost::bind (&Writer::thread, this)); @@@ -184,7 -175,7 +185,7 @@@ Writer::fake_write (int frame, Eyes eye } FILE* ifi = fopen_boost (_film->info_path (frame, eyes), "r"); - libdcp::FrameInfo info (ifi); + dcp::FrameInfo info (ifi); fclose (ifi); QueueItem qi; @@@ -209,8 -200,8 +210,8 @@@ void Writer::write (shared_ptr audio) { - if (_sound_asset) { - _sound_asset_writer->write (audio->data(), audio->frames()); + if (_sound_mxf_writer) { + _sound_mxf_writer->write (audio->data(), audio->frames()); } } @@@ -286,7 -277,7 +287,7 @@@ tr qi.encoded.reset (new EncodedData (_film->j2c_path (qi.frame, qi.eyes, false))); } - libdcp::FrameInfo fin = _picture_asset_writer->write (qi.encoded->data(), qi.encoded->size()); + dcp::FrameInfo fin = _picture_mxf_writer->write (qi.encoded->data(), qi.encoded->size()); qi.encoded->write_info (_film, qi.frame, qi.eyes, fin); _last_written[qi.eyes] = qi.encoded; ++_full_written; @@@ -294,27 -285,39 +295,27 @@@ } case QueueItem::FAKE: LOG_GENERAL (N_("Writer FAKE-writes %1 to MXF"), qi.frame); - _picture_asset_writer->fake_write (qi.size); + _picture_mxf_writer->fake_write (qi.size); _last_written[qi.eyes].reset (); ++_fake_written; break; - case QueueItem::REPEAT: - { - LOG_GENERAL (N_("Writer REPEAT-writes %1 to MXF"), qi.frame); - libdcp::FrameInfo fin = _picture_asset_writer->write ( - _last_written[qi.eyes]->data(), - _last_written[qi.eyes]->size() - ); - - _last_written[qi.eyes]->write_info (_film, qi.frame, qi.eyes, fin); - ++_repeat_written; - break; - } } lock.lock (); _last_written_frame = qi.frame; _last_written_eyes = qi.eyes; - if (_film->length()) { - shared_ptr job = _job.lock (); - assert (job); - int total = _film->time_to_video_frames (_film->length ()); - if (_film->three_d ()) { - /* _full_written and so on are incremented for each eye, so we need to double the total - frames to get the correct progress. - */ - total *= 2; - } - job->set_progress (float (_full_written + _fake_written + _repeat_written) / total); + shared_ptr job = _job.lock (); + assert (job); + int64_t total = _film->length().frames (_film->video_frame_rate ()); + if (_film->three_d ()) { + /* _full_written and so on are incremented for each eye, so we need to double the total + frames to get the correct progress. + */ + total *= 2; + } + if (total) { + job->set_progress (float (_full_written + _fake_written) / total); } } @@@ -389,11 -392,15 +390,11 @@@ Writer::finish ( terminate_thread (true); - _picture_asset_writer->finalize (); - if (_sound_asset_writer) { - _sound_asset_writer->finalize (); + _picture_mxf_writer->finalize (); + if (_sound_mxf_writer) { + _sound_mxf_writer->finalize (); } - int const frames = _last_written_frame + 1; - - _picture_asset->set_duration (frames); - /* Hard-link the video MXF into the DCP */ boost::filesystem::path video_from; video_from /= _film->internal_video_mxf_dir(); @@@ -406,16 -413,22 +407,19 @@@ boost::system::error_code ec; boost::filesystem::create_hard_link (video_from, video_to, ec); if (ec) { - /* hard link failed; copy instead */ - boost::filesystem::copy_file (video_from, video_to); - LOG_WARNING_NC ("Hard-link failed; fell back to copying"); + LOG_WARNING_NC ("Hard-link failed; copying instead"); + boost::filesystem::copy_file (video_from, video_to, ec); + if (ec) { + LOG_ERROR ("Failed to copy video file from %1 to %2 (%3)", video_from.string(), video_to.string(), ec.message ()); + throw FileError (ec.message(), video_from); + } } - /* And update the asset */ - - _picture_asset->set_directory (_film->dir (_film->dcp_name ())); - _picture_asset->set_file_name (_film->video_mxf_filename ()); + _picture_mxf->set_file (video_to); /* Move the audio MXF into the DCP */ - if (_sound_asset) { + if (_sound_mxf) { boost::filesystem::path audio_to; audio_to /= _film->dir (_film->dcp_name ()); audio_to /= _film->audio_mxf_filename (); @@@ -426,86 -439,80 +430,86 @@@ String::compose (_("could not move audio MXF into the DCP (%1)"), ec.value ()), _film->file (_film->audio_mxf_filename ()) ); } - - _sound_asset->set_directory (_film->dir (_film->dcp_name ())); - _sound_asset->set_duration (frames); + + _sound_mxf->set_file (audio_to); } - - libdcp::DCP dcp (_film->dir (_film->dcp_name())); - shared_ptr cpl ( - new libdcp::CPL ( - _film->dir (_film->dcp_name()), + dcp::DCP dcp (_film->dir (_film->dcp_name())); + + shared_ptr cpl ( + new dcp::CPL ( _film->dcp_name(), - _film->dcp_content_type()->libdcp_kind (), - frames, - _film->video_frame_rate () + _film->dcp_content_type()->libdcp_kind () ) ); - dcp.add_cpl (cpl); + dcp.add (cpl); + + shared_ptr reel (new dcp::Reel ()); + + shared_ptr mono = dynamic_pointer_cast (_picture_mxf); + if (mono) { + reel->add (shared_ptr (new dcp::ReelMonoPictureAsset (mono, 0))); + dcp.add (mono); + } + + shared_ptr stereo = dynamic_pointer_cast (_picture_mxf); + if (stereo) { + reel->add (shared_ptr (new dcp::ReelStereoPictureAsset (stereo, 0))); + dcp.add (stereo); + } + + if (_sound_mxf) { + reel->add (shared_ptr (new dcp::ReelSoundAsset (_sound_mxf, 0))); + dcp.add (_sound_mxf); + } - cpl->add_reel (shared_ptr (new libdcp::Reel ( - _picture_asset, - _sound_asset, - shared_ptr () - ) - )); + if (_subtitle_content) { + _subtitle_content->write_xml (_film->dir (_film->dcp_name ()) / _film->subtitle_xml_filename ()); + reel->add (shared_ptr ( + new dcp::ReelSubtitleAsset ( + _subtitle_content, + dcp::Fraction (_film->video_frame_rate(), 1), + _picture_mxf->intrinsic_duration (), + 0 + ) + )); + + dcp.add (_subtitle_content); + } + + cpl->add (reel); shared_ptr job = _job.lock (); assert (job); job->sub (_("Computing image digest")); - _picture_asset->compute_digest (boost::bind (&Job::set_progress, job.get(), _1, false)); + _picture_mxf->hash (boost::bind (&Job::set_progress, job.get(), _1, false)); - if (_sound_asset) { + if (_sound_mxf) { job->sub (_("Computing audio digest")); - _sound_asset->compute_digest (boost::bind (&Job::set_progress, job.get(), _1, false)); + _sound_mxf->hash (boost::bind (&Job::set_progress, job.get(), _1, false)); } - libdcp::XMLMetadata meta; + dcp::XMLMetadata meta; meta.issuer = Config::instance()->dcp_issuer (); meta.creator = String::compose ("DCP-o-matic %1 %2", dcpomatic_version, dcpomatic_git_commit); meta.set_issue_date_now (); - dcp.write_xml (_film->interop (), meta, _film->is_signed() ? make_signer () : shared_ptr ()); - - LOG_GENERAL ( - N_("Wrote %1 FULL, %2 FAKE, %3 REPEAT; %4 pushed to disk"), _full_written, _fake_written, _repeat_written, _pushed_to_disk - ); -} -/** Tell the writer that frame `f' should be a repeat of the frame before it */ -void -Writer::repeat (int f, Eyes e) -{ - boost::mutex::scoped_lock lock (_mutex); - - while (_queued_full_in_memory > _maximum_frames_in_memory) { - /* The queue is too big; wait until that is sorted out */ - _full_condition.wait (lock); - } - - QueueItem qi; - qi.type = QueueItem::REPEAT; - qi.frame = f; - if (_film->three_d() && e == EYES_BOTH) { - qi.eyes = EYES_LEFT; - _queue.push_back (qi); - qi.eyes = EYES_RIGHT; - _queue.push_back (qi); - } else { - qi.eyes = e; - _queue.push_back (qi); + shared_ptr signer; + if (_film->is_signed ()) { + signer = Config::instance()->signer (); + /* We did check earlier, but check again here to be on the safe side */ + if (!signer->valid ()) { + throw InvalidSignerError (); + } } - /* Now there's something to do: wake anything wait()ing on _empty_condition */ - _empty_condition.notify_all (); + dcp.write_xml (_film->interop () ? dcp::INTEROP : dcp::SMPTE, meta, signer); + + LOG_GENERAL ( + N_("Wrote %1 FULL, %2 FAKE, %3 pushed to disk"), _full_written, _fake_written, _pushed_to_disk + ); } bool @@@ -518,7 -525,7 +522,7 @@@ Writer::check_existing_picture_mxf_fram return false; } - libdcp::FrameInfo info (ifi); + dcp::FrameInfo info (ifi); fclose (ifi); if (info.size == 0) { LOG_GENERAL ("Existing frame %1 has no info file", f); @@@ -603,24 -610,6 +607,24 @@@ Writer::can_fake_write (int frame) cons return (frame != 0 && frame < _first_nonexistant_frame); } +void +Writer::write (PlayerSubtitles subs) +{ + if (subs.text.empty ()) { + return; + } + + if (!_subtitle_content) { + _subtitle_content.reset ( + new dcp::SubtitleContent (_film->name(), _film->isdcf_metadata().subtitle_language) + ); + } + + for (list::const_iterator i = subs.text.begin(); i != subs.text.end(); ++i) { + _subtitle_content->add (*i); + } +} + bool operator< (QueueItem const & a, QueueItem const & b) { diff --combined src/tools/dcpomatic.cc index 8a0aa245e,fa89a4871..01aa0158b --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@@ -30,7 -30,7 +30,7 @@@ #include #include #include -#include +#include #include "wx/film_viewer.h" #include "wx/film_editor.h" #include "wx/job_manager_view.h" @@@ -45,7 -45,6 +45,7 @@@ #include "wx/servers_list_dialog.h" #include "wx/hints_dialog.h" #include "wx/update_dialog.h" +#include "wx/content_panel.h" #include "lib/film.h" #include "lib/config.h" #include "lib/util.h" @@@ -73,6 -72,8 +73,6 @@@ using std::exception using boost::shared_ptr; using boost::dynamic_pointer_cast; -// #define DCPOMATIC_WINDOWS_CONSOLE 1 - class FilmChangedDialog { public: @@@ -126,7 -127,9 +126,9 @@@ enum ID_jobs_show_dcp, ID_tools_hints, ID_tools_encoding_servers, - ID_tools_check_for_updates + ID_tools_check_for_updates, + /* IDs for shortcuts (with no associated menu item) */ + ID_add_file }; class Frame : public wxFrame @@@ -142,24 -145,20 +144,24 @@@ public , _history_position (0) , _history_separator (0) { -#if defined(DCPOMATIC_WINDOWS) && defined(DCPOMATIC_WINDOWS_CONSOLE) - AllocConsole(); - - HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); - int hCrt = _open_osfhandle((intptr_t) handle_out, _O_TEXT); - FILE* hf_out = _fdopen(hCrt, "w"); - setvbuf(hf_out, NULL, _IONBF, 1); - *stdout = *hf_out; - - HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE); - hCrt = _open_osfhandle((intptr_t) handle_in, _O_TEXT); - FILE* hf_in = _fdopen(hCrt, "r"); - setvbuf(hf_in, NULL, _IONBF, 128); - *stdin = *hf_in; +#if defined(DCPOMATIC_WINDOWS) + if (Config::instance()->win32_console ()) { + AllocConsole(); + + HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); + int hCrt = _open_osfhandle((intptr_t) handle_out, _O_TEXT); + FILE* hf_out = _fdopen(hCrt, "w"); + setvbuf(hf_out, NULL, _IONBF, 1); + *stdout = *hf_out; + + HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE); + hCrt = _open_osfhandle((intptr_t) handle_in, _O_TEXT); + FILE* hf_in = _fdopen(hCrt, "r"); + setvbuf(hf_in, NULL, _IONBF, 128); + *stdin = *hf_in; + + cout << "DCP-o-matic is starting." << "\n"; + } #endif wxMenuBar* bar = new wxMenuBar; @@@ -189,6 -188,12 +191,12 @@@ Bind (wxEVT_CLOSE_WINDOW, boost::bind (&Frame::close, this, _1)); + wxAcceleratorEntry accel[1]; + accel[0].Set (wxACCEL_CTRL, static_cast('A'), ID_add_file); - Bind (wxEVT_MENU, boost::bind (&FilmEditor::content_add_file_clicked, _film_editor), ID_add_file); ++ Bind (wxEVT_MENU, boost::bind (&ContentPanel::add_file_clicked, _film_editor->content_panel()), ID_add_file); + wxAcceleratorTable accel_table (1, accel); + SetAcceleratorTable (accel_table); + /* Use a panel as the only child of the Frame so that we avoid the dark-grey background on Windows. */ @@@ -405,7 -410,7 +413,7 @@@ private shared_ptr (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 ()); @@@ -418,7 -423,7 +426,7 @@@ void content_scale_to_fit_width () { - VideoContentList vc = _film_editor->selected_video_content (); + VideoContentList vc = _film_editor->content_panel()->selected_video (); for (VideoContentList::iterator i = vc.begin(); i != vc.end(); ++i) { (*i)->scale_and_crop_to_fit_width (); } @@@ -426,7 -431,7 +434,7 @@@ void content_scale_to_fit_height () { - VideoContentList vc = _film_editor->selected_video_content (); + VideoContentList vc = _film_editor->content_panel()->selected_video (); for (VideoContentList::iterator i = vc.begin(); i != vc.end(); ++i) { (*i)->scale_and_crop_to_fit_height (); } @@@ -537,7 -542,7 +545,7 @@@ } bool const dcp_creation = (i != jobs.end ()) && !(*i)->finished (); bool const have_cpl = _film && !_film->cpls().empty (); - bool const have_selected_video_content = !_film_editor->selected_video_content().empty(); + bool const have_selected_video_content = !_film_editor->content_panel()->selected_video().empty(); for (map::iterator j = menu_items.begin(); j != menu_items.end(); ++j) { @@@ -592,10 -597,10 +600,10 @@@ void setup_menu (wxMenuBar* m) { _file_menu = new wxMenu; - add_item (_file_menu, _("New..."), ID_file_new, ALWAYS); - add_item (_file_menu, _("&Open..."), ID_file_open, ALWAYS); + add_item (_file_menu, _("New...\tCtrl-N"), ID_file_new, ALWAYS); + add_item (_file_menu, _("&Open...\tCtrl-O"), ID_file_open, ALWAYS); _file_menu->AppendSeparator (); - add_item (_file_menu, _("&Save"), ID_file_save, NEEDS_FILM); + add_item (_file_menu, _("&Save\tCtrl-S"), ID_file_save, NEEDS_FILM); _file_menu->AppendSeparator (); add_item (_file_menu, _("&Properties..."), ID_file_properties, NEEDS_FILM); @@@ -612,10 -617,10 +620,10 @@@ #endif #ifdef __WXOSX__ - add_item (_file_menu, _("&Preferences..."), wxID_PREFERENCES, ALWAYS); + add_item (_file_menu, _("&Preferences...\tCtrl-P"), wxID_PREFERENCES, ALWAYS); #else wxMenu* edit = new wxMenu; - add_item (edit, _("&Preferences..."), wxID_PREFERENCES, ALWAYS); + add_item (edit, _("&Preferences...\tCtrl-P"), wxID_PREFERENCES, ALWAYS); #endif wxMenu* content = new wxMenu; @@@ -623,13 -628,13 +631,13 @@@ add_item (content, _("Scale to fit &height"), ID_content_scale_to_fit_height, NEEDS_FILM | NEEDS_SELECTED_VIDEO_CONTENT); wxMenu* jobs_menu = new wxMenu; - add_item (jobs_menu, _("&Make DCP"), ID_jobs_make_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION); - add_item (jobs_menu, _("Make &KDMs..."), ID_jobs_make_kdms, NEEDS_FILM); + add_item (jobs_menu, _("&Make DCP\tCtrl-M"), ID_jobs_make_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION); + add_item (jobs_menu, _("Make &KDMs...\tCtrl-K"), ID_jobs_make_kdms, NEEDS_FILM); add_item (jobs_menu, _("&Send DCP to TMS"), ID_jobs_send_dcp_to_tms, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL); add_item (jobs_menu, _("S&how DCP"), ID_jobs_show_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL); wxMenu* tools = new wxMenu; - add_item (tools, _("Hints..."), ID_tools_hints, 0); + add_item (tools, _("Hints...\tCtrl-H"), ID_tools_hints, 0); add_item (tools, _("Encoding servers..."), ID_tools_encoding_servers, 0); add_item (tools, _("Check for updates"), ID_tools_check_for_updates, 0); @@@ -702,9 -707,6 +710,9 @@@ static const wxCmdLineEntryDesc command { wxCMD_LINE_NONE, "", "", "", wxCmdLineParamType (0), 0 } }; +/** @class App + * @brief The magic App class for wxWidgets. + */ class App : public wxApp { bool OnInit () diff --combined src/wx/content_panel.h index 1f64d51c6,000000000..ab198411d mode 100644,000000..100644 --- a/src/wx/content_panel.h +++ b/src/wx/content_panel.h @@@ -1,102 -1,0 +1,103 @@@ +/* + Copyright (C) 2012-2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include "lib/types.h" +#include "lib/film.h" +#include "content_menu.h" + +class wxNotebook; +class wxPanel; +class wxSizer; +class wxListCtrl; +class wxListEvent; +class TimelineDialog; +class FilmEditor; +class ContentSubPanel; +class Film; + +class ContentPanel +{ +public: + ContentPanel (wxNotebook *, boost::shared_ptr); + + boost::shared_ptr film () const { + return _film; + } + + void set_film (boost::shared_ptr f); + void set_general_sensitivity (bool s); + void set_selection (boost::weak_ptr); + + void film_changed (Film::Property p); + void film_content_changed (int p); + + wxPanel* panel () const { + return _panel; + } + + wxNotebook* notebook () const { + return _notebook; + } + + ContentList selected (); + VideoContentList selected_video (); + AudioContentList selected_audio (); + SubtitleContentList selected_subtitle (); + FFmpegContentList selected_ffmpeg (); + ++ void add_file_clicked (); ++ +private: + void sequence_video_changed (); + void selection_changed (); - void add_file_clicked (); + void add_folder_clicked (); + void remove_clicked (); + void earlier_clicked (); + void later_clicked (); + void right_click (wxListEvent &); + void files_dropped (wxDropFilesEvent &); + void timeline_clicked (); + + void setup (); + void setup_sensitivity (); + + wxPanel* _panel; + wxSizer* _sizer; + wxNotebook* _notebook; + wxListCtrl* _content; + wxButton* _add_file; + wxButton* _add_folder; + wxButton* _remove; + wxButton* _earlier; + wxButton* _later; + wxButton* _timeline; + wxCheckBox* _sequence_video; + ContentSubPanel* _video_panel; + ContentSubPanel* _audio_panel; + ContentSubPanel* _subtitle_panel; + ContentSubPanel* _timing_panel; + std::list _panels; + ContentMenu* _menu; + TimelineDialog* _timeline_dialog; + + boost::shared_ptr _film; + bool _generally_sensitive; +}; diff --combined src/wx/film_editor.h index b311184fa,ba9ff6fa0..25749fffa --- a/src/wx/film_editor.h +++ b/src/wx/film_editor.h @@@ -22,15 -22,23 +22,15 @@@ */ #include -#include -#include -#include #include #include "lib/film.h" -#include "content_menu.h" +class wxSpinCtrl; class wxNotebook; -class wxListCtrl; -class wxListEvent; -class wxGridBagSizer; class Film; -class TimelineDialog; class Ratio; -class Timecode; -class FilmEditorPanel; -class SubtitleContent; +class ContentPanel; +class DCPPanel; /** @class FilmEditor * @brief A wx widget to edit a film's metadata, and perform various functions. @@@ -41,31 -49,121 +41,30 @@@ public FilmEditor (wxWindow *); void set_film (boost::shared_ptr); - void set_selection (boost::weak_ptr); boost::signals2::signal FileChanged; /* Stuff for panels */ - - wxNotebook* content_notebook () const { - return _content_notebook; - } + ContentPanel* content_panel () const { + return _content_panel; + } + boost::shared_ptr film () const { return _film; } - ContentList selected_content (); - VideoContentList selected_video_content (); - AudioContentList selected_audio_content (); - SubtitleContentList selected_subtitle_content (); - FFmpegContentList selected_ffmpeg_content (); - - void content_add_file_clicked (); - --private: - void make_dcp_panel (); - void make_content_panel (); - void connect_to_widgets (); - - /* Handle changes to the view */ - void name_changed (); - void use_isdcf_name_toggled (); - void edit_isdcf_button_clicked (); - void content_selection_changed (); - void content_add_folder_clicked (); - void content_remove_clicked (); - void content_earlier_clicked (); - void content_later_clicked (); - void content_files_dropped (wxDropFilesEvent& event); - void container_changed (); - void dcp_content_type_changed (); - void scaler_changed (); - void j2k_bandwidth_changed (); - void frame_rate_choice_changed (); - void frame_rate_spin_changed (); - void best_frame_rate_clicked (); - void content_timeline_clicked (); - void audio_channels_changed (); - void resolution_changed (); - void sequence_video_changed (); - void content_right_click (wxListEvent &); - void three_d_changed (); - void standard_changed (); - void signed_toggled (); - void encrypted_toggled (); - /* Handle changes to the model */ void film_changed (Film::Property); void film_content_changed (int); - void use_isdcf_name_changed (); void set_general_sensitivity (bool); - void setup_dcp_name (); - void setup_content (); - void setup_container (); - void setup_content_sensitivity (); - void setup_frame_rate_widget (); - void active_jobs_changed (bool); - void config_changed (); - - FilmEditorPanel* _video_panel; - FilmEditorPanel* _audio_panel; - FilmEditorPanel* _subtitle_panel; - FilmEditorPanel* _timing_panel; - std::list _panels; wxNotebook* _main_notebook; - wxNotebook* _content_notebook; - wxPanel* _dcp_panel; - wxSizer* _dcp_sizer; - wxPanel* _content_panel; - wxSizer* _content_sizer; + ContentPanel* _content_panel; + DCPPanel* _dcp_panel; /** The film we are editing */ boost::shared_ptr _film; - wxTextCtrl* _name; - wxStaticText* _dcp_name; - wxCheckBox* _use_isdcf_name; - wxChoice* _container; - wxListCtrl* _content; - wxButton* _content_add_file; - wxButton* _content_add_folder; - wxButton* _content_remove; - wxButton* _content_earlier; - wxButton* _content_later; - wxButton* _content_timeline; - wxCheckBox* _sequence_video; - wxButton* _edit_isdcf_button; - wxChoice* _scaler; - wxSpinCtrl* _j2k_bandwidth; - wxChoice* _dcp_content_type; - wxChoice* _frame_rate_choice; - wxSpinCtrl* _frame_rate_spin; - wxSizer* _frame_rate_sizer; - wxSpinCtrl* _audio_channels; - wxButton* _best_frame_rate; - wxCheckBox* _three_d; - wxChoice* _resolution; - wxChoice* _standard; - wxCheckBox* _signed; - wxCheckBox* _encrypted; - - ContentMenu _menu; - - std::vector _ratios; - - bool _generally_sensitive; - TimelineDialog* _timeline_dialog; };