Remove 16 year old session-import prototype (2/2)

This was based on Arodur 2.x sessions modifying XML
which no longer applies (and non functioning GUI).
This commit is contained in:
Robin Gareus
2025-11-25 16:52:01 +01:00
parent 2d169824cd
commit 7893b348a8
13 changed files with 0 additions and 2035 deletions

View File

@@ -1,97 +0,0 @@
/*
* Copyright (C) 2008 Sakari Bergen <sakari.bergen@beatwaves.net>
* Copyright (C) 2009-2010 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2009-2012 David Robillard <d@drobilla.net>
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <list>
#include <memory>
#include "pbd/xml++.h"
#include "pbd/id.h"
#include "ardour/element_importer.h"
#include "ardour/element_import_handler.h"
namespace ARDOUR {
class AudioRegionImportHandler;
class AudioRegionImporter;
class AudioPlaylistImporter;
class Session;
class LIBARDOUR_API AudioPlaylistImportHandler : public ElementImportHandler
{
public:
typedef std::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 std::string get_info () const;
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;
};
class LIBARDOUR_API UnusedAudioPlaylistImportHandler : public AudioPlaylistImportHandler
{
public:
UnusedAudioPlaylistImportHandler (XMLTree const & source, Session & session, AudioRegionImportHandler & region_handler) :
AudioPlaylistImportHandler (source, session, region_handler, "UnusedPlaylists") { }
std::string get_info () const;
};
class LIBARDOUR_API AudioPlaylistImporter : public ElementImporter
{
public:
AudioPlaylistImporter (XMLTree const & source, Session & session, AudioPlaylistImportHandler & handler, XMLNode const & node);
AudioPlaylistImporter (AudioPlaylistImporter const & other);
~AudioPlaylistImporter ();
std::string get_info () const;
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<std::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;
};
} // namespace ARDOUR

View File

@@ -1,110 +0,0 @@
/*
* Copyright (C) 2008-2009 Sakari Bergen <sakari.bergen@beatwaves.net>
* Copyright (C) 2009-2012 David Robillard <d@drobilla.net>
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <list>
#include <map>
#include <memory>
#include <utility>
#include "pbd/xml++.h"
#include "pbd/id.h"
#include "ardour/element_importer.h"
#include "ardour/element_import_handler.h"
#include "ardour/import_status.h"
namespace ARDOUR {
class Region;
class Session;
class Source;
class LIBARDOUR_API AudioRegionImportHandler : public ElementImportHandler
{
public:
// Inerface implementation
AudioRegionImportHandler (XMLTree const & source, Session & session);
std::string get_info () const;
void create_regions_from_children (XMLNode const & node, ElementList & list);
// Source management
bool check_source (std::string const & filename) const;
void add_source (std::string const & filename, std::shared_ptr<Source> const & source);
std::shared_ptr<Source> const & get_source (std::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<std::string, std::shared_ptr<Source> > SourceMap;
typedef std::pair<std::string, std::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 LIBARDOUR_API AudioRegionImporter : public ElementImporter
{
public:
AudioRegionImporter (XMLTree const & source, Session & session, AudioRegionImportHandler & handler, XMLNode const & node);
~AudioRegionImporter ();
// Interface implementation
std::string get_info () const;
ImportStatus * get_import_status () { return &status; }
// other stuff
void add_sources_to_session ();
XMLNode const & get_xml ();
protected:
bool _prepare_move ();
void _cancel_move ();
void _move ();
private:
XMLNode xml_region;
AudioRegionImportHandler & handler;
PBD::ID old_id;
PBD::ID id;
std::list<std::string> filenames;
ImportStatus status;
bool parse_xml_region ();
bool parse_source_xml ();
std::string get_sound_dir (XMLTree const & tree);
void prepare_region ();
void prepare_sources ();
std::vector<std::shared_ptr<Region> > region;
bool region_prepared;
bool sources_prepared;
};
} // namespace ARDOUR

View File

@@ -1,85 +0,0 @@
/*
* Copyright (C) 2008 Sakari Bergen <sakari.bergen@beatwaves.net>
* Copyright (C) 2009-2014 David Robillard <d@drobilla.net>
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#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 LIBARDOUR_API AudioTrackImportHandler : public ElementImportHandler
{
public:
AudioTrackImportHandler (XMLTree const & source, Session & session, AudioPlaylistImportHandler & pl_handler);
virtual ~AudioTrackImportHandler () {}
virtual std::string get_info () const;
};
class LIBARDOUR_API AudioTrackImporter : public ElementImporter
{
public:
AudioTrackImporter (XMLTree const & source,
Session & session,
AudioTrackImportHandler & track_handler,
XMLNode const & node,
AudioPlaylistImportHandler & pl_handler);
~AudioTrackImporter ();
std::string get_info () const;
protected:
bool _prepare_move ();
void _cancel_move ();
void _move ();
private:
typedef std::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

@@ -1,133 +0,0 @@
/*
* Copyright (C) 2008-2009 Sakari Bergen <sakari.bergen@beatwaves.net>
* Copyright (C) 2009-2010 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2009-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2009 David Robillard <d@drobilla.net>
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <string>
#include <utility>
#include "pbd/signals.h"
#include "ardour/libardour_visibility.h"
#include "ardour/types.h"
class XMLTree;
namespace ARDOUR {
class Session;
class ImportStatus;
/// Virtual interface class for element importers
class LIBARDOUR_API ElementImporter
{
public:
ElementImporter (XMLTree const & source, ARDOUR::Session & session);
virtual ~ElementImporter ();
/** Returns the element name
* @return the name of the element
*/
virtual std::string get_name () const { return name; };
/** Gets a textual representation of the element
* @return a textual representation on this specific element
*/
virtual std::string get_info () const = 0;
/** Gets import status, if applicable. */
virtual ImportStatus * get_import_status () { return 0; }
/** Prepares to move element
*
* @return whther or not the element could be prepared for moving
*/
bool prepare_move ();
/** Cancels moving of element
* If the element has been set to be moved, this cancels the move.
*/
void cancel_move ();
/// Moves the element to the taget session
void move ();
/// Check if element is broken. Cannot be moved if broken.
bool broken () { return _broken; }
/// Signal that requests for anew name
static PBD::Signal<std::pair<bool, std::string>(std::string, std::string)> Rename;
/// Signal for ok/cancel prompting
static PBD::Signal<bool(std::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;
/// Target session
ARDOUR::Session & session;
/// Ture if the element has been prepared and queued for importing
bool queued () { return _queued; }
/// Name of element
std::string name;
/// The sample rate of the session from which we are importing
samplecnt_t sample_rate;
/// Converts timecode time to a string
std::string timecode_to_string (Timecode::Time & time) const;
/// Converts samples so that times match the sessions sample rate
samplecnt_t rate_convert_samples (samplecnt_t samples) const;
/// Converts samples so that times match the sessions sample rate (for straight use in XML)
std::string rate_convert_samples (std::string const & samples) const;
/// Set element broken
void set_broken () { _broken = true; }
private:
bool _queued;
bool _broken;
};
} // namespace ARDOUR

