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