2 Copyright (C) 2011 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "libardour-config.h"
26 #include <glibmm/fileutils.h>
27 #include <glibmm/miscutils.h>
29 #include "pbd/error.h"
30 #include "pbd/convert.h"
31 #include "pbd/enumwriter.h"
33 #include "ardour/audioplaylist.h"
34 #include "ardour/audio_playlist_source.h"
35 #include "ardour/audioregion.h"
36 #include "ardour/debug.h"
37 #include "ardour/filename_extensions.h"
38 #include "ardour/session.h"
39 #include "ardour/session_directory.h"
40 #include "ardour/session_playlists.h"
41 #include "ardour/source_factory.h"
46 using namespace ARDOUR;
49 AudioPlaylistSource::AudioPlaylistSource (Session& s, const ID& orig, const std::string& name, boost::shared_ptr<AudioPlaylist> p,
50 uint32_t chn, frameoffset_t begin, framecnt_t len, Source::Flag flags)
51 : Source (s, DataType::AUDIO, name)
52 , PlaylistSource (s, orig, name, p, DataType::AUDIO, begin, len, flags)
53 , AudioSource (s, name)
54 , _playlist_channel (chn)
56 AudioSource::_length = len;
57 ensure_buffers_for_level (_level, _session.frame_rate());
60 AudioPlaylistSource::AudioPlaylistSource (Session& s, const XMLNode& node)
62 , PlaylistSource (s, node)
63 , AudioSource (s, node)
65 /* PlaylistSources are never writable, renameable, removable or destructive */
66 _flags = Flag (_flags & ~(Writable|CanRename|Removable|RemovableIfEmpty|RemoveAtDestroy|Destructive));
68 /* ancestors have already called ::set_state() in their XML-based
72 if (set_state (node, Stateful::loading_state_version, false)) {
73 throw failed_constructor ();
77 AudioPlaylistSource::~AudioPlaylistSource ()
82 AudioPlaylistSource::get_state ()
84 XMLNode& node (AudioSource::get_state ());
87 /* merge PlaylistSource state */
89 PlaylistSource::add_state (node);
91 snprintf (buf, sizeof (buf), "%" PRIu32, _playlist_channel);
92 node.add_property ("channel", buf);
98 AudioPlaylistSource::set_state (const XMLNode& node, int version)
100 return set_state (node, version, true);
104 AudioPlaylistSource::set_state (const XMLNode& node, int version, bool with_descendants)
106 if (with_descendants) {
107 if (Source::set_state (node, version) ||
108 PlaylistSource::set_state (node, version) ||
109 AudioSource::set_state (node, version)) {
114 const XMLProperty* prop;
115 pair<framepos_t,framepos_t> extent = _playlist->get_extent();
116 AudioSource::_length = extent.second - extent.first;
118 if ((prop = node.property (X_("channel"))) == 0) {
119 throw failed_constructor ();
122 sscanf (prop->value().c_str(), "%" PRIu32, &_playlist_channel);
124 ensure_buffers_for_level (_level, _session.frame_rate());
130 AudioPlaylistSource::read_unlocked (Sample* dst, framepos_t start, framecnt_t cnt) const
132 boost::shared_ptr<Sample> sbuf;
133 boost::shared_ptr<gain_t> gbuf;
136 pair<framepos_t,framepos_t> extent = _playlist->get_extent();
138 /* we must be careful not to read beyond the end of our "section" of
139 * the playlist, because otherwise we may read data that exists, but
140 * is not supposed be part of our data.
143 if (cnt > _playlist_length - start) {
144 to_read = _playlist_length - start;
145 to_zero = cnt - to_read;
152 /* Don't need to hold the lock for the actual read, and
153 actually, we cannot, but we do want to interlock
154 with any changes to the list of buffers caused
155 by creating new nested playlists/sources
157 Glib::Mutex::Lock lm (_level_buffer_lock);
158 sbuf = _mixdown_buffers[_level-1];
159 gbuf = _gain_buffers[_level-1];
162 boost::dynamic_pointer_cast<AudioPlaylist>(_playlist)->read (dst, sbuf.get(), gbuf.get(), start+_playlist_offset, to_read, _playlist_channel);
165 memset (dst+to_read, 0, sizeof (Sample) * to_zero);
172 AudioPlaylistSource::write_unlocked (Sample *src, framecnt_t cnt)
174 fatal << string_compose (_("programming error: %1"), "AudioPlaylistSource::write() called - should be impossible") << endmsg;
180 AudioPlaylistSource::empty () const
182 return !_playlist || _playlist->empty();
186 AudioPlaylistSource::n_channels () const
188 /* use just the first region to decide */
194 boost::shared_ptr<Region> r = _playlist->region_list().front ();
195 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
197 return ar->audio_source()->n_channels ();
201 AudioPlaylistSource::sample_rate () const
203 /* use just the first region to decide */
206 _session.frame_rate ();
209 boost::shared_ptr<Region> r = _playlist->region_list().front ();
210 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
212 return ar->audio_source()->sample_rate ();
216 AudioPlaylistSource::setup_peakfile ()
218 _peak_path = Glib::build_filename (_session.session_directory().peak_path().to_string(), name() + ARDOUR::peakfile_suffix);
219 return initialize_peakfile (false, string());
223 AudioPlaylistSource::peak_path (string /*audio_path_IGNORED*/)