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 AudioSource::_length = extent.second - extent.first;
121 if ((prop = node.property (X_("channel"))) == 0) {
122 throw failed_constructor ();
125 sscanf (prop->value().c_str(), "%" PRIu32, &_playlist_channel);
127 ensure_buffers_for_level (_level, _session.frame_rate());
133 AudioPlaylistSource::read_unlocked (Sample* dst, framepos_t start, framecnt_t cnt) const
135 boost::shared_ptr<Sample> sbuf;
136 boost::shared_ptr<gain_t> gbuf;
139 pair<framepos_t,framepos_t> extent = _playlist->get_extent();
141 /* we must be careful not to read beyond the end of our "section" of
142 * the playlist, because otherwise we may read data that exists, but
143 * is not supposed be part of our data.
146 if (cnt > _playlist_length - start) {
147 to_read = _playlist_length - start;
148 to_zero = cnt - to_read;
155 /* Don't need to hold the lock for the actual read, and
156 actually, we cannot, but we do want to interlock
157 with any changes to the list of buffers caused
158 by creating new nested playlists/sources
160 Glib::Mutex::Lock lm (_level_buffer_lock);
161 sbuf = _mixdown_buffers[_level-1];
162 gbuf = _gain_buffers[_level-1];
165 boost::dynamic_pointer_cast<AudioPlaylist>(_playlist)->read (dst, sbuf.get(), gbuf.get(), start+_playlist_offset, to_read, _playlist_channel);
168 memset (dst+to_read, 0, sizeof (Sample) * to_zero);
175 AudioPlaylistSource::write_unlocked (Sample *src, framecnt_t cnt)
177 fatal << string_compose (_("programming error: %1"), "AudioPlaylistSource::write() called - should be impossible") << endmsg;
183 AudioPlaylistSource::empty () const
185 return !_playlist || _playlist->empty();
189 AudioPlaylistSource::n_channels () const
191 /* use just the first region to decide */
197 boost::shared_ptr<Region> r = _playlist->region_list().front ();
198 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
200 return ar->audio_source()->n_channels ();
204 AudioPlaylistSource::sample_rate () const
206 /* use just the first region to decide */
209 _session.frame_rate ();
212 boost::shared_ptr<Region> r = _playlist->region_list().front ();
213 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
215 return ar->audio_source()->sample_rate ();
219 AudioPlaylistSource::setup_peakfile ()
221 _peak_path = Glib::build_filename (_session.session_directory().peak_path().to_string(), name() + ARDOUR::peakfile_suffix);
222 return initialize_peakfile (false, string());
226 AudioPlaylistSource::peak_path (string /*audio_path_IGNORED*/)