5b81e2a161b94073fa4afc8aa7facc4a090b5656
[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         , _actual_speed (0.0)
53         , _target_speed (0.0)
54         , _buffer_reallocation_required (false)
55         , _seek_required (false)
56         , _slaved (false)
57         , loop_location (0)
58         , in_set_state (false)
59         , file_frame (0)
60         , playback_sample (0)
61         , wrap_buffer_size (0)
62         , speed_buffer_size (0)
63         , _need_butler (false)
64         , channels (new ChannelList)
65         , _midi_buf (new MidiRingBuffer<framepos_t> (s.butler()->midi_diskstream_buffer_size()))
66         , _frames_written_to_ringbuffer (0)
67         , _frames_read_from_ringbuffer (0)
68 {
69         midi_interpolation.add_channel_to (0,0);
70 }
71
72 void
73 DiskIOProcessor::init ()
74 {
75         set_block_size (_session.get_block_size());
76 }
77
78 void
79 DiskIOProcessor::set_buffering_parameters (BufferingPreset bp)
80 {
81         framecnt_t read_chunk_size;
82         framecnt_t read_buffer_size;
83         framecnt_t write_chunk_size;
84         framecnt_t write_buffer_size;
85
86         if (!get_buffering_presets (bp, read_chunk_size, read_buffer_size, write_chunk_size, write_buffer_size)) {
87                 return;
88         }
89
90         DiskReader::set_chunk_frames (read_chunk_size);
91         DiskWriter::set_chunk_frames (write_chunk_size);
92
93         Config->set_audio_capture_buffer_seconds (write_buffer_size);
94         Config->set_audio_playback_buffer_seconds (read_buffer_size);
95 }
96
97 bool
98 DiskIOProcessor::get_buffering_presets (BufferingPreset bp,
99                                         framecnt_t& read_chunk_size,
100                                         framecnt_t& read_buffer_size,
101                                         framecnt_t& write_chunk_size,
102                                         framecnt_t& write_buffer_size)
103 {
104         switch (bp) {
105         case Small:
106                 read_chunk_size = 65536;  /* samples */
107                 write_chunk_size = 65536; /* samples */
108                 read_buffer_size = 5;  /* seconds */
109                 write_buffer_size = 5; /* seconds */
110                 break;
111
112         case Medium:
113                 read_chunk_size = 262144;  /* samples */
114                 write_chunk_size = 131072; /* samples */
115                 read_buffer_size = 10;  /* seconds */
116                 write_buffer_size = 10; /* seconds */
117                 break;
118
119         case Large:
120                 read_chunk_size = 524288; /* samples */
121                 write_chunk_size = 131072; /* samples */
122                 read_buffer_size = 20; /* seconds */
123                 write_buffer_size = 20; /* seconds */
124                 break;
125
126         default:
127                 return false;
128         }
129
130         return true;
131 }
132
133 bool
134 DiskIOProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out)
135 {
136         if (in.n_midi() != 0 && in.n_midi() != 1) {
137                 /* we only support zero or 1 MIDI stream */
138                 return false;
139         }
140
141         if (in != out) {
142                 /* currently no way to deliver different channels that we receive */
143                 return false;
144         }
145
146         return true;
147 }
148
149 bool
150 DiskIOProcessor::configure_io (ChanCount in, ChanCount out)
151 {
152         DEBUG_TRACE (DEBUG::DiskIO, string_compose ("Configuring %1 for in:%2 out:%3\n", name(), in, out));
153
154         RCUWriter<ChannelList> writer (channels);
155         boost::shared_ptr<ChannelList> c = writer.get_copy();
156
157         uint32_t n_audio = in.n_audio();
158
159         if (n_audio > c->size()) {
160                 add_channel_to (c, n_audio - c->size());
161         } else if (n_audio < c->size()) {
162                 remove_channel_from (c, c->size() - n_audio);
163         }
164
165         if (in.n_midi() > 0 && !_midi_buf) {
166                 const size_t size = _session.butler()->midi_diskstream_buffer_size();
167                 _midi_buf = new MidiRingBuffer<framepos_t>(size);
168                 midi_interpolation.add_channel_to (0,0);
169         }
170
171         seek (_session.transport_frame());
172
173         return Processor::configure_io (in, out);
174 }
175
176 int
177 DiskIOProcessor::set_block_size (pframes_t nframes)
178 {
179         return 0;
180 }
181
182 int
183 DiskIOProcessor::set_loop (Location *location)
184 {
185         if (location) {
186                 if (location->start() >= location->end()) {
187                         error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
188                         return -1;
189                 }
190         }
191
192         loop_location = location;
193
194         LoopSet (location); /* EMIT SIGNAL */
195         return 0;
196 }
197
198 void
199 DiskIOProcessor::non_realtime_locate (framepos_t location)
200 {
201         /* now refill channel buffers */
202
203         seek (location, true);
204 }
205
206 void
207 DiskIOProcessor::non_realtime_set_speed ()
208 {
209         if (_buffer_reallocation_required) {
210                 _buffer_reallocation_required = false;
211         }
212
213         if (_seek_required) {
214                 seek (_session.transport_frame(), true);
215                 _seek_required = false;
216         }
217 }
218
219 bool
220 DiskIOProcessor::realtime_set_speed (double new_speed, bool global)
221 {
222         bool changed = false;
223
224         DEBUG_TRACE (DEBUG::Transport, string_compose ("%1 will run at %2\n", name(), new_speed));
225
226         if (_target_speed != new_speed) {
227                 _target_speed = new_speed;
228                 changed = true;
229
230                 framecnt_t required_wrap_size = (framecnt_t) ceil (_session.get_block_size() * fabs (new_speed)) + 2;
231
232                 if (required_wrap_size > wrap_buffer_size) {
233                         _buffer_reallocation_required = true;
234                 }
235         }
236
237         if (changed) {
238                 if (!global) {
239                         _seek_required = true;
240                 }
241                 SpeedChanged (); /* EMIT SIGNAL */
242         }
243
244         return _buffer_reallocation_required || _seek_required;
245 }
246
247 int
248 DiskIOProcessor::set_state (const XMLNode& node, int version)
249 {
250         XMLProperty const * prop;
251
252         Processor::set_state (node, version);
253
254         if ((prop = node.property ("flags")) != 0) {
255                 _flags = Flag (string_2_enum (prop->value(), _flags));
256         }
257
258         if ((prop = node.property ("speed")) != 0) {
259                 double sp = atof (prop->value().c_str());
260
261                 if (realtime_set_speed (sp, false)) {
262                         non_realtime_set_speed ();
263                 }
264         }
265         return 0;
266 }
267
268 int
269 DiskIOProcessor::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_many)
270 {
271         while (how_many--) {
272                 c->push_back (new ChannelInfo (_session.butler()->audio_diskstream_playback_buffer_size()));
273                 interpolation.add_channel_to (_session.butler()->audio_diskstream_playback_buffer_size(), speed_buffer_size);
274                 DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: new channel, write space = %2 read = %3\n",
275                                                             name(),
276                                                             c->back()->buf->write_space(),
277                                                             c->back()->buf->read_space()));
278         }
279
280         return 0;
281 }
282
283 int
284 DiskIOProcessor::add_channel (uint32_t how_many)
285 {
286         RCUWriter<ChannelList> writer (channels);
287         boost::shared_ptr<ChannelList> c = writer.get_copy();
288
289         return add_channel_to (c, how_many);
290 }
291
292 int
293 DiskIOProcessor::remove_channel_from (boost::shared_ptr<ChannelList> c, uint32_t how_many)
294 {
295         while (how_many-- && !c->empty()) {
296                 delete c->back();
297                 c->pop_back();
298                 interpolation.remove_channel_from ();
299         }
300
301         return 0;
302 }
303
304 int
305 DiskIOProcessor::remove_channel (uint32_t how_many)
306 {
307         RCUWriter<ChannelList> writer (channels);
308         boost::shared_ptr<ChannelList> c = writer.get_copy();
309
310         return remove_channel_from (c, how_many);
311 }
312
313 void
314 DiskIOProcessor::playlist_deleted (boost::weak_ptr<Playlist> wpl)
315 {
316         boost::shared_ptr<Playlist> pl (wpl.lock());
317
318         if (!pl) {
319                 return;
320         }
321
322         for (uint32_t n = 0; n < DataType::num_types; ++n) {
323                 if (pl == _playlists[n]) {
324
325                         /* this catches an ordering issue with session destruction. playlists
326                            are destroyed before disk readers. we have to invalidate any handles
327                            we have to the playlist.
328                         */
329                         _playlists[n].reset ();
330                         break;
331                 }
332         }
333 }
334
335 boost::shared_ptr<AudioPlaylist>
336 DiskIOProcessor::audio_playlist () const
337 {
338         return boost::dynamic_pointer_cast<AudioPlaylist> (_playlists[DataType::AUDIO]);
339 }
340
341 boost::shared_ptr<MidiPlaylist>
342 DiskIOProcessor::midi_playlist () const
343 {
344         return boost::dynamic_pointer_cast<MidiPlaylist> (_playlists[DataType::MIDI]);
345 }
346
347 int
348 DiskIOProcessor::use_playlist (DataType dt, boost::shared_ptr<Playlist> playlist)
349 {
350         if (!playlist) {
351                 return 0;
352         }
353
354         DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: set to use playlist %2 (%3)\n", name(), playlist->name(), dt.to_string()));
355
356         if (playlist == _playlists[dt]) {
357                 return 0;
358         }
359
360         playlist_connections.drop_connections ();
361
362         if (_playlists[dt]) {
363                 _playlists[dt]->release();
364         }
365
366         _playlists[dt] = playlist;
367         playlist->use();
368
369         playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_modified, this));
370         playlist->LayeringChanged.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_modified, this));
371         playlist->DropReferences.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_deleted, this, boost::weak_ptr<Playlist>(playlist)));
372         playlist->RangesMoved.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_ranges_moved, this, _1, _2));
373
374         DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1 now use playlist %1 (%2)\n", name(), playlist->name(), playlist->id()));
375
376         PlaylistChanged (dt); /* EMIT SIGNAL */
377         _session.set_dirty ();
378
379         return 0;
380 }
381
382 DiskIOProcessor::ChannelInfo::ChannelInfo (framecnt_t bufsize)
383 {
384         buf = new RingBufferNPT<Sample> (bufsize);
385
386         /* touch the ringbuffer buffer, which will cause
387            them to be mapped into locked physical RAM if
388            we're running with mlockall(). this doesn't do
389            much if we're not.
390         */
391
392         memset (buf->buffer(), 0, sizeof (Sample) * buf->bufsize());
393         capture_transition_buf = new RingBufferNPT<CaptureTransition> (256);
394 }
395
396 void
397 DiskIOProcessor::ChannelInfo::resize (framecnt_t bufsize)
398 {
399         delete buf;
400         buf = new RingBufferNPT<Sample> (bufsize);
401         memset (buf->buffer(), 0, sizeof (Sample) * buf->bufsize());
402 }
403
404 DiskIOProcessor::ChannelInfo::~ChannelInfo ()
405 {
406         delete buf;
407         buf = 0;
408
409         delete capture_transition_buf;
410         capture_transition_buf = 0;
411 }
412
413 void
414 DiskIOProcessor::set_route (boost::shared_ptr<Route> r)
415 {
416         _route = r;
417 }
418
419 /** Get the start, end, and length of a location "atomically".
420  *
421  * Note: Locations don't get deleted, so all we care about when I say "atomic"
422  * is that we are always pointing to the same one and using start/length values
423  * obtained just once.  Use this function to achieve this since location being
424  * a parameter achieves this.
425  */
426 void
427 DiskIOProcessor::get_location_times(const Location* location,
428                    framepos_t*     start,
429                    framepos_t*     end,
430                    framepos_t*     length)
431 {
432         if (location) {
433                 *start  = location->start();
434                 *end    = location->end();
435                 *length = *end - *start;
436         }
437 }