2 Copyright (C) 2009-2016 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 "pbd/debug.h"
21 #include "pbd/error.h"
24 #include "ardour/audioplaylist.h"
25 #include "ardour/butler.h"
26 #include "ardour/debug.h"
27 #include "ardour/disk_io.h"
28 #include "ardour/disk_reader.h"
29 #include "ardour/disk_writer.h"
30 #include "ardour/location.h"
31 #include "ardour/midi_ring_buffer.h"
32 #include "ardour/midi_playlist.h"
33 #include "ardour/playlist.h"
34 #include "ardour/playlist_factory.h"
35 #include "ardour/rc_configuration.h"
36 #include "ardour/session.h"
37 #include "ardour/session_playlists.h"
39 using namespace ARDOUR;
43 const string DiskIOProcessor::state_node_name = X_("DiskIOProcessor");
45 // PBD::Signal0<void> DiskIOProcessor::DiskOverrun;
46 // PBD::Signal0<void> DiskIOProcessor::DiskUnderrun;
48 DiskIOProcessor::DiskIOProcessor (Session& s, string const & str, Flag f)
51 , i_am_the_modifier (false)
52 , _visible_speed (0.0)
56 , _buffer_reallocation_required (false)
57 , _seek_required (false)
60 , in_set_state (false)
63 , wrap_buffer_size (0)
64 , speed_buffer_size (0)
65 , _need_butler (false)
66 , channels (new ChannelList)
67 , _midi_buf (new MidiRingBuffer<framepos_t> (s.butler()->midi_diskstream_buffer_size()))
68 , _frames_written_to_ringbuffer (0)
69 , _frames_read_from_ringbuffer (0)
71 midi_interpolation.add_channel_to (0,0);
75 DiskIOProcessor::init ()
77 set_block_size (_session.get_block_size());
81 DiskIOProcessor::set_buffering_parameters (BufferingPreset bp)
83 framecnt_t read_chunk_size;
84 framecnt_t read_buffer_size;
85 framecnt_t write_chunk_size;
86 framecnt_t write_buffer_size;
88 if (!get_buffering_presets (bp, read_chunk_size, read_buffer_size, write_chunk_size, write_buffer_size)) {
92 DiskReader::set_chunk_frames (read_chunk_size);
93 DiskWriter::set_chunk_frames (write_chunk_size);
95 Config->set_audio_capture_buffer_seconds (write_buffer_size);
96 Config->set_audio_playback_buffer_seconds (read_buffer_size);
100 DiskIOProcessor::get_buffering_presets (BufferingPreset bp,
101 framecnt_t& read_chunk_size,
102 framecnt_t& read_buffer_size,
103 framecnt_t& write_chunk_size,
104 framecnt_t& write_buffer_size)
108 read_chunk_size = 65536; /* samples */
109 write_chunk_size = 65536; /* samples */
110 read_buffer_size = 5; /* seconds */
111 write_buffer_size = 5; /* seconds */
115 read_chunk_size = 262144; /* samples */
116 write_chunk_size = 131072; /* samples */
117 read_buffer_size = 10; /* seconds */
118 write_buffer_size = 10; /* seconds */
122 read_chunk_size = 524288; /* samples */
123 write_chunk_size = 131072; /* samples */
124 read_buffer_size = 20; /* seconds */
125 write_buffer_size = 20; /* seconds */
136 DiskIOProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out)
138 if (in.n_midi() != 0 && in.n_midi() != 1) {
139 /* we only support zero or 1 MIDI stream */
144 /* currently no way to deliver different channels that we receive */
152 DiskIOProcessor::configure_io (ChanCount in, ChanCount out)
154 DEBUG_TRACE (DEBUG::DiskIO, string_compose ("Configuring %1 for in:%2 out:%3\n", name(), in, out));
156 RCUWriter<ChannelList> writer (channels);
157 boost::shared_ptr<ChannelList> c = writer.get_copy();
159 uint32_t n_audio = in.n_audio();
161 if (n_audio > c->size()) {
162 add_channel_to (c, n_audio - c->size());
163 } else if (n_audio < c->size()) {
164 remove_channel_from (c, c->size() - n_audio);
167 if (in.n_midi() > 0 && !_midi_buf) {
168 const size_t size = _session.butler()->midi_diskstream_buffer_size();
169 _midi_buf = new MidiRingBuffer<framepos_t>(size);
170 midi_interpolation.add_channel_to (0,0);
173 if (speed() != 1.0f || speed() != -1.0f) {
174 seek ((framepos_t) (_session.transport_frame() * (double) speed()));
176 seek (_session.transport_frame());
179 return Processor::configure_io (in, out);
183 DiskIOProcessor::set_block_size (pframes_t nframes)
189 DiskIOProcessor::set_loop (Location *location)
192 if (location->start() >= location->end()) {
193 error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
198 loop_location = location;
200 LoopSet (location); /* EMIT SIGNAL */
205 DiskIOProcessor::non_realtime_locate (framepos_t location)
207 /* now refill channel buffers */
209 if (speed() != 1.0f || speed() != -1.0f) {
210 seek ((framepos_t) (location * (double) speed()), true);
212 seek (location, true);
217 DiskIOProcessor::non_realtime_set_speed ()
219 if (_buffer_reallocation_required) {
220 _buffer_reallocation_required = false;
223 if (_seek_required) {
224 if (speed() != 1.0f || speed() != -1.0f) {
225 seek ((framepos_t) (_session.transport_frame() * (double) speed()), true);
228 seek (_session.transport_frame(), true);
231 _seek_required = false;
236 DiskIOProcessor::realtime_set_speed (double sp, bool global)
238 bool changed = false;
239 double new_speed = sp * _session.transport_speed();
241 if (_visible_speed != sp) {
246 if (new_speed != _actual_speed) {
248 framecnt_t required_wrap_size = (framecnt_t) ceil (_session.get_block_size() *
249 fabs (new_speed)) + 2;
251 if (required_wrap_size > wrap_buffer_size) {
252 _buffer_reallocation_required = true;
255 _actual_speed = new_speed;
256 _target_speed = fabs(_actual_speed);
261 _seek_required = true;
263 SpeedChanged (); /* EMIT SIGNAL */
266 return _buffer_reallocation_required || _seek_required;
270 DiskIOProcessor::set_state (const XMLNode& node, int version)
272 XMLProperty const * prop;
274 Processor::set_state (node, version);
276 if ((prop = node.property ("flags")) != 0) {
277 _flags = Flag (string_2_enum (prop->value(), _flags));
280 if ((prop = node.property ("speed")) != 0) {
281 double sp = atof (prop->value().c_str());
283 if (realtime_set_speed (sp, false)) {
284 non_realtime_set_speed ();
291 DiskIOProcessor::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_many)
294 c->push_back (new ChannelInfo (_session.butler()->audio_diskstream_playback_buffer_size()));
295 interpolation.add_channel_to (_session.butler()->audio_diskstream_playback_buffer_size(), speed_buffer_size);
302 DiskIOProcessor::add_channel (uint32_t how_many)
304 RCUWriter<ChannelList> writer (channels);
305 boost::shared_ptr<ChannelList> c = writer.get_copy();
307 return add_channel_to (c, how_many);
311 DiskIOProcessor::remove_channel_from (boost::shared_ptr<ChannelList> c, uint32_t how_many)
313 while (how_many-- && !c->empty()) {
316 interpolation.remove_channel_from ();
323 DiskIOProcessor::remove_channel (uint32_t how_many)
325 RCUWriter<ChannelList> writer (channels);
326 boost::shared_ptr<ChannelList> c = writer.get_copy();
328 return remove_channel_from (c, how_many);
332 DiskIOProcessor::playlist_deleted (boost::weak_ptr<Playlist> wpl)
334 boost::shared_ptr<Playlist> pl (wpl.lock());
340 for (uint32_t n = 0; n < DataType::num_types; ++n) {
341 if (pl == _playlists[n]) {
343 /* this catches an ordering issue with session destruction. playlists
344 are destroyed before disk readers. we have to invalidate any handles
345 we have to the playlist.
347 _playlists[n].reset ();
353 boost::shared_ptr<AudioPlaylist>
354 DiskIOProcessor::audio_playlist () const
356 return boost::dynamic_pointer_cast<AudioPlaylist> (_playlists[DataType::AUDIO]);
359 boost::shared_ptr<MidiPlaylist>
360 DiskIOProcessor::midi_playlist () const
362 return boost::dynamic_pointer_cast<MidiPlaylist> (_playlists[DataType::MIDI]);
366 DiskIOProcessor::use_playlist (DataType dt, boost::shared_ptr<Playlist> playlist)
372 DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: set to use playlist %2 (%3)\n", name(), playlist->name(), dt.to_string()));
374 if (playlist == _playlists[dt]) {
378 playlist_connections.drop_connections ();
380 if (_playlists[dt]) {
381 _playlists[dt]->release();
384 _playlists[dt] = playlist;
387 playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_modified, this));
388 playlist->LayeringChanged.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_modified, this));
389 playlist->DropReferences.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_deleted, this, boost::weak_ptr<Playlist>(playlist)));
390 playlist->RangesMoved.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_ranges_moved, this, _1, _2));
392 DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1 now use playlist %1 (%2)\n", name(), playlist->name(), playlist->id()));
394 PlaylistChanged (dt); /* EMIT SIGNAL */
395 _session.set_dirty ();
400 DiskIOProcessor::ChannelInfo::ChannelInfo (framecnt_t bufsize)
402 buf = new RingBufferNPT<Sample> (bufsize);
404 /* touch the ringbuffer buffer, which will cause
405 them to be mapped into locked physical RAM if
406 we're running with mlockall(). this doesn't do
410 memset (buf->buffer(), 0, sizeof (Sample) * buf->bufsize());
411 capture_transition_buf = new RingBufferNPT<CaptureTransition> (256);
415 DiskIOProcessor::ChannelInfo::resize (framecnt_t bufsize)
418 buf = new RingBufferNPT<Sample> (bufsize);
419 memset (buf->buffer(), 0, sizeof (Sample) * buf->bufsize());
422 DiskIOProcessor::ChannelInfo::~ChannelInfo ()
427 delete capture_transition_buf;
428 capture_transition_buf = 0;
432 DiskIOProcessor::set_route (boost::shared_ptr<Route> r)
437 /** Get the start, end, and length of a location "atomically".
439 * Note: Locations don't get deleted, so all we care about when I say "atomic"
440 * is that we are always pointing to the same one and using start/length values
441 * obtained just once. Use this function to achieve this since location being
442 * a parameter achieves this.
445 DiskIOProcessor::get_location_times(const Location* location,
451 *start = location->start();
452 *end = location->end();
453 *length = *end - *start;