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