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