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