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