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 66status_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 101status_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 143status_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 175status_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 219status_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 266status_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 313void 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 367status_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 387void _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 407void _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 426void _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 490broadcast: 491 _broadcastOutputFormatParams(); 492} 493 494 495void 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 513void 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