repository_infos: Enable automatic updates on the main Haiku repostiory.
[haiku.git] / src / apps / cortex / addons / AudioAdapter / AudioAdapterNode.cpp
blobf85ca3db793abc141947af0f512fce2f8066a4b7
1 /*
2 * Copyright (c) 1999-2000, Eric Moon.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
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.
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.
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.
32 // AudioAdapterNode.cpp
34 #include "AudioAdapterNode.h"
35 #include "AudioAdapterParams.h"
37 #include "SoundUtils.h"
39 #include <cstdio>
40 #include <cstring>
42 // -------------------------------------------------------- //
43 // ctor/dtor
44 // -------------------------------------------------------- //
46 _AudioAdapterNode::~_AudioAdapterNode() {}
48 _AudioAdapterNode::_AudioAdapterNode(
49 const char* name,
50 IAudioOpFactory* opFactory,
51 BMediaAddOn* addOn) :
53 BMediaNode(name),
54 AudioFilterNode(name, opFactory, addOn) {
56 // PRINT((
57 // "\n"
58 // "--*-- _AudioAdapterNode() [%s] --*--\n\n",
59 // __BUILD_DATE__));
62 // -------------------------------------------------------- //
63 // AudioFilterNode
64 // -------------------------------------------------------- //
66 status_t _AudioAdapterNode::getRequiredInputFormat(
67 media_format& ioFormat) {
69 status_t err = getPreferredInputFormat(ioFormat);
70 if(err < B_OK)
71 return err;
73 // 16sep99: input byte-swapping now supported
74 ioFormat.u.raw_audio.byte_order = media_raw_audio_format::wildcard.byte_order;
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);
81 // media_raw_audio_format& w = media_raw_audio_format::wildcard;
83 // copy user preferences
84 ioFormat.u.raw_audio.format = p->inputFormat.format;
85 ioFormat.u.raw_audio.channel_count = p->inputFormat.channel_count;
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;
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;
96 return B_OK;
99 // +++++ 17sep99: use parameter data!
101 status_t _AudioAdapterNode::getPreferredInputFormat(
102 media_format& ioFormat) {
104 status_t err = _inherited::getPreferredInputFormat(ioFormat);
105 if(err < B_OK)
106 return err;
108 _AudioAdapterParams* p = dynamic_cast<_AudioAdapterParams*>(parameterSet());
109 ASSERT(p);
111 media_raw_audio_format& f = ioFormat.u.raw_audio;
112 media_raw_audio_format& w = media_raw_audio_format::wildcard;
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;
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;
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;
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;
140 return B_OK;
143 status_t _AudioAdapterNode::getRequiredOutputFormat(
144 media_format& ioFormat) {
146 status_t err = getPreferredOutputFormat(ioFormat);
147 if(err < B_OK)
148 return err;
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;
153 _AudioAdapterParams* p = dynamic_cast<_AudioAdapterParams*>(parameterSet());
154 ASSERT(p);
156 // media_raw_audio_format& w = media_raw_audio_format::wildcard;
158 // copy user preferences
159 ioFormat.u.raw_audio.format = p->outputFormat.format;
160 ioFormat.u.raw_audio.channel_count = p->outputFormat.channel_count;
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;
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;
170 return B_OK;
173 // +++++ 17sep99: use parameter data!
175 status_t _AudioAdapterNode::getPreferredOutputFormat(
176 media_format& ioFormat) {
178 status_t err = _inherited::getPreferredOutputFormat(ioFormat);
179 if(err < B_OK)
180 return err;
182 _AudioAdapterParams* p = dynamic_cast<_AudioAdapterParams*>(parameterSet());
183 ASSERT(p);
185 media_raw_audio_format& w = media_raw_audio_format::wildcard;
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;
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;
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;
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;
216 return B_OK;
219 status_t _AudioAdapterNode::validateProposedInputFormat(
220 const media_format& preferredFormat,
221 media_format& ioProposedFormat) {
223 status_t err = _inherited::validateProposedInputFormat(
224 preferredFormat, ioProposedFormat);
226 media_raw_audio_format& w = media_raw_audio_format::wildcard;
228 if(output().destination != media_destination::null) {
230 // an output connection exists; constrain the input format
232 // is there enough information to suggest a buffer size?
234 ioProposedFormat.u.raw_audio.format != w.format &&
235 ioProposedFormat.u.raw_audio.channel_count != w.channel_count) {
237 size_t target_buffer_size =
238 bytes_per_frame(ioProposedFormat.u.raw_audio) *
239 frames_per_buffer(output().format.u.raw_audio);
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;
245 ioProposedFormat.u.raw_audio.buffer_size = target_buffer_size;
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;
254 ioProposedFormat.u.raw_audio.frame_rate = output().format.u.raw_audio.frame_rate;
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;
266 status_t _AudioAdapterNode::validateProposedOutputFormat(
267 const media_format& preferredFormat,
268 media_format& ioProposedFormat) {
270 status_t err = _inherited::validateProposedOutputFormat(
271 preferredFormat, ioProposedFormat);
273 media_raw_audio_format& w = media_raw_audio_format::wildcard;
275 if(input().source != media_source::null) {
277 // an input connection exists; constrain the output format
279 // is there enough information to suggest a buffer size?
281 ioProposedFormat.u.raw_audio.format != w.format &&
282 ioProposedFormat.u.raw_audio.channel_count != w.channel_count) {
284 size_t target_buffer_size =
285 bytes_per_frame(ioProposedFormat.u.raw_audio) *
286 frames_per_buffer(input().format.u.raw_audio);
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;
292 ioProposedFormat.u.raw_audio.buffer_size = target_buffer_size;
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;
301 ioProposedFormat.u.raw_audio.frame_rate = input().format.u.raw_audio.frame_rate;
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;
313 void
314 _AudioAdapterNode::SetParameterValue(int32 id, bigtime_t changeTime, const void *value, size_t size)
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;
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;
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;
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;
356 break;
359 return _inherited::SetParameterValue(id, changeTime, value, size);
363 // -------------------------------------------------------- //
364 // BBufferProducer/Consumer
365 // -------------------------------------------------------- //
367 status_t _AudioAdapterNode::Connected(
368 const media_source& source,
369 const media_destination& destination,
370 const media_format& format,
371 media_input* outInput) {
373 status_t err = _inherited::Connected(
374 source, destination, format, outInput);
376 if(err == B_OK) {
377 _AudioAdapterParams* p = dynamic_cast<_AudioAdapterParams*>(parameterSet());
378 ASSERT(p);
379 p->inputFormat = format.u.raw_audio;
381 _broadcastInputFormatParams();
384 return err;
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) {
394 if(status == B_OK) {
395 _AudioAdapterParams* p = dynamic_cast<_AudioAdapterParams*>(parameterSet());
396 ASSERT(p);
397 p->outputFormat = format.u.raw_audio;
399 _broadcastOutputFormatParams();
402 _inherited::Connect(
403 status, source, destination, format, ioName);
407 void _AudioAdapterNode::_attemptInputFormatChange(
408 const media_multi_audio_format& format) {
409 // +++++
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));
422 // +++++ reject attempt: broadcast params for current format
423 _broadcastInputFormatParams();
426 void _AudioAdapterNode::_attemptOutputFormatChange(
427 const media_multi_audio_format& format) {
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));
439 media_destination dest = output().destination;
440 if(dest == media_destination::null) {
441 PRINT((
442 "! output not connected!\n"));
443 return;
446 _AudioAdapterParams* p = dynamic_cast<_AudioAdapterParams*>(parameterSet());
447 ASSERT(p);
448 status_t err;
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;
458 err = prepareFormatChange(f);
459 if(err < B_OK)
461 PRINT((
462 "! format not supported\n"));
463 goto broadcast;
466 err = ProposeFormatChange(&f, dest);
467 if(err < B_OK)
469 PRINT((
470 "! format rejected\n"));
471 goto broadcast;
474 err = ChangeFormat(
475 output().source,
476 dest,
477 &f);
479 if(err < B_OK) {
480 PRINT(("! ChangeFormat(): %s\n", strerror(err)));
481 goto broadcast;
484 // store new format
485 p->outputFormat = format;
487 // inform AudioFilterNode of format change
488 doFormatChange(f);
490 broadcast:
491 _broadcastOutputFormatParams();
495 void
496 _AudioAdapterNode::_broadcastInputFormatParams()
498 PRINT(("_AudioAdapterNode::_broadcastInputFormatParams()\n"));
499 BroadcastNewParameterValue(
500 0LL,
501 _AudioAdapterParams::P_INPUT_FORMAT,
502 (void*)&input().format.u.raw_audio.format,
504 BroadcastNewParameterValue(
505 0LL,
506 _AudioAdapterParams::P_INPUT_CHANNEL_COUNT,
507 (void*)&input().format.u.raw_audio.channel_count,
509 // BroadcastChangedParameter(_AudioAdapterParams::P_INPUT_FORMAT);
510 // BroadcastChangedParameter(_AudioAdapterParams::P_INPUT_CHANNEL_COUNT);
513 void
514 _AudioAdapterNode::_broadcastOutputFormatParams()
516 PRINT(("_AudioAdapterNode::_broadcastOutputFormatParams()\n"));
518 BroadcastNewParameterValue(
519 0LL,
520 _AudioAdapterParams::P_OUTPUT_FORMAT,
521 (void*)&output().format.u.raw_audio.format,
523 BroadcastNewParameterValue(
524 0LL,
525 _AudioAdapterParams::P_OUTPUT_CHANNEL_COUNT,
526 (void*)&output().format.u.raw_audio.channel_count,
528 // BroadcastChangedParameter(_AudioAdapterParams::P_OUTPUT_FORMAT);
529 // BroadcastChangedParameter(_AudioAdapterParams::P_OUTPUT_CHANNEL_COUNT);
534 // END -- AudioAdapterNode.cpp --