xref: /haiku/src/add-ons/media/media-add-ons/multi_audio/MultiAudioDevice.cpp (revision 922e7ba1f3228e6f28db69b0ded8f86eb32dea17)
1 /*
2  * Copyright (c) 2002-2007, Jerome Duval (jerome.duval@free.fr)
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "MultiAudioDevice.h"
8 
9 #include <errno.h>
10 #include <string.h>
11 
12 #include <MediaDefs.h>
13 
14 #include "debug.h"
15 #include "MultiAudioUtility.h"
16 
17 
18 using namespace MultiAudio;
19 
20 
21 MultiAudioDevice::MultiAudioDevice(const char* name, const char* path)
22 {
23 	CALLED();
24 
25 	strlcpy(fPath, path, B_PATH_NAME_LENGTH);
26 	PRINT(("name: %s, path: %s\n", name, fPath));
27 
28 	fInitStatus = _InitDriver();
29 }
30 
31 
32 MultiAudioDevice::~MultiAudioDevice()
33 {
34 	CALLED();
35 	if (fDevice >= 0)
36 		close(fDevice);
37 }
38 
39 
40 status_t
41 MultiAudioDevice::InitCheck() const
42 {
43 	CALLED();
44 	return fInitStatus;
45 }
46 
47 
48 status_t
49 MultiAudioDevice::BufferExchange(multi_buffer_info *info)
50 {
51 	return buffer_exchange(fDevice, info);
52 }
53 
54 
55 status_t
56 MultiAudioDevice::SetMix(multi_mix_value_info *info)
57 {
58 	return set_mix(fDevice, info);
59 }
60 
61 
62 status_t
63 MultiAudioDevice::GetMix(multi_mix_value_info *info)
64 {
65 	return get_mix(fDevice, info);
66 }
67 
68 
69 status_t
70 MultiAudioDevice::SetInputFrameRate(uint32 multiAudioRate)
71 {
72 	if ((fDescription.input_rates & multiAudioRate) == 0)
73 		return B_BAD_VALUE;
74 
75 	if (fFormatInfo.input.rate == multiAudioRate)
76 		return B_OK;
77 
78 	uint32 oldRate = fFormatInfo.input.rate;
79 	fFormatInfo.input.rate = multiAudioRate;
80 
81 	status_t status = set_global_format(fDevice, &fFormatInfo);
82 	if (status != B_OK) {
83 		fprintf(stderr, "Failed on B_MULTI_SET_GLOBAL_FORMAT: %s\n",
84 			strerror(status));
85 		fFormatInfo.input.rate = oldRate;
86 		return status;
87 	}
88 
89 	return _GetBuffers();
90 }
91 
92 
93 status_t
94 MultiAudioDevice::SetOutputFrameRate(uint32 multiAudioRate)
95 {
96 	if ((fDescription.output_rates & multiAudioRate) == 0)
97 		return B_BAD_VALUE;
98 
99 	if (fFormatInfo.output.rate == multiAudioRate)
100 		return B_OK;
101 
102 	uint32 oldRate = fFormatInfo.output.rate;
103 	fFormatInfo.output.rate = multiAudioRate;
104 
105 	status_t status = set_global_format(fDevice, &fFormatInfo);
106 	if (status != B_OK) {
107 		fprintf(stderr, "Failed on B_MULTI_SET_GLOBAL_FORMAT: %s\n",
108 			strerror(status));
109 		fFormatInfo.output.rate = oldRate;
110 		return status;
111 	}
112 
113 	return _GetBuffers();
114 }
115 
116 
117 status_t
118 MultiAudioDevice::_InitDriver()
119 {
120 	int num_outputs, num_inputs, num_channels;
121 
122 	CALLED();
123 
124 	// open the device driver
125 
126 	fDevice = open(fPath, O_WRONLY);
127 	if (fDevice == -1) {
128 		fprintf(stderr, "Failed to open %s: %s\n", fPath, strerror(errno));
129 		return B_ERROR;
130 	}
131 
132 	// Get description
133 
134 	fDescription.info_size = sizeof(fDescription);
135 	fDescription.request_channel_count = MAX_CHANNELS;
136 	fDescription.channels = fChannelInfo;
137 	status_t status = get_description(fDevice, &fDescription);
138 	if (status != B_OK) {
139 		fprintf(stderr, "Failed on B_MULTI_GET_DESCRIPTION: %s\n",
140 			strerror(status));
141 		return status;
142 	}
143 
144 	PRINT(("Friendly name:\t%s\nVendor:\t\t%s\n",
145 		fDescription.friendly_name, fDescription.vendor_info));
146 	PRINT(("%ld outputs\t%ld inputs\n%ld out busses\t%ld in busses\n",
147 		fDescription.output_channel_count, fDescription.input_channel_count,
148 		fDescription.output_bus_channel_count,
149 		fDescription.input_bus_channel_count));
150 	PRINT(("\nChannels\n"
151 		"ID\tKind\tDesig\tConnectors\n"));
152 
153 	for (int32 i = 0; i < fDescription.output_channel_count
154 			+ fDescription.input_channel_count; i++) {
155 		PRINT(("%ld\t%d\t0x%lx\t0x%lx\n", fDescription.channels[i].channel_id,
156 			fDescription.channels[i].kind,
157 			fDescription.channels[i].designations,
158 			fDescription.channels[i].connectors));
159 	}
160 	PRINT(("\n"));
161 
162 	PRINT(("Output rates\t\t0x%lx\n", fDescription.output_rates));
163 	PRINT(("Input rates\t\t0x%lx\n", fDescription.input_rates));
164 	PRINT(("Max CVSR\t\t%.0f\n", fDescription.max_cvsr_rate));
165 	PRINT(("Min CVSR\t\t%.0f\n", fDescription.min_cvsr_rate));
166 	PRINT(("Output formats\t\t0x%lx\n", fDescription.output_formats));
167 	PRINT(("Input formats\t\t0x%lx\n", fDescription.input_formats));
168 	PRINT(("Lock sources\t\t0x%lx\n", fDescription.lock_sources));
169 	PRINT(("Timecode sources\t0x%lx\n", fDescription.timecode_sources));
170 	PRINT(("Interface flags\t\t0x%lx\n", fDescription.interface_flags));
171 	PRINT(("Control panel string:\t\t%s\n", fDescription.control_panel));
172 	PRINT(("\n"));
173 
174 	num_outputs = fDescription.output_channel_count;
175 	num_inputs = fDescription.input_channel_count;
176 	num_channels = num_outputs + num_inputs;
177 
178 	// Get and set enabled channels
179 
180 	multi_channel_enable enable;
181 	uint32 enableBits;
182 	enable.info_size = sizeof(enable);
183 	enable.enable_bits = (uchar*)&enableBits;
184 
185 	status = get_enabled_channels(fDevice, &enable);
186 	if (status != B_OK) {
187 		fprintf(stderr, "Failed on B_MULTI_GET_ENABLED_CHANNELS: %s\n",
188 			strerror(status));
189 		return status;
190 	}
191 
192 	enableBits = (1 << num_channels) - 1;
193 	enable.lock_source = B_MULTI_LOCK_INTERNAL;
194 
195 	status = set_enabled_channels(fDevice, &enable);
196 	if (status != B_OK) {
197 		fprintf(stderr, "Failed on B_MULTI_SET_ENABLED_CHANNELS 0x%x: %s\n",
198 			*enable.enable_bits, strerror(status));
199 		return status;
200 	}
201 
202 	// Set the sample rate
203 
204 	fFormatInfo.info_size = sizeof(multi_format_info);
205 	fFormatInfo.output.rate = select_sample_rate(fDescription.output_rates);
206 	fFormatInfo.output.cvsr = 0;
207 	fFormatInfo.output.format = select_format(fDescription.output_formats);
208 	fFormatInfo.input.rate = select_sample_rate(fDescription.input_rates);
209 	fFormatInfo.input.cvsr = fFormatInfo.output.cvsr;
210 	fFormatInfo.input.format = select_format(fDescription.input_formats);
211 
212 	status = set_global_format(fDevice, &fFormatInfo);
213 	if (status != B_OK) {
214 		fprintf(stderr, "Failed on B_MULTI_SET_GLOBAL_FORMAT: %s\n",
215 			strerror(status));
216 	}
217 
218 	status = get_global_format(fDevice, &fFormatInfo);
219 	if (status != B_OK) {
220 		fprintf(stderr, "Failed on B_MULTI_GET_GLOBAL_FORMAT: %s\n",
221 			strerror(status));
222 		return status;
223 	}
224 
225 	// Get the buffers
226 	status = _GetBuffers();
227 	if (status != B_OK)
228 		return status;
229 
230 
231 	fMixControlInfo.info_size = sizeof(fMixControlInfo);
232 	fMixControlInfo.control_count = MAX_CONTROLS;
233 	fMixControlInfo.controls = fMixControl;
234 
235 	status = list_mix_controls(fDevice, &fMixControlInfo);
236 	if (status != B_OK) {
237 		fprintf(stderr, "Failed on DRIVER_LIST_MIX_CONTROLS: %s\n",
238 			strerror(status));
239 		return status;
240 	}
241 
242 	return B_OK;
243 }
244 
245 
246 status_t
247 MultiAudioDevice::_GetBuffers()
248 {
249 	for (uint32 i = 0; i < MAX_BUFFERS; i++) {
250 		fPlayBuffers[i] = &fPlayBufferList[i * MAX_CHANNELS];
251 		fRecordBuffers[i] = &fRecordBufferList[i * MAX_CHANNELS];
252 	}
253 	fBufferList.info_size = sizeof(multi_buffer_list);
254 	fBufferList.request_playback_buffer_size = 0;
255 		// use the default...
256 	fBufferList.request_playback_buffers = MAX_BUFFERS;
257 	fBufferList.request_playback_channels = fDescription.output_channel_count;
258 	fBufferList.playback_buffers = (buffer_desc **) fPlayBuffers;
259 	fBufferList.request_record_buffer_size = 0;
260 		// use the default...
261 	fBufferList.request_record_buffers = MAX_BUFFERS;
262 	fBufferList.request_record_channels = fDescription.input_channel_count;
263 	fBufferList.record_buffers = /*(buffer_desc **)*/ fRecordBuffers;
264 
265 	status_t status = get_buffers(fDevice, &fBufferList);
266 	if (status != B_OK) {
267 		fprintf(stderr, "Failed on B_MULTI_GET_BUFFERS: %s\n",
268 			strerror(status));
269 		return status;
270 	}
271 
272 	for (int32 i = 0; i < fBufferList.return_playback_buffers; i++) {
273 		for (int32 j = 0; j < fBufferList.return_playback_channels; j++) {
274 			PRINT(("fBufferList.playback_buffers[%ld][%ld].base: %p\n",
275 				i, j, fBufferList.playback_buffers[i][j].base));
276 			PRINT(("fBufferList.playback_buffers[%ld][%ld].stride: %li\n",
277 				i, j, fBufferList.playback_buffers[i][j].stride));
278 		}
279 	}
280 
281 	for (int32 i = 0; i < fBufferList.return_record_buffers; i++) {
282 		for (int32 j = 0; j < fBufferList.return_record_channels; j++) {
283 			PRINT(("fBufferList.record_buffers[%ld][%ld].base: %p\n",
284 				i, j, fBufferList.record_buffers[i][j].base));
285 			PRINT(("fBufferList.record_buffers[%ld][%ld].stride: %li\n",
286 				i, j, fBufferList.record_buffers[i][j].stride));
287 		}
288 	}
289 
290 	return B_OK;
291 }
292