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