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: %ld engines, %ld mixers\n", 368 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