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