1/*
2 * Copyright (c) 2002, 2003 Jerome Duval (jerome.duval@free.fr)
3 * Distributed under the terms of the MIT License.
4 */
5
6//! Multi-audio replacement media addon for BeOS
7
8
9#include "MultiAudioNode.h"
10
11#include <stdio.h>
12#include <string.h>
13
14#include <Autolock.h>
15#include <Buffer.h>
16#include <BufferGroup.h>
17#include <Catalog.h>
18#include <ParameterWeb.h>
19#include <String.h>
20
21#include <Referenceable.h>
22
23#include "MultiAudioUtility.h"
24#ifdef DEBUG
25#	define PRINTING
26#endif
27#include "debug.h"
28#include "Resampler.h"
29
30#undef B_TRANSLATION_CONTEXT
31#define B_TRANSLATION_CONTEXT "MultiAudio"
32
33#define PARAMETER_ID_INPUT_FREQUENCY	1
34#define PARAMETER_ID_OUTPUT_FREQUENCY	2
35
36
37//This represent an hardware output
38class node_input {
39public:
40	node_input(media_input& input, media_format format);
41	~node_input();
42
43	int32				fChannelId;
44	media_input			fInput;
45	media_format 		fPreferredFormat;
46	media_format		fFormat;
47	volatile uint32		fBufferCycle;
48	multi_buffer_info	fOldBufferInfo;
49	BBuffer*			fBuffer;
50	Resampler			*fResampler;
51};
52
53
54//This represent an hardware input
55class node_output {
56public:
57	node_output(media_output& output, media_format format);
58	~node_output();
59
60	int32				fChannelId;
61	media_output		fOutput;
62	media_format 		fPreferredFormat;
63	media_format		fFormat;
64
65	BBufferGroup*		fBufferGroup;
66	bool 				fOutputEnabled;
67	uint64 				fSamplesSent;
68	volatile uint32 	fBufferCycle;
69	multi_buffer_info	fOldBufferInfo;
70	Resampler			*fResampler;
71};
72
73
74struct FrameRateChangeCookie : public BReferenceable {
75	float	oldFrameRate;
76	uint32	id;
77};
78
79
80struct sample_rate_info {
81	uint32		multiAudioRate;
82	const char*	name;
83};
84
85
86static const sample_rate_info kSampleRateInfos[] = {
87	{B_SR_8000,		"8000"},
88	{B_SR_11025,	"11025"},
89	{B_SR_12000,	"12000"},
90	{B_SR_16000,	"16000"},
91	{B_SR_22050,	"22050"},
92	{B_SR_24000,	"24000"},
93	{B_SR_32000,	"32000"},
94	{B_SR_44100,	"44100"},
95	{B_SR_48000,	"48000"},
96	{B_SR_64000,	"64000"},
97	{B_SR_88200,	"88200"},
98	{B_SR_96000,	"96000"},
99	{B_SR_176400,	"176400"},
100	{B_SR_192000,	"192000"},
101	{B_SR_384000,	"384000"},
102	{B_SR_1536000,	"1536000"},
103	{}
104};
105
106
107const char* kMultiControlString[] = {
108	"NAME IS ATTACHED",
109	B_TRANSLATE("Output"), B_TRANSLATE("Input"), B_TRANSLATE("Setup"),
110	B_TRANSLATE("Tone control"), B_TRANSLATE("Extended Setup"),
111	B_TRANSLATE("Enhanced Setup"), B_TRANSLATE("Master"), B_TRANSLATE("Beep"),
112	B_TRANSLATE("Phone"), B_TRANSLATE("Mic"), B_TRANSLATE("Line"),
113	B_TRANSLATE("CD"), B_TRANSLATE("Video"), B_TRANSLATE("Aux"),
114	B_TRANSLATE("Wave"), B_TRANSLATE("Gain"), B_TRANSLATE("Level"),
115	B_TRANSLATE("Volume"), B_TRANSLATE("Mute"), B_TRANSLATE("Enable"),
116	B_TRANSLATE("Stereo mix"), B_TRANSLATE("Mono mix"),
117	B_TRANSLATE("Output stereo mix"), B_TRANSLATE("Output mono mix"),
118	B_TRANSLATE("Output bass"), B_TRANSLATE("Output treble"),
119	B_TRANSLATE("Output 3D center"), B_TRANSLATE("Output 3D depth"),
120	B_TRANSLATE("Headphones"), B_TRANSLATE("SPDIF")
121};
122
123
124//	#pragma mark -
125
126
127node_input::node_input(media_input& input, media_format format)
128{
129	CALLED();
130	fInput = input;
131	fPreferredFormat = format;
132	fBufferCycle = 1;
133	fBuffer = NULL;
134	fResampler = NULL;
135}
136
137
138node_input::~node_input()
139{
140	CALLED();
141}
142
143
144//	#pragma mark -
145
146
147node_output::node_output(media_output& output, media_format format)
148	:
149	fBufferGroup(NULL),
150	fOutputEnabled(true)
151{
152	CALLED();
153	fOutput = output;
154	fPreferredFormat = format;
155	fBufferCycle = 1;
156	fResampler = NULL;
157}
158
159
160node_output::~node_output()
161{
162	CALLED();
163}
164
165
166//	#pragma mark -
167
168
169MultiAudioNode::MultiAudioNode(BMediaAddOn* addon, const char* name,
170		MultiAudioDevice* device, int32 internalID, BMessage* config)
171	: BMediaNode(name), BBufferConsumer(B_MEDIA_RAW_AUDIO),
172	BBufferProducer(B_MEDIA_RAW_AUDIO),
173	fBufferLock("multi audio buffers"),
174	fThread(-1),
175	fDevice(device),
176	fTimeSourceStarted(false),
177	fWeb(NULL),
178	fConfig()
179{
180	CALLED();
181	fInitStatus = B_NO_INIT;
182
183	if (!device)
184		return;
185
186	fAddOn = addon;
187	fId = internalID;
188
189	AddNodeKind(B_PHYSICAL_OUTPUT);
190	AddNodeKind(B_PHYSICAL_INPUT);
191
192	// initialize our preferred format objects
193	memset(&fOutputPreferredFormat, 0, sizeof(fOutputPreferredFormat)); // set everything to wildcard first
194	fOutputPreferredFormat.type = B_MEDIA_RAW_AUDIO;
195	fOutputPreferredFormat.u.raw_audio.format = MultiAudio::convert_to_media_format(fDevice->FormatInfo().output.format);
196	fOutputPreferredFormat.u.raw_audio.valid_bits = MultiAudio::convert_to_valid_bits(fDevice->FormatInfo().output.format);
197	fOutputPreferredFormat.u.raw_audio.channel_count = 2;
198	fOutputPreferredFormat.u.raw_audio.frame_rate = MultiAudio::convert_to_sample_rate(fDevice->FormatInfo().output.rate);		// measured in Hertz
199	fOutputPreferredFormat.u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;
200
201	// we'll use the consumer's preferred buffer size, if any
202	fOutputPreferredFormat.u.raw_audio.buffer_size = fDevice->BufferList().return_playback_buffer_size
203		* (fOutputPreferredFormat.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK)
204		* fOutputPreferredFormat.u.raw_audio.channel_count;
205
206	// initialize our preferred format objects
207	memset(&fInputPreferredFormat, 0, sizeof(fInputPreferredFormat)); // set everything to wildcard first
208	fInputPreferredFormat.type = B_MEDIA_RAW_AUDIO;
209	fInputPreferredFormat.u.raw_audio.format = MultiAudio::convert_to_media_format(fDevice->FormatInfo().input.format);
210	fInputPreferredFormat.u.raw_audio.valid_bits = MultiAudio::convert_to_valid_bits(fDevice->FormatInfo().input.format);
211	fInputPreferredFormat.u.raw_audio.channel_count = 2;
212	fInputPreferredFormat.u.raw_audio.frame_rate = MultiAudio::convert_to_sample_rate(fDevice->FormatInfo().input.rate);		// measured in Hertz
213	fInputPreferredFormat.u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;
214
215	// we'll use the consumer's preferred buffer size, if any
216	fInputPreferredFormat.u.raw_audio.buffer_size = fDevice->BufferList().return_record_buffer_size
217		* (fInputPreferredFormat.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK)
218		* fInputPreferredFormat.u.raw_audio.channel_count;
219
220
221	if (config != NULL) {
222		fConfig = *config;
223		PRINT_OBJECT(*config);
224	}
225
226	fInitStatus = B_OK;
227}
228
229
230MultiAudioNode::~MultiAudioNode()
231{
232	CALLED();
233	fAddOn->GetConfigurationFor(this, NULL);
234
235	_StopOutputThread();
236	BMediaEventLooper::Quit();
237
238	fWeb = NULL;
239}
240
241
242status_t
243MultiAudioNode::InitCheck() const
244{
245	CALLED();
246	return fInitStatus;
247}
248
249
250void
251MultiAudioNode::GetFlavor(flavor_info* info, int32 id)
252{
253	CALLED();
254	if (info == NULL)
255		return;
256
257	info->flavor_flags = 0;
258	info->possible_count = 1;	// one flavor at a time
259	info->in_format_count = 0; // no inputs
260	info->in_formats = 0;
261	info->out_format_count = 0; // no outputs
262	info->out_formats = 0;
263	info->internal_id = id;
264
265	info->name = (char*)"MultiAudioNode Node";
266	info->info = (char*)"The MultiAudioNode node outputs to multi_audio "
267		"drivers.";
268	info->kinds = B_BUFFER_CONSUMER | B_BUFFER_PRODUCER | B_TIME_SOURCE
269		| B_PHYSICAL_OUTPUT | B_PHYSICAL_INPUT | B_CONTROLLABLE;
270	info->in_format_count = 1; // 1 input
271	media_format* inFormats = new media_format[info->in_format_count];
272	GetFormat(&inFormats[0]);
273	info->in_formats = inFormats;
274
275	info->out_format_count = 1; // 1 output
276	media_format* outFormats = new media_format[info->out_format_count];
277	GetFormat(&outFormats[0]);
278	info->out_formats = outFormats;
279}
280
281
282void
283MultiAudioNode::GetFormat(media_format* format)
284{
285	CALLED();
286	if (format == NULL)
287		return;
288
289	format->type = B_MEDIA_RAW_AUDIO;
290	format->require_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
291	format->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
292	format->u.raw_audio = media_raw_audio_format::wildcard;
293}
294
295
296//#pragma mark - BMediaNode
297
298
299BMediaAddOn*
300MultiAudioNode::AddOn(int32* _internalID) const
301{
302	CALLED();
303	// BeBook says this only gets called if we were in an add-on.
304	if (fAddOn != 0 && _internalID != NULL)
305		*_internalID = fId;
306
307	return fAddOn;
308}
309
310
311void
312MultiAudioNode::Preroll()
313{
314	CALLED();
315	// XXX:Performance opportunity
316	BMediaNode::Preroll();
317}
318
319
320status_t
321MultiAudioNode::HandleMessage(int32 message, const void* data, size_t size)
322{
323	CALLED();
324	return B_ERROR;
325}
326
327
328void
329MultiAudioNode::NodeRegistered()
330{
331	CALLED();
332
333	if (fInitStatus != B_OK) {
334		ReportError(B_NODE_IN_DISTRESS);
335		return;
336	}
337
338	SetPriority(B_REAL_TIME_PRIORITY);
339	Run();
340
341	node_input *currentInput = NULL;
342	int32 currentId = 0;
343
344	for (int32 i = 0; i < fDevice->Description().output_channel_count; i++) {
345		if (currentInput == NULL
346			|| (fDevice->Description().channels[i].designations & B_CHANNEL_MONO_BUS)
347			|| (fDevice->Description().channels[currentId].designations & B_CHANNEL_STEREO_BUS
348				&& ( fDevice->Description().channels[i].designations & B_CHANNEL_LEFT ||
349					!(fDevice->Description().channels[i].designations & B_CHANNEL_STEREO_BUS)))
350			|| (fDevice->Description().channels[currentId].designations & B_CHANNEL_SURROUND_BUS
351				&& ( fDevice->Description().channels[i].designations & B_CHANNEL_LEFT ||
352					!(fDevice->Description().channels[i].designations & B_CHANNEL_SURROUND_BUS)))
353			) {
354			PRINT(("NodeRegistered() : creating an input for %li\n", i));
355			PRINT(("%ld\t%d\t0x%lx\t0x%lx\n",
356				fDevice->Description().channels[i].channel_id,
357				fDevice->Description().channels[i].kind,
358				fDevice->Description().channels[i].designations,
359				fDevice->Description().channels[i].connectors));
360
361			media_input* input = new media_input;
362
363			input->format = fOutputPreferredFormat;
364			input->destination.port = ControlPort();
365			input->destination.id = fInputs.CountItems();
366			input->node = Node();
367			sprintf(input->name, "output %ld", input->destination.id);
368
369			currentInput = new node_input(*input, fOutputPreferredFormat);
370			currentInput->fPreferredFormat.u.raw_audio.channel_count = 1;
371			currentInput->fInput.format = currentInput->fPreferredFormat;
372			delete currentInput->fResampler;
373			currentInput->fResampler = new
374				Resampler(currentInput->fPreferredFormat.AudioFormat(),
375					fOutputPreferredFormat.AudioFormat());
376
377			currentInput->fChannelId = fDevice->Description().channels[i].channel_id;
378			fInputs.AddItem(currentInput);
379
380			currentId = i;
381		} else {
382			PRINT(("NodeRegistered() : adding a channel\n"));
383			currentInput->fPreferredFormat.u.raw_audio.channel_count++;
384			currentInput->fInput.format = currentInput->fPreferredFormat;
385		}
386		currentInput->fInput.format.u.raw_audio.format = media_raw_audio_format::wildcard.format;
387	}
388
389	node_output *currentOutput = NULL;
390	currentId = 0;
391
392	for (int32 i = fDevice->Description().output_channel_count;
393			i < fDevice->Description().output_channel_count
394				+ fDevice->Description().input_channel_count; i++) {
395		if (currentOutput == NULL
396			|| (fDevice->Description().channels[i].designations & B_CHANNEL_MONO_BUS)
397			|| (fDevice->Description().channels[currentId].designations & B_CHANNEL_STEREO_BUS
398				&& ( fDevice->Description().channels[i].designations & B_CHANNEL_LEFT ||
399					!(fDevice->Description().channels[i].designations & B_CHANNEL_STEREO_BUS)))
400			|| (fDevice->Description().channels[currentId].designations & B_CHANNEL_SURROUND_BUS
401				&& ( fDevice->Description().channels[i].designations & B_CHANNEL_LEFT ||
402					!(fDevice->Description().channels[i].designations & B_CHANNEL_SURROUND_BUS)))
403			) {
404			PRINT(("NodeRegistered() : creating an output for %li\n", i));
405			PRINT(("%ld\t%d\t0x%lx\t0x%lx\n",fDevice->Description().channels[i].channel_id,
406											fDevice->Description().channels[i].kind,
407											fDevice->Description().channels[i].designations,
408											fDevice->Description().channels[i].connectors));
409
410			media_output *output = new media_output;
411
412			output->format = fInputPreferredFormat;
413			output->destination = media_destination::null;
414			output->source.port = ControlPort();
415			output->source.id = fOutputs.CountItems();
416			output->node = Node();
417			sprintf(output->name, "input %ld", output->source.id);
418
419			currentOutput = new node_output(*output, fInputPreferredFormat);
420			currentOutput->fPreferredFormat.u.raw_audio.channel_count = 1;
421			currentOutput->fOutput.format = currentOutput->fPreferredFormat;
422			delete currentOutput->fResampler;
423			currentOutput->fResampler = new
424				Resampler(fInputPreferredFormat.AudioFormat(),
425					currentOutput->fPreferredFormat.AudioFormat());
426
427			currentOutput->fChannelId = fDevice->Description().channels[i].channel_id;
428			fOutputs.AddItem(currentOutput);
429
430			currentId = i;
431		} else {
432			PRINT(("NodeRegistered() : adding a channel\n"));
433			currentOutput->fPreferredFormat.u.raw_audio.channel_count++;
434			currentOutput->fOutput.format = currentOutput->fPreferredFormat;
435		}
436	}
437
438	// Set up our parameter web
439	fWeb = MakeParameterWeb();
440	SetParameterWeb(fWeb);
441
442	// Apply configuration
443#ifdef PRINTING
444	bigtime_t start = system_time();
445#endif
446
447	int32 index = 0;
448	int32 parameterID = 0;
449	const void *data;
450	ssize_t size;
451	while (fConfig.FindInt32("parameterID", index, &parameterID) == B_OK) {
452		if (fConfig.FindData("parameterData", B_RAW_TYPE, index, &data, &size)
453				== B_OK) {
454			SetParameterValue(parameterID, TimeSource()->Now(), data, size);
455		}
456		index++;
457	}
458
459	PRINT(("apply configuration in : %Ld\n", system_time() - start));
460}
461
462
463status_t
464MultiAudioNode::RequestCompleted(const media_request_info& info)
465{
466	CALLED();
467
468	if (info.what != media_request_info::B_REQUEST_FORMAT_CHANGE)
469		return B_OK;
470
471	FrameRateChangeCookie* cookie
472		= (FrameRateChangeCookie*)info.user_data;
473	if (cookie == NULL)
474		return B_OK;
475
476	BReference<FrameRateChangeCookie> cookieReference(cookie, true);
477
478	// if the request failed, we reset the frame rate
479	if (info.status != B_OK) {
480		if (cookie->id == PARAMETER_ID_INPUT_FREQUENCY) {
481			_SetNodeInputFrameRate(cookie->oldFrameRate);
482			if (fDevice->Description().output_rates & B_SR_SAME_AS_INPUT)
483				_SetNodeOutputFrameRate(cookie->oldFrameRate);
484		} else if (cookie->id == PARAMETER_ID_OUTPUT_FREQUENCY)
485			_SetNodeOutputFrameRate(cookie->oldFrameRate);
486
487		// TODO: If we have multiple connections, we should request to change
488		// the format back!
489	}
490
491	return B_OK;
492}
493
494
495void
496MultiAudioNode::SetTimeSource(BTimeSource* timeSource)
497{
498	CALLED();
499}
500
501
502//	#pragma mark - BBufferConsumer
503
504
505status_t
506MultiAudioNode::AcceptFormat(const media_destination& dest,
507	media_format* format)
508{
509	// Check to make sure the format is okay, then remove
510	// any wildcards corresponding to our requirements.
511	CALLED();
512
513	if (format == NULL)
514		return B_BAD_VALUE;
515	if (format->type != B_MEDIA_RAW_AUDIO)
516		return B_MEDIA_BAD_FORMAT;
517
518	node_input *channel = _FindInput(dest);
519	if (channel == NULL)
520		return B_MEDIA_BAD_DESTINATION;
521
522/*	media_format * myFormat = GetFormat();
523	fprintf(stderr,"proposed format: ");
524	print_media_format(format);
525	fprintf(stderr,"\n");
526	fprintf(stderr,"my format: ");
527	print_media_format(myFormat);
528	fprintf(stderr,"\n");*/
529	// Be's format_is_compatible doesn't work.
530//	if (!format_is_compatible(*format,*myFormat)) {
531
532	channel->fFormat = channel->fPreferredFormat;
533
534	/*if(format->u.raw_audio.format == media_raw_audio_format::B_AUDIO_FLOAT
535		&& channel->fPreferredFormat.u.raw_audio.format == media_raw_audio_format::B_AUDIO_SHORT)
536		format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
537	else*/
538	format->u.raw_audio.format = channel->fPreferredFormat.u.raw_audio.format;
539	format->u.raw_audio.valid_bits = channel->fPreferredFormat.u.raw_audio.valid_bits;
540
541	format->u.raw_audio.frame_rate = channel->fPreferredFormat.u.raw_audio.frame_rate;
542	format->u.raw_audio.channel_count = channel->fPreferredFormat.u.raw_audio.channel_count;
543	format->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;
544	format->u.raw_audio.buffer_size = fDevice->BufferList().return_playback_buffer_size
545		* (format->u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK)
546		* format->u.raw_audio.channel_count;
547
548	/*media_format myFormat;
549	GetFormat(&myFormat);
550	if (!format_is_acceptible(*format,myFormat)) {
551		fprintf(stderr,"<- B_MEDIA_BAD_FORMAT\n");
552		return B_MEDIA_BAD_FORMAT;
553	}*/
554	//AddRequirements(format);
555	return B_OK;
556}
557
558
559status_t
560MultiAudioNode::GetNextInput(int32* cookie, media_input* _input)
561{
562	CALLED();
563	if (_input == NULL)
564		return B_BAD_VALUE;
565
566	if (*cookie >= fInputs.CountItems() || *cookie < 0)
567		return B_BAD_INDEX;
568
569	node_input *channel = (node_input *)fInputs.ItemAt(*cookie);
570	*_input = channel->fInput;
571	*cookie += 1;
572	PRINT(("input.format : %lu\n", channel->fInput.format.u.raw_audio.format));
573	return B_OK;
574}
575
576
577void
578MultiAudioNode::DisposeInputCookie(int32 cookie)
579{
580	CALLED();
581	// nothing to do since our cookies are just integers
582}
583
584
585void
586MultiAudioNode::BufferReceived(BBuffer* buffer)
587{
588	//CALLED();
589	switch (buffer->Header()->type) {
590		/*case B_MEDIA_PARAMETERS:
591			{
592			status_t status = ApplyParameterData(buffer->Data(),buffer->SizeUsed());
593			if (status != B_OK) {
594				fprintf(stderr,"ApplyParameterData in MultiAudioNode::BufferReceived failed\n");
595			}
596			buffer->Recycle();
597			}
598			break;*/
599		case B_MEDIA_RAW_AUDIO:
600			if (buffer->Flags() & BBuffer::B_SMALL_BUFFER) {
601				fprintf(stderr,"NOT IMPLEMENTED: B_SMALL_BUFFER in MultiAudioNode::BufferReceived\n");
602				// XXX: implement this part
603				buffer->Recycle();
604			} else {
605				media_timed_event event(buffer->Header()->start_time, BTimedEventQueue::B_HANDLE_BUFFER,
606										buffer, BTimedEventQueue::B_RECYCLE_BUFFER);
607				status_t status = EventQueue()->AddEvent(event);
608				if (status != B_OK) {
609					fprintf(stderr,"EventQueue()->AddEvent(event) in MultiAudioNode::BufferReceived failed\n");
610					buffer->Recycle();
611				}
612			}
613			break;
614		default:
615			fprintf(stderr,"unexpected buffer type in MultiAudioNode::BufferReceived\n");
616			buffer->Recycle();
617			break;
618	}
619}
620
621
622void
623MultiAudioNode::ProducerDataStatus(const media_destination& forWhom,
624	int32 status, bigtime_t atPerformanceTime)
625{
626	//CALLED();
627
628	node_input *channel = _FindInput(forWhom);
629	if (channel == NULL) {
630		fprintf(stderr,"invalid destination received in MultiAudioNode::ProducerDataStatus\n");
631		return;
632	}
633
634	media_timed_event event(atPerformanceTime, BTimedEventQueue::B_DATA_STATUS,
635		&channel->fInput, BTimedEventQueue::B_NO_CLEANUP, status, 0, NULL);
636	EventQueue()->AddEvent(event);
637}
638
639
640status_t
641MultiAudioNode::GetLatencyFor(const media_destination& forWhom,
642	bigtime_t* _latency, media_node_id* _timeSource)
643{
644	CALLED();
645	if (_latency == NULL || _timeSource == NULL)
646		return B_BAD_VALUE;
647
648	node_input *channel = _FindInput(forWhom);
649	if (channel == NULL)
650		return B_MEDIA_BAD_DESTINATION;
651
652	*_latency = EventLatency();
653	*_timeSource = TimeSource()->ID();
654	return B_OK;
655}
656
657
658status_t
659MultiAudioNode::Connected(const media_source& producer,
660	const media_destination& where, const media_format& with_format,
661	media_input* out_input)
662{
663	CALLED();
664	if (out_input == 0) {
665		fprintf(stderr, "<- B_BAD_VALUE\n");
666		return B_BAD_VALUE; // no crashing
667	}
668
669	node_input *channel = _FindInput(where);
670
671	if (channel == NULL) {
672		fprintf(stderr, "<- B_MEDIA_BAD_DESTINATION\n");
673		return B_MEDIA_BAD_DESTINATION;
674	}
675
676	_UpdateInternalLatency(with_format);
677
678	// record the agreed upon values
679	channel->fInput.source = producer;
680	channel->fInput.format = with_format;
681	*out_input = channel->fInput;
682
683	_StartOutputThreadIfNeeded();
684
685	return B_OK;
686}
687
688
689void
690MultiAudioNode::Disconnected(const media_source& producer,
691	const media_destination& where)
692{
693	CALLED();
694	node_input *channel = _FindInput(where);
695
696	if (channel == NULL || channel->fInput.source != producer)
697		return;
698
699	channel->fInput.source = media_source::null;
700	channel->fInput.format = channel->fPreferredFormat;
701
702	BAutolock locker(fBufferLock);
703	_FillWithZeros(*channel);
704	//GetFormat(&channel->fInput.format);
705}
706
707
708status_t
709MultiAudioNode::FormatChanged(const media_source& producer,
710	const media_destination& consumer, int32 change_tag,
711	const media_format& format)
712{
713	CALLED();
714	node_input *channel = _FindInput(consumer);
715
716	if(channel==NULL) {
717		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
718		return B_MEDIA_BAD_DESTINATION;
719	}
720	if (channel->fInput.source != producer) {
721		return B_MEDIA_BAD_SOURCE;
722	}
723
724	return B_ERROR;
725}
726
727
728status_t
729MultiAudioNode::SeekTagRequested(const media_destination& destination,
730				bigtime_t in_target_time,
731				uint32 in_flags,
732				media_seek_tag * out_seek_tag,
733				bigtime_t * out_tagged_time,
734				uint32 * out_flags)
735{
736	CALLED();
737	return BBufferConsumer::SeekTagRequested(destination,in_target_time,in_flags,
738											out_seek_tag,out_tagged_time,out_flags);
739}
740
741
742//	#pragma mark - BBufferProducer
743
744
745status_t
746MultiAudioNode::FormatSuggestionRequested(media_type type, int32 /*quality*/,
747	media_format* format)
748{
749	// FormatSuggestionRequested() is not necessarily part of the format negotiation
750	// process; it's simply an interrogation -- the caller wants to see what the node's
751	// preferred data format is, given a suggestion by the caller.
752	CALLED();
753
754	if (!format)
755	{
756		fprintf(stderr, "\tERROR - NULL format pointer passed in!\n");
757		return B_BAD_VALUE;
758	}
759
760	// this is the format we'll be returning (our preferred format)
761	*format = fInputPreferredFormat;
762
763	// a wildcard type is okay; we can specialize it
764	if (type == B_MEDIA_UNKNOWN_TYPE) type = B_MEDIA_RAW_AUDIO;
765
766	// we only support raw audio
767	if (type != B_MEDIA_RAW_AUDIO) return B_MEDIA_BAD_FORMAT;
768	else return B_OK;
769}
770
771
772status_t
773MultiAudioNode::FormatProposal(const media_source& output, media_format* format)
774{
775	// FormatProposal() is the first stage in the BMediaRoster::Connect() process.  We hand
776	// out a suggested format, with wildcards for any variations we support.
777	CALLED();
778	node_output *channel = _FindOutput(output);
779
780	// is this a proposal for our select output?
781	if (channel == NULL)
782	{
783		fprintf(stderr, "MultiAudioNode::FormatProposal returning B_MEDIA_BAD_SOURCE\n");
784		return B_MEDIA_BAD_SOURCE;
785	}
786
787	// we only support floating-point raw audio, so we always return that, but we
788	// supply an error code depending on whether we found the proposal acceptable.
789	media_type requestedType = format->type;
790	*format = channel->fPreferredFormat;
791	if ((requestedType != B_MEDIA_UNKNOWN_TYPE) && (requestedType != B_MEDIA_RAW_AUDIO))
792	{
793		fprintf(stderr, "MultiAudioNode::FormatProposal returning B_MEDIA_BAD_FORMAT\n");
794		return B_MEDIA_BAD_FORMAT;
795	}
796	else return B_OK;		// raw audio or wildcard type, either is okay by us
797}
798
799
800status_t
801MultiAudioNode::FormatChangeRequested(const media_source& source,
802	const media_destination& destination, media_format* format,
803	int32* _deprecated_)
804{
805	CALLED();
806
807	// we don't support any other formats, so we just reject any format changes.
808	return B_ERROR;
809}
810
811
812status_t
813MultiAudioNode::GetNextOutput(int32* cookie, media_output* out_output)
814{
815	CALLED();
816
817	if ((*cookie < fOutputs.CountItems()) && (*cookie >= 0)) {
818		node_output *channel = (node_output *)fOutputs.ItemAt(*cookie);
819		*out_output = channel->fOutput;
820		*cookie += 1;
821		return B_OK;
822	} else
823		return B_BAD_INDEX;
824}
825
826
827status_t
828MultiAudioNode::DisposeOutputCookie(int32 cookie)
829{
830	CALLED();
831	// do nothing because we don't use the cookie for anything special
832	return B_OK;
833}
834
835
836status_t
837MultiAudioNode::SetBufferGroup(const media_source& for_source,
838	BBufferGroup* newGroup)
839{
840	CALLED();
841
842	node_output *channel = _FindOutput(for_source);
843
844	// is this our output?
845	if (channel == NULL)
846	{
847		fprintf(stderr, "MultiAudioNode::SetBufferGroup returning B_MEDIA_BAD_SOURCE\n");
848		return B_MEDIA_BAD_SOURCE;
849	}
850
851	// Are we being passed the buffer group we're already using?
852	if (newGroup == channel->fBufferGroup) return B_OK;
853
854	// Ahh, someone wants us to use a different buffer group.  At this point we delete
855	// the one we are using and use the specified one instead.  If the specified group is
856	// NULL, we need to recreate one ourselves, and use *that*.  Note that if we're
857	// caching a BBuffer that we requested earlier, we have to Recycle() that buffer
858	// *before* deleting the buffer group, otherwise we'll deadlock waiting for that
859	// buffer to be recycled!
860	delete channel->fBufferGroup;		// waits for all buffers to recycle
861	if (newGroup != NULL)
862	{
863		// we were given a valid group; just use that one from now on
864		channel->fBufferGroup = newGroup;
865	}
866	else
867	{
868		// we were passed a NULL group pointer; that means we construct
869		// our own buffer group to use from now on
870		size_t size = channel->fOutput.format.u.raw_audio.buffer_size;
871		int32 count = int32(fLatency / BufferDuration() + 1 + 1);
872		channel->fBufferGroup = new BBufferGroup(size, count);
873	}
874
875	return B_OK;
876}
877
878
879status_t
880MultiAudioNode::PrepareToConnect(const media_source& what,
881	const media_destination& where, media_format* format,
882	media_source* source, char* name)
883{
884	CALLED();
885
886	// is this our output?
887	node_output* channel = _FindOutput(what);
888	if (channel == NULL) {
889		fprintf(stderr, "MultiAudioNode::PrepareToConnect returning B_MEDIA_BAD_SOURCE\n");
890		return B_MEDIA_BAD_SOURCE;
891	}
892
893	// are we already connected?
894	if (channel->fOutput.destination != media_destination::null)
895		return B_MEDIA_ALREADY_CONNECTED;
896
897	// the format may not yet be fully specialized (the consumer might have
898	// passed back some wildcards).  Finish specializing it now, and return an
899	// error if we don't support the requested format.
900	if (format->type != B_MEDIA_RAW_AUDIO) {
901		fprintf(stderr, "\tnon-raw-audio format?!\n");
902		return B_MEDIA_BAD_FORMAT;
903	}
904
905	// !!! validate all other fields except for buffer_size here, because the
906	// consumer might have supplied different values from AcceptFormat()?
907
908	// check the buffer size, which may still be wildcarded
909	if (format->u.raw_audio.buffer_size
910			== media_raw_audio_format::wildcard.buffer_size) {
911		format->u.raw_audio.buffer_size = 2048;
912			// pick something comfortable to suggest
913		fprintf(stderr, "\tno buffer size provided, suggesting %lu\n",
914			format->u.raw_audio.buffer_size);
915	} else {
916		fprintf(stderr, "\tconsumer suggested buffer_size %lu\n",
917			format->u.raw_audio.buffer_size);
918	}
919
920	// Now reserve the connection, and return information about it
921	channel->fOutput.destination = where;
922	channel->fOutput.format = *format;
923
924	*source = channel->fOutput.source;
925#ifdef __HAIKU__
926	strlcpy(name, channel->fOutput.name, B_MEDIA_NAME_LENGTH);
927#else
928	strncpy(name, channel->fOutput.name, B_MEDIA_NAME_LENGTH);
929#endif
930	return B_OK;
931}
932
933
934void
935MultiAudioNode::Connect(status_t error, const media_source& source,
936	const media_destination& destination, const media_format& format,
937	char* name)
938{
939	CALLED();
940
941	// is this our output?
942	node_output* channel = _FindOutput(source);
943	if (channel == NULL) {
944		fprintf(stderr, "MultiAudioNode::Connect returning (cause : B_MEDIA_BAD_SOURCE)\n");
945		return;
946	}
947
948	// If something earlier failed, Connect() might still be called, but with
949	// a non-zero error code.  When that happens we simply unreserve the
950	// connection and do nothing else.
951	if (error) {
952		channel->fOutput.destination = media_destination::null;
953		channel->fOutput.format = channel->fPreferredFormat;
954		return;
955	}
956
957	// Okay, the connection has been confirmed.  Record the destination and
958	// format that we agreed on, and report our connection name again.
959	channel->fOutput.destination = destination;
960	channel->fOutput.format = format;
961#ifdef __HAIKU__
962	strlcpy(name, channel->fOutput.name, B_MEDIA_NAME_LENGTH);
963#else
964	strncpy(name, channel->fOutput.name, B_MEDIA_NAME_LENGTH);
965#endif
966
967	// reset our buffer duration, etc. to avoid later calculations
968	bigtime_t duration = channel->fOutput.format.u.raw_audio.buffer_size * 10000
969		/ ((channel->fOutput.format.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK)
970			* channel->fOutput.format.u.raw_audio.channel_count)
971		/ ((int32)(channel->fOutput.format.u.raw_audio.frame_rate / 100));
972
973	SetBufferDuration(duration);
974
975	// Now that we're connected, we can determine our downstream latency.
976	// Do so, then make sure we get our events early enough.
977	media_node_id id;
978	FindLatencyFor(channel->fOutput.destination, &fLatency, &id);
979	PRINT(("\tdownstream latency = %Ld\n", fLatency));
980
981	fInternalLatency = BufferDuration();
982	PRINT(("\tbuffer-filling took %Ld usec on this machine\n", fInternalLatency));
983	//SetEventLatency(fLatency + fInternalLatency);
984
985	// Set up the buffer group for our connection, as long as nobody handed us
986	// a buffer group (via SetBufferGroup()) prior to this.  That can happen,
987	// for example, if the consumer calls SetOutputBuffersFor() on us from
988	// within its Connected() method.
989	if (!channel->fBufferGroup)
990		_AllocateBuffers(*channel);
991
992	_StartOutputThreadIfNeeded();
993}
994
995
996void
997MultiAudioNode::Disconnect(const media_source& what,
998	const media_destination& where)
999{
1000	CALLED();
1001
1002	// is this our output?
1003	node_output* channel = _FindOutput(what);
1004	if (channel == NULL) {
1005		fprintf(stderr, "MultiAudioNode::Disconnect() returning (cause : B_MEDIA_BAD_SOURCE)\n");
1006		return;
1007	}
1008
1009	// Make sure that our connection is the one being disconnected
1010	if (where == channel->fOutput.destination
1011		&& what == channel->fOutput.source) {
1012		channel->fOutput.destination = media_destination::null;
1013		channel->fOutput.format = channel->fPreferredFormat;
1014		delete channel->fBufferGroup;
1015		channel->fBufferGroup = NULL;
1016	} else {
1017		fprintf(stderr, "\tDisconnect() called with wrong source/destination (%ld/%ld), ours is (%ld/%ld)\n",
1018			what.id, where.id, channel->fOutput.source.id, channel->fOutput.destination.id);
1019	}
1020}
1021
1022
1023void
1024MultiAudioNode::LateNoticeReceived(const media_source& what, bigtime_t howMuch,
1025	bigtime_t performanceTime)
1026{
1027	CALLED();
1028
1029	// is this our output?
1030	node_output *channel = _FindOutput(what);
1031	if (channel == NULL)
1032		return;
1033
1034	// If we're late, we need to catch up.  Respond in a manner appropriate
1035	// to our current run mode.
1036	if (RunMode() == B_RECORDING) {
1037		// A hardware capture node can't adjust; it simply emits buffers at
1038		// appropriate points.  We (partially) simulate this by not adjusting
1039		// our behavior upon receiving late notices -- after all, the hardware
1040		// can't choose to capture "sooner"....
1041	} else if (RunMode() == B_INCREASE_LATENCY) {
1042		// We're late, and our run mode dictates that we try to produce buffers
1043		// earlier in order to catch up.  This argues that the downstream nodes
1044		// are not properly reporting their latency, but there's not much we can
1045		// do about that at the moment, so we try to start producing buffers
1046		// earlier to compensate.
1047		fInternalLatency += howMuch;
1048		SetEventLatency(fLatency + fInternalLatency);
1049
1050		fprintf(stderr, "\tincreasing latency to %Ld\n",
1051			fLatency + fInternalLatency);
1052	} else {
1053		// The other run modes dictate various strategies for sacrificing data
1054		// quality in the interests of timely data delivery.  The way *we* do
1055		// this is to skip a buffer, which catches us up in time by one buffer
1056		// duration.
1057		/*size_t nSamples = fOutput.format.u.raw_audio.buffer_size / sizeof(float);
1058		mSamplesSent += nSamples;*/
1059
1060		fprintf(stderr, "\tskipping a buffer to try to catch up\n");
1061	}
1062}
1063
1064
1065void
1066MultiAudioNode::EnableOutput(const media_source& what, bool enabled,
1067	int32* _deprecated_)
1068{
1069	CALLED();
1070
1071	// If I had more than one output, I'd have to walk my list of output
1072	// records to see which one matched the given source, and then
1073	// enable/disable that one.  But this node only has one output, so I
1074	// just make sure the given source matches, then set the enable state
1075	// accordingly.
1076	node_output *channel = _FindOutput(what);
1077	if (channel != NULL)
1078		channel->fOutputEnabled = enabled;
1079}
1080
1081
1082void
1083MultiAudioNode::AdditionalBufferRequested(const media_source& source,
1084	media_buffer_id previousBuffer, bigtime_t previousTime,
1085	const media_seek_tag* previousTag)
1086{
1087	CALLED();
1088	// we don't support offline mode
1089	return;
1090}
1091
1092
1093//	#pragma mark - BMediaEventLooper
1094
1095
1096void
1097MultiAudioNode::HandleEvent(const media_timed_event* event, bigtime_t lateness,
1098	bool realTimeEvent)
1099{
1100	//CALLED();
1101	switch (event->type) {
1102		case BTimedEventQueue::B_START:
1103			_HandleStart(event, lateness, realTimeEvent);
1104			break;
1105		case BTimedEventQueue::B_SEEK:
1106			_HandleSeek(event, lateness, realTimeEvent);
1107			break;
1108		case BTimedEventQueue::B_WARP:
1109			_HandleWarp(event, lateness, realTimeEvent);
1110			break;
1111		case BTimedEventQueue::B_STOP:
1112			_HandleStop(event, lateness, realTimeEvent);
1113			break;
1114		case BTimedEventQueue::B_HANDLE_BUFFER:
1115			if (RunState() == BMediaEventLooper::B_STARTED)
1116				_HandleBuffer(event, lateness, realTimeEvent);
1117			break;
1118		case BTimedEventQueue::B_DATA_STATUS:
1119			_HandleDataStatus(event, lateness, realTimeEvent);
1120			break;
1121		case BTimedEventQueue::B_PARAMETER:
1122			_HandleParameter(event, lateness, realTimeEvent);
1123			break;
1124		default:
1125			fprintf(stderr,"  unknown event type: %li\n", event->type);
1126			break;
1127	}
1128}
1129
1130
1131status_t
1132MultiAudioNode::_HandleBuffer(const media_timed_event* event,
1133	bigtime_t lateness, bool realTimeEvent)
1134{
1135	//CALLED();
1136	BBuffer* buffer = const_cast<BBuffer*>((BBuffer*)event->pointer);
1137	if (buffer == NULL)
1138		return B_BAD_VALUE;
1139
1140	//PRINT(("buffer->Header()->destination : %i\n", buffer->Header()->destination));
1141
1142	node_input* channel = _FindInput(buffer->Header()->destination);
1143	if (channel == NULL) {
1144		buffer->Recycle();
1145		return B_MEDIA_BAD_DESTINATION;
1146	}
1147
1148	bigtime_t now = TimeSource()->Now();
1149	bigtime_t performanceTime = buffer->Header()->start_time;
1150
1151	// the how_early calculate here doesn't include scheduling latency because
1152	// we've already been scheduled to handle the buffer
1153	bigtime_t howEarly = performanceTime - EventLatency() - now;
1154
1155	// if the buffer is late, we ignore it and report the fact to the producer
1156	// who sent it to us
1157	if (RunMode() != B_OFFLINE && RunMode() != B_RECORDING && howEarly < 0LL) {
1158		// lateness doesn't matter in offline mode or in recording mode
1159		//mLateBuffers++;
1160		NotifyLateProducer(channel->fInput.source, -howEarly, performanceTime);
1161		fprintf(stderr,"	<- LATE BUFFER : %lli\n", howEarly);
1162		buffer->Recycle();
1163	} else {
1164		//WriteBuffer(buffer, *channel);
1165		// TODO: This seems like a very fragile mechanism to wait until
1166		// the previous buffer for this channel has been processed...
1167		if (channel->fBuffer != NULL) {
1168			PRINT(("MultiAudioNode::HandleBuffer snoozing recycling channelId : %li, how_early:%Ld\n", channel->fChannelId, howEarly));
1169			//channel->fBuffer->Recycle();
1170			snooze(100);
1171			if (channel->fBuffer != NULL)
1172				buffer->Recycle();
1173			else
1174				channel->fBuffer = buffer;
1175		} else {
1176			//PRINT(("MultiAudioNode::HandleBuffer writing channelId : %li, how_early:%Ld\n", channel->fChannelId, howEarly));
1177			channel->fBuffer = buffer;
1178		}
1179	}
1180	return B_OK;
1181}
1182
1183
1184status_t
1185MultiAudioNode::_HandleDataStatus(const media_timed_event* event,
1186	bigtime_t lateness, bool realTimeEvent)
1187{
1188	//CALLED();
1189	PRINT(("MultiAudioNode::HandleDataStatus status:%li, lateness:%Li\n", event->data, lateness));
1190	switch (event->data) {
1191		case B_DATA_NOT_AVAILABLE:
1192			break;
1193		case B_DATA_AVAILABLE:
1194			break;
1195		case B_PRODUCER_STOPPED:
1196			break;
1197		default:
1198			break;
1199	}
1200	return B_OK;
1201}
1202
1203
1204status_t
1205MultiAudioNode::_HandleStart(const media_timed_event *event, bigtime_t lateness,
1206	bool realTimeEvent)
1207{
1208	CALLED();
1209	if (RunState() != B_STARTED) {
1210	}
1211	return B_OK;
1212}
1213
1214
1215status_t
1216MultiAudioNode::_HandleSeek(const media_timed_event* event, bigtime_t lateness,
1217	bool realTimeEvent)
1218{
1219	CALLED();
1220	PRINT(("MultiAudioNode::HandleSeek(t=%lld,d=%li,bd=%lld)\n",
1221		event->event_time,event->data,event->bigdata));
1222	return B_OK;
1223}
1224
1225
1226status_t
1227MultiAudioNode::_HandleWarp(const media_timed_event* event, bigtime_t lateness,
1228	bool realTimeEvent)
1229{
1230	CALLED();
1231	return B_OK;
1232}
1233
1234
1235status_t
1236MultiAudioNode::_HandleStop(const media_timed_event* event, bigtime_t lateness,
1237	bool realTimeEvent)
1238{
1239	CALLED();
1240	// flush the queue so downstreamers don't get any more
1241	EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true,
1242		BTimedEventQueue::B_HANDLE_BUFFER);
1243
1244	//_StopOutputThread();
1245	return B_OK;
1246}
1247
1248
1249status_t
1250MultiAudioNode::_HandleParameter(const media_timed_event* event,
1251	bigtime_t lateness, bool realTimeEvent)
1252{
1253	CALLED();
1254	return B_OK;
1255}
1256
1257
1258//	#pragma mark - BTimeSource
1259
1260
1261void
1262MultiAudioNode::SetRunMode(run_mode mode)
1263{
1264	CALLED();
1265	PRINT(("MultiAudioNode::SetRunMode mode:%i\n", mode));
1266	//BTimeSource::SetRunMode(mode);
1267}
1268
1269
1270status_t
1271MultiAudioNode::TimeSourceOp(const time_source_op_info& op, void* _reserved)
1272{
1273	CALLED();
1274	switch (op.op) {
1275		case B_TIMESOURCE_START:
1276			PRINT(("TimeSourceOp op B_TIMESOURCE_START\n"));
1277			if (RunState() != BMediaEventLooper::B_STARTED) {
1278				fTimeSourceStarted = true;
1279				_StartOutputThreadIfNeeded();
1280
1281				media_timed_event startEvent(0, BTimedEventQueue::B_START);
1282				EventQueue()->AddEvent(startEvent);
1283			}
1284			break;
1285		case B_TIMESOURCE_STOP:
1286			PRINT(("TimeSourceOp op B_TIMESOURCE_STOP\n"));
1287			if (RunState() == BMediaEventLooper::B_STARTED) {
1288				media_timed_event stopEvent(0, BTimedEventQueue::B_STOP);
1289				EventQueue()->AddEvent(stopEvent);
1290				fTimeSourceStarted = false;
1291				_StopOutputThread();
1292				PublishTime(0, 0, 0);
1293			}
1294			break;
1295		case B_TIMESOURCE_STOP_IMMEDIATELY:
1296			PRINT(("TimeSourceOp op B_TIMESOURCE_STOP_IMMEDIATELY\n"));
1297			if (RunState() == BMediaEventLooper::B_STARTED) {
1298				media_timed_event stopEvent(0, BTimedEventQueue::B_STOP);
1299				EventQueue()->AddEvent(stopEvent);
1300				fTimeSourceStarted = false;
1301				_StopOutputThread();
1302				PublishTime(0, 0, 0);
1303			}
1304			break;
1305		case B_TIMESOURCE_SEEK:
1306			PRINT(("TimeSourceOp op B_TIMESOURCE_SEEK\n"));
1307			BroadcastTimeWarp(op.real_time, op.performance_time);
1308			break;
1309		default:
1310			break;
1311	}
1312	return B_OK;
1313}
1314
1315
1316//	#pragma mark - BControllable
1317
1318
1319status_t
1320MultiAudioNode::GetParameterValue(int32 id, bigtime_t* lastChange, void* value,
1321	size_t* size)
1322{
1323	CALLED();
1324
1325	PRINT(("id : %li\n", id));
1326	BParameter* parameter = NULL;
1327	for (int32 i = 0; i < fWeb->CountParameters(); i++) {
1328		parameter = fWeb->ParameterAt(i);
1329		if (parameter->ID() == id)
1330			break;
1331	}
1332
1333	if (parameter == NULL) {
1334		// Hmmm, we were asked for a parameter that we don't actually
1335		// support.  Report an error back to the caller.
1336		PRINT(("\terror - asked for illegal parameter %ld\n", id));
1337		return B_ERROR;
1338	}
1339
1340	if (id == PARAMETER_ID_INPUT_FREQUENCY
1341		|| id == PARAMETER_ID_OUTPUT_FREQUENCY) {
1342		const multi_format_info& info = fDevice->FormatInfo();
1343
1344		uint32 rate = id == PARAMETER_ID_INPUT_FREQUENCY
1345			? info.input.rate : info.output.rate;
1346
1347		if (*size < sizeof(rate))
1348			return B_ERROR;
1349
1350		memcpy(value, &rate, sizeof(rate));
1351		*size = sizeof(rate);
1352		return B_OK;
1353	}
1354
1355	multi_mix_value_info info;
1356	multi_mix_value values[2];
1357	info.values = values;
1358	info.item_count = 0;
1359	multi_mix_control* controls = fDevice->MixControlInfo().controls;
1360	int32 control_id = controls[id - 100].id;
1361
1362	if (*size < sizeof(float))
1363		return B_ERROR;
1364
1365	if (parameter->Type() == BParameter::B_CONTINUOUS_PARAMETER) {
1366		info.item_count = 1;
1367		values[0].id = control_id;
1368
1369		if (parameter->CountChannels() == 2) {
1370			if (*size < 2*sizeof(float))
1371				return B_ERROR;
1372			info.item_count = 2;
1373			values[1].id = controls[id + 1 - 100].id;
1374		}
1375	} else if(parameter->Type() == BParameter::B_DISCRETE_PARAMETER) {
1376		info.item_count = 1;
1377		values[0].id = control_id;
1378	}
1379
1380	if (info.item_count > 0) {
1381		status_t status = fDevice->GetMix(&info);
1382		if (status != B_OK) {
1383			fprintf(stderr, "Failed on DRIVER_GET_MIX\n");
1384		} else {
1385			if (parameter->Type() == BParameter::B_CONTINUOUS_PARAMETER) {
1386				((float*)value)[0] = values[0].gain;
1387				*size = sizeof(float);
1388
1389				if (parameter->CountChannels() == 2) {
1390					((float*)value)[1] = values[1].gain;
1391					*size = 2*sizeof(float);
1392				}
1393
1394				for (uint32 i = 0; i < *size / sizeof(float); i++) {
1395					PRINT(("GetParameterValue B_CONTINUOUS_PARAMETER value[%li] : %f\n", i, ((float*)value)[i]));
1396				}
1397			} else if (parameter->Type() == BParameter::B_DISCRETE_PARAMETER) {
1398				BDiscreteParameter* discrete = (BDiscreteParameter*)parameter;
1399				if (discrete->CountItems() <= 2)
1400					((int32*)value)[0] = values[0].enable ? 1 : 0;
1401				else
1402					((int32*)value)[0] = values[0].mux;
1403
1404				*size = sizeof(int32);
1405
1406				for (uint32 i = 0; i < *size / sizeof(int32); i++) {
1407					PRINT(("GetParameterValue B_DISCRETE_PARAMETER value[%li] : %li\n", i, ((int32*)value)[i]));
1408				}
1409			}
1410		}
1411	}
1412	return B_OK;
1413}
1414
1415
1416void
1417MultiAudioNode::SetParameterValue(int32 id, bigtime_t performanceTime,
1418	const void* value, size_t size)
1419{
1420	CALLED();
1421	PRINT(("id : %li, performance_time : %lld, size : %li\n", id, performanceTime, size));
1422
1423	BParameter* parameter = NULL;
1424	for (int32 i = 0; i < fWeb->CountParameters(); i++) {
1425		parameter = fWeb->ParameterAt(i);
1426		if (parameter->ID() == id)
1427			break;
1428	}
1429
1430	if (parameter == NULL)
1431		return;
1432
1433	if (id == PARAMETER_ID_OUTPUT_FREQUENCY
1434		|| (id == PARAMETER_ID_INPUT_FREQUENCY
1435			&& (fDevice->Description().output_rates & B_SR_SAME_AS_INPUT))) {
1436		uint32 rate;
1437		if (size < sizeof(rate))
1438			return;
1439		memcpy(&rate, value, sizeof(rate));
1440
1441		if (rate == fOutputPreferredFormat.u.raw_audio.frame_rate)
1442			return;
1443
1444		// create a cookie RequestCompleted() can get the old frame rate from,
1445		// if anything goes wrong
1446		FrameRateChangeCookie* cookie
1447			= new(std::nothrow) FrameRateChangeCookie;
1448		if (cookie == NULL)
1449			return;
1450
1451		cookie->oldFrameRate = fOutputPreferredFormat.u.raw_audio.frame_rate;
1452		cookie->id = id;
1453		BReference<FrameRateChangeCookie> cookieReference(cookie, true);
1454
1455		// NOTE: What we should do is call RequestFormatChange() for all
1456		// connections and change the device's format in RequestCompleted().
1457		// Unfortunately we need the new buffer size first, which we only get
1458		// from the device after changing the format. So we do that now and
1459		// reset it in RequestCompleted(), if something went wrong. This causes
1460		// the buffers we receive until then to be played incorrectly leading
1461		// to unpleasant noise.
1462		float frameRate = MultiAudio::convert_to_sample_rate(rate);
1463		if (_SetNodeInputFrameRate(frameRate) != B_OK)
1464			return;
1465
1466		for (int32 i = 0; i < fInputs.CountItems(); i++) {
1467			node_input* channel = (node_input*)fInputs.ItemAt(i);
1468			if (channel->fInput.source == media_source::null)
1469				continue;
1470
1471			media_format newFormat = channel->fInput.format;
1472			newFormat.u.raw_audio.frame_rate = frameRate;
1473			newFormat.u.raw_audio.buffer_size
1474				= fOutputPreferredFormat.u.raw_audio.buffer_size;
1475
1476			int32 changeTag = 0;
1477			status_t error = RequestFormatChange(channel->fInput.source,
1478				channel->fInput.destination, newFormat, NULL, &changeTag);
1479			if (error == B_OK)
1480				cookie->AcquireReference();
1481		}
1482
1483		if (id != PARAMETER_ID_INPUT_FREQUENCY)
1484			return;
1485		//Do not return cause we should go in the next if
1486	}
1487
1488	if (id == PARAMETER_ID_INPUT_FREQUENCY) {
1489		uint32 rate;
1490		if (size < sizeof(rate))
1491			return;
1492		memcpy(&rate, value, sizeof(rate));
1493
1494		if (rate == fInputPreferredFormat.u.raw_audio.frame_rate)
1495			return;
1496
1497		// create a cookie RequestCompleted() can get the old frame rate from,
1498		// if anything goes wrong
1499		FrameRateChangeCookie* cookie
1500			= new(std::nothrow) FrameRateChangeCookie;
1501		if (cookie == NULL)
1502			return;
1503
1504		cookie->oldFrameRate = fInputPreferredFormat.u.raw_audio.frame_rate;
1505		cookie->id = id;
1506		BReference<FrameRateChangeCookie> cookieReference(cookie, true);
1507
1508		// NOTE: What we should do is call RequestFormatChange() for all
1509		// connections and change the device's format in RequestCompleted().
1510		// Unfortunately we need the new buffer size first, which we only get
1511		// from the device after changing the format. So we do that now and
1512		// reset it in RequestCompleted(), if something went wrong. This causes
1513		// the buffers we receive until then to be played incorrectly leading
1514		// to unpleasant noise.
1515		float frameRate = MultiAudio::convert_to_sample_rate(rate);
1516		if (_SetNodeOutputFrameRate(frameRate) != B_OK)
1517			return;
1518
1519		for (int32 i = 0; i < fOutputs.CountItems(); i++) {
1520			node_output* channel = (node_output*)fOutputs.ItemAt(i);
1521			if (channel->fOutput.source == media_source::null)
1522				continue;
1523
1524			media_format newFormat = channel->fOutput.format;
1525			newFormat.u.raw_audio.frame_rate = frameRate;
1526			newFormat.u.raw_audio.buffer_size
1527				= fInputPreferredFormat.u.raw_audio.buffer_size;
1528
1529			int32 changeTag = 0;
1530			status_t error = RequestFormatChange(channel->fOutput.source,
1531				channel->fOutput.destination, newFormat, NULL, &changeTag);
1532			if (error == B_OK)
1533				cookie->AcquireReference();
1534		}
1535
1536		return;
1537	}
1538
1539	multi_mix_value_info info;
1540	multi_mix_value values[2];
1541	info.values = values;
1542	info.item_count = 0;
1543	multi_mix_control* controls = fDevice->MixControlInfo().controls;
1544	int32 control_id = controls[id - 100].id;
1545
1546	if (parameter->Type() == BParameter::B_CONTINUOUS_PARAMETER) {
1547		for (uint32 i = 0; i < size / sizeof(float); i++) {
1548			PRINT(("SetParameterValue B_CONTINUOUS_PARAMETER value[%li] : %f\n", i, ((float*)value)[i]));
1549		}
1550		info.item_count = 1;
1551		values[0].id = control_id;
1552		values[0].gain = ((float*)value)[0];
1553
1554		if (parameter->CountChannels() == 2) {
1555			info.item_count = 2;
1556			values[1].id = controls[id + 1 - 100].id;
1557			values[1].gain = ((float*)value)[1];
1558		}
1559	} else if (parameter->Type() == BParameter::B_DISCRETE_PARAMETER) {
1560		for (uint32 i = 0; i < size / sizeof(int32); i++) {
1561			PRINT(("SetParameterValue B_DISCRETE_PARAMETER value[%li] : %li\n", i, ((int32*)value)[i]));
1562		}
1563
1564		BDiscreteParameter* discrete = (BDiscreteParameter*)parameter;
1565		if (discrete->CountItems() <= 2) {
1566			info.item_count = 1;
1567			values[0].id = control_id;
1568			values[0].enable = ((int32*)value)[0] == 1;
1569		} else {
1570			info.item_count = 1;
1571			values[0].id = control_id;
1572			values[0].mux = ((uint32*)value)[0];
1573		}
1574	}
1575
1576	if (info.item_count > 0) {
1577		status_t status = fDevice->SetMix(&info);
1578		if (status != B_OK)
1579			fprintf(stderr, "Failed on DRIVER_SET_MIX\n");
1580	}
1581}
1582
1583
1584BParameterWeb*
1585MultiAudioNode::MakeParameterWeb()
1586{
1587	CALLED();
1588	BParameterWeb* web = new BParameterWeb;
1589
1590	PRINT(("MixControlInfo().control_count : %li\n",
1591		fDevice->MixControlInfo().control_count));
1592
1593	BParameterGroup* generalGroup = web->MakeGroup(B_TRANSLATE("General"));
1594
1595	const multi_description& description = fDevice->Description();
1596
1597	if (description.output_rates & B_SR_SAME_AS_INPUT) {
1598		_CreateFrequencyParameterGroup(generalGroup, B_TRANSLATE("Input & Output"),
1599			PARAMETER_ID_INPUT_FREQUENCY, description.input_rates);
1600	} else {
1601		_CreateFrequencyParameterGroup(generalGroup, B_TRANSLATE("Input"),
1602			PARAMETER_ID_INPUT_FREQUENCY, description.input_rates);
1603		_CreateFrequencyParameterGroup(generalGroup, B_TRANSLATE("Output"),
1604			PARAMETER_ID_OUTPUT_FREQUENCY, description.output_rates);
1605	}
1606
1607	multi_mix_control* controls = fDevice->MixControlInfo().controls;
1608
1609	for (int i = 0; i < fDevice->MixControlInfo().control_count; i++) {
1610		if (controls[i].flags & B_MULTI_MIX_GROUP && controls[i].parent == 0) {
1611			PRINT(("NEW_GROUP\n"));
1612			BParameterGroup* child = web->MakeGroup(
1613				_GetControlName(controls[i]));
1614
1615			int32 numParameters = 0;
1616			_ProcessGroup(child, i, numParameters);
1617		}
1618	}
1619
1620	return web;
1621}
1622
1623
1624const char*
1625MultiAudioNode::_GetControlName(multi_mix_control& control)
1626{
1627	if (control.string != S_null)
1628		return kMultiControlString[control.string];
1629
1630	return control.name;
1631}
1632
1633
1634void
1635MultiAudioNode::_ProcessGroup(BParameterGroup* group, int32 index,
1636	int32& numParameters)
1637{
1638	CALLED();
1639	multi_mix_control* parent = &fDevice->MixControlInfo().controls[index];
1640	multi_mix_control* controls = fDevice->MixControlInfo().controls;
1641
1642	for (int32 i = 0; i < fDevice->MixControlInfo().control_count; i++) {
1643		if (controls[i].parent != parent->id)
1644			continue;
1645
1646		const char* name = _GetControlName(controls[i]);
1647
1648		if (controls[i].flags & B_MULTI_MIX_GROUP) {
1649			PRINT(("NEW_GROUP\n"));
1650			BParameterGroup* child = group->MakeGroup(name);
1651			child->MakeNullParameter(100 + i, B_MEDIA_RAW_AUDIO, name,
1652				B_WEB_BUFFER_OUTPUT);
1653
1654			int32 num = 1;
1655			_ProcessGroup(child, i, num);
1656		} else if (controls[i].flags & B_MULTI_MIX_MUX) {
1657			PRINT(("NEW_MUX\n"));
1658			BDiscreteParameter* parameter = group->MakeDiscreteParameter(
1659				100 + i, B_MEDIA_RAW_AUDIO, name, B_INPUT_MUX);
1660			if (numParameters > 0) {
1661				(group->ParameterAt(numParameters - 1))->AddOutput(
1662					group->ParameterAt(numParameters));
1663				numParameters++;
1664			}
1665			_ProcessMux(parameter, i);
1666		} else if (controls[i].flags & B_MULTI_MIX_GAIN) {
1667			PRINT(("NEW_GAIN\n"));
1668			group->MakeContinuousParameter(100 + i,
1669				B_MEDIA_RAW_AUDIO, "", B_MASTER_GAIN, "dB",
1670				controls[i].gain.min_gain, controls[i].gain.max_gain,
1671				controls[i].gain.granularity);
1672
1673			if (i + 1 < fDevice->MixControlInfo().control_count
1674				&& controls[i + 1].master == controls[i].id
1675				&& controls[i + 1].flags & B_MULTI_MIX_GAIN) {
1676				group->ParameterAt(numParameters)->SetChannelCount(
1677					group->ParameterAt(numParameters)->CountChannels() + 1);
1678				i++;
1679			}
1680
1681			PRINT(("num parameters : %ld\n", numParameters));
1682			if (numParameters > 0) {
1683				(group->ParameterAt(numParameters - 1))->AddOutput(
1684					group->ParameterAt(numParameters));
1685				numParameters++;
1686			}
1687		} else if (controls[i].flags & B_MULTI_MIX_ENABLE) {
1688			PRINT(("NEW_ENABLE\n"));
1689			if (controls[i].string == S_MUTE) {
1690				group->MakeDiscreteParameter(100 + i,
1691					B_MEDIA_RAW_AUDIO, name, B_MUTE);
1692			} else {
1693				group->MakeDiscreteParameter(100 + i,
1694					B_MEDIA_RAW_AUDIO, name, B_ENABLE);
1695			}
1696			if (numParameters > 0) {
1697				(group->ParameterAt(numParameters - 1))->AddOutput(
1698					group->ParameterAt(numParameters));
1699				numParameters++;
1700			}
1701		}
1702	}
1703}
1704
1705
1706void
1707MultiAudioNode::_ProcessMux(BDiscreteParameter* parameter, int32 index)
1708{
1709	CALLED();
1710	multi_mix_control* parent = &fDevice->MixControlInfo().controls[index];
1711	multi_mix_control* controls = fDevice->MixControlInfo().controls;
1712	int32 itemIndex = 0;
1713
1714	for (int32 i = 0; i < fDevice->MixControlInfo().control_count; i++) {
1715		if (controls[i].parent != parent->id)
1716			continue;
1717
1718		if (controls[i].flags & B_MULTI_MIX_MUX_VALUE) {
1719			PRINT(("NEW_MUX_VALUE\n"));
1720			parameter->AddItem(itemIndex, _GetControlName(controls[i]));
1721			itemIndex++;
1722		}
1723	}
1724}
1725
1726
1727void
1728MultiAudioNode::_CreateFrequencyParameterGroup(BParameterGroup* parentGroup,
1729	const char* name, int32 parameterID, uint32 rateMask)
1730{
1731	BParameterGroup* group = parentGroup->MakeGroup(name);
1732	BDiscreteParameter* frequencyParam = group->MakeDiscreteParameter(
1733		parameterID, B_MEDIA_NO_TYPE, BString(name) << B_TRANSLATE(" frequency:"),
1734		B_GENERIC);
1735
1736	for (int32 i = 0; kSampleRateInfos[i].name != NULL; i++) {
1737		const sample_rate_info& info = kSampleRateInfos[i];
1738		if ((rateMask & info.multiAudioRate) != 0) {
1739			frequencyParam->AddItem(info.multiAudioRate,
1740				BString(info.name) << " Hz");
1741		}
1742	}
1743}
1744
1745
1746//	#pragma mark - MultiAudioNode specific functions
1747
1748
1749int32
1750MultiAudioNode::_OutputThread()
1751{
1752	CALLED();
1753	multi_buffer_info bufferInfo;
1754	bufferInfo.info_size = sizeof(multi_buffer_info);
1755	bufferInfo.playback_buffer_cycle = 0;
1756	bufferInfo.record_buffer_cycle = 0;
1757
1758	// init the performance time computation
1759	{
1760		BAutolock locker(fBufferLock);
1761		fTimeComputer.Init(fOutputPreferredFormat.u.raw_audio.frame_rate,
1762			system_time());
1763	}
1764
1765	while (true) {
1766		// TODO: why this semaphore??
1767		if (acquire_sem_etc(fBufferFreeSem, 1, B_RELATIVE_TIMEOUT, 0)
1768				== B_BAD_SEM_ID) {
1769			return B_OK;
1770		}
1771
1772		BAutolock locker(fBufferLock);
1773			// make sure the buffers don't change while we're playing with them
1774
1775		// send buffer
1776		fDevice->BufferExchange(&bufferInfo);
1777
1778		//PRINT(("MultiAudioNode::RunThread: buffer exchanged\n"));
1779		//PRINT(("MultiAudioNode::RunThread: played_real_time : %Ld\n", bufferInfo.played_real_time));
1780		//PRINT(("MultiAudioNode::RunThread: played_frames_count : %Ld\n", bufferInfo.played_frames_count));
1781		//PRINT(("MultiAudioNode::RunThread: buffer_cycle : %li\n", bufferInfo.playback_buffer_cycle));
1782
1783		for (int32 i = 0; i < fInputs.CountItems(); i++) {
1784			node_input* input = (node_input*)fInputs.ItemAt(i);
1785
1786			if (bufferInfo.playback_buffer_cycle >= 0
1787				&& bufferInfo.playback_buffer_cycle
1788						< fDevice->BufferList().return_playback_buffers
1789				&& (input->fOldBufferInfo.playback_buffer_cycle
1790						!= bufferInfo.playback_buffer_cycle
1791					|| fDevice->BufferList().return_playback_buffers == 1)
1792				&& (input->fInput.source != media_source::null
1793					|| input->fChannelId == 0)) {
1794				//PRINT(("playback_buffer_cycle ok input : %li %ld\n", i, bufferInfo.playback_buffer_cycle));
1795
1796				input->fBufferCycle = (bufferInfo.playback_buffer_cycle - 1
1797						+ fDevice->BufferList().return_playback_buffers)
1798					% fDevice->BufferList().return_playback_buffers;
1799
1800				// update the timesource
1801				if (input->fChannelId == 0) {
1802					//PRINT(("updating timesource\n"));
1803					_UpdateTimeSource(bufferInfo, input->fOldBufferInfo,
1804						*input);
1805				}
1806
1807				input->fOldBufferInfo = bufferInfo;
1808
1809				if (input->fBuffer != NULL) {
1810					_FillNextBuffer(*input, input->fBuffer);
1811					input->fBuffer->Recycle();
1812					input->fBuffer = NULL;
1813				} else {
1814					// put zeros in current buffer
1815					if (input->fInput.source != media_source::null)
1816						_WriteZeros(*input, input->fBufferCycle);
1817					//PRINT(("MultiAudioNode::Runthread WriteZeros\n"));
1818				}
1819
1820				// mark buffer free
1821				release_sem(fBufferFreeSem);
1822			} else {
1823				//PRINT(("playback_buffer_cycle non ok input : %i\n", i));
1824			}
1825		}
1826
1827		PRINT(("MultiAudioNode::RunThread: recorded_real_time : %Ld\n",
1828			bufferInfo.recorded_real_time));
1829		PRINT(("MultiAudioNode::RunThread: recorded_frames_count : %Ld\n",
1830			bufferInfo.recorded_frames_count));
1831		PRINT(("MultiAudioNode::RunThread: record_buffer_cycle : %li\n",
1832			bufferInfo.record_buffer_cycle));
1833
1834		for (int32 i = 0; i < fOutputs.CountItems(); i++) {
1835			node_output* output = (node_output*)fOutputs.ItemAt(i);
1836
1837			// make sure we're both started *and* connected before delivering a
1838			// buffer
1839			if (RunState() == BMediaEventLooper::B_STARTED
1840				&& output->fOutput.destination != media_destination::null) {
1841				if (bufferInfo.record_buffer_cycle >= 0
1842					&& bufferInfo.record_buffer_cycle
1843							< fDevice->BufferList().return_record_buffers
1844					&& (output->fOldBufferInfo.record_buffer_cycle
1845							!= bufferInfo.record_buffer_cycle
1846						|| fDevice->BufferList().return_record_buffers == 1)) {
1847					//PRINT(("record_buffer_cycle ok\n"));
1848
1849					output->fBufferCycle = bufferInfo.record_buffer_cycle;
1850
1851					// Get the next buffer of data
1852					BBuffer* buffer = _FillNextBuffer(bufferInfo, *output);
1853					if (buffer != NULL) {
1854						// send the buffer downstream if and only if output is
1855						// enabled
1856						status_t err = B_ERROR;
1857						if (output->fOutputEnabled) {
1858							err = SendBuffer(buffer, output->fOutput.source,
1859								output->fOutput.destination);
1860						}
1861						if (err) {
1862							buffer->Recycle();
1863						} else {
1864							// track how much media we've delivered so far
1865							size_t numSamples
1866								= output->fOutput.format.u.raw_audio.buffer_size
1867								/ (output->fOutput.format.u.raw_audio.format
1868									& media_raw_audio_format::B_AUDIO_SIZE_MASK);
1869							output->fSamplesSent += numSamples;
1870						}
1871					}
1872
1873					output->fOldBufferInfo = bufferInfo;
1874				} else {
1875					//PRINT(("record_buffer_cycle non ok\n"));
1876				}
1877			}
1878		}
1879	}
1880
1881	return B_OK;
1882}
1883
1884
1885void
1886MultiAudioNode::_WriteZeros(node_input& input, uint32 bufferCycle)
1887{
1888	//CALLED();
1889	/*int32 samples = input.fInput.format.u.raw_audio.buffer_size;
1890	if(input.fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_UCHAR) {
1891		uint8 *sample = (uint8*)fDevice->BufferList().playback_buffers[input.fBufferCycle][input.fChannelId].base;
1892		for(int32 i = samples-1; i>=0; i--)
1893			*sample++ = 128;
1894	} else {
1895		int32 *sample = (int32*)fDevice->BufferList().playback_buffers[input.fBufferCycle][input.fChannelId].base;
1896		for(int32 i = (samples / 4)-1; i>=0; i--)
1897			*sample++ = 0;
1898	}*/
1899
1900	uint32 channelCount = input.fFormat.u.raw_audio.channel_count;
1901	uint32 bufferSize = fDevice->BufferList().return_playback_buffer_size;
1902	size_t stride = fDevice->BufferList().playback_buffers[bufferCycle]
1903		[input.fChannelId].stride;
1904
1905	switch (input.fFormat.u.raw_audio.format) {
1906		case media_raw_audio_format::B_AUDIO_FLOAT:
1907			for (uint32 channel = 0; channel < channelCount; channel++) {
1908				char* dest = _PlaybackBuffer(bufferCycle,
1909					input.fChannelId + channel);
1910				for (uint32 i = bufferSize; i > 0; i--) {
1911					*(float*)dest = 0;
1912					dest += stride;
1913				}
1914			}
1915			break;
1916
1917		case media_raw_audio_format::B_AUDIO_DOUBLE:
1918			for (uint32 channel = 0; channel < channelCount; channel++) {
1919				char* dest = _PlaybackBuffer(bufferCycle,
1920					input.fChannelId + channel);
1921				for (uint32 i = bufferSize; i > 0; i--) {
1922					*(double*)dest = 0;
1923					dest += stride;
1924				}
1925			}
1926			break;
1927
1928		case media_raw_audio_format::B_AUDIO_INT:
1929			for (uint32 channel = 0; channel < channelCount; channel++) {
1930				char* dest = _PlaybackBuffer(bufferCycle,
1931					input.fChannelId + channel);
1932				for (uint32 i = bufferSize; i > 0; i--) {
1933					*(int32*)dest = 0;
1934					dest += stride;
1935				}
1936			}
1937			break;
1938
1939		case media_raw_audio_format::B_AUDIO_SHORT:
1940			for (uint32 channel = 0; channel < channelCount; channel++) {
1941				char* dest = _PlaybackBuffer(bufferCycle,
1942					input.fChannelId + channel);
1943				for (uint32 i = bufferSize; i > 0; i--) {
1944					*(int16*)dest = 0;
1945					dest += stride;
1946				}
1947			}
1948			break;
1949
1950		case media_raw_audio_format::B_AUDIO_UCHAR:
1951			for (uint32 channel = 0; channel < channelCount; channel++) {
1952				char* dest = _PlaybackBuffer(bufferCycle,
1953					input.fChannelId + channel);
1954				for (uint32 i = bufferSize; i > 0; i--) {
1955					*(uint8*)dest = 128;
1956					dest += stride;
1957				}
1958			}
1959			break;
1960
1961		case media_raw_audio_format::B_AUDIO_CHAR:
1962			for (uint32 channel = 0; channel < channelCount; channel++) {
1963				char* dest = _PlaybackBuffer(bufferCycle,
1964					input.fChannelId + channel);
1965				for (uint32 i = bufferSize; i > 0; i--) {
1966					*(int8*)dest = 0;
1967					dest += stride;
1968				}
1969			}
1970			break;
1971
1972		default:
1973			fprintf(stderr, "ERROR in WriteZeros format not handled\n");
1974	}
1975}
1976
1977
1978void
1979MultiAudioNode::_FillWithZeros(node_input& input)
1980{
1981	CALLED();
1982	for (int32 i = 0; i < fDevice->BufferList().return_playback_buffers; i++)
1983		_WriteZeros(input, i);
1984}
1985
1986
1987void
1988MultiAudioNode::_FillNextBuffer(node_input& input, BBuffer* buffer)
1989{
1990	uint32 channelCount = input.fInput.format.u.raw_audio.channel_count;
1991	size_t inputSampleSize = input.fInput.format.u.raw_audio.format
1992			& media_raw_audio_format::B_AUDIO_SIZE_MASK;
1993
1994	uint32 bufferSize = fDevice->BufferList().return_playback_buffer_size;
1995
1996	if (buffer->SizeUsed() / inputSampleSize / channelCount != bufferSize) {
1997		_WriteZeros(input, input.fBufferCycle);
1998		return;
1999	}
2000
2001	if (channelCount != input.fFormat.u.raw_audio.channel_count) {
2002		PRINT(("Channel count is different"));
2003		return;
2004	}
2005
2006	if (input.fResampler != NULL) {
2007		size_t srcStride = channelCount * inputSampleSize;
2008
2009		for (uint32 channel = 0; channel < channelCount; channel++) {
2010			char* src = (char*)buffer->Data() + channel * inputSampleSize;
2011			char* dst = _PlaybackBuffer(input.fBufferCycle,
2012							input.fChannelId + channel);
2013			size_t dstStride = _PlaybackStride(input.fBufferCycle,
2014							input.fChannelId + channel);
2015
2016			input.fResampler->Resample(src, srcStride,
2017				dst, dstStride, bufferSize);
2018		}
2019	}
2020}
2021
2022
2023status_t
2024MultiAudioNode::_StartOutputThreadIfNeeded()
2025{
2026	CALLED();
2027	// the thread is already started ?
2028	if (fThread >= 0)
2029		return B_OK;
2030
2031	// allocate buffer free semaphore
2032	fBufferFreeSem = create_sem(
2033		fDevice->BufferList().return_playback_buffers - 1,
2034		"multi_audio out buffer free");
2035	if (fBufferFreeSem < B_OK)
2036		return fBufferFreeSem;
2037
2038	PublishTime(-50, 0, 0);
2039
2040	fThread = spawn_thread(_OutputThreadEntry, "multi_audio audio output",
2041		B_REAL_TIME_PRIORITY, this);
2042	if (fThread < B_OK) {
2043		delete_sem(fBufferFreeSem);
2044		return fThread;
2045	}
2046
2047	resume_thread(fThread);
2048	return B_OK;
2049}
2050
2051
2052status_t
2053MultiAudioNode::_StopOutputThread()
2054{
2055	CALLED();
2056	delete_sem(fBufferFreeSem);
2057
2058	status_t exitValue;
2059	wait_for_thread(fThread, &exitValue);
2060	fThread = -1;
2061	return B_OK;
2062}
2063
2064
2065void
2066MultiAudioNode::_AllocateBuffers(node_output &channel)
2067{
2068	CALLED();
2069
2070	// allocate enough buffers to span our downstream latency, plus one
2071	size_t size = channel.fOutput.format.u.raw_audio.buffer_size;
2072	int32 count = int32(fLatency / BufferDuration() + 1 + 1);
2073
2074	PRINT(("\tlatency = %Ld, buffer duration = %Ld\n", fLatency,
2075		BufferDuration()));
2076	PRINT(("\tcreating group of %ld buffers, size = %lu\n", count, size));
2077	channel.fBufferGroup = new BBufferGroup(size, count);
2078}
2079
2080
2081void
2082MultiAudioNode::_UpdateTimeSource(multi_buffer_info& info,
2083	multi_buffer_info& oldInfo, node_input& input)
2084{
2085	//CALLED();
2086	if (!fTimeSourceStarted || oldInfo.played_real_time == 0)
2087		return;
2088
2089	fTimeComputer.AddTimeStamp(info.played_real_time,
2090		info.played_frames_count);
2091	PublishTime(fTimeComputer.PerformanceTime(), fTimeComputer.RealTime(),
2092		fTimeComputer.Drift());
2093}
2094
2095
2096BBuffer*
2097MultiAudioNode::_FillNextBuffer(multi_buffer_info &info, node_output &output)
2098{
2099	//CALLED();
2100	// get a buffer from our buffer group
2101	//PRINT(("buffer size : %i, buffer duration : %i\n", fOutput.format.u.raw_audio.buffer_size, BufferDuration()));
2102	//PRINT(("MBI.record_buffer_cycle : %i\n", MBI.record_buffer_cycle));
2103	//PRINT(("MBI.recorded_real_time : %i\n", MBI.recorded_real_time));
2104	//PRINT(("MBI.recorded_frames_count : %i\n", MBI.recorded_frames_count));
2105	if (!output.fBufferGroup)
2106		return NULL;
2107
2108	BBuffer* buffer = output.fBufferGroup->RequestBuffer(
2109		output.fOutput.format.u.raw_audio.buffer_size, BufferDuration());
2110	if (buffer == NULL) {
2111		// If we fail to get a buffer (for example, if the request times out),
2112		// we skip this buffer and go on to the next, to avoid locking up the
2113		// control thread.
2114		fprintf(stderr, "Buffer is null");
2115		return NULL;
2116	}
2117
2118	if (fDevice == NULL)
2119		fprintf(stderr, "fDevice NULL\n");
2120	if (buffer->Header() == NULL)
2121		fprintf(stderr, "buffer->Header() NULL\n");
2122	if (TimeSource() == NULL)
2123		fprintf(stderr, "TimeSource() NULL\n");
2124
2125	uint32 channelCount = output.fOutput.format.u.raw_audio.channel_count;
2126	size_t outputSampleSize = output.fOutput.format.u.raw_audio.format
2127		& media_raw_audio_format::B_AUDIO_SIZE_MASK;
2128
2129	uint32 bufferSize = fDevice->BufferList().return_record_buffer_size;
2130
2131	if (output.fResampler != NULL) {
2132		size_t dstStride = channelCount * outputSampleSize;
2133
2134		uint32 channelId = output.fChannelId
2135			- fDevice->Description().output_channel_count;
2136
2137		for (uint32 channel = 0; channel < channelCount; channel++) {
2138			char* src = _RecordBuffer(output.fBufferCycle,
2139									channelId + channel);
2140			size_t srcStride = _RecordStride(output.fBufferCycle,
2141									channelId + channel);
2142			char* dst = (char*)buffer->Data() + channel * outputSampleSize;
2143
2144			output.fResampler->Resample(src, srcStride, dst, dstStride,
2145				bufferSize);
2146		}
2147	}
2148
2149	// fill in the buffer header
2150	media_header* header = buffer->Header();
2151	header->type = B_MEDIA_RAW_AUDIO;
2152	header->size_used = output.fOutput.format.u.raw_audio.buffer_size;
2153	header->time_source = TimeSource()->ID();
2154	header->start_time = PerformanceTimeFor(info.recorded_real_time);
2155
2156	return buffer;
2157}
2158
2159
2160status_t
2161MultiAudioNode::GetConfigurationFor(BMessage* message)
2162{
2163	CALLED();
2164
2165	BParameter *parameter = NULL;
2166	void *buffer;
2167	size_t bufferSize = 128;
2168	bigtime_t lastChange;
2169	status_t err;
2170
2171	if (message == NULL)
2172		return B_BAD_VALUE;
2173
2174	buffer = malloc(bufferSize);
2175	if (buffer == NULL)
2176		return B_NO_MEMORY;
2177
2178	for (int32 i = 0; i < fWeb->CountParameters(); i++) {
2179		parameter = fWeb->ParameterAt(i);
2180		if (parameter->Type() != BParameter::B_CONTINUOUS_PARAMETER
2181			&& parameter->Type() != BParameter::B_DISCRETE_PARAMETER)
2182			continue;
2183
2184		PRINT(("getting parameter %li\n", parameter->ID()));
2185		size_t size = bufferSize;
2186		while ((err = GetParameterValue(parameter->ID(), &lastChange, buffer,
2187				&size)) == B_NO_MEMORY && bufferSize < 128 * 1024) {
2188			bufferSize += 128;
2189			free(buffer);
2190			buffer = malloc(bufferSize);
2191			if (buffer == NULL)
2192				return B_NO_MEMORY;
2193		}
2194
2195		if (err == B_OK && size > 0) {
2196			message->AddInt32("parameterID", parameter->ID());
2197			message->AddData("parameterData", B_RAW_TYPE, buffer, size, false);
2198		} else {
2199			PRINT(("parameter err : %s\n", strerror(err)));
2200		}
2201	}
2202
2203	free(buffer);
2204	PRINT_OBJECT(*message);
2205	return B_OK;
2206}
2207
2208
2209node_output*
2210MultiAudioNode::_FindOutput(media_source source)
2211{
2212	node_output* channel = NULL;
2213
2214	for (int32 i = 0; i < fOutputs.CountItems(); i++) {
2215		channel = (node_output*)fOutputs.ItemAt(i);
2216		if (source == channel->fOutput.source)
2217			break;
2218	}
2219
2220	if (source != channel->fOutput.source)
2221		return NULL;
2222
2223	return channel;
2224}
2225
2226
2227node_input*
2228MultiAudioNode::_FindInput(media_destination dest)
2229{
2230	node_input* channel = NULL;
2231
2232	for (int32 i = 0; i < fInputs.CountItems(); i++) {
2233		channel = (node_input*)fInputs.ItemAt(i);
2234		if (dest == channel->fInput.destination)
2235			break;
2236	}
2237
2238	if (dest != channel->fInput.destination)
2239		return NULL;
2240
2241	return channel;
2242}
2243
2244
2245node_input*
2246MultiAudioNode::_FindInput(int32 destinationId)
2247{
2248	node_input* channel = NULL;
2249
2250	for (int32 i = 0; i < fInputs.CountItems(); i++) {
2251		channel = (node_input*)fInputs.ItemAt(i);
2252		if (destinationId == channel->fInput.destination.id)
2253			break;
2254	}
2255
2256	if (destinationId != channel->fInput.destination.id)
2257		return NULL;
2258
2259	return channel;
2260}
2261
2262
2263/*static*/ status_t
2264MultiAudioNode::_OutputThreadEntry(void* data)
2265{
2266	CALLED();
2267	return static_cast<MultiAudioNode*>(data)->_OutputThread();
2268}
2269
2270
2271status_t
2272MultiAudioNode::_SetNodeInputFrameRate(float frameRate)
2273{
2274	// check whether the frame rate is supported
2275	uint32 multiAudioRate = MultiAudio::convert_from_sample_rate(frameRate);
2276	if ((fDevice->Description().output_rates & multiAudioRate) == 0)
2277		return B_BAD_VALUE;
2278
2279	BAutolock locker(fBufferLock);
2280
2281	// already set?
2282	if (fDevice->FormatInfo().output.rate == multiAudioRate)
2283		return B_OK;
2284
2285	// set the frame rate on the device
2286	status_t error = fDevice->SetOutputFrameRate(multiAudioRate);
2287	if (error != B_OK)
2288		return error;
2289
2290	// it went fine -- update all formats
2291	fOutputPreferredFormat.u.raw_audio.frame_rate = frameRate;
2292	fOutputPreferredFormat.u.raw_audio.buffer_size
2293		= fDevice->BufferList().return_playback_buffer_size
2294			* (fOutputPreferredFormat.u.raw_audio.format
2295				& media_raw_audio_format::B_AUDIO_SIZE_MASK)
2296			* fOutputPreferredFormat.u.raw_audio.channel_count;
2297
2298	for (int32 i = 0; node_input* channel = (node_input*)fInputs.ItemAt(i);
2299			i++) {
2300		channel->fPreferredFormat.u.raw_audio.frame_rate = frameRate;
2301		channel->fPreferredFormat.u.raw_audio.buffer_size
2302			= fOutputPreferredFormat.u.raw_audio.buffer_size;
2303
2304		channel->fFormat.u.raw_audio.frame_rate = frameRate;
2305		channel->fFormat.u.raw_audio.buffer_size
2306			= fOutputPreferredFormat.u.raw_audio.buffer_size;
2307
2308		channel->fInput.format.u.raw_audio.frame_rate = frameRate;
2309		channel->fInput.format.u.raw_audio.buffer_size
2310			= fOutputPreferredFormat.u.raw_audio.buffer_size;
2311	}
2312
2313	// make sure the time base is reset
2314	fTimeComputer.SetFrameRate(frameRate);
2315
2316	// update internal latency
2317	_UpdateInternalLatency(fOutputPreferredFormat);
2318
2319	return B_OK;
2320}
2321
2322
2323status_t
2324MultiAudioNode::_SetNodeOutputFrameRate(float frameRate)
2325{
2326	// check whether the frame rate is supported
2327	uint32 multiAudioRate = MultiAudio::convert_from_sample_rate(frameRate);
2328	if ((fDevice->Description().input_rates & multiAudioRate) == 0)
2329		return B_BAD_VALUE;
2330
2331	BAutolock locker(fBufferLock);
2332
2333	// already set?
2334	if (fDevice->FormatInfo().input.rate == multiAudioRate)
2335		return B_OK;
2336
2337	// set the frame rate on the device
2338	status_t error = fDevice->SetInputFrameRate(multiAudioRate);
2339	if (error != B_OK)
2340		return error;
2341
2342	// it went fine -- update all formats
2343	fInputPreferredFormat.u.raw_audio.frame_rate = frameRate;
2344	fInputPreferredFormat.u.raw_audio.buffer_size
2345		= fDevice->BufferList().return_record_buffer_size
2346			* (fInputPreferredFormat.u.raw_audio.format
2347				& media_raw_audio_format::B_AUDIO_SIZE_MASK)
2348			* fInputPreferredFormat.u.raw_audio.channel_count;
2349
2350	for (int32 i = 0; node_output* channel = (node_output*)fOutputs.ItemAt(i);
2351			i++) {
2352		channel->fPreferredFormat.u.raw_audio.frame_rate = frameRate;
2353		channel->fPreferredFormat.u.raw_audio.buffer_size
2354			= fInputPreferredFormat.u.raw_audio.buffer_size;
2355
2356		channel->fFormat.u.raw_audio.frame_rate = frameRate;
2357		channel->fFormat.u.raw_audio.buffer_size
2358			= fInputPreferredFormat.u.raw_audio.buffer_size;
2359
2360		channel->fOutput.format.u.raw_audio.frame_rate = frameRate;
2361		channel->fOutput.format.u.raw_audio.buffer_size
2362			= fInputPreferredFormat.u.raw_audio.buffer_size;
2363	}
2364
2365	// make sure the time base is reset
2366	fTimeComputer.SetFrameRate(frameRate);
2367
2368	// update internal latency
2369	_UpdateInternalLatency(fInputPreferredFormat);
2370
2371	return B_OK;
2372}
2373
2374
2375void
2376MultiAudioNode::_UpdateInternalLatency(const media_format& format)
2377{
2378	// use half a buffer length latency
2379	fInternalLatency = format.u.raw_audio.buffer_size * 10000 / 2
2380		/ ((format.u.raw_audio.format
2381				& media_raw_audio_format::B_AUDIO_SIZE_MASK)
2382			* format.u.raw_audio.channel_count)
2383		/ ((int32)(format.u.raw_audio.frame_rate / 100));
2384
2385	PRINT(("  internal latency = %lld\n",fInternalLatency));
2386
2387	SetEventLatency(fInternalLatency);
2388}
2389