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;
140 /* we must be careful not to read beyond the end of our "section" of
141 * the playlist, because otherwise we may read data that exists, but
142 * is not supposed be part of our data.
145 if (cnt > _playlist_length - start) {
146 to_read = _playlist_length - start;
147 to_zero = cnt - to_read;
154 /* Don't need to hold the lock for the actual read, and
155 actually, we cannot, but we do want to interlock
156 with any changes to the list of buffers caused
157 by creating new nested playlists/sources
159 Glib::Mutex::Lock lm (_level_buffer_lock);
160 sbuf = _mixdown_buffers[_level-1];
161 gbuf = _gain_buffers[_level-1];
164 boost::dynamic_pointer_cast<AudioPlaylist>(_playlist)->read (dst, sbuf.get(), gbuf.get(), start+_playlist_offset, to_read, _playlist_channel);
167 memset (dst+to_read, 0, sizeof (Sample) * to_zero);
174 AudioPlaylistSource::write_unlocked (Sample *, framecnt_t)
176 fatal << string_compose (_("programming error: %1"), "AudioPlaylistSource::write() called - should be impossible") << endmsg;
182 AudioPlaylistSource::empty () const
184 return !_playlist || _playlist->empty();
188 AudioPlaylistSource::n_channels () const
190 /* use just the first region to decide */
196 boost::shared_ptr<Region> r = _playlist->region_list().front ();
197 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
199 return ar->audio_source()->n_channels ();
203 AudioPlaylistSource::sample_rate () const
205 /* use just the first region to decide */
208 _session.frame_rate ();
211 boost::shared_ptr<Region> r = _playlist->region_list().front ();
212 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
214 return ar->audio_source()->sample_rate ();
218 AudioPlaylistSource::setup_peakfile ()
220 _peak_path = Glib::build_filename (_session.session_directory().peak_path().to_string(), name() + ARDOUR::peakfile_suffix);
221 return initialize_peakfile (false, string());
225 AudioPlaylistSource::peak_path (string /*audio_path_IGNORED*/)