e15620b1d26e6b5bb72ae8d991bee966c3430533
[ardour.git] / libs / ardour / disk_io.cc
1 /*
2     Copyright (C) 2009-2016 Paul Davis
3
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.
8
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.
13
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.
17
18 */
19
20 #include "pbd/debug.h"
21 #include "pbd/error.h"
22 #include "pbd/i18n.h"
23
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"
38
39 using namespace ARDOUR;
40 using namespace PBD;
41 using namespace std;
42
43 const string DiskIOProcessor::state_node_name = X_("DiskIOProcessor");
44
45 // PBD::Signal0<void> DiskIOProcessor::DiskOverrun;
46 // PBD::Signal0<void>  DiskIOProcessor::DiskUnderrun;
47
48 DiskIOProcessor::DiskIOProcessor (Session& s, string const & str, Flag f)
49         : Processor (s, str)
50         , _flags (f)
51         , i_am_the_modifier (false)
52         , _visible_speed (0.0)
53         , _actual_speed (0.0)
54         , _speed (0.0)
55         , _target_speed (0.0)
56         , _buffer_reallocation_required (false)
57         , _seek_required (false)
58         , _slaved (false)
59         , loop_location (0)
60         , in_set_state (false)
61         , file_frame (0)
62         , playback_sample (0)
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)
70 {
71         midi_interpolation.add_channel_to (0,0);
72 }
73
74 void
75 DiskIOProcessor::init ()
76 {
77         set_block_size (_session.get_block_size());
78 }
79
80 void
81 DiskIOProcessor::set_buffering_parameters (BufferingPreset bp)
82 {
83         framecnt_t read_chunk_size;
84         framecnt_t read_buffer_size;
85         framecnt_t write_chunk_size;
86         framecnt_t write_buffer_size;
87
88         if (!get_buffering_presets (bp, read_chunk_size, read_buffer_size, write_chunk_size, write_buffer_size)) {
89                 return;
90         }
91
92         DiskReader::set_chunk_frames (read_chunk_size);
93         DiskWriter::set_chunk_frames (write_chunk_size);
94
95         Config->set_audio_capture_buffer_seconds (write_buffer_size);
96         Config->set_audio_playback_buffer_seconds (read_buffer_size);
97 }
98
99 bool
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)
105 {
106         switch (bp) {
107         case Small:
108                 read_chunk_size = 65536;  /* samples */
109                 write_chunk_size = 65536; /* samples */
110                 read_buffer_size = 5;  /* seconds */
111                 write_buffer_size = 5; /* seconds */
112                 break;
113
114         case Medium:
115                 read_chunk_size = 262144;  /* samples */
116                 write_chunk_size = 131072; /* samples */
117                 read_buffer_size = 10;  /* seconds */
118                 write_buffer_size = 10; /* seconds */
119                 break;
120
121         case Large:
122                 read_chunk_size = 524288; /* samples */
123                 write_chunk_size = 131072; /* samples */
124                 read_buffer_size = 20; /* seconds */
125                 write_buffer_size = 20; /* seconds */
126                 break;
127
128         default:
129                 return false;
130         }
131
132         return true;
133 }
134
135 bool
136 DiskIOProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out)
137 {
138         if (in.n_midi() != 0 && in.n_midi() != 1) {
139                 /* we only support zero or 1 MIDI stream */
140                 return false;
141         }
142
143         if (in != out) {
144                 /* currently no way to deliver different channels that we receive */
145                 return false;
146         }
147
148         return true;
149 }
150
151 bool
152 DiskIOProcessor::configure_io (ChanCount in, ChanCount out)
153 {
154         DEBUG_TRACE (DEBUG::DiskIO, string_compose ("Configuring %1 for in:%2 out:%3\n", name(), in, out));
155
156         RCUWriter<ChannelList> writer (channels);
157         boost::shared_ptr<ChannelList> c = writer.get_copy();
158
159         uint32_t n_audio = in.n_audio();
160
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);
165         }
166
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);
171         }
172
173         if (speed() != 1.0f || speed() != -1.0f) {
174                 seek ((framepos_t) (_session.transport_frame() * (double) speed()));
175         } else {
176                 seek (_session.transport_frame());
177         }
178
179         return Processor::configure_io (in, out);
180 }
181
182 int
183 DiskIOProcessor::set_block_size (pframes_t nframes)
184 {
185         return 0;
186 }
187
188 int
189 DiskIOProcessor::set_loop (Location *location)
190 {
191         if (location) {
192                 if (location->start() >= location->end()) {
193                         error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
194                         return -1;
195                 }
196         }
197
198         loop_location = location;
199
200         LoopSet (location); /* EMIT SIGNAL */
201         return 0;
202 }
203
204 void
205 DiskIOProcessor::non_realtime_locate (framepos_t location)
206 {
207         /* now refill channel buffers */
208
209         if (speed() != 1.0f || speed() != -1.0f) {
210                 seek ((framepos_t) (location * (double) speed()), true);
211         } else {
212                 seek (location, true);
213         }
214 }
215
216 void
217 DiskIOProcessor::non_realtime_set_speed ()
218 {
219         if (_buffer_reallocation_required) {
220                 _buffer_reallocation_required = false;
221         }
222
223         if (_seek_required) {
224                 if (speed() != 1.0f || speed() != -1.0f) {
225                         seek ((framepos_t) (_session.transport_frame() * (double) speed()), true);
226                 }
227                 else {
228                         seek (_session.transport_frame(), true);
229                 }
230
231                 _seek_required = false;
232         }
233 }
234
235 bool
236 DiskIOProcessor::realtime_set_speed (double sp, bool global)
237 {
238         bool changed = false;
239         double new_speed = sp * _session.transport_speed();
240
241         if (_visible_speed != sp) {
242                 _visible_speed = sp;
243                 changed = true;
244         }
245
246         if (new_speed != _actual_speed) {
247
248                 framecnt_t required_wrap_size = (framecnt_t) ceil (_session.get_block_size() *
249                                                                   fabs (new_speed)) + 2;
250
251                 if (required_wrap_size > wrap_buffer_size) {
252                         _buffer_reallocation_required = true;
253                 }
254
255                 _actual_speed = new_speed;
256                 _target_speed = fabs(_actual_speed);
257         }
258
259         if (changed) {
260                 if (!global) {
261                         _seek_required = true;
262                 }
263                 SpeedChanged (); /* EMIT SIGNAL */
264         }
265
266         return _buffer_reallocation_required || _seek_required;
267 }
268
269 int
270 DiskIOProcessor::set_state (const XMLNode& node, int version)
271 {
272         XMLProperty const * prop;
273
274         Processor::set_state (node, version);
275
276         if ((prop = node.property ("flags")) != 0) {
277                 _flags = Flag (string_2_enum (prop->value(), _flags));
278         }
279
280         if ((prop = node.property ("speed")) != 0) {
281                 double sp = atof (prop->value().c_str());
282
283                 if (realtime_set_speed (sp, false)) {
284                         non_realtime_set_speed ();
285                 }
286         }
287         return 0;
288 }
289
290 int
291 DiskIOProcessor::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_many)
292 {
293         while (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);
296         }
297
298         return 0;
299 }
300
301 int
302 DiskIOProcessor::add_channel (uint32_t how_many)
303 {
304         RCUWriter<ChannelList> writer (channels);
305         boost::shared_ptr<ChannelList> c = writer.get_copy();
306
307         return add_channel_to (c, how_many);
308 }
309
310 int
311 DiskIOProcessor::remove_channel_from (boost::shared_ptr<ChannelList> c, uint32_t how_many)
312 {
313         while (how_many-- && !c->empty()) {
314                 delete c->back();
315                 c->pop_back();
316                 interpolation.remove_channel_from ();
317         }
318
319         return 0;
320 }
321
322 int
323 DiskIOProcessor::remove_channel (uint32_t how_many)
324 {
325         RCUWriter<ChannelList> writer (channels);
326         boost::shared_ptr<ChannelList> c = writer.get_copy();
327
328         return remove_channel_from (c, how_many);
329 }
330
331 void
332 DiskIOProcessor::playlist_deleted (boost::weak_ptr<Playlist> wpl)
333 {
334         boost::shared_ptr<Playlist> pl (wpl.lock());
335
336         if (!pl) {
337                 return;
338         }
339
340         for (uint32_t n = 0; n < DataType::num_types; ++n) {
341                 if (pl == _playlists[n]) {
342
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.
346                         */
347                         _playlists[n].reset ();
348                         break;
349                 }
350         }
351 }
352
353 boost::shared_ptr<AudioPlaylist>
354 DiskIOProcessor::audio_playlist () const
355 {
356         return boost::dynamic_pointer_cast<AudioPlaylist> (_playlists[DataType::AUDIO]);
357 }
358
359 boost::shared_ptr<MidiPlaylist>
360 DiskIOProcessor::midi_playlist () const
361 {
362         return boost::dynamic_pointer_cast<MidiPlaylist> (_playlists[DataType::MIDI]);
363 }
364
365 int
366 DiskIOProcessor::use_playlist (DataType dt, boost::shared_ptr<Playlist> playlist)
367 {
368         if (!playlist) {
369                 return 0;
370         }
371
372         DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: set to use playlist %2 (%3)\n", name(), playlist->name(), dt.to_string()));
373
374         if (playlist == _playlists[dt]) {
375                 return 0;
376         }
377
378         playlist_connections.drop_connections ();
379
380         if (_playlists[dt]) {
381                 _playlists[dt]->release();
382         }
383
384         _playlists[dt] = playlist;
385         playlist->use();
386
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));
391
392         DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1 now use playlist %1 (%2)\n", name(), playlist->name(), playlist->id()));
393
394         PlaylistChanged (dt); /* EMIT SIGNAL */
395         _session.set_dirty ();
396
397         return 0;
398 }
399
400 DiskIOProcessor::ChannelInfo::ChannelInfo (framecnt_t bufsize)
401 {
402         buf = new RingBufferNPT<Sample> (bufsize);
403
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
407            much if we're not.
408         */
409
410         memset (buf->buffer(), 0, sizeof (Sample) * buf->bufsize());
411         capture_transition_buf = new RingBufferNPT<CaptureTransition> (256);
412 }
413
414 void
415 DiskIOProcessor::ChannelInfo::resize (framecnt_t bufsize)
416 {
417         delete buf;
418         buf = new RingBufferNPT<Sample> (bufsize);
419         memset (buf->buffer(), 0, sizeof (Sample) * buf->bufsize());
420 }
421
422 DiskIOProcessor::ChannelInfo::~ChannelInfo ()
423 {
424         delete buf;
425         buf = 0;
426
427         delete capture_transition_buf;
428         capture_transition_buf = 0;
429 }
430
431 void
432 DiskIOProcessor::set_route (boost::shared_ptr<Route> r)
433 {
434         _route = r;
435 }
436
437 /** Get the start, end, and length of a location "atomically".
438  *
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.
443  */
444 void
445 DiskIOProcessor::get_location_times(const Location* location,
446                    framepos_t*     start,
447                    framepos_t*     end,
448                    framepos_t*     length)
449 {
450         if (location) {
451                 *start  = location->start();
452                 *end    = location->end();
453                 *length = *end - *start;
454         }
455 }