diff options
Diffstat (limited to 'libs/ardour')
-rw-r--r-- | libs/ardour/SConscript | 6 | ||||
-rw-r--r-- | libs/ardour/ardour/audio_playlist_importer.h | 87 | ||||
-rw-r--r-- | libs/ardour/ardour/audio_region_importer.h | 107 | ||||
-rw-r--r-- | libs/ardour/ardour/element_import_handler.h | 110 | ||||
-rw-r--r-- | libs/ardour/ardour/element_importer.h | 122 | ||||
-rw-r--r-- | libs/ardour/ardour/location.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/location_importer.h | 63 | ||||
-rw-r--r-- | libs/ardour/ardour/playlist_factory.h | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/tempo_map_importer.h | 60 | ||||
-rw-r--r-- | libs/ardour/audio_playlist_importer.cc | 221 | ||||
-rw-r--r-- | libs/ardour/audio_region_importer.cc | 398 | ||||
-rw-r--r-- | libs/ardour/element_import_handler.cc | 55 | ||||
-rw-r--r-- | libs/ardour/element_importer.cc | 84 | ||||
-rw-r--r-- | libs/ardour/location.cc | 8 | ||||
-rw-r--r-- | libs/ardour/location_importer.cc | 195 | ||||
-rw-r--r-- | libs/ardour/playlist_factory.cc | 10 | ||||
-rw-r--r-- | libs/ardour/session.cc | 22 | ||||
-rw-r--r-- | libs/ardour/tempo_map_importer.cc | 108 |
19 files changed, 1655 insertions, 9 deletions
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index 352d1b26f6..156daf2bc0 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -36,6 +36,7 @@ audio_buffer.cc audio_diskstream.cc audio_library.cc audio_playlist.cc +audio_playlist_importer.cc audio_port.cc audio_track.cc audioanalyser.cc @@ -43,6 +44,7 @@ audioengine.cc audiofile_tagger.cc audiofilesource.cc audioregion.cc +audio_region_importer.cc audiosource.cc auditioner.cc auto_bundle.cc @@ -64,6 +66,8 @@ cycle_timer.cc default_click.cc directory_names.cc diskstream.cc +element_importer.cc +element_import_handler.cc enums.cc event_type_map.cc export_channel_configuration.cc @@ -96,6 +100,7 @@ jack_port.cc jack_slave.cc ladspa_plugin.cc location.cc +location_importer.cc meter.cc midi_buffer.cc midi_clock_slave.cc @@ -159,6 +164,7 @@ svn_revision.cc tape_file_matcher.cc template_utils.cc tempo.cc +tempo_map_importer.cc track.cc transient_detector.cc user_bundle.cc diff --git a/libs/ardour/ardour/audio_playlist_importer.h b/libs/ardour/ardour/audio_playlist_importer.h new file mode 100644 index 0000000000..a3e72f18c8 --- /dev/null +++ b/libs/ardour/ardour/audio_playlist_importer.h @@ -0,0 +1,87 @@ +/* + Copyright (C) 2008 Paul Davis + Author: Sakari Bergen + + 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. + +*/ + +#ifndef __ardour_audio_playlist_importer_h__ +#define __ardour_audio_playlist_importer_h__ + +#include <list> + +#include <boost/shared_ptr.hpp> + +#include <pbd/xml++.h> +#include <pbd/id.h> + +#include <ardour/element_importer.h> +#include <ardour/element_import_handler.h> +#include <ardour/types.h> + +#include "i18n.h" + +namespace ARDOUR { + +class AudioRegionImportHandler; +class AudioRegionImporter; + +class AudioPlaylistImportHandler : public ElementImportHandler +{ + public: + AudioPlaylistImportHandler (XMLTree const & source, Session & session, AudioRegionImportHandler & region_handler, const char * nodename = "Playlists"); + virtual ~AudioPlaylistImportHandler () {} + virtual string get_info () const; + + void get_regions (XMLNode const & node, ElementList & list); + void update_region_id (XMLProperty* id_prop); + + protected: + AudioRegionImportHandler & region_handler; +}; + +class UnusedAudioPlaylistImportHandler : public AudioPlaylistImportHandler +{ + public: + UnusedAudioPlaylistImportHandler (XMLTree const & source, Session & session, AudioRegionImportHandler & region_handler) : + AudioPlaylistImportHandler (source, session, region_handler, X_("UnusedPlaylists")) { } + string get_info () const { return _("Audio Playlists (unused)"); } +}; + +class AudioPlaylistImporter : public ElementImporter +{ + public: + AudioPlaylistImporter (XMLTree const & source, Session & session, AudioPlaylistImportHandler & handler, XMLNode const & node); + + string get_info () const; + bool prepare_move (); + void cancel_move (); + void move (); + + void set_diskstream (PBD::ID const & id); + + private: + typedef std::list<boost::shared_ptr<AudioRegionImporter> > RegionList; + + AudioPlaylistImportHandler & handler; + XMLNode xml_playlist; + PBD::ID diskstream_id; + RegionList regions; +}; + +} // namespace ARDOUR + +#endif diff --git a/libs/ardour/ardour/audio_region_importer.h b/libs/ardour/ardour/audio_region_importer.h new file mode 100644 index 0000000000..a2205390ab --- /dev/null +++ b/libs/ardour/ardour/audio_region_importer.h @@ -0,0 +1,107 @@ +/* + Copyright (C) 2008 Paul Davis + Author: Sakari Bergen + + 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. + +*/ + +#ifndef __ardour_audio_region_importer_h__ +#define __ardour_audio_region_importer_h__ + +#include <list> +#include <map> +#include <utility> + +#include <boost/shared_ptr.hpp> + +#include <pbd/xml++.h> +#include <pbd/id.h> +#include <pbd/filesystem.h> +#include <ardour/types.h> +#include <ardour/element_importer.h> +#include <ardour/element_import_handler.h> + +namespace ARDOUR { + +class Region; + +class AudioRegionImportHandler : public ElementImportHandler +{ + public: + // Inerface implementation + AudioRegionImportHandler (XMLTree const & source, Session & session); + string get_info () const; + + void create_regions_from_children (XMLNode const & node, ElementList & list); + + // Source management + bool check_source (string const & filename) const; + void add_source (string const & filename, boost::shared_ptr<Source> const & source); + boost::shared_ptr<Source> const & get_source (string const & filename) const; + + // Id management + void register_id (PBD::ID & old_id, PBD::ID & new_id); + PBD::ID const & get_new_id (PBD::ID & old_id) const; + + private: + // Source management + typedef std::map<string, boost::shared_ptr<Source> > SourceMap; + typedef std::pair<string, boost::shared_ptr<Source> > SourcePair; + SourceMap sources; + + // Id management + typedef std::map<PBD::ID, PBD::ID> IdMap; + typedef std::pair<PBD::ID, PBD::ID> IdPair; + IdMap id_map; +}; + +class AudioRegionImporter : public ElementImporter +{ + public: + AudioRegionImporter (XMLTree const & source, Session & session, AudioRegionImportHandler & handler, XMLNode const & node); + + // Interface implementation + string get_info () const; + bool prepare_move (); + void cancel_move (); + void move (); + + // other stuff + void add_sources_to_session (); + XMLNode const & get_xml (); + + private: + + XMLNode xml_region; + AudioRegionImportHandler & handler; + PBD::ID old_id; + PBD::ID id; + std::list<string> filenames; + + bool parse_xml_region (); + bool parse_source_xml (); + PBD::sys::path get_sound_dir (XMLTree const & tree); + + void prepare_region (); + void prepare_sources (); + std::vector<boost::shared_ptr<Region> > region; + bool region_prepared; + bool sources_prepared; +}; + +} // namespace ARDOUR + +#endif diff --git a/libs/ardour/ardour/element_import_handler.h b/libs/ardour/ardour/element_import_handler.h new file mode 100644 index 0000000000..9393c31559 --- /dev/null +++ b/libs/ardour/ardour/element_import_handler.h @@ -0,0 +1,110 @@ +/* + Copyright (C) 2008 Paul Davis + Author: Sakari Bergen + + 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. + +*/ + +#ifndef __ardour_element_import_handler_h__ +#define __ardour_element_import_handler_h__ + +#include <string> +#include <list> + +#include <boost/shared_ptr.hpp> + +using std::string; +class XMLTree; + +namespace ARDOUR { + +class Session; +class ElementImporter; + +/// Virtual interface class for element import handlers +class ElementImportHandler +{ + public: + typedef boost::shared_ptr<ElementImporter> ElementPtr; + typedef std::list<ElementPtr> ElementList; + + /** ElementImportHandler constructor + * The constructor should find everything from the XML Tree it can handle + * and create respective Elements stored in elements. + * + * @param source XML tree to be parsed + * @see elements + */ + ElementImportHandler (XMLTree const & source, ARDOUR::Session & session) : + source (source), session (session) { } + + virtual ~ElementImportHandler (); + + /** Gets a textual representation of the element type + * @return textual representation of element type + */ + virtual string get_info () const = 0; + + /// Elements this handler handles + ElementList elements; + + /* For checking duplicates names against queued elements */ + + /** Checks whether or not an element with some name is queued or not + * @param name name to check + * @return true if name is not used + */ + bool check_name (const string & name) const; + + /// Adds name to the list of used names + void add_name (string name); + + /// Removes name from the list of used names + void remove_name (const string & name); + + /// Checks wheter or not all elements can be imported cleanly + static bool dirty () { return _dirty; } + + /// Sets handler dirty + static void set_dirty () { _dirty = true; } + + /// Checks wheter or not all elements were imported cleanly + static bool errors () { return _errors; } + + /// Sets handler dirty + static void set_errors () { _errors = true; } + + protected: + /// Source session XML tree + XMLTree const & source; + + /// Destination session + ARDOUR::Session & session; + + /// Session XML readability + static bool _dirty; + + /// Errors post initialization + static bool _errors; + + private: + /// List of names for duplicate checking + std::list<string> names; +}; + +} // namespace ARDOUR + +#endif diff --git a/libs/ardour/ardour/element_importer.h b/libs/ardour/ardour/element_importer.h new file mode 100644 index 0000000000..34ab0a7cc6 --- /dev/null +++ b/libs/ardour/ardour/element_importer.h @@ -0,0 +1,122 @@ +/* + Copyright (C) 2008 Paul Davis + Author: Sakari Bergen + + 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. + +*/ + +#ifndef __ardour_element_importer_h__ +#define __ardour_element_importer_h__ + +#include <string> +#include <utility> + +#include <sigc++/signal.h> + +#include <ardour/types.h> + +using std::string; + +class XMLTree; +namespace ARDOUR { + +class Session; + +/// Virtual interface class for element importers +class ElementImporter +{ + public: + + ElementImporter (XMLTree const & source, ARDOUR::Session & session); + virtual ~ElementImporter () {}; + + /** Returns the element name + * @return the name of the element + */ + virtual string get_name () const { return name; }; + + /** Gets a textual representation of the element + * @return a textual representation on this specific element + */ + virtual string get_info () const = 0; + + /** Prepares to move element + * Should take care of all tasks that need to be done + * before moving the element. This includes prompting + * the user for more information if necessary. + * + * If the element can be moved, queued should be set to true. + * + * @return whther or not the element could be prepared for moving + */ + virtual bool prepare_move () = 0; + + /** Cancels moving of element + * If the element has been set to be moved, this cancels the move. + * queued should be set to false. + */ + virtual void cancel_move () = 0; + + /** Moves the element to the taget session + * In addition to actually adding the element to the session + * changing ids, renaming files etc. should be taken care of. + */ + virtual void move () = 0; + + /// Check if element is broken. Cannot be moved if broken. + bool broken () { return _broken; } + + /// Signal that requests for anew name + static sigc::signal <std::pair<bool, string>, string, string> Rename; + + /// Signal for ok/cancel prompting + static sigc::signal <bool, string> Prompt; + + protected: + /// Source XML-tree + XMLTree const & source; + + /// Target session + ARDOUR::Session & session; + + /// Ture if the element has been prepared and queued for importing + bool queued; + + /// Name of element + string name; + + /// The sample rate of the session from which we are importing + nframes_t sample_rate; + + /// Converts smpte time to a string + string smpte_to_string(SMPTE::Time & time) const; + + /// Converts samples so that times match the sessions sample rate + nframes_t rate_convert_samples (nframes_t samples) const; + + /// Converts samples so that times match the sessions sample rate (for straight use in XML) + string rate_convert_samples (string const & samples) const; + + /// Set element broken + void set_broken () { _broken = true; } + + private: + bool _broken; +}; + +} // namespace ARDOUR + +#endif diff --git a/libs/ardour/ardour/location.h b/libs/ardour/ardour/location.h index d5b672a89d..ae0ec5acd8 100644 --- a/libs/ardour/ardour/location.h +++ b/libs/ardour/ardour/location.h @@ -99,6 +99,7 @@ class Location : public PBD::StatefulDestructible void set_cd (bool yn, void *src); void set_is_end (bool yn, void* src); void set_is_start (bool yn, void* src); + void set_is_range_marker (bool yn, void* src); bool is_auto_punch () const { return _flags & IsAutoPunch; } bool is_auto_loop () const { return _flags & IsAutoLoop; } diff --git a/libs/ardour/ardour/location_importer.h b/libs/ardour/ardour/location_importer.h new file mode 100644 index 0000000000..7066151383 --- /dev/null +++ b/libs/ardour/ardour/location_importer.h @@ -0,0 +1,63 @@ +/* + Copyright (C) 2008 Paul Davis + Author: Sakari Bergen + + 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. + +*/ + +#ifndef __ardour_location_importer_h__ +#define __ardour_location_importer_h__ + +#include <ardour/element_importer.h> +#include <ardour/element_import_handler.h> + +#include <boost/shared_ptr.hpp> + +#include <pbd/xml++.h> +#include <ardour/location.h> +#include <ardour/types.h> + +namespace ARDOUR { + +class LocationImportHandler : public ElementImportHandler +{ + public: + LocationImportHandler (XMLTree const & source, Session & session); + string get_info () const; +}; + +class LocationImporter : public ElementImporter +{ + public: + LocationImporter (XMLTree const & source, Session & session, LocationImportHandler & handler, XMLNode const & node); + ~LocationImporter (); + + string get_info () const; + bool prepare_move (); + void cancel_move (); + void move (); + + private: + LocationImportHandler & handler; + XMLNode xml_location; + Location * location; + + void parse_xml (); +}; + +} // namespace ARDOUR + +#endif diff --git a/libs/ardour/ardour/playlist_factory.h b/libs/ardour/ardour/playlist_factory.h index a28e2611d9..239fa49a04 100644 --- a/libs/ardour/ardour/playlist_factory.h +++ b/libs/ardour/ardour/playlist_factory.h @@ -31,9 +31,9 @@ class Session; class PlaylistFactory { public: - static sigc::signal<void,boost::shared_ptr<Playlist> > PlaylistCreated; + static sigc::signal<void,boost::shared_ptr<Playlist>, bool> PlaylistCreated; - static boost::shared_ptr<Playlist> create (Session&, const XMLNode&, bool hidden = false); + static boost::shared_ptr<Playlist> create (Session&, const XMLNode&, bool hidden = false, bool unused = false); static boost::shared_ptr<Playlist> create (DataType type, Session&, string name, bool hidden = false); static boost::shared_ptr<Playlist> create (boost::shared_ptr<const Playlist>, string name, bool hidden = false); static boost::shared_ptr<Playlist> create (boost::shared_ptr<const Playlist>, nframes_t start, nframes_t cnt, string name, bool hidden = false); diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index fa074071c5..83e3200224 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -685,7 +685,8 @@ class Session : public PBD::StatefulDestructible /* playlist management */ boost::shared_ptr<Playlist> playlist_by_name (string name); - void add_playlist (boost::shared_ptr<Playlist>); + void unassigned_playlists (std::list<boost::shared_ptr<Playlist> > & list); + void add_playlist (boost::shared_ptr<Playlist>, bool unused = false); sigc::signal<void,boost::shared_ptr<Playlist> > PlaylistAdded; sigc::signal<void,boost::shared_ptr<Playlist> > PlaylistRemoved; diff --git a/libs/ardour/ardour/tempo_map_importer.h b/libs/ardour/ardour/tempo_map_importer.h new file mode 100644 index 0000000000..6c2a057943 --- /dev/null +++ b/libs/ardour/ardour/tempo_map_importer.h @@ -0,0 +1,60 @@ +/* + Copyright (C) 2008 Paul Davis + Author: Sakari Bergen + + 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. + +*/ + +#ifndef __ardour_tempo_map_importer_h__ +#define __ardour_tempo_map_importer_h__ + +#include <boost/shared_ptr.hpp> + +#include <pbd/xml++.h> + +#include <ardour/element_importer.h> +#include <ardour/element_import_handler.h> +#include <ardour/tempo.h> +#include <ardour/types.h> + +namespace ARDOUR { + +class TempoMapImportHandler : public ElementImportHandler +{ + public: + TempoMapImportHandler (XMLTree const & source, Session & session); + string get_info () const; +}; + +class TempoMapImporter : public ElementImporter +{ + private: + typedef boost::shared_ptr<XMLNode> XMLNodePtr; + public: + TempoMapImporter (XMLTree const & source, Session & session, XMLNode const & node); + + virtual string get_info () const; + virtual bool prepare_move (); + virtual void cancel_move (); + virtual void move (); + + private: + XMLNode xml_tempo_map; +}; + +} // namespace ARDOUR + +#endif diff --git a/libs/ardour/audio_playlist_importer.cc b/libs/ardour/audio_playlist_importer.cc new file mode 100644 index 0000000000..d6a2b2f9fb --- /dev/null +++ b/libs/ardour/audio_playlist_importer.cc @@ -0,0 +1,221 @@ +/* + Copyright (C) 2008 Paul Davis + Author: Sakari Bergen + + 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 <ardour/audio_playlist_importer.h> + +#include <sstream> + +#include <pbd/failed_constructor.h> +#include <pbd/compose.h> +#include <pbd/error.h> + +#include <ardour/audio_region_importer.h> +#include <ardour/session.h> +#include <ardour/playlist.h> +#include <ardour/playlist_factory.h> + +using namespace PBD; +using namespace ARDOUR; + +/**** Handler ***/ +AudioPlaylistImportHandler::AudioPlaylistImportHandler (XMLTree const & source, Session & session, AudioRegionImportHandler & region_handler, const char * nodename) : + ElementImportHandler (source, session), + region_handler (region_handler) +{ + XMLNode const * root = source.root(); + XMLNode const * playlists; + + if (!(playlists = root->child (nodename))) { + throw failed_constructor(); + } + + XMLNodeList const & pl_children = playlists->children(); + for (XMLNodeList::const_iterator it = pl_children.begin(); it != pl_children.end(); ++it) { + const XMLProperty* type = (*it)->property("type"); + if ( !type || type->value() == "audio" ) { + try { + elements.push_back (ElementPtr ( new AudioPlaylistImporter (source, session, *this, **it))); + } catch (failed_constructor err) { + set_dirty(); + } + } + } +} + +string +AudioPlaylistImportHandler::get_info () const +{ + return _("Audio Playlists"); +} + +void +AudioPlaylistImportHandler::get_regions (XMLNode const & node, ElementList & list) +{ + region_handler.create_regions_from_children (node, list); +} + +void +AudioPlaylistImportHandler::update_region_id (XMLProperty* id_prop) +{ + PBD::ID old_id (id_prop->value()); + PBD::ID new_id (region_handler.get_new_id (old_id)); + id_prop->set_value (new_id.to_s()); +} + +/*** AudioPlaylistImporter ***/ +AudioPlaylistImporter::AudioPlaylistImporter (XMLTree const & source, Session & session, AudioPlaylistImportHandler & handler, XMLNode const & node) : + ElementImporter (source, session), + handler (handler), + xml_playlist (node), + diskstream_id ("0") +{ + bool ds_ok = false; + + // Populate region list + ElementImportHandler::ElementList elements; + handler.get_regions (node, elements); + for (ElementImportHandler::ElementList::iterator it = elements.begin(); it != elements.end(); ++it) { + regions.push_back (boost::dynamic_pointer_cast<AudioRegionImporter> (*it)); + } + + // Parse XML + XMLPropertyList const & props = xml_playlist.properties(); + for (XMLPropertyList::const_iterator it = props.begin(); it != props.end(); ++it) { + string prop = (*it)->name(); + if (!prop.compare("type") || !prop.compare("frozen")) { + // All ok + } else if (!prop.compare("name")) { + name = (*it)->value(); + } else if (!prop.compare("orig_diskstream_id")) { + ds_ok = true; + } else { + std::cerr << string_compose (X_("AudioPlaylistImporter did not recognise XML-property \"%1\""), prop) << endmsg; + } + } + + if (!ds_ok) { + error << string_compose (X_("AudioPlaylistImporter (%1): did not find XML-property \"orig_diskstream_id\" which is mandatory"), name) << endmsg; + throw failed_constructor(); + } +} + +string +AudioPlaylistImporter::get_info () const +{ + XMLNodeList children = xml_playlist.children(); + unsigned int regions = 0; + std::ostringstream oss; + + for (XMLNodeIterator it = children.begin(); it != children.end(); it++) { + if ((*it)->name() == "Region") { + ++regions; + } + } + + oss << regions << " "; + + if (regions == 1) { + oss << _("region"); + } else { + oss << _("regions"); + } + + return oss.str(); +} + +bool +AudioPlaylistImporter::prepare_move () +{ + // Rename + while (session.playlist_by_name (name) || !handler.check_name (name)) { + std::pair<bool, string> rename_pair = Rename (_("A playlist with this name already exists, please rename it."), name); + if (!rename_pair.first) { + return false; + } + name = rename_pair.second; + } + xml_playlist.property ("name")->set_value (name); + handler.add_name (name); + + queued = true; + return true; +} + +void +AudioPlaylistImporter::cancel_move () +{ + handler.remove_name (name); + queued = false; +} + +void +AudioPlaylistImporter::move () +{ + boost::shared_ptr<Playlist> playlist; + + // Update diskstream id + xml_playlist.property ("orig_diskstream_id")->set_value (diskstream_id.to_s()); + + // Update region XML in playlist and prepare sources + xml_playlist.remove_nodes("Region"); + for (RegionList::iterator it = regions.begin(); it != regions.end(); ++it) { + xml_playlist.add_child_copy ((*it)->get_xml()); + (*it)->add_sources_to_session(); + if ((*it)->broken()) { + handler.set_dirty(); + set_broken(); + return; // TODO clean up? + } + } + + // Update region ids in crossfades + XMLNodeList crossfades = xml_playlist.children("Crossfade"); + for (XMLNodeIterator it = crossfades.begin(); it != crossfades.end(); ++it) { + XMLProperty* in = (*it)->property("in"); + XMLProperty* out = (*it)->property("out"); + if (!in || !out) { + error << string_compose (X_("AudioPlaylistImporter (%1): did not find the \"in\" or \"out\" property from a crossfade"), name) << endmsg; + } + + handler.update_region_id (in); + handler.update_region_id (out); + + // rate convert length and position + XMLProperty* length = (*it)->property("length"); + if (length) { + length->set_value (rate_convert_samples (length->value())); + } + + XMLProperty* position = (*it)->property("position"); + if (position) { + position->set_value (rate_convert_samples (position->value())); + } + } + + // Create playlist + playlist = PlaylistFactory::create (session, xml_playlist, false, true); +} + +void +AudioPlaylistImporter::set_diskstream (PBD::ID const & id) +{ + diskstream_id = id; +} + diff --git a/libs/ardour/audio_region_importer.cc b/libs/ardour/audio_region_importer.cc new file mode 100644 index 0000000000..ab8261a369 --- /dev/null +++ b/libs/ardour/audio_region_importer.cc @@ -0,0 +1,398 @@ +/* + Copyright (C) 2008 Paul Davis + Author: Sakari Bergen + + 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 <ardour/audio_region_importer.h> + +#include <sstream> + +#include <pbd/failed_constructor.h> +#include <pbd/compose.h> +#include <pbd/error.h> + +#include <ardour/session.h> +#include <ardour/region.h> +#include <ardour/source_factory.h> +#include <ardour/region_factory.h> +#include <ardour/session_directory.h> + +#include "i18n.h" + +using namespace PBD; +using namespace ARDOUR; + +/**** Handler ***/ +AudioRegionImportHandler::AudioRegionImportHandler (XMLTree const & source, Session & session) : + ElementImportHandler (source, session) +{ + XMLNode const * root = source.root(); + XMLNode const * regions; + + if (!(regions = root->child (X_("Regions")))) { + throw failed_constructor(); + } + + create_regions_from_children (*regions, elements); +} + +void +AudioRegionImportHandler::create_regions_from_children (XMLNode const & node, ElementList & list) +{ + XMLNodeList const & children = node.children(); + for (XMLNodeList::const_iterator it = children.begin(); it != children.end(); ++it) { + XMLProperty const * type = (*it)->property("type"); + if (!(*it)->name().compare ("Region") && (!type || type->value() == "audio") ) { + try { + list.push_back (ElementPtr ( new AudioRegionImporter (source, session, *this, **it))); + } catch (failed_constructor err) { + set_dirty(); + } + } + } +} + +string +AudioRegionImportHandler::get_info () const +{ + return _("Audio Regions"); +} + +bool +AudioRegionImportHandler::check_source (string const & filename) const +{ + return (sources.find (filename) != sources.end()); +} + +void +AudioRegionImportHandler::add_source (string const & filename, boost::shared_ptr<Source> const & source) +{ + sources.insert (SourcePair (filename, source)); +} + +boost::shared_ptr<Source> const & +AudioRegionImportHandler::get_source (string const & filename) const +{ + return (sources.find (filename))->second; +} + +void +AudioRegionImportHandler::register_id (PBD::ID & old_id, PBD::ID & new_id) +{ + id_map.insert (IdPair (old_id, new_id)); +} + +PBD::ID const & +AudioRegionImportHandler::get_new_id (PBD::ID & old_id) const +{ + return (id_map.find (old_id))->second; +} + +/*** AudioRegionImporter ***/ +AudioRegionImporter::AudioRegionImporter (XMLTree const & source, Session & session, AudioRegionImportHandler & handler, XMLNode const & node) : + ElementImporter (source, session), + xml_region (node), + handler (handler), + old_id ("0"), + region_prepared (false), + sources_prepared (false) +{ + if (!parse_xml_region () || !parse_source_xml ()) { + throw failed_constructor(); + } + handler.register_id (old_id, id); +} + +string +AudioRegionImporter::get_info () const +{ + nframes_t length, position; + SMPTE::Time length_time, position_time; + std::ostringstream oss; + + // Get sample positions + std::istringstream iss_length(xml_region.property ("length")->value()); + iss_length >> length; + std::istringstream iss_position(xml_region.property ("position")->value()); + iss_position >> position; + + // Convert to smpte + session.sample_to_smpte(length, length_time, true, false); + session.sample_to_smpte(position, position_time, true, false); + + // return info + oss << _("Length: ") << + smpte_to_string(length_time) << + _("\nPosition: ") << + smpte_to_string(position_time) << + _("\nChannels: ") << + xml_region.property ("channels")->value(); + + + return oss.str(); +} + +bool +AudioRegionImporter::prepare_move () +{ + queued = true; + return true; +} + +void +AudioRegionImporter::cancel_move () +{ + queued = false; +} + +void +AudioRegionImporter::move () +{ + if (!region_prepared) { + prepare_region(); + if (!region_prepared) { + return; + } + } + + if (broken()) { + return; + } + + session.add_regions (region); +} + +bool +AudioRegionImporter::parse_xml_region () +{ + XMLPropertyList const & props = xml_region.properties();; + bool id_ok = false; + bool name_ok = false; + + for (XMLPropertyList::const_iterator it = props.begin(); it != props.end(); ++it) { + string prop = (*it)->name(); + if (!prop.compare ("type") || !prop.compare ("stretch") || + !prop.compare ("shift") || !prop.compare ("first_edit") || + !prop.compare ("layer") || !prop.compare ("flags") || + !prop.compare ("scale-gain") || !prop.compare("channels") || + prop.find ("master-source-") == 0 || prop.find ("source-") == 0) { + // All ok + } else if (!prop.compare ("start") || !prop.compare ("length") || + !prop.compare ("position") || !prop.compare ("ancestral-start") || + !prop.compare ("ancestral-length") || !prop.compare ("sync-position")) { + // Sample rate conversion + (*it)->set_value (rate_convert_samples ((*it)->value())); + } else if (!prop.compare("id")) { + // get old id and update id + old_id = (*it)->value(); + (*it)->set_value (id.to_s()); + id_ok = true; + } else if (!prop.compare("name")) { + // rename region if necessary + name = (*it)->value(); + name = session.new_region_name (name); + (*it)->set_value (name); + name_ok = true; + } else { + std::cerr << string_compose (X_("AudioRegionImporter (%1): did not recognise XML-property \"%1\""), name, prop) << endmsg; + } + } + + if (!id_ok) { + error << string_compose (X_("AudioRegionImporter (%1): did not find necessary XML-property \"id\""), name) << endmsg; + return false; + } + + if (!name_ok) { + error << X_("AudioRegionImporter: did not find necessary XML-property \"name\"") << endmsg; + return false; + } + + return true; +} + +bool +AudioRegionImporter::parse_source_xml () +{ + uint32_t channels; + char buf[128]; + PBD::sys::path source_dir = get_sound_dir (source); + PBD::sys::path source_path; + XMLNode * source_node; + XMLProperty *prop; + + // Get XML for sources + if (!(source_node = source.root()->child (X_("Sources")))) { + return false; + } + XMLNodeList const & sources = source_node->children(); + + // Get source for each channel + if (!(prop = xml_region.property ("channels"))) { + error << string_compose (X_("AudioRegionImporter (%1): did not find necessary XML-property \"channels\""), name) << endmsg; + return false; + } + + channels = atoi (prop->value()); + for (uint32_t i = 0; i < channels; ++i) { + bool source_found = false; + + // Get id for source-n + snprintf (buf, sizeof(buf), X_("source-%d"), i); + prop = xml_region.property (buf); + if (!prop) { + error << string_compose (X_("AudioRegionImporter (%1): did not find necessary XML-property \"%3\""), name, buf) << endmsg; + return false; + } + string source_id = prop->value(); + + // Get source + for (XMLNodeList::const_iterator it = sources.begin(); it != sources.end(); it++) { + prop = (*it)->property ("id"); + if (prop && !source_id.compare (prop->value())) { + source_path = source_dir; + prop = (*it)->property ("name"); + if (!prop) { + error << string_compose (X_("AudioRegionImporter (%1): source %2 has no \"name\" property"), name, source_id) << endmsg; + return false; + } + source_path /= prop->value(); + filenames.push_back (source_path.to_string()); + + source_found = true; + break; + } + } + + if (!source_found) { + error << string_compose (X_("AudioRegionImporter (%1): could not find all necessary sources"), name) << endmsg; + return false; + } + } + + return true; +} + +PBD::sys::path +AudioRegionImporter::get_sound_dir (XMLTree const & tree) +{ + PBD::sys::path source_dir = tree.filename(); + source_dir = source_dir.branch_path(); + SessionDirectory session_dir(source_dir); + source_dir = session_dir.sound_path(); + + return source_dir; +} + +void +AudioRegionImporter::prepare_region () +{ + if (region_prepared) { + return; + } + + SourceList source_list; + prepare_sources(); + + // Create source list + for (std::list<string>::iterator it = filenames.begin(); it != filenames.end(); ++it) { + source_list.push_back (handler.get_source (*it)); + } + + // create region and update XML + region.push_back (RegionFactory::create (source_list, xml_region)); + if (*region.begin()) { + xml_region = (*region.begin())->get_state(); + } else { + error << string_compose (X_("AudioRegionImporter (%1): could not construct Region"), name) << endmsg; + handler.set_errors(); + } + + region_prepared = true; +} + +void +AudioRegionImporter::prepare_sources () +{ + if (sources_prepared) { + return; + } + + Session::import_status status; + + // Get sources that still need to be imported + for (std::list<string>::iterator it = filenames.begin(); it != filenames.end(); ++it) { + if (!handler.check_source (*it)) { + status.paths.push_back (*it); + } + } + + // Prepare rest of import struct TODO quality + status.replace_existing_source = false; + status.done = false; + status.cancel = false; + status.freeze = false; + status.progress = 0.0; + status.quality = SrcBest; + + // import files + // TODO: threading & exception handling + session.import_audiofiles (status); + + // Add imported sources to handlers map + std::vector<Glib::ustring>::iterator file_it = status.paths.begin(); + for (SourceList::iterator source_it = status.sources.begin(); source_it != status.sources.end(); ++source_it) { + if (*source_it) { + handler.add_source(*file_it, *source_it); + } else { + error << string_compose (X_("AudioRegionImporter (%1): could not import all necessary sources"), name) << endmsg; + handler.set_errors(); + set_broken(); + } + + ++file_it; + } + + sources_prepared = true; +} + +void +AudioRegionImporter::add_sources_to_session () +{ + if (!sources_prepared) { + prepare_sources(); + } + + if (broken()) { + return; + } + + for (std::list<string>::iterator it = filenames.begin(); it != filenames.end(); ++it) { + session.add_source (handler.get_source (*it)); + } +} + +XMLNode const & +AudioRegionImporter::get_xml () +{ + if(!region_prepared) { + prepare_region(); + } + + return xml_region; +} diff --git a/libs/ardour/element_import_handler.cc b/libs/ardour/element_import_handler.cc new file mode 100644 index 0000000000..013dd3fe44 --- /dev/null +++ b/libs/ardour/element_import_handler.cc @@ -0,0 +1,55 @@ +/* + Copyright (C) 2008 Paul Davis + Author: Sakari Bergen + + 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 <ardour/element_import_handler.h> + +#include <algorithm> + +using namespace ARDOUR; + +bool ElementImportHandler::_dirty = false; +bool ElementImportHandler::_errors = false; + +ElementImportHandler::~ElementImportHandler () +{ + _dirty = false; + _errors = false; +} + +bool +ElementImportHandler::check_name (const string & name) const +{ + return std::find (names.begin(), names.end(), name) == names.end(); +} + +void +ElementImportHandler::add_name (string name) +{ + names.push_back (name); +} + +void +ElementImportHandler::remove_name (const string & name) +{ + std::list<string>::iterator it = std::find (names.begin(), names.end(), name); + if (it != names.end()) { + names.erase(it); + } +} diff --git a/libs/ardour/element_importer.cc b/libs/ardour/element_importer.cc new file mode 100644 index 0000000000..0312f0ef15 --- /dev/null +++ b/libs/ardour/element_importer.cc @@ -0,0 +1,84 @@ +/* + Copyright (C) 2008 Paul Davis + Author: Sakari Bergen + + 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 <ardour/element_importer.h> + +#include <sstream> +#include <iomanip> + +#include <pbd/convert.h> +#include <ardour/session.h> + +#include "i18n.h" + +using namespace PBD; +using namespace ARDOUR; + +sigc::signal <std::pair<bool, string>, string, string> ElementImporter::Rename; +sigc::signal <bool, string> ElementImporter::Prompt; + +ElementImporter::ElementImporter (XMLTree const & source, ARDOUR::Session & session) : + source (source), + session(session), + queued (false), + _broken (false) +{ + // Get samplerate + XMLProperty *prop; + prop = source.root()->property ("sample-rate"); + if (prop) { + std::istringstream iss (prop->value()); + iss >> sample_rate; + } +} + +string +ElementImporter::smpte_to_string(SMPTE::Time & time) const +{ + std::ostringstream oss; + oss << std::setfill('0') << std::right << + std::setw(2) << + time.hours << ":" << + std::setw(2) << + time.minutes << ":" << + std::setw(2) << + time.seconds << ":" << + std::setw(2) << + time.frames; + + return oss.str(); +} + +nframes_t +ElementImporter::rate_convert_samples (nframes_t samples) const +{ + if (sample_rate == session.frame_rate()) { + return samples; + } + + // +0.5 for proper rounding + return static_cast<nframes_t> (samples * (static_cast<double> (session.nominal_frame_rate()) / sample_rate) + 0.5); +} + +string +ElementImporter::rate_convert_samples (string const & samples) const +{ + return to_string (rate_convert_samples (atoi (samples)), std::dec); +} diff --git a/libs/ardour/location.cc b/libs/ardour/location.cc index 8dd4bbc636..be34e34349 100644 --- a/libs/ardour/location.cc +++ b/libs/ardour/location.cc @@ -247,6 +247,14 @@ Location::set_is_start (bool yn, void *src) } void +Location::set_is_range_marker (bool yn, void *src) +{ + if (set_flag_internal (yn, IsRangeMarker)) { + FlagsChanged (this, src); /* EMIT SIGNAL */ + } +} + +void Location::set_auto_punch (bool yn, void *src) { if (is_mark() || _start == _end) { diff --git a/libs/ardour/location_importer.cc b/libs/ardour/location_importer.cc new file mode 100644 index 0000000000..31f19ef164 --- /dev/null +++ b/libs/ardour/location_importer.cc @@ -0,0 +1,195 @@ +/* + Copyright (C) 2008 Paul Davis + Author: Sakari Bergen + + 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 <ardour/location_importer.h> + +#include <sstream> +#include <stdexcept> + +#include <ardour/session.h> +#include <pbd/convert.h> +#include <pbd/failed_constructor.h> + +#include "i18n.h" + +using namespace PBD; +using namespace ARDOUR; + +/**** Handler ***/ +LocationImportHandler::LocationImportHandler (XMLTree const & source, Session & session) : + ElementImportHandler (source, session) +{ + XMLNode const *root = source.root(); + XMLNode const * location_node; + + if (!(location_node = root->child ("Locations"))) { + throw failed_constructor(); + } + + // Construct importable locations + XMLNodeList const & locations = location_node->children(); + for (XMLNodeList::const_iterator it = locations.begin(); it != locations.end(); it++) { + try { + elements.push_back (ElementPtr ( new LocationImporter (source, session, *this, **it))); + } catch (failed_constructor err) { + _dirty = true; + } + } +} + +string +LocationImportHandler::get_info () const +{ + return _("Locations"); +} + +/*** LocationImporter ***/ +LocationImporter::LocationImporter (XMLTree const & source, Session & session, LocationImportHandler & handler, XMLNode const & node) : + ElementImporter (source, session), + handler (handler), + xml_location (node), + location (0) + { + // Parse XML + bool name_ok = false; + XMLPropertyList props = xml_location.properties(); + + for (XMLPropertyIterator it = props.begin(); it != props.end(); ++it) { + string prop = (*it)->name(); + if (!prop.compare ("id") || !prop.compare ("flags") || !prop.compare ("locked")) { + // All ok + } else if (!prop.compare ("start") || !prop.compare ("end")) { + // Sample rate conversion + (*it)->set_value (rate_convert_samples ((*it)->value())); + } else if (!prop.compare ("name")) { + // rename region if necessary + name = (*it)->value(); + name_ok = true; + } else { + std::cerr << string_compose (X_("LocationImporter did not recognise XML-property \"%1\""), prop) << endmsg; + } + } + + if (!name_ok) { + error << X_("LocationImporter did not find necessary XML-property \"name\"") << endmsg; + throw failed_constructor(); + } +} + +LocationImporter::~LocationImporter () +{ + if (!queued && location) { + delete location; + } +} + +string +LocationImporter::get_info () const +{ + nframes_t start, end; + SMPTE::Time start_time, end_time; + + // Get sample positions + std::istringstream iss_start (xml_location.property ("start")->value()); + iss_start >> start; + std::istringstream iss_end (xml_location.property ("end")->value()); + iss_end >> end; + + // Convert to smpte + session.sample_to_smpte (start, start_time, true, false); + session.sample_to_smpte (end, end_time, true, false); + + // return info + std::ostringstream oss; + if (start == end) { + oss << _("Location: ") << smpte_to_string (start_time); + } else { + oss << _("Range\nstart: ") << smpte_to_string (start_time) << + _("\nend: ") << smpte_to_string (end_time); + } + + return oss.str(); +} + +bool +LocationImporter::prepare_move () +{ + try { + Location const original (xml_location); + location = new Location (original); // Updates id + } catch (failed_constructor& err) { + throw std::runtime_error (X_("Error in session file!")); + return false; + } + + std::pair<bool, string> rename_pair; + + if (location->is_auto_punch()) { + rename_pair = Rename (_("The location is the Punch range. It will be imported as a normal range.\nYou may rename the imported location:"), name); + if (!rename_pair.first) { + return false; + } + + name = rename_pair.second; + location->set_auto_punch (false, this); + location->set_is_range_marker (true, this); + } + + if (location->is_auto_loop()) { + rename_pair = Rename (_("The location is a Loop range. It will be imported as a normal range.\nYou may rename the imported location:"), name); + if (!rename_pair.first) { return false; } + + location->set_auto_loop (false, this); + location->set_is_range_marker (true, this); + } + + // duplicate name checking + Locations::LocationList const & locations(session.locations()->list()); + for (Locations::LocationList::const_iterator it = locations.begin(); it != locations.end(); ++it) { + if (!((*it)->name().compare (location->name())) || !handler.check_name (location->name())) { + rename_pair = Rename (_("A location with that name already exists.\nYou may rename the imported location:"), name); + if (!rename_pair.first) { return false; } + name = rename_pair.second; + } + } + + location->set_name (name); + queued = true; + return true; +} + +void +LocationImporter::cancel_move () +{ + queued = false; + if (location) { + delete location; + location = 0; + } +} + +void +LocationImporter::move () +{ + if (!queued) { + return; + } + session.locations()->add (location); +} diff --git a/libs/ardour/playlist_factory.cc b/libs/ardour/playlist_factory.cc index a801bae76c..129ff514af 100644 --- a/libs/ardour/playlist_factory.cc +++ b/libs/ardour/playlist_factory.cc @@ -29,10 +29,10 @@ using namespace ARDOUR; using namespace PBD; -sigc::signal<void,boost::shared_ptr<Playlist> > PlaylistFactory::PlaylistCreated; +sigc::signal<void,boost::shared_ptr<Playlist>, bool> PlaylistFactory::PlaylistCreated; boost::shared_ptr<Playlist> -PlaylistFactory::create (Session& s, const XMLNode& node, bool hidden) +PlaylistFactory::create (Session& s, const XMLNode& node, bool hidden, bool unused) { const XMLProperty* type = node.property("type"); @@ -46,7 +46,7 @@ PlaylistFactory::create (Session& s, const XMLNode& node, bool hidden) pl->set_region_ownership (); if (pl && !hidden) { - PlaylistCreated (pl); + PlaylistCreated (pl, unused); } return pl; } @@ -62,7 +62,7 @@ PlaylistFactory::create (DataType type, Session& s, string name, bool hidden) pl = boost::shared_ptr<Playlist> (new MidiPlaylist (s, name, hidden)); if (pl && !hidden) { - PlaylistCreated (pl); + PlaylistCreated (pl, false); } return pl; @@ -84,7 +84,7 @@ PlaylistFactory::create (boost::shared_ptr<const Playlist> old, string name, boo } if (pl && !hidden) { - PlaylistCreated (pl); + PlaylistCreated (pl, false); } return pl; diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index ffa7d17761..30f93f9646 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -3368,7 +3368,23 @@ Session::playlist_by_name (string name) } void -Session::add_playlist (boost::shared_ptr<Playlist> playlist) +Session::unassigned_playlists (std::list<boost::shared_ptr<Playlist> > & list) +{ + Glib::Mutex::Lock lm (playlist_lock); + for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) { + if (!(*i)->get_orig_diskstream_id().to_s().compare ("0")) { + list.push_back (*i); + } + } + for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) { + if (!(*i)->get_orig_diskstream_id().to_s().compare ("0")) { + list.push_back (*i); + } + } +} + +void +Session::add_playlist (boost::shared_ptr<Playlist> playlist, bool unused) { if (playlist->hidden()) { return; @@ -3383,6 +3399,10 @@ Session::add_playlist (boost::shared_ptr<Playlist> playlist) } } + if (unused) { + playlist->release(); + } + set_dirty(); PlaylistAdded (playlist); /* EMIT SIGNAL */ diff --git a/libs/ardour/tempo_map_importer.cc b/libs/ardour/tempo_map_importer.cc new file mode 100644 index 0000000000..45f2c90dfa --- /dev/null +++ b/libs/ardour/tempo_map_importer.cc @@ -0,0 +1,108 @@ +/* + Copyright (C) 2008 Paul Davis + Author: Sakari Bergen + + 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 <ardour/tempo_map_importer.h> + +#include <sstream> + +#include <ardour/session.h> +#include <pbd/failed_constructor.h> +#include <pbd/compose.h> +#include <pbd/error.h> + +#include "i18n.h" + +using namespace PBD; +using namespace ARDOUR; + +/**** Handler ***/ +TempoMapImportHandler::TempoMapImportHandler (XMLTree const & source, Session & session) : + ElementImportHandler (source, session) +{ + XMLNode const * root = source.root(); + XMLNode const * tempo_map; + + if (!(tempo_map = root->child (X_("TempoMap")))) { + throw failed_constructor(); + } + + elements.push_back (ElementPtr ( new TempoMapImporter (source, session, *tempo_map))); +} + +string +TempoMapImportHandler::get_info () const +{ + return _("Tempo map"); +} + +/*** TempoMapImporter ***/ +TempoMapImporter::TempoMapImporter (XMLTree const & source, Session & session, XMLNode const & node) : + ElementImporter (source, session), + xml_tempo_map (node) +{ + name = _("Tempo Map"); +} + +string +TempoMapImporter::get_info () const +{ + std::ostringstream oss; + unsigned int tempos = 0; + unsigned int meters = 0; + XMLNodeList children = xml_tempo_map.children(); + + for (XMLNodeIterator it = children.begin(); it != children.end(); it++) { + if ((*it)->name() == "Tempo") { + tempos++; + } else if ((*it)->name() == "Meters") { + meters++; + } + } + + // return info + oss << _("Tempo marks: ") << tempos << _("\nMeter marks: ") << meters; + + return oss.str(); +} + +bool +TempoMapImporter::prepare_move () +{ + // Prompt user for verification + bool replace = Prompt (_("This will replace the current tempo map!\nAre you shure you want to do this?")); + + if (replace) { + queued = true; + } + + return replace; +} + +void +TempoMapImporter::cancel_move () +{ + queued = false; +} + +void +TempoMapImporter::move () +{ + session.tempo_map().set_state (xml_tempo_map); +} |