X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fexport_profile_manager.cc;h=c2d6cb087a6a36ced0e2bb0719031ef7a03fc0e9;hb=b3e7c88988b6b3ade5872935b7c371cf3a6a1040;hp=7eaa7c0632a1185ff4486d16dc7d0dee747f446d;hpb=7a5a5da95367860eb6176a52786155e1d0656e77;p=ardour.git diff --git a/libs/ardour/export_profile_manager.cc b/libs/ardour/export_profile_manager.cc index 7eaa7c0632..c2d6cb087a 100644 --- a/libs/ardour/export_profile_manager.cc +++ b/libs/ardour/export_profile_manager.cc @@ -20,8 +20,13 @@ #include #include +#include + +#include +#include #include +#include #include "pbd/enumwriter.h" #include "pbd/xml++.h" @@ -29,13 +34,14 @@ #include "ardour/export_profile_manager.h" #include "ardour/export_format_specification.h" -#include "ardour/export_formats_search_path.h" +#include "ardour/search_paths.h" #include "ardour/export_timespan.h" #include "ardour/export_channel_configuration.h" #include "ardour/export_filename.h" #include "ardour/export_preset.h" #include "ardour/export_handler.h" #include "ardour/export_failed.h" +#include "ardour/directory_names.h" #include "ardour/filename_extensions.h" #include "ardour/route.h" #include "ardour/session.h" @@ -50,21 +56,37 @@ using namespace PBD; namespace ARDOUR { -ExportProfileManager::ExportProfileManager (Session & s, std::string xml_node_name) - : xml_node_name (xml_node_name) +ExportProfileManager::ExportProfileManager (Session & s, ExportType type) + : type(type) , handler (s.get_export_handler()) , session (s) - , session_range (new Location (s)) , ranges (new LocationList ()) , single_range_mode (false) , format_list (new FormatList ()) { + switch(type) { + case RegularExport: + xml_node_name = X_("ExportProfile"); + break; + case RangeExport: + xml_node_name = X_("RangeExportProfile"); + break; + case SelectionExport: + xml_node_name = X_("SelectionExportProfile"); + break; + case RegionExport: + xml_node_name = X_("RegionExportProfile"); + break; + case StemExport: + xml_node_name = X_("StemExportProfile"); + break; + } + /* Initialize path variables */ - export_config_dir = user_config_directory(); - export_config_dir /= "export"; + export_config_dir = Glib::build_filename (user_config_directory(), export_dir_name); search_path += export_formats_search_path(); @@ -72,8 +94,10 @@ ExportProfileManager::ExportProfileManager (Session & s, std::string xml_node_na /* create export config directory if necessary */ - if (!sys::exists (export_config_dir)) { - sys::create_directory (export_config_dir); + if (!Glib::file_test (export_config_dir, Glib::FILE_TEST_EXISTS)) { + if (g_mkdir_with_parents (export_config_dir.c_str(), 0755) != 0) { + error << string_compose (_("Unable to create export format directory %1: %2"), export_config_dir, g_strerror(errno)) << endmsg; + } } load_presets (); @@ -90,19 +114,22 @@ ExportProfileManager::ExportProfileManager (Session & s, std::string xml_node_na ExportProfileManager::~ExportProfileManager () { - if (single_range_mode) { return; } - - XMLNode * instant_xml (new XMLNode (xml_node_name)); - serialize_profile (*instant_xml); - session.add_instant_xml (*instant_xml, false); + XMLNode * extra_xml (new XMLNode (xml_node_name)); + serialize_profile (*extra_xml); + session.add_extra_xml (*extra_xml); } void ExportProfileManager::load_profile () { - XMLNode * instant_node = session.instant_xml (xml_node_name); - if (instant_node) { - set_state (*instant_node); + XMLNode * extra_node = session.extra_xml (xml_node_name); + /* Legacy sessions used Session instant.xml for this */ + if (!extra_node) { + extra_node = session.instant_xml (xml_node_name); + } + + if (extra_node) { + set_state (*extra_node); } else { XMLNode empty_node (xml_node_name); set_state (empty_node); @@ -134,7 +161,8 @@ ExportProfileManager::prepare_for_export () } // ...and each channel config - filename->include_channel_config = (channel_configs.size() > 1); + filename->include_channel_config = (type == StemExport) || + (channel_configs.size() > 1); for(ChannelConfigStateList::iterator cc_it = channel_configs.begin(); cc_it != channel_configs.end(); ++cc_it) { handler->add_export_config (*ts_it, (*cc_it)->config, (*format_it)->format, filename, b); } @@ -167,9 +195,9 @@ ExportProfileManager::load_preset (ExportPresetPtr preset) void ExportProfileManager::load_presets () { - vector found = find_file (string_compose (X_("*%1"),export_preset_suffix)); + vector found = find_file (string_compose (X_("*%1"),export_preset_suffix)); - for (vector::iterator it = found.begin(); it != found.end(); ++it) { + for (vector::iterator it = found.begin(); it != found.end(); ++it) { load_preset_from_disk (*it); } } @@ -178,7 +206,7 @@ std::string ExportProfileManager::preset_filename (std::string const & preset_name) { string safe_name = legalize_for_path (preset_name); - return export_config_dir.to_string() + "/" + safe_name + export_preset_suffix; + return Glib::build_filename (export_config_dir, safe_name + export_preset_suffix); } ExportPresetPtr @@ -230,7 +258,9 @@ ExportProfileManager::remove_preset () FileMap::iterator it = preset_file_map.find (current_preset->id()); if (it != preset_file_map.end()) { - sys::remove (it->second); + if (g_remove (it->second.c_str()) != 0) { + error << string_compose (_("Unable to remove export preset %1: %2"), it->second, g_strerror(errno)) << endmsg; + } preset_file_map.erase (it); } @@ -239,9 +269,9 @@ ExportProfileManager::remove_preset () } void -ExportProfileManager::load_preset_from_disk (PBD::sys::path const & path) +ExportProfileManager::load_preset_from_disk (std::string const & path) { - ExportPresetPtr preset (new ExportPreset (path.to_string(), session)); + ExportPresetPtr preset (new ExportPreset (path, session)); /* Handle id to filename mapping and don't add duplicates to list */ @@ -302,13 +332,12 @@ ExportProfileManager::serialize_local_profile (XMLNode & root) } } -std::vector +std::vector ExportProfileManager::find_file (std::string const & pattern) { - vector found; + vector found; - Glib::PatternSpec pattern_spec (pattern); - find_matching_files_in_search_path (search_path, pattern_spec, found); + find_files_matching_pattern (found, search_path, pattern); return found; } @@ -359,13 +388,16 @@ ExportProfileManager::init_timespans (XMLNodeList nodes) } if (timespans.empty()) { - TimespanStatePtr state (new TimespanState (session_range, selection_range, ranges)); + TimespanStatePtr state (new TimespanState (selection_range, ranges)); timespans.push_back (state); // Add session as default selection + Location * session_range = session.locations()->session_range_location(); + if (!session_range) { return false; } + ExportTimespanPtr timespan = handler->add_timespan(); timespan->set_name (session_range->name()); - timespan->set_range_id ("session"); + timespan->set_range_id (session_range->id().to_s()); timespan->set_range (session_range->start(), session_range->end()); state->timespans->push_back (timespan); return false; @@ -377,7 +409,7 @@ ExportProfileManager::init_timespans (XMLNodeList nodes) ExportProfileManager::TimespanStatePtr ExportProfileManager::deserialize_timespan (XMLNode & root) { - TimespanStatePtr state (new TimespanState (session_range, selection_range, ranges)); + TimespanStatePtr state (new TimespanState (selection_range, ranges)); XMLProperty const * prop; XMLNodeList spans = root.children ("Range"); @@ -387,23 +419,32 @@ ExportProfileManager::deserialize_timespan (XMLNode & root) if (!prop) { continue; } string id = prop->value(); + Location * location = 0; for (LocationList::iterator it = ranges->begin(); it != ranges->end(); ++it) { - if ((!id.compare ("session") && *it == session_range.get()) || - (!id.compare ("selection") && *it == selection_range.get()) || - (!id.compare ((*it)->id().to_s()))) { - ExportTimespanPtr timespan = handler->add_timespan(); - timespan->set_name ((*it)->name()); - timespan->set_range_id (id); - timespan->set_range ((*it)->start(), (*it)->end()); - state->timespans->push_back (timespan); + if ((id == "selection" && *it == selection_range.get()) || + (id == (*it)->id().to_s())) { + location = *it; + break; } } + + if (!location) { continue; } + + ExportTimespanPtr timespan = handler->add_timespan(); + timespan->set_name (location->name()); + timespan->set_range_id (location->id().to_s()); + timespan->set_range (location->start(), location->end()); + state->timespans->push_back (timespan); } if ((prop = root.property ("format"))) { state->time_format = (TimeFormat) string_2_enum (prop->value(), TimeFormat); } + if (state->timespans->empty()) { + return TimespanStatePtr(); + } + return state; } @@ -414,7 +455,6 @@ ExportProfileManager::serialize_timespan (TimespanStatePtr state) XMLNode * span; update_ranges (); - for (TimespanList::iterator it = state->timespans->begin(); it != state->timespans->end(); ++it) { if ((span = root.add_child ("Range"))) { span->add_property ("id", (*it)->range_id()); @@ -437,9 +477,10 @@ ExportProfileManager::update_ranges () { /* Session */ - session_range->set_name (_("Session")); - session_range->set (session.current_start_frame(), session.current_end_frame()); - ranges->push_back (session_range.get()); + Location * session_range = session.locations()->session_range_location(); + if (session_range) { + ranges->push_back (session_range); + } /* Selection */ @@ -475,6 +516,8 @@ ExportProfileManager::init_channel_configs (XMLNodeList nodes) channel_configs.push_back (config); // Add master outs as default + if (!session.master_out()) { return false; } + IO* master_out = session.master_out()->output().get(); if (!master_out) { return false; } @@ -519,7 +562,7 @@ ExportProfileManager::remove_format_state (FormatStatePtr state) } } -sys::path +std::string ExportProfileManager::save_format_to_disk (ExportFormatSpecPtr format) { // TODO filename character stripping @@ -533,19 +576,18 @@ ExportProfileManager::save_format_to_disk (ExportFormatSpecPtr format) new_name = legalize_for_path (new_name); - sys::path new_path (export_config_dir); - new_path /= new_name; + std::string new_path = Glib::build_filename (export_config_dir, new_name); /* Check if format is on disk already */ FileMap::iterator it; if ((it = format_file_map.find (format->id())) != format_file_map.end()) { /* Check if config is not in user config dir */ - if (it->second.branch_path().to_string().compare (export_config_dir.to_string())) { + if (Glib::path_get_dirname (it->second) != export_config_dir) { /* Write new file */ - XMLTree tree (new_path.to_string()); + XMLTree tree (new_path); tree.set_root (&format->get_state()); tree.write(); @@ -553,12 +595,14 @@ ExportProfileManager::save_format_to_disk (ExportFormatSpecPtr format) /* Update file and rename if necessary */ - XMLTree tree (it->second.to_string()); + XMLTree tree (it->second); tree.set_root (&format->get_state()); tree.write(); - if (new_name.compare (it->second.leaf())) { - sys::rename (it->second, new_path); + if (new_name != Glib::path_get_basename (it->second)) { + if (g_rename (it->second.c_str(), new_path.c_str()) != 0) { + error << string_compose (_("Unable to rename export format %1 to %2: %3"), it->second, new_path, g_strerror(errno)) << endmsg; + }; } } @@ -567,7 +611,7 @@ ExportProfileManager::save_format_to_disk (ExportFormatSpecPtr format) } else { /* Write new file */ - XMLTree tree (new_path.to_string()); + XMLTree tree (new_path); tree.set_root (&format->get_state()); tree.write(); } @@ -588,7 +632,10 @@ ExportProfileManager::remove_format_profile (ExportFormatSpecPtr format) FileMap::iterator it = format_file_map.find (format->id()); if (it != format_file_map.end()) { - sys::remove (it->second); + if (g_remove (it->second.c_str()) != 0) { + error << string_compose (_("Unable to remove export profile %1: %2"), it->second, g_strerror(errno)) << endmsg; + return; + } format_file_map.erase (it); } @@ -601,12 +648,13 @@ ExportProfileManager::get_new_format (ExportFormatSpecPtr original) ExportFormatSpecPtr format; if (original) { format.reset (new ExportFormatSpecification (*original)); + std::cerr << "After new format created from original, format has id [" << format->id().to_s() << ']' << std::endl; } else { format = handler->add_format(); - format->set_name ("empty format"); + format->set_name (_("empty format")); } - sys::path path = save_format_to_disk (format); + std::string path = save_format_to_disk (format); FilePair pair (format->id(), path); format_file_map.insert (pair); @@ -642,7 +690,7 @@ ExportProfileManager::FormatStatePtr ExportProfileManager::deserialize_format (XMLNode & root) { XMLProperty * prop; - UUID id; + PBD::UUID id; if ((prop = root.property ("id"))) { id = prop->value(); @@ -671,18 +719,30 @@ ExportProfileManager::serialize_format (FormatStatePtr state) void ExportProfileManager::load_formats () { - vector found = find_file (string_compose ("*%1", export_format_suffix)); + vector found = find_file (string_compose ("*%1", export_format_suffix)); - for (vector::iterator it = found.begin(); it != found.end(); ++it) { + for (vector::iterator it = found.begin(); it != found.end(); ++it) { load_format_from_disk (*it); } } void -ExportProfileManager::load_format_from_disk (PBD::sys::path const & path) +ExportProfileManager::load_format_from_disk (std::string const & path) { - XMLTree const tree (path.to_string()); - ExportFormatSpecPtr format = handler->add_format (*tree.root()); + XMLTree tree; + + if (!tree.read (path)) { + error << string_compose (_("Cannot load export format from %1"), path) << endmsg; + return; + } + + XMLNode* root = tree.root(); + if (!root) { + error << string_compose (_("Cannot export format read from %1"), path) << endmsg; + return; + } + + ExportFormatSpecPtr format = handler->add_format (*root); /* Handle id to filename mapping and don't add duplicates to list */ @@ -713,6 +773,21 @@ ExportProfileManager::remove_filename_state (FilenameStatePtr state) } } +std::string +ExportProfileManager::get_sample_filename_for_format (ExportFilenamePtr filename, ExportFormatSpecPtr format) +{ + assert (format); + + if (channel_configs.empty()) { return ""; } + + std::list filenames; + build_filenames (filenames, filename, timespans.front()->timespans, + channel_configs.front()->config, format); + + if (filenames.empty()) { return ""; } + return filenames.front(); +} + bool ExportProfileManager::init_filenames (XMLNodeList nodes) { @@ -817,27 +892,28 @@ ExportProfileManager::check_config (boost::shared_ptr warnings, // filename->include_timespan = (timespans->size() > 1); Disabled for now... - for (std::list::iterator timespan_it = timespans->begin(); timespan_it != timespans->end(); ++timespan_it) { - filename->set_timespan (*timespan_it); + std::list paths; + build_filenames(paths, filename, timespans, channel_config, format); - if (channel_config->get_split()) { - filename->include_channel = true; + for (std::list::const_iterator path_it = paths.begin(); path_it != paths.end(); ++path_it) { - for (uint32_t chan = 1; chan <= channel_config->get_n_chans(); ++chan) { - filename->set_channel (chan); + string path = *path_it; - string path = filename->get_path (format); + if (Glib::file_test (path, Glib::FILE_TEST_EXISTS)) { + warnings->conflicting_filenames.push_back (path); + } - if (sys::exists (sys::path (path))) { - warnings->conflicting_filenames.push_back (path); - } + if (format->with_toc()) { + string marker_file = handler->get_cd_marker_filename(path, CDMarkerTOC); + if (Glib::file_test (marker_file, Glib::FILE_TEST_EXISTS)) { + warnings->conflicting_filenames.push_back (marker_file); } + } - } else { - string path = filename->get_path (format); - - if (sys::exists (sys::path (path))) { - warnings->conflicting_filenames.push_back (path); + if (format->with_cue()) { + string marker_file = handler->get_cd_marker_filename(path, CDMarkerCUE); + if (Glib::file_test (marker_file, Glib::FILE_TEST_EXISTS)) { + warnings->conflicting_filenames.push_back (marker_file); } } } @@ -866,4 +942,28 @@ ExportProfileManager::check_sndfile_format (ExportFormatSpecPtr format, unsigned return (sf_format_check (&sf_info) == SF_TRUE ? true : false); } +void +ExportProfileManager::build_filenames(std::list & result, ExportFilenamePtr filename, + TimespanListPtr timespans, ExportChannelConfigPtr channel_config, + ExportFormatSpecPtr format) +{ + for (std::list::iterator timespan_it = timespans->begin(); + timespan_it != timespans->end(); ++timespan_it) { + filename->set_timespan (*timespan_it); + + if (channel_config->get_split()) { + filename->include_channel = true; + + for (uint32_t chan = 1; chan <= channel_config->get_n_chans(); ++chan) { + filename->set_channel (chan); + result.push_back(filename->get_path (format)); + } + + } else { + filename->include_channel = false; + result.push_back(filename->get_path (format)); + } + } +} + }; // namespace ARDOUR