More work on track import and some cleaning up of ElementImporter interface

git-svn-id: svn://localhost/ardour2/branches/3.0@4265 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Sakari Bergen 2008-11-26 17:13:50 +00:00
parent 95a86871c0
commit 38382b7921
13 changed files with 284 additions and 97 deletions

View File

@ -105,13 +105,13 @@ void
SessionImportDialog::load_session (const string& filename)
{
tree.read (filename);
AudioRegionImportHandler *region_handler;
boost::shared_ptr<AudioRegionImportHandler> region_handler (new AudioRegionImportHandler (tree, target));
boost::shared_ptr<AudioPlaylistImportHandler> pl_handler (new AudioPlaylistImportHandler (tree, target, *region_handler));
region_handler = new AudioRegionImportHandler (tree, target);
handlers.push_back (HandlerPtr(region_handler));
handlers.push_back (HandlerPtr(new AudioPlaylistImportHandler (tree, target, *region_handler)));
handlers.push_back (boost::static_pointer_cast<ElementImportHandler> (region_handler));
handlers.push_back (boost::static_pointer_cast<ElementImportHandler> (pl_handler));
handlers.push_back (HandlerPtr(new UnusedAudioPlaylistImportHandler (tree, target, *region_handler)));
handlers.push_back (HandlerPtr(new AudioTrackImportHandler (tree, target)));
handlers.push_back (HandlerPtr(new AudioTrackImportHandler (tree, target, *pl_handler)));
handlers.push_back (HandlerPtr(new LocationImportHandler (tree, target)));
handlers.push_back (HandlerPtr(new TempoMapImportHandler (tree, target)));

View File

@ -38,16 +38,22 @@ namespace ARDOUR {
class AudioRegionImportHandler;
class AudioRegionImporter;
class AudioPlaylistImporter;
class AudioPlaylistImportHandler : public ElementImportHandler
{
public:
typedef boost::shared_ptr<AudioPlaylistImporter> PlaylistPtr;
typedef std::list<PlaylistPtr> PlaylistList;
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 get_regions (XMLNode const & node, ElementList & list) const;
void update_region_id (XMLProperty* id_prop);
void playlists_by_diskstream (PBD::ID const & id, PlaylistList & list) const;
protected:
AudioRegionImportHandler & region_handler;
@ -65,19 +71,27 @@ class AudioPlaylistImporter : public ElementImporter
{
public:
AudioPlaylistImporter (XMLTree const & source, Session & session, AudioPlaylistImportHandler & handler, XMLNode const & node);
AudioPlaylistImporter (AudioPlaylistImporter const & other);
string get_info () const;
bool prepare_move ();
void cancel_move ();
void move ();
void set_diskstream (PBD::ID const & id);
PBD::ID const & orig_diskstream () const { return orig_diskstream_id; }
protected:
bool _prepare_move ();
void _cancel_move ();
void _move ();
private:
typedef std::list<boost::shared_ptr<AudioRegionImporter> > RegionList;
void populate_region_list ();
AudioPlaylistImportHandler & handler;
XMLNode const & orig_node;
XMLNode xml_playlist;
PBD::ID orig_diskstream_id;
PBD::ID diskstream_id;
RegionList regions;
};

View File

@ -75,14 +75,16 @@ class AudioRegionImporter : public ElementImporter
// 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 ();
protected:
bool _prepare_move ();
void _cancel_move ();
void _move ();
private:
XMLNode xml_region;

View File

@ -21,44 +21,68 @@
#ifndef __ardour_audio_track_importer_h__
#define __ardour_audio_track_importer_h__
#include <list>
#include <pbd/xml++.h>
#include <pbd/id.h>
#include <ardour/element_importer.h>
#include <ardour/element_import_handler.h>
namespace ARDOUR {
class AudioPlaylistImportHandler;
class AudioPlaylistImporter;
class AudioTrackImportHandler : public ElementImportHandler
{
public:
AudioTrackImportHandler (XMLTree const & source, Session & session);
AudioTrackImportHandler (XMLTree const & source, Session & session, AudioPlaylistImportHandler & pl_handler);
virtual ~AudioTrackImportHandler () {}
virtual string get_info () const;
private:
AudioPlaylistImportHandler & pl_handler;
};
class AudioTrackImporter : public ElementImporter
{
public:
AudioTrackImporter (XMLTree const & source, Session & session, AudioTrackImportHandler & handler, XMLNode const & node);
AudioTrackImporter (XMLTree const & source,
Session & session,
AudioTrackImportHandler & track_handler,
XMLNode const & node,
AudioPlaylistImportHandler & pl_handler);
string get_info () const;
bool prepare_move ();
void cancel_move ();
void move ();
protected:
bool _prepare_move ();
void _cancel_move ();
void _move ();
private:
typedef boost::shared_ptr<AudioPlaylistImporter> PlaylistPtr;
typedef std::list<PlaylistPtr> PlaylistList;
bool parse_route_xml ();
bool parse_io ();
bool parse_processor (XMLNode & node);
bool parse_controllable (XMLNode & node);
bool parse_automation (XMLNode & node);
bool rate_convert_events (XMLNode & node);
AudioTrackImportHandler & track_handler;
XMLNode xml_track;
PBD::ID old_ds_id;
PBD::ID new_ds_id;
PlaylistList playlists;
AudioPlaylistImportHandler & pl_handler;
};
} // namespace ARDOUR

View File

@ -41,7 +41,7 @@ class ElementImporter
public:
ElementImporter (XMLTree const & source, ARDOUR::Session & session);
virtual ~ElementImporter () {};
virtual ~ElementImporter ();
/** Returns the element name
* @return the name of the element
@ -54,27 +54,18 @@ class ElementImporter
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;
bool prepare_move ();
/** 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;
void cancel_move ();
/** 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;
/// Moves the element to the taget session
void move ();
/// Check if element is broken. Cannot be moved if broken.
bool broken () { return _broken; }
@ -86,6 +77,24 @@ class ElementImporter
static sigc::signal <bool, string> Prompt;
protected:
/** 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;
/** 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.
*
* @return whether or not the element can be moved
*/
virtual bool _prepare_move () = 0;
/// Cancel move
virtual void _cancel_move () = 0;
/// Source XML-tree
XMLTree const & source;
@ -93,7 +102,7 @@ class ElementImporter
ARDOUR::Session & session;
/// Ture if the element has been prepared and queued for importing
bool queued;
bool queued () { return _queued; }
/// Name of element
string name;
@ -114,6 +123,7 @@ class ElementImporter
void set_broken () { _broken = true; }
private:
bool _queued;
bool _broken;
};

View File

@ -46,9 +46,11 @@ class LocationImporter : public ElementImporter
~LocationImporter ();
string get_info () const;
bool prepare_move ();
void cancel_move ();
void move ();
protected:
bool _prepare_move ();
void _cancel_move ();
void _move ();
private:
LocationImportHandler & handler;

View File

@ -47,9 +47,11 @@ class TempoMapImporter : public ElementImporter
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 ();
protected:
bool _prepare_move ();
void _cancel_move ();
void _move ();
private:
XMLNode xml_tempo_map;

View File

@ -66,7 +66,7 @@ AudioPlaylistImportHandler::get_info () const
}
void
AudioPlaylistImportHandler::get_regions (XMLNode const & node, ElementList & list)
AudioPlaylistImportHandler::get_regions (XMLNode const & node, ElementList & list) const
{
region_handler.create_regions_from_children (node, list);
}
@ -79,21 +79,28 @@ AudioPlaylistImportHandler::update_region_id (XMLProperty* id_prop)
id_prop->set_value (new_id.to_s());
}
void
AudioPlaylistImportHandler::playlists_by_diskstream (PBD::ID const & id, PlaylistList & list) const
{
for (ElementList::const_iterator it = elements.begin(); it != elements.end(); ++it) {
boost::shared_ptr<AudioPlaylistImporter> pl = boost::dynamic_pointer_cast<AudioPlaylistImporter> (*it);
if (pl && pl->orig_diskstream() == id) {
list.push_back (PlaylistPtr (new AudioPlaylistImporter (*pl)));
}
}
}
/*** AudioPlaylistImporter ***/
AudioPlaylistImporter::AudioPlaylistImporter (XMLTree const & source, Session & session, AudioPlaylistImportHandler & handler, XMLNode const & node) :
ElementImporter (source, session),
handler (handler),
orig_node (node),
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));
}
populate_region_list ();
// Parse XML
XMLPropertyList const & props = xml_playlist.properties();
@ -104,6 +111,7 @@ AudioPlaylistImporter::AudioPlaylistImporter (XMLTree const & source, Session &
} else if (!prop.compare("name")) {
name = (*it)->value();
} else if (!prop.compare("orig-diskstream-id")) {
orig_diskstream_id = (*it)->value();
ds_ok = true;
} else {
std::cerr << string_compose (X_("AudioPlaylistImporter did not recognise XML-property \"%1\""), prop) << endmsg;
@ -116,6 +124,16 @@ AudioPlaylistImporter::AudioPlaylistImporter (XMLTree const & source, Session &
}
}
AudioPlaylistImporter::AudioPlaylistImporter (AudioPlaylistImporter const & other) :
ElementImporter (other.source, other.session),
handler (other.handler),
orig_node (other.orig_node),
xml_playlist (other.xml_playlist),
orig_diskstream_id (other.orig_diskstream_id)
{
populate_region_list ();
}
string
AudioPlaylistImporter::get_info () const
{
@ -141,7 +159,7 @@ AudioPlaylistImporter::get_info () const
}
bool
AudioPlaylistImporter::prepare_move ()
AudioPlaylistImporter::_prepare_move ()
{
// Rename
while (session.playlist_by_name (name) || !handler.check_name (name)) {
@ -154,19 +172,17 @@ AudioPlaylistImporter::prepare_move ()
xml_playlist.property ("name")->set_value (name);
handler.add_name (name);
queued = true;
return true;
}
void
AudioPlaylistImporter::cancel_move ()
AudioPlaylistImporter::_cancel_move ()
{
handler.remove_name (name);
queued = false;
}
void
AudioPlaylistImporter::move ()
AudioPlaylistImporter::_move ()
{
boost::shared_ptr<Playlist> playlist;
@ -219,3 +235,13 @@ AudioPlaylistImporter::set_diskstream (PBD::ID const & id)
diskstream_id = id;
}
void
AudioPlaylistImporter::populate_region_list ()
{
ElementImportHandler::ElementList elements;
handler.get_regions (orig_node, elements);
for (ElementImportHandler::ElementList::iterator it = elements.begin(); it != elements.end(); ++it) {
regions.push_back (boost::dynamic_pointer_cast<AudioRegionImporter> (*it));
}
}

View File

@ -148,20 +148,18 @@ AudioRegionImporter::get_info () const
}
bool
AudioRegionImporter::prepare_move ()
AudioRegionImporter::_prepare_move ()
{
queued = true;
return true;
}
void
AudioRegionImporter::cancel_move ()
AudioRegionImporter::_cancel_move ()
{
queued = false;
}
void
AudioRegionImporter::move ()
AudioRegionImporter::_move ()
{
if (!region_prepared) {
prepare_region();
@ -190,6 +188,7 @@ AudioRegionImporter::parse_xml_region ()
!prop.compare ("shift") || !prop.compare ("first_edit") ||
!prop.compare ("layer") || !prop.compare ("flags") ||
!prop.compare ("scale-gain") || !prop.compare("channels") ||
!prop.compare ("first-edit") ||
prop.find ("master-source-") == 0 || prop.find ("source-") == 0) {
// All ok
} else if (!prop.compare ("start") || !prop.compare ("length") ||
@ -209,7 +208,7 @@ AudioRegionImporter::parse_xml_region ()
(*it)->set_value (name);
name_ok = true;
} else {
std::cerr << string_compose (X_("AudioRegionImporter (%1): did not recognise XML-property \"%1\""), name, prop) << endmsg;
std::cerr << string_compose (X_("AudioRegionImporter (%1): did not recognise XML-property \"%2\""), name, prop) << endmsg;
}
}
@ -256,7 +255,7 @@ AudioRegionImporter::parse_source_xml ()
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;
error << string_compose (X_("AudioRegionImporter (%1): did not find necessary XML-property \"%2\""), name, buf) << endmsg;
return false;
}
string source_id = prop->value();

