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"
31 #include "ardour/audioplaylist.h"
32 #include "ardour/audio_playlist_source.h"
33 #include "ardour/audioregion.h"
34 #include "ardour/filename_extensions.h"
35 #include "ardour/session.h"
36 #include "ardour/session_directory.h"
41 using namespace ARDOUR;
44 AudioPlaylistSource::AudioPlaylistSource (Session& s, const ID& orig, const std::string& name, boost::shared_ptr<AudioPlaylist> p,
45 uint32_t chn, frameoffset_t begin, framecnt_t len, Source::Flag flags)
46 : Source (s, DataType::AUDIO, name)
47 , PlaylistSource (s, orig, name, p, DataType::AUDIO, begin, len, flags)
48 , AudioSource (s, name)
49 , _playlist_channel (chn)
51 AudioSource::_length = len;
52 ensure_buffers_for_level (_level, _session.frame_rate());
55 AudioPlaylistSource::AudioPlaylistSource (Session& s, const XMLNode& node)
57 , PlaylistSource (s, node)
58 , AudioSource (s, node)
60 /* PlaylistSources are never writable, renameable, removable or destructive */
61 _flags = Flag (_flags & ~(Writable|CanRename|Removable|RemovableIfEmpty|RemoveAtDestroy|Destructive));
63 /* ancestors have already called ::set_state() in their XML-based
67 if (set_state (node, Stateful::loading_state_version, false)) {
68 throw failed_constructor ();
71 AudioSource::_length = _playlist_length;
74 AudioPlaylistSource::~AudioPlaylistSource ()
79 AudioPlaylistSource::get_state ()
81 XMLNode& node (AudioSource::get_state ());
84 /* merge PlaylistSource state */
86 PlaylistSource::add_state (node);
88 snprintf (buf, sizeof (buf), "%" PRIu32, _playlist_channel);
89 node.add_property ("channel", buf);
95 AudioPlaylistSource::set_state (const XMLNode& node, int version)
97 return set_state (node, version, true);
101 AudioPlaylistSource::set_state (const XMLNode& node, int version, bool with_descendants)
103 if (with_descendants) {
104 if (Source::set_state (node, version) ||
105 PlaylistSource::set_state (node, version) ||
106 AudioSource::set_state (node, version)) {
111 XMLProperty const * prop;
112 pair<framepos_t,framepos_t> extent = _playlist->get_extent();
114 AudioSource::_length = extent.second - extent.first;
116 if ((prop = node.property (X_("channel"))) == 0) {
117 throw failed_constructor ();
120 sscanf (prop->value().c_str(), "%" PRIu32, &_playlist_channel);
122 ensure_buffers_for_level (_level, _session.frame_rate());
128 AudioPlaylistSource::read_unlocked (Sample* dst, framepos_t start, framecnt_t cnt) const
130 boost::shared_array<Sample> sbuf;
131 boost::shared_array<gain_t> gbuf;
135 /* we must be careful not to read beyond the end of our "section" of
136 * the playlist, because otherwise we may read data that exists, but
137 * is not supposed be part of our data.
140 if (cnt > _playlist_length - start) {
141 to_read = _playlist_length - start;
142 to_zero = cnt - to_read;
149 /* Don't need to hold the lock for the actual read, and
150 actually, we cannot, but we do want to interlock
151 with any changes to the list of buffers caused
152 by creating new nested playlists/sources
154 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
155 sbuf = _mixdown_buffers[_level-1];
156 gbuf = _gain_buffers[_level-1];
159 boost::dynamic_pointer_cast<AudioPlaylist>(_playlist)->read (dst, sbuf.get(), gbuf.get(), start+_playlist_offset, to_read, _playlist_channel);
162 memset (dst+to_read, 0, sizeof (Sample) * to_zero);
169 AudioPlaylistSource::write_unlocked (Sample *, framecnt_t)
171 fatal << string_compose (_("programming error: %1"), "AudioPlaylistSource::write() called - should be impossible") << endmsg;
172 abort(); /*NOTREACHED*/
177 AudioPlaylistSource::empty () const
179 return !_playlist || _playlist->empty();
183 AudioPlaylistSource::n_channels () const
185 /* use just the first region to decide */
191 boost::shared_ptr<Region> r = _playlist->region_list().front ();
192 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
194 return ar->audio_source()->n_channels ();
198 AudioPlaylistSource::sample_rate () const
200 /* use just the first region to decide */
203 _session.frame_rate ();
206 boost::shared_ptr<Region> r = _playlist->region_list().front ();
207 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
209 return ar->audio_source()->sample_rate ();
213 AudioPlaylistSource::setup_peakfile ()
215 _peak_path = Glib::build_filename (_session.session_directory().peak_path(), name() + ARDOUR::peakfile_suffix);
216 return initialize_peakfile (string());
220 AudioPlaylistSource::construct_peak_filepath (const string& /*audio_path_*/, const bool /* in_session */, const bool /* old_peak_name */) const