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