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