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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
|
/*
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"
#include "ardour/port_manager.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 AudioBackendInfo;
class AudioEngine : public SessionHandlePtr, public PortManager
{
public:
static AudioEngine* create (const std::string& client_name, const std::string& session_uuid);
virtual ~AudioEngine ();
int discover_backends();
std::vector<std::string> available_backends() const;
std::string current_backend_name () const;
int set_backend (const std::string&);
ProcessThread* main_thread() const { return _main_thread; }
std::string client_name() const { return backend_client_name; }
/* START BACKEND PROXY API
*
* See audio_backend.h for full documentation and semantics. These wrappers
* just forward to a backend implementation.
*/
int start ();
int stop ();
int pause ();
int freewheel (bool start_stop);
float get_cpu_load() const ;
void transport_start ();
void transport_stop ();
TransportState transport_state ();
void transport_locate (framepos_t pos);
framepos_t transport_frame();
framecnt_t sample_rate () const;
pframes_t samples_per_cycle () const;
int usecs_per_cycle () const;
size_t raw_buffer_size (DataType t);
pframes_t sample_time ();
pframes_t sample_time_at_cycle_start ();
pframes_t samples_since_cycle_start ();
bool get_sync_offset (pframes_t& offset) const;
int create_process_thread (boost::function<void()> func, pthread_t*, size_t stacksize);
bool is_realtime() const;
bool connected() const;
int set_device_name (const std::string&);
int set_sample_rate (float);
int set_buffer_size (uint32_t);
int set_sample_format (SampleFormat);
int set_interleaved (bool yn);
int set_input_channels (uint32_t);
int set_output_channels (uint32_t);
int set_systemic_input_latency (uint32_t);
int set_systemic_output_latency (uint32_t);
/* END BACKEND PROXY API */
bool freewheeling() const { return _freewheeling; }
bool running() const { return _running; }
Glib::Threads::Mutex& process_lock() { return _process_lock; }
int request_buffer_size (pframes_t samples) {
return set_buffer_size (samples);
}
framecnt_t processed_frames() const { return _processed_frames; }
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;
static AudioEngine* instance() { return _instance; }
static void destroy();
void died ();
/* The backend will cause these at the appropriate time(s)
*/
int process_callback (pframes_t nframes);
int buffer_size_change (pframes_t nframes);
int sample_rate_change (pframes_t nframes);
void freewheel_callback (bool);
void timebase_callback (TransportState state, pframes_t nframes, framepos_t pos, int new_position);
int sync_callback (TransportState state, framepos_t position);
int port_registration_callback ();
void latency_callback (bool for_playback);
void halted_callback (const char* reason);
/* sets up the process callback thread */
static void thread_init_callback (void *);
private:
AudioEngine (const std::string& client_name, const std::string& session_uuid);
static AudioEngine* _instance;
boost::shared_ptr<AudioBackend> _backend;
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;
std::string backend_client_name;
std::string backend_session_uuid;
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;
typedef std::map<std::string,AudioBackendInfo*> BackendMap;
BackendMap _backends;
AudioBackendInfo* backend_discover (const std::string&);
void drop_backend ();
};
} // namespace ARDOUR
#endif /* __ardour_audioengine_h__ */
|