1 /* 2 * OpenSound media addon for BeOS and Haiku 3 * 4 * Copyright (c) 2007, François Revol (revol@free.fr) 5 * Distributed under the terms of the MIT License. 6 */ 7 8 #include "OpenSoundDeviceEngine.h" 9 #include "debug.h" 10 #include "driver_io.h" 11 #include <MediaDefs.h> 12 #include <Debug.h> 13 #include <errno.h> 14 #include <string.h> 15 16 OpenSoundDeviceEngine::~OpenSoundDeviceEngine() 17 { 18 CALLED(); 19 if (fFD != 0) { 20 close(fFD); 21 } 22 } 23 24 OpenSoundDeviceEngine::OpenSoundDeviceEngine(oss_audioinfo *info) 25 : fNextPlay(NULL) 26 , fNextRec(NULL) 27 , fOpenMode(0) 28 , fFD(-1) 29 , fMediaFormat() 30 , fPlayedFramesCount(0LL) 31 , fPlayedRealTime(0LL) 32 { 33 CALLED(); 34 fInitCheckStatus = B_NO_INIT; 35 memcpy(&fAudioInfo, info, sizeof(oss_audioinfo)); 36 37 // XXX:REMOVEME 38 // set default format 39 /* 40 SetFormat(OpenSoundDevice::select_oss_format(info->oformats)); 41 SetChannels(info->max_channels); 42 SetSpeed(info->max_rate); 43 */ 44 fInitCheckStatus = B_OK; 45 } 46 47 48 status_t OpenSoundDeviceEngine::InitCheck(void) const 49 { 50 CALLED(); 51 return fInitCheckStatus; 52 } 53 54 55 status_t OpenSoundDeviceEngine::Open(int mode) 56 { 57 int omode, v; 58 CALLED(); 59 60 switch (mode) { 61 case OPEN_READ: 62 if (!(Caps() & DSP_CAP_INPUT)) 63 return EINVAL; 64 omode = O_RDONLY; 65 break; 66 case OPEN_WRITE: 67 if (!(Caps() & DSP_CAP_OUTPUT)) 68 return EINVAL; 69 omode = O_WRONLY; 70 break; 71 case OPEN_READWRITE: 72 if (!(Caps() & DSP_CAP_OUTPUT) || !(Caps() & DSP_CAP_INPUT)) 73 return EINVAL; 74 omode = O_RDWR; 75 break; 76 default: 77 return EINVAL; 78 } 79 // O_EXCL = bypass soft mixer = direct access 80 omode |= O_EXCL; 81 82 Close(); 83 fOpenMode = mode; 84 fFD = open(fAudioInfo.devnode, omode); 85 if (fFD < 0) { 86 fInitCheckStatus = errno; 87 return EIO; 88 } 89 // disable format convertions 90 v = 0; 91 if (ioctl(fFD, SNDCTL_DSP_COOKEDMODE, &v, sizeof(int)) < 0) { 92 fInitCheckStatus = errno; 93 Close(); 94 return EIO; 95 } 96 #if 0 97 // set fragments 98 v = 0x7fff0000 | 0x000b; // unlimited * 2048 99 if (ioctl(fFD, SNDCTL_DSP_SETFRAGMENT, &v, sizeof(int)) < 0) { 100 fInitCheckStatus = errno; 101 Close(); 102 return EIO; 103 } 104 #endif 105 106 #if 0 107 // set latency policy = fragment size 108 // XXX: BParameter? 109 v = 0; 110 if (ioctl(fFD, SNDCTL_DSP_POLICY, &v, sizeof(int)) < 0) { 111 fInitCheckStatus = errno; 112 Close(); 113 return EIO; 114 } 115 #endif 116 117 fPlayedFramesCount = 0LL; 118 fPlayedRealTime = system_time(); 119 return B_OK; 120 } 121 122 123 status_t OpenSoundDeviceEngine::Close(void) 124 { 125 CALLED(); 126 if (fFD > -1) 127 close(fFD); 128 fFD = -1; 129 fOpenMode = 0; 130 fMediaFormat = media_format(); 131 fPlayedFramesCount = 0LL; 132 fPlayedRealTime = 0LL; 133 return B_OK; 134 } 135 136 137 ssize_t OpenSoundDeviceEngine::Read(void *buffer, size_t size) 138 { 139 ssize_t done; 140 CALLED(); 141 done = read(fFD, buffer, size); 142 if (done < 0) 143 return errno; 144 return done; 145 } 146 147 148 ssize_t OpenSoundDeviceEngine::Write(const void *buffer, size_t size) 149 { 150 ssize_t done; 151 int v; 152 CALLED(); 153 ASSERT(size > 0); 154 done = write(fFD, buffer, size); 155 if (done < 0) 156 return errno; 157 switch (fMediaFormat.type) { 158 case B_MEDIA_RAW_AUDIO: 159 fPlayedFramesCount += done / (fMediaFormat.u.raw_audio.channel_count 160 * (fMediaFormat.AudioFormat() & media_raw_audio_format::B_AUDIO_SIZE_MASK)); 161 /* fPlayedRealTime = system_time(); 162 v = 0; 163 if (ioctl(fFD, SNDCTL_DSP_GETODELAY, &v, sizeof(int)) > -1) { 164 bigtime_t delay = (bigtime_t)v * 1000000LL 165 / (fMediaFormat.u.raw_audio.channel_count * fMediaFormat.u.raw_audio.frame_rate 166 * (fMediaFormat.AudioFormat() & media_raw_audio_format::B_AUDIO_SIZE_MASK)); 167 fPlayedRealTime += delay; 168 PRINT(("********************************* v = %d, delay %Ld\n", v, delay)); 169 }*/ 170 // PRINT(("OpenSoundDeviceEngine::%s: wrote %d, played %Ld frames"/*", realtime %Ld"*/"\n", __FUNCTION__, done, fPlayedFramesCount/*, fPlayedRealTime*/)); 171 break; 172 case B_MEDIA_ENCODED_AUDIO: 173 //XXX: WRITEME! -- bitrate ? 174 break; 175 default: 176 return EINVAL; 177 } 178 return done; 179 } 180 181 182 status_t OpenSoundDeviceEngine::UpdateInfo(void) 183 { 184 status_t err; 185 CALLED(); 186 if (fFD < 0) 187 return ENODEV; 188 189 if (ioctl(fFD, SNDCTL_ENGINEINFO, &fAudioInfo, sizeof(oss_audioinfo)) < 0) { 190 return errno; 191 } 192 return B_OK; 193 } 194 195 196 197 198 int OpenSoundDeviceEngine::GetChannels(void) 199 { 200 int chans = -1; 201 CALLED(); 202 if (ioctl(fFD, SNDCTL_DSP_CHANNELS, &chans, sizeof(int)) < 0) { 203 PRINT(("OpenSoundDeviceEngine::%s: %s: %s\n", 204 __FUNCTION__, "SNDCTL_DSP_CHANNELS", strerror(errno))); 205 return -1; 206 } 207 return chans; 208 } 209 210 status_t OpenSoundDeviceEngine::SetChannels(int chans) 211 { 212 CALLED(); 213 if (ioctl(fFD, SNDCTL_DSP_CHANNELS, &chans, sizeof(int)) < 0) { 214 PRINT(("OpenSoundDeviceEngine::%s: %s: %s\n", 215 __FUNCTION__, "SNDCTL_DSP_CHANNELS", strerror(errno))); 216 return EIO; 217 } 218 PRINT(("OpenSoundDeviceEngine::%s: %d\n", __FUNCTION__, chans)); 219 return B_OK; 220 } 221 222 //XXX: either GetFormat*s*() or cache SetFormat()! 223 int OpenSoundDeviceEngine::GetFormat(void) 224 { 225 int fmt = -1; 226 CALLED(); 227 if (ioctl(fFD, SNDCTL_DSP_GETFMTS, &fmt, sizeof(int)) < 0) { 228 PRINT(("OpenSoundDeviceEngine::%s: %s: %s\n", 229 __FUNCTION__, "SNDCTL_DSP_GETFMTS", strerror(errno))); 230 return -1; 231 } 232 return fmt; 233 } 234 235 status_t OpenSoundDeviceEngine::SetFormat(int fmt) 236 { 237 CALLED(); 238 if (ioctl(fFD, SNDCTL_DSP_SETFMT, &fmt, sizeof(int)) < 0) { 239 PRINT(("OpenSoundDeviceEngine::%s: %s: %s\n", 240 __FUNCTION__, "SNDCTL_DSP_SETFMT", strerror(errno))); 241 return EIO; 242 } 243 PRINT(("OpenSoundDeviceEngine::%s: 0x%08x\n", __FUNCTION__, fmt)); 244 return B_OK; 245 } 246 247 int OpenSoundDeviceEngine::GetSpeed(void) 248 { 249 int speed = -1; 250 CALLED(); 251 if (ioctl(fFD, SNDCTL_DSP_SPEED, &speed, sizeof(int)) < 0) { 252 PRINT(("OpenSoundDeviceEngine::%s: %s: %s\n", 253 __FUNCTION__, "SNDCTL_DSP_SPEED", strerror(errno))); 254 return -1; 255 } 256 return speed; 257 } 258 259 status_t OpenSoundDeviceEngine::SetSpeed(int speed) 260 { 261 CALLED(); 262 if (ioctl(fFD, SNDCTL_DSP_SPEED, &speed, sizeof(int)) < 0) { 263 PRINT(("OpenSoundDeviceEngine::%s: %s: %s\n", 264 __FUNCTION__, "SNDCTL_DSP_SPEED", strerror(errno))); 265 return EIO; 266 } 267 PRINT(("OpenSoundDeviceEngine::%s: %d\n", __FUNCTION__, speed)); 268 return B_OK; 269 } 270 271 272 size_t OpenSoundDeviceEngine::GetISpace(audio_buf_info *info) 273 { 274 audio_buf_info abinfo; 275 CALLED(); 276 if (!info) 277 info = &abinfo; 278 memset(info, 0, sizeof(audio_buf_info)); 279 if (!(fOpenMode & OPEN_READ)) 280 return 0; 281 if (ioctl(fFD, SNDCTL_DSP_GETISPACE, info, sizeof(audio_buf_info)) < 0) { 282 PRINT(("OpenSoundDeviceEngine::%s: %s: %s\n", 283 __FUNCTION__, "SNDCTL_DSP_GETISPACE", strerror(errno))); 284 return EIO; 285 } 286 //PRINT(("OpenSoundDeviceEngine::%s: ISPACE: { bytes=%d, fragments=%d, fragsize=%d, fragstotal=%d }\n", __FUNCTION__, info->bytes, info->fragments, info->fragsize, info->fragstotal)); 287 return info->bytes; 288 } 289 290 291 size_t OpenSoundDeviceEngine::GetOSpace(audio_buf_info *info) 292 { 293 audio_buf_info abinfo; 294 //CALLED(); 295 if (!info) 296 info = &abinfo; 297 memset(info, 0, sizeof(audio_buf_info)); 298 if (!(fOpenMode & OPEN_WRITE)) 299 return 0; 300 if (ioctl(fFD, SNDCTL_DSP_GETOSPACE, info, sizeof(audio_buf_info)) < 0) { 301 PRINT(("OpenSoundDeviceEngine::%s: %s: %s\n", 302 __FUNCTION__, "SNDCTL_DSP_GETOSPACE", strerror(errno))); 303 return EIO; 304 } 305 //PRINT(("OpenSoundDeviceEngine::%s: OSPACE: { bytes=%d, fragments=%d, fragsize=%d, fragstotal=%d }\n", __FUNCTION__, info->bytes, info->fragments, info->fragsize, info->fragstotal)); 306 return info->bytes; 307 } 308 309 310 int OpenSoundDeviceEngine::GetODelay(void) 311 { 312 //CALLED(); 313 int v = 1; 314 if (ioctl(fFD, SNDCTL_DSP_GETODELAY, &v, sizeof(int)) < 0) { 315 return 0; 316 } 317 return v; 318 } 319 320 321 status_t OpenSoundDeviceEngine::StartRecording(void) 322 { 323 CALLED(); 324 oss_syncgroup group; 325 group.id = 0; 326 group.mode = PCM_ENABLE_INPUT; 327 if (ioctl(fFD, SNDCTL_DSP_SYNCGROUP, &group, sizeof(group)) < 0) { 328 PRINT(("OpenSoundDeviceEngine::%s: %s: %s\n", 329 __FUNCTION__, "SNDCTL_DSP_SYNCGROUP", strerror(errno))); 330 return EIO; 331 } 332 if (ioctl(fFD, SNDCTL_DSP_SYNCSTART, &group.id, sizeof(group.id)) < 0) { 333 PRINT(("OpenSoundDeviceEngine::%s: %s: %s\n", 334 __FUNCTION__, "SNDCTL_DSP_SYNCSTART", strerror(errno))); 335 return EIO; 336 } 337 return B_OK; 338 } 339 340 341 int64 OpenSoundDeviceEngine::PlayedFramesCount(void) 342 { 343 return fPlayedFramesCount;//XXX 344 return fPlayedFramesCount - (GetODelay() / (fMediaFormat.u.raw_audio.channel_count 345 * (fMediaFormat.AudioFormat() & media_raw_audio_format::B_AUDIO_SIZE_MASK))); 346 return fPlayedFramesCount - (GetODelay() / (/*fMediaFormat.u.raw_audio.channel_count 347 * */(fMediaFormat.AudioFormat() & media_raw_audio_format::B_AUDIO_SIZE_MASK))); 348 //return fPlayedFramesCount; 349 } 350 351 352 bigtime_t OpenSoundDeviceEngine::PlayedRealTime(void) 353 { 354 //CALLED(); 355 bigtime_t playedRealTime = system_time(); 356 return playedRealTime;//XXX 357 int v = 1; 358 if (ioctl(fFD, SNDCTL_DSP_GETODELAY, &v, sizeof(int)) < 0) { 359 return playedRealTime; 360 } 361 bigtime_t delay = (bigtime_t)(v * 1000000LL 362 / (fMediaFormat.u.raw_audio.channel_count * fMediaFormat.u.raw_audio.frame_rate 363 * (fMediaFormat.AudioFormat() & media_raw_audio_format::B_AUDIO_SIZE_MASK))); 364 playedRealTime += delay; 365 //PRINT(("********************************* v = %d, delay %Ld\n", v, delay)); 366 // playedRealTime-=41000; 367 return playedRealTime; 368 } 369 370 371 status_t OpenSoundDeviceEngine::WildcardFormatFor(int fmt, media_format &format, bool rec) 372 { 373 status_t err; 374 CALLED(); 375 fmt &= rec ? Info()->iformats : Info()->oformats; 376 if (fmt == 0) 377 return B_MEDIA_BAD_FORMAT; 378 err = OpenSoundDevice::get_media_format_for(fmt, format); 379 if (err < B_OK) 380 return err; 381 char buf[1024]; 382 string_for_format(format, buf, 1024); 383 if (format.type == B_MEDIA_RAW_AUDIO) { 384 format.u.raw_audio = media_multi_audio_format::wildcard; 385 format.u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN; 386 // single rate supported 387 if (Info()->min_rate == Info()->max_rate) 388 format.u.raw_audio.frame_rate = OpenSoundDevice::convert_oss_rate_to_media_rate(Info()->max_rate); // measured in Hertz 389 } else if (format.type == B_MEDIA_ENCODED_AUDIO) { 390 format.u.encoded_audio.output = media_multi_audio_format::wildcard; 391 //format.u.encoded_audio.output.byte_order = B_MEDIA_HOST_ENDIAN; 392 // single rate supported 393 //if (Info()->min_rate == Info()->max_rate) 394 // format.u.encoded_audio.output.frame_rate = OpenSoundDevice::convert_oss_rate_to_media_rate(Info()->max_rate); // measured in Hertz 395 } else 396 return EINVAL; 397 PRINT(("%s: %s\n", __FUNCTION__, buf)); 398 return B_OK; 399 } 400 401 402 status_t OpenSoundDeviceEngine::PreferredFormatFor(int fmt, media_format &format, bool rec) 403 { 404 status_t err; 405 CALLED(); 406 fmt &= rec ? Info()->iformats : Info()->oformats; 407 if (fmt == 0) 408 return B_MEDIA_BAD_FORMAT; 409 err = WildcardFormatFor(fmt, format); 410 if (err < B_OK) 411 return err; 412 if (format.type == B_MEDIA_RAW_AUDIO) { 413 media_multi_audio_format &raw = format.u.raw_audio; 414 //format.u.raw_audio.channel_count = Info()->max_channels; 415 raw.byte_order = B_MEDIA_HOST_ENDIAN; 416 raw.frame_rate = OpenSoundDevice::convert_oss_rate_to_media_rate(Info()->max_rate); // measured in Hertz 417 raw.buffer_size = DEFAULT_BUFFER_SIZE; 418 /*if (rec) 419 raw.buffer_size = 2048;*/ 420 /* 421 format.u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN; 422 format.u.raw_audio.frame_rate = OpenSoundDevice::convert_oss_rate_to_media_rate(Info()->max_rate); // measured in Hertz 423 format.u.raw_audio.buffer_size = DEFAULT_BUFFER_SIZE; 424 */ 425 } else if (format.type == B_MEDIA_ENCODED_AUDIO) { 426 media_raw_audio_format &raw = format.u.encoded_audio.output; 427 //format.u.encoded_audio.output.channel_count = Info()->max_channels; 428 raw.byte_order = B_MEDIA_HOST_ENDIAN; 429 // single rate supported 430 if (Info()->min_rate == Info()->max_rate) 431 raw.frame_rate = OpenSoundDevice::convert_oss_rate_to_media_rate(Info()->max_rate); // measured in Hertz 432 raw.buffer_size = DEFAULT_BUFFER_SIZE; 433 } else 434 return EINVAL; 435 char buf[1024]; 436 string_for_format(format, buf, 1024); 437 PRINT(("%s: %s\n", __FUNCTION__, buf)); 438 return B_OK; 439 } 440 441 442 status_t OpenSoundDeviceEngine::AcceptFormatFor(int fmt, media_format &format, bool rec) 443 { 444 status_t err; 445 int afmt = 0; 446 CALLED(); 447 fmt &= rec ? Info()->iformats : Info()->oformats; 448 if (fmt == 0) 449 return B_MEDIA_BAD_FORMAT; 450 media_format wc; 451 err = WildcardFormatFor(fmt, wc); 452 if (err < B_OK) 453 return err; 454 455 err = Open(rec ? OPEN_READ : OPEN_WRITE); 456 if (err < B_OK) 457 return err; 458 459 if (format.type == B_MEDIA_RAW_AUDIO) { 460 media_multi_audio_format &raw = format.u.raw_audio; 461 462 // channel count 463 raw.channel_count = MAX((unsigned)(Info()->min_channels), MIN((unsigned)(Info()->max_channels), raw.channel_count)); 464 err = SetChannels(raw.channel_count); 465 if (err < B_OK) { 466 Close(); 467 return err; 468 } 469 470 PRINT(("%s:step1 fmt=0x%08x, raw.format=0x%08lx\n", __FUNCTION__, fmt, raw.format)); 471 // if specified, try it 472 if (raw.format) 473 afmt = OpenSoundDevice::convert_media_format_to_oss_format(raw.format); 474 afmt &= fmt; 475 PRINT(("%s:step2 afmt=0x%08x\n", __FUNCTION__, afmt)); 476 // select the best as default 477 if (afmt == 0) { 478 afmt = OpenSoundDevice::select_oss_format(fmt); 479 raw.format = OpenSoundDevice::convert_oss_format_to_media_format(afmt); 480 //Close(); 481 //return B_MEDIA_BAD_FORMAT; 482 } 483 PRINT(("%s:step3 afmt=0x%08x\n", __FUNCTION__, afmt)); 484 // convert back 485 raw.format = OpenSoundDevice::convert_oss_format_to_media_format(afmt); 486 PRINT(("%s:step4 afmt=0x%08x, raw.format=0x%08lx\n", __FUNCTION__, afmt, raw.format)); 487 raw.valid_bits = OpenSoundDevice::convert_oss_format_to_valid_bits(afmt); 488 489 err = SetFormat(afmt); 490 if (err < B_OK) { 491 Close(); 492 return err; 493 } 494 495 // endianness 496 raw.byte_order = OpenSoundDevice::convert_oss_format_to_endian(afmt); 497 498 // sample rate 499 raw.frame_rate = OpenSoundDevice::select_oss_rate(Info(), raw.frame_rate); // measured in Hertz 500 //raw.frame_rate = OpenSoundDevice::convert_oss_rate_to_media_rate(Info()->max_rate); // measured in Hertz 501 err = SetSpeed(OpenSoundDevice::convert_media_rate_to_oss_rate(raw.frame_rate)); 502 if (err < B_OK) { 503 Close(); 504 return err; 505 } 506 507 508 509 #if 0 510 raw.buffer_size = DEFAULT_BUFFER_SIZE 511 * (raw.format & media_raw_audio_format::B_AUDIO_SIZE_MASK) 512 * raw.channel_count; 513 #endif 514 audio_buf_info abinfo; 515 if (ioctl(fFD, rec?SNDCTL_DSP_GETISPACE:SNDCTL_DSP_GETOSPACE, &abinfo, sizeof(abinfo)) < 0) { 516 PRINT(("OpenSoundDeviceEngine::%s: %s: %s\n", 517 __FUNCTION__, "SNDCTL_DSP_GET?SPACE", strerror(errno))); 518 return -1; 519 } 520 PRINT(("OSS: %cSPACE: { bytes=%d, fragments=%d, fragsize=%d, fragstotal=%d }\n", rec?'I':'O', abinfo.bytes, abinfo.fragments, abinfo.fragsize, abinfo.fragstotal)); 521 // cache the first one in the Device 522 // so StartThread() knows the number of frags 523 //if (!fFragments.fragstotal) 524 // memcpy(&fFragments, &abinfo, sizeof(abinfo)); 525 526 // make sure buffer size is less than the driver's own buffer ( /2 to keep some margin ) 527 // if (/*rec && raw.buffer_size &&*/ raw.buffer_size >= abinfo.fragsize * abinfo.fragstotal / 2) 528 // return B_MEDIA_BAD_FORMAT; 529 // if (!raw.buffer_size) 530 raw.buffer_size = abinfo.fragsize;// * abinfo.fragstotal / 4;//XXX 531 /* * (raw.format & media_raw_audio_format::B_AUDIO_SIZE_MASK) 532 * raw.channel_count;*/ 533 } else if (format.type == B_MEDIA_ENCODED_AUDIO) { 534 media_raw_audio_format &raw = format.u.encoded_audio.output; 535 // XXX: do we really have to do this ? 536 raw.channel_count = MAX((unsigned)(Info()->min_channels), MIN((unsigned)(Info()->max_channels), raw.channel_count)); 537 raw.byte_order = B_MEDIA_HOST_ENDIAN; 538 raw.frame_rate = OpenSoundDevice::select_oss_rate(Info(), raw.frame_rate); // measured in Hertz 539 //raw.frame_rate = OpenSoundDevice::convert_oss_rate_to_media_rate(Info()->max_rate); // measured in Hertz 540 raw.buffer_size = DEFAULT_BUFFER_SIZE; 541 542 } else { 543 Close(); 544 return EINVAL; 545 } 546 // cache it 547 fMediaFormat = format; 548 char buf[1024]; 549 string_for_format(format, buf, 1024); 550 PRINT(("%s: %s\n", __FUNCTION__, buf)); 551 return B_OK; 552 } 553 554 555 status_t OpenSoundDeviceEngine::SpecializeFormatFor(int fmt, media_format &format, bool rec) 556 { 557 status_t err; 558 int afmt = 0; 559 CALLED(); 560 fmt &= rec ? Info()->iformats : Info()->oformats; 561 if (fmt == 0) 562 return B_MEDIA_BAD_FORMAT; 563 media_format wc; 564 err = WildcardFormatFor(fmt, wc); 565 if (err < B_OK) 566 return err; 567 568 err = Open(rec ? OPEN_READ : OPEN_WRITE); 569 if (err < B_OK) 570 return err; 571 572 if (format.type == B_MEDIA_RAW_AUDIO) { 573 media_multi_audio_format &raw = format.u.raw_audio; 574 575 PRINT(("%s:step1 fmt=0x%08x, raw.format=0x%08lx\n", __FUNCTION__, fmt, raw.format)); 576 // select the best as default 577 if (!raw.format) { 578 afmt = OpenSoundDevice::select_oss_format(fmt); 579 raw.format = OpenSoundDevice::convert_oss_format_to_media_format(afmt); 580 } 581 // if specified, try it 582 if (raw.format) 583 afmt = OpenSoundDevice::convert_media_format_to_oss_format(raw.format); 584 afmt &= fmt; 585 PRINT(("%s:step2 afmt=0x%08x\n", __FUNCTION__, afmt)); 586 if (afmt == 0) { 587 Close(); 588 return B_MEDIA_BAD_FORMAT; 589 } 590 // convert back 591 raw.format = OpenSoundDevice::convert_oss_format_to_media_format(afmt); 592 PRINT(("%s:step4 afmt=0x%08x, raw.format=0x%08lx\n", __FUNCTION__, afmt, raw.format)); 593 if (!raw.valid_bits) 594 raw.valid_bits = OpenSoundDevice::convert_oss_format_to_valid_bits(afmt); 595 if (raw.valid_bits != OpenSoundDevice::convert_oss_format_to_valid_bits(afmt)) { 596 Close(); 597 return B_MEDIA_BAD_FORMAT; 598 } 599 600 err = SetFormat(afmt); 601 if (err < B_OK) { 602 Close(); 603 return err; 604 } 605 606 // endianness 607 if (!raw.byte_order) 608 raw.byte_order = OpenSoundDevice::convert_oss_format_to_endian(afmt); 609 if (raw.byte_order != OpenSoundDevice::convert_oss_format_to_endian(afmt)) { 610 Close(); 611 return B_MEDIA_BAD_FORMAT; 612 } 613 614 // channel count 615 if (!raw.channel_count) 616 raw.channel_count = (unsigned)Info()->min_channels; 617 if (raw.channel_count < Info()->min_channels || raw.channel_count > Info()->max_channels) 618 return B_MEDIA_BAD_FORMAT; 619 err = SetChannels(raw.channel_count); 620 if (err < B_OK) { 621 Close(); 622 return err; 623 } 624 625 // sample rate 626 if (!raw.frame_rate) 627 raw.frame_rate = Info()->max_rate; 628 //raw.frame_rate = OpenSoundDevice::convert_oss_rate_to_media_rate(Info()->max_rate); // measured in Hertz 629 err = SetSpeed(OpenSoundDevice::convert_media_rate_to_oss_rate(raw.frame_rate)); 630 if (err < B_OK) { 631 Close(); 632 return err; 633 } 634 635 #if 0 636 raw.buffer_size = DEFAULT_BUFFER_SIZE 637 * (raw.format & media_raw_audio_format::B_AUDIO_SIZE_MASK) 638 * raw.channel_count; 639 #endif 640 audio_buf_info abinfo; 641 if (ioctl(fFD, rec?SNDCTL_DSP_GETISPACE:SNDCTL_DSP_GETOSPACE, &abinfo, sizeof(abinfo)) < 0) { 642 PRINT(("OpenSoundDeviceEngine::%s: %s: %s\n", 643 __FUNCTION__, "SNDCTL_DSP_GET?SPACE", strerror(errno))); 644 return -1; 645 } 646 PRINT(("OSS: %cSPACE: { bytes=%d, fragments=%d, fragsize=%d, fragstotal=%d }\n", rec?'I':'O', abinfo.bytes, abinfo.fragments, abinfo.fragsize, abinfo.fragstotal)); 647 // cache the first one in the Device 648 // so StartThread() knows the number of frags 649 //if (!fFragments.fragstotal) 650 // memcpy(&fFragments, &abinfo, sizeof(abinfo)); 651 652 // make sure buffer size is less than the driver's own buffer ( /2 to keep some margin ) 653 if (/*rec && raw.buffer_size &&*/ raw.buffer_size > abinfo.fragsize * abinfo.fragstotal / 4) 654 return B_MEDIA_BAD_FORMAT; 655 if (!raw.buffer_size) 656 raw.buffer_size = abinfo.fragsize;//XXX 657 /* * (raw.format & media_raw_audio_format::B_AUDIO_SIZE_MASK) 658 * raw.channel_count;*/ 659 } else if (format.type == B_MEDIA_ENCODED_AUDIO) { 660 media_raw_audio_format &raw = format.u.encoded_audio.output; 661 // XXX: do we really have to do this ? 662 raw.channel_count = MAX((unsigned)(Info()->min_channels), MIN((unsigned)(Info()->max_channels), raw.channel_count)); 663 raw.byte_order = B_MEDIA_HOST_ENDIAN; 664 raw.frame_rate = OpenSoundDevice::select_oss_rate(Info(), raw.frame_rate); // measured in Hertz 665 //raw.frame_rate = OpenSoundDevice::convert_oss_rate_to_media_rate(Info()->max_rate); // measured in Hertz 666 raw.buffer_size = DEFAULT_BUFFER_SIZE; 667 668 } else { 669 Close(); 670 return EINVAL; 671 } 672 // cache it 673 fMediaFormat = format; 674 char buf[1024]; 675 string_for_format(format, buf, 1024); 676 PRINT(("%s: %s\n", __FUNCTION__, buf)); 677 return B_OK; 678 } 679