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