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