4f8f244c223c9c5c76fb5e67aefe36565f749ce6
[ardour.git] / libs / ardour / session_butler.cc
1 /*
2     Copyright (C) 1999-2002 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 <algorithm>
21 #include <string>
22 #include <cmath>
23 #include <cerrno>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <poll.h>
27
28 #include <glibmm/thread.h>
29
30 #include "pbd/error.h"
31 #include "pbd/pthread_utils.h"
32 #include "pbd/stacktrace.h"
33
34 #include "ardour/audio_diskstream.h"
35 #include "ardour/audioengine.h"
36 #include "ardour/configuration.h"
37 #include "ardour/crossfade.h"
38 #include "ardour/io.h"
39 #include "ardour/midi_diskstream.h"
40 #include "ardour/session.h"
41 #include "ardour/timestamps.h"
42
43 #include "i18n.h"
44
45 using namespace std;
46 using namespace ARDOUR;
47 using namespace PBD;
48
49 static float _read_data_rate;
50 static float _write_data_rate;
51
52 /* XXX put this in the right place */
53
54 static inline uint32_t next_power_of_two (uint32_t n)
55 {
56         --n;
57         n |= n >> 16;
58         n |= n >> 8;
59         n |= n >> 4;
60         n |= n >> 2;
61         n |= n >> 1;
62         ++n;
63         return n;
64 }
65
66 /*---------------------------------------------------------------------------
67  BUTLER THREAD
68  ---------------------------------------------------------------------------*/
69
70 int
71 Session::start_butler_thread ()
72 {
73         /* size is in Samples, not bytes */
74         audio_dstream_buffer_size = (uint32_t) floor (Config->get_audio_track_buffer_seconds() * (float) frame_rate());
75
76         /* size is in bytes
77          * XXX: Jack needs to tell us the MIDI buffer size
78          * (i.e. how many MIDI bytes we might see in a cycle)
79          */
80         midi_dstream_buffer_size = (uint32_t) floor (Config->get_midi_track_buffer_seconds() * (float)frame_rate());
81         MidiDiskstream::set_readahead_frames ((nframes_t) (Config->get_midi_readahead() * (float) frame_rate()));
82
83         Crossfade::set_buffer_size (audio_dstream_buffer_size);
84
85         butler_should_run = false;
86
87         if (pipe (butler_request_pipe)) {
88                 error << string_compose(_("Cannot create transport request signal pipe (%1)"), strerror (errno)) << endmsg;
89                 return -1;
90         }
91
92         if (fcntl (butler_request_pipe[0], F_SETFL, O_NONBLOCK)) {
93                 error << string_compose(_("UI: cannot set O_NONBLOCK on butler request pipe (%1)"), strerror (errno)) << endmsg;
94                 return -1;
95         }
96
97         if (fcntl (butler_request_pipe[1], F_SETFL, O_NONBLOCK)) {
98                 error << string_compose(_("UI: cannot set O_NONBLOCK on butler request pipe (%1)"), strerror (errno)) << endmsg;
99                 return -1;
100         }
101
102         if (pthread_create_and_store ("disk butler", &butler_thread, 0, _butler_thread_work, this)) {
103                 error << _("Session: could not create butler thread") << endmsg;
104                 return -1;
105         }
106
107         // pthread_detach (butler_thread);
108
109         return 0;
110 }
111
112 void
113 Session::terminate_butler_thread ()
114 {
115         if (butler_thread) {
116                 void* status;
117                 char c = ButlerRequest::Quit;
118                 ::write (butler_request_pipe[1], &c, 1);
119                 pthread_join (butler_thread, &status);
120         }
121 }
122
123 void
124 Session::schedule_butler_transport_work ()
125 {
126         g_atomic_int_inc (&butler_should_do_transport_work);
127         summon_butler ();
128 }
129
130 void
131 Session::schedule_curve_reallocation ()
132 {
133         post_transport_work = PostTransportWork (post_transport_work | PostTransportCurveRealloc);
134         schedule_butler_transport_work ();
135 }
136
137 void
138 Session::summon_butler ()
139 {
140         char c = ButlerRequest::Run;
141         ::write (butler_request_pipe[1], &c, 1);
142         // PBD::stacktrace (cerr);
143 }
144
145 void
146 Session::stop_butler ()
147 {
148         Glib::Mutex::Lock lm (butler_request_lock);
149         char c = ButlerRequest::Pause;
150         ::write (butler_request_pipe[1], &c, 1);
151         butler_paused.wait(butler_request_lock);
152 }
153
154 void
155 Session::wait_till_butler_finished ()
156 {
157         Glib::Mutex::Lock lm (butler_request_lock);
158         char c = ButlerRequest::Wake;
159         ::write (butler_request_pipe[1], &c, 1);
160         butler_paused.wait(butler_request_lock);
161 }
162
163 void *
164 Session::_butler_thread_work (void* arg)
165 {
166         PBD::notify_gui_about_thread_creation (pthread_self(), X_("Butler"));
167         return ((Session *) arg)->butler_thread_work ();
168         return 0;
169 }
170
171 void *
172 Session::butler_thread_work ()
173 {
174         uint32_t err = 0;
175         int32_t bytes;
176         bool compute_io;
177         microseconds_t begin, end;
178
179         struct pollfd pfd[1];
180         bool disk_work_outstanding = false;
181         DiskstreamList::iterator i;
182
183         while (true) {
184                 pfd[0].fd = butler_request_pipe[0];
185                 pfd[0].events = POLLIN|POLLERR|POLLHUP;
186
187                 if (poll (pfd, 1, (disk_work_outstanding ? 0 : -1)) < 0) {
188
189                         if (errno == EINTR) {
190                                 continue;
191                         }
192
193                         error << string_compose (_("poll on butler request pipe failed (%1)"),
194                                           strerror (errno))
195                               << endmsg;
196                         break;
197                 }
198
199                 if (pfd[0].revents & ~POLLIN) {
200                         error << string_compose (_("Error on butler thread request pipe: fd=%1 err=%2"), pfd[0].fd, pfd[0].revents) << endmsg;
201                         break;
202                 }
203
204                 if (pfd[0].revents & POLLIN) {
205
206                         char req;
207
208                         /* empty the pipe of all current requests */
209
210                         while (1) {
211                                 size_t nread = ::read (butler_request_pipe[0], &req, sizeof (req));
212                                 if (nread == 1) {
213
214                                         switch ((ButlerRequest::Type) req) {
215
216                                         case ButlerRequest::Wake:
217                                                 break;
218
219                                         case ButlerRequest::Run:
220                                                 butler_should_run = true;
221                                                 break;
222
223                                         case ButlerRequest::Pause:
224                                                 butler_should_run = false;
225                                                 break;
226
227                                         case ButlerRequest::Quit:
228                                                 pthread_exit_pbd (0);
229                                                 /*NOTREACHED*/
230                                                 break;
231
232                                         default:
233                                                 break;
234                                         }
235
236                                 } else if (nread == 0) {
237                                         break;
238                                 } else if (errno == EAGAIN) {
239                                         break;
240                                 } else {
241                                         fatal << _("Error reading from butler request pipe") << endmsg;
242                                         /*NOTREACHED*/
243                                 }
244                         }
245                 }
246
247                 if (transport_work_requested()) {
248                         butler_transport_work ();
249                 }
250
251                 disk_work_outstanding = false;
252                 bytes = 0;
253                 compute_io = true;
254
255                 begin = get_microseconds();
256
257                 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader ();
258
259 //              for (i = dsl->begin(); i != dsl->end(); ++i) {
260 //                      cerr << "BEFORE " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl;
261 //              }
262
263                 for (i = dsl->begin(); !transport_work_requested() && butler_should_run && i != dsl->end(); ++i) {
264
265                         boost::shared_ptr<Diskstream> ds = *i;
266
267                         /* don't read inactive tracks */
268
269                         boost::shared_ptr<IO> io = ds->io();
270
271                         if (io && !io->active()) {
272                                 continue;
273                         }
274
275                         switch (ds->do_refill ()) {
276                         case 0:
277                                 bytes += ds->read_data_count();
278                                 break;
279                         case 1:
280                                 bytes += ds->read_data_count();
281                                 disk_work_outstanding = true;
282                                 break;
283
284                         default:
285                                 compute_io = false;
286                                 error << string_compose(_("Butler read ahead failure on dstream %1"), (*i)->name()) << endmsg;
287                                 break;
288                         }
289
290                 }
291
292                 if (i != dsl->end()) {
293                         /* we didn't get to all the streams */
294                         disk_work_outstanding = true;
295                 }
296
297                 if (!err && transport_work_requested()) {
298                         continue;
299                 }
300
301                 if (compute_io) {
302                         end = get_microseconds();
303                         if(end-begin > 0) {
304                         _read_data_rate = (float) bytes / (float) (end - begin);
305                         } else { _read_data_rate = 0; // infinity better
306                          }
307                 }
308
309                 bytes = 0;
310                 compute_io = true;
311                 begin = get_microseconds();
312
313                 for (i = dsl->begin(); !transport_work_requested() && butler_should_run && i != dsl->end(); ++i) {
314                         // cerr << "write behind for " << (*i)->name () << endl;
315
316                         /* note that we still try to flush diskstreams attached to inactive routes
317                          */
318
319                         switch ((*i)->do_flush (ButlerContext)) {
320                         case 0:
321                                 bytes += (*i)->write_data_count();
322                                 break;
323                         case 1:
324                                 bytes += (*i)->write_data_count();
325                                 disk_work_outstanding = true;
326                                 break;
327
328                         default:
329                                 err++;
330                                 compute_io = false;
331                                 error << string_compose(_("Butler write-behind failure on dstream %1"), (*i)->name()) << endmsg;
332                                 /* don't break - try to flush all streams in case they
333                                    are split across disks.
334                                 */
335                         }
336                 }
337
338                 if (err && actively_recording()) {
339                         /* stop the transport and try to catch as much possible
340                            captured state as we can.
341                         */
342                         request_stop ();
343                 }
344
345                 if (i != dsl->end()) {
346                         /* we didn't get to all the streams */
347                         disk_work_outstanding = true;
348                 }
349
350                 if (!err && transport_work_requested()) {
351                         continue;
352                 }
353
354                 if (compute_io) {
355                         // there are no apparent users for this calculation?
356                         end = get_microseconds();
357                         if(end-begin > 0) {
358                         _write_data_rate = (float) bytes / (float) (end - begin);
359                         } else {
360                         _write_data_rate = 0; // Well, infinity would be better
361                         }
362                 }
363
364                 if (!disk_work_outstanding) {
365                         refresh_disk_space ();
366                 }
367
368
369                 {
370                         Glib::Mutex::Lock lm (butler_request_lock);
371
372                         if (butler_should_run && (disk_work_outstanding || transport_work_requested())) {
373 //                              for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
374 //                                      cerr << "AFTER " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl;
375 //                              }
376
377                                 continue;
378                         }
379
380                         butler_paused.signal();
381                 }
382         }
383
384         pthread_exit_pbd (0);
385         /*NOTREACHED*/
386         return (0);
387 }
388
389
390 void
391 Session::request_overwrite_buffer (Diskstream* stream)
392 {
393         Event *ev = new Event (Event::Overwrite, Event::Add, Event::Immediate, 0, 0, 0.0);
394         ev->set_ptr (stream);
395         queue_event (ev);
396 }
397
398 /** Process thread. */
399 void
400 Session::overwrite_some_buffers (Diskstream* ds)
401 {
402         if (actively_recording()) {
403                 return;
404         }
405
406         if (ds) {
407
408                 ds->set_pending_overwrite (true);
409
410         } else {
411
412                 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
413                 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
414                         (*i)->set_pending_overwrite (true);
415                 }
416         }
417
418         post_transport_work = PostTransportWork (post_transport_work | PostTransportOverWrite);
419         schedule_butler_transport_work ();
420 }
421
422 float
423 Session::read_data_rate () const
424 {
425         /* disk i/o in excess of 10000MB/sec indicate the buffer cache
426            in action. ignore it.
427         */
428         return _read_data_rate > 10485.7600000f ? 0.0f : _read_data_rate;
429 }
430
431 float
432 Session::write_data_rate () const
433 {
434         /* disk i/o in excess of 10000MB/sec indicate the buffer cache
435            in action. ignore it.
436         */
437         return _write_data_rate > 10485.7600000f ? 0.0f : _write_data_rate;
438 }
439
440 uint32_t
441 Session::playback_load ()
442 {
443         return (uint32_t) g_atomic_int_get (&_playback_load);
444 }
445
446 uint32_t
447 Session::capture_load ()
448 {
449         return (uint32_t) g_atomic_int_get (&_capture_load);
450 }
451
452 uint32_t
453 Session::playback_load_min ()
454 {
455         return (uint32_t) g_atomic_int_get (&_playback_load_min);
456 }
457
458 uint32_t
459 Session::capture_load_min ()
460 {
461         return (uint32_t) g_atomic_int_get (&_capture_load_min);
462 }
463
464 void
465 Session::reset_capture_load_min ()
466 {
467         g_atomic_int_set (&_capture_load_min, 100);
468 }
469
470
471 void
472 Session::reset_playback_load_min ()
473 {
474         g_atomic_int_set (&_playback_load_min, 100);
475 }