1 /* 2 * Copyright (c) 1999-2000, Eric Moon. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions, and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions, and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 32 // AudioAdapterNode.cpp 33 34 #include "AudioAdapterNode.h" 35 #include "AudioAdapterParams.h" 36 37 #include "SoundUtils.h" 38 39 #include <cstdio> 40 #include <cstring> 41 42 // -------------------------------------------------------- // 43 // ctor/dtor 44 // -------------------------------------------------------- // 45 46 _AudioAdapterNode::~_AudioAdapterNode() {} 47 48 _AudioAdapterNode::_AudioAdapterNode( 49 const char* name, 50 IAudioOpFactory* opFactory, 51 BMediaAddOn* addOn) : 52 53 BMediaNode(name), 54 AudioFilterNode(name, opFactory, addOn) { 55 56 // PRINT(( 57 // "\n" 58 // "--*-- _AudioAdapterNode() [%s] --*--\n\n", 59 // __BUILD_DATE__)); 60 } 61 62 // -------------------------------------------------------- // 63 // AudioFilterNode 64 // -------------------------------------------------------- // 65 66 status_t _AudioAdapterNode::getRequiredInputFormat( 67 media_format& ioFormat) { 68 69 status_t err = getPreferredInputFormat(ioFormat); 70 if(err < B_OK) 71 return err; 72 73 // 16sep99: input byte-swapping now supported 74 ioFormat.u.raw_audio.byte_order = media_raw_audio_format::wildcard.byte_order; 75 76 // ioFormat.u.raw_audio.format = media_raw_audio_format::wildcard.format; 77 // ioFormat.u.raw_audio.channel_count = media_raw_audio_format::wildcard.channel_count; 78 _AudioAdapterParams* p = dynamic_cast<_AudioAdapterParams*>(parameterSet()); 79 ASSERT(p); 80 81 // media_raw_audio_format& w = media_raw_audio_format::wildcard; 82 83 // copy user preferences 84 ioFormat.u.raw_audio.format = p->inputFormat.format; 85 ioFormat.u.raw_audio.channel_count = p->inputFormat.channel_count; 86 87 88 // don't require a buffer size until format & channel_count are known [16sep99] 89 ioFormat.u.raw_audio.buffer_size = media_raw_audio_format::wildcard.buffer_size; 90 91 if(output().destination == media_destination::null) { 92 // frame rate isn't constrained yet 93 ioFormat.u.raw_audio.frame_rate = media_raw_audio_format::wildcard.frame_rate; 94 } 95 96 return B_OK; 97 } 98 99 // +++++ 17sep99: use parameter data! 100 101 status_t _AudioAdapterNode::getPreferredInputFormat( 102 media_format& ioFormat) { 103 104 status_t err = _inherited::getPreferredInputFormat(ioFormat); 105 if(err < B_OK) 106 return err; 107 108 _AudioAdapterParams* p = dynamic_cast<_AudioAdapterParams*>(parameterSet()); 109 ASSERT(p); 110 111 media_raw_audio_format& f = ioFormat.u.raw_audio; 112 const media_raw_audio_format& w = media_raw_audio_format::wildcard; 113 114 // copy user preferences 115 if(p->inputFormat.format != w.format) 116 f.format = p->inputFormat.format; 117 if(p->inputFormat.channel_count != w.channel_count) 118 f.channel_count = p->inputFormat.channel_count; 119 120 // // if one end is connected, prefer not to do channel conversions [15sep99] 121 // if(output().destination != media_destination::null) 122 // ioFormat.u.raw_audio.channel_count = output().format.u.raw_audio.channel_count; 123 124 // if output connected, constrain: 125 // buffer_size 126 // frame_rate 127 if(output().destination != media_destination::null) { 128 // if the user doesn't care, default to the output's frame format 129 if(f.format == w.format) 130 f.format = output().format.u.raw_audio.format; 131 if(f.channel_count == w.channel_count) 132 f.channel_count = output().format.u.raw_audio.channel_count; 133 134 f.buffer_size = 135 bytes_per_frame(f) * 136 frames_per_buffer(output().format.u.raw_audio); 137 f.frame_rate = output().format.u.raw_audio.frame_rate; 138 } 139 140 return B_OK; 141 } 142 143 status_t _AudioAdapterNode::getRequiredOutputFormat( 144 media_format& ioFormat) { 145 146 status_t err = getPreferredOutputFormat(ioFormat); 147 if(err < B_OK) 148 return err; 149 150 ioFormat.u.raw_audio.format = media_raw_audio_format::wildcard.format; 151 ioFormat.u.raw_audio.channel_count = media_raw_audio_format::wildcard.channel_count; 152 153 _AudioAdapterParams* p = dynamic_cast<_AudioAdapterParams*>(parameterSet()); 154 ASSERT(p); 155 156 // media_raw_audio_format& w = media_raw_audio_format::wildcard; 157 158 // copy user preferences 159 ioFormat.u.raw_audio.format = p->outputFormat.format; 160 ioFormat.u.raw_audio.channel_count = p->outputFormat.channel_count; 161 162 // don't require a buffer size until format & channel_count are known [16sep99] 163 ioFormat.u.raw_audio.buffer_size = media_raw_audio_format::wildcard.buffer_size; 164 165 if(input().source == media_source::null) { 166 // frame rate isn't constrained yet 167 ioFormat.u.raw_audio.frame_rate = media_raw_audio_format::wildcard.frame_rate; 168 } 169 170 return B_OK; 171 } 172 173 // +++++ 17sep99: use parameter data! 174 175 status_t _AudioAdapterNode::getPreferredOutputFormat( 176 media_format& ioFormat) { 177 178 status_t err = _inherited::getPreferredOutputFormat(ioFormat); 179 if(err < B_OK) 180 return err; 181 182 _AudioAdapterParams* p = dynamic_cast<_AudioAdapterParams*>(parameterSet()); 183 ASSERT(p); 184 185 const media_raw_audio_format& w = media_raw_audio_format::wildcard; 186 187 // copy user preferences 188 if(p->outputFormat.format != w.format) 189 ioFormat.u.raw_audio.format = p->outputFormat.format; 190 if(p->outputFormat.channel_count != w.channel_count) 191 ioFormat.u.raw_audio.channel_count = p->outputFormat.channel_count; 192 193 //// // if one end is connected, prefer not to do channel conversions [15sep99] 194 //// if(input().source != media_source::null) 195 //// ioFormat.u.raw_audio.channel_count = input().format.u.raw_audio.channel_count; 196 197 // if input connected, constrain: 198 // buffer_size 199 // frame_rate 200 if(input().source != media_source::null) { 201 // if the user doesn't care, default to the input's frame format 202 if(ioFormat.u.raw_audio.format == w.format) 203 ioFormat.u.raw_audio.format = input().format.u.raw_audio.format; 204 if(ioFormat.u.raw_audio.channel_count == w.channel_count) 205 ioFormat.u.raw_audio.channel_count = input().format.u.raw_audio.channel_count; 206 207 ioFormat.u.raw_audio.buffer_size = 208 bytes_per_frame(ioFormat.u.raw_audio) * 209 frames_per_buffer(input().format.u.raw_audio); 210 PRINT(("##### preferred output buffer_size: %ld (%" B_PRIxSIZE ")\n", ioFormat.u.raw_audio.buffer_size, ioFormat.u.raw_audio.buffer_size)); 211 ioFormat.u.raw_audio.frame_rate = input().format.u.raw_audio.frame_rate; 212 213 } 214 215 216 return B_OK; 217 } 218 219 status_t _AudioAdapterNode::validateProposedInputFormat( 220 const media_format& preferredFormat, 221 media_format& ioProposedFormat) { 222 223 status_t err = _inherited::validateProposedInputFormat( 224 preferredFormat, ioProposedFormat); 225 226 const media_raw_audio_format& w = media_raw_audio_format::wildcard; 227 228 if(output().destination != media_destination::null) { 229 230 // an output connection exists; constrain the input format 231 232 // is there enough information to suggest a buffer size? 233 if( 234 ioProposedFormat.u.raw_audio.format != w.format && 235 ioProposedFormat.u.raw_audio.channel_count != w.channel_count) { 236 237 size_t target_buffer_size = 238 bytes_per_frame(ioProposedFormat.u.raw_audio) * 239 frames_per_buffer(output().format.u.raw_audio); 240 241 if(ioProposedFormat.u.raw_audio.buffer_size != target_buffer_size) { 242 if(ioProposedFormat.u.raw_audio.buffer_size != w.buffer_size) 243 err = B_MEDIA_BAD_FORMAT; 244 245 ioProposedFormat.u.raw_audio.buffer_size = target_buffer_size; 246 } 247 } 248 249 // require output frame rate 250 if(ioProposedFormat.u.raw_audio.frame_rate != output().format.u.raw_audio.frame_rate) { 251 if(ioProposedFormat.u.raw_audio.frame_rate != w.frame_rate) 252 err = B_MEDIA_BAD_FORMAT; 253 254 ioProposedFormat.u.raw_audio.frame_rate = output().format.u.raw_audio.frame_rate; 255 } 256 } 257 258 char fmt_string[256]; 259 string_for_format(ioProposedFormat, fmt_string, 255); 260 PRINT(( 261 "### _AudioAdapterNode::validateProposedInputFormat():\n" 262 " %s\n", fmt_string)); 263 return err; 264 } 265 266 status_t _AudioAdapterNode::validateProposedOutputFormat( 267 const media_format& preferredFormat, 268 media_format& ioProposedFormat) { 269 270 status_t err = _inherited::validateProposedOutputFormat( 271 preferredFormat, ioProposedFormat); 272 273 const media_raw_audio_format& w = media_raw_audio_format::wildcard; 274 275 if(input().source != media_source::null) { 276 277 // an input connection exists; constrain the output format 278 279 // is there enough information to suggest a buffer size? 280 if( 281 ioProposedFormat.u.raw_audio.format != w.format && 282 ioProposedFormat.u.raw_audio.channel_count != w.channel_count) { 283 284 size_t target_buffer_size = 285 bytes_per_frame(ioProposedFormat.u.raw_audio) * 286 frames_per_buffer(input().format.u.raw_audio); 287 288 if(ioProposedFormat.u.raw_audio.buffer_size != target_buffer_size) { 289 if(ioProposedFormat.u.raw_audio.buffer_size != w.buffer_size) 290 err = B_MEDIA_BAD_FORMAT; 291 292 ioProposedFormat.u.raw_audio.buffer_size = target_buffer_size; 293 } 294 } 295 296 // require same frame rate as input 297 if(ioProposedFormat.u.raw_audio.frame_rate != input().format.u.raw_audio.frame_rate) { 298 if(ioProposedFormat.u.raw_audio.frame_rate != w.frame_rate) 299 err = B_MEDIA_BAD_FORMAT; 300 301 ioProposedFormat.u.raw_audio.frame_rate = input().format.u.raw_audio.frame_rate; 302 } 303 } 304 305 char fmt_string[256]; 306 string_for_format(ioProposedFormat, fmt_string, 255); 307 PRINT(( 308 "### _AudioAdapterNode::validateProposedOutputFormat():\n" 309 " %s\n", fmt_string)); 310 return err; 311 } 312 313 void 314 _AudioAdapterNode::SetParameterValue(int32 id, bigtime_t changeTime, const void *value, size_t size) 315 { 316 switch(id) { 317 case _AudioAdapterParams::P_INPUT_FORMAT: 318 if(input().source != media_source::null) { 319 media_multi_audio_format f = input().format.u.raw_audio; 320 if(size != 4) 321 return; 322 f.format = *(uint32*)value; 323 _attemptInputFormatChange(f); 324 return; 325 } 326 break; 327 case _AudioAdapterParams::P_INPUT_CHANNEL_COUNT: 328 if(input().source != media_source::null) { 329 media_multi_audio_format f = input().format.u.raw_audio; 330 if(size != 4) 331 return; 332 f.channel_count = *(uint32*)value; 333 _attemptInputFormatChange(f); 334 return; 335 } 336 break; 337 case _AudioAdapterParams::P_OUTPUT_FORMAT: 338 if(output().source != media_source::null) { 339 media_multi_audio_format f = output().format.u.raw_audio; 340 if(size != 4) 341 return; 342 f.format = *(uint32*)value; 343 _attemptOutputFormatChange(f); 344 return; 345 } 346 break; 347 case _AudioAdapterParams::P_OUTPUT_CHANNEL_COUNT: 348 if(output().source != media_source::null) { 349 media_multi_audio_format f = output().format.u.raw_audio; 350 if(size != 4) 351 return; 352 f.channel_count = *(uint32*)value; 353 _attemptOutputFormatChange(f); 354 return; 355 } 356 break; 357 } 358 359 return _inherited::SetParameterValue(id, changeTime, value, size); 360 } 361 362 363 // -------------------------------------------------------- // 364 // BBufferProducer/Consumer 365 // -------------------------------------------------------- // 366 367 status_t _AudioAdapterNode::Connected( 368 const media_source& source, 369 const media_destination& destination, 370 const media_format& format, 371 media_input* outInput) { 372 373 status_t err = _inherited::Connected( 374 source, destination, format, outInput); 375 376 if(err == B_OK) { 377 _AudioAdapterParams* p = dynamic_cast<_AudioAdapterParams*>(parameterSet()); 378 ASSERT(p); 379 p->inputFormat = format.u.raw_audio; 380 381 _broadcastInputFormatParams(); 382 } 383 384 return err; 385 } 386 387 void _AudioAdapterNode::Connect( 388 status_t status, 389 const media_source& source, 390 const media_destination& destination, 391 const media_format& format, 392 char* ioName) { 393 394 if(status == B_OK) { 395 _AudioAdapterParams* p = dynamic_cast<_AudioAdapterParams*>(parameterSet()); 396 ASSERT(p); 397 p->outputFormat = format.u.raw_audio; 398 399 _broadcastOutputFormatParams(); 400 } 401 402 _inherited::Connect( 403 status, source, destination, format, ioName); 404 } 405 406 407 void _AudioAdapterNode::_attemptInputFormatChange( 408 const media_multi_audio_format& format) { 409 // +++++ 410 411 char fmtString[256]; 412 media_format f; 413 f.type = B_MEDIA_RAW_AUDIO; 414 f.u.raw_audio = format; 415 string_for_format(f, fmtString, 256); 416 PRINT(( 417 "_AudioAdapterNode::attemptInputFormatChange():\n '%s'\n", 418 fmtString)); 419 420 421 422 // +++++ reject attempt: broadcast params for current format 423 _broadcastInputFormatParams(); 424 } 425 426 void _AudioAdapterNode::_attemptOutputFormatChange( 427 const media_multi_audio_format& format) { 428 429 // +++++ 430 char fmtString[256]; 431 media_format f; 432 f.type = B_MEDIA_RAW_AUDIO; 433 f.u.raw_audio = format; 434 string_for_format(f, fmtString, 256); 435 PRINT(( 436 "_AudioAdapterNode::attemptOutputFormatChange():\n '%s'\n", 437 fmtString)); 438 439 media_destination dest = output().destination; 440 if(dest == media_destination::null) { 441 PRINT(( 442 "! output not connected!\n")); 443 return; 444 } 445 446 _AudioAdapterParams* p = dynamic_cast<_AudioAdapterParams*>(parameterSet()); 447 ASSERT(p); 448 status_t err; 449 450 // disallow wildcards 451 if(format.format == media_raw_audio_format::wildcard.format || 452 format.channel_count == media_raw_audio_format::wildcard.channel_count) { 453 PRINT(( 454 "! wildcards not allowed\n")); 455 goto broadcast; 456 } 457 458 err = prepareFormatChange(f); 459 if(err < B_OK) 460 { 461 PRINT(( 462 "! format not supported\n")); 463 goto broadcast; 464 } 465 466 err = ProposeFormatChange(&f, dest); 467 if(err < B_OK) 468 { 469 PRINT(( 470 "! format rejected\n")); 471 goto broadcast; 472 } 473 474 err = ChangeFormat( 475 output().source, 476 dest, 477 &f); 478 479 if(err < B_OK) { 480 PRINT(("! ChangeFormat(): %s\n", strerror(err))); 481 goto broadcast; 482 } 483 484 // store new format 485 p->outputFormat = format; 486 487 // inform AudioFilterNode of format change 488 doFormatChange(f); 489 490 broadcast: 491 _broadcastOutputFormatParams(); 492 } 493 494 495 void 496 _AudioAdapterNode::_broadcastInputFormatParams() 497 { 498 PRINT(("_AudioAdapterNode::_broadcastInputFormatParams()\n")); 499 BroadcastNewParameterValue( 500 0LL, 501 _AudioAdapterParams::P_INPUT_FORMAT, 502 (void*)&input().format.u.raw_audio.format, 503 4); 504 BroadcastNewParameterValue( 505 0LL, 506 _AudioAdapterParams::P_INPUT_CHANNEL_COUNT, 507 (void*)&input().format.u.raw_audio.channel_count, 508 4); 509 // BroadcastChangedParameter(_AudioAdapterParams::P_INPUT_FORMAT); 510 // BroadcastChangedParameter(_AudioAdapterParams::P_INPUT_CHANNEL_COUNT); 511 } 512 513 void 514 _AudioAdapterNode::_broadcastOutputFormatParams() 515 { 516 PRINT(("_AudioAdapterNode::_broadcastOutputFormatParams()\n")); 517 518 BroadcastNewParameterValue( 519 0LL, 520 _AudioAdapterParams::P_OUTPUT_FORMAT, 521 (void*)&output().format.u.raw_audio.format, 522 4); 523 BroadcastNewParameterValue( 524 0LL, 525 _AudioAdapterParams::P_OUTPUT_CHANNEL_COUNT, 526 (void*)&output().format.u.raw_audio.channel_count, 527 4); 528 // BroadcastChangedParameter(_AudioAdapterParams::P_OUTPUT_FORMAT); 529 // BroadcastChangedParameter(_AudioAdapterParams::P_OUTPUT_CHANNEL_COUNT); 530 } 531 532 533 534 // END -- AudioAdapterNode.cpp -- 535