xref: /haiku/src/add-ons/media/media-add-ons/opensound/OpenSoundDevice.cpp (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
1 /*
2  * Copyright (c) 2002-2007, Jerome Duval (jerome.duval@free.fr)
3  * Copyright (c) 2007, François Revol (revol@free.fr)
4  * Distributed under the terms of the MIT License.
5  */
6 
7 #include "OpenSoundDevice.h"
8 #include "OpenSoundDeviceEngine.h"
9 #include "OpenSoundDeviceMixer.h"
10 #include "debug.h"
11 #include "driver_io.h"
12 #include <MediaDefs.h>
13 #include <Debug.h>
14 #include <errno.h>
15 #include <string.h>
16 
17 const int gSupportedFormats[] = {
18 	AFMT_SUPPORTED_PCM,
19 #ifdef ENABLE_NON_RAW_SUPPORT
20 	AFMT_MU_LAW,
21 	AFMT_A_LAW,
22 	AFMT_IMA_ADPCM,
23 	AFMT_MPEG,
24 	AFMT_AC3,
25 	AFMT_VORBIS,
26 	AFMT_SPDIF_RAW,
27 	AFMT_S24_PACKED,
28 #endif /*ENABLE_NON_RAW_SUPPORT*/
29 	0
30 };
31 
32 const char* gSupportedFormatsNames[] = {
33 	"raw", //AFMT_SUPPORTED_PCM,
34 	"µ-law", //AFMT_MU_LAW,
35 	"a-law", //AFMT_A_LAW,
36 	"IMA4 ADPCM", //AFMT_IMA_ADPCM,
37 	"MPEG layer 2", //AFMT_MPEG,
38 	"AC3", //AFMT_AC3,
39 	"Vorbis", //AFMT_VORBIS,
40 	"Raw S/PDIF", //AFMT_SPDIF_RAW,
41 	"Packed 24bit", //AFMT_S24_PACKED,*/
42 	0
43 };
44 
45 
46 
47 
48 float OpenSoundDevice::convert_oss_rate_to_media_rate(int rate)
49 {
50 	return (float)rate;
51 }
52 
53 
54 int OpenSoundDevice::convert_media_rate_to_oss_rate(float rate)
55 {
56 	return (int)rate;
57 }
58 
59 
60 uint32 OpenSoundDevice::convert_oss_format_to_media_format(int fmt)
61 {
62 	if (fmt & AFMT_FLOAT)
63 		return media_raw_audio_format::B_AUDIO_FLOAT;
64 	if (fmt & AFMT_S32_LE ||
65 		fmt & AFMT_S24_LE ||
66 		fmt & AFMT_S32_BE ||
67 		fmt & AFMT_S24_BE)
68 		return media_raw_audio_format::B_AUDIO_INT;
69 	if (fmt & AFMT_S16_LE ||
70 		fmt & AFMT_S16_BE) /* U16 unsupported */
71 		return media_raw_audio_format::B_AUDIO_SHORT;
72 	if (fmt & AFMT_S8)
73 		return media_raw_audio_format::B_AUDIO_CHAR;
74 	if (fmt & AFMT_U8)
75 		return media_raw_audio_format::B_AUDIO_UCHAR;
76 	return 0;
77 }
78 
79 
80 int OpenSoundDevice::convert_oss_format_to_endian(int fmt)
81 {
82 	if (fmt & AFMT_FLOAT)
83 		return B_MEDIA_HOST_ENDIAN;
84 	if (fmt & AFMT_S32_LE ||
85 		fmt & AFMT_S24_LE ||
86 		fmt & AFMT_S16_LE ||
87 		fmt & AFMT_U16_LE ||
88 		fmt & AFMT_S24_PACKED)
89 		return B_MEDIA_LITTLE_ENDIAN;
90 	if (fmt & AFMT_S32_BE ||
91 		fmt & AFMT_S24_BE ||
92 		fmt & AFMT_S16_BE ||
93 		fmt & AFMT_U16_BE)
94 		return B_MEDIA_BIG_ENDIAN;
95 	if (fmt & AFMT_S8 ||
96 		fmt & AFMT_U8)
97 		return B_MEDIA_HOST_ENDIAN;
98 	return B_MEDIA_HOST_ENDIAN;
99 }
100 
101 int16 OpenSoundDevice::convert_oss_format_to_valid_bits(int fmt)
102 {
103 	if (fmt & AFMT_S32_NE)
104 		return 32;
105 	if (fmt & AFMT_S24_NE)
106 		return 24;
107 	if (fmt & AFMT_S32_OE)
108 		return 32;
109 	if (fmt & AFMT_S24_OE)
110 		return 24;
111 	if (fmt & AFMT_S24_PACKED)
112 		return 24;
113 	if (fmt & AFMT_SPDIF_RAW)
114 		return 32;
115 	return 0;
116 }
117 
118 
119 int OpenSoundDevice::convert_media_format_to_oss_format(uint32 fmt)
120 {
121 	switch (fmt) {
122 		case media_raw_audio_format::B_AUDIO_FLOAT:
123 			return AFMT_FLOAT;
124 		case media_raw_audio_format::B_AUDIO_INT:
125 			return AFMT_S32_NE;
126 		case media_raw_audio_format::B_AUDIO_SHORT:
127 			return AFMT_S16_NE;
128 		case media_raw_audio_format::B_AUDIO_CHAR:
129 			return AFMT_S8;
130 		case media_raw_audio_format::B_AUDIO_UCHAR:
131 			return AFMT_U8;
132 		default:
133 			return 0;
134 	}
135 }
136 
137 
138 int OpenSoundDevice::select_oss_rate(const oss_audioinfo *info, int rate)
139 {
140 	if (info->caps & PCM_CAP_FREERATE) {
141 		// if not wildcard and matches, return the hint
142 		if (rate && rate >= info->min_rate && rate <= info->max_rate)
143 			return rate;
144 		// else use max available
145 		return info->max_rate;
146 	}
147 	uint32 max_rate = 0;
148 	for (uint32 i = 0; i < info->nrates; i++) {
149 		if ((int32)info->rates[i] < info->min_rate
150 			|| (int32)info->rates[i] > info->max_rate)
151 			continue;
152 		// if the hint matches
153 		if (rate && rate == (int32)info->rates[i])
154 			return rate;
155 		if (info->rates[i] > max_rate)
156 			max_rate = info->rates[i];
157 	}
158 	// highest rate
159 	return max_rate;
160 }
161 
162 
163 int OpenSoundDevice::select_oss_format(int fmt)
164 {
165 	//highest format, Native Endian first
166 	if (fmt & AFMT_FLOAT) {
167 		return AFMT_FLOAT;
168 	} else if (fmt & AFMT_S32_NE) {
169 		return AFMT_S32_NE;
170 	} else if (fmt & AFMT_S24_NE) {
171 		return AFMT_S24_NE;
172 	} else if (fmt & AFMT_S16_NE) {
173 		return AFMT_S16_NE;
174 	} else if (fmt & AFMT_S32_OE) {
175 		return AFMT_S32_OE;
176 	} else if (fmt & AFMT_S24_OE) {
177 		return AFMT_S24_OE;
178 	} else if (fmt & AFMT_S16_OE) {
179 		return AFMT_S16_OE;
180 	} else if (fmt & AFMT_S8) {
181 		return AFMT_S8;
182 	} else if (fmt & AFMT_U8) {
183 		return AFMT_U8;
184 	} else
185 		return 0;
186 }
187 
188 status_t OpenSoundDevice::get_media_format_description_for(int fmt, media_format_description *desc, int count)
189 {
190 	int i;
191 	for (i = 0; i < count; i++)
192 		memset(&desc[i], 0, sizeof(media_format_description));
193 	if (count < 1)
194 		return 0;
195 	if (fmt & AFMT_SUPPORTED_PCM) {
196 		desc[0].family = B_BEOS_FORMAT_FAMILY;
197 		desc[0].u.beos.format = 1;
198 		return 1;
199 	}
200 	switch (fmt) {
201 	case AFMT_MU_LAW:
202 		desc[0].family = B_MISC_FORMAT_FAMILY;
203 		desc[0].u.misc.file_format = '.snd';
204 		desc[0].u.misc.codec = 'ulaw';
205 		if (count < 2)
206 			return 1;
207 		desc[1].family = B_WAV_FORMAT_FAMILY;
208 		desc[1].u.wav.codec = 0x07;
209 		return 2;
210 		if (count < 3)
211 			return 2;
212 		desc[1].family = B_QUICKTIME_FORMAT_FAMILY;
213 		desc[1].u.quicktime.codec = 'ulaw';
214 		desc[1].u.quicktime.vendor = 0;
215 		return 3;
216 	case AFMT_A_LAW:
217 		desc[0].family = B_MISC_FORMAT_FAMILY;
218 		desc[0].u.misc.file_format = '.snd';
219 		desc[0].u.misc.codec = 'alaw';
220 		return 1;
221 		// wav/qt ?
222 	case AFMT_IMA_ADPCM:
223 		desc[0].family = B_BEOS_FORMAT_FAMILY;
224 		desc[0].u.beos.format = 'ima4';
225 		return 1;
226 	case AFMT_MPEG: /* layer 2 */
227 		desc[0].family = B_MPEG_FORMAT_FAMILY;
228 		desc[0].u.mpeg.id = 0x102;
229 		if (count < 2)
230 			return 1;
231 		desc[1].family = B_WAV_FORMAT_FAMILY;
232 		desc[1].u.wav.codec = 0x50;
233 		if (count < 3)
234 			return 2;
235 		desc[1].family = B_AVI_FORMAT_FAMILY;
236 		desc[1].u.avi.codec = 0x65610050;
237 		return 3;
238 	case AFMT_AC3:
239 		desc[0].family = B_WAV_FORMAT_FAMILY;
240 		desc[0].u.wav.codec = 0x2000;
241 		if (count < 2)
242 			return 1;
243 		desc[1].family = B_AVI_FORMAT_FAMILY;
244 		desc[1].u.avi.codec = 0x65612000;
245 		return 2;
246 	case AFMT_VORBIS:
247 		// nothing official
248 		desc[0].family = B_MISC_FORMAT_FAMILY;
249 		desc[0].u.misc.file_format = 'OSS4';
250 		desc[0].u.misc.codec = 'VORB';
251 		return 1;
252 	case AFMT_SPDIF_RAW:
253 		// nothing official
254 		desc[0].family = B_MISC_FORMAT_FAMILY;
255 		desc[0].u.misc.file_format = 'OSS4';
256 		desc[0].u.misc.codec = 'PDIF';
257 		return 1;
258 	case AFMT_S24_PACKED:
259 		// nothing official
260 		desc[0].family = B_MISC_FORMAT_FAMILY;
261 		desc[0].u.misc.file_format = 'OSS4';
262 		desc[0].u.misc.codec = 'S24P';
263 		return 1;
264 	default:
265 		return EINVAL;
266 	}
267 	return 0;
268 };
269 
270 
271 status_t OpenSoundDevice::register_media_formats()
272 {
273 	status_t err;
274 	int i, count;
275 	BMediaFormats formats;
276 	if (formats.InitCheck() < B_OK)
277 		return formats.InitCheck();
278 	media_format format;
279 	for (i = 0; gSupportedFormats[i]; i++) {
280 		media_format_description desc[10];
281 		err = count = get_media_format_description_for(gSupportedFormats[i], desc, 10);
282 		if (err < 1)
283 			continue;
284 		if (gSupportedFormats[i] & AFMT_SUPPORTED_PCM) {
285 			format.type = B_MEDIA_RAW_AUDIO;
286 			format.u.raw_audio = media_multi_audio_format::wildcard;
287 		} else {
288 			format.type = B_MEDIA_ENCODED_AUDIO;
289 			format.u.encoded_audio = media_encoded_audio_format::wildcard;
290 		}
291 		err = formats.MakeFormatFor(desc, count, &format);
292 		PRINT(("OpenSoundDevice::register_media_formats: MakeFormatFor: %s\n", strerror(err)));
293 	}
294 	return B_OK;
295 };
296 
297 
298 status_t OpenSoundDevice::get_media_format_for(int fmt, media_format &format)
299 {
300 	status_t err;
301 	BMediaFormats formats;
302 	if (formats.InitCheck() < B_OK)
303 		return formats.InitCheck();
304 	/* shortcut for raw */
305 	if (fmt & AFMT_SUPPORTED_PCM) {
306 		format = media_format();
307 		format.type = B_MEDIA_RAW_AUDIO;
308 		format.u.raw_audio = media_raw_audio_format::wildcard;
309 		return B_OK;
310 	}
311 	media_format_description desc;
312 	err = get_media_format_description_for(fmt, &desc);
313 	if (err < B_OK)
314 		return err;
315 	err = formats.GetFormatFor(desc, &format);
316 	return err;
317 };
318 
319 
320 OpenSoundDevice::~OpenSoundDevice()
321 {
322 	CALLED();
323 	OpenSoundDeviceEngine *engine;
324 	OpenSoundDeviceMixer *mixer;
325 	while ((engine = EngineAt(0))) {
326 		delete engine;
327 		fEngines.RemoveItems(0, 1);
328 	}
329 	while ((mixer = MixerAt(0))) {
330 		delete mixer;
331 		fMixers.RemoveItems(0, 1);
332 	}
333 }
334 
335 OpenSoundDevice::OpenSoundDevice(oss_card_info *cardinfo)
336 	: fLocker("OpenSoundDevice")
337 {
338 	CALLED();
339 	fInitCheckStatus = B_NO_INIT;
340 	memcpy(&fCardInfo, cardinfo, sizeof(oss_card_info));
341 	memset(&fFragments, 0, sizeof(fFragments));
342 #if 0
343 	strcpy(fDevice_name, name);
344 	strcpy(fDevice_path, path);
345 
346 	PRINT(("name : %s, path : %s\n", fDevice_name, fDevice_path));
347 
348 	if (InitDriver() != B_OK)
349 		return;
350 
351 	fInitCheckStatus = B_OK;
352 #endif
353 }
354 
355 
356 status_t OpenSoundDevice::InitCheck(void) const
357 {
358 	CALLED();
359 	return fInitCheckStatus;
360 }
361 
362 
363 status_t OpenSoundDevice::InitDriver()
364 {
365 
366 	CALLED();
367 	PRINT(("OpenSoundDevice::InitDriver: %" B_PRId32 " engines, %" B_PRId32
368 		" mixers\n", CountEngines(), CountMixers()));
369 
370 	if (CountMixers()) {
371 		;//...
372 	}
373 
374 	fInitCheckStatus = B_OK;
375 
376 	return B_OK;
377 }
378 
379 
380 status_t
381 OpenSoundDevice::AddEngine(oss_audioinfo *info)
382 {
383 	status_t err;
384 	/* discard shadow/hidden engines (!?) */
385 	CALLED();
386 /*
387 	if (info->caps & PCM_CAP_SHADOW)
388 		return B_OK;
389 	if (info->caps & PCM_CAP_HIDDEN)
390 		return B_OK;
391 */
392 	OpenSoundDeviceEngine *engine = new OpenSoundDeviceEngine(info);
393 	if (!engine)
394 		return ENOMEM;
395 	err = engine->InitCheck();
396 	if (err < B_OK) {
397 		delete engine;
398 		return err;
399 	}
400 	fEngines.AddItem(engine);
401 	return B_OK;
402 }
403 
404 
405 status_t
406 OpenSoundDevice::AddMixer(oss_mixerinfo *info)
407 {
408 	status_t err;
409 	CALLED();
410 	OpenSoundDeviceMixer *mixer = new OpenSoundDeviceMixer(info);
411 	if (!mixer)
412 		return ENOMEM;
413 	err = mixer->InitCheck();
414 	if (err < B_OK) {
415 		delete mixer;
416 		return err;
417 	}
418 	fMixers.AddItem(mixer);
419 	return B_OK;
420 }
421 
422 
423 int32
424 OpenSoundDevice::CountEngines()
425 {
426 	return fEngines.CountItems();
427 }
428 
429 
430 int32
431 OpenSoundDevice::CountMixers()
432 {
433 	return fMixers.CountItems();
434 }
435 
436 
437 OpenSoundDeviceEngine *
438 OpenSoundDevice::EngineAt(int32 i)
439 {
440 	return (OpenSoundDeviceEngine *)(fEngines.ItemAt(i));
441 }
442 
443 
444 OpenSoundDeviceMixer *
445 OpenSoundDevice::MixerAt(int32 i)
446 {
447 	return (OpenSoundDeviceMixer *)(fMixers.ItemAt(i));
448 }
449 
450 OpenSoundDeviceEngine *
451 OpenSoundDevice::NextFreeEngineAt(int32 i, bool rec)
452 {
453 	// find the first free engine in the rec or play chain
454 	OpenSoundDeviceEngine *engine = EngineAt(i);
455 	while (engine && engine->InUse()) {
456 		engine = rec ? (engine->NextRec()) : (engine->NextPlay());
457 	}
458 	return engine;
459 }
460 
461