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
17const 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
32const 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
48float OpenSoundDevice::convert_oss_rate_to_media_rate(int rate)
49{
50	return (float)rate;
51}
52
53
54int OpenSoundDevice::convert_media_rate_to_oss_rate(float rate)
55{
56	return (int)rate;
57}
58
59
60uint32 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
80int 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
101int16 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
119int 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
138int 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
163int 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
188status_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		desc[i] = 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
271status_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
298status_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
320OpenSoundDevice::~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
335OpenSoundDevice::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
356status_t OpenSoundDevice::InitCheck(void) const
357{
358	CALLED();
359	return fInitCheckStatus;
360}
361
362
363status_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
380status_t
381OpenSoundDevice::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 =
393		new(std::nothrow) OpenSoundDeviceEngine(info);
394	if (!engine)
395		return ENOMEM;
396	err = engine->InitCheck();
397	if (err < B_OK) {
398		delete engine;
399		return err;
400	}
401	fEngines.AddItem(engine);
402	return B_OK;
403}
404
405
406status_t
407OpenSoundDevice::AddMixer(oss_mixerinfo *info)
408{
409	status_t err;
410	CALLED();
411	OpenSoundDeviceMixer *mixer =
412		new(std::nothrow) OpenSoundDeviceMixer(info);
413	if (!mixer)
414		return ENOMEM;
415	err = mixer->InitCheck();
416	if (err < B_OK) {
417		delete mixer;
418		return err;
419	}
420	fMixers.AddItem(mixer);
421	return B_OK;
422}
423
424
425int32
426OpenSoundDevice::CountEngines()
427{
428	return fEngines.CountItems();
429}
430
431
432int32
433OpenSoundDevice::CountMixers()
434{
435	return fMixers.CountItems();
436}
437
438
439OpenSoundDeviceEngine *
440OpenSoundDevice::EngineAt(int32 i)
441{
442	return (OpenSoundDeviceEngine *)(fEngines.ItemAt(i));
443}
444
445
446OpenSoundDeviceMixer *
447OpenSoundDevice::MixerAt(int32 i)
448{
449	return (OpenSoundDeviceMixer *)(fMixers.ItemAt(i));
450}
451
452OpenSoundDeviceEngine *
453OpenSoundDevice::NextFreeEngineAt(int32 i, bool rec)
454{
455	// find the first free engine in the rec or play chain
456	OpenSoundDeviceEngine *engine = EngineAt(i);
457	while (engine && engine->InUse()) {
458		engine = rec ? (engine->NextRec()) : (engine->NextPlay());
459	}
460	return engine;
461}
462
463