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, sampleoffset_t begin, samplecnt_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.sample_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 ());
83 /* merge PlaylistSource state */
85 PlaylistSource::add_state (node);
87 node.set_property ("channel", _playlist_channel);
93 AudioPlaylistSource::set_state (const XMLNode& node, int version)
95 return set_state (node, version, true);
99 AudioPlaylistSource::set_state (const XMLNode& node, int version, bool with_descendants)
101 if (with_descendants) {
102 if (Source::set_state (node, version) ||
103 PlaylistSource::set_state (node, version) ||
104 AudioSource::set_state (node, version)) {
109 pair<samplepos_t,samplepos_t> extent = _playlist->get_extent();
111 AudioSource::_length = extent.second - extent.first;
113 if (!node.get_property (X_("channel"), _playlist_channel)) {
114 throw failed_constructor ();
117 ensure_buffers_for_level (_level, _session.sample_rate());
123 AudioPlaylistSource::read_unlocked (Sample* dst, samplepos_t start, samplecnt_t cnt) const
125 boost::shared_array<Sample> sbuf;
126 boost::shared_array<gain_t> gbuf;
130 /* we must be careful not to read beyond the end of our "section" of
131 * the playlist, because otherwise we may read data that exists, but
132 * is not supposed be part of our data.
135 if (cnt > _playlist_length - start) {
136 to_read = _playlist_length - start;
137 to_zero = cnt - to_read;
144 /* Don't need to hold the lock for the actual read, and
145 actually, we cannot, but we do want to interlock
146 with any changes to the list of buffers caused
147 by creating new nested playlists/sources
149 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
150 sbuf = _mixdown_buffers[_level-1];
151 gbuf = _gain_buffers[_level-1];
154 boost::dynamic_pointer_cast<AudioPlaylist>(_playlist)->read (dst, sbuf.get(), gbuf.get(), start+_playlist_offset, to_read, _playlist_channel);
157 memset (dst+to_read, 0, sizeof (Sample) * to_zero);
164 AudioPlaylistSource::write_unlocked (Sample *, samplecnt_t)
166 fatal << string_compose (_("programming error: %1"), "AudioPlaylistSource::write() called - should be impossible") << endmsg;
167 abort(); /*NOTREACHED*/
172 AudioPlaylistSource::empty () const
174 return !_playlist || _playlist->empty();
178 AudioPlaylistSource::n_channels () const
180 /* use just the first region to decide */
186 boost::shared_ptr<Region> r = _playlist->region_list_property().front ();
187 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
189 return ar->audio_source()->n_channels ();
193 AudioPlaylistSource::sample_rate () const
195 /* use just the first region to decide */
198 _session.sample_rate ();
201 boost::shared_ptr<Region> r = _playlist->region_list_property().front ();
202 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
204 return ar->audio_source()->sample_rate ();
208 AudioPlaylistSource::setup_peakfile ()
210 _peak_path = Glib::build_filename (_session.session_directory().peak_path(), name() + ARDOUR::peakfile_suffix);
211 return initialize_peakfile (string());
215 AudioPlaylistSource::construct_peak_filepath (const string& /*audio_path_*/, const bool /* in_session */, const bool /* old_peak_name */) const