X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fexport_profile_manager.cc;h=6c4f829bb89fca383e02a54fc106cd93fac7a9ec;hb=80d9eaf96cd00f3084d18c32b4b31aabda0e6737;hp=40160d1ada4bea8b4815c1ac1135e00c94b322a7;hpb=b6642d14ca64153b5731d1a3a79e4d00060541ca;p=ardour.git diff --git a/libs/ardour/export_profile_manager.cc b/libs/ardour/export_profile_manager.cc index 40160d1ada..6c4f829bb8 100644 --- a/libs/ardour/export_profile_manager.cc +++ b/libs/ardour/export_profile_manager.cc @@ -21,7 +21,11 @@ #include #include +#include +#include + #include +#include #include "pbd/enumwriter.h" #include "pbd/xml++.h" @@ -29,12 +33,14 @@ #include "ardour/export_profile_manager.h" #include "ardour/export_format_specification.h" +#include "ardour/export_formats_search_path.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" @@ -49,30 +55,31 @@ using namespace PBD; namespace ARDOUR { -ExportProfileManager::ExportProfileManager (Session & s) : - handler (s.get_export_handler()), - session (s), +ExportProfileManager::ExportProfileManager (Session & s, std::string xml_node_name) + : xml_node_name (xml_node_name) + , handler (s.get_export_handler()) + , session (s) - session_range (new Location (s)), - ranges (new LocationList ()), - single_range_mode (false), + , session_range (new Location (s)) + , ranges (new LocationList ()) + , single_range_mode (false) - format_list (new FormatList ()) + , format_list (new FormatList ()) { - /* Initialize path variables */ - export_config_dir = user_config_directory(); - export_config_dir /= "export"; - search_path += export_config_dir; + export_config_dir = Glib::build_filename (user_config_directory(), export_dir_name); + + search_path += export_formats_search_path(); - search_path += ardour_search_path().add_subdirectory_to_paths("export"); - search_path += system_config_search_path().add_subdirectory_to_paths("export");; + info << string_compose (_("Searching for export formats in %1"), search_path.to_string()) << endmsg; /* 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 (); @@ -89,9 +96,7 @@ ExportProfileManager::ExportProfileManager (Session & s) : ExportProfileManager::~ExportProfileManager () { - if (single_range_mode) { return; } - - XMLNode * instant_xml (new XMLNode ("ExportProfile")); + XMLNode * instant_xml (new XMLNode (xml_node_name)); serialize_profile (*instant_xml); session.add_instant_xml (*instant_xml, false); } @@ -99,11 +104,11 @@ ExportProfileManager::~ExportProfileManager () void ExportProfileManager::load_profile () { - XMLNode * instant_node = session.instant_xml ("ExportProfile"); + XMLNode * instant_node = session.instant_xml (xml_node_name); if (instant_node) { set_state (*instant_node); } else { - XMLNode empty_node ("ExportProfile"); + XMLNode empty_node (xml_node_name); set_state (empty_node); } } @@ -111,17 +116,19 @@ ExportProfileManager::load_profile () void ExportProfileManager::prepare_for_export () { - ChannelConfigPtr channel_config = channel_configs.front()->config; TimespanListPtr ts_list = timespans.front()->timespans; FormatStateList::const_iterator format_it; FilenameStateList::const_iterator filename_it; + // For each timespan for (TimespanList::iterator ts_it = ts_list->begin(); ts_it != ts_list->end(); ++ts_it) { + // ..., each format-filename pair for (format_it = formats.begin(), filename_it = filenames.begin(); format_it != formats.end() && filename_it != filenames.end(); ++format_it, ++filename_it) { + ExportFilenamePtr filename = (*filename_it)->filename; // filename->include_timespan = (ts_list->size() > 1); Disabled for now... boost::shared_ptr b; @@ -129,14 +136,18 @@ ExportProfileManager::prepare_for_export () b.reset (new BroadcastInfo); b->set_from_session (session, (*ts_it)->get_start()); } - - handler->add_export_config (*ts_it, channel_config, (*format_it)->format, (*filename_it)->filename, b); + + // ...and each channel config + filename->include_channel_config = (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); + } } } } bool -ExportProfileManager::load_preset (PresetPtr preset) +ExportProfileManager::load_preset (ExportPresetPtr preset) { bool ok = true; @@ -160,17 +171,34 @@ ExportProfileManager::load_preset (PresetPtr 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); } } -ExportProfileManager::PresetPtr +std::string +ExportProfileManager::preset_filename (std::string const & preset_name) +{ + string safe_name = legalize_for_path (preset_name); + return Glib::build_filename (export_config_dir, safe_name + export_preset_suffix); +} + +ExportPresetPtr +ExportProfileManager::new_preset (string const & name) +{ + // Generate new ID and do regular save + string filename = preset_filename (name); + current_preset.reset (new ExportPreset (filename, session)); + preset_list.push_back (current_preset); + return save_preset (name); +} + +ExportPresetPtr ExportProfileManager::save_preset (string const & name) { - string filename = export_config_dir.to_string() + "/" + name + export_preset_suffix; + string filename = preset_filename (name); if (!current_preset) { current_preset.reset (new ExportPreset (filename, session)); @@ -206,7 +234,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); } @@ -215,9 +245,9 @@ ExportProfileManager::remove_preset () } void -ExportProfileManager::load_preset_from_disk (PBD::sys::path const & path) +ExportProfileManager::load_preset_from_disk (std::string const & path) { - PresetPtr 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 */ @@ -278,10 +308,10 @@ 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); @@ -290,7 +320,7 @@ ExportProfileManager::find_file (std::string const & pattern) } void -ExportProfileManager::set_selection_range (nframes_t start, nframes_t end) +ExportProfileManager::set_selection_range (framepos_t start, framepos_t end) { if (start || end) { @@ -307,7 +337,7 @@ ExportProfileManager::set_selection_range (nframes_t start, nframes_t end) } std::string -ExportProfileManager::set_single_range (nframes_t start, nframes_t end, Glib::ustring name) +ExportProfileManager::set_single_range (framepos_t start, framepos_t end, string name) { single_range_mode = true; @@ -337,9 +367,9 @@ ExportProfileManager::init_timespans (XMLNodeList nodes) if (timespans.empty()) { TimespanStatePtr state (new TimespanState (session_range, selection_range, ranges)); timespans.push_back (state); - + // Add session as default selection - TimespanPtr timespan = handler->add_timespan(); + ExportTimespanPtr timespan = handler->add_timespan(); timespan->set_name (session_range->name()); timespan->set_range_id ("session"); timespan->set_range (session_range->start(), session_range->end()); @@ -361,13 +391,13 @@ ExportProfileManager::deserialize_timespan (XMLNode & root) prop = (*node_it)->property ("id"); if (!prop) { continue; } - ustring id = prop->value(); + string id = prop->value(); 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()))) { - TimespanPtr timespan = handler->add_timespan(); + ExportTimespanPtr timespan = handler->add_timespan(); timespan->set_name ((*it)->name()); timespan->set_range_id (id); timespan->set_range ((*it)->start(), (*it)->end()); @@ -433,6 +463,14 @@ ExportProfileManager::update_ranges () { } } +ExportProfileManager::ChannelConfigStatePtr +ExportProfileManager::add_channel_config () +{ + ChannelConfigStatePtr ptr(new ChannelConfigState(handler->add_channel_config())); + channel_configs.push_back(ptr); + return ptr; +} + bool ExportProfileManager::init_channel_configs (XMLNodeList nodes) { @@ -441,15 +479,15 @@ ExportProfileManager::init_channel_configs (XMLNodeList nodes) if (nodes.empty()) { ChannelConfigStatePtr config (new ChannelConfigState (handler->add_channel_config())); channel_configs.push_back (config); - + // Add master outs as default IO* master_out = session.master_out()->output().get(); if (!master_out) { return false; } - + for (uint32_t n = 0; n < master_out->n_ports().n_audio(); ++n) { PortExportChannel * channel = new PortExportChannel (); channel->add_port (master_out->audio (n)); - + ExportChannelPtr chan_ptr (channel); config->config->register_channel (chan_ptr); } @@ -487,29 +525,32 @@ ExportProfileManager::remove_format_state (FormatStatePtr state) } } -sys::path -ExportProfileManager::save_format_to_disk (FormatPtr format) +std::string +ExportProfileManager::save_format_to_disk (ExportFormatSpecPtr format) { // TODO filename character stripping /* Get filename for file */ - Glib::ustring new_name = format->name(); + string new_name = format->name(); new_name += export_format_suffix; - sys::path new_path (export_config_dir); - new_path /= new_name; + /* make sure its legal for the filesystem */ + + new_name = legalize_for_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(); @@ -517,12 +558,14 @@ ExportProfileManager::save_format_to_disk (FormatPtr 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; + }; } } @@ -531,7 +574,7 @@ ExportProfileManager::save_format_to_disk (FormatPtr format) } else { /* Write new file */ - XMLTree tree (new_path.to_string()); + XMLTree tree (new_path); tree.set_root (&format->get_state()); tree.write(); } @@ -541,7 +584,7 @@ ExportProfileManager::save_format_to_disk (FormatPtr format) } void -ExportProfileManager::remove_format_profile (FormatPtr format) +ExportProfileManager::remove_format_profile (ExportFormatSpecPtr format) { for (FormatList::iterator it = format_list->begin(); it != format_list->end(); ++it) { if (*it == format) { @@ -552,17 +595,20 @@ ExportProfileManager::remove_format_profile (FormatPtr 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); } FormatListChanged (); } -ExportProfileManager::FormatPtr -ExportProfileManager::get_new_format (FormatPtr original) +ExportFormatSpecPtr +ExportProfileManager::get_new_format (ExportFormatSpecPtr original) { - FormatPtr format; + ExportFormatSpecPtr format; if (original) { format.reset (new ExportFormatSpecification (*original)); } else { @@ -570,7 +616,7 @@ ExportProfileManager::get_new_format (FormatPtr original) 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); @@ -594,7 +640,7 @@ ExportProfileManager::init_formats (XMLNodeList nodes) } if (formats.empty ()) { - FormatStatePtr format (new FormatState (format_list, FormatPtr ())); + FormatStatePtr format (new FormatState (format_list, ExportFormatSpecPtr ())); formats.push_back (format); return false; } @@ -635,18 +681,18 @@ 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()); - FormatPtr format = handler->add_format (*tree.root()); + XMLTree const tree (path); + ExportFormatSpecPtr format = handler->add_format (*tree.root()); /* Handle id to filename mapping and don't add duplicates to list */ @@ -677,13 +723,28 @@ 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) { filenames.clear (); for (XMLNodeList::const_iterator it = nodes.begin(); it != nodes.end(); ++it) { - FilenamePtr filename = handler->add_filename(); + ExportFilenamePtr filename = handler->add_filename(); filename->set_state (**it); filenames.push_back (FilenameStatePtr (new FilenameState (filename))); } @@ -702,13 +763,21 @@ ExportProfileManager::get_warnings () { boost::shared_ptr warnings (new Warnings ()); - ChannelConfigStatePtr channel_config_state = channel_configs.front(); + ChannelConfigStatePtr channel_config_state; + if (!channel_configs.empty ()) { + channel_config_state = channel_configs.front(); + } + TimespanStatePtr timespan_state = timespans.front(); /*** Check "global" config ***/ TimespanListPtr timespans = timespan_state->timespans; - ChannelConfigPtr channel_config = channel_config_state->config; + + ExportChannelConfigPtr channel_config; + if (channel_config_state) { + channel_config = channel_config_state->config; + } /* Check Timespans are not empty */ @@ -716,22 +785,27 @@ ExportProfileManager::get_warnings () warnings->errors.push_back (_("No timespan has been selected!")); } - /* Check channel config ports */ - - if (!channel_config->all_channels_have_ports ()) { - warnings->warnings.push_back (_("Some channels are empty")); + if (channel_config_state == 0) { + warnings->errors.push_back (_("No channels have been selected!")); + } else { + /* Check channel config ports */ + if (!channel_config->all_channels_have_ports ()) { + warnings->warnings.push_back (_("Some channels are empty")); + } } /*** Check files ***/ - FormatStateList::const_iterator format_it; - FilenameStateList::const_iterator filename_it; - for (format_it = formats.begin(), filename_it = filenames.begin(); - format_it != formats.end() && filename_it != filenames.end(); - ++format_it, ++filename_it) { + if (channel_config_state) { + FormatStateList::const_iterator format_it; + FilenameStateList::const_iterator filename_it; + for (format_it = formats.begin(), filename_it = filenames.begin(); + format_it != formats.end() && filename_it != filenames.end(); + ++format_it, ++filename_it) { check_config (warnings, timespan_state, channel_config_state, *format_it, *filename_it); + } } - + return warnings; } @@ -743,9 +817,9 @@ ExportProfileManager::check_config (boost::shared_ptr warnings, FilenameStatePtr filename_state) { TimespanListPtr timespans = timespan_state->timespans; - ChannelConfigPtr channel_config = channel_config_state->config; - FormatPtr format = format_state->format; - FilenamePtr filename = filename_state->filename; + ExportChannelConfigPtr channel_config = channel_config_state->config; + ExportFormatSpecPtr format = format_state->format; + ExportFilenamePtr filename = filename_state->filename; /* Check format and maximum channel count */ if (!format || !format->type()) { @@ -768,34 +842,35 @@ 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; - Glib::ustring 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 { - Glib::ustring 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); } } } } bool -ExportProfileManager::check_format (FormatPtr format, uint32_t channels) +ExportProfileManager::check_format (ExportFormatSpecPtr format, uint32_t channels) { switch (format->type()) { case ExportFormatBase::T_Sndfile: @@ -807,7 +882,7 @@ ExportProfileManager::check_format (FormatPtr format, uint32_t channels) } bool -ExportProfileManager::check_sndfile_format (FormatPtr format, unsigned int channels) +ExportProfileManager::check_sndfile_format (ExportFormatSpecPtr format, unsigned int channels) { SF_INFO sf_info; sf_info.channels = channels; @@ -817,4 +892,28 @@ ExportProfileManager::check_sndfile_format (FormatPtr format, unsigned int chann 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