summaryrefslogtreecommitdiff
path: root/libs/ardour/ardour/audioengine.h
blob: a3f16ff376eb1dbeeb2610f6c7a7300f162b244d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/*
    Copyright (C) 2002-2004 Paul Davis

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#ifndef __ardour_audioengine_h__
#define __ardour_audioengine_h__

#ifdef WAF_BUILD
#include "libardour-config.h"
#endif

#include <iostream>
#include <list>
#include <set>
#include <cmath>
#include <exception>
#include <string>

#include <glibmm/threads.h>

#include "pbd/signals.h"
#include "pbd/stacktrace.h"

#include <jack/weakjack.h>
#include <jack/jack.h>
#include <jack/transport.h>
#include <jack/thread.h>

#include "ardour/ardour.h"

#include "ardour/data_type.h"
#include "ardour/session_handle.h"
#include "ardour/types.h"
#include "ardour/chan_count.h"

#ifdef HAVE_JACK_SESSION
#include <jack/session.h>
#endif

namespace ARDOUR {

class InternalPort;
class MidiPort;
class Port;
class Session;
class ProcessThread;
class AudioBackend;

class AudioEngine : public SessionHandlePtr
{
public:
    typedef std::map<std::string,boost::shared_ptr<Port> > Ports;
    
    AudioEngine (std::string client_name, std::string session_uuid);
    virtual ~AudioEngine ();
    
    static int discover_backends();
    std::vector<std::string> available_backends() const;
    std::string current_backend_name () const;

    ProcessThread* main_thread() const { return _main_thread; }
    
    std::string client_name() const { return backend_client_name; }
    
    int stop (bool forever = false);
    int start ();
    int pause ();
    int freewheel (bool onoff);
    bool freewheeling() const { return _freewheeling; }
   
    bool running() const { return _running; }
    Glib::Threads::Mutex& process_lock() { return _process_lock; }

    int request_buffer_size (pframes_t);

    framecnt_t processed_frames() const { return _processed_frames; }
    
    float get_cpu_load();
    
    void set_session (Session *);
    void remove_session (); // not a replacement for SessionHandle::session_going_away()
    
    class NoBackendAvailable : public std::exception {
      public:
	virtual const char *what() const throw() { return "could not connect to engine backend"; }
    };
    
    void split_cycle (pframes_t offset);
    
    int  reset_timebase ();
    
    void update_latencies ();

    
    /* this signal is sent for every process() cycle while freewheeling.
       (the regular process() call to session->process() is not made)
    */
    
    PBD::Signal1<int, pframes_t> Freewheel;
    
    PBD::Signal0<void> Xrun;
    
    /* this signal is if the backend notifies us of a graph order event */
    
    PBD::Signal0<void> GraphReordered;
    
#ifdef HAVE_JACK_SESSION
    PBD::Signal1<void,jack_session_event_t *> JackSessionEvent;
#endif
    
    /* this signal is emitted if the sample rate changes */
    
    PBD::Signal1<void, framecnt_t> SampleRateChanged;
    
    /* this signal is sent if the backend ever disconnects us */
    
    PBD::Signal1<void,const char*> Halted;
    
    /* these two are emitted when the engine itself is
       started and stopped
    */
    
    PBD::Signal0<void> Running;
    PBD::Signal0<void> Stopped;
    
    /** Emitted if a Port is registered or unregistered */
    PBD::Signal0<void> PortRegisteredOrUnregistered;
    
    /** Emitted if a Port is connected or disconnected.
     *  The Port parameters are the ports being connected / disconnected, or 0 if they are not known to Ardour.
     *  The std::string parameters are the (long) port names.
     *  The bool parameter is true if ports were connected, or false for disconnected.
     */
    PBD::Signal5<void, boost::weak_ptr<Port>, std::string, boost::weak_ptr<Port>, std::string, bool> PortConnectedOrDisconnected;
    
    std::string make_port_name_relative (std::string) const;
    std::string make_port_name_non_relative (std::string) const;
    bool port_is_mine (const std::string&) const;
    
    static AudioEngine* instance() { return _instance; }
    static void destroy();
    void died ();
    
    /* The backend will cause this at the appropriate time(s)
     */
    int    process_callback (pframes_t nframes);
    
  private:
    static AudioEngine*       _instance;
    
    Glib::Threads::Mutex      _process_lock;
    Glib::Threads::Cond        session_removed;
    bool                       session_remove_pending;
    frameoffset_t              session_removal_countdown;
    gain_t                     session_removal_gain;
    gain_t                     session_removal_gain_step;
    bool                      _running;
    bool                      _has_run;
    mutable framecnt_t        _buffer_size;
    std::map<DataType,size_t> _raw_buffer_sizes;
    mutable framecnt_t        _frame_rate;
    /// number of frames between each check for changes in monitor input
    framecnt_t                 monitor_check_interval;
    /// time of the last monitor check in frames
    framecnt_t                 last_monitor_check;
    /// the number of frames processed since start() was called
    framecnt_t                _processed_frames;
    bool                      _freewheeling;
    bool                      _pre_freewheel_mmc_enabled;
    int                       _usecs_per_cycle;
    bool                       port_remove_in_progress;
    Glib::Threads::Thread*     m_meter_thread;
    ProcessThread*            _main_thread;
    
    
    void meter_thread ();
    void start_metering_thread ();
    void stop_metering_thread ();
    
    static gint      m_meter_exit;
    
    void parameter_changed (const std::string&);
    PBD::ScopedConnection config_connection;
};
	
} // namespace ARDOUR

#endif /* __ardour_audioengine_h__ */