2 * Copyright (C) 2011-2012 David Robillard <d@drobilla.net>
3 * Copyright (C) 2011-2017 Paul Davis <paul@linuxaudiosystems.com>
4 * Copyright (C) 2012-2016 Tim Mayberry <mojofunk@gmail.com>
5 * Copyright (C) 2014-2016 Robin Gareus <robin@gareus.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "libardour-config.h"
29 #include <glibmm/fileutils.h>
30 #include <glibmm/miscutils.h>
32 #include "pbd/error.h"
34 #include "ardour/audioplaylist.h"
35 #include "ardour/audio_playlist_source.h"
36 #include "ardour/audioregion.h"
37 #include "ardour/filename_extensions.h"
38 #include "ardour/session.h"
39 #include "ardour/session_directory.h"
44 using namespace ARDOUR;
47 AudioPlaylistSource::AudioPlaylistSource (Session& s, const ID& orig, const std::string& name, boost::shared_ptr<AudioPlaylist> p,
48 uint32_t chn, sampleoffset_t begin, samplecnt_t len, Source::Flag flags)
49 : Source (s, DataType::AUDIO, name)
50 , PlaylistSource (s, orig, name, p, DataType::AUDIO, begin, len, flags)
51 , AudioSource (s, name)
52 , _playlist_channel (chn)
54 AudioSource::_length = len;
55 ensure_buffers_for_level (_level, _session.sample_rate());
58 AudioPlaylistSource::AudioPlaylistSource (Session& s, const XMLNode& node)
60 , PlaylistSource (s, node)
61 , AudioSource (s, node)
63 /* PlaylistSources are never writable, renameable, removable or destructive */
64 _flags = Flag (_flags & ~(Writable|CanRename|Removable|RemovableIfEmpty|RemoveAtDestroy|Destructive));
66 /* ancestors have already called ::set_state() in their XML-based
70 if (set_state (node, Stateful::loading_state_version, false)) {
71 throw failed_constructor ();
74 AudioSource::_length = _playlist_length;
77 AudioPlaylistSource::~AudioPlaylistSource ()
82 AudioPlaylistSource::get_state ()
84 XMLNode& node (AudioSource::get_state ());
86 /* merge PlaylistSource state */
88 PlaylistSource::add_state (node);
90 node.set_property ("channel", _playlist_channel);
96 AudioPlaylistSource::set_state (const XMLNode& node, int version)
98 return set_state (node, version, true);
102 AudioPlaylistSource::set_state (const XMLNode& node, int version, bool with_descendants)
104 if (with_descendants) {
105 if (Source::set_state (node, version) ||
106 PlaylistSource::set_state (node, version) ||
107 AudioSource::set_state (node, version)) {
112 pair<samplepos_t,samplepos_t> extent = _playlist->get_extent();
114 AudioSource::_length = extent.second - extent.first;
116 if (!node.get_property (X_("channel"), _playlist_channel)) {
117 throw failed_constructor ();
120 ensure_buffers_for_level (_level, _session.sample_rate());
126 AudioPlaylistSource::read_unlocked (Sample* dst, samplepos_t start, samplecnt_t cnt) const
128 boost::shared_array<Sample> sbuf;
129 boost::shared_array<gain_t> gbuf;
133 /* we must be careful not to read beyond the end of our "section" of
134 * the playlist, because otherwise we may read data that exists, but
135 * is not supposed be part of our data.
138 if (cnt > _playlist_length - start) {
139 to_read = _playlist_length - start;
140 to_zero = cnt - to_read;
147 /* Don't need to hold the lock for the actual read, and
148 actually, we cannot, but we do want to interlock
149 with any changes to the list of buffers caused
150 by creating new nested playlists/sources
152 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
153 sbuf = _mixdown_buffers[_level-1];
154 gbuf = _gain_buffers[_level-1];
157 boost::dynamic_pointer_cast<AudioPlaylist>(_playlist)->read (dst, sbuf.get(), gbuf.get(), start+_playlist_offset, to_read, _playlist_channel);
160 memset (dst+to_read, 0, sizeof (Sample) * to_zero);
167 AudioPlaylistSource::write_unlocked (Sample *, samplecnt_t)
169 fatal << string_compose (_("programming error: %1"), "AudioPlaylistSource::write() called - should be impossible") << endmsg;
170 abort(); /*NOTREACHED*/
175 AudioPlaylistSource::empty () const
177 return !_playlist || _playlist->empty();
181 AudioPlaylistSource::n_channels () const
183 /* use just the first region to decide */
189 boost::shared_ptr<Region> r = _playlist->region_list_property().front ();
190 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
192 return ar->audio_source()->n_channels ();
196 AudioPlaylistSource::sample_rate () const
198 /* use just the first region to decide */
201 _session.sample_rate ();
204 boost::shared_ptr<Region> r = _playlist->region_list_property().front ();
205 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
207 return ar->audio_source()->sample_rate ();
211 AudioPlaylistSource::setup_peakfile ()
213 _peak_path = Glib::build_filename (_session.session_directory().peak_path(), name() + ARDOUR::peakfile_suffix);
214 return initialize_peakfile (string());
218 AudioPlaylistSource::construct_peak_filepath (const string& /*audio_path_*/, const bool /* in_session */, const bool /* old_peak_name */) const