1 /* 2 * Copyright (c) 2002, 2003 Jerome Duval (jerome.duval@free.fr) 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 //! Media add-on for drivers that use the multi audio interface 8 9 10 #include "MultiAudioNode.h" 11 12 #include <stdio.h> 13 #include <string.h> 14 15 #include <Autolock.h> 16 #include <Buffer.h> 17 #include <BufferGroup.h> 18 #include <Catalog.h> 19 #include <ParameterWeb.h> 20 #include <String.h> 21 22 #include <Referenceable.h> 23 24 #include "MultiAudioUtility.h" 25 #ifdef DEBUG 26 # define PRINTING 27 #endif 28 #include "debug.h" 29 #include "Resampler.h" 30 31 #undef B_TRANSLATION_CONTEXT 32 #define B_TRANSLATION_CONTEXT "MultiAudio" 33 34 #define PARAMETER_ID_INPUT_FREQUENCY 1 35 #define PARAMETER_ID_OUTPUT_FREQUENCY 2 36 37 38 //This represent an hardware output 39 class node_input { 40 public: 41 node_input(media_input& input, media_format format); 42 ~node_input(); 43 44 int32 fChannelId; 45 media_input fInput; 46 media_format fPreferredFormat; 47 media_format fFormat; 48 volatile uint32 fBufferCycle; 49 int32 fOldBufferCycle; 50 BBuffer* fBuffer; 51 Resampler *fResampler; 52 }; 53 54 55 //This represent an hardware input 56 class node_output { 57 public: 58 node_output(media_output& output, media_format format); 59 ~node_output(); 60 61 int32 fChannelId; 62 media_output fOutput; 63 media_format fPreferredFormat; 64 media_format fFormat; 65 66 BBufferGroup* fBufferGroup; 67 bool fOutputEnabled; 68 uint64 fSamplesSent; 69 volatile uint32 fBufferCycle; 70 int32 fOldBufferCycle; 71 Resampler* fResampler; 72 }; 73 74 75 struct FrameRateChangeCookie : public BReferenceable { 76 float oldFrameRate; 77 uint32 id; 78 }; 79 80 81 struct sample_rate_info { 82 uint32 multiAudioRate; 83 const char* name; 84 }; 85 86 87 static const sample_rate_info kSampleRateInfos[] = { 88 {B_SR_8000, "8000"}, 89 {B_SR_11025, "11025"}, 90 {B_SR_12000, "12000"}, 91 {B_SR_16000, "16000"}, 92 {B_SR_22050, "22050"}, 93 {B_SR_24000, "24000"}, 94 {B_SR_32000, "32000"}, 95 {B_SR_44100, "44100"}, 96 {B_SR_48000, "48000"}, 97 {B_SR_64000, "64000"}, 98 {B_SR_88200, "88200"}, 99 {B_SR_96000, "96000"}, 100 {B_SR_176400, "176400"}, 101 {B_SR_192000, "192000"}, 102 {B_SR_384000, "384000"}, 103 {B_SR_1536000, "1536000"}, 104 {} 105 }; 106 107 108 const char* kMultiControlString[] = { 109 "NAME IS ATTACHED", 110 B_TRANSLATE("Output"), B_TRANSLATE("Input"), B_TRANSLATE("Setup"), 111 B_TRANSLATE("Tone control"), B_TRANSLATE("Extended Setup"), 112 B_TRANSLATE("Enhanced Setup"), B_TRANSLATE("Master"), B_TRANSLATE("Beep"), 113 B_TRANSLATE("Phone"), B_TRANSLATE("Mic"), B_TRANSLATE("Line"), 114 B_TRANSLATE("CD"), B_TRANSLATE("Video"), B_TRANSLATE("Aux"), 115 B_TRANSLATE("Wave"), B_TRANSLATE("Gain"), B_TRANSLATE("Level"), 116 B_TRANSLATE("Volume"), B_TRANSLATE("Mute"), B_TRANSLATE("Enable"), 117 B_TRANSLATE("Stereo mix"), B_TRANSLATE("Mono mix"), 118 B_TRANSLATE("Output stereo mix"), B_TRANSLATE("Output mono mix"), 119 B_TRANSLATE("Output bass"), B_TRANSLATE("Output treble"), 120 B_TRANSLATE("Output 3D center"), B_TRANSLATE("Output 3D depth"), 121 B_TRANSLATE("Headphones"), B_TRANSLATE("SPDIF") 122 }; 123 124 125 // #pragma mark - 126 127 128 node_input::node_input(media_input& input, media_format format) 129 { 130 CALLED(); 131 fInput = input; 132 fPreferredFormat = format; 133 fBufferCycle = 1; 134 fOldBufferCycle = -1; 135 fBuffer = NULL; 136 fResampler = NULL; 137 } 138 139 140 node_input::~node_input() 141 { 142 CALLED(); 143 } 144 145 146 // #pragma mark - 147 148 149 node_output::node_output(media_output& output, media_format format) 150 : 151 fBufferGroup(NULL), 152 fOutputEnabled(true) 153 { 154 CALLED(); 155 fOutput = output; 156 fPreferredFormat = format; 157 fBufferCycle = 1; 158 fOldBufferCycle = -1; 159 fResampler = NULL; 160 } 161 162 163 node_output::~node_output() 164 { 165 CALLED(); 166 } 167 168 169 // #pragma mark - 170 171 172 MultiAudioNode::MultiAudioNode(BMediaAddOn* addon, const char* name, 173 MultiAudioDevice* device, int32 internalID, BMessage* config) 174 : 175 BMediaNode(name), 176 BBufferConsumer(B_MEDIA_RAW_AUDIO), 177 BBufferProducer(B_MEDIA_RAW_AUDIO), 178 BMediaEventLooper(), 179 fBufferLock("multi audio buffers"), 180 fQuitThread(0), 181 fThread(-1), 182 fDevice(device), 183 fTimeSourceStarted(false), 184 fWeb(NULL), 185 fConfig() 186 { 187 CALLED(); 188 fInitStatus = B_NO_INIT; 189 190 if (!device) 191 return; 192 193 fAddOn = addon; 194 fId = internalID; 195 196 AddNodeKind(B_PHYSICAL_OUTPUT); 197 AddNodeKind(B_PHYSICAL_INPUT); 198 199 // initialize our preferred format objects 200 fOutputPreferredFormat.type = B_MEDIA_RAW_AUDIO; 201 fOutputPreferredFormat.u.raw_audio.format 202 = MultiAudio::convert_to_media_format( 203 fDevice->FormatInfo().output.format); 204 fOutputPreferredFormat.u.raw_audio.valid_bits 205 = MultiAudio::convert_to_valid_bits( 206 fDevice->FormatInfo().output.format); 207 fOutputPreferredFormat.u.raw_audio.channel_count = 2; 208 fOutputPreferredFormat.u.raw_audio.frame_rate 209 = MultiAudio::convert_to_sample_rate(fDevice->FormatInfo().output.rate); 210 // measured in Hertz 211 fOutputPreferredFormat.u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN; 212 213 // we'll use the consumer's preferred buffer size, if any 214 fOutputPreferredFormat.u.raw_audio.buffer_size 215 = fDevice->BufferList().return_playback_buffer_size 216 * (fOutputPreferredFormat.u.raw_audio.format 217 & media_raw_audio_format::B_AUDIO_SIZE_MASK) 218 * fOutputPreferredFormat.u.raw_audio.channel_count; 219 220 // initialize our preferred format objects 221 fInputPreferredFormat.type = B_MEDIA_RAW_AUDIO; 222 fInputPreferredFormat.u.raw_audio.format 223 = MultiAudio::convert_to_media_format( 224 fDevice->FormatInfo().input.format); 225 fInputPreferredFormat.u.raw_audio.valid_bits 226 = MultiAudio::convert_to_valid_bits(fDevice->FormatInfo().input.format); 227 fInputPreferredFormat.u.raw_audio.channel_count = 2; 228 fInputPreferredFormat.u.raw_audio.frame_rate 229 = MultiAudio::convert_to_sample_rate(fDevice->FormatInfo().input.rate); 230 // measured in Hertz 231 fInputPreferredFormat.u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN; 232 233 // we'll use the consumer's preferred buffer size, if any 234 fInputPreferredFormat.u.raw_audio.buffer_size 235 = fDevice->BufferList().return_record_buffer_size 236 * (fInputPreferredFormat.u.raw_audio.format 237 & media_raw_audio_format::B_AUDIO_SIZE_MASK) 238 * fInputPreferredFormat.u.raw_audio.channel_count; 239 240 if (config != NULL) { 241 fConfig = *config; 242 PRINT_OBJECT(*config); 243 } 244 245 fInitStatus = B_OK; 246 } 247 248 249 MultiAudioNode::~MultiAudioNode() 250 { 251 CALLED(); 252 fAddOn->GetConfigurationFor(this, NULL); 253 254 _StopOutputThread(); 255 BMediaEventLooper::Quit(); 256 } 257 258 259 status_t 260 MultiAudioNode::InitCheck() const 261 { 262 CALLED(); 263 return fInitStatus; 264 } 265 266 267 void 268 MultiAudioNode::GetFlavor(flavor_info* info, int32 id) 269 { 270 CALLED(); 271 if (info == NULL) 272 return; 273 274 info->flavor_flags = 0; 275 info->possible_count = 1; 276 // one flavor at a time 277 info->in_format_count = 0; 278 // no inputs 279 info->in_formats = 0; 280 info->out_format_count = 0; 281 // no outputs 282 info->out_formats = 0; 283 info->internal_id = id; 284 285 info->name = const_cast<char*>("MultiAudioNode Node"); 286 info->info = const_cast<char*>("The MultiAudioNode node outputs to " 287 "multi_audio drivers."); 288 info->kinds = B_BUFFER_CONSUMER | B_BUFFER_PRODUCER | B_TIME_SOURCE 289 | B_PHYSICAL_OUTPUT | B_PHYSICAL_INPUT | B_CONTROLLABLE; 290 info->in_format_count = 1; 291 // 1 input 292 media_format* inFormats = new media_format[info->in_format_count]; 293 GetFormat(&inFormats[0]); 294 info->in_formats = inFormats; 295 296 info->out_format_count = 1; 297 // 1 output 298 media_format* outFormats = new media_format[info->out_format_count]; 299 GetFormat(&outFormats[0]); 300 info->out_formats = outFormats; 301 } 302 303 304 void 305 MultiAudioNode::GetFormat(media_format* format) 306 { 307 CALLED(); 308 if (format == NULL) 309 return; 310 311 format->type = B_MEDIA_RAW_AUDIO; 312 format->require_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS; 313 format->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS; 314 format->u.raw_audio = media_raw_audio_format::wildcard; 315 } 316 317 318 //#pragma mark - BMediaNode 319 320 321 BMediaAddOn* 322 MultiAudioNode::AddOn(int32* _internalID) const 323 { 324 CALLED(); 325 // BeBook says this only gets called if we were in an add-on. 326 if (fAddOn != 0 && _internalID != NULL) 327 *_internalID = fId; 328 329 return fAddOn; 330 } 331 332 333 void 334 MultiAudioNode::Preroll() 335 { 336 CALLED(); 337 // TODO: Performance opportunity 338 BMediaNode::Preroll(); 339 } 340 341 342 status_t 343 MultiAudioNode::HandleMessage(int32 message, const void* data, size_t size) 344 { 345 CALLED(); 346 return B_ERROR; 347 } 348 349 350 void 351 MultiAudioNode::NodeRegistered() 352 { 353 CALLED(); 354 355 if (fInitStatus != B_OK) { 356 ReportError(B_NODE_IN_DISTRESS); 357 return; 358 } 359 360 node_input *currentInput = NULL; 361 int32 currentId = 0; 362 363 for (int32 i = 0; i < fDevice->Description().output_channel_count; i++) { 364 if (currentInput == NULL 365 || (fDevice->Description().channels[i].designations 366 & B_CHANNEL_MONO_BUS) != 0 367 || ((fDevice->Description().channels[currentId].designations 368 & B_CHANNEL_STEREO_BUS) != 0 369 && ((fDevice->Description().channels[i].designations 370 & B_CHANNEL_LEFT) != 0 371 || (fDevice->Description().channels[i].designations 372 & B_CHANNEL_STEREO_BUS) == 0)) 373 || ((fDevice->Description().channels[currentId].designations 374 & B_CHANNEL_SURROUND_BUS) != 0 375 && ((fDevice->Description().channels[i].designations 376 & B_CHANNEL_LEFT) != 0 377 || (fDevice->Description().channels[i].designations 378 & B_CHANNEL_SURROUND_BUS) == 0))) { 379 PRINT(("NodeRegistered(): creating an input for %" B_PRIi32 "\n", 380 i)); 381 PRINT(("%" B_PRId32 "\t%d\t0x%" B_PRIx32 "\t0x%" B_PRIx32 "\n", 382 fDevice->Description().channels[i].channel_id, 383 fDevice->Description().channels[i].kind, 384 fDevice->Description().channels[i].designations, 385 fDevice->Description().channels[i].connectors)); 386 387 media_input* input = new media_input; 388 389 input->format = fOutputPreferredFormat; 390 input->destination.port = ControlPort(); 391 input->destination.id = fInputs.CountItems(); 392 input->node = Node(); 393 sprintf(input->name, "output %" B_PRId32, input->destination.id); 394 395 currentInput = new node_input(*input, fOutputPreferredFormat); 396 currentInput->fPreferredFormat.u.raw_audio.channel_count = 1; 397 currentInput->fInput.format = currentInput->fPreferredFormat; 398 delete currentInput->fResampler; 399 currentInput->fResampler = new 400 Resampler(currentInput->fPreferredFormat.AudioFormat(), 401 fOutputPreferredFormat.AudioFormat()); 402 403 currentInput->fChannelId 404 = fDevice->Description().channels[i].channel_id; 405 fInputs.AddItem(currentInput); 406 407 currentId = i; 408 } else { 409 PRINT(("NodeRegistered(): adding a channel\n")); 410 currentInput->fPreferredFormat.u.raw_audio.channel_count++; 411 currentInput->fInput.format = currentInput->fPreferredFormat; 412 } 413 currentInput->fInput.format.u.raw_audio.format 414 = media_raw_audio_format::wildcard.format; 415 } 416 417 node_output *currentOutput = NULL; 418 currentId = 0; 419 420 for (int32 i = fDevice->Description().output_channel_count; 421 i < fDevice->Description().output_channel_count 422 + fDevice->Description().input_channel_count; i++) { 423 if (currentOutput == NULL 424 || (fDevice->Description().channels[i].designations 425 & B_CHANNEL_MONO_BUS) != 0 426 || ((fDevice->Description().channels[currentId].designations 427 & B_CHANNEL_STEREO_BUS) != 0 428 && ((fDevice->Description().channels[i].designations 429 & B_CHANNEL_LEFT) != 0 430 || (fDevice->Description().channels[i].designations 431 & B_CHANNEL_STEREO_BUS) == 0)) 432 || ((fDevice->Description().channels[currentId].designations 433 & B_CHANNEL_SURROUND_BUS) != 0 434 && ((fDevice->Description().channels[i].designations 435 & B_CHANNEL_LEFT) != 0 436 || (fDevice->Description().channels[i].designations 437 & B_CHANNEL_SURROUND_BUS) == 0))) { 438 PRINT(("NodeRegistered(): creating an output for %" B_PRIi32 "\n", 439 i)); 440 PRINT(("%" B_PRId32 "\t%d\t0x%" B_PRIx32 "\t0x%" B_PRIx32 "\n", 441 fDevice->Description().channels[i].channel_id, 442 fDevice->Description().channels[i].kind, 443 fDevice->Description().channels[i].designations, 444 fDevice->Description().channels[i].connectors)); 445 446 media_output *output = new media_output; 447 448 output->format = fInputPreferredFormat; 449 output->destination = media_destination::null; 450 output->source.port = ControlPort(); 451 output->source.id = fOutputs.CountItems(); 452 output->node = Node(); 453 sprintf(output->name, "input %" B_PRId32, output->source.id); 454 455 currentOutput = new node_output(*output, fInputPreferredFormat); 456 currentOutput->fPreferredFormat.u.raw_audio.channel_count = 1; 457 currentOutput->fOutput.format = currentOutput->fPreferredFormat; 458 delete currentOutput->fResampler; 459 currentOutput->fResampler = new 460 Resampler(fInputPreferredFormat.AudioFormat(), 461 currentOutput->fPreferredFormat.AudioFormat()); 462 463 currentOutput->fChannelId 464 = fDevice->Description().channels[i].channel_id; 465 fOutputs.AddItem(currentOutput); 466 467 currentId = i; 468 } else { 469 PRINT(("NodeRegistered(): adding a channel\n")); 470 currentOutput->fPreferredFormat.u.raw_audio.channel_count++; 471 currentOutput->fOutput.format = currentOutput->fPreferredFormat; 472 } 473 } 474 475 // Set up our parameter web 476 fWeb = MakeParameterWeb(); 477 SetParameterWeb(fWeb); 478 479 // Apply configuration 480 #ifdef PRINTING 481 bigtime_t start = system_time(); 482 #endif 483 484 int32 index = 0; 485 int32 parameterID = 0; 486 const void *data; 487 ssize_t size; 488 while (fConfig.FindInt32("parameterID", index, ¶meterID) == B_OK) { 489 if (fConfig.FindData("parameterData", B_RAW_TYPE, index, &data, &size) 490 == B_OK) { 491 SetParameterValue(parameterID, TimeSource()->Now(), data, size); 492 } 493 index++; 494 } 495 496 PRINT(("apply configuration in: %" B_PRIdBIGTIME "\n", 497 system_time() - start)); 498 499 SetPriority(B_REAL_TIME_PRIORITY); 500 Run(); 501 } 502 503 504 status_t 505 MultiAudioNode::RequestCompleted(const media_request_info& info) 506 { 507 CALLED(); 508 509 if (info.what != media_request_info::B_REQUEST_FORMAT_CHANGE) 510 return B_OK; 511 512 FrameRateChangeCookie* cookie 513 = (FrameRateChangeCookie*)info.user_data; 514 if (cookie == NULL) 515 return B_OK; 516 517 BReference<FrameRateChangeCookie> cookieReference(cookie, true); 518 519 // if the request failed, we reset the frame rate 520 if (info.status != B_OK) { 521 if (cookie->id == PARAMETER_ID_INPUT_FREQUENCY) { 522 _SetNodeInputFrameRate(cookie->oldFrameRate); 523 if (fDevice->Description().output_rates & B_SR_SAME_AS_INPUT) 524 _SetNodeOutputFrameRate(cookie->oldFrameRate); 525 } else if (cookie->id == PARAMETER_ID_OUTPUT_FREQUENCY) 526 _SetNodeOutputFrameRate(cookie->oldFrameRate); 527 528 // TODO: If we have multiple connections, we should request to change 529 // the format back! 530 } 531 532 return B_OK; 533 } 534 535 536 void 537 MultiAudioNode::SetTimeSource(BTimeSource* timeSource) 538 { 539 CALLED(); 540 } 541 542 543 // #pragma mark - BBufferConsumer 544 545 546 status_t 547 MultiAudioNode::AcceptFormat(const media_destination& dest, 548 media_format* format) 549 { 550 // Check to make sure the format is okay, then remove 551 // any wildcards corresponding to our requirements. 552 CALLED(); 553 554 if (format == NULL) 555 return B_BAD_VALUE; 556 if (format->type != B_MEDIA_RAW_AUDIO) 557 return B_MEDIA_BAD_FORMAT; 558 559 node_input *channel = _FindInput(dest); 560 if (channel == NULL) 561 return B_MEDIA_BAD_DESTINATION; 562 563 /* media_format * myFormat = GetFormat(); 564 fprintf(stderr,"proposed format: "); 565 print_media_format(format); 566 fprintf(stderr,"\n"); 567 fprintf(stderr,"my format: "); 568 print_media_format(myFormat); 569 fprintf(stderr,"\n");*/ 570 // Be's format_is_compatible doesn't work. 571 // if (!format_is_compatible(*format,*myFormat)) { 572 573 channel->fFormat = channel->fPreferredFormat; 574 575 /*if(format->u.raw_audio.format == media_raw_audio_format::B_AUDIO_FLOAT 576 && channel->fPreferredFormat.u.raw_audio.format == media_raw_audio_format::B_AUDIO_SHORT) 577 format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; 578 else*/ 579 format->u.raw_audio.format = channel->fPreferredFormat.u.raw_audio.format; 580 format->u.raw_audio.valid_bits 581 = channel->fPreferredFormat.u.raw_audio.valid_bits; 582 583 format->u.raw_audio.frame_rate 584 = channel->fPreferredFormat.u.raw_audio.frame_rate; 585 format->u.raw_audio.channel_count 586 = channel->fPreferredFormat.u.raw_audio.channel_count; 587 format->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN; 588 format->u.raw_audio.buffer_size 589 = fDevice->BufferList().return_playback_buffer_size 590 * (format->u.raw_audio.format 591 & media_raw_audio_format::B_AUDIO_SIZE_MASK) 592 * format->u.raw_audio.channel_count; 593 594 /*media_format myFormat; 595 GetFormat(&myFormat); 596 if (!format_is_acceptible(*format,myFormat)) { 597 fprintf(stderr,"<- B_MEDIA_BAD_FORMAT\n"); 598 return B_MEDIA_BAD_FORMAT; 599 }*/ 600 //AddRequirements(format); 601 return B_OK; 602 } 603 604 605 status_t 606 MultiAudioNode::GetNextInput(int32* cookie, media_input* _input) 607 { 608 CALLED(); 609 if (_input == NULL) 610 return B_BAD_VALUE; 611 612 if (*cookie >= fInputs.CountItems() || *cookie < 0) 613 return B_BAD_INDEX; 614 615 node_input* channel = (node_input*)fInputs.ItemAt(*cookie); 616 *_input = channel->fInput; 617 *cookie += 1; 618 PRINT(("input.format: %" B_PRIu32 "\n", 619 channel->fInput.format.u.raw_audio.format)); 620 return B_OK; 621 } 622 623 624 void 625 MultiAudioNode::DisposeInputCookie(int32 cookie) 626 { 627 CALLED(); 628 // nothing to do since our cookies are just integers 629 } 630 631 632 void 633 MultiAudioNode::BufferReceived(BBuffer* buffer) 634 { 635 //CALLED(); 636 switch (buffer->Header()->type) { 637 /*case B_MEDIA_PARAMETERS: 638 { 639 status_t status = ApplyParameterData(buffer->Data(),buffer->SizeUsed()); 640 if (status != B_OK) { 641 fprintf(stderr,"ApplyParameterData in MultiAudioNode::BufferReceived failed\n"); 642 } 643 buffer->Recycle(); 644 } 645 break;*/ 646 case B_MEDIA_RAW_AUDIO: 647 if ((buffer->Flags() & BBuffer::B_SMALL_BUFFER) != 0) { 648 fprintf(stderr, "NOT IMPLEMENTED: B_SMALL_BUFFER in " 649 "MultiAudioNode::BufferReceived\n"); 650 // TODO: implement this part 651 buffer->Recycle(); 652 } else { 653 media_timed_event event(buffer->Header()->start_time, 654 BTimedEventQueue::B_HANDLE_BUFFER, buffer, 655 BTimedEventQueue::B_RECYCLE_BUFFER); 656 status_t status = EventQueue()->AddEvent(event); 657 if (status != B_OK) { 658 fprintf(stderr, "EventQueue()->AddEvent(event) in " 659 "MultiAudioNode::BufferReceived failed\n"); 660 buffer->Recycle(); 661 } 662 } 663 break; 664 default: 665 fprintf(stderr, "unexpected buffer type in " 666 "MultiAudioNode::BufferReceived\n"); 667 buffer->Recycle(); 668 break; 669 } 670 } 671 672 673 void 674 MultiAudioNode::ProducerDataStatus(const media_destination& forWhom, 675 int32 status, bigtime_t atPerformanceTime) 676 { 677 node_input* channel = _FindInput(forWhom); 678 if (channel == NULL) { 679 fprintf(stderr, "invalid destination received in " 680 "MultiAudioNode::ProducerDataStatus\n"); 681 return; 682 } 683 684 media_timed_event event(atPerformanceTime, BTimedEventQueue::B_DATA_STATUS, 685 &channel->fInput, BTimedEventQueue::B_NO_CLEANUP, status, 0, NULL); 686 EventQueue()->AddEvent(event); 687 } 688 689 690 status_t 691 MultiAudioNode::GetLatencyFor(const media_destination& forWhom, 692 bigtime_t* _latency, media_node_id* _timeSource) 693 { 694 CALLED(); 695 if (_latency == NULL || _timeSource == NULL) 696 return B_BAD_VALUE; 697 698 node_input* channel = _FindInput(forWhom); 699 if (channel == NULL) 700 return B_MEDIA_BAD_DESTINATION; 701 702 *_latency = EventLatency(); 703 *_timeSource = TimeSource()->ID(); 704 return B_OK; 705 } 706 707 708 status_t 709 MultiAudioNode::Connected(const media_source& producer, 710 const media_destination& where, const media_format& with_format, 711 media_input* out_input) 712 { 713 CALLED(); 714 if (out_input == 0) { 715 fprintf(stderr, "<- B_BAD_VALUE\n"); 716 return B_BAD_VALUE; 717 } 718 719 node_input* channel = _FindInput(where); 720 if (channel == NULL) { 721 fprintf(stderr, "<- B_MEDIA_BAD_DESTINATION\n"); 722 return B_MEDIA_BAD_DESTINATION; 723 } 724 725 _UpdateInternalLatency(with_format); 726 727 // record the agreed upon values 728 channel->fInput.source = producer; 729 channel->fInput.format = with_format; 730 *out_input = channel->fInput; 731 732 _StartOutputThreadIfNeeded(); 733 734 return B_OK; 735 } 736 737 738 void 739 MultiAudioNode::Disconnected(const media_source& producer, 740 const media_destination& where) 741 { 742 CALLED(); 743 744 node_input* channel = _FindInput(where); 745 if (channel == NULL || channel->fInput.source != producer) 746 return; 747 748 channel->fInput.source = media_source::null; 749 channel->fInput.format = channel->fPreferredFormat; 750 751 BAutolock locker(fBufferLock); 752 _FillWithZeros(*channel); 753 //GetFormat(&channel->fInput.format); 754 } 755 756 757 status_t 758 MultiAudioNode::FormatChanged(const media_source& producer, 759 const media_destination& consumer, int32 change_tag, 760 const media_format& format) 761 { 762 CALLED(); 763 764 node_input* channel = _FindInput(consumer); 765 766 if (channel==NULL) { 767 fprintf(stderr, "<- B_MEDIA_BAD_DESTINATION\n"); 768 return B_MEDIA_BAD_DESTINATION; 769 } 770 if (channel->fInput.source != producer) 771 return B_MEDIA_BAD_SOURCE; 772 773 return B_ERROR; 774 } 775 776 777 status_t 778 MultiAudioNode::SeekTagRequested(const media_destination& destination, 779 bigtime_t targetTime, uint32 flags, media_seek_tag* _seekTag, 780 bigtime_t* _taggedTime, uint32* _flags) 781 { 782 CALLED(); 783 return BBufferConsumer::SeekTagRequested(destination, targetTime, flags, 784 _seekTag, _taggedTime, _flags); 785 } 786 787 788 // #pragma mark - BBufferProducer 789 790 791 status_t 792 MultiAudioNode::FormatSuggestionRequested(media_type type, int32 /*quality*/, 793 media_format* format) 794 { 795 // FormatSuggestionRequested() is not necessarily part of the format 796 // negotiation process; it's simply an interrogation -- the caller 797 // wants to see what the node's preferred data format is, given a 798 // suggestion by the caller. 799 CALLED(); 800 801 if (format == NULL) { 802 fprintf(stderr, "\tERROR - NULL format pointer passed in!\n"); 803 return B_BAD_VALUE; 804 } 805 806 // this is the format we'll be returning (our preferred format) 807 *format = fInputPreferredFormat; 808 809 // a wildcard type is okay; we can specialize it 810 if (type == B_MEDIA_UNKNOWN_TYPE) 811 type = B_MEDIA_RAW_AUDIO; 812 813 // we only support raw audio 814 if (type != B_MEDIA_RAW_AUDIO) 815 return B_MEDIA_BAD_FORMAT; 816 817 return B_OK; 818 } 819 820 821 status_t 822 MultiAudioNode::FormatProposal(const media_source& output, media_format* format) 823 { 824 // FormatProposal() is the first stage in the BMediaRoster::Connect() 825 // process. We hand out a suggested format, with wildcards for any 826 // variations we support. 827 CALLED(); 828 829 // is this a proposal for our select output? 830 node_output* channel = _FindOutput(output); 831 if (channel == NULL) { 832 fprintf(stderr, "MultiAudioNode::FormatProposal returning " 833 "B_MEDIA_BAD_SOURCE\n"); 834 return B_MEDIA_BAD_SOURCE; 835 } 836 837 // We only support floating-point raw audio, so we always return that, 838 // but we supply an error code depending on whether we found the proposal 839 // acceptable. 840 media_type requestedType = format->type; 841 *format = channel->fPreferredFormat; 842 if (requestedType != B_MEDIA_UNKNOWN_TYPE 843 && requestedType != B_MEDIA_RAW_AUDIO) { 844 fprintf(stderr, "MultiAudioNode::FormatProposal returning " 845 "B_MEDIA_BAD_FORMAT\n"); 846 return B_MEDIA_BAD_FORMAT; 847 } 848 // raw audio or wildcard type, either is okay by us 849 return B_OK; 850 } 851 852 853 status_t 854 MultiAudioNode::FormatChangeRequested(const media_source& source, 855 const media_destination& destination, media_format* format, 856 int32* _deprecated_) 857 { 858 CALLED(); 859 860 // we don't support any other formats, so we just reject any format changes. 861 return B_ERROR; 862 } 863 864 865 status_t 866 MultiAudioNode::GetNextOutput(int32* cookie, media_output* _output) 867 { 868 CALLED(); 869 870 if (*cookie < fOutputs.CountItems() && *cookie >= 0) { 871 node_output* channel = (node_output*)fOutputs.ItemAt(*cookie); 872 *_output = channel->fOutput; 873 *cookie += 1; 874 return B_OK; 875 } 876 return B_BAD_INDEX; 877 } 878 879 880 status_t 881 MultiAudioNode::DisposeOutputCookie(int32 cookie) 882 { 883 CALLED(); 884 // do nothing because we don't use the cookie for anything special 885 return B_OK; 886 } 887 888 889 status_t 890 MultiAudioNode::SetBufferGroup(const media_source& forSource, 891 BBufferGroup* newGroup) 892 { 893 CALLED(); 894 895 // is this our output? 896 node_output* channel = _FindOutput(forSource); 897 if (channel == NULL) { 898 fprintf(stderr, "MultiAudioNode::SetBufferGroup returning " 899 "B_MEDIA_BAD_SOURCE\n"); 900 return B_MEDIA_BAD_SOURCE; 901 } 902 903 // Are we being passed the buffer group we're already using? 904 if (newGroup == channel->fBufferGroup) 905 return B_OK; 906 907 // Ahh, someone wants us to use a different buffer group. At this point 908 // we delete the one we are using and use the specified one instead. 909 // If the specified group is NULL, we need to recreate one ourselves, and 910 // use *that*. Note that if we're caching a BBuffer that we requested 911 // earlier, we have to Recycle() that buffer *before* deleting the buffer 912 // group, otherwise we'll deadlock waiting for that buffer to be recycled! 913 delete channel->fBufferGroup; 914 // waits for all buffers to recycle 915 if (newGroup != NULL) { 916 // we were given a valid group; just use that one from now on 917 channel->fBufferGroup = newGroup; 918 } else { 919 // we were passed a NULL group pointer; that means we construct 920 // our own buffer group to use from now on 921 size_t size = channel->fOutput.format.u.raw_audio.buffer_size; 922 int32 count = int32(fLatency / BufferDuration() + 1 + 1); 923 BBufferGroup* group = new BBufferGroup(size, count); 924 if (group == NULL || group->InitCheck() != B_OK) { 925 delete group; 926 fprintf(stderr, "MultiAudioNode::SetBufferGroup failed to" 927 "instantiate a new group.\n"); 928 return B_ERROR; 929 } 930 channel->fBufferGroup = group; 931 } 932 933 return B_OK; 934 } 935 936 937 status_t 938 MultiAudioNode::PrepareToConnect(const media_source& what, 939 const media_destination& where, media_format* format, 940 media_source* source, char* name) 941 { 942 CALLED(); 943 944 // is this our output? 945 node_output* channel = _FindOutput(what); 946 if (channel == NULL) { 947 fprintf(stderr, "MultiAudioNode::PrepareToConnect returning " 948 "B_MEDIA_BAD_SOURCE\n"); 949 return B_MEDIA_BAD_SOURCE; 950 } 951 952 // are we already connected? 953 if (channel->fOutput.destination != media_destination::null) 954 return B_MEDIA_ALREADY_CONNECTED; 955 956 // the format may not yet be fully specialized (the consumer might have 957 // passed back some wildcards). Finish specializing it now, and return an 958 // error if we don't support the requested format. 959 if (format->type != B_MEDIA_RAW_AUDIO) { 960 fprintf(stderr, "\tnon-raw-audio format?!\n"); 961 return B_MEDIA_BAD_FORMAT; 962 } 963 964 // !!! validate all other fields except for buffer_size here, because the 965 // consumer might have supplied different values from AcceptFormat()? 966 967 // check the buffer size, which may still be wildcarded 968 if (format->u.raw_audio.buffer_size 969 == media_raw_audio_format::wildcard.buffer_size) { 970 format->u.raw_audio.buffer_size = 2048; 971 // pick something comfortable to suggest 972 fprintf(stderr, "\tno buffer size provided, suggesting %lu\n", 973 format->u.raw_audio.buffer_size); 974 } else { 975 fprintf(stderr, "\tconsumer suggested buffer_size %lu\n", 976 format->u.raw_audio.buffer_size); 977 } 978 979 // Now reserve the connection, and return information about it 980 channel->fOutput.destination = where; 981 channel->fOutput.format = *format; 982 983 *source = channel->fOutput.source; 984 strlcpy(name, channel->fOutput.name, B_MEDIA_NAME_LENGTH); 985 return B_OK; 986 } 987 988 989 void 990 MultiAudioNode::Connect(status_t error, const media_source& source, 991 const media_destination& destination, const media_format& format, 992 char* name) 993 { 994 CALLED(); 995 996 // is this our output? 997 node_output* channel = _FindOutput(source); 998 if (channel == NULL) { 999 fprintf(stderr, "MultiAudioNode::Connect returning (cause: " 1000 "B_MEDIA_BAD_SOURCE)\n"); 1001 return; 1002 } 1003 1004 // If something earlier failed, Connect() might still be called, but with 1005 // a non-zero error code. When that happens we simply unreserve the 1006 // connection and do nothing else. 1007 if (error != B_OK) { 1008 channel->fOutput.destination = media_destination::null; 1009 channel->fOutput.format = channel->fPreferredFormat; 1010 return; 1011 } 1012 1013 // Okay, the connection has been confirmed. Record the destination and 1014 // format that we agreed on, and report our connection name again. 1015 channel->fOutput.destination = destination; 1016 channel->fOutput.format = format; 1017 strlcpy(name, channel->fOutput.name, B_MEDIA_NAME_LENGTH); 1018 1019 // reset our buffer duration, etc. to avoid later calculations 1020 bigtime_t duration = channel->fOutput.format.u.raw_audio.buffer_size * 10000 1021 / ((channel->fOutput.format.u.raw_audio.format 1022 & media_raw_audio_format::B_AUDIO_SIZE_MASK) 1023 * channel->fOutput.format.u.raw_audio.channel_count) 1024 / ((int32)(channel->fOutput.format.u.raw_audio.frame_rate / 100)); 1025 1026 SetBufferDuration(duration); 1027 1028 // Now that we're connected, we can determine our downstream latency. 1029 // Do so, then make sure we get our events early enough. 1030 media_node_id id; 1031 FindLatencyFor(channel->fOutput.destination, &fLatency, &id); 1032 PRINT(("\tdownstream latency = %" B_PRIdBIGTIME "\n", fLatency)); 1033 1034 fInternalLatency = BufferDuration(); 1035 PRINT(("\tbuffer-filling took %" B_PRIdBIGTIME " usec on this machine\n", 1036 fInternalLatency)); 1037 //SetEventLatency(fLatency + fInternalLatency); 1038 1039 // Set up the buffer group for our connection, as long as nobody handed us 1040 // a buffer group (via SetBufferGroup()) prior to this. That can happen, 1041 // for example, if the consumer calls SetOutputBuffersFor() on us from 1042 // within its Connected() method. 1043 if (channel->fBufferGroup == NULL) 1044 _AllocateBuffers(*channel); 1045 1046 _StartOutputThreadIfNeeded(); 1047 } 1048 1049 1050 void 1051 MultiAudioNode::Disconnect(const media_source& what, 1052 const media_destination& where) 1053 { 1054 CALLED(); 1055 1056 // is this our output? 1057 node_output* channel = _FindOutput(what); 1058 if (channel == NULL) { 1059 fprintf(stderr, "MultiAudioNode::Disconnect() returning (cause: " 1060 "B_MEDIA_BAD_SOURCE)\n"); 1061 return; 1062 } 1063 1064 // Make sure that our connection is the one being disconnected 1065 if (where == channel->fOutput.destination 1066 && what == channel->fOutput.source) { 1067 channel->fOutput.destination = media_destination::null; 1068 channel->fOutput.format = channel->fPreferredFormat; 1069 delete channel->fBufferGroup; 1070 channel->fBufferGroup = NULL; 1071 } else { 1072 fprintf(stderr, "\tDisconnect() called with wrong source/destination (" 1073 "%" B_PRId32 "/%" B_PRId32 "), ours is (%" B_PRId32 "/%" B_PRId32 1074 ")\n", what.id, where.id, channel->fOutput.source.id, 1075 channel->fOutput.destination.id); 1076 } 1077 } 1078 1079 1080 void 1081 MultiAudioNode::LateNoticeReceived(const media_source& what, bigtime_t howMuch, 1082 bigtime_t performanceTime) 1083 { 1084 CALLED(); 1085 1086 // is this our output? 1087 node_output* channel = _FindOutput(what); 1088 if (channel == NULL) 1089 return; 1090 1091 // If we're late, we need to catch up. Respond in a manner appropriate 1092 // to our current run mode. 1093 if (RunMode() == B_RECORDING) { 1094 // A hardware capture node can't adjust; it simply emits buffers at 1095 // appropriate points. We (partially) simulate this by not adjusting 1096 // our behavior upon receiving late notices -- after all, the hardware 1097 // can't choose to capture "sooner".... 1098 } else if (RunMode() == B_INCREASE_LATENCY) { 1099 // We're late, and our run mode dictates that we try to produce buffers 1100 // earlier in order to catch up. This argues that the downstream nodes 1101 // are not properly reporting their latency, but there's not much we can 1102 // do about that at the moment, so we try to start producing buffers 1103 // earlier to compensate. 1104 fInternalLatency += howMuch; 1105 SetEventLatency(fLatency + fInternalLatency); 1106 1107 fprintf(stderr, "\tincreasing latency to %" B_PRIdBIGTIME"\n", 1108 fLatency + fInternalLatency); 1109 } else { 1110 // The other run modes dictate various strategies for sacrificing data 1111 // quality in the interests of timely data delivery. The way *we* do 1112 // this is to skip a buffer, which catches us up in time by one buffer 1113 // duration. 1114 /*size_t nSamples = fOutput.format.u.raw_audio.buffer_size / sizeof(float); 1115 mSamplesSent += nSamples;*/ 1116 1117 fprintf(stderr, "\tskipping a buffer to try to catch up\n"); 1118 } 1119 } 1120 1121 1122 void 1123 MultiAudioNode::EnableOutput(const media_source& what, bool enabled, 1124 int32* _deprecated_) 1125 { 1126 CALLED(); 1127 1128 // If I had more than one output, I'd have to walk my list of output 1129 // records to see which one matched the given source, and then 1130 // enable/disable that one. But this node only has one output, so I 1131 // just make sure the given source matches, then set the enable state 1132 // accordingly. 1133 node_output* channel = _FindOutput(what); 1134 if (channel != NULL) 1135 channel->fOutputEnabled = enabled; 1136 } 1137 1138 1139 void 1140 MultiAudioNode::AdditionalBufferRequested(const media_source& source, 1141 media_buffer_id previousBuffer, bigtime_t previousTime, 1142 const media_seek_tag* previousTag) 1143 { 1144 CALLED(); 1145 // we don't support offline mode 1146 return; 1147 } 1148 1149 1150 // #pragma mark - BMediaEventLooper 1151 1152 1153 void 1154 MultiAudioNode::HandleEvent(const media_timed_event* event, bigtime_t lateness, 1155 bool realTimeEvent) 1156 { 1157 switch (event->type) { 1158 case BTimedEventQueue::B_START: 1159 _HandleStart(event, lateness, realTimeEvent); 1160 break; 1161 case BTimedEventQueue::B_SEEK: 1162 _HandleSeek(event, lateness, realTimeEvent); 1163 break; 1164 case BTimedEventQueue::B_WARP: 1165 _HandleWarp(event, lateness, realTimeEvent); 1166 break; 1167 case BTimedEventQueue::B_STOP: 1168 _HandleStop(event, lateness, realTimeEvent); 1169 break; 1170 case BTimedEventQueue::B_HANDLE_BUFFER: 1171 if (RunState() == BMediaEventLooper::B_STARTED) 1172 _HandleBuffer(event, lateness, realTimeEvent); 1173 break; 1174 case BTimedEventQueue::B_DATA_STATUS: 1175 _HandleDataStatus(event, lateness, realTimeEvent); 1176 break; 1177 case BTimedEventQueue::B_PARAMETER: 1178 _HandleParameter(event, lateness, realTimeEvent); 1179 break; 1180 default: 1181 fprintf(stderr," unknown event type: %" B_PRId32 "\n", 1182 event->type); 1183 break; 1184 } 1185 } 1186 1187 1188 status_t 1189 MultiAudioNode::_HandleBuffer(const media_timed_event* event, 1190 bigtime_t lateness, bool realTimeEvent) 1191 { 1192 BBuffer* buffer = const_cast<BBuffer*>((BBuffer*)event->pointer); 1193 if (buffer == NULL) 1194 return B_BAD_VALUE; 1195 1196 //PRINT(("buffer->Header()->destination: %i\n", buffer->Header()->destination)); 1197 1198 node_input* channel = _FindInput(buffer->Header()->destination); 1199 if (channel == NULL) { 1200 buffer->Recycle(); 1201 return B_MEDIA_BAD_DESTINATION; 1202 } 1203 1204 // if the buffer is late, we ignore it and report the fact to the producer 1205 // who sent it to us 1206 if (RunMode() != B_OFFLINE && RunMode() != B_RECORDING && lateness > 0) { 1207 // lateness doesn't matter in offline mode or in recording mode 1208 //mLateBuffers++; 1209 NotifyLateProducer(channel->fInput.source, lateness, event->event_time); 1210 fprintf(stderr," <- LATE BUFFER: %" B_PRIdBIGTIME "\n", lateness); 1211 buffer->Recycle(); 1212 } else { 1213 //WriteBuffer(buffer, *channel); 1214 // TODO: This seems like a very fragile mechanism to wait until 1215 // the previous buffer for this channel has been processed... 1216 if (channel->fBuffer != NULL) { 1217 PRINT(("MultiAudioNode::HandleBuffer snoozing recycling channelId: " 1218 "%" B_PRIi32 ", how_early:%" B_PRIdBIGTIME "\n", 1219 channel->fChannelId, lateness)); 1220 //channel->fBuffer->Recycle(); 1221 snooze(100); 1222 if (channel->fBuffer != NULL) 1223 buffer->Recycle(); 1224 else 1225 channel->fBuffer = buffer; 1226 } else { 1227 //PRINT(("MultiAudioNode::HandleBuffer writing channelId: %li, how_early:%Ld\n", channel->fChannelId, howEarly)); 1228 channel->fBuffer = buffer; 1229 } 1230 } 1231 return B_OK; 1232 } 1233 1234 1235 status_t 1236 MultiAudioNode::_HandleDataStatus(const media_timed_event* event, 1237 bigtime_t lateness, bool realTimeEvent) 1238 { 1239 PRINT(("MultiAudioNode::HandleDataStatus status:%" B_PRIi32 ", lateness:%" 1240 B_PRIiBIGTIME "\n", event->data, lateness)); 1241 switch (event->data) { 1242 case B_DATA_NOT_AVAILABLE: 1243 break; 1244 case B_DATA_AVAILABLE: 1245 break; 1246 case B_PRODUCER_STOPPED: 1247 break; 1248 default: 1249 break; 1250 } 1251 return B_OK; 1252 } 1253 1254 1255 status_t 1256 MultiAudioNode::_HandleStart(const media_timed_event* event, bigtime_t lateness, 1257 bool realTimeEvent) 1258 { 1259 CALLED(); 1260 if (RunState() != B_STARTED) { 1261 } 1262 return B_OK; 1263 } 1264 1265 1266 status_t 1267 MultiAudioNode::_HandleSeek(const media_timed_event* event, bigtime_t lateness, 1268 bool realTimeEvent) 1269 { 1270 CALLED(); 1271 PRINT(("MultiAudioNode::HandleSeek(t=%" B_PRIdBIGTIME ",d=%" B_PRIi32 1272 ",bd=%" B_PRId64 ")\n", 1273 event->event_time,event->data,event->bigdata)); 1274 return B_OK; 1275 } 1276 1277 1278 status_t 1279 MultiAudioNode::_HandleWarp(const media_timed_event* event, bigtime_t lateness, 1280 bool realTimeEvent) 1281 { 1282 CALLED(); 1283 return B_OK; 1284 } 1285 1286 1287 status_t 1288 MultiAudioNode::_HandleStop(const media_timed_event* event, bigtime_t lateness, 1289 bool realTimeEvent) 1290 { 1291 CALLED(); 1292 // flush the queue so downstreamers don't get any more 1293 EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true, 1294 BTimedEventQueue::B_HANDLE_BUFFER); 1295 1296 //_StopOutputThread(); 1297 return B_OK; 1298 } 1299 1300 1301 status_t 1302 MultiAudioNode::_HandleParameter(const media_timed_event* event, 1303 bigtime_t lateness, bool realTimeEvent) 1304 { 1305 CALLED(); 1306 return B_OK; 1307 } 1308 1309 1310 // #pragma mark - BTimeSource 1311 1312 1313 void 1314 MultiAudioNode::SetRunMode(run_mode mode) 1315 { 1316 CALLED(); 1317 PRINT(("MultiAudioNode::SetRunMode mode:%i\n", mode)); 1318 //BTimeSource::SetRunMode(mode); 1319 } 1320 1321 1322 status_t 1323 MultiAudioNode::TimeSourceOp(const time_source_op_info& op, void* _reserved) 1324 { 1325 CALLED(); 1326 switch (op.op) { 1327 case B_TIMESOURCE_START: 1328 PRINT(("TimeSourceOp op B_TIMESOURCE_START\n")); 1329 if (RunState() != BMediaEventLooper::B_STARTED) { 1330 fTimeSourceStarted = true; 1331 _StartOutputThreadIfNeeded(); 1332 1333 media_timed_event startEvent(0, BTimedEventQueue::B_START); 1334 EventQueue()->AddEvent(startEvent); 1335 } 1336 break; 1337 case B_TIMESOURCE_STOP: 1338 PRINT(("TimeSourceOp op B_TIMESOURCE_STOP\n")); 1339 if (RunState() == BMediaEventLooper::B_STARTED) { 1340 media_timed_event stopEvent(0, BTimedEventQueue::B_STOP); 1341 EventQueue()->AddEvent(stopEvent); 1342 fTimeSourceStarted = false; 1343 _StopOutputThread(); 1344 PublishTime(0, 0, 0); 1345 } 1346 break; 1347 case B_TIMESOURCE_STOP_IMMEDIATELY: 1348 PRINT(("TimeSourceOp op B_TIMESOURCE_STOP_IMMEDIATELY\n")); 1349 if (RunState() == BMediaEventLooper::B_STARTED) { 1350 media_timed_event stopEvent(0, BTimedEventQueue::B_STOP); 1351 EventQueue()->AddEvent(stopEvent); 1352 fTimeSourceStarted = false; 1353 _StopOutputThread(); 1354 PublishTime(0, 0, 0); 1355 } 1356 break; 1357 case B_TIMESOURCE_SEEK: 1358 PRINT(("TimeSourceOp op B_TIMESOURCE_SEEK\n")); 1359 BroadcastTimeWarp(op.real_time, op.performance_time); 1360 break; 1361 default: 1362 break; 1363 } 1364 return B_OK; 1365 } 1366 1367 1368 // #pragma mark - BControllable 1369 1370 1371 status_t 1372 MultiAudioNode::GetParameterValue(int32 id, bigtime_t* lastChange, void* value, 1373 size_t* size) 1374 { 1375 CALLED(); 1376 1377 PRINT(("id: %" B_PRIi32 "\n", id)); 1378 BParameter* parameter = NULL; 1379 for (int32 i = 0; i < fWeb->CountParameters(); i++) { 1380 parameter = fWeb->ParameterAt(i); 1381 if (parameter->ID() == id) 1382 break; 1383 } 1384 1385 if (parameter == NULL) { 1386 // Hmmm, we were asked for a parameter that we don't actually 1387 // support. Report an error back to the caller. 1388 PRINT(("\terror - asked for illegal parameter %" B_PRId32 "\n", id)); 1389 return B_ERROR; 1390 } 1391 1392 if (id == PARAMETER_ID_INPUT_FREQUENCY 1393 || id == PARAMETER_ID_OUTPUT_FREQUENCY) { 1394 const multi_format_info& info = fDevice->FormatInfo(); 1395 1396 uint32 rate = id == PARAMETER_ID_INPUT_FREQUENCY 1397 ? info.input.rate : info.output.rate; 1398 1399 if (*size < sizeof(rate)) 1400 return B_ERROR; 1401 1402 memcpy(value, &rate, sizeof(rate)); 1403 *size = sizeof(rate); 1404 return B_OK; 1405 } 1406 1407 multi_mix_value_info info; 1408 multi_mix_value values[2]; 1409 info.values = values; 1410 info.item_count = 0; 1411 multi_mix_control* controls = fDevice->MixControlInfo().controls; 1412 int32 control_id = controls[id - 100].id; 1413 1414 if (*size < sizeof(float)) 1415 return B_ERROR; 1416 1417 if (parameter->Type() == BParameter::B_CONTINUOUS_PARAMETER) { 1418 info.item_count = 1; 1419 values[0].id = control_id; 1420 1421 if (parameter->CountChannels() == 2) { 1422 if (*size < 2*sizeof(float)) 1423 return B_ERROR; 1424 info.item_count = 2; 1425 values[1].id = controls[id + 1 - 100].id; 1426 } 1427 } else if (parameter->Type() == BParameter::B_DISCRETE_PARAMETER) { 1428 info.item_count = 1; 1429 values[0].id = control_id; 1430 } 1431 1432 if (info.item_count > 0) { 1433 status_t status = fDevice->GetMix(&info); 1434 if (status != B_OK) { 1435 fprintf(stderr, "Failed on DRIVER_GET_MIX\n"); 1436 } else { 1437 if (parameter->Type() == BParameter::B_CONTINUOUS_PARAMETER) { 1438 ((float*)value)[0] = values[0].gain; 1439 *size = sizeof(float); 1440 1441 if (parameter->CountChannels() == 2) { 1442 ((float*)value)[1] = values[1].gain; 1443 *size = 2*sizeof(float); 1444 } 1445 1446 for (uint32 i = 0; i < *size / sizeof(float); i++) { 1447 PRINT(("GetParameterValue B_CONTINUOUS_PARAMETER value[%" 1448 B_PRIi32 "]: %f\n", i, ((float*)value)[i])); 1449 } 1450 } else if (parameter->Type() == BParameter::B_DISCRETE_PARAMETER) { 1451 BDiscreteParameter* discrete = (BDiscreteParameter*)parameter; 1452 if (discrete->CountItems() <= 2) 1453 ((int32*)value)[0] = values[0].enable ? 1 : 0; 1454 else 1455 ((int32*)value)[0] = values[0].mux; 1456 1457 *size = sizeof(int32); 1458 1459 for (uint32 i = 0; i < *size / sizeof(int32); i++) { 1460 PRINT(("GetParameterValue B_DISCRETE_PARAMETER value[%" 1461 B_PRIi32 "]: %" B_PRIi32 "\n", i, ((int32*)value)[i])); 1462 } 1463 } 1464 } 1465 } 1466 return B_OK; 1467 } 1468 1469 1470 void 1471 MultiAudioNode::SetParameterValue(int32 id, bigtime_t performanceTime, 1472 const void* value, size_t size) 1473 { 1474 CALLED(); 1475 PRINT(("id: %" B_PRIi32 ", performance_time: %" B_PRIdBIGTIME 1476 ", size: %" B_PRIuSIZE "\n", id, performanceTime, size)); 1477 1478 BParameter* parameter = NULL; 1479 for (int32 i = 0; i < fWeb->CountParameters(); i++) { 1480 parameter = fWeb->ParameterAt(i); 1481 if (parameter->ID() == id) 1482 break; 1483 } 1484 1485 if (parameter == NULL) 1486 return; 1487 1488 if (id == PARAMETER_ID_OUTPUT_FREQUENCY 1489 || (id == PARAMETER_ID_INPUT_FREQUENCY 1490 && (fDevice->Description().output_rates 1491 & B_SR_SAME_AS_INPUT) != 0)) { 1492 uint32 rate; 1493 if (size < sizeof(rate)) 1494 return; 1495 memcpy(&rate, value, sizeof(rate)); 1496 1497 if (rate == fOutputPreferredFormat.u.raw_audio.frame_rate) 1498 return; 1499 1500 // create a cookie RequestCompleted() can get the old frame rate from, 1501 // if anything goes wrong 1502 FrameRateChangeCookie* cookie = new(std::nothrow) FrameRateChangeCookie; 1503 if (cookie == NULL) 1504 return; 1505 1506 cookie->oldFrameRate = fOutputPreferredFormat.u.raw_audio.frame_rate; 1507 cookie->id = id; 1508 BReference<FrameRateChangeCookie> cookieReference(cookie, true); 1509 1510 // NOTE: What we should do is call RequestFormatChange() for all 1511 // connections and change the device's format in RequestCompleted(). 1512 // Unfortunately we need the new buffer size first, which we only get 1513 // from the device after changing the format. So we do that now and 1514 // reset it in RequestCompleted(), if something went wrong. This causes 1515 // the buffers we receive until then to be played incorrectly leading 1516 // to unpleasant noise. 1517 float frameRate = MultiAudio::convert_to_sample_rate(rate); 1518 if (_SetNodeInputFrameRate(frameRate) != B_OK) 1519 return; 1520 1521 for (int32 i = 0; i < fInputs.CountItems(); i++) { 1522 node_input* channel = (node_input*)fInputs.ItemAt(i); 1523 if (channel->fInput.source == media_source::null) 1524 continue; 1525 1526 media_format newFormat = channel->fInput.format; 1527 newFormat.u.raw_audio.frame_rate = frameRate; 1528 newFormat.u.raw_audio.buffer_size 1529 = fOutputPreferredFormat.u.raw_audio.buffer_size; 1530 1531 int32 changeTag = 0; 1532 status_t error = RequestFormatChange(channel->fInput.source, 1533 channel->fInput.destination, newFormat, NULL, &changeTag); 1534 if (error == B_OK) 1535 cookie->AcquireReference(); 1536 } 1537 1538 if (id != PARAMETER_ID_INPUT_FREQUENCY) 1539 return; 1540 //Do not return cause we should go in the next if 1541 } 1542 1543 if (id == PARAMETER_ID_INPUT_FREQUENCY) { 1544 uint32 rate; 1545 if (size < sizeof(rate)) 1546 return; 1547 memcpy(&rate, value, sizeof(rate)); 1548 1549 if (rate == fInputPreferredFormat.u.raw_audio.frame_rate) 1550 return; 1551 1552 // create a cookie RequestCompleted() can get the old frame rate from, 1553 // if anything goes wrong 1554 FrameRateChangeCookie* cookie = new(std::nothrow) FrameRateChangeCookie; 1555 if (cookie == NULL) 1556 return; 1557 1558 cookie->oldFrameRate = fInputPreferredFormat.u.raw_audio.frame_rate; 1559 cookie->id = id; 1560 BReference<FrameRateChangeCookie> cookieReference(cookie, true); 1561 1562 // NOTE: What we should do is call RequestFormatChange() for all 1563 // connections and change the device's format in RequestCompleted(). 1564 // Unfortunately we need the new buffer size first, which we only get 1565 // from the device after changing the format. So we do that now and 1566 // reset it in RequestCompleted(), if something went wrong. This causes 1567 // the buffers we receive until then to be played incorrectly leading 1568 // to unpleasant noise. 1569 float frameRate = MultiAudio::convert_to_sample_rate(rate); 1570 if (_SetNodeOutputFrameRate(frameRate) != B_OK) 1571 return; 1572 1573 for (int32 i = 0; i < fOutputs.CountItems(); i++) { 1574 node_output* channel = (node_output*)fOutputs.ItemAt(i); 1575 if (channel->fOutput.source == media_source::null) 1576 continue; 1577 1578 media_format newFormat = channel->fOutput.format; 1579 newFormat.u.raw_audio.frame_rate = frameRate; 1580 newFormat.u.raw_audio.buffer_size 1581 = fInputPreferredFormat.u.raw_audio.buffer_size; 1582 1583 int32 changeTag = 0; 1584 status_t error = RequestFormatChange(channel->fOutput.source, 1585 channel->fOutput.destination, newFormat, NULL, &changeTag); 1586 if (error == B_OK) 1587 cookie->AcquireReference(); 1588 } 1589 1590 return; 1591 } 1592 1593 multi_mix_value_info info; 1594 multi_mix_value values[2]; 1595 info.values = values; 1596 info.item_count = 0; 1597 multi_mix_control* controls = fDevice->MixControlInfo().controls; 1598 int32 control_id = controls[id - 100].id; 1599 1600 if (parameter->Type() == BParameter::B_CONTINUOUS_PARAMETER) { 1601 for (uint32 i = 0; i < size / sizeof(float); i++) { 1602 PRINT(("SetParameterValue B_CONTINUOUS_PARAMETER value[%" B_PRIi32 1603 "]: %f\n", i, ((float*)value)[i])); 1604 } 1605 info.item_count = 1; 1606 values[0].id = control_id; 1607 values[0].gain = ((float*)value)[0]; 1608 1609 if (parameter->CountChannels() == 2) { 1610 info.item_count = 2; 1611 values[1].id = controls[id + 1 - 100].id; 1612 values[1].gain = ((float*)value)[1]; 1613 } 1614 } else if (parameter->Type() == BParameter::B_DISCRETE_PARAMETER) { 1615 for (uint32 i = 0; i < size / sizeof(int32); i++) { 1616 PRINT(("SetParameterValue B_DISCRETE_PARAMETER value[%" B_PRIi32 1617 "]: %" B_PRIi32 "\n", i, ((int32*)value)[i])); 1618 } 1619 1620 BDiscreteParameter* discrete = (BDiscreteParameter*)parameter; 1621 if (discrete->CountItems() <= 2) { 1622 info.item_count = 1; 1623 values[0].id = control_id; 1624 values[0].enable = ((int32*)value)[0] == 1; 1625 } else { 1626 info.item_count = 1; 1627 values[0].id = control_id; 1628 values[0].mux = ((uint32*)value)[0]; 1629 } 1630 } 1631 1632 if (info.item_count > 0) { 1633 status_t status = fDevice->SetMix(&info); 1634 if (status != B_OK) 1635 fprintf(stderr, "Failed on DRIVER_SET_MIX\n"); 1636 } 1637 } 1638 1639 1640 BParameterWeb* 1641 MultiAudioNode::MakeParameterWeb() 1642 { 1643 CALLED(); 1644 BParameterWeb* web = new BParameterWeb(); 1645 1646 PRINT(("MixControlInfo().control_count: %" B_PRIi32 "\n", 1647 fDevice->MixControlInfo().control_count)); 1648 1649 BParameterGroup* generalGroup = web->MakeGroup(B_TRANSLATE("General")); 1650 1651 const multi_description& description = fDevice->Description(); 1652 1653 if ((description.output_rates & B_SR_SAME_AS_INPUT) != 0) { 1654 _CreateFrequencyParameterGroup(generalGroup, 1655 B_TRANSLATE("Input & Output"), PARAMETER_ID_INPUT_FREQUENCY, 1656 description.input_rates); 1657 } else { 1658 _CreateFrequencyParameterGroup(generalGroup, B_TRANSLATE("Input"), 1659 PARAMETER_ID_INPUT_FREQUENCY, description.input_rates); 1660 _CreateFrequencyParameterGroup(generalGroup, B_TRANSLATE("Output"), 1661 PARAMETER_ID_OUTPUT_FREQUENCY, description.output_rates); 1662 } 1663 1664 multi_mix_control* controls = fDevice->MixControlInfo().controls; 1665 1666 for (int i = 0; i < fDevice->MixControlInfo().control_count; i++) { 1667 if ((controls[i].flags & B_MULTI_MIX_GROUP) != 0 1668 && controls[i].parent == 0) { 1669 PRINT(("NEW_GROUP\n")); 1670 BParameterGroup* child = web->MakeGroup( 1671 _GetControlName(controls[i])); 1672 1673 int32 numParameters = 0; 1674 _ProcessGroup(child, i, numParameters); 1675 } 1676 } 1677 1678 return web; 1679 } 1680 1681 1682 const char* 1683 MultiAudioNode::_GetControlName(multi_mix_control& control) 1684 { 1685 if (control.string != S_null) 1686 return kMultiControlString[control.string]; 1687 1688 return control.name; 1689 } 1690 1691 1692 void 1693 MultiAudioNode::_ProcessGroup(BParameterGroup* group, int32 index, 1694 int32& numParameters) 1695 { 1696 CALLED(); 1697 multi_mix_control* parent = &fDevice->MixControlInfo().controls[index]; 1698 multi_mix_control* controls = fDevice->MixControlInfo().controls; 1699 1700 for (int32 i = 0; i < fDevice->MixControlInfo().control_count; i++) { 1701 if (controls[i].parent != parent->id) 1702 continue; 1703 1704 const char* name = _GetControlName(controls[i]); 1705 1706 if (controls[i].flags & B_MULTI_MIX_GROUP) { 1707 PRINT(("NEW_GROUP\n")); 1708 BParameterGroup* child = group->MakeGroup(name); 1709 child->MakeNullParameter(100 + i, B_MEDIA_RAW_AUDIO, name, 1710 B_WEB_BUFFER_OUTPUT); 1711 1712 int32 num = 1; 1713 _ProcessGroup(child, i, num); 1714 } else if (controls[i].flags & B_MULTI_MIX_MUX) { 1715 PRINT(("NEW_MUX\n")); 1716 BDiscreteParameter* parameter = group->MakeDiscreteParameter( 1717 100 + i, B_MEDIA_RAW_AUDIO, name, B_INPUT_MUX); 1718 if (numParameters > 0) { 1719 (group->ParameterAt(numParameters - 1))->AddOutput( 1720 group->ParameterAt(numParameters)); 1721 numParameters++; 1722 } 1723 _ProcessMux(parameter, i); 1724 } else if (controls[i].flags & B_MULTI_MIX_GAIN) { 1725 PRINT(("NEW_GAIN\n")); 1726 group->MakeContinuousParameter(100 + i, 1727 B_MEDIA_RAW_AUDIO, "", B_MASTER_GAIN, "dB", 1728 controls[i].gain.min_gain, controls[i].gain.max_gain, 1729 controls[i].gain.granularity); 1730 1731 if (i + 1 < fDevice->MixControlInfo().control_count 1732 && controls[i + 1].master == controls[i].id 1733 && (controls[i + 1].flags & B_MULTI_MIX_GAIN) != 0) { 1734 group->ParameterAt(numParameters)->SetChannelCount( 1735 group->ParameterAt(numParameters)->CountChannels() + 1); 1736 i++; 1737 } 1738 1739 PRINT(("num parameters: %" B_PRId32 "\n", numParameters)); 1740 if (numParameters > 0) { 1741 group->ParameterAt(numParameters - 1)->AddOutput( 1742 group->ParameterAt(numParameters)); 1743 numParameters++; 1744 } 1745 } else if (controls[i].flags & B_MULTI_MIX_ENABLE) { 1746 PRINT(("NEW_ENABLE\n")); 1747 if (controls[i].string == S_MUTE) { 1748 group->MakeDiscreteParameter(100 + i, 1749 B_MEDIA_RAW_AUDIO, name, B_MUTE); 1750 } else { 1751 group->MakeDiscreteParameter(100 + i, 1752 B_MEDIA_RAW_AUDIO, name, B_ENABLE); 1753 } 1754 if (numParameters > 0) { 1755 group->ParameterAt(numParameters - 1)->AddOutput( 1756 group->ParameterAt(numParameters)); 1757 numParameters++; 1758 } 1759 } 1760 } 1761 } 1762 1763 1764 void 1765 MultiAudioNode::_ProcessMux(BDiscreteParameter* parameter, int32 index) 1766 { 1767 CALLED(); 1768 multi_mix_control* parent = &fDevice->MixControlInfo().controls[index]; 1769 multi_mix_control* controls = fDevice->MixControlInfo().controls; 1770 int32 itemIndex = 0; 1771 1772 for (int32 i = 0; i < fDevice->MixControlInfo().control_count; i++) { 1773 if (controls[i].parent != parent->id) 1774 continue; 1775 1776 if ((controls[i].flags & B_MULTI_MIX_MUX_VALUE) != 0) { 1777 PRINT(("NEW_MUX_VALUE\n")); 1778 parameter->AddItem(itemIndex, _GetControlName(controls[i])); 1779 itemIndex++; 1780 } 1781 } 1782 } 1783 1784 1785 void 1786 MultiAudioNode::_CreateFrequencyParameterGroup(BParameterGroup* parentGroup, 1787 const char* name, int32 parameterID, uint32 rateMask) 1788 { 1789 BParameterGroup* group = parentGroup->MakeGroup(name); 1790 BDiscreteParameter* frequencyParam = group->MakeDiscreteParameter( 1791 parameterID, B_MEDIA_NO_TYPE, 1792 BString(name) << B_TRANSLATE(" frequency:"), 1793 B_GENERIC); 1794 1795 for (int32 i = 0; kSampleRateInfos[i].name != NULL; i++) { 1796 const sample_rate_info& info = kSampleRateInfos[i]; 1797 if ((rateMask & info.multiAudioRate) != 0) { 1798 frequencyParam->AddItem(info.multiAudioRate, 1799 BString(info.name) << " Hz"); 1800 } 1801 } 1802 } 1803 1804 1805 // #pragma mark - MultiAudioNode specific functions 1806 1807 1808 int32 1809 MultiAudioNode::_OutputThread() 1810 { 1811 CALLED(); 1812 multi_buffer_info bufferInfo; 1813 bufferInfo.info_size = sizeof(multi_buffer_info); 1814 bufferInfo.playback_buffer_cycle = 0; 1815 bufferInfo.record_buffer_cycle = 0; 1816 1817 // init the performance time computation 1818 { 1819 BAutolock locker(fBufferLock); 1820 fTimeComputer.Init(fOutputPreferredFormat.u.raw_audio.frame_rate, 1821 system_time()); 1822 } 1823 1824 while (atomic_get(&fQuitThread) == 0) { 1825 BAutolock locker(fBufferLock); 1826 // make sure the buffers don't change while we're playing with them 1827 1828 // send buffer 1829 fDevice->BufferExchange(&bufferInfo); 1830 1831 //PRINT(("MultiAudioNode::RunThread: buffer exchanged\n")); 1832 //PRINT(("MultiAudioNode::RunThread: played_real_time: %Ld\n", bufferInfo.played_real_time)); 1833 //PRINT(("MultiAudioNode::RunThread: played_frames_count: %Ld\n", bufferInfo.played_frames_count)); 1834 //PRINT(("MultiAudioNode::RunThread: buffer_cycle: %li\n", bufferInfo.playback_buffer_cycle)); 1835 1836 for (int32 i = 0; i < fInputs.CountItems(); i++) { 1837 node_input* input = (node_input*)fInputs.ItemAt(i); 1838 1839 if (bufferInfo.playback_buffer_cycle >= 0 1840 && bufferInfo.playback_buffer_cycle 1841 < fDevice->BufferList().return_playback_buffers 1842 && (input->fOldBufferCycle != bufferInfo.playback_buffer_cycle 1843 || fDevice->BufferList().return_playback_buffers == 1) 1844 && (input->fInput.source != media_source::null 1845 || input->fChannelId == 0)) { 1846 //PRINT(("playback_buffer_cycle ok input: %li %ld\n", i, bufferInfo.playback_buffer_cycle)); 1847 1848 input->fBufferCycle = (bufferInfo.playback_buffer_cycle - 1 1849 + fDevice->BufferList().return_playback_buffers) 1850 % fDevice->BufferList().return_playback_buffers; 1851 1852 // update the timesource 1853 if (input->fChannelId == 0) { 1854 //PRINT(("updating timesource\n")); 1855 _UpdateTimeSource(bufferInfo, *input); 1856 } 1857 1858 input->fOldBufferCycle = bufferInfo.playback_buffer_cycle; 1859 1860 if (input->fBuffer != NULL) { 1861 _FillNextBuffer(*input, input->fBuffer); 1862 input->fBuffer->Recycle(); 1863 input->fBuffer = NULL; 1864 } else { 1865 // put zeros in current buffer 1866 if (input->fInput.source != media_source::null) 1867 _WriteZeros(*input, input->fBufferCycle); 1868 //PRINT(("MultiAudioNode::Runthread WriteZeros\n")); 1869 } 1870 } else { 1871 //PRINT(("playback_buffer_cycle non ok input: %i\n", i)); 1872 } 1873 } 1874 1875 PRINT(("MultiAudioNode::RunThread: recorded_real_time: %" B_PRIdBIGTIME 1876 "\n", bufferInfo.recorded_real_time)); 1877 PRINT(("MultiAudioNode::RunThread: recorded_frames_count: %" 1878 B_PRId64 "\n", bufferInfo.recorded_frames_count)); 1879 PRINT(("MultiAudioNode::RunThread: record_buffer_cycle: %" B_PRIi32 1880 "\n", bufferInfo.record_buffer_cycle)); 1881 1882 for (int32 i = 0; i < fOutputs.CountItems(); i++) { 1883 node_output* output = (node_output*)fOutputs.ItemAt(i); 1884 1885 // make sure we're both started *and* connected before delivering a 1886 // buffer 1887 if (RunState() == BMediaEventLooper::B_STARTED 1888 && output->fOutput.destination != media_destination::null) { 1889 if (bufferInfo.record_buffer_cycle >= 0 1890 && bufferInfo.record_buffer_cycle 1891 < fDevice->BufferList().return_record_buffers 1892 && (output->fOldBufferCycle 1893 != bufferInfo.record_buffer_cycle 1894 || fDevice->BufferList().return_record_buffers == 1)) { 1895 //PRINT(("record_buffer_cycle ok\n")); 1896 1897 output->fBufferCycle = bufferInfo.record_buffer_cycle; 1898 1899 // Get the next buffer of data 1900 BBuffer* buffer = _FillNextBuffer(bufferInfo, *output); 1901 if (buffer != NULL) { 1902 // send the buffer downstream if and only if output is 1903 // enabled 1904 status_t err = B_ERROR; 1905 if (output->fOutputEnabled) { 1906 err = SendBuffer(buffer, output->fOutput.source, 1907 output->fOutput.destination); 1908 } 1909 if (err != B_OK) { 1910 buffer->Recycle(); 1911 } else { 1912 // track how much media we've delivered so far 1913 size_t numSamples 1914 = output->fOutput.format.u.raw_audio.buffer_size 1915 / (output->fOutput.format.u.raw_audio.format 1916 & media_raw_audio_format 1917 ::B_AUDIO_SIZE_MASK); 1918 output->fSamplesSent += numSamples; 1919 } 1920 } 1921 1922 output->fOldBufferCycle = bufferInfo.record_buffer_cycle; 1923 } else { 1924 //PRINT(("record_buffer_cycle non ok\n")); 1925 } 1926 } 1927 } 1928 } 1929 1930 return B_OK; 1931 } 1932 1933 1934 void 1935 MultiAudioNode::_WriteZeros(node_input& input, uint32 bufferCycle) 1936 { 1937 //CALLED(); 1938 /*int32 samples = input.fInput.format.u.raw_audio.buffer_size; 1939 if(input.fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_UCHAR) { 1940 uint8 *sample = (uint8*)fDevice->BufferList().playback_buffers[input.fBufferCycle][input.fChannelId].base; 1941 for(int32 i = samples-1; i>=0; i--) 1942 *sample++ = 128; 1943 } else { 1944 int32 *sample = (int32*)fDevice->BufferList().playback_buffers[input.fBufferCycle][input.fChannelId].base; 1945 for(int32 i = (samples / 4)-1; i>=0; i--) 1946 *sample++ = 0; 1947 }*/ 1948 1949 uint32 channelCount = input.fFormat.u.raw_audio.channel_count; 1950 uint32 bufferSize = fDevice->BufferList().return_playback_buffer_size; 1951 size_t stride = fDevice->BufferList().playback_buffers[bufferCycle] 1952 [input.fChannelId].stride; 1953 1954 switch (input.fFormat.u.raw_audio.format) { 1955 case media_raw_audio_format::B_AUDIO_FLOAT: 1956 for (uint32 channel = 0; channel < channelCount; channel++) { 1957 char* dest = _PlaybackBuffer(bufferCycle, 1958 input.fChannelId + channel); 1959 for (uint32 i = bufferSize; i > 0; i--) { 1960 *(float*)dest = 0; 1961 dest += stride; 1962 } 1963 } 1964 break; 1965 1966 case media_raw_audio_format::B_AUDIO_DOUBLE: 1967 for (uint32 channel = 0; channel < channelCount; channel++) { 1968 char* dest = _PlaybackBuffer(bufferCycle, 1969 input.fChannelId + channel); 1970 for (uint32 i = bufferSize; i > 0; i--) { 1971 *(double*)dest = 0; 1972 dest += stride; 1973 } 1974 } 1975 break; 1976 1977 case media_raw_audio_format::B_AUDIO_INT: 1978 for (uint32 channel = 0; channel < channelCount; channel++) { 1979 char* dest = _PlaybackBuffer(bufferCycle, 1980 input.fChannelId + channel); 1981 for (uint32 i = bufferSize; i > 0; i--) { 1982 *(int32*)dest = 0; 1983 dest += stride; 1984 } 1985 } 1986 break; 1987 1988 case media_raw_audio_format::B_AUDIO_SHORT: 1989 for (uint32 channel = 0; channel < channelCount; channel++) { 1990 char* dest = _PlaybackBuffer(bufferCycle, 1991 input.fChannelId + channel); 1992 for (uint32 i = bufferSize; i > 0; i--) { 1993 *(int16*)dest = 0; 1994 dest += stride; 1995 } 1996 } 1997 break; 1998 1999 case media_raw_audio_format::B_AUDIO_UCHAR: 2000 for (uint32 channel = 0; channel < channelCount; channel++) { 2001 char* dest = _PlaybackBuffer(bufferCycle, 2002 input.fChannelId + channel); 2003 for (uint32 i = bufferSize; i > 0; i--) { 2004 *(uint8*)dest = 128; 2005 dest += stride; 2006 } 2007 } 2008 break; 2009 2010 case media_raw_audio_format::B_AUDIO_CHAR: 2011 for (uint32 channel = 0; channel < channelCount; channel++) { 2012 char* dest = _PlaybackBuffer(bufferCycle, 2013 input.fChannelId + channel); 2014 for (uint32 i = bufferSize; i > 0; i--) { 2015 *(int8*)dest = 0; 2016 dest += stride; 2017 } 2018 } 2019 break; 2020 2021 default: 2022 fprintf(stderr, "ERROR in WriteZeros format not handled\n"); 2023 } 2024 } 2025 2026 2027 void 2028 MultiAudioNode::_FillWithZeros(node_input& input) 2029 { 2030 CALLED(); 2031 for (int32 i = 0; i < fDevice->BufferList().return_playback_buffers; i++) 2032 _WriteZeros(input, i); 2033 } 2034 2035 2036 void 2037 MultiAudioNode::_FillNextBuffer(node_input& input, BBuffer* buffer) 2038 { 2039 uint32 channelCount = input.fInput.format.u.raw_audio.channel_count; 2040 size_t inputSampleSize = input.fInput.format.u.raw_audio.format 2041 & media_raw_audio_format::B_AUDIO_SIZE_MASK; 2042 2043 uint32 bufferSize = fDevice->BufferList().return_playback_buffer_size; 2044 2045 if (buffer->SizeUsed() / inputSampleSize / channelCount != bufferSize) { 2046 _WriteZeros(input, input.fBufferCycle); 2047 return; 2048 } 2049 2050 if (channelCount != input.fFormat.u.raw_audio.channel_count) { 2051 PRINT(("Channel count is different")); 2052 return; 2053 } 2054 2055 if (input.fResampler != NULL) { 2056 size_t srcStride = channelCount * inputSampleSize; 2057 2058 for (uint32 channel = 0; channel < channelCount; channel++) { 2059 char* src = (char*)buffer->Data() + channel * inputSampleSize; 2060 char* dst = _PlaybackBuffer(input.fBufferCycle, 2061 input.fChannelId + channel); 2062 size_t dstStride = _PlaybackStride(input.fBufferCycle, 2063 input.fChannelId + channel); 2064 2065 input.fResampler->Resample(src, srcStride, 2066 dst, dstStride, bufferSize); 2067 } 2068 } 2069 } 2070 2071 2072 status_t 2073 MultiAudioNode::_StartOutputThreadIfNeeded() 2074 { 2075 CALLED(); 2076 // the thread is already started ? 2077 if (fThread >= 0) 2078 return B_OK; 2079 2080 PublishTime(-50, 0, 0); 2081 2082 fThread = spawn_thread(_OutputThreadEntry, "multi_audio audio output", 2083 B_REAL_TIME_PRIORITY, this); 2084 if (fThread < 0) 2085 return fThread; 2086 2087 resume_thread(fThread); 2088 return B_OK; 2089 } 2090 2091 2092 status_t 2093 MultiAudioNode::_StopOutputThread() 2094 { 2095 CALLED(); 2096 atomic_set(&fQuitThread, 1); 2097 2098 wait_for_thread(fThread, NULL); 2099 fThread = -1; 2100 return B_OK; 2101 } 2102 2103 2104 void 2105 MultiAudioNode::_AllocateBuffers(node_output &channel) 2106 { 2107 CALLED(); 2108 2109 // allocate enough buffers to span our downstream latency, plus one 2110 size_t size = channel.fOutput.format.u.raw_audio.buffer_size; 2111 int32 count = int32(fLatency / BufferDuration() + 1 + 1); 2112 2113 PRINT(("\tlatency = %" B_PRIdBIGTIME ", buffer duration = %" B_PRIdBIGTIME 2114 "\n", fLatency, BufferDuration())); 2115 PRINT(("\tcreating group of %" B_PRId32 " buffers, size = %" B_PRIuSIZE 2116 "\n", count, size)); 2117 channel.fBufferGroup = new BBufferGroup(size, count); 2118 } 2119 2120 2121 void 2122 MultiAudioNode::_UpdateTimeSource(multi_buffer_info& info, node_input& input) 2123 { 2124 //CALLED(); 2125 if (!fTimeSourceStarted) 2126 return; 2127 2128 fTimeComputer.AddTimeStamp(info.played_real_time, 2129 info.played_frames_count); 2130 PublishTime(fTimeComputer.PerformanceTime(), fTimeComputer.RealTime(), 2131 fTimeComputer.Drift()); 2132 } 2133 2134 2135 BBuffer* 2136 MultiAudioNode::_FillNextBuffer(multi_buffer_info& info, node_output& output) 2137 { 2138 //CALLED(); 2139 // get a buffer from our buffer group 2140 //PRINT(("buffer size: %i, buffer duration: %i\n", fOutput.format.u.raw_audio.buffer_size, BufferDuration())); 2141 //PRINT(("MBI.record_buffer_cycle: %i\n", MBI.record_buffer_cycle)); 2142 //PRINT(("MBI.recorded_real_time: %i\n", MBI.recorded_real_time)); 2143 //PRINT(("MBI.recorded_frames_count: %i\n", MBI.recorded_frames_count)); 2144 if (output.fBufferGroup == NULL) 2145 return NULL; 2146 2147 BBuffer* buffer = output.fBufferGroup->RequestBuffer( 2148 output.fOutput.format.u.raw_audio.buffer_size, BufferDuration()); 2149 if (buffer == NULL) { 2150 // If we fail to get a buffer (for example, if the request times out), 2151 // we skip this buffer and go on to the next, to avoid locking up the 2152 // control thread. 2153 fprintf(stderr, "Buffer is null"); 2154 return NULL; 2155 } 2156 2157 if (fDevice == NULL) 2158 fprintf(stderr, "fDevice NULL\n"); 2159 if (buffer->Header() == NULL) 2160 fprintf(stderr, "buffer->Header() NULL\n"); 2161 if (TimeSource() == NULL) 2162 fprintf(stderr, "TimeSource() NULL\n"); 2163 2164 uint32 channelCount = output.fOutput.format.u.raw_audio.channel_count; 2165 size_t outputSampleSize = output.fOutput.format.u.raw_audio.format 2166 & media_raw_audio_format::B_AUDIO_SIZE_MASK; 2167 2168 uint32 bufferSize = fDevice->BufferList().return_record_buffer_size; 2169 2170 if (output.fResampler != NULL) { 2171 size_t dstStride = channelCount * outputSampleSize; 2172 2173 uint32 channelId = output.fChannelId 2174 - fDevice->Description().output_channel_count; 2175 2176 for (uint32 channel = 0; channel < channelCount; channel++) { 2177 char* src = _RecordBuffer(output.fBufferCycle, 2178 channelId + channel); 2179 size_t srcStride = _RecordStride(output.fBufferCycle, 2180 channelId + channel); 2181 char* dst = (char*)buffer->Data() + channel * outputSampleSize; 2182 2183 output.fResampler->Resample(src, srcStride, dst, dstStride, 2184 bufferSize); 2185 } 2186 } 2187 2188 // fill in the buffer header 2189 media_header* header = buffer->Header(); 2190 header->type = B_MEDIA_RAW_AUDIO; 2191 header->size_used = output.fOutput.format.u.raw_audio.buffer_size; 2192 header->time_source = TimeSource()->ID(); 2193 header->start_time = PerformanceTimeFor(info.recorded_real_time); 2194 2195 return buffer; 2196 } 2197 2198 2199 status_t 2200 MultiAudioNode::GetConfigurationFor(BMessage* message) 2201 { 2202 CALLED(); 2203 if (message == NULL) 2204 return B_BAD_VALUE; 2205 2206 size_t bufferSize = 128; 2207 void* buffer = malloc(bufferSize); 2208 if (buffer == NULL) 2209 return B_NO_MEMORY; 2210 2211 for (int32 i = 0; i < fWeb->CountParameters(); i++) { 2212 BParameter* parameter = fWeb->ParameterAt(i); 2213 if (parameter->Type() != BParameter::B_CONTINUOUS_PARAMETER 2214 && parameter->Type() != BParameter::B_DISCRETE_PARAMETER) 2215 continue; 2216 2217 PRINT(("getting parameter %" B_PRIi32 "\n", parameter->ID())); 2218 size_t size = bufferSize; 2219 bigtime_t lastChange; 2220 status_t err; 2221 while ((err = GetParameterValue(parameter->ID(), &lastChange, buffer, 2222 &size)) == B_NO_MEMORY && bufferSize < 128 * 1024) { 2223 bufferSize += 128; 2224 free(buffer); 2225 buffer = malloc(bufferSize); 2226 if (buffer == NULL) 2227 return B_NO_MEMORY; 2228 } 2229 2230 if (err == B_OK && size > 0) { 2231 message->AddInt32("parameterID", parameter->ID()); 2232 message->AddData("parameterData", B_RAW_TYPE, buffer, size, false); 2233 } else { 2234 PRINT(("parameter err: %s\n", strerror(err))); 2235 } 2236 } 2237 2238 free(buffer); 2239 PRINT_OBJECT(*message); 2240 return B_OK; 2241 } 2242 2243 2244 node_output* 2245 MultiAudioNode::_FindOutput(media_source source) 2246 { 2247 node_output* channel = NULL; 2248 2249 for (int32 i = 0; i < fOutputs.CountItems(); i++) { 2250 channel = (node_output*)fOutputs.ItemAt(i); 2251 if (source == channel->fOutput.source) 2252 break; 2253 } 2254 2255 if (source != channel->fOutput.source) 2256 return NULL; 2257 2258 return channel; 2259 } 2260 2261 2262 node_input* 2263 MultiAudioNode::_FindInput(media_destination dest) 2264 { 2265 node_input* channel = NULL; 2266 2267 for (int32 i = 0; i < fInputs.CountItems(); i++) { 2268 channel = (node_input*)fInputs.ItemAt(i); 2269 if (dest == channel->fInput.destination) 2270 break; 2271 } 2272 2273 if (dest != channel->fInput.destination) 2274 return NULL; 2275 2276 return channel; 2277 } 2278 2279 2280 node_input* 2281 MultiAudioNode::_FindInput(int32 destinationId) 2282 { 2283 node_input* channel = NULL; 2284 2285 for (int32 i = 0; i < fInputs.CountItems(); i++) { 2286 channel = (node_input*)fInputs.ItemAt(i); 2287 if (destinationId == channel->fInput.destination.id) 2288 break; 2289 } 2290 2291 if (destinationId != channel->fInput.destination.id) 2292 return NULL; 2293 2294 return channel; 2295 } 2296 2297 2298 /*static*/ status_t 2299 MultiAudioNode::_OutputThreadEntry(void* data) 2300 { 2301 CALLED(); 2302 return static_cast<MultiAudioNode*>(data)->_OutputThread(); 2303 } 2304 2305 2306 status_t 2307 MultiAudioNode::_SetNodeInputFrameRate(float frameRate) 2308 { 2309 // check whether the frame rate is supported 2310 uint32 multiAudioRate = MultiAudio::convert_from_sample_rate(frameRate); 2311 if ((fDevice->Description().output_rates & multiAudioRate) == 0) 2312 return B_BAD_VALUE; 2313 2314 BAutolock locker(fBufferLock); 2315 2316 // already set? 2317 if (fDevice->FormatInfo().output.rate == multiAudioRate) 2318 return B_OK; 2319 2320 // set the frame rate on the device 2321 status_t error = fDevice->SetOutputFrameRate(multiAudioRate); 2322 if (error != B_OK) 2323 return error; 2324 2325 // it went fine -- update all formats 2326 fOutputPreferredFormat.u.raw_audio.frame_rate = frameRate; 2327 fOutputPreferredFormat.u.raw_audio.buffer_size 2328 = fDevice->BufferList().return_playback_buffer_size 2329 * (fOutputPreferredFormat.u.raw_audio.format 2330 & media_raw_audio_format::B_AUDIO_SIZE_MASK) 2331 * fOutputPreferredFormat.u.raw_audio.channel_count; 2332 2333 for (int32 i = 0; node_input* channel = (node_input*)fInputs.ItemAt(i); 2334 i++) { 2335 channel->fPreferredFormat.u.raw_audio.frame_rate = frameRate; 2336 channel->fPreferredFormat.u.raw_audio.buffer_size 2337 = fOutputPreferredFormat.u.raw_audio.buffer_size; 2338 2339 channel->fFormat.u.raw_audio.frame_rate = frameRate; 2340 channel->fFormat.u.raw_audio.buffer_size 2341 = fOutputPreferredFormat.u.raw_audio.buffer_size; 2342 2343 channel->fInput.format.u.raw_audio.frame_rate = frameRate; 2344 channel->fInput.format.u.raw_audio.buffer_size 2345 = fOutputPreferredFormat.u.raw_audio.buffer_size; 2346 } 2347 2348 // make sure the time base is reset 2349 fTimeComputer.SetFrameRate(frameRate); 2350 2351 // update internal latency 2352 _UpdateInternalLatency(fOutputPreferredFormat); 2353 2354 return B_OK; 2355 } 2356 2357 2358 status_t 2359 MultiAudioNode::_SetNodeOutputFrameRate(float frameRate) 2360 { 2361 // check whether the frame rate is supported 2362 uint32 multiAudioRate = MultiAudio::convert_from_sample_rate(frameRate); 2363 if ((fDevice->Description().input_rates & multiAudioRate) == 0) 2364 return B_BAD_VALUE; 2365 2366 BAutolock locker(fBufferLock); 2367 2368 // already set? 2369 if (fDevice->FormatInfo().input.rate == multiAudioRate) 2370 return B_OK; 2371 2372 // set the frame rate on the device 2373 status_t error = fDevice->SetInputFrameRate(multiAudioRate); 2374 if (error != B_OK) 2375 return error; 2376 2377 // it went fine -- update all formats 2378 fInputPreferredFormat.u.raw_audio.frame_rate = frameRate; 2379 fInputPreferredFormat.u.raw_audio.buffer_size 2380 = fDevice->BufferList().return_record_buffer_size 2381 * (fInputPreferredFormat.u.raw_audio.format 2382 & media_raw_audio_format::B_AUDIO_SIZE_MASK) 2383 * fInputPreferredFormat.u.raw_audio.channel_count; 2384 2385 for (int32 i = 0; node_output* channel = (node_output*)fOutputs.ItemAt(i); 2386 i++) { 2387 channel->fPreferredFormat.u.raw_audio.frame_rate = frameRate; 2388 channel->fPreferredFormat.u.raw_audio.buffer_size 2389 = fInputPreferredFormat.u.raw_audio.buffer_size; 2390 2391 channel->fFormat.u.raw_audio.frame_rate = frameRate; 2392 channel->fFormat.u.raw_audio.buffer_size 2393 = fInputPreferredFormat.u.raw_audio.buffer_size; 2394 2395 channel->fOutput.format.u.raw_audio.frame_rate = frameRate; 2396 channel->fOutput.format.u.raw_audio.buffer_size 2397 = fInputPreferredFormat.u.raw_audio.buffer_size; 2398 } 2399 2400 // make sure the time base is reset 2401 fTimeComputer.SetFrameRate(frameRate); 2402 2403 // update internal latency 2404 _UpdateInternalLatency(fInputPreferredFormat); 2405 2406 return B_OK; 2407 } 2408 2409 2410 void 2411 MultiAudioNode::_UpdateInternalLatency(const media_format& format) 2412 { 2413 // use half a buffer length latency 2414 fInternalLatency = format.u.raw_audio.buffer_size * 10000 / 2 2415 / ((format.u.raw_audio.format 2416 & media_raw_audio_format::B_AUDIO_SIZE_MASK) 2417 * format.u.raw_audio.channel_count) 2418 / ((int32)(format.u.raw_audio.frame_rate / 100)); 2419 2420 PRINT((" internal latency = %" B_PRIdBIGTIME "\n", fInternalLatency)); 2421 2422 SetEventLatency(fInternalLatency); 2423 } 2424