xref: /haiku/src/add-ons/media/media-add-ons/multi_audio/MultiAudioDevice.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
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::_InitDriver()
50 {
51 	int num_outputs, num_inputs, num_channels;
52 
53 	CALLED();
54 
55 	// open the device driver
56 
57 	fDevice = open(fPath, O_WRONLY);
58 	if (fDevice == -1) {
59 		fprintf(stderr, "Failed to open %s: %s\n", fPath, strerror(errno));
60 		return B_ERROR;
61 	}
62 
63 	// Get description
64 
65 	fDescription.info_size = sizeof(fDescription);
66 	fDescription.request_channel_count = MAX_CHANNELS;
67 	fDescription.channels = fChannelInfo;
68 	status_t status = get_description(fDevice, &fDescription);
69 	if (status != B_OK) {
70 		fprintf(stderr, "Failed on B_MULTI_GET_DESCRIPTION: %s\n",
71 			strerror(status));
72 		return status;
73 	}
74 
75 	PRINT(("Friendly name:\t%s\nVendor:\t\t%s\n",
76 		fDescription.friendly_name, fDescription.vendor_info));
77 	PRINT(("%ld outputs\t%ld inputs\n%ld out busses\t%ld in busses\n",
78 		fDescription.output_channel_count, fDescription.input_channel_count,
79 		fDescription.output_bus_channel_count,
80 		fDescription.input_bus_channel_count));
81 	PRINT(("\nChannels\n"
82 		"ID\tKind\tDesig\tConnectors\n"));
83 
84 	for (int32 i = 0; i < fDescription.output_channel_count
85 			+ fDescription.input_channel_count; i++) {
86 		PRINT(("%ld\t%d\t0x%lx\t0x%lx\n", fDescription.channels[i].channel_id,
87 			fDescription.channels[i].kind,
88 			fDescription.channels[i].designations,
89 			fDescription.channels[i].connectors));
90 	}
91 	PRINT(("\n"));
92 
93 	PRINT(("Output rates\t\t0x%lx\n", fDescription.output_rates));
94 	PRINT(("Input rates\t\t0x%lx\n", fDescription.input_rates));
95 	PRINT(("Max CVSR\t\t%.0f\n", fDescription.max_cvsr_rate));
96 	PRINT(("Min CVSR\t\t%.0f\n", fDescription.min_cvsr_rate));
97 	PRINT(("Output formats\t\t0x%lx\n", fDescription.output_formats));
98 	PRINT(("Input formats\t\t0x%lx\n", fDescription.input_formats));
99 	PRINT(("Lock sources\t\t0x%lx\n", fDescription.lock_sources));
100 	PRINT(("Timecode sources\t0x%lx\n", fDescription.timecode_sources));
101 	PRINT(("Interface flags\t\t0x%lx\n", fDescription.interface_flags));
102 	PRINT(("Control panel string:\t\t%s\n", fDescription.control_panel));
103 	PRINT(("\n"));
104 
105 	num_outputs = fDescription.output_channel_count;
106 	num_inputs = fDescription.input_channel_count;
107 	num_channels = num_outputs + num_inputs;
108 
109 	// Get and set enabled channels
110 
111 	multi_channel_enable enable;
112 	uint32 enableBits;
113 	enable.info_size = sizeof(enable);
114 	enable.enable_bits = (uchar*)&enableBits;
115 
116 	status = get_enabled_channels(fDevice, &enable);
117 	if (status != B_OK) {
118 		fprintf(stderr, "Failed on B_MULTI_GET_ENABLED_CHANNELS: %s\n",
119 			strerror(status));
120 		return status;
121 	}
122 
123 	enableBits = (1 << num_channels) - 1;
124 	enable.lock_source = B_MULTI_LOCK_INTERNAL;
125 
126 	status = set_enabled_channels(fDevice, &enable);
127 	if (status != B_OK) {
128 		fprintf(stderr, "Failed on B_MULTI_SET_ENABLED_CHANNELS 0x%x: %s\n",
129 			*enable.enable_bits, strerror(status));
130 		return status;
131 	}
132 
133 	// Set the sample rate
134 
135 	fFormatInfo.info_size = sizeof(multi_format_info);
136 	fFormatInfo.output.rate = select_sample_rate(fDescription.output_rates);
137 	fFormatInfo.output.cvsr = 0;
138 	fFormatInfo.output.format = select_format(fDescription.output_formats);
139 	fFormatInfo.input.rate = select_sample_rate(fDescription.input_rates);
140 	fFormatInfo.input.cvsr = fFormatInfo.output.cvsr;
141 	fFormatInfo.input.format = select_format(fDescription.input_formats);
142 
143 	status = set_global_format(fDevice, &fFormatInfo);
144 	if (status != B_OK) {
145 		fprintf(stderr, "Failed on B_MULTI_SET_GLOBAL_FORMAT: %s\n",
146 			strerror(status));
147 	}
148 
149 	status = get_global_format(fDevice, &fFormatInfo);
150 	if (status != B_OK) {
151 		fprintf(stderr, "Failed on B_MULTI_GET_GLOBAL_FORMAT: %s\n",
152 			strerror(status));
153 		return status;
154 	}
155 
156 	// Get the buffers
157 
158 	for (uint32 i = 0; i < MAX_BUFFERS; i++) {
159 		fPlayBuffers[i] = &fPlayBufferList[i * MAX_CHANNELS];
160 		fRecordBuffers[i] = &fRecordBufferList[i * MAX_CHANNELS];
161 	}
162 	fBufferList.info_size = sizeof(multi_buffer_list);
163 	fBufferList.request_playback_buffer_size = 0;
164 		// use the default...
165 	fBufferList.request_playback_buffers = MAX_BUFFERS;
166 	fBufferList.request_playback_channels = num_outputs;
167 	fBufferList.playback_buffers = (buffer_desc **) fPlayBuffers;
168 	fBufferList.request_record_buffer_size = 0;
169 		// use the default...
170 	fBufferList.request_record_buffers = MAX_BUFFERS;
171 	fBufferList.request_record_channels = num_inputs;
172 	fBufferList.record_buffers = /*(buffer_desc **)*/ fRecordBuffers;
173 
174 	status = get_buffers(fDevice, &fBufferList);
175 	if (status != B_OK) {
176 		fprintf(stderr, "Failed on B_MULTI_GET_BUFFERS: %s\n",
177 			strerror(status));
178 		return status;
179 	}
180 
181 	for (int32 i = 0; i < fBufferList.return_playback_buffers; i++) {
182 		for (int32 j = 0; j < fBufferList.return_playback_channels; j++) {
183 			PRINT(("fBufferList.playback_buffers[%ld][%ld].base: %p\n",
184 				i, j, fBufferList.playback_buffers[i][j].base));
185 			PRINT(("fBufferList.playback_buffers[%ld][%ld].stride: %li\n",
186 				i, j, fBufferList.playback_buffers[i][j].stride));
187 		}
188 	}
189 
190 	for (int32 i = 0; i < fBufferList.return_record_buffers; i++) {
191 		for (int32 j = 0; j < fBufferList.return_record_channels; j++) {
192 			PRINT(("fBufferList.record_buffers[%ld][%ld].base: %p\n",
193 				i, j, fBufferList.record_buffers[i][j].base));
194 			PRINT(("fBufferList.record_buffers[%ld][%ld].stride: %li\n",
195 				i, j, fBufferList.record_buffers[i][j].stride));
196 		}
197 	}
198 
199 	fMixControlInfo.info_size = sizeof(fMixControlInfo);
200 	fMixControlInfo.control_count = MAX_CONTROLS;
201 	fMixControlInfo.controls = fMixControl;
202 
203 	status = list_mix_controls(fDevice, &fMixControlInfo);
204 	if (status != B_OK) {
205 		fprintf(stderr, "Failed on DRIVER_LIST_MIX_CONTROLS: %s\n",
206 			strerror(status));
207 		return status;
208 	}
209 
210 	return B_OK;
211 }
212 
213 
214 status_t
215 MultiAudioDevice::BufferExchange(multi_buffer_info *info)
216 {
217 	return buffer_exchange(fDevice, info);
218 }
219 
220 
221 status_t
222 MultiAudioDevice::SetMix(multi_mix_value_info *info)
223 {
224 	return set_mix(fDevice, info);
225 }
226 
227 
228 status_t
229 MultiAudioDevice::GetMix(multi_mix_value_info *info)
230 {
231 	return get_mix(fDevice, info);
232 }
233