summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorSakari Bergen <sakari.bergen@beatwaves.net>2008-09-26 08:29:30 +0000
committerSakari Bergen <sakari.bergen@beatwaves.net>2008-09-26 08:29:30 +0000
commit572fa80aa713e723f63e1e1822db614307eea6af (patch)
tree6d8e8ed27d6192790f54482f14e93dda73d3a485 /libs/ardour
parent10d57b266cbec7054399f20f8e8c76cdff7e1592 (diff)
Add Import from session -functionality
git-svn-id: svn://localhost/ardour2/branches/3.0@3805 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/SConscript6
-rw-r--r--libs/ardour/ardour/audio_playlist_importer.h87
-rw-r--r--libs/ardour/ardour/audio_region_importer.h107
-rw-r--r--libs/ardour/ardour/element_import_handler.h110
-rw-r--r--libs/ardour/ardour/element_importer.h122
-rw-r--r--libs/ardour/ardour/location.h1
-rw-r--r--libs/ardour/ardour/location_importer.h63
-rw-r--r--libs/ardour/ardour/playlist_factory.h4
-rw-r--r--libs/ardour/ardour/session.h3
-rw-r--r--libs/ardour/ardour/tempo_map_importer.h60
-rw-r--r--libs/ardour/audio_playlist_importer.cc221
-rw-r--r--libs/ardour/audio_region_importer.cc398
-rw-r--r--libs/ardour/element_import_handler.cc55
-rw-r--r--libs/ardour/element_importer.cc84
-rw-r--r--libs/ardour/location.cc8
-rw-r--r--libs/ardour/location_importer.cc195
-rw-r--r--libs/ardour/playlist_factory.cc10
-rw-r--r--libs/ardour/session.cc22
-rw-r--r--libs/ardour/tempo_map_importer.cc108
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);
+}