View File

@ -20,12 +20,14 @@
#include <ardour/audio_track_importer.h>
#include <ardour/audio_playlist_importer.h>
#include <ardour/session.h>
#include <pbd/id.h>
#include <pbd/failed_constructor.h>
#include <pbd/convert.h>
#include <sstream>
#include "i18n.h"
using namespace PBD;
@ -33,8 +35,9 @@ using namespace ARDOUR;
/*** AudioTrackImportHandler ***/
AudioTrackImportHandler::AudioTrackImportHandler (XMLTree const & source, Session & session) :
ElementImportHandler (source, session)
AudioTrackImportHandler::AudioTrackImportHandler (XMLTree const & source, Session & session, AudioPlaylistImportHandler & pl_handler) :
ElementImportHandler (source, session),
pl_handler (pl_handler)
{
XMLNode const * root = source.root();
XMLNode const * routes;
@ -46,9 +49,9 @@ AudioTrackImportHandler::AudioTrackImportHandler (XMLTree const & source, Sessio
XMLNodeList const & route_list = routes->children();
for (XMLNodeList::const_iterator it = route_list.begin(); it != route_list.end(); ++it) {
const XMLProperty* type = (*it)->property("default-type");
if ( !type || type->value() == "audio" ) {
if ( (!type || type->value() == "audio") && ((*it)->property ("diskstream") != 0 || (*it)->property ("diskstream-id") != 0)) {
try {
elements.push_back (ElementPtr ( new AudioTrackImporter (source, session, *this, **it)));
elements.push_back (ElementPtr ( new AudioTrackImporter (source, session, *this, **it, pl_handler)));
} catch (failed_constructor err) {
set_dirty();
}
@ -65,9 +68,15 @@ AudioTrackImportHandler::get_info () const
/*** AudioTrackImporter ***/
AudioTrackImporter::AudioTrackImporter (XMLTree const & source, Session & session, AudioTrackImportHandler & handler, XMLNode const & node) :
AudioTrackImporter::AudioTrackImporter (XMLTree const & source,
Session & session,
AudioTrackImportHandler & handler,
XMLNode const & node,
AudioPlaylistImportHandler & pl_handler) :
ElementImporter (source, session),
xml_track (node)
track_handler (track_handler),
xml_track (node),
pl_handler (pl_handler)
{
XMLProperty * prop;
@ -96,8 +105,12 @@ AudioTrackImporter::AudioTrackImporter (XMLTree const & source, Session & sessio
bool
AudioTrackImporter::parse_route_xml ()
{
XMLPropertyList const & props = xml_track.properties();
bool ds_ok = false;
// Remove order keys, new ones will be generated
xml_track.remove_property ("order-keys");
XMLPropertyList const & props = xml_track.properties();
for (XMLPropertyList::const_iterator it = props.begin(); it != props.end(); ++it) {
string prop = (*it)->name();
if (!prop.compare ("default-type") || !prop.compare ("flags") ||
@ -107,15 +120,20 @@ AudioTrackImporter::parse_route_xml ()
!prop.compare ("mute-affects-post-fader") || !prop.compare("mute-affects-control-outs") ||
!prop.compare ("mute-affects-main-outs") || !prop.compare("mode")) {
// All ok
} else if (!prop.compare("order-keys")) {
// TODO
} else if (!prop.compare("diskstream-id")) {
// TODO
old_ds_id = (*it)->value();
(*it)->set_value (new_ds_id.to_s());
ds_ok = true;
} else {
std::cerr << string_compose (X_("AudioTrackImporter: did not recognise XML-property \"%1\""), prop) << endmsg;
}
}
if (!ds_ok) {
error << X_("AudioTrackImporter: did not find necessary XML-property \"diskstream-id\"") << endmsg;
return false;
}
return true;
}
@ -137,17 +155,16 @@ AudioTrackImporter::parse_io ()
if (!prop.compare ("gain") || !prop.compare ("iolimits")) {
// All ok
} else if (!prop.compare("name")) {
name = prop;
name = (*it)->value();
name_ok = true;
} else if (!prop.compare("id")) {
PBD::ID id;
(*it)->set_value (id.to_s());
id_ok = true;
// TODO
} else if (!prop.compare("inputs")) {
// TODO
// TODO Let the IO class do it's thing for now...
} else if (!prop.compare("outputs")) {
// TODO
// TODO Let the IO class do it's thing for now...
} else {
std::cerr << string_compose (X_("AudioTrackImporter: did not recognise XML-property \"%1\""), prop) << endmsg;
}
@ -189,20 +206,46 @@ AudioTrackImporter::get_info () const
}
bool
AudioTrackImporter::prepare_move ()
AudioTrackImporter::_prepare_move ()
{
/* Copy dependent playlists */
pl_handler.playlists_by_diskstream (old_ds_id, playlists);
for (PlaylistList::iterator it = playlists.begin(); it != playlists.end(); ++it) {
if (!(*it)->prepare_move ()) {
playlists.clear ();
return false;
}
(*it)->set_diskstream (new_ds_id);
}
/* Rename */
while (session.route_by_name (name) || !track_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_track.child ("IO")->property ("name")->set_value (name);
track_handler.add_name (name);
// TODO
return false;
return true;
}
void
AudioTrackImporter::cancel_move ()
AudioTrackImporter::_cancel_move ()
{
track_handler.remove_name (name);
playlists.clear ();
// TODO
}
void
AudioTrackImporter::move ()
AudioTrackImporter::_move ()
{
// TODO
}
@ -246,8 +289,54 @@ AudioTrackImporter::parse_automation (XMLNode & node)
prop->set_value (id.to_s());
}
// TODO rate convert events
if (!(*it)->name().compare ("events")) {
rate_convert_events (**it);
}
}
return true;
}
bool
AudioTrackImporter::rate_convert_events (XMLNode & node)
{
if (node.children().empty()) {
return false;
}
XMLNode* content_node = node.children().front();
if (content_node->content().empty()) {
return false;
}
std::stringstream str (content_node->content());
std::ostringstream new_content;
nframes_t x;
double y;
bool ok = true;
while (str) {
str >> x;
if (!str) {
break;
}
str >> y;
if (!str) {
ok = false;
break;
}
new_content << rate_convert_samples (x) << ' ' << y;
}
if (!ok) {
error << X_("AudioTrackImporter: error in rate converting automation events") << endmsg;
return false;
}
content_node->set_content (new_content.str());
return true;
}

View File

@ -37,7 +37,7 @@ sigc::signal <bool, string> ElementImporter::Prompt;
ElementImporter::ElementImporter (XMLTree const & source, ARDOUR::Session & session) :
source (source),
session(session),
queued (false),
_queued (false),
_broken (false)
{
// Get samplerate
@ -49,6 +49,35 @@ ElementImporter::ElementImporter (XMLTree const & source, ARDOUR::Session & sess
}
}
ElementImporter::~ElementImporter ()
{
cancel_move ();
}
void
ElementImporter::move ()
{
if (!_queued) { return; }
_move ();
}
bool
ElementImporter::prepare_move ()
{
if (_queued) {
return true;
}
_queued = _prepare_move ();
return _queued;
}
void
ElementImporter::cancel_move ()
{
if (!_queued) { return; }
_cancel_move ();
}
string
ElementImporter::smpte_to_string(SMPTE::Time & time) const
{

View File

@ -95,7 +95,7 @@ LocationImporter::LocationImporter (XMLTree const & source, Session & session, L
LocationImporter::~LocationImporter ()
{
if (!queued && location) {
if (!queued() && location) {
delete location;
}
}
@ -129,7 +129,7 @@ LocationImporter::get_info () const
}
bool
LocationImporter::prepare_move ()
LocationImporter::_prepare_move ()
{
try {
Location const original (xml_location);
@ -171,14 +171,13 @@ LocationImporter::prepare_move ()
}
location->set_name (name);
queued = true;
return true;
}
void
LocationImporter::cancel_move ()
{
queued = false;
LocationImporter::_cancel_move ()
{
if (location) {
delete location;
location = 0;
@ -186,10 +185,7 @@ LocationImporter::cancel_move ()
}
void
LocationImporter::move ()
LocationImporter::_move ()
{
if (!queued) {
return;
}
session.locations()->add (location);
}

View File

@ -83,26 +83,20 @@ TempoMapImporter::get_info () const
}
bool
TempoMapImporter::prepare_move ()
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 ()
TempoMapImporter::_cancel_move ()
{
queued = false;
}
void
TempoMapImporter::move ()
TempoMapImporter::_move ()
{
session.tempo_map().set_state (xml_tempo_map);
}