d0e6b9dc351c8ca3ead297b87dd9736365c6fd06
[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/error.h"
21 #include "pbd/i18n.h"
22
23 #include "ardour/butler.h"
24 #include "ardour/disk_io.h"
25 #include "ardour/disk_reader.h"
26 #include "ardour/disk_writer.h"
27 #include "ardour/location.h"
28 #include "ardour/rc_configuration.h"
29 #include "ardour/session.h"
30
31 using namespace ARDOUR;
32 using namespace PBD;
33 using namespace std;
34
35 const string DiskIOProcessor::state_node_name = X_("DiskIOProcessor");
36
37 // PBD::Signal0<void> DiskIOProcessor::DiskOverrun;
38 // PBD::Signal0<void>  DiskIOProcessor::DiskUnderrun;
39
40 DiskIOProcessor::DiskIOProcessor (Session& s, string const & str, Flag f)
41         : Processor (s, str)
42         , _flags (f)
43         , i_am_the_modifier (false)
44         , _visible_speed (0.0)
45         , _actual_speed (0.0)
46         , _speed (0.0)
47         , _target_speed (0.0)
48         , _buffer_reallocation_required (false)
49         , _seek_required (false)
50         , _slaved (false)
51         , loop_location (0)
52         , in_set_state (false)
53         , wrap_buffer_size (0)
54         , speed_buffer_size (0)
55         , channels (new ChannelList)
56 {
57 }
58
59 void
60 DiskIOProcessor::set_buffering_parameters (BufferingPreset bp)
61 {
62         framecnt_t read_chunk_size;
63         framecnt_t read_buffer_size;
64         framecnt_t write_chunk_size;
65         framecnt_t write_buffer_size;
66
67         if (!get_buffering_presets (bp, read_chunk_size, read_buffer_size, write_chunk_size, write_buffer_size)) {
68                 return;
69         }
70
71         DiskReader::set_chunk_frames (read_chunk_size);
72         DiskWriter::set_chunk_frames (write_chunk_size);
73
74         Config->set_audio_capture_buffer_seconds (write_buffer_size);
75         Config->set_audio_playback_buffer_seconds (read_buffer_size);
76 }
77
78 bool
79 DiskIOProcessor::get_buffering_presets (BufferingPreset bp,
80                                         framecnt_t& read_chunk_size,
81                                         framecnt_t& read_buffer_size,
82                                         framecnt_t& write_chunk_size,
83                                         framecnt_t& write_buffer_size)
84 {
85         switch (bp) {
86         case Small:
87                 read_chunk_size = 65536;  /* samples */
88                 write_chunk_size = 65536; /* samples */
89                 read_buffer_size = 5;  /* seconds */
90                 write_buffer_size = 5; /* seconds */
91                 break;
92
93         case Medium:
94                 read_chunk_size = 262144;  /* samples */
95                 write_chunk_size = 131072; /* samples */
96                 read_buffer_size = 10;  /* seconds */
97                 write_buffer_size = 10; /* seconds */
98                 break;
99
100         case Large:
101                 read_chunk_size = 524288; /* samples */
102                 write_chunk_size = 131072; /* samples */
103                 read_buffer_size = 20; /* seconds */
104                 write_buffer_size = 20; /* seconds */
105                 break;
106
107         default:
108                 return false;
109         }
110
111         return true;
112 }
113
114
115 int
116 DiskIOProcessor::set_loop (Location *location)
117 {
118         if (location) {
119                 if (location->start() >= location->end()) {
120                         error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
121                         return -1;
122                 }
123         }
124
125         loop_location = location;
126
127         LoopSet (location); /* EMIT SIGNAL */
128         return 0;
129 }
130
131 void
132 DiskIOProcessor::non_realtime_set_speed ()
133 {
134         if (_buffer_reallocation_required)
135         {
136                 Glib::Threads::Mutex::Lock lm (state_lock);
137                 allocate_temporary_buffers ();
138
139                 _buffer_reallocation_required = false;
140         }
141
142         if (_seek_required) {
143                 if (speed() != 1.0f || speed() != -1.0f) {
144                         seek ((framepos_t) (_session.transport_frame() * (double) speed()), true);
145                 }
146                 else {
147                         seek (_session.transport_frame(), true);
148                 }
149
150                 _seek_required = false;
151         }
152 }
153
154 bool
155 DiskIOProcessor::realtime_set_speed (double sp, bool global)
156 {
157         bool changed = false;
158         double new_speed = sp * _session.transport_speed();
159
160         if (_visible_speed != sp) {
161                 _visible_speed = sp;
162                 changed = true;
163         }
164
165         if (new_speed != _actual_speed) {
166
167                 framecnt_t required_wrap_size = (framecnt_t) ceil (_session.get_block_size() *
168                                                                   fabs (new_speed)) + 2;
169
170                 if (required_wrap_size > wrap_buffer_size) {
171                         _buffer_reallocation_required = true;
172                 }
173
174                 _actual_speed = new_speed;
175                 _target_speed = fabs(_actual_speed);
176         }
177
178         if (changed) {
179                 if (!global) {
180                         _seek_required = true;
181                 }
182                 SpeedChanged (); /* EMIT SIGNAL */
183         }
184
185         return _buffer_reallocation_required || _seek_required;
186 }
187
188 int
189 DiskIOProcessor::set_state (const XMLNode& node, int version)
190 {
191         XMLProperty const * prop;
192
193         Processor::set_state (node, version);
194
195         if ((prop = node.property ("flags")) != 0) {
196                 _flags = Flag (string_2_enum (prop->value(), _flags));
197         }
198
199         if ((prop = node.property ("speed")) != 0) {
200                 double sp = atof (prop->value().c_str());
201
202                 if (realtime_set_speed (sp, false)) {
203                         non_realtime_set_speed ();
204                 }
205         }
206         return 0;
207 }
208
209 int
210 DiskIOProcessor::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_many)
211 {
212         while (how_many--) {
213                 c->push_back (new ChannelInfo(
214                                       _session.butler()->audio_diskstream_playback_buffer_size(),
215                                       speed_buffer_size, wrap_buffer_size));
216                 interpolation.add_channel_to (
217                         _session.butler()->audio_diskstream_playback_buffer_size(),
218                         speed_buffer_size);
219         }
220
221         _n_channels.set (DataType::AUDIO, c->size());
222
223         return 0;
224 }
225
226 int
227 DiskIOProcessor::add_channel (uint32_t how_many)
228 {
229         RCUWriter<ChannelList> writer (channels);
230         boost::shared_ptr<ChannelList> c = writer.get_copy();
231
232         return add_channel_to (c, how_many);
233 }
234
235 int
236 DiskIOProcessor::remove_channel_from (boost::shared_ptr<ChannelList> c, uint32_t how_many)
237 {
238         while (how_many-- && !c->empty()) {
239                 delete c->back();
240                 c->pop_back();
241                 interpolation.remove_channel_from ();
242         }
243
244         _n_channels.set(DataType::AUDIO, c->size());
245
246         return 0;
247 }
248
249 int
250 DiskIOProcessor::remove_channel (uint32_t how_many)
251 {
252         RCUWriter<ChannelList> writer (channels);
253         boost::shared_ptr<ChannelList> c = writer.get_copy();
254
255         return remove_channel_from (c, how_many);
256 }
257