diff options
-rw-r--r-- | gtk2_ardour/export_format_dialog.cc | 9 | ||||
-rw-r--r-- | gtk2_ardour/export_format_dialog.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/export_format_manager.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/export_format_specification.h | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/export_handler.h | 5 | ||||
-rw-r--r-- | libs/ardour/ardour/types.h | 3 | ||||
-rw-r--r-- | libs/ardour/export_format_manager.cc | 6 | ||||
-rw-r--r-- | libs/ardour/export_format_specification.cc | 17 | ||||
-rw-r--r-- | libs/ardour/export_handler.cc | 54 |
9 files changed, 93 insertions, 8 deletions
diff --git a/gtk2_ardour/export_format_dialog.cc b/gtk2_ardour/export_format_dialog.cc index c2c3909b1b..f76effaebb 100644 --- a/gtk2_ardour/export_format_dialog.cc +++ b/gtk2_ardour/export_format_dialog.cc @@ -69,6 +69,7 @@ ExportFormatDialog::ExportFormatDialog (FormatPtr format, bool new_dialog) : with_cue (_("Create CUE file for disk-at-once CD/DVD creation")), with_toc (_("Create TOC file for disk-at-once CD/DVD creation")), + with_mp4chaps (_("Create chapter mark file for MP4 chapter marks")), tag_checkbox (_("Tag file with session's metadata")) { @@ -149,10 +150,12 @@ ExportFormatDialog::ExportFormatDialog (FormatPtr format, bool new_dialog) : with_cue.signal_toggled().connect (sigc::mem_fun (*this, &ExportFormatDialog::update_with_cue)); with_toc.signal_toggled().connect (sigc::mem_fun (*this, &ExportFormatDialog::update_with_toc)); + with_mp4chaps.signal_toggled().connect (sigc::mem_fun (*this, &ExportFormatDialog::update_with_mp4chaps)); command_entry.signal_changed().connect (sigc::mem_fun (*this, &ExportFormatDialog::update_command)); cue_toc_vbox.pack_start (with_cue, false, false); cue_toc_vbox.pack_start (with_toc, false, false); + cue_toc_vbox.pack_start (with_mp4chaps, false, false); /* Load state before hooking up the rest of the signals */ @@ -261,6 +264,7 @@ ExportFormatDialog::load_state (FormatPtr spec) with_cue.set_active (spec->with_cue()); with_toc.set_active (spec->with_toc()); + with_mp4chaps.set_active (spec->with_mp4chaps()); for (Gtk::ListStore::Children::iterator it = src_quality_list->children().begin(); it != src_quality_list->children().end(); ++it) { if (it->get_value (src_quality_cols.id) == spec->src_quality()) { @@ -726,6 +730,11 @@ ExportFormatDialog::update_with_toc () manager.select_with_toc (with_toc.get_active()); } +void +ExportFormatDialog::update_with_mp4chaps () +{ + manager.select_with_mp4chaps (with_mp4chaps.get_active()); +} void ExportFormatDialog::update_command () diff --git a/gtk2_ardour/export_format_dialog.h b/gtk2_ardour/export_format_dialog.h index 8a3211db23..6a25d707bf 100644 --- a/gtk2_ardour/export_format_dialog.h +++ b/gtk2_ardour/export_format_dialog.h @@ -311,11 +311,13 @@ class ExportFormatDialog : public ArdourDialog, public PBD::ScopedConnectionList Gtk::CheckButton with_cue; Gtk::CheckButton with_toc; + Gtk::CheckButton with_mp4chaps; Gtk::VBox cue_toc_vbox; void update_with_toc (); void update_with_cue (); + void update_with_mp4chaps(); void update_command (); Gtk::TreeView sample_format_view; diff --git a/libs/ardour/ardour/export_format_manager.h b/libs/ardour/ardour/export_format_manager.h index dad7d84b72..fff97299e5 100644 --- a/libs/ardour/ardour/export_format_manager.h +++ b/libs/ardour/ardour/export_format_manager.h @@ -100,6 +100,7 @@ class LIBARDOUR_API ExportFormatManager : public PBD::ScopedConnectionList void select_with_cue (bool); void select_with_toc (bool); + void select_with_mp4chaps (bool); void select_upload (bool); void set_command (std::string); void select_src_quality (ExportFormatBase::SRCQuality value); diff --git a/libs/ardour/ardour/export_format_specification.h b/libs/ardour/ardour/export_format_specification.h index 2a62d792f0..ed6e259644 100644 --- a/libs/ardour/ardour/export_format_specification.h +++ b/libs/ardour/ardour/export_format_specification.h @@ -96,6 +96,7 @@ class LIBARDOUR_API ExportFormatSpecification : public ExportFormatBase { void set_tag (bool tag_it) { _tag = tag_it; } void set_with_cue (bool yn) { _with_cue = yn; } void set_with_toc (bool yn) { _with_toc = yn; } + void set_with_mp4chaps (bool yn) { _with_mp4chaps = yn; } void set_soundcloud_upload (bool yn) { _soundcloud_upload = yn; } void set_command (std::string command) { _command = command; } @@ -127,6 +128,8 @@ class LIBARDOUR_API ExportFormatSpecification : public ExportFormatBase { float normalize_target () const { return _normalize_target; } bool with_toc() const { return _with_toc; } bool with_cue() const { return _with_cue; } + bool with_mp4chaps() const { return _with_mp4chaps; } + bool soundcloud_upload() const { return _soundcloud_upload; } std::string command() const { return _command; } @@ -178,6 +181,7 @@ class LIBARDOUR_API ExportFormatSpecification : public ExportFormatBase { float _normalize_target; bool _with_toc; bool _with_cue; + bool _with_mp4chaps; bool _soundcloud_upload; std::string _command; diff --git a/libs/ardour/ardour/export_handler.h b/libs/ardour/ardour/export_handler.h index 8336cea732..526d32b4c6 100644 --- a/libs/ardour/ardour/export_handler.h +++ b/libs/ardour/ardour/export_handler.h @@ -185,14 +185,19 @@ class LIBARDOUR_API ExportHandler : public ExportElementFactory, public sigc::tr void write_cue_header (CDMarkerStatus & status); void write_toc_header (CDMarkerStatus & status); + void write_mp4ch_header (CDMarkerStatus & status); void write_track_info_cue (CDMarkerStatus & status); void write_track_info_toc (CDMarkerStatus & status); + void write_track_info_mp4ch (CDMarkerStatus & status); void write_index_info_cue (CDMarkerStatus & status); void write_index_info_toc (CDMarkerStatus & status); + void write_index_info_mp4ch (CDMarkerStatus & status); void frames_to_cd_frames_string (char* buf, framepos_t when); + void frames_to_chapter_marks_string (char* buf, framepos_t when); + std::string toc_escape_cdtext (const std::string&); std::string toc_escape_filename (const std::string&); std::string cue_escape_cdtext (const std::string& txt); diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index 921cb3e39a..b0fb9faa9c 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -461,7 +461,8 @@ namespace ARDOUR { enum CDMarkerFormat { CDMarkerNone, CDMarkerCUE, - CDMarkerTOC + CDMarkerTOC, + MP4Chaps }; enum HeaderFormat { diff --git a/libs/ardour/export_format_manager.cc b/libs/ardour/export_format_manager.cc index 04cfa76677..f87a08686f 100644 --- a/libs/ardour/export_format_manager.cc +++ b/libs/ardour/export_format_manager.cc @@ -293,6 +293,12 @@ ExportFormatManager::select_with_toc (bool value) check_for_description_change (); } +void +ExportFormatManager::select_with_mp4chaps (bool value) +{ + current_selection->set_with_mp4chaps (value); + check_for_description_change (); +} void ExportFormatManager::set_command (std::string command) diff --git a/libs/ardour/export_format_specification.cc b/libs/ardour/export_format_specification.cc index 9a972da0bf..7e41b209a4 100644 --- a/libs/ardour/export_format_specification.cc +++ b/libs/ardour/export_format_specification.cc @@ -170,6 +170,7 @@ ExportFormatSpecification::ExportFormatSpecification (Session & s) , _normalize_target (1.0) , _with_toc (false) , _with_cue (false) + , _with_mp4chaps (false) , _soundcloud_upload (false) , _command ("") { @@ -248,6 +249,7 @@ ExportFormatSpecification::get_state () root->add_property ("id", _id.to_s()); root->add_property ("with-cue", _with_cue ? "true" : "false"); root->add_property ("with-toc", _with_toc ? "true" : "false"); + root->add_property ("with-mp4chaps", _with_mp4chaps ? "true" : "false"); root->add_property ("command", _command); node = root->add_child ("Encoding"); @@ -319,14 +321,19 @@ ExportFormatSpecification::set_state (const XMLNode & root) } else { _with_cue = false; } - + if ((prop = root.property ("with-toc"))) { _with_toc = string_is_affirmative (prop->value()); } else { _with_toc = false; } - - + + if ((prop = root.property ("with-mp4chaps"))) { + _with_mp4chaps = string_is_affirmative (prop->value()); + } else { + _with_mp4chaps = false; + } + if ((prop = root.property ("command"))) { _command = prop->value(); } else { @@ -602,6 +609,10 @@ ExportFormatSpecification::description (bool include_name) components.push_back ("CUE"); } + if (_with_mp4chaps) { + components.push_back ("MP4ch"); + } + if (!_command.empty()) { components.push_back ("+"); } diff --git a/libs/ardour/export_handler.cc b/libs/ardour/export_handler.cc index b44c46e549..33e19d663f 100644 --- a/libs/ardour/export_handler.cc +++ b/libs/ardour/export_handler.cc @@ -305,6 +305,10 @@ ExportHandler::finish_timespan () export_cd_marker_file (current_timespan, fmt, filename, CDMarkerTOC); } + if (fmt->with_mp4chaps()) { + export_cd_marker_file (current_timespan, fmt, filename, MP4Chaps); + } + if (fmt->tag()) { AudiofileTagger::tag_file(filename, *SessionMetadata::Metadata()); } @@ -403,6 +407,11 @@ ExportHandler::export_cd_marker_file (ExportTimespanPtr timespan, ExportFormatSp track_func = &ExportHandler::write_track_info_cue; index_func = &ExportHandler::write_index_info_cue; break; + case MP4Chaps: + header_func = &ExportHandler::write_mp4ch_header; + track_func = &ExportHandler::write_track_info_mp4ch; + index_func = &ExportHandler::write_index_info_mp4ch; + break; default: return; } @@ -500,17 +509,19 @@ ExportHandler::export_cd_marker_file (ExportTimespanPtr timespan, ExportFormatSp string ExportHandler::get_cd_marker_filename(std::string filename, CDMarkerFormat format) { - /* do not strip file suffix because there may be more than one format, + /* do not strip file suffix because there may be more than one format, and we do not want the CD marker file from one format to overwrite another (e.g. foo.wav.cue > foo.aiff.cue) */ switch (format) { - case CDMarkerTOC: + case CDMarkerTOC: return filename + ".toc"; - case CDMarkerCUE: + case CDMarkerCUE: return filename + ".cue"; - default: + case MP4Chaps: + return filename + ".chapters.txt"; + default: return filename + ".marker"; // Should not be reached when actually creating a file } } @@ -590,6 +601,11 @@ ExportHandler::write_toc_header (CDMarkerStatus & status) } void +ExportHandler::write_mp4ch_header (CDMarkerStatus & status) +{ +} + +void ExportHandler::write_track_info_cue (CDMarkerStatus & status) { gchar buf[18]; @@ -693,6 +709,14 @@ ExportHandler::write_track_info_toc (CDMarkerStatus & status) status.out << "START" << buf << endl; } +void ExportHandler::write_track_info_mp4ch (CDMarkerStatus & status) +{ + gchar buf[18]; + + frames_to_chapter_marks_string(buf, status.track_start_frame); + status.out << buf << " " << status.marker->name() << endl; +} + void ExportHandler::write_index_info_cue (CDMarkerStatus & status) { @@ -716,6 +740,11 @@ ExportHandler::write_index_info_toc (CDMarkerStatus & status) } void +ExportHandler::write_index_info_mp4ch (CDMarkerStatus & status) +{ +} + +void ExportHandler::frames_to_cd_frames_string (char* buf, framepos_t when) { framecnt_t remainder; @@ -730,6 +759,23 @@ ExportHandler::frames_to_cd_frames_string (char* buf, framepos_t when) sprintf (buf, " %02d:%02d:%02d", mins, secs, frames); } +void +ExportHandler::frames_to_chapter_marks_string (char* buf, framepos_t when) +{ + framecnt_t remainder; + framecnt_t fr = session.nominal_frame_rate(); + int hours, mins, secs, msecs; + + hours = when / (3600 * fr); + remainder = when - (hours * 3600 * fr); + mins = remainder / (60 * fr); + remainder -= mins * 60 * fr; + secs = remainder / fr; + remainder -= secs * fr; + msecs = (remainder * 1000) / fr; + sprintf (buf, "%02d:%02d:%02d.%03d", hours, mins, secs, msecs); +} + std::string ExportHandler::toc_escape_cdtext (const std::string& txt) { |