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