From 4b5bd4ca46fe00a473682bf21927a0d67ac1a3a4 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 16 May 2011 15:49:26 +0000 Subject: [PATCH] refactor playlist sources to allow for MIDI and upcoming work on save/restore git-svn-id: svn://localhost/ardour2/branches/3.0@9521 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/audio_playlist_source.h | 15 +-- libs/ardour/ardour/playlist_source.h | 55 +++++++++ libs/ardour/audio_playlist_source.cc | 99 ++++++---------- libs/ardour/file_source.cc | 2 +- libs/ardour/playlist_source.cc | 132 +++++++++++++++++++++ libs/ardour/source_factory.cc | 10 +- libs/ardour/wscript | 1 + 7 files changed, 240 insertions(+), 74 deletions(-) create mode 100644 libs/ardour/ardour/playlist_source.h create mode 100644 libs/ardour/playlist_source.cc diff --git a/libs/ardour/ardour/audio_playlist_source.h b/libs/ardour/ardour/audio_playlist_source.h index d6047de1fc..3514a06407 100644 --- a/libs/ardour/ardour/audio_playlist_source.h +++ b/libs/ardour/ardour/audio_playlist_source.h @@ -26,16 +26,17 @@ #include "ardour/ardour.h" #include "ardour/audiosource.h" +#include "ardour/playlist_source.h" namespace ARDOUR { class AudioPlaylist; -class AudioPlaylistSource : public AudioSource { +class AudioPlaylistSource : public AudioSource, public PlaylistSource { public: virtual ~AudioPlaylistSource (); - - bool empty() const; + + bool empty() const; std::string peak_path (std::string audio_path); uint32_t n_channels() const; bool clamped_at_unity () const { return false; } @@ -56,15 +57,15 @@ class AudioPlaylistSource : public AudioSource { friend class SourceFactory; AudioPlaylistSource (Session&, const std::string& name, boost::shared_ptr, uint32_t chn, - frameoffset_t begin, framecnt_t len, bool copy, Source::Flag flags); + frameoffset_t begin, framecnt_t len, Source::Flag flags); AudioPlaylistSource (Session&, const XMLNode&); private: - boost::shared_ptr _playlist; - frameoffset_t _playlist_offset; - framecnt_t _playlist_length; uint32_t _playlist_channel; std::string _peak_path; + + int set_state (const XMLNode&, int version, bool with_descendants); + }; } /* namespace */ diff --git a/libs/ardour/ardour/playlist_source.h b/libs/ardour/ardour/playlist_source.h new file mode 100644 index 0000000000..8732870ec0 --- /dev/null +++ b/libs/ardour/ardour/playlist_source.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2011 Paul Davis + + 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_playlist_source_h__ +#define __ardour_playlist_source_h__ + +#include + +#include + +#include "ardour/ardour.h" +#include "ardour/source.h" + +namespace ARDOUR { + +class Playlist; + +class PlaylistSource : virtual public Source { + public: + virtual ~PlaylistSource (); + + int set_state (const XMLNode&, int version); + + protected: + boost::shared_ptr _playlist; + frameoffset_t _playlist_offset; + framecnt_t _playlist_length; + + PlaylistSource (Session&, const std::string& name, boost::shared_ptr, DataType, + frameoffset_t begin, framecnt_t len, Source::Flag flags); + PlaylistSource (Session&, const XMLNode&); + + void add_state (XMLNode&); + +}; + +} /* namespace */ + +#endif /* __ardour_playlist_source_h__ */ diff --git a/libs/ardour/audio_playlist_source.cc b/libs/ardour/audio_playlist_source.cc index e8fabef7b1..2160b9bd3a 100644 --- a/libs/ardour/audio_playlist_source.cc +++ b/libs/ardour/audio_playlist_source.cc @@ -46,39 +46,33 @@ using namespace ARDOUR; using namespace PBD; AudioPlaylistSource::AudioPlaylistSource (Session& s, const std::string& name, boost::shared_ptr p, - uint32_t chn, frameoffset_t begin, framecnt_t len, bool copy, Source::Flag flags) + uint32_t chn, frameoffset_t begin, framecnt_t len, Source::Flag flags) : Source (s, DataType::AUDIO, name) , AudioSource (s, name) - , _playlist (p) + , PlaylistSource (s, name, p, DataType::AUDIO, begin, len, flags) , _playlist_channel (chn) { - /* PlaylistSources are never writable, renameable, removable or destructive */ - _flags = Flag (_flags & ~(Writable|CanRename|Removable|RemovableIfEmpty|RemoveAtDestroy|Destructive)); - - if (!copy) { - _playlist = p; - _playlist_offset = begin; - _playlist_length = len; - } else { - _playlist.reset (new AudioPlaylist (p, begin, len, "XXXNAMEXXX", true)); - _playlist_offset = 0; - _playlist_length = len; - } - - _length = len; _peak_path = Glib::build_filename (_session.session_directory().peak_path().to_string(), name); - _level = _playlist->max_source_level () + 1; + + AudioSource::_length = len; ensure_buffers_for_level (_level); } AudioPlaylistSource::AudioPlaylistSource (Session& s, const XMLNode& node) : Source (s, DataType::AUDIO, "toBeRenamed") , AudioSource (s, node) + , PlaylistSource (s, node) { /* PlaylistSources are never writable, renameable, removable or destructive */ _flags = Flag (_flags & ~(Writable|CanRename|Removable|RemovableIfEmpty|RemoveAtDestroy|Destructive)); + + /* ancestors have already called ::set_state() in their XML-based + constructors. + */ - set_state (node, 3000); + if (set_state (node, Stateful::loading_state_version, false)) { + throw failed_constructor (); + } } AudioPlaylistSource::~AudioPlaylistSource () @@ -90,61 +84,39 @@ AudioPlaylistSource::get_state () { XMLNode& node (AudioSource::get_state ()); char buf[64]; - snprintf (buf, sizeof (buf), "%" PRIi64, _playlist_offset); - node.add_property ("offset", buf); - snprintf (buf, sizeof (buf), "%" PRIu64, _playlist_length); - node.add_property ("length", buf); + + /* merge PlaylistSource state */ + + PlaylistSource::add_state (node); + snprintf (buf, sizeof (buf), "%" PRIu32, _playlist_channel); node.add_property ("channel", buf); - node.add_property ("name", name()); node.add_property ("peak-path", _peak_path); return node; } -int -AudioPlaylistSource::set_state (const XMLNode& node, int /* version */) -{ - /* get playlist ID */ - - const XMLProperty *prop = node.property (X_("playlist")); - - if (!prop) { - throw failed_constructor (); - } - - PBD::ID id (prop->value()); - - /* get playlist */ - - boost::shared_ptr p = _session.playlists->by_id (id); - _playlist = boost::dynamic_pointer_cast(p); - - if (!_playlist) { - throw failed_constructor (); - } - - pair extent = _playlist->get_extent(); - _length = extent.second - extent.first; - - /* other properties */ - - if ((prop = node.property (X_("name"))) == 0) { - throw failed_constructor (); - } - set_name (prop->value()); +int +AudioPlaylistSource::set_state (const XMLNode& node, int version) +{ + return set_state (node, version, true); +} - if ((prop = node.property (X_("offset"))) == 0) { - throw failed_constructor (); - } - sscanf (prop->value().c_str(), "%" PRIi64, &_playlist_offset); - - if ((prop = node.property (X_("length"))) == 0) { - throw failed_constructor (); +int +AudioPlaylistSource::set_state (const XMLNode& node, int version, bool with_descendants) +{ + if (with_descendants) { + if (Source::set_state (node, version) || + AudioSource::set_state (node, version) || + PlaylistSource::set_state (node, version)) { + return -1; + } } - sscanf (prop->value().c_str(), "%" PRIu64, &_playlist_length); + const XMLProperty* prop; + pair extent = _playlist->get_extent(); + AudioSource::_length = extent.second - extent.first; if ((prop = node.property (X_("channel"))) == 0) { throw failed_constructor (); @@ -158,7 +130,6 @@ AudioPlaylistSource::set_state (const XMLNode& node, int /* version */) _peak_path = prop->value (); - _level = _playlist->max_source_level () + 1; ensure_buffers_for_level (_level); return 0; @@ -197,7 +168,7 @@ AudioPlaylistSource::read_unlocked (Sample* dst, framepos_t start, framecnt_t cn gbuf = _gain_buffers[_level-1]; } - _playlist->read (dst, sbuf, gbuf, start+_playlist_offset, to_read, _playlist_channel); + boost::dynamic_pointer_cast(_playlist)->read (dst, sbuf, gbuf, start+_playlist_offset, to_read, _playlist_channel); if (to_zero) { memset (dst+to_read, 0, sizeof (Sample) * to_zero); diff --git a/libs/ardour/file_source.cc b/libs/ardour/file_source.cc index e6990aa487..eb6978c6e8 100644 --- a/libs/ardour/file_source.cc +++ b/libs/ardour/file_source.cc @@ -68,7 +68,7 @@ FileSource::FileSource (Session& session, DataType type, const string& path, con } FileSource::FileSource (Session& session, const XMLNode& node, bool /*must_exist*/) - : Source(session, node) + : Source (session, node) , _file_is_new (false) { /* this setting of _path is temporary - we expect derived classes diff --git a/libs/ardour/playlist_source.cc b/libs/ardour/playlist_source.cc new file mode 100644 index 0000000000..7ac175959c --- /dev/null +++ b/libs/ardour/playlist_source.cc @@ -0,0 +1,132 @@ +/* + Copyright (C) 2011 Paul Davis + + 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. +*/ + +#ifdef WAF_BUILD +#include "libardour-config.h" +#endif + +#include +#include + +#include +#include + +#include "pbd/error.h" +#include "pbd/convert.h" +#include "pbd/enumwriter.h" + +#include "ardour/playlist.h" +#include "ardour/playlist_source.h" +#include "ardour/session.h" +#include "ardour/session_playlists.h" +#include "ardour/source_factory.h" + +#include "i18n.h" + +using namespace std; +using namespace ARDOUR; +using namespace PBD; + +PlaylistSource::PlaylistSource (Session& s, const std::string& name, boost::shared_ptr p, DataType type, + frameoffset_t begin, framecnt_t len, Source::Flag flags) + : Source (s, type, name) + , _playlist (p) +{ + /* PlaylistSources are never writable, renameable, removable or destructive */ + _flags = Flag (_flags & ~(Writable|CanRename|Removable|RemovableIfEmpty|RemoveAtDestroy|Destructive)); + + _playlist = p; + _playlist_offset = begin; + _playlist_length = len; + + _level = _playlist->max_source_level () + 1; +} + +PlaylistSource::PlaylistSource (Session& s, const XMLNode& node) + : Source (s, DataType::AUDIO, "toBeRenamed") +{ + /* PlaylistSources are never writable, renameable, removable or destructive */ + _flags = Flag (_flags & ~(Writable|CanRename|Removable|RemovableIfEmpty|RemoveAtDestroy|Destructive)); + + + if (set_state (node, Stateful::loading_state_version)) { + throw failed_constructor (); + } +} + +PlaylistSource::~PlaylistSource () +{ +} + +void +PlaylistSource::add_state (XMLNode& node) +{ + char buf[64]; + + _playlist->id().print (buf, sizeof (buf)); + node.add_property ("playlist", buf); + snprintf (buf, sizeof (buf), "%" PRIi64, _playlist_offset); + node.add_property ("offset", buf); + snprintf (buf, sizeof (buf), "%" PRIu64, _playlist_length); + node.add_property ("length", buf); +} + +int +PlaylistSource::set_state (const XMLNode& node, int version) +{ + /* get playlist ID */ + + const XMLProperty *prop = node.property (X_("playlist")); + + if (!prop) { + throw failed_constructor (); + } + + PBD::ID id (prop->value()); + + /* get playlist */ + + boost::shared_ptr p = _session.playlists->by_id (id); + + if (!_playlist) { + throw failed_constructor (); + } + + /* other properties */ + + if ((prop = node.property (X_("name"))) == 0) { + throw failed_constructor (); + } + + set_name (prop->value()); + + if ((prop = node.property (X_("offset"))) == 0) { + throw failed_constructor (); + } + sscanf (prop->value().c_str(), "%" PRIi64, &_playlist_offset); + + if ((prop = node.property (X_("length"))) == 0) { + throw failed_constructor (); + } + + sscanf (prop->value().c_str(), "%" PRIu64, &_playlist_length); + + _level = _playlist->max_source_level () + 1; + + return 0; +} diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc index 1bf3956694..4d3f02b1dc 100644 --- a/libs/ardour/source_factory.cc +++ b/libs/ardour/source_factory.cc @@ -332,9 +332,15 @@ SourceFactory::createFromPlaylist (DataType type, Session& s, boost::shared_ptr< try { boost::shared_ptr ap = boost::dynamic_pointer_cast(p); - + if (ap) { - Source* src = new AudioPlaylistSource (s, name, ap, chn, start, len, copy, Source::Flag (0)); + + if (copy) { + ap.reset (new AudioPlaylist (ap, start, len, name, true)); + start = 0; + } + + Source* src = new AudioPlaylistSource (s, name, ap, chn, start, len, Source::Flag (0)); boost::shared_ptr ret (src); if (setup_peakfile (ret, defer_peaks)) { diff --git a/libs/ardour/wscript b/libs/ardour/wscript index 9669d7b1b6..1b344d34ef 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -150,6 +150,7 @@ libardour_sources = [ 'pi_controller.cc', 'playlist.cc', 'playlist_factory.cc', + 'playlist_source.cc', 'plugin.cc', 'plugin_insert.cc', 'plugin_manager.cc',