summaryrefslogtreecommitdiff
path: root/libs/backends/coreaudio/coreaudio_pcmio.h
blob: e6d82571f48d9ab2176fc5b460c0b8a6828826c7 (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
204
205
206
/*
 * Copyright (C) 2015 Robin Gareus <robin@gareus.org>
 *
 * 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 __libbackend_coreaudio_pcmio_h__
#define __libbackend_coreaudio_pcmio_h__

#include <CoreServices/CoreServices.h>
#include <CoreAudio/CoreAudio.h>
#include <AudioUnit/AudioUnit.h>

#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>

#include <map>
#include <vector>
#include <string>

#define AUHAL_OUTPUT_ELEMENT 0
#define AUHAL_INPUT_ELEMENT 1


namespace ARDOUR {

class CoreAudioPCM {
public:
	CoreAudioPCM (void);
	~CoreAudioPCM (void);


	int      state (void) const { return _state; }
	uint32_t n_playback_channels (void) const { return _playback_channels; }
	uint32_t n_capture_channels (void) const { return _capture_channels; }

	void     discover();
	void     device_list (std::map<size_t, std::string> &devices) const { devices = _devices;}
	void     input_device_list (std::map<size_t, std::string> &devices) const { devices = _input_devices;}
	void     output_device_list (std::map<size_t, std::string> &devices) const { devices = _output_devices;}
	void     duplex_device_list (std::map<size_t, std::string> &devices) const { devices = _duplex_devices;}

	int      available_sample_rates (uint32_t device_id, std::vector<float>& sampleRates);
	int      available_buffer_sizes (uint32_t device_id, std::vector<uint32_t>& sampleRates);
	uint32_t available_channels (uint32_t device_id, bool input);
	float    current_sample_rate (uint32_t device_id, bool input = false);
	uint32_t get_latency (uint32_t device_id, bool input);
	uint32_t get_latency (bool input);

	std::string cached_port_name (uint32_t portnum, bool input) const;

	float    sample_rate ();
	uint32_t samples_per_period () const { return _samples_per_period; };

	int      set_samples_per_period (uint32_t);

	void     launch_control_app (uint32_t device_id);

	void     pcm_stop (void);
	int      pcm_start (
			uint32_t input_device,
			uint32_t output_device,
			uint32_t sample_rate,
			uint32_t samples_per_period,
			int (process_callback (void*, const uint32_t, const uint64_t)),
			void * process_arg
			);

	void     set_error_callback (
			void ( error_callback (void*)),
			void * error_arg
			) {
		_error_callback = error_callback;
		_error_arg = error_arg;
	}

	void     set_hw_changed_callback (
			void ( callback (void*)),
			void * arg
			) {
		_hw_changed_callback = callback;
		_hw_changed_arg = arg;
	}

	void     set_xrun_callback (
			void ( callback (void*)),
			void * arg
			) {
		_xrun_callback = callback;
		_xrun_arg = arg;
	}
	void     set_buffer_size_callback (
			void ( callback (void*)),
			void * arg
			) {
		_buffer_size_callback = callback;
		_buffer_size_arg = arg;
	}
	void     set_sample_rate_callback (
			void ( callback (void*)),
			void * arg
			) {
		_sample_rate_callback = callback;
		_sample_rate_arg = arg;
	}

	// must be called from process_callback;
	int      get_capture_channel (uint32_t chn, float *input, uint32_t n_samples);
	int      set_playback_channel (uint32_t chn, const float *input, uint32_t n_samples);
	uint32_t n_samples() const { return _cur_samples_per_period; };

	// really private
	OSStatus render_callback (
			AudioUnitRenderActionFlags* ioActionFlags,
			const AudioTimeStamp* inTimeStamp,
			UInt32 inBusNumber,
			UInt32 inNumberSamples,
			AudioBufferList* ioData);

	void xrun_callback ();
	void buffer_size_callback ();
	void sample_rate_callback ();
	void hw_changed_callback ();

private:
	float    current_sample_rate_id (AudioDeviceID id, bool input);
	uint32_t current_buffer_size_id (AudioDeviceID id);
	int      set_device_sample_rate_id (AudioDeviceID id, float rate, bool input);
	int      set_device_buffer_size_id (AudioDeviceID id, uint32_t samples_per_period);
	int      set_device_sample_rate (uint32_t device_id, float rate, bool input);
	void     get_stream_latencies (uint32_t device_id, bool input, std::vector<uint32_t>& latencies);
	void     cache_port_names (AudioDeviceID id, bool input);

	void destroy_aggregate_device();
	int  create_aggregate_device(
			AudioDeviceID input_device_id,
			AudioDeviceID output_device_id,
			uint32_t sample_rate,
			AudioDeviceID *created_device);


	::AudioUnit _auhal;
	AudioDeviceID* _device_ids;
	AudioBufferList* _input_audio_buffer_list;
	AudioBufferList* _output_audio_buffer_list;

	AudioDeviceID _active_device_id;
	AudioDeviceID _aggregate_device_id;
	AudioDeviceID _aggregate_plugin_id;

	int _state;

	uint32_t _samples_per_period;
	uint32_t _cur_samples_per_period;
	uint32_t _capture_channels;
	uint32_t _playback_channels;
	bool     _in_process;
	size_t   _n_devices;

	int (* _process_callback) (void*, const uint32_t, const uint64_t);
	void * _process_arg;

	void (* _error_callback) (void*);
	void  * _error_arg;

	void (* _hw_changed_callback) (void*);
	void  * _hw_changed_arg;

	void (* _xrun_callback) (void*);
	void  * _xrun_arg;

	void (* _buffer_size_callback) (void*);
	void  * _buffer_size_arg;

	void (* _sample_rate_callback) (void*);
	void  * _sample_rate_arg;


	// TODO proper device info struct
	std::map<size_t, std::string> _devices;
	std::map<size_t, std::string> _input_devices;
	std::map<size_t, std::string> _output_devices;
	std::map<size_t, std::string> _duplex_devices;
	uint32_t * _device_ins;
	uint32_t * _device_outs;
	std::vector<std::string> _input_names;
	std::vector<std::string> _output_names;

	pthread_mutex_t _discovery_lock;
};

} // namespace

#endif /* __libbackend_coreaudio_pcmio_h__ */