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