vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / media / media-add-ons / opensound / OpenSoundDevice.cpp
blob427d3020fc102febd02d457c6622e86cef45160e
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 */
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>
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*/
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,*/
48 float OpenSoundDevice::convert_oss_rate_to_media_rate(int rate)
50 return (float)rate;
54 int OpenSoundDevice::convert_media_rate_to_oss_rate(float rate)
56 return (int)rate;
60 uint32 OpenSoundDevice::convert_oss_format_to_media_format(int fmt)
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;
80 int OpenSoundDevice::convert_oss_format_to_endian(int fmt)
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;
101 int16 OpenSoundDevice::convert_oss_format_to_valid_bits(int fmt)
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;
119 int OpenSoundDevice::convert_media_format_to_oss_format(uint32 fmt)
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;
138 int OpenSoundDevice::select_oss_rate(const oss_audioinfo *info, int rate)
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;
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];
158 // highest rate
159 return max_rate;
163 int OpenSoundDevice::select_oss_format(int fmt)
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;
188 status_t OpenSoundDevice::get_media_format_description_for(int fmt, media_format_description *desc, int count)
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;
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;
267 return 0;
271 status_t OpenSoundDevice::register_media_formats()
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;
291 err = formats.MakeFormatFor(desc, count, &format);
292 PRINT(("OpenSoundDevice::register_media_formats: MakeFormatFor: %s\n", strerror(err)));
294 return B_OK;
298 status_t OpenSoundDevice::get_media_format_for(int fmt, media_format &format)
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;
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;
320 OpenSoundDevice::~OpenSoundDevice()
322 CALLED();
323 OpenSoundDeviceEngine *engine;
324 OpenSoundDeviceMixer *mixer;
325 while ((engine = EngineAt(0))) {
326 delete engine;
327 fEngines.RemoveItems(0, 1);
329 while ((mixer = MixerAt(0))) {
330 delete mixer;
331 fMixers.RemoveItems(0, 1);
335 OpenSoundDevice::OpenSoundDevice(oss_card_info *cardinfo)
336 : fLocker("OpenSoundDevice")
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);
346 PRINT(("name : %s, path : %s\n", fDevice_name, fDevice_path));
348 if (InitDriver() != B_OK)
349 return;
351 fInitCheckStatus = B_OK;
352 #endif
356 status_t OpenSoundDevice::InitCheck(void) const
358 CALLED();
359 return fInitCheckStatus;
363 status_t OpenSoundDevice::InitDriver()
366 CALLED();
367 PRINT(("OpenSoundDevice::InitDriver: %" B_PRId32 " engines, %" B_PRId32
368 " mixers\n", CountEngines(), CountMixers()));
370 if (CountMixers()) {
371 ;//...
374 fInitCheckStatus = B_OK;
376 return B_OK;
380 status_t
381 OpenSoundDevice::AddEngine(oss_audioinfo *info)
383 status_t err;
384 /* discard shadow/hidden engines (!?) */
385 CALLED();
387 if (info->caps & PCM_CAP_SHADOW)
388 return B_OK;
389 if (info->caps & PCM_CAP_HIDDEN)
390 return B_OK;
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;
400 fEngines.AddItem(engine);
401 return B_OK;
405 status_t
406 OpenSoundDevice::AddMixer(oss_mixerinfo *info)
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;
418 fMixers.AddItem(mixer);
419 return B_OK;
423 int32
424 OpenSoundDevice::CountEngines()
426 return fEngines.CountItems();
430 int32
431 OpenSoundDevice::CountMixers()
433 return fMixers.CountItems();
437 OpenSoundDeviceEngine *
438 OpenSoundDevice::EngineAt(int32 i)
440 return (OpenSoundDeviceEngine *)(fEngines.ItemAt(i));
444 OpenSoundDeviceMixer *
445 OpenSoundDevice::MixerAt(int32 i)
447 return (OpenSoundDeviceMixer *)(fMixers.ItemAt(i));
450 OpenSoundDeviceEngine *
451 OpenSoundDevice::NextFreeEngineAt(int32 i, bool rec)
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());
458 return engine;