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