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