xref: /haiku/src/add-ons/media/media-add-ons/multi_audio/MultiAudioNode.cpp (revision 5629675a326ecf2ff3fd23f154beb525c171048d)
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 	}
1260 	return B_OK;
1261 }
1262 
1263 
1264 status_t
1265 MultiAudioNode::_HandleSeek(const media_timed_event* event, bigtime_t lateness,
1266 	bool realTimeEvent)
1267 {
1268 	CALLED();
1269 	PRINT(("MultiAudioNode::HandleSeek(t=%" B_PRIdBIGTIME ",d=%" B_PRIi32
1270 			",bd=%" B_PRId64 ")\n",
1271 		event->event_time,event->data,event->bigdata));
1272 	return B_OK;
1273 }
1274 
1275 
1276 status_t
1277 MultiAudioNode::_HandleWarp(const media_timed_event* event, bigtime_t lateness,
1278 	bool realTimeEvent)
1279 {
1280 	CALLED();
1281 	return B_OK;
1282 }
1283 
1284 
1285 status_t
1286 MultiAudioNode::_HandleStop(const media_timed_event* event, bigtime_t lateness,
1287 	bool realTimeEvent)
1288 {
1289 	CALLED();
1290 	// flush the queue so downstreamers don't get any more
1291 	EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true,
1292 		BTimedEventQueue::B_HANDLE_BUFFER);
1293 
1294 	//_StopOutputThread();
1295 	return B_OK;
1296 }
1297 
1298 
1299 status_t
1300 MultiAudioNode::_HandleParameter(const media_timed_event* event,
1301 	bigtime_t lateness, bool realTimeEvent)
1302 {
1303 	CALLED();
1304 	return B_OK;
1305 }
1306 
1307 
1308 //	#pragma mark - BTimeSource
1309 
1310 
1311 void
1312 MultiAudioNode::SetRunMode(run_mode mode)
1313 {
1314 	CALLED();
1315 	PRINT(("MultiAudioNode::SetRunMode mode:%i\n", mode));
1316 	//BTimeSource::SetRunMode(mode);
1317 }
1318 
1319 
1320 status_t
1321 MultiAudioNode::TimeSourceOp(const time_source_op_info& op, void* _reserved)
1322 {
1323 	CALLED();
1324 	switch (op.op) {
1325 		case B_TIMESOURCE_START:
1326 			PRINT(("TimeSourceOp op B_TIMESOURCE_START\n"));
1327 			if (RunState() != BMediaEventLooper::B_STARTED) {
1328 				fTimeSourceStarted = true;
1329 				_StartOutputThreadIfNeeded();
1330 
1331 				media_timed_event startEvent(0, BTimedEventQueue::B_START);
1332 				EventQueue()->AddEvent(startEvent);
1333 			}
1334 			break;
1335 		case B_TIMESOURCE_STOP:
1336 			PRINT(("TimeSourceOp op B_TIMESOURCE_STOP\n"));
1337 			if (RunState() == BMediaEventLooper::B_STARTED) {
1338 				media_timed_event stopEvent(0, BTimedEventQueue::B_STOP);
1339 				EventQueue()->AddEvent(stopEvent);
1340 				fTimeSourceStarted = false;
1341 				_StopOutputThread();
1342 				PublishTime(0, 0, 0);
1343 			}
1344 			break;
1345 		case B_TIMESOURCE_STOP_IMMEDIATELY:
1346 			PRINT(("TimeSourceOp op B_TIMESOURCE_STOP_IMMEDIATELY\n"));
1347 			if (RunState() == BMediaEventLooper::B_STARTED) {
1348 				media_timed_event stopEvent(0, BTimedEventQueue::B_STOP);
1349 				EventQueue()->AddEvent(stopEvent);
1350 				fTimeSourceStarted = false;
1351 				_StopOutputThread();
1352 				PublishTime(0, 0, 0);
1353 			}
1354 			break;
1355 		case B_TIMESOURCE_SEEK:
1356 			PRINT(("TimeSourceOp op B_TIMESOURCE_SEEK\n"));
1357 			BroadcastTimeWarp(op.real_time, op.performance_time);
1358 			break;
1359 		default:
1360 			break;
1361 	}
1362 	return B_OK;
1363 }
1364 
1365 
1366 //	#pragma mark - BControllable
1367 
1368 
1369 status_t
1370 MultiAudioNode::GetParameterValue(int32 id, bigtime_t* lastChange, void* value,
1371 	size_t* size)
1372 {
1373 	CALLED();
1374 
1375 	PRINT(("id: %" B_PRIi32 "\n", id));
1376 	BParameter* parameter = NULL;
1377 	for (int32 i = 0; i < fWeb->CountParameters(); i++) {
1378 		parameter = fWeb->ParameterAt(i);
1379 		if (parameter->ID() == id)
1380 			break;
1381 	}
1382 
1383 	if (parameter == NULL) {
1384 		// Hmmm, we were asked for a parameter that we don't actually
1385 		// support.  Report an error back to the caller.
1386 		PRINT(("\terror - asked for illegal parameter %" B_PRId32 "\n", id));
1387 		return B_ERROR;
1388 	}
1389 
1390 	if (id == PARAMETER_ID_INPUT_FREQUENCY
1391 		|| id == PARAMETER_ID_OUTPUT_FREQUENCY) {
1392 		const multi_format_info& info = fDevice->FormatInfo();
1393 
1394 		uint32 rate = id == PARAMETER_ID_INPUT_FREQUENCY
1395 			? info.input.rate : info.output.rate;
1396 
1397 		if (*size < sizeof(rate))
1398 			return B_ERROR;
1399 
1400 		memcpy(value, &rate, sizeof(rate));
1401 		*size = sizeof(rate);
1402 		return B_OK;
1403 	}
1404 
1405 	multi_mix_value_info info;
1406 	multi_mix_value values[2];
1407 	info.values = values;
1408 	info.item_count = 0;
1409 	multi_mix_control* controls = fDevice->MixControlInfo().controls;
1410 	int32 control_id = controls[id - 100].id;
1411 
1412 	if (*size < sizeof(float))
1413 		return B_ERROR;
1414 
1415 	if (parameter->Type() == BParameter::B_CONTINUOUS_PARAMETER) {
1416 		info.item_count = 1;
1417 		values[0].id = control_id;
1418 
1419 		if (parameter->CountChannels() == 2) {
1420 			if (*size < 2*sizeof(float))
1421 				return B_ERROR;
1422 			info.item_count = 2;
1423 			values[1].id = controls[id + 1 - 100].id;
1424 		}
1425 	} else if (parameter->Type() == BParameter::B_DISCRETE_PARAMETER) {
1426 		info.item_count = 1;
1427 		values[0].id = control_id;
1428 	}
1429 
1430 	if (info.item_count > 0) {
1431 		status_t status = fDevice->GetMix(&info);
1432 		if (status != B_OK) {
1433 			fprintf(stderr, "Failed on DRIVER_GET_MIX\n");
1434 		} else {
1435 			if (parameter->Type() == BParameter::B_CONTINUOUS_PARAMETER) {
1436 				((float*)value)[0] = values[0].gain;
1437 				*size = sizeof(float);
1438 
1439 				if (parameter->CountChannels() == 2) {
1440 					((float*)value)[1] = values[1].gain;
1441 					*size = 2*sizeof(float);
1442 				}
1443 
1444 				for (uint32 i = 0; i < *size / sizeof(float); i++) {
1445 					PRINT(("GetParameterValue B_CONTINUOUS_PARAMETER value[%"
1446 						B_PRIi32 "]: %f\n", i, ((float*)value)[i]));
1447 				}
1448 			} else if (parameter->Type() == BParameter::B_DISCRETE_PARAMETER) {
1449 				BDiscreteParameter* discrete = (BDiscreteParameter*)parameter;
1450 				if (discrete->CountItems() <= 2)
1451 					((int32*)value)[0] = values[0].enable ? 1 : 0;
1452 				else
1453 					((int32*)value)[0] = values[0].mux;
1454 
1455 				*size = sizeof(int32);
1456 
1457 				for (uint32 i = 0; i < *size / sizeof(int32); i++) {
1458 					PRINT(("GetParameterValue B_DISCRETE_PARAMETER value[%"
1459 						B_PRIi32 "]: %" B_PRIi32 "\n", i, ((int32*)value)[i]));
1460 				}
1461 			}
1462 		}
1463 	}
1464 	return B_OK;
1465 }
1466 
1467 
1468 void
1469 MultiAudioNode::SetParameterValue(int32 id, bigtime_t performanceTime,
1470 	const void* value, size_t size)
1471 {
1472 	CALLED();
1473 	PRINT(("id: %" B_PRIi32 ", performance_time: %" B_PRIdBIGTIME
1474 		", size: %" B_PRIuSIZE "\n", id, performanceTime, size));
1475 
1476 	BParameter* parameter = NULL;
1477 	for (int32 i = 0; i < fWeb->CountParameters(); i++) {
1478 		parameter = fWeb->ParameterAt(i);
1479 		if (parameter->ID() == id)
1480 			break;
1481 	}
1482 
1483 	if (parameter == NULL)
1484 		return;
1485 
1486 	if (id == PARAMETER_ID_OUTPUT_FREQUENCY
1487 		|| (id == PARAMETER_ID_INPUT_FREQUENCY
1488 			&& (fDevice->Description().output_rates
1489 				& B_SR_SAME_AS_INPUT) != 0)) {
1490 		uint32 rate;
1491 		if (size < sizeof(rate))
1492 			return;
1493 		memcpy(&rate, value, sizeof(rate));
1494 
1495 		if (rate == fOutputPreferredFormat.u.raw_audio.frame_rate)
1496 			return;
1497 
1498 		// create a cookie RequestCompleted() can get the old frame rate from,
1499 		// if anything goes wrong
1500 		FrameRateChangeCookie* cookie = new(std::nothrow) FrameRateChangeCookie;
1501 		if (cookie == NULL)
1502 			return;
1503 
1504 		cookie->oldFrameRate = fOutputPreferredFormat.u.raw_audio.frame_rate;
1505 		cookie->id = id;
1506 		BReference<FrameRateChangeCookie> cookieReference(cookie, true);
1507 
1508 		// NOTE: What we should do is call RequestFormatChange() for all
1509 		// connections and change the device's format in RequestCompleted().
1510 		// Unfortunately we need the new buffer size first, which we only get
1511 		// from the device after changing the format. So we do that now and
1512 		// reset it in RequestCompleted(), if something went wrong. This causes
1513 		// the buffers we receive until then to be played incorrectly leading
1514 		// to unpleasant noise.
1515 		float frameRate = MultiAudio::convert_to_sample_rate(rate);
1516 		if (_SetNodeInputFrameRate(frameRate) != B_OK)
1517 			return;
1518 
1519 		for (int32 i = 0; i < fInputs.CountItems(); i++) {
1520 			node_input* channel = (node_input*)fInputs.ItemAt(i);
1521 			if (channel->fInput.source == media_source::null)
1522 				continue;
1523 
1524 			media_format newFormat = channel->fInput.format;
1525 			newFormat.u.raw_audio.frame_rate = frameRate;
1526 			newFormat.u.raw_audio.buffer_size
1527 				= fOutputPreferredFormat.u.raw_audio.buffer_size;
1528 
1529 			int32 changeTag = 0;
1530 			status_t error = RequestFormatChange(channel->fInput.source,
1531 				channel->fInput.destination, newFormat, NULL, &changeTag);
1532 			if (error == B_OK)
1533 				cookie->AcquireReference();
1534 		}
1535 
1536 		if (id != PARAMETER_ID_INPUT_FREQUENCY)
1537 			return;
1538 		//Do not return cause we should go in the next if
1539 	}
1540 
1541 	if (id == PARAMETER_ID_INPUT_FREQUENCY) {
1542 		uint32 rate;
1543 		if (size < sizeof(rate))
1544 			return;
1545 		memcpy(&rate, value, sizeof(rate));
1546 
1547 		if (rate == fInputPreferredFormat.u.raw_audio.frame_rate)
1548 			return;
1549 
1550 		// create a cookie RequestCompleted() can get the old frame rate from,
1551 		// if anything goes wrong
1552 		FrameRateChangeCookie* cookie = new(std::nothrow) FrameRateChangeCookie;
1553 		if (cookie == NULL)
1554 			return;
1555 
1556 		cookie->oldFrameRate = fInputPreferredFormat.u.raw_audio.frame_rate;
1557 		cookie->id = id;
1558 		BReference<FrameRateChangeCookie> cookieReference(cookie, true);
1559 
1560 		// NOTE: What we should do is call RequestFormatChange() for all
1561 		// connections and change the device's format in RequestCompleted().
1562 		// Unfortunately we need the new buffer size first, which we only get
1563 		// from the device after changing the format. So we do that now and
1564 		// reset it in RequestCompleted(), if something went wrong. This causes
1565 		// the buffers we receive until then to be played incorrectly leading
1566 		// to unpleasant noise.
1567 		float frameRate = MultiAudio::convert_to_sample_rate(rate);
1568 		if (_SetNodeOutputFrameRate(frameRate) != B_OK)
1569 			return;
1570 
1571 		for (int32 i = 0; i < fOutputs.CountItems(); i++) {
1572 			node_output* channel = (node_output*)fOutputs.ItemAt(i);
1573 			if (channel->fOutput.source == media_source::null)
1574 				continue;
1575 
1576 			media_format newFormat = channel->fOutput.format;
1577 			newFormat.u.raw_audio.frame_rate = frameRate;
1578 			newFormat.u.raw_audio.buffer_size
1579 				= fInputPreferredFormat.u.raw_audio.buffer_size;
1580 
1581 			int32 changeTag = 0;
1582 			status_t error = RequestFormatChange(channel->fOutput.source,
1583 				channel->fOutput.destination, newFormat, NULL, &changeTag);
1584 			if (error == B_OK)
1585 				cookie->AcquireReference();
1586 		}
1587 
1588 		return;
1589 	}
1590 
1591 	multi_mix_value_info info;
1592 	multi_mix_value values[2];
1593 	info.values = values;
1594 	info.item_count = 0;
1595 	multi_mix_control* controls = fDevice->MixControlInfo().controls;
1596 	int32 control_id = controls[id - 100].id;
1597 
1598 	if (parameter->Type() == BParameter::B_CONTINUOUS_PARAMETER) {
1599 		for (uint32 i = 0; i < size / sizeof(float); i++) {
1600 			PRINT(("SetParameterValue B_CONTINUOUS_PARAMETER value[%" B_PRIi32
1601 				"]: %f\n", i, ((float*)value)[i]));
1602 		}
1603 		info.item_count = 1;
1604 		values[0].id = control_id;
1605 		values[0].gain = ((float*)value)[0];
1606 
1607 		if (parameter->CountChannels() == 2) {
1608 			info.item_count = 2;
1609 			values[1].id = controls[id + 1 - 100].id;
1610 			values[1].gain = ((float*)value)[1];
1611 		}
1612 	} else if (parameter->Type() == BParameter::B_DISCRETE_PARAMETER) {
1613 		for (uint32 i = 0; i < size / sizeof(int32); i++) {
1614 			PRINT(("SetParameterValue B_DISCRETE_PARAMETER value[%" B_PRIi32
1615 				"]: %" B_PRIi32 "\n", i, ((int32*)value)[i]));
1616 		}
1617 
1618 		BDiscreteParameter* discrete = (BDiscreteParameter*)parameter;
1619 		if (discrete->CountItems() <= 2) {
1620 			info.item_count = 1;
1621 			values[0].id = control_id;
1622 			values[0].enable = ((int32*)value)[0] == 1;
1623 		} else {
1624 			info.item_count = 1;
1625 			values[0].id = control_id;
1626 			values[0].mux = ((uint32*)value)[0];
1627 		}
1628 	}
1629 
1630 	if (info.item_count > 0) {
1631 		status_t status = fDevice->SetMix(&info);
1632 		if (status != B_OK)
1633 			fprintf(stderr, "Failed on DRIVER_SET_MIX\n");
1634 	}
1635 }
1636 
1637 
1638 BParameterWeb*
1639 MultiAudioNode::MakeParameterWeb()
1640 {
1641 	CALLED();
1642 	BParameterWeb* web = new BParameterWeb();
1643 
1644 	PRINT(("MixControlInfo().control_count: %" B_PRIi32 "\n",
1645 		fDevice->MixControlInfo().control_count));
1646 
1647 	BParameterGroup* generalGroup = web->MakeGroup(B_TRANSLATE("General"));
1648 
1649 	const multi_description& description = fDevice->Description();
1650 
1651 	if ((description.output_rates & B_SR_SAME_AS_INPUT) != 0) {
1652 		_CreateFrequencyParameterGroup(generalGroup,
1653 			B_TRANSLATE("Input & Output"), PARAMETER_ID_INPUT_FREQUENCY,
1654 			description.input_rates);
1655 	} else {
1656 		_CreateFrequencyParameterGroup(generalGroup, B_TRANSLATE("Input"),
1657 			PARAMETER_ID_INPUT_FREQUENCY, description.input_rates);
1658 		_CreateFrequencyParameterGroup(generalGroup, B_TRANSLATE("Output"),
1659 			PARAMETER_ID_OUTPUT_FREQUENCY, description.output_rates);
1660 	}
1661 
1662 	multi_mix_control* controls = fDevice->MixControlInfo().controls;
1663 
1664 	for (int i = 0; i < fDevice->MixControlInfo().control_count; i++) {
1665 		if ((controls[i].flags & B_MULTI_MIX_GROUP) != 0
1666 			&& controls[i].parent == 0) {
1667 			PRINT(("NEW_GROUP\n"));
1668 			BParameterGroup* child = web->MakeGroup(
1669 				_GetControlName(controls[i]));
1670 
1671 			int32 numParameters = 0;
1672 			_ProcessGroup(child, i, numParameters);
1673 		}
1674 	}
1675 
1676 	return web;
1677 }
1678 
1679 
1680 const char*
1681 MultiAudioNode::_GetControlName(multi_mix_control& control)
1682 {
1683 	if (control.string != S_null)
1684 		return kMultiControlString[control.string];
1685 
1686 	return control.name;
1687 }
1688 
1689 
1690 void
1691 MultiAudioNode::_ProcessGroup(BParameterGroup* group, int32 index,
1692 	int32& numParameters)
1693 {
1694 	CALLED();
1695 	multi_mix_control* parent = &fDevice->MixControlInfo().controls[index];
1696 	multi_mix_control* controls = fDevice->MixControlInfo().controls;
1697 
1698 	for (int32 i = 0; i < fDevice->MixControlInfo().control_count; i++) {
1699 		if (controls[i].parent != parent->id)
1700 			continue;
1701 
1702 		const char* name = _GetControlName(controls[i]);
1703 
1704 		if (controls[i].flags & B_MULTI_MIX_GROUP) {
1705 			PRINT(("NEW_GROUP\n"));
1706 			BParameterGroup* child = group->MakeGroup(name);
1707 			child->MakeNullParameter(100 + i, B_MEDIA_RAW_AUDIO, name,
1708 				B_WEB_BUFFER_OUTPUT);
1709 
1710 			int32 num = 1;
1711 			_ProcessGroup(child, i, num);
1712 		} else if (controls[i].flags & B_MULTI_MIX_MUX) {
1713 			PRINT(("NEW_MUX\n"));
1714 			BDiscreteParameter* parameter = group->MakeDiscreteParameter(
1715 				100 + i, B_MEDIA_RAW_AUDIO, name, B_INPUT_MUX);
1716 			if (numParameters > 0) {
1717 				(group->ParameterAt(numParameters - 1))->AddOutput(
1718 					group->ParameterAt(numParameters));
1719 				numParameters++;
1720 			}
1721 			_ProcessMux(parameter, i);
1722 		} else if (controls[i].flags & B_MULTI_MIX_GAIN) {
1723 			PRINT(("NEW_GAIN\n"));
1724 			group->MakeContinuousParameter(100 + i,
1725 				B_MEDIA_RAW_AUDIO, "", B_MASTER_GAIN, "dB",
1726 				controls[i].gain.min_gain, controls[i].gain.max_gain,
1727 				controls[i].gain.granularity);
1728 
1729 			if (i + 1 < fDevice->MixControlInfo().control_count
1730 				&& controls[i + 1].master == controls[i].id
1731 				&& (controls[i + 1].flags & B_MULTI_MIX_GAIN) != 0) {
1732 				group->ParameterAt(numParameters)->SetChannelCount(
1733 					group->ParameterAt(numParameters)->CountChannels() + 1);
1734 				i++;
1735 			}
1736 
1737 			PRINT(("num parameters: %" B_PRId32 "\n", numParameters));
1738 			if (numParameters > 0) {
1739 				group->ParameterAt(numParameters - 1)->AddOutput(
1740 					group->ParameterAt(numParameters));
1741 				numParameters++;
1742 			}
1743 		} else if (controls[i].flags & B_MULTI_MIX_ENABLE) {
1744 			PRINT(("NEW_ENABLE\n"));
1745 			if (controls[i].string == S_MUTE) {
1746 				group->MakeDiscreteParameter(100 + i,
1747 					B_MEDIA_RAW_AUDIO, name, B_MUTE);
1748 			} else {
1749 				group->MakeDiscreteParameter(100 + i,
1750 					B_MEDIA_RAW_AUDIO, name, B_ENABLE);
1751 			}
1752 			if (numParameters > 0) {
1753 				group->ParameterAt(numParameters - 1)->AddOutput(
1754 					group->ParameterAt(numParameters));
1755 				numParameters++;
1756 			}
1757 		}
1758 	}
1759 }
1760 
1761 
1762 void
1763 MultiAudioNode::_ProcessMux(BDiscreteParameter* parameter, int32 index)
1764 {
1765 	CALLED();
1766 	multi_mix_control* parent = &fDevice->MixControlInfo().controls[index];
1767 	multi_mix_control* controls = fDevice->MixControlInfo().controls;
1768 	int32 itemIndex = 0;
1769 
1770 	for (int32 i = 0; i < fDevice->MixControlInfo().control_count; i++) {
1771 		if (controls[i].parent != parent->id)
1772 			continue;
1773 
1774 		if ((controls[i].flags & B_MULTI_MIX_MUX_VALUE) != 0) {
1775 			PRINT(("NEW_MUX_VALUE\n"));
1776 			parameter->AddItem(itemIndex, _GetControlName(controls[i]));
1777 			itemIndex++;
1778 		}
1779 	}
1780 }
1781 
1782 
1783 void
1784 MultiAudioNode::_CreateFrequencyParameterGroup(BParameterGroup* parentGroup,
1785 	const char* name, int32 parameterID, uint32 rateMask)
1786 {
1787 	BParameterGroup* group = parentGroup->MakeGroup(name);
1788 	BDiscreteParameter* frequencyParam = group->MakeDiscreteParameter(
1789 		parameterID, B_MEDIA_NO_TYPE,
1790 		BString(name) << B_TRANSLATE(" frequency:"),
1791 		B_GENERIC);
1792 
1793 	for (int32 i = 0; kSampleRateInfos[i].name != NULL; i++) {
1794 		const sample_rate_info& info = kSampleRateInfos[i];
1795 		if ((rateMask & info.multiAudioRate) != 0) {
1796 			frequencyParam->AddItem(info.multiAudioRate,
1797 				BString(info.name) << " Hz");
1798 		}
1799 	}
1800 }
1801 
1802 
1803 //	#pragma mark - MultiAudioNode specific functions
1804 
1805 
1806 int32
1807 MultiAudioNode::_OutputThread()
1808 {
1809 	CALLED();
1810 	multi_buffer_info bufferInfo;
1811 	bufferInfo.info_size = sizeof(multi_buffer_info);
1812 	bufferInfo.playback_buffer_cycle = 0;
1813 	bufferInfo.record_buffer_cycle = 0;
1814 
1815 	// init the performance time computation
1816 	{
1817 		BAutolock locker(fBufferLock);
1818 		fTimeComputer.Init(fOutputPreferredFormat.u.raw_audio.frame_rate,
1819 			system_time());
1820 	}
1821 
1822 	while (atomic_get(&fQuitThread) == 0) {
1823 		BAutolock locker(fBufferLock);
1824 			// make sure the buffers don't change while we're playing with them
1825 
1826 		// send buffer
1827 		fDevice->BufferExchange(&bufferInfo);
1828 
1829 		//PRINT(("MultiAudioNode::RunThread: buffer exchanged\n"));
1830 		//PRINT(("MultiAudioNode::RunThread: played_real_time: %Ld\n", bufferInfo.played_real_time));
1831 		//PRINT(("MultiAudioNode::RunThread: played_frames_count: %Ld\n", bufferInfo.played_frames_count));
1832 		//PRINT(("MultiAudioNode::RunThread: buffer_cycle: %li\n", bufferInfo.playback_buffer_cycle));
1833 
1834 		for (int32 i = 0; i < fInputs.CountItems(); i++) {
1835 			node_input* input = (node_input*)fInputs.ItemAt(i);
1836 
1837 			if (bufferInfo.playback_buffer_cycle >= 0
1838 				&& bufferInfo.playback_buffer_cycle
1839 						< fDevice->BufferList().return_playback_buffers
1840 				&& (input->fOldBufferInfo.playback_buffer_cycle
1841 						!= bufferInfo.playback_buffer_cycle
1842 					|| fDevice->BufferList().return_playback_buffers == 1)
1843 				&& (input->fInput.source != media_source::null
1844 					|| input->fChannelId == 0)) {
1845 				//PRINT(("playback_buffer_cycle ok input: %li %ld\n", i, bufferInfo.playback_buffer_cycle));
1846 
1847 				input->fBufferCycle = (bufferInfo.playback_buffer_cycle - 1
1848 						+ fDevice->BufferList().return_playback_buffers)
1849 					% fDevice->BufferList().return_playback_buffers;
1850 
1851 				// update the timesource
1852 				if (input->fChannelId == 0) {
1853 					//PRINT(("updating timesource\n"));
1854 					_UpdateTimeSource(bufferInfo, input->fOldBufferInfo,
1855 						*input);
1856 				}
1857 
1858 				input->fOldBufferInfo = bufferInfo;
1859 
1860 				if (input->fBuffer != NULL) {
1861 					_FillNextBuffer(*input, input->fBuffer);
1862 					input->fBuffer->Recycle();
1863 					input->fBuffer = NULL;
1864 				} else {
1865 					// put zeros in current buffer
1866 					if (input->fInput.source != media_source::null)
1867 						_WriteZeros(*input, input->fBufferCycle);
1868 					//PRINT(("MultiAudioNode::Runthread WriteZeros\n"));
1869 				}
1870 			} else {
1871 				//PRINT(("playback_buffer_cycle non ok input: %i\n", i));
1872 			}
1873 		}
1874 
1875 		PRINT(("MultiAudioNode::RunThread: recorded_real_time: %" B_PRIdBIGTIME
1876 				"\n", bufferInfo.recorded_real_time));
1877 		PRINT(("MultiAudioNode::RunThread: recorded_frames_count: %"
1878 				B_PRId64 "\n", bufferInfo.recorded_frames_count));
1879 		PRINT(("MultiAudioNode::RunThread: record_buffer_cycle: %" B_PRIi32
1880 				"\n", bufferInfo.record_buffer_cycle));
1881 
1882 		for (int32 i = 0; i < fOutputs.CountItems(); i++) {
1883 			node_output* output = (node_output*)fOutputs.ItemAt(i);
1884 
1885 			// make sure we're both started *and* connected before delivering a
1886 			// buffer
1887 			if (RunState() == BMediaEventLooper::B_STARTED
1888 				&& output->fOutput.destination != media_destination::null) {
1889 				if (bufferInfo.record_buffer_cycle >= 0
1890 					&& bufferInfo.record_buffer_cycle
1891 							< fDevice->BufferList().return_record_buffers
1892 					&& (output->fOldBufferInfo.record_buffer_cycle
1893 							!= bufferInfo.record_buffer_cycle
1894 						|| fDevice->BufferList().return_record_buffers == 1)) {
1895 					//PRINT(("record_buffer_cycle ok\n"));
1896 
1897 					output->fBufferCycle = bufferInfo.record_buffer_cycle;
1898 
1899 					// Get the next buffer of data
1900 					BBuffer* buffer = _FillNextBuffer(bufferInfo, *output);
1901 					if (buffer != NULL) {
1902 						// send the buffer downstream if and only if output is
1903 						// enabled
1904 						status_t err = B_ERROR;
1905 						if (output->fOutputEnabled) {
1906 							err = SendBuffer(buffer, output->fOutput.source,
1907 								output->fOutput.destination);
1908 						}
1909 						if (err != B_OK) {
1910 							buffer->Recycle();
1911 						} else {
1912 							// track how much media we've delivered so far
1913 							size_t numSamples
1914 								= output->fOutput.format.u.raw_audio.buffer_size
1915 									/ (output->fOutput.format.u.raw_audio.format
1916 										& media_raw_audio_format
1917 											::B_AUDIO_SIZE_MASK);
1918 							output->fSamplesSent += numSamples;
1919 						}
1920 					}
1921 
1922 					output->fOldBufferInfo = bufferInfo;
1923 				} else {
1924 					//PRINT(("record_buffer_cycle non ok\n"));
1925 				}
1926 			}
1927 		}
1928 	}
1929 
1930 	return B_OK;
1931 }
1932 
1933 
1934 void
1935 MultiAudioNode::_WriteZeros(node_input& input, uint32 bufferCycle)
1936 {
1937 	//CALLED();
1938 	/*int32 samples = input.fInput.format.u.raw_audio.buffer_size;
1939 	if(input.fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_UCHAR) {
1940 		uint8 *sample = (uint8*)fDevice->BufferList().playback_buffers[input.fBufferCycle][input.fChannelId].base;
1941 		for(int32 i = samples-1; i>=0; i--)
1942 			*sample++ = 128;
1943 	} else {
1944 		int32 *sample = (int32*)fDevice->BufferList().playback_buffers[input.fBufferCycle][input.fChannelId].base;
1945 		for(int32 i = (samples / 4)-1; i>=0; i--)
1946 			*sample++ = 0;
1947 	}*/
1948 
1949 	uint32 channelCount = input.fFormat.u.raw_audio.channel_count;
1950 	uint32 bufferSize = fDevice->BufferList().return_playback_buffer_size;
1951 	size_t stride = fDevice->BufferList().playback_buffers[bufferCycle]
1952 		[input.fChannelId].stride;
1953 
1954 	switch (input.fFormat.u.raw_audio.format) {
1955 		case media_raw_audio_format::B_AUDIO_FLOAT:
1956 			for (uint32 channel = 0; channel < channelCount; channel++) {
1957 				char* dest = _PlaybackBuffer(bufferCycle,
1958 					input.fChannelId + channel);
1959 				for (uint32 i = bufferSize; i > 0; i--) {
1960 					*(float*)dest = 0;
1961 					dest += stride;
1962 				}
1963 			}
1964 			break;
1965 
1966 		case media_raw_audio_format::B_AUDIO_DOUBLE:
1967 			for (uint32 channel = 0; channel < channelCount; channel++) {
1968 				char* dest = _PlaybackBuffer(bufferCycle,
1969 					input.fChannelId + channel);
1970 				for (uint32 i = bufferSize; i > 0; i--) {
1971 					*(double*)dest = 0;
1972 					dest += stride;
1973 				}
1974 			}
1975 			break;
1976 
1977 		case media_raw_audio_format::B_AUDIO_INT:
1978 			for (uint32 channel = 0; channel < channelCount; channel++) {
1979 				char* dest = _PlaybackBuffer(bufferCycle,
1980 					input.fChannelId + channel);
1981 				for (uint32 i = bufferSize; i > 0; i--) {
1982 					*(int32*)dest = 0;
1983 					dest += stride;
1984 				}
1985 			}
1986 			break;
1987 
1988 		case media_raw_audio_format::B_AUDIO_SHORT:
1989 			for (uint32 channel = 0; channel < channelCount; channel++) {
1990 				char* dest = _PlaybackBuffer(bufferCycle,
1991 					input.fChannelId + channel);
1992 				for (uint32 i = bufferSize; i > 0; i--) {
1993 					*(int16*)dest = 0;
1994 					dest += stride;
1995 				}
1996 			}
1997 			break;
1998 
1999 		case media_raw_audio_format::B_AUDIO_UCHAR:
2000 			for (uint32 channel = 0; channel < channelCount; channel++) {
2001 				char* dest = _PlaybackBuffer(bufferCycle,
2002 					input.fChannelId + channel);
2003 				for (uint32 i = bufferSize; i > 0; i--) {
2004 					*(uint8*)dest = 128;
2005 					dest += stride;
2006 				}
2007 			}
2008 			break;
2009 
2010 		case media_raw_audio_format::B_AUDIO_CHAR:
2011 			for (uint32 channel = 0; channel < channelCount; channel++) {
2012 				char* dest = _PlaybackBuffer(bufferCycle,
2013 					input.fChannelId + channel);
2014 				for (uint32 i = bufferSize; i > 0; i--) {
2015 					*(int8*)dest = 0;
2016 					dest += stride;
2017 				}
2018 			}
2019 			break;
2020 
2021 		default:
2022 			fprintf(stderr, "ERROR in WriteZeros format not handled\n");
2023 	}
2024 }
2025 
2026 
2027 void
2028 MultiAudioNode::_FillWithZeros(node_input& input)
2029 {
2030 	CALLED();
2031 	for (int32 i = 0; i < fDevice->BufferList().return_playback_buffers; i++)
2032 		_WriteZeros(input, i);
2033 }
2034 
2035 
2036 void
2037 MultiAudioNode::_FillNextBuffer(node_input& input, BBuffer* buffer)
2038 {
2039 	uint32 channelCount = input.fInput.format.u.raw_audio.channel_count;
2040 	size_t inputSampleSize = input.fInput.format.u.raw_audio.format
2041 			& media_raw_audio_format::B_AUDIO_SIZE_MASK;
2042 
2043 	uint32 bufferSize = fDevice->BufferList().return_playback_buffer_size;
2044 
2045 	if (buffer->SizeUsed() / inputSampleSize / channelCount != bufferSize) {
2046 		_WriteZeros(input, input.fBufferCycle);
2047 		return;
2048 	}
2049 
2050 	if (channelCount != input.fFormat.u.raw_audio.channel_count) {
2051 		PRINT(("Channel count is different"));
2052 		return;
2053 	}
2054 
2055 	if (input.fResampler != NULL) {
2056 		size_t srcStride = channelCount * inputSampleSize;
2057 
2058 		for (uint32 channel = 0; channel < channelCount; channel++) {
2059 			char* src = (char*)buffer->Data() + channel * inputSampleSize;
2060 			char* dst = _PlaybackBuffer(input.fBufferCycle,
2061 							input.fChannelId + channel);
2062 			size_t dstStride = _PlaybackStride(input.fBufferCycle,
2063 							input.fChannelId + channel);
2064 
2065 			input.fResampler->Resample(src, srcStride,
2066 				dst, dstStride, bufferSize);
2067 		}
2068 	}
2069 }
2070 
2071 
2072 status_t
2073 MultiAudioNode::_StartOutputThreadIfNeeded()
2074 {
2075 	CALLED();
2076 	// the thread is already started ?
2077 	if (fThread >= 0)
2078 		return B_OK;
2079 
2080 	PublishTime(-50, 0, 0);
2081 
2082 	fThread = spawn_thread(_OutputThreadEntry, "multi_audio audio output",
2083 		B_REAL_TIME_PRIORITY, this);
2084 	if (fThread < 0)
2085 		return fThread;
2086 
2087 	resume_thread(fThread);
2088 	return B_OK;
2089 }
2090 
2091 
2092 status_t
2093 MultiAudioNode::_StopOutputThread()
2094 {
2095 	CALLED();
2096 	atomic_set(&fQuitThread, 1);
2097 
2098 	wait_for_thread(fThread, NULL);
2099 	fThread = -1;
2100 	return B_OK;
2101 }
2102 
2103 
2104 void
2105 MultiAudioNode::_AllocateBuffers(node_output &channel)
2106 {
2107 	CALLED();
2108 
2109 	// allocate enough buffers to span our downstream latency, plus one
2110 	size_t size = channel.fOutput.format.u.raw_audio.buffer_size;
2111 	int32 count = int32(fLatency / BufferDuration() + 1 + 1);
2112 
2113 	PRINT(("\tlatency = %" B_PRIdBIGTIME ", buffer duration = %" B_PRIdBIGTIME
2114 			"\n", fLatency, BufferDuration()));
2115 	PRINT(("\tcreating group of %" B_PRId32 " buffers, size = %" B_PRIuSIZE
2116 			"\n", count, size));
2117 	channel.fBufferGroup = new BBufferGroup(size, count);
2118 }
2119 
2120 
2121 void
2122 MultiAudioNode::_UpdateTimeSource(multi_buffer_info& info,
2123 	multi_buffer_info& oldInfo, node_input& input)
2124 {
2125 	//CALLED();
2126 	if (!fTimeSourceStarted || oldInfo.played_real_time == 0)
2127 		return;
2128 
2129 	fTimeComputer.AddTimeStamp(info.played_real_time,
2130 		info.played_frames_count);
2131 	PublishTime(fTimeComputer.PerformanceTime(), fTimeComputer.RealTime(),
2132 		fTimeComputer.Drift());
2133 }
2134 
2135 
2136 BBuffer*
2137 MultiAudioNode::_FillNextBuffer(multi_buffer_info& info, node_output& output)
2138 {
2139 	//CALLED();
2140 	// get a buffer from our buffer group
2141 	//PRINT(("buffer size: %i, buffer duration: %i\n", fOutput.format.u.raw_audio.buffer_size, BufferDuration()));
2142 	//PRINT(("MBI.record_buffer_cycle: %i\n", MBI.record_buffer_cycle));
2143 	//PRINT(("MBI.recorded_real_time: %i\n", MBI.recorded_real_time));
2144 	//PRINT(("MBI.recorded_frames_count: %i\n", MBI.recorded_frames_count));
2145 	if (output.fBufferGroup == NULL)
2146 		return NULL;
2147 
2148 	BBuffer* buffer = output.fBufferGroup->RequestBuffer(
2149 		output.fOutput.format.u.raw_audio.buffer_size, BufferDuration());
2150 	if (buffer == NULL) {
2151 		// If we fail to get a buffer (for example, if the request times out),
2152 		// we skip this buffer and go on to the next, to avoid locking up the
2153 		// control thread.
2154 		fprintf(stderr, "Buffer is null");
2155 		return NULL;
2156 	}
2157 
2158 	if (fDevice == NULL)
2159 		fprintf(stderr, "fDevice NULL\n");
2160 	if (buffer->Header() == NULL)
2161 		fprintf(stderr, "buffer->Header() NULL\n");
2162 	if (TimeSource() == NULL)
2163 		fprintf(stderr, "TimeSource() NULL\n");
2164 
2165 	uint32 channelCount = output.fOutput.format.u.raw_audio.channel_count;
2166 	size_t outputSampleSize = output.fOutput.format.u.raw_audio.format
2167 		& media_raw_audio_format::B_AUDIO_SIZE_MASK;
2168 
2169 	uint32 bufferSize = fDevice->BufferList().return_record_buffer_size;
2170 
2171 	if (output.fResampler != NULL) {
2172 		size_t dstStride = channelCount * outputSampleSize;
2173 
2174 		uint32 channelId = output.fChannelId
2175 			- fDevice->Description().output_channel_count;
2176 
2177 		for (uint32 channel = 0; channel < channelCount; channel++) {
2178 			char* src = _RecordBuffer(output.fBufferCycle,
2179 									channelId + channel);
2180 			size_t srcStride = _RecordStride(output.fBufferCycle,
2181 									channelId + channel);
2182 			char* dst = (char*)buffer->Data() + channel * outputSampleSize;
2183 
2184 			output.fResampler->Resample(src, srcStride, dst, dstStride,
2185 				bufferSize);
2186 		}
2187 	}
2188 
2189 	// fill in the buffer header
2190 	media_header* header = buffer->Header();
2191 	header->type = B_MEDIA_RAW_AUDIO;
2192 	header->size_used = output.fOutput.format.u.raw_audio.buffer_size;
2193 	header->time_source = TimeSource()->ID();
2194 	header->start_time = PerformanceTimeFor(info.recorded_real_time);
2195 
2196 	return buffer;
2197 }
2198 
2199 
2200 status_t
2201 MultiAudioNode::GetConfigurationFor(BMessage* message)
2202 {
2203 	CALLED();
2204 	if (message == NULL)
2205 		return B_BAD_VALUE;
2206 
2207 	size_t bufferSize = 128;
2208 	void* buffer = malloc(bufferSize);
2209 	if (buffer == NULL)
2210 		return B_NO_MEMORY;
2211 
2212 	for (int32 i = 0; i < fWeb->CountParameters(); i++) {
2213 		BParameter* parameter = fWeb->ParameterAt(i);
2214 		if (parameter->Type() != BParameter::B_CONTINUOUS_PARAMETER
2215 			&& parameter->Type() != BParameter::B_DISCRETE_PARAMETER)
2216 			continue;
2217 
2218 		PRINT(("getting parameter %" B_PRIi32 "\n", parameter->ID()));
2219 		size_t size = bufferSize;
2220 		bigtime_t lastChange;
2221 		status_t err;
2222 		while ((err = GetParameterValue(parameter->ID(), &lastChange, buffer,
2223 				&size)) == B_NO_MEMORY && bufferSize < 128 * 1024) {
2224 			bufferSize += 128;
2225 			free(buffer);
2226 			buffer = malloc(bufferSize);
2227 			if (buffer == NULL)
2228 				return B_NO_MEMORY;
2229 		}
2230 
2231 		if (err == B_OK && size > 0) {
2232 			message->AddInt32("parameterID", parameter->ID());
2233 			message->AddData("parameterData", B_RAW_TYPE, buffer, size, false);
2234 		} else {
2235 			PRINT(("parameter err: %s\n", strerror(err)));
2236 		}
2237 	}
2238 
2239 	free(buffer);
2240 	PRINT_OBJECT(*message);
2241 	return B_OK;
2242 }
2243 
2244 
2245 node_output*
2246 MultiAudioNode::_FindOutput(media_source source)
2247 {
2248 	node_output* channel = NULL;
2249 
2250 	for (int32 i = 0; i < fOutputs.CountItems(); i++) {
2251 		channel = (node_output*)fOutputs.ItemAt(i);
2252 		if (source == channel->fOutput.source)
2253 			break;
2254 	}
2255 
2256 	if (source != channel->fOutput.source)
2257 		return NULL;
2258 
2259 	return channel;
2260 }
2261 
2262 
2263 node_input*
2264 MultiAudioNode::_FindInput(media_destination dest)
2265 {
2266 	node_input* channel = NULL;
2267 
2268 	for (int32 i = 0; i < fInputs.CountItems(); i++) {
2269 		channel = (node_input*)fInputs.ItemAt(i);
2270 		if (dest == channel->fInput.destination)
2271 			break;
2272 	}
2273 
2274 	if (dest != channel->fInput.destination)
2275 		return NULL;
2276 
2277 	return channel;
2278 }
2279 
2280 
2281 node_input*
2282 MultiAudioNode::_FindInput(int32 destinationId)
2283 {
2284 	node_input* channel = NULL;
2285 
2286 	for (int32 i = 0; i < fInputs.CountItems(); i++) {
2287 		channel = (node_input*)fInputs.ItemAt(i);
2288 		if (destinationId == channel->fInput.destination.id)
2289 			break;
2290 	}
2291 
2292 	if (destinationId != channel->fInput.destination.id)
2293 		return NULL;
2294 
2295 	return channel;
2296 }
2297 
2298 
2299 /*static*/ status_t
2300 MultiAudioNode::_OutputThreadEntry(void* data)
2301 {
2302 	CALLED();
2303 	return static_cast<MultiAudioNode*>(data)->_OutputThread();
2304 }
2305 
2306 
2307 status_t
2308 MultiAudioNode::_SetNodeInputFrameRate(float frameRate)
2309 {
2310 	// check whether the frame rate is supported
2311 	uint32 multiAudioRate = MultiAudio::convert_from_sample_rate(frameRate);
2312 	if ((fDevice->Description().output_rates & multiAudioRate) == 0)
2313 		return B_BAD_VALUE;
2314 
2315 	BAutolock locker(fBufferLock);
2316 
2317 	// already set?
2318 	if (fDevice->FormatInfo().output.rate == multiAudioRate)
2319 		return B_OK;
2320 
2321 	// set the frame rate on the device
2322 	status_t error = fDevice->SetOutputFrameRate(multiAudioRate);
2323 	if (error != B_OK)
2324 		return error;
2325 
2326 	// it went fine -- update all formats
2327 	fOutputPreferredFormat.u.raw_audio.frame_rate = frameRate;
2328 	fOutputPreferredFormat.u.raw_audio.buffer_size
2329 		= fDevice->BufferList().return_playback_buffer_size
2330 			* (fOutputPreferredFormat.u.raw_audio.format
2331 				& media_raw_audio_format::B_AUDIO_SIZE_MASK)
2332 			* fOutputPreferredFormat.u.raw_audio.channel_count;
2333 
2334 	for (int32 i = 0; node_input* channel = (node_input*)fInputs.ItemAt(i);
2335 			i++) {
2336 		channel->fPreferredFormat.u.raw_audio.frame_rate = frameRate;
2337 		channel->fPreferredFormat.u.raw_audio.buffer_size
2338 			= fOutputPreferredFormat.u.raw_audio.buffer_size;
2339 
2340 		channel->fFormat.u.raw_audio.frame_rate = frameRate;
2341 		channel->fFormat.u.raw_audio.buffer_size
2342 			= fOutputPreferredFormat.u.raw_audio.buffer_size;
2343 
2344 		channel->fInput.format.u.raw_audio.frame_rate = frameRate;
2345 		channel->fInput.format.u.raw_audio.buffer_size
2346 			= fOutputPreferredFormat.u.raw_audio.buffer_size;
2347 	}
2348 
2349 	// make sure the time base is reset
2350 	fTimeComputer.SetFrameRate(frameRate);
2351 
2352 	// update internal latency
2353 	_UpdateInternalLatency(fOutputPreferredFormat);
2354 
2355 	return B_OK;
2356 }
2357 
2358 
2359 status_t
2360 MultiAudioNode::_SetNodeOutputFrameRate(float frameRate)
2361 {
2362 	// check whether the frame rate is supported
2363 	uint32 multiAudioRate = MultiAudio::convert_from_sample_rate(frameRate);
2364 	if ((fDevice->Description().input_rates & multiAudioRate) == 0)
2365 		return B_BAD_VALUE;
2366 
2367 	BAutolock locker(fBufferLock);
2368 
2369 	// already set?
2370 	if (fDevice->FormatInfo().input.rate == multiAudioRate)
2371 		return B_OK;
2372 
2373 	// set the frame rate on the device
2374 	status_t error = fDevice->SetInputFrameRate(multiAudioRate);
2375 	if (error != B_OK)
2376 		return error;
2377 
2378 	// it went fine -- update all formats
2379 	fInputPreferredFormat.u.raw_audio.frame_rate = frameRate;
2380 	fInputPreferredFormat.u.raw_audio.buffer_size
2381 		= fDevice->BufferList().return_record_buffer_size
2382 			* (fInputPreferredFormat.u.raw_audio.format
2383 				& media_raw_audio_format::B_AUDIO_SIZE_MASK)
2384 			* fInputPreferredFormat.u.raw_audio.channel_count;
2385 
2386 	for (int32 i = 0; node_output* channel = (node_output*)fOutputs.ItemAt(i);
2387 			i++) {
2388 		channel->fPreferredFormat.u.raw_audio.frame_rate = frameRate;
2389 		channel->fPreferredFormat.u.raw_audio.buffer_size
2390 			= fInputPreferredFormat.u.raw_audio.buffer_size;
2391 
2392 		channel->fFormat.u.raw_audio.frame_rate = frameRate;
2393 		channel->fFormat.u.raw_audio.buffer_size
2394 			= fInputPreferredFormat.u.raw_audio.buffer_size;
2395 
2396 		channel->fOutput.format.u.raw_audio.frame_rate = frameRate;
2397 		channel->fOutput.format.u.raw_audio.buffer_size
2398 			= fInputPreferredFormat.u.raw_audio.buffer_size;
2399 	}
2400 
2401 	// make sure the time base is reset
2402 	fTimeComputer.SetFrameRate(frameRate);
2403 
2404 	// update internal latency
2405 	_UpdateInternalLatency(fInputPreferredFormat);
2406 
2407 	return B_OK;
2408 }
2409 
2410 
2411 void
2412 MultiAudioNode::_UpdateInternalLatency(const media_format& format)
2413 {
2414 	// use half a buffer length latency
2415 	fInternalLatency = format.u.raw_audio.buffer_size * 10000 / 2
2416 		/ ((format.u.raw_audio.format
2417 				& media_raw_audio_format::B_AUDIO_SIZE_MASK)
2418 			* format.u.raw_audio.channel_count)
2419 		/ ((int32)(format.u.raw_audio.frame_rate / 100));
2420 
2421 	PRINT(("  internal latency = %" B_PRIdBIGTIME "\n", fInternalLatency));
2422 
2423 	SetEventLatency(fInternalLatency);
2424 }
2425