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