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