summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/export_format_dialog.cc9
-rw-r--r--gtk2_ardour/export_format_dialog.h2
-rw-r--r--libs/ardour/ardour/export_format_manager.h1
-rw-r--r--libs/ardour/ardour/export_format_specification.h4
-rw-r--r--libs/ardour/ardour/export_handler.h5
-rw-r--r--libs/ardour/ardour/types.h3
-rw-r--r--libs/ardour/export_format_manager.cc6
-rw-r--r--libs/ardour/export_format_specification.cc17
-rw-r--r--libs/ardour/export_handler.cc54
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)
{