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