part-way through getting the audioengine changes to compile
[ardour.git] / libs / ardour / audioengine.cc
1 /*
2     Copyright (C) 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 <unistd.h>
21 #include <cerrno>
22 #include <vector>
23 #include <exception>
24 #include <stdexcept>
25 #include <sstream>
26
27 #include <glibmm/timer.h>
28 #include <glibmm/pattern.h>
29 #include <glibmm/module.h>
30
31 #include "pbd/epa.h"
32 #include "pbd/file_utils.h"
33 #include "pbd/pthread_utils.h"
34 #include "pbd/stacktrace.h"
35 #include "pbd/unknown_type.h"
36
37 #include <jack/weakjack.h>
38
39 #include "midi++/port.h"
40 #include "midi++/jack_midi_port.h"
41 #include "midi++/mmc.h"
42 #include "midi++/manager.h"
43
44 #include "ardour/audio_port.h"
45 #include "ardour/audio_backend.h"
46 #include "ardour/audioengine.h"
47 #include "ardour/backend_search_path.h"
48 #include "ardour/buffer.h"
49 #include "ardour/cycle_timer.h"
50 #include "ardour/internal_send.h"
51 #include "ardour/meter.h"
52 #include "ardour/midi_port.h"
53 #include "ardour/port.h"
54 #include "ardour/process_thread.h"
55 #include "ardour/session.h"
56
57 #include "i18n.h"
58
59 using namespace std;
60 using namespace ARDOUR;
61 using namespace PBD;
62
63 gint AudioEngine::m_meter_exit;
64 AudioEngine* AudioEngine::_instance = 0;
65
66 AudioEngine::AudioEngine (const std::string& bcn, const std::string& bsu)
67         : _backend (0)
68         , session_remove_pending (false)
69         , session_removal_countdown (-1)
70         , monitor_check_interval (INT32_MAX)
71         , last_monitor_check (0)
72         , _processed_frames (0)
73         , _freewheeling (false)
74         , _pre_freewheel_mmc_enabled (false)
75         , _usecs_per_cycle (0)
76         , port_remove_in_progress (false)
77         , m_meter_thread (0)
78         , _main_thread (0)
79         , backend_client_name (bcn)
80         , backend_session_uuid (bsu)
81 {
82         g_atomic_int_set (&m_meter_exit, 0);
83 }
84
85 AudioEngine::~AudioEngine ()
86 {
87         drop_backend ();
88
89         config_connection.disconnect ();
90
91         {
92                 Glib::Threads::Mutex::Lock tm (_process_lock);
93                 session_removed.signal ();
94                 stop_metering_thread ();
95         }
96 }
97
98 AudioEngine*
99 AudioEngine::create (const std::string& bcn, const std::string& bsu)
100 {
101         if (_instance) {
102                 return _instance;
103         }
104         return new AudioEngine (bcn, bsu);
105 }
106
107 void
108 AudioEngine::drop_backend ()
109 {
110         if (_backend) {
111                 _backend->stop ();
112                 delete _backend;
113                 _backend = 0;
114         }
115 }
116
117 int
118 AudioEngine::set_backend (const std::string& name)
119 {
120         BackendMap::iterator b = _backends.find (name);
121
122         if (b == _backends.end()) {
123                 return -1;
124         }
125
126         drop_backend ();
127
128         _backend = b->second;
129
130         return 0;
131 }
132
133 void
134 _thread_init_callback (void * /*arg*/)
135 {
136         /* make sure that anybody who needs to know about this thread
137            knows about it.
138         */
139
140         pthread_set_name (X_("audioengine"));
141
142         PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("Audioengine"), 4096);
143         PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("Audioengine"), 128);
144
145         SessionEvent::create_per_thread_pool (X_("Audioengine"), 512);
146
147         MIDI::JackMIDIPort::set_process_thread (pthread_self());
148 }
149
150
151
152 void
153 AudioEngine::split_cycle (pframes_t offset)
154 {
155         /* caller must hold process lock */
156
157         Port::increment_global_port_buffer_offset (offset);
158
159         /* tell all Ports that we're going to start a new (split) cycle */
160
161         boost::shared_ptr<Ports> p = ports.reader();
162
163         for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
164                 i->second->cycle_split ();
165         }
166 }
167
168
169 /** Method called by our ::process_thread when there is work to be done.
170  *  @param nframes Number of frames to process.
171  */
172 int
173 AudioEngine::process_callback (pframes_t nframes)
174 {
175         Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK);
176
177         PT_TIMING_REF;
178         PT_TIMING_CHECK (1);
179
180         /// The number of frames that will have been processed when we've finished
181         pframes_t next_processed_frames;
182
183         /* handle wrap around of total frames counter */
184
185         if (max_framepos - _processed_frames < nframes) {
186                 next_processed_frames = nframes - (max_framepos - _processed_frames);
187         } else {
188                 next_processed_frames = _processed_frames + nframes;
189         }
190
191         if (!tm.locked()) {
192                 /* return having done nothing */
193                 _processed_frames = next_processed_frames;
194                 return 0;
195         }
196
197         if (session_remove_pending) {
198
199                 /* perform the actual session removal */
200
201                 if (session_removal_countdown < 0) {
202
203                         /* fade out over 1 second */
204                         session_removal_countdown = _frame_rate/2;
205                         session_removal_gain = 1.0;
206                         session_removal_gain_step = 1.0/session_removal_countdown;
207
208                 } else if (session_removal_countdown > 0) {
209
210                         /* we'll be fading audio out.
211                            
212                            if this is the last time we do this as part 
213                            of session removal, do a MIDI panic now
214                            to get MIDI stopped. This relies on the fact
215                            that "immediate data" (aka "out of band data") from
216                            MIDI tracks is *appended* after any other data, 
217                            so that it emerges after any outbound note ons, etc.
218                         */
219
220                         if (session_removal_countdown <= nframes) {
221                                 _session->midi_panic ();
222                         }
223
224                 } else {
225                         /* fade out done */
226                         _session = 0;
227                         session_removal_countdown = -1; // reset to "not in progress"
228                         session_remove_pending = false;
229                         session_removed.signal(); // wakes up thread that initiated session removal
230                 }
231         }
232
233         if (_session == 0) {
234
235                 if (!_freewheeling) {
236                         MIDI::Manager::instance()->cycle_start(nframes);
237                         MIDI::Manager::instance()->cycle_end();
238                 }
239
240                 _processed_frames = next_processed_frames;
241
242                 return 0;
243         }
244
245         /* tell all relevant objects that we're starting a new cycle */
246
247         InternalSend::CycleStart (nframes);
248         Port::set_global_port_buffer_offset (0);
249         Port::set_cycle_framecnt (nframes);
250
251         /* tell all Ports that we're starting a new cycle */
252
253         boost::shared_ptr<Ports> p = ports.reader();
254
255         for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
256                 i->second->cycle_start (nframes);
257         }
258
259         /* test if we are freewheeling and there are freewheel signals connected.
260            ardour should act normally even when freewheeling unless /it/ is
261            exporting 
262         */
263
264         if (_freewheeling && !Freewheel.empty()) {
265
266                 Freewheel (nframes);
267
268         } else {
269                 MIDI::Manager::instance()->cycle_start(nframes);
270
271                 if (_session) {
272                         _session->process (nframes);
273                 }
274
275                 MIDI::Manager::instance()->cycle_end();
276         }
277
278         if (_freewheeling) {
279                 return 0;
280         }
281
282         if (!_running) {
283                 _processed_frames = next_processed_frames;
284                 return 0;
285         }
286
287         if (last_monitor_check + monitor_check_interval < next_processed_frames) {
288
289                 boost::shared_ptr<Ports> p = ports.reader();
290
291                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
292
293                         bool x;
294
295                         if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
296                                 i->second->set_last_monitor (x);
297                                 /* XXX I think this is dangerous, due to
298                                    a likely mutex in the signal handlers ...
299                                 */
300                                 i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
301                         }
302                 }
303                 last_monitor_check = next_processed_frames;
304         }
305
306         if (_session->silent()) {
307
308                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
309
310                         if (i->second->sends_output()) {
311                                 i->second->get_buffer(nframes).silence(nframes);
312                         }
313                 }
314         }
315
316         if (session_remove_pending && session_removal_countdown) {
317
318                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
319
320                         if (i->second->sends_output()) {
321
322                                 boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
323                                 if (ap) {
324                                         Sample* s = ap->engine_get_whole_audio_buffer ();
325                                         gain_t g = session_removal_gain;
326                                         
327                                         for (pframes_t n = 0; n < nframes; ++n) {
328                                                 *s++ *= g;
329                                                 g -= session_removal_gain_step;
330                                         }
331                                 }
332                         }
333                 }
334                 
335                 if (session_removal_countdown > nframes) {
336                         session_removal_countdown -= nframes;
337                 } else {
338                         session_removal_countdown = 0;
339                 }
340
341                 session_removal_gain -= (nframes * session_removal_gain_step);
342         }
343
344         // Finalize ports
345
346         for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
347                 i->second->cycle_end (nframes);
348         }
349
350         _processed_frames = next_processed_frames;
351
352         PT_TIMING_CHECK (2);
353         
354         return 0;
355 }
356
357
358 void
359 AudioEngine::stop_metering_thread ()
360 {
361         if (m_meter_thread) {
362                 g_atomic_int_set (&m_meter_exit, 1);
363                 m_meter_thread->join ();
364                 m_meter_thread = 0;
365         }
366 }
367
368 void
369 AudioEngine::start_metering_thread ()
370 {
371         if (m_meter_thread == 0) {
372                 g_atomic_int_set (&m_meter_exit, 0);
373                 m_meter_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::meter_thread, this));
374         }
375 }
376
377 void
378 AudioEngine::meter_thread ()
379 {
380         pthread_set_name (X_("meter"));
381
382         while (true) {
383                 Glib::usleep (10000); /* 1/100th sec interval */
384                 if (g_atomic_int_get(&m_meter_exit)) {
385                         break;
386                 }
387                 Metering::Meter ();
388         }
389 }
390
391 void
392 AudioEngine::set_session (Session *s)
393 {
394         Glib::Threads::Mutex::Lock pl (_process_lock);
395
396         SessionHandlePtr::set_session (s);
397
398         if (_session) {
399
400                 start_metering_thread ();
401
402                 pframes_t blocksize = _backend->get_buffer_size ();
403
404                 /* page in as much of the session process code as we
405                    can before we really start running.
406                 */
407
408                 boost::shared_ptr<Ports> p = ports.reader();
409
410                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
411                         i->second->cycle_start (blocksize);
412                 }
413
414                 _session->process (blocksize);
415                 _session->process (blocksize);
416                 _session->process (blocksize);
417                 _session->process (blocksize);
418                 _session->process (blocksize);
419                 _session->process (blocksize);
420                 _session->process (blocksize);
421                 _session->process (blocksize);
422
423                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
424                         i->second->cycle_end (blocksize);
425                 }
426         }
427 }
428
429 void
430 AudioEngine::remove_session ()
431 {
432         Glib::Threads::Mutex::Lock lm (_process_lock);
433
434         if (_running) {
435
436                 stop_metering_thread ();
437
438                 if (_session) {
439                         session_remove_pending = true;
440                         session_removed.wait(_process_lock);
441                 }
442
443         } else {
444                 SessionHandlePtr::set_session (0);
445         }
446
447         remove_all_ports ();
448 }
449
450
451 void
452 AudioEngine::died ()
453 {
454         /* called from a signal handler for SIGPIPE */
455
456         stop_metering_thread ();
457
458         _running = false;
459         _buffer_size = 0;
460         _frame_rate = 0;
461 }
462
463 int
464 AudioEngine::reset_timebase ()
465 {
466         if (_session) {
467                 if (_session->config.get_jack_time_master()) {
468                         _backend->set_time_master (true);
469                 } else {
470                         _backend->set_time_master (false);
471                 }
472         }
473         return 0;
474 }
475
476
477 void
478 AudioEngine::destroy ()
479 {
480         delete _instance;
481         _instance = 0;
482 }
483
484 int
485 AudioEngine::discover_backends ()
486 {
487         vector<std::string> backend_modules;
488         AudioBackend* backend;
489
490         _backends.clear ();
491
492         Glib::PatternSpec so_extension_pattern("*.so");
493         Glib::PatternSpec dylib_extension_pattern("*.dylib");
494
495         find_matching_files_in_search_path (backend_search_path (),
496                                             so_extension_pattern, backend_modules);
497
498         find_matching_files_in_search_path (backend_search_path (),
499                                             dylib_extension_pattern, backend_modules);
500
501         DEBUG_TRACE (DEBUG::Panning, string_compose (_("looking for backends in %1"), backend_search_path().to_string()));
502
503         for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
504                 if ((backend = backend_discover (*i)) != 0) {
505                         _backends.insert (make_pair (backend->name(), backend));
506                 }
507         }
508
509         return _backends.size();
510 }
511
512 AudioBackend*
513 AudioEngine::backend_discover (const string& path)
514 {
515         Glib::Module* module = new Glib::Module(path);
516         AudioBackend* (*dfunc)(void);
517         void* func = 0;
518
519         if (!module) {
520                 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
521                                 Glib::Module::get_last_error()) << endmsg;
522                 delete module;
523                 return 0;
524         }
525
526         if (!module->get_symbol("backend_factory", func)) {
527                 error << string_compose(_("AudioEngine: module \"%1\" has no factory function."), path) << endmsg;
528                 error << Glib::Module::get_last_error() << endmsg;
529                 delete module;
530                 return 0;
531         }
532
533         dfunc = (AudioBackend* (*)(void))func;
534         AudioBackend* backend = dfunc();
535
536         return backend;
537 }
538
539 /* BACKEND PROXY WRAPPERS */
540
541 int
542 AudioEngine::start ()
543 {
544         if (!_backend) {
545                 return -1;
546         }
547
548         if (!_running) {
549
550                 if (_session) {
551                         BootMessage (_("Connect session to engine"));
552                         _session->set_frame_rate (_backend->sample_rate());
553                 }
554
555                 _processed_frames = 0;
556                 last_monitor_check = 0;
557
558                 if (_backend->start() == 0) {
559                         _running = true;
560                         _has_run = true;
561                         Running(); /* EMIT SIGNAL */
562                 } else {
563                         /* should report error? */
564                 }
565         }
566                 
567         return _running ? 0 : -1;
568 }
569
570 int
571 AudioEngine::stop ()
572 {
573         if (!_backend) {
574                 return 0;
575         }
576         
577         return _backend->stop ();
578 }
579
580 int
581 AudioEngine::pause ()
582 {
583         if (!_backend) {
584                 return 0;
585         }
586         
587         return _backend->pause ();
588 }
589
590 int
591 AudioEngine::freewheel (bool start_stop)
592 {
593         if (!_backend) {
594                 return -1;
595         }
596
597         /* _freewheeling will be set when first Freewheel signal occurs */
598
599         return _backend->freewheel (start_stop);
600 }
601
602 float
603 AudioEngine::get_cpu_load() const 
604 {
605         if (!_backend) {
606                 return 0.0;
607         }
608         return _backend->get_cpu_load ();
609 }
610
611 void
612 AudioEngine::transport_start ()
613 {
614         if (!_backend) {
615                 return;
616         }
617         return _backend->transport_start ();
618 }
619
620 void
621 AudioEngine::transport_stop ()
622 {
623         if (!_backend) {
624                 return;
625         }
626         return _backend->transport_stop ();
627 }
628
629 TransportState
630 AudioEngine::transport_state ()
631 {
632         if (!_backend) {
633                 return TransportStopped;
634         }
635         return _backend->transport_state ();
636 }
637
638 void
639 AudioEngine::transport_locate (framepos_t pos)
640 {
641         if (!_backend) {
642                 return;
643         }
644         return _backend->transport_locate (pos);
645 }
646
647 framepos_t
648 AudioEngine::transport_frame()
649 {
650         if (!_backend) {
651                 return 0;
652         }
653         return _backend->transport_frame ();
654 }
655
656 framecnt_t
657 AudioEngine::sample_rate () const
658 {
659         if (!_backend) {
660                 return 0;
661         }
662         return _backend->sample_rate ();
663 }
664
665 pframes_t
666 AudioEngine::samples_per_cycle () const
667 {
668         if (!_backend) {
669                 return 0;
670         }
671         return _backend->samples_per_cycle ();
672 }
673
674 int
675 AudioEngine::usecs_per_cycle () const
676 {
677         if (!_backend) {
678                 return -1;
679         }
680         return _backend->start ();
681 }
682
683 size_t
684 AudioEngine::raw_buffer_size (DataType t)
685 {
686         if (!_backend) {
687                 return -1;
688         }
689         return _backend->raw_buffer_size (t);
690 }
691
692 pframes_t
693 AudioEngine::sample_time ()
694 {
695         if (!_backend) {
696                 return 0;
697         }
698         return _backend->sample_time ();
699 }
700
701 pframes_t
702 AudioEngine::sample_time_at_cycle_start ()
703 {
704         if (!_backend) {
705                 return 0;
706         }
707         return _backend->sample_time_at_cycle_start ();
708 }
709
710 pframes_t
711 AudioEngine::samples_since_cycle_start ()
712 {
713         if (!_backend) {
714                 return 0;
715         }
716         return _backend->samples_since_cycle_start ();
717 }
718
719 bool
720 AudioEngine::get_sync_offset (pframes_t& offset) const
721 {
722         if (!_backend) {
723                 return false;
724         }
725         return _backend->get_sync_offset (offset);
726 }
727
728 int
729 AudioEngine::create_process_thread (boost::function<void()> func, pthread_t* thr, size_t stacksize)
730 {
731         if (!_backend) {
732                 return -1;
733         }
734         return _backend->create_process_thread (func, thr, stacksize);
735 }
736