move _file_frame from DiskIOProcessor into DiskReader (only place where it is needed...
[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         RCUWriter<ChannelList> writer (channels);
151         boost::shared_ptr<ChannelList> c = writer.get_copy();
152
153         uint32_t n_audio = in.n_audio();
154         bool changed = false;
155
156         if (n_audio > c->size()) {
157                 add_channel_to (c, n_audio - c->size());
158                 changed = true;
159         } else if (n_audio < c->size()) {
160                 remove_channel_from (c, c->size() - n_audio);
161                 changed = true;
162         }
163
164         if (in.n_midi() > 0 && !_midi_buf) {
165                 const size_t size = _session.butler()->midi_diskstream_buffer_size();
166                 _midi_buf = new MidiRingBuffer<framepos_t>(size);
167                 midi_interpolation.add_channel_to (0,0);
168                 changed = true;
169         }
170
171         if (changed) {
172                 seek (_session.transport_frame());
173         }
174
175         return Processor::configure_io (in, out);
176 }
177
178 int
179 DiskIOProcessor::set_block_size (pframes_t nframes)
180 {
181         return 0;
182 }
183
184 int
185 DiskIOProcessor::set_loop (Location *location)
186 {
187         if (location) {
188                 if (location->start() >= location->end()) {
189                         error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
190                         return -1;
191                 }
192         }
193
194         loop_location = location;
195
196         LoopSet (location); /* EMIT SIGNAL */
197         return 0;
198 }
199
200 void
201 DiskIOProcessor::non_realtime_locate (framepos_t location)
202 {
203         /* now refill channel buffers */
204
205         seek (location, true);
206 }
207
208 void
209 DiskIOProcessor::non_realtime_speed_change ()
210 {
211         if (_buffer_reallocation_required) {
212                 _buffer_reallocation_required = false;
213         }
214
215         if (_seek_required) {
216                 seek (_session.transport_frame(), true);
217                 _seek_required = false;
218         }
219 }
220
221 bool
222 DiskIOProcessor::realtime_speed_change ()
223 {
224         const framecnt_t required_wrap_size = (framecnt_t) ceil (_session.get_block_size() * fabs (_session.transport_speed())) + 2;
225         bool _buffer_reallocation_required;
226
227         if (required_wrap_size > wrap_buffer_size) {
228                 _buffer_reallocation_required = true;
229         } else {
230                 _buffer_reallocation_required = false;
231         }
232
233         return _buffer_reallocation_required;
234 }
235
236 int
237 DiskIOProcessor::set_state (const XMLNode& node, int version)
238 {
239         XMLProperty const * prop;
240
241         Processor::set_state (node, version);
242
243         if ((prop = node.property ("flags")) != 0) {
244                 _flags = Flag (string_2_enum (prop->value(), _flags));
245         }
246
247         return 0;
248 }
249
250 int
251 DiskIOProcessor::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_many)
252 {
253         while (how_many--) {
254                 c->push_back (new ChannelInfo (_session.butler()->audio_diskstream_playback_buffer_size()));
255                 interpolation.add_channel_to (_session.butler()->audio_diskstream_playback_buffer_size(), speed_buffer_size);
256                 DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: new channel, write space = %2 read = %3\n",
257                                                             name(),
258                                                             c->back()->buf->write_space(),
259                                                             c->back()->buf->read_space()));
260         }
261
262         return 0;
263 }
264
265 int
266 DiskIOProcessor::add_channel (uint32_t how_many)
267 {
268         RCUWriter<ChannelList> writer (channels);
269         boost::shared_ptr<ChannelList> c = writer.get_copy();
270
271         return add_channel_to (c, how_many);
272 }
273
274 int
275 DiskIOProcessor::remove_channel_from (boost::shared_ptr<ChannelList> c, uint32_t how_many)
276 {
277         while (how_many-- && !c->empty()) {
278                 delete c->back();
279                 c->pop_back();
280                 interpolation.remove_channel_from ();
281         }
282
283         return 0;
284 }
285
286 int
287 DiskIOProcessor::remove_channel (uint32_t how_many)
288 {
289         RCUWriter<ChannelList> writer (channels);
290         boost::shared_ptr<ChannelList> c = writer.get_copy();
291
292         return remove_channel_from (c, how_many);
293 }
294
295 void
296 DiskIOProcessor::playlist_deleted (boost::weak_ptr<Playlist> wpl)
297 {
298         boost::shared_ptr<Playlist> pl (wpl.lock());
299
300         if (!pl) {
301                 return;
302         }
303
304         for (uint32_t n = 0; n < DataType::num_types; ++n) {
305                 if (pl == _playlists[n]) {
306
307                         /* this catches an ordering issue with session destruction. playlists
308                            are destroyed before disk readers. we have to invalidate any handles
309                            we have to the playlist.
310                         */
311                         _playlists[n].reset ();
312                         break;
313                 }
314         }
315 }
316
317 boost::shared_ptr<AudioPlaylist>
318 DiskIOProcessor::audio_playlist () const
319 {
320         return boost::dynamic_pointer_cast<AudioPlaylist> (_playlists[DataType::AUDIO]);
321 }
322
323 boost::shared_ptr<MidiPlaylist>
324 DiskIOProcessor::midi_playlist () const
325 {
326         return boost::dynamic_pointer_cast<MidiPlaylist> (_playlists[DataType::MIDI]);
327 }
328
329 int
330 DiskIOProcessor::use_playlist (DataType dt, boost::shared_ptr<Playlist> playlist)
331 {
332         if (!playlist) {
333                 return 0;
334         }
335
336         DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: set to use playlist %2 (%3)\n", name(), playlist->name(), dt.to_string()));
337
338         if (playlist == _playlists[dt]) {
339                 DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: already using that playlist\n", name()));
340                 return 0;
341         }
342
343         playlist_connections.drop_connections ();
344
345         if (_playlists[dt]) {
346                 _playlists[dt]->release();
347         }
348
349         _playlists[dt] = playlist;
350         playlist->use();
351
352         playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_modified, this));
353         playlist->LayeringChanged.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_modified, this));
354         playlist->DropReferences.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_deleted, this, boost::weak_ptr<Playlist>(playlist)));
355         playlist->RangesMoved.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_ranges_moved, this, _1, _2));
356
357         DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1 now using playlist %1 (%2)\n", name(), playlist->name(), playlist->id()));
358
359         PlaylistChanged (dt); /* EMIT SIGNAL */
360         _session.set_dirty ();
361
362         return 0;
363 }
364
365 DiskIOProcessor::ChannelInfo::ChannelInfo (framecnt_t bufsize)
366 {
367         buf = new RingBufferNPT<Sample> (bufsize);
368
369         /* touch the ringbuffer buffer, which will cause
370            them to be mapped into locked physical RAM if
371            we're running with mlockall(). this doesn't do
372            much if we're not.
373         */
374
375         memset (buf->buffer(), 0, sizeof (Sample) * buf->bufsize());
376         capture_transition_buf = new RingBufferNPT<CaptureTransition> (256);
377 }
378
379 void
380 DiskIOProcessor::ChannelInfo::resize (framecnt_t bufsize)
381 {
382         delete buf;
383         buf = new RingBufferNPT<Sample> (bufsize);
384         memset (buf->buffer(), 0, sizeof (Sample) * buf->bufsize());
385 }
386
387 DiskIOProcessor::ChannelInfo::~ChannelInfo ()
388 {
389         delete buf;
390         buf = 0;
391
392         delete capture_transition_buf;
393         capture_transition_buf = 0;
394 }
395
396 void
397 DiskIOProcessor::drop_route ()
398 {
399         _route.reset ();
400 }
401
402 void
403 DiskIOProcessor::set_route (boost::shared_ptr<Route> r)
404 {
405         _route = r;
406
407         if (_route) {
408                 _route->DropReferences.connect_same_thread (*this, boost::bind (&DiskIOProcessor::drop_route, this));
409         }
410 }
411
412 /** Get the start, end, and length of a location "atomically".
413  *
414  * Note: Locations don't get deleted, so all we care about when I say "atomic"
415  * is that we are always pointing to the same one and using start/length values
416  * obtained just once.  Use this function to achieve this since location being
417  * a parameter achieves this.
418  */
419 void
420 DiskIOProcessor::get_location_times(const Location* location,
421                    framepos_t*     start,
422                    framepos_t*     end,
423                    framepos_t*     length)
424 {
425         if (location) {
426                 *start  = location->start();
427                 *end    = location->end();
428                 *length = *end - *start;
429         }
430 }
431