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 ();
76 AudioSource::_length = _playlist_length;
79 AudioPlaylistSource::~AudioPlaylistSource ()
84 AudioPlaylistSource::get_state ()
86 XMLNode& node (AudioSource::get_state ());
89 /* merge PlaylistSource state */
91 PlaylistSource::add_state (node);
93 snprintf (buf, sizeof (buf), "%" PRIu32, _playlist_channel);
94 node.add_property ("channel", buf);
100 AudioPlaylistSource::set_state (const XMLNode& node, int version)
102 return set_state (node, version, true);
106 AudioPlaylistSource::set_state (const XMLNode& node, int version, bool with_descendants)
108 if (with_descendants) {
109 if (Source::set_state (node, version) ||
110 PlaylistSource::set_state (node, version) ||
111 AudioSource::set_state (node, version)) {
116 const XMLProperty* prop;
117 pair<framepos_t,framepos_t> extent = _playlist->get_extent();
119 cerr << "APS " << id() << " playlist ID " << _playlist->id() << " has " << _playlist->n_regions() << " playlist extents = " << extent.first << " .. " << extent.second << endl;
121 AudioSource::_length = extent.second - extent.first;
123 if ((prop = node.property (X_("channel"))) == 0) {
124 throw failed_constructor ();
127 sscanf (prop->value().c_str(), "%" PRIu32, &_playlist_channel);
129 ensure_buffers_for_level (_level, _session.frame_rate());
135 AudioPlaylistSource::read_unlocked (Sample* dst, framepos_t start, framecnt_t cnt) const
137 boost::shared_ptr<Sample> sbuf;
138 boost::shared_ptr<gain_t> gbuf;
141 pair<framepos_t,framepos_t> extent = _playlist->get_extent();
143 /* we must be careful not to read beyond the end of our "section" of
144 * the playlist, because otherwise we may read data that exists, but
145 * is not supposed be part of our data.
148 if (cnt > _playlist_length - start) {
149 to_read = _playlist_length - start;
150 to_zero = cnt - to_read;
157 /* Don't need to hold the lock for the actual read, and
158 actually, we cannot, but we do want to interlock
159 with any changes to the list of buffers caused
160 by creating new nested playlists/sources
162 Glib::Mutex::Lock lm (_level_buffer_lock);
163 sbuf = _mixdown_buffers[_level-1];
164 gbuf = _gain_buffers[_level-1];
167 boost::dynamic_pointer_cast<AudioPlaylist>(_playlist)->read (dst, sbuf.get(), gbuf.get(), start+_playlist_offset, to_read, _playlist_channel);
170 memset (dst+to_read, 0, sizeof (Sample) * to_zero);
177 AudioPlaylistSource::write_unlocked (Sample *src, framecnt_t cnt)
179 fatal << string_compose (_("programming error: %1"), "AudioPlaylistSource::write() called - should be impossible") << endmsg;
185 AudioPlaylistSource::empty () const
187 return !_playlist || _playlist->empty();
191 AudioPlaylistSource::n_channels () const
193 /* use just the first region to decide */
199 boost::shared_ptr<Region> r = _playlist->region_list().front ();
200 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
202 return ar->audio_source()->n_channels ();
206 AudioPlaylistSource::sample_rate () const
208 /* use just the first region to decide */
211 _session.frame_rate ();
214 boost::shared_ptr<Region> r = _playlist->region_list().front ();
215 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
217 return ar->audio_source()->sample_rate ();
221 AudioPlaylistSource::setup_peakfile ()
223 _peak_path = Glib::build_filename (_session.session_directory().peak_path().to_string(), name() + ARDOUR::peakfile_suffix);
224 return initialize_peakfile (false, string());
228 AudioPlaylistSource::peak_path (string /*audio_path_IGNORED*/)