View File

@@ -1,63 +0,0 @@
/*
* Copyright (C) 2008 Sakari Bergen <sakari.bergen@beatwaves.net>
* Copyright (C) 2009-2012 David Robillard <d@drobilla.net>
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <memory>
#include "ardour/element_importer.h"
#include "ardour/element_import_handler.h"
#include "pbd/xml++.h"
namespace ARDOUR {
class Location;
class Session;
class LIBARDOUR_API LocationImportHandler : public ElementImportHandler
{
public:
LocationImportHandler (XMLTree const & source, Session & session);
std::string get_info () const;
};
class LIBARDOUR_API LocationImporter : public ElementImporter
{
public:
LocationImporter (XMLTree const & source, Session & session, LocationImportHandler & handler, XMLNode const & node);
~LocationImporter ();
std::string get_info () const;
protected:
bool _prepare_move ();
void _cancel_move ();
void _move ();
private:
LocationImportHandler & handler;
XMLNode xml_location;
Location * location;
void parse_xml ();
};
} // namespace ARDOUR

View File

@@ -1,59 +0,0 @@
/*
* Copyright (C) 2008 Sakari Bergen <sakari.bergen@beatwaves.net>
* Copyright (C) 2009-2012 David Robillard <d@drobilla.net>
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <memory>
#include "pbd/xml++.h"
#include "ardour/element_importer.h"
#include "ardour/element_import_handler.h"
namespace ARDOUR {
class Session;
class LIBARDOUR_API TempoMapImportHandler : public ElementImportHandler
{
public:
TempoMapImportHandler (XMLTree const & source, Session & session);
std::string get_info () const;
};
class LIBARDOUR_API TempoMapImporter : public ElementImporter
{
private:
typedef std::shared_ptr<XMLNode> XMLNodePtr;
public:
TempoMapImporter (XMLTree const & source, Session & session, XMLNode const & node);
virtual std::string get_info () const;
protected:
bool _prepare_move ();
void _cancel_move ();
void _move ();
private:
XMLNode xml_tempo_map;
};
} // namespace ARDOUR

View File

@@ -1,270 +0,0 @@
/*
* Copyright (C) 2008-2014 David Robillard <d@drobilla.net>
* Copyright (C) 2008 Sakari Bergen <sakari.bergen@beatwaves.net>
* Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2009-2016 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2014-2019 Robin Gareus <robin@gareus.org>
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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_factory.h"
#include "ardour/session_playlists.h"
#include "pbd/i18n.h"
using namespace std;
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) {
XMLProperty const * type = (*it)->property("type");
if ( !type || type->value() == "audio" ) {
try {
elements.push_back (ElementPtr ( new AudioPlaylistImporter (source, session, *this, **it)));
} catch (failed_constructor const&) {
set_dirty();
}
}
}
}
string
AudioPlaylistImportHandler::get_info () const
{
return _("Audio Playlists");
}
void
AudioPlaylistImportHandler::get_regions (XMLNode const & node, ElementList & list) const
{
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());
}
void
AudioPlaylistImportHandler::playlists_by_diskstream (PBD::ID const & id, PlaylistList & list) const
{
for (ElementList::const_iterator it = elements.begin(); it != elements.end(); ++it) {
std::shared_ptr<AudioPlaylistImporter> pl = std::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 ();
// 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")) {
orig_diskstream_id = (*it)->value();
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();
}
}
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 ();
}
AudioPlaylistImporter::~AudioPlaylistImporter ()
{
}
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.playlists()->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;
}
XMLProperty * p = xml_playlist.property ("name");
if (!p) {
error << _("badly-formed XML in imported playlist") << endmsg;
return false;
}
p->set_value (name);
handler.add_name (name);
return true;
}
void
AudioPlaylistImporter::_cancel_move ()
{
handler.remove_name (name);
}
void
AudioPlaylistImporter::_move ()
{
std::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;
continue; // or fatal?
}
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);
}
void
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 (std::dynamic_pointer_cast<AudioRegionImporter> (*it));
}
}
string
UnusedAudioPlaylistImportHandler::get_info () const
{
return _("Audio Playlists (unused)");
}

View File

@@ -1,399 +0,0 @@
/*
* Copyright (C) 2008-2009 Sakari Bergen <sakari.bergen@beatwaves.net>
* Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2009-2012 David Robillard <d@drobilla.net>
* Copyright (C) 2009-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2012 Tim Mayberry <mojofunk@gmail.com>
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "ardour/audio_region_importer.h"
#include <sstream>
#include <glibmm/miscutils.h>
#include "pbd/failed_constructor.h"
#include "pbd/compose.h"
#include "pbd/error.h"
#include "ardour/session.h"
#include "ardour/region.h"
#include "ardour/region_factory.h"
#include "ardour/session_directory.h"
#include "pbd/i18n.h"
using namespace std;
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 const&) {
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, std::shared_ptr<Source> const & source)
{
sources.insert (SourcePair (filename, source));
}
std::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);
}
AudioRegionImporter::~AudioRegionImporter ()
{
}
string
AudioRegionImporter::get_info () const
{
samplecnt_t length, position;
Timecode::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 timecode
session.sample_to_timecode(length, length_time, true, false);
session.sample_to_timecode(position, position_time, true, false);
// return info
oss << _("Length: ") <<
timecode_to_string(length_time) <<
_("\nPosition: ") <<
timecode_to_string(position_time) <<
_("\nChannels: ") <<
xml_region.property ("channels")->value();
return oss.str();
}
bool
AudioRegionImporter::_prepare_move ()
{
return true;
}
void
AudioRegionImporter::_cancel_move ()
{
}
void
AudioRegionImporter::_move ()
{
if (!region_prepared) {
prepare_region();
if (!region_prepared) {
return;
}
}
if (broken()) {
return;
}
}
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.compare ("first-edit") ||
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 = RegionFactory::new_region_name (name);
(*it)->set_value (name);
name_ok = true;
} else {
std::cerr << string_compose (X_("AudioRegionImporter (%1): did not recognise XML-property \"%2\""), 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];
std::string source_dir(get_sound_dir (source));
XMLNode * source_node;
XMLProperty const * 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().c_str());
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 \"%2\""), 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())) {
prop = (*it)->property ("name");
if (!prop) {
error << string_compose (X_("AudioRegionImporter (%1): source %2 has no \"name\" property"), name, source_id) << endmsg;
return false;
}
filenames.push_back (Glib::build_filename (source_dir, prop->value()));
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;
}
std::string
AudioRegionImporter::get_sound_dir (XMLTree const & tree)
{
SessionDirectory session_dir(Glib::path_get_dirname (tree.filename()));
return session_dir.sound_path();
}
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
std::shared_ptr<Region> r = RegionFactory::create (source_list, xml_region);
region.push_back (r);
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;
}
status.total = 0;
status.replace_existing_source = false;
status.done = false;
status.cancel = false;
status.freeze = false;
status.import_markers = false;
status.progress = 0.0;
status.quality = SrcBest; // TODO other qualities also
status.replace_existing_source = false;
status.split_midi_channels = false;
status.import_markers = false;
// 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);
status.total++;
}
}
// import files
// TODO: threading & exception handling
session.import_files (status);
// Add imported sources to handlers map
std::vector<string>::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;
}

View File

@@ -1,408 +0,0 @@
/*
* Copyright (C) 2008-2009 Sakari Bergen <sakari.bergen@beatwaves.net>
* Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2009-2014 David Robillard <d@drobilla.net>
* Copyright (C) 2009-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2015-2018 Robin Gareus <robin@gareus.org>
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "ardour/audio_track_importer.h"
#include "ardour/audio_playlist_importer.h"
#include "ardour/disk_reader.h"
#include "ardour/session.h"
#include "pbd/controllable.h"
#include "pbd/failed_constructor.h"
#include "pbd/string_convert.h"
#include <sstream>
#include <algorithm>
#include "pbd/i18n.h"
using namespace std;
using namespace PBD;
using namespace ARDOUR;
/*** AudioTrackImportHandler ***/
AudioTrackImportHandler::AudioTrackImportHandler (XMLTree const & source, Session & session, AudioPlaylistImportHandler & pl_handler) :
ElementImportHandler (source, session)
{
XMLNode const * root = source.root();
XMLNode const * routes;
if (!(routes = root->child ("Routes"))) {
throw failed_constructor();
}
XMLNodeList const & route_list = routes->children();
for (XMLNodeList::const_iterator it = route_list.begin(); it != route_list.end(); ++it) {
XMLProperty const * type = (*it)->property("default-type");
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, pl_handler)));
} catch (failed_constructor const&) {
set_dirty();
}
}
}
}
string
AudioTrackImportHandler::get_info () const
{
return _("Audio Tracks");
}
/*** AudioTrackImporter ***/
AudioTrackImporter::AudioTrackImporter (XMLTree const & source,
Session & session,
AudioTrackImportHandler & track_handler,
XMLNode const & node,
AudioPlaylistImportHandler & pl_handler) :
ElementImporter (source, session),
track_handler (track_handler),
xml_track (node),
pl_handler (pl_handler)
{
XMLProperty * prop;
if (!parse_route_xml ()) {
throw failed_constructor();
}
if (!parse_io ()) {
throw failed_constructor();
}
XMLNodeList const & controllables = node.children (Controllable::xml_node_name);
for (XMLNodeList::const_iterator it = controllables.begin(); it != controllables.end(); ++it) {
parse_controllable (**it);
}
XMLNode * remote_control = xml_track.child ("RemoteControl");
if (remote_control && (prop = remote_control->property ("id"))) {
uint32_t control_id = session.ntracks() + session.nbusses() + 1;
prop->set_value (to_string (control_id));
}
xml_track.remove_nodes_and_delete ("Extra");
}
AudioTrackImporter::~AudioTrackImporter ()
{
playlists.clear ();
}
bool
AudioTrackImporter::parse_route_xml ()
{
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") ||
!prop.compare ("active") || !prop.compare ("muted") ||
!prop.compare ("soloed") || !prop.compare ("phase-invert") ||
!prop.compare ("denormal-protection") || !prop.compare("mute-affects-pre-fader") ||
!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("diskstream-id")) {
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;
}
bool
AudioTrackImporter::parse_io ()
{
XMLNode * io;
bool name_ok = false;
bool id_ok = false;
if (!(io = xml_track.child ("IO"))) {
return false;
}
XMLPropertyList const & props = io->properties();
for (XMLPropertyList::const_iterator it = props.begin(); it != props.end(); ++it) {
string prop = (*it)->name();
if (!prop.compare ("gain") || !prop.compare ("iolimits")) {
// All ok
} else if (!prop.compare("name")) {
name = (*it)->value();
name_ok = true;
} else if (!prop.compare("id")) {
PBD::ID id;
(*it)->set_value (id.to_s());
id_ok = true;
} else if (!prop.compare("inputs")) {
// TODO Handle this properly!
/* Input and output ports are counted and added empty, so that no in/output connecting function fails. */
uint32_t num_inputs = std::count ((*it)->value().begin(), (*it)->value().end(), '{');
std::string value;
for (uint32_t i = 0; i < num_inputs; i++) { value += "{}"; }
(*it)->set_value (value);
} else if (!prop.compare("outputs")) {
// TODO See comments above
uint32_t num_outputs = std::count ((*it)->value().begin(), (*it)->value().end(), '{');
std::string value;
for (uint32_t i = 0; i < num_outputs; i++) { value += "{}"; }
(*it)->set_value (value);
} else {
std::cerr << string_compose (X_("AudioTrackImporter: did not recognise XML-property \"%1\""), prop) << endmsg;
}
}
if (!name_ok) {
error << X_("AudioTrackImporter: did not find necessary XML-property \"name\"") << endmsg;
return false;
}
if (!id_ok) {
error << X_("AudioTrackImporter: did not find necessary XML-property \"id\"") << endmsg;
return false;
}
XMLNodeList const & controllables = io->children (Controllable::xml_node_name);
for (XMLNodeList::const_iterator it = controllables.begin(); it != controllables.end(); ++it) {
parse_controllable (**it);
}
XMLNodeList const & processors = io->children ("Processor");
for (XMLNodeList::const_iterator it = processors.begin(); it != processors.end(); ++it) {
parse_processor (**it);
}
XMLNodeList const & automations = io->children ("Automation");
for (XMLNodeList::const_iterator it = automations.begin(); it != automations.end(); ++it) {
parse_automation (**it);
}
return true;
}
string
AudioTrackImporter::get_info () const
{
// TODO
return name;
}
/** @return true if everything is ok */
bool
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;
}
XMLNode* c = xml_track.child ("IO");
if (!c) {
error << _("badly-formed XML in imported track") << endmsg;
return false;
}
XMLProperty * p = c->property ("name");
if (!p) {
error << _("badly-formed XML in imported track") << endmsg;
return false;
}
p->set_value (name);
track_handler.add_name (name);
return true;
}
void
AudioTrackImporter::_cancel_move ()
{
track_handler.remove_name (name);
playlists.clear ();
}
void
AudioTrackImporter::_move ()
{
/* XXX DISK */
#if 0
/* Add diskstream */
std::shared_ptr<XMLSharedNodeList> ds_node_list;
string xpath = "/Session/DiskStreams/AudioDiskstream[@id='" + old_ds_id.to_s() + "']";
ds_node_list = source.find (xpath);
if (ds_node_list->size() != 1) {
error << string_compose (_("Error Importing Audio track %1"), name) << endmsg;
return;
}
std::shared_ptr<XMLNode> ds_node = ds_node_list->front();
XMLProperty * p = ds_node->property (X_("id"));
assert (p);
p->set_value (new_ds_id.to_s());
std::shared_ptr<DiskReader> new_ds (new DiskReader (session, *ds_node));
new_ds->set_name (name);
new_ds->do_refill_with_alloc (true, false);
new_ds->set_block_size (session.get_block_size ());
/* Import playlists */
for (PlaylistList::const_iterator it = playlists.begin(); it != playlists.end(); ++it) {
(*it)->move ();
}
/* Import track */
XMLNode routes ("Routes");
routes.add_child_copy (xml_track);
session.load_routes (routes, 3000);
#endif
}
bool
AudioTrackImporter::parse_processor (XMLNode & node)
{
XMLNode * automation = node.child ("Automation");
if (automation) {
parse_automation (*automation);
}
return true;
}
bool
AudioTrackImporter::parse_controllable (XMLNode & node)
{
XMLProperty * prop;
if ((prop = node.property ("id"))) {
PBD::ID new_id;
prop->set_value (new_id.to_s());
} else {
return false;
}
return true;
}
bool
AudioTrackImporter::parse_automation (XMLNode & node)
{
XMLNodeList const & lists = node.children ("AutomationList");
for (XMLNodeList::const_iterator it = lists.begin(); it != lists.end(); ++it) {
XMLProperty * prop;
if ((prop = (*it)->property ("id"))) {
PBD::ID id;
prop->set_value (id.to_s());
}
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;
samplecnt_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

@@ -1,109 +0,0 @@
/*
* Copyright (C) 2008 Sakari Bergen <sakari.bergen@beatwaves.net>
* Copyright (C) 2009-2010 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2009-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2009 David Robillard <d@drobilla.net>
* Copyright (C) 2016 Tim Mayberry <mojofunk@gmail.com>
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "ardour/element_importer.h"
#include <sstream>
#include <iomanip>
#include "pbd/string_convert.h"
#include "ardour/session.h"
#include "pbd/i18n.h"
using namespace std;
using namespace PBD;
using namespace ARDOUR;
PBD::Signal<std::pair<bool, string>(string, string)> ElementImporter::Rename;
PBD::Signal<bool(string)> ElementImporter::Prompt;
ElementImporter::ElementImporter (XMLTree const & source, ARDOUR::Session & session) :
source (source),
session(session),
_queued (false),
_broken (false)
{
source.root()->get_property ("sample-rate", sample_rate);
}
ElementImporter::~ElementImporter ()
{
}
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::timecode_to_string(Timecode::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();
}
samplecnt_t
ElementImporter::rate_convert_samples (samplecnt_t samples) const
{
if (sample_rate == session.sample_rate()) {
return samples;
}
// +0.5 for proper rounding
return static_cast<samplecnt_t> (samples * (static_cast<double> (session.nominal_sample_rate()) / sample_rate) + 0.5);
}
string
ElementImporter::rate_convert_samples (string const & samples) const
{
return to_string (rate_convert_samples (string_to<uint32_t>(samples)));
}

View File

@@ -1,191 +0,0 @@
/*
* Copyright (C) 2008-2010 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2008 Sakari Bergen <sakari.bergen@beatwaves.net>
* Copyright (C) 2009-2010 David Robillard <d@drobilla.net>
* Copyright (C) 2009-2017 Paul Davis <paul@linuxaudiosystems.com>
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "ardour/location_importer.h"
#include <sstream>
#include <stdexcept>
#include "ardour/session.h"
#include "pbd/convert.h"
#include "pbd/failed_constructor.h"
#include "pbd/i18n.h"
using namespace std;
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 const&) {
_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()) {
delete location;
}
}
string
LocationImporter::get_info () const
{
samplepos_t start, end;
Timecode::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 timecode
session.sample_to_timecode (start, start_time, true, false);
session.sample_to_timecode (end, end_time, true, false);
// return info
std::ostringstream oss;
if (start == end) {
oss << _("Location: ") << timecode_to_string (start_time);
} else {
oss << _("Range\nstart: ") << timecode_to_string (start_time) <<
_("\nend: ") << timecode_to_string (end_time);
}
return oss.str();
}
bool
LocationImporter::_prepare_move ()
{
try {
Location const original (session, xml_location);
location = new Location (original, false); // 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);
return true;
}
void
LocationImporter::_cancel_move ()
{
delete location;
location = 0;
}
void
LocationImporter::_move ()
{
session.locations()->add (location);
}

View File

@@ -1,105 +0,0 @@
/*
* Copyright (C) 2008 Sakari Bergen <sakari.bergen@beatwaves.net>
* Copyright (C) 2009-2012 David Robillard <d@drobilla.net>
* Copyright (C) 2009-2016 Paul Davis <paul@linuxaudiosystems.com>
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "ardour/tempo_map_importer.h"
#include <sstream>
#include "ardour/session.h"
#include "ardour/tempo.h"
#include "pbd/failed_constructor.h"
#include "pbd/i18n.h"
using namespace std;
using namespace PBD;
using namespace ARDOUR;
using namespace Temporal;
/**** 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
std::optional<bool> replace = Prompt (_("This will replace the current tempo map!\nAre you sure you want to do this?"));
return replace.value_or (false);
}
void
TempoMapImporter::_cancel_move ()
{
}
void
TempoMapImporter::_move ()
{
TempoMap::WritableSharedPtr tmap (TempoMap::write_copy());
tmap->set_state (xml_tempo_map, Stateful::current_state_version);
TempoMap::update (tmap);
}

View File

@@ -20,12 +20,9 @@ libardour_sources = [
'audio_buffer.cc',
'audio_library.cc',
'audio_playlist.cc',
'audio_playlist_importer.cc',
'audio_playlist_source.cc',
'audio_port.cc',
'audio_region_importer.cc',
'audio_track.cc',
'audio_track_importer.cc',
'audioanalyser.cc',
'audioengine.cc',
'audiofile_tagger.cc',
@@ -67,7 +64,6 @@ libardour_sources = [
'dsp_filter.cc',
'ebur128_analysis.cc',
'element_import_handler.cc',
'element_importer.cc',
'engine_slave.cc',
'enums.cc',
'event_type_map.cc',
@@ -117,7 +113,6 @@ libardour_sources = [
'legatize.cc',
'library.cc',
'location.cc',
'location_importer.cc',
'ltc_file_reader.cc',
'ltc_slave.cc',
'lua_api.cc',
@@ -261,7 +256,6 @@ libardour_sources = [
'rt_midibuffer.cc',
'tailtime.cc',
'template_utils.cc',
'tempo_map_importer.cc',
'thawlist.cc',
'thread_buffers.cc',
'ticker.cc',