xref: /haiku/src/apps/cortex/addons/AudioAdapter/AudioAdapterNode.cpp (revision 02354704729d38c3b078c696adc1bbbd33cbcf72)
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