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