xref: /haiku/src/kits/media/BufferProducer.cpp (revision b84955d416f92e89c9d73999f545a2dec353d988)
1255a01c7Sbeveloper /*
2332cc6bcSAxel Dörfler  * Copyright 2010-2012, Axel Dörfler, axeld@pinc-software.de.
399e658c3SAxel Dörfler  * Copyright 2002-2003, Marcus Overhagen, <Marcus@Overhagen.de>.
4b289aaf6SAxel Dörfler  * Distributed under the terms of the MIT License.
5255a01c7Sbeveloper  */
6255a01c7Sbeveloper 
7b289aaf6SAxel Dörfler 
8b289aaf6SAxel Dörfler #include <Buffer.h>
960f15390Sbeveloper #include <BufferConsumer.h>
1052a38012Sejakowatz #include <BufferGroup.h>
11b289aaf6SAxel Dörfler #include <BufferProducer.h>
1252a38012Sejakowatz 
13*b84955d4SBarrett17 #include "MediaDebug.h"
14b289aaf6SAxel Dörfler #include "DataExchange.h"
15b289aaf6SAxel Dörfler #include "MediaMisc.h"
16b289aaf6SAxel Dörfler 
17b289aaf6SAxel Dörfler 
18b289aaf6SAxel Dörfler // #pragma mark - protected BBufferProducer
19b289aaf6SAxel Dörfler 
2052a38012Sejakowatz 
~BBufferProducer()2152a38012Sejakowatz BBufferProducer::~BBufferProducer()
2252a38012Sejakowatz {
2352a38012Sejakowatz 	CALLED();
2452a38012Sejakowatz }
2552a38012Sejakowatz 
26b289aaf6SAxel Dörfler 
27b289aaf6SAxel Dörfler // #pragma mark - public BBufferProducer
28b289aaf6SAxel Dörfler 
2952a38012Sejakowatz 
3052a38012Sejakowatz /*static*/ status_t
ClipDataToRegion(int32 format,int32 size,const void * data,BRegion * region)31b289aaf6SAxel Dörfler BBufferProducer::ClipDataToRegion(int32 format, int32 size, const void* data,
3252a38012Sejakowatz 	BRegion* region)
3352a38012Sejakowatz {
3452a38012Sejakowatz 	CALLED();
3552a38012Sejakowatz 
3652a38012Sejakowatz 	if (format != B_CLIP_SHORT_RUNS)
3752a38012Sejakowatz 		return B_MEDIA_BAD_CLIP_FORMAT;
3852a38012Sejakowatz 
39b289aaf6SAxel Dörfler 	return clip_shorts_to_region((const int16*)data, size / sizeof(int16),
40b289aaf6SAxel Dörfler 		region);
4152a38012Sejakowatz }
4252a38012Sejakowatz 
43b289aaf6SAxel Dörfler 
4452a38012Sejakowatz media_type
ProducerType()4552a38012Sejakowatz BBufferProducer::ProducerType()
4652a38012Sejakowatz {
4752a38012Sejakowatz 	CALLED();
4852a38012Sejakowatz 	return fProducerType;
4952a38012Sejakowatz }
5052a38012Sejakowatz 
5152a38012Sejakowatz 
52b289aaf6SAxel Dörfler // #pragma mark - protected BBufferProducer
53b289aaf6SAxel Dörfler 
54b289aaf6SAxel Dörfler 
BBufferProducer(media_type producer_type)55b289aaf6SAxel Dörfler BBufferProducer::BBufferProducer(media_type producer_type)
56b289aaf6SAxel Dörfler 	:
5752a38012Sejakowatz 	BMediaNode("called by BBufferProducer"),
5852a38012Sejakowatz 	fProducerType(producer_type),
5952a38012Sejakowatz 	fInitialLatency(0),
6060f15390Sbeveloper 	fInitialFlags(0),
6160f15390Sbeveloper 	fDelay(0)
6252a38012Sejakowatz {
6352a38012Sejakowatz 	CALLED();
6452a38012Sejakowatz 
6552a38012Sejakowatz 	AddNodeKind(B_BUFFER_PRODUCER);
6652a38012Sejakowatz }
6752a38012Sejakowatz 
6852a38012Sejakowatz 
6952a38012Sejakowatz status_t
VideoClippingChanged(const media_source & source,int16 numShorts,int16 * clipData,const media_video_display_info & display,int32 *)70b289aaf6SAxel Dörfler BBufferProducer::VideoClippingChanged(const media_source& source,
71b289aaf6SAxel Dörfler 	int16 numShorts, int16* clipData, const media_video_display_info& display,
72b289aaf6SAxel Dörfler 	int32* /*_deprecated_*/)
7352a38012Sejakowatz {
7452a38012Sejakowatz 	CALLED();
7552a38012Sejakowatz 	// may be implemented by derived classes
7652a38012Sejakowatz 	return B_ERROR;
7752a38012Sejakowatz }
7852a38012Sejakowatz 
7952a38012Sejakowatz 
8052a38012Sejakowatz status_t
GetLatency(bigtime_t * _latency)81b289aaf6SAxel Dörfler BBufferProducer::GetLatency(bigtime_t* _latency)
8252a38012Sejakowatz {
8360f15390Sbeveloper 	CALLED();
8460f15390Sbeveloper 	// The default implementation of GetLatency() finds the maximum
8552a38012Sejakowatz 	// latency of your currently-available outputs by iterating over
8652a38012Sejakowatz 	// them, and returns that value in outLatency
8752a38012Sejakowatz 
8860f15390Sbeveloper 	int32 cookie;
8960f15390Sbeveloper 	bigtime_t latency;
9060f15390Sbeveloper 	media_output output;
9160f15390Sbeveloper 	media_node_id unused;
9260f15390Sbeveloper 
93b289aaf6SAxel Dörfler 	*_latency = 0;
9460f15390Sbeveloper 	cookie = 0;
95b289aaf6SAxel Dörfler 	while (GetNextOutput(&cookie, &output) == B_OK) {
9660f15390Sbeveloper 		if (output.destination == media_destination::null)
9760f15390Sbeveloper 			continue;
9860f15390Sbeveloper 
99b289aaf6SAxel Dörfler 		if (output.node.node == fNodeID) {
100b289aaf6SAxel Dörfler 			// avoid port writes (deadlock) if loopback connection
101b289aaf6SAxel Dörfler 			if (fConsumerThis == NULL)
10260f15390Sbeveloper 				fConsumerThis = dynamic_cast<BBufferConsumer*>(this);
103b289aaf6SAxel Dörfler 			if (fConsumerThis == NULL)
10460f15390Sbeveloper 				continue;
105b289aaf6SAxel Dörfler 
10660f15390Sbeveloper 			latency = 0;
107b289aaf6SAxel Dörfler 			if (fConsumerThis->GetLatencyFor(output.destination, &latency,
108b289aaf6SAxel Dörfler 					&unused) == B_OK && latency > *_latency) {
109b289aaf6SAxel Dörfler 				*_latency = latency;
110b289aaf6SAxel Dörfler 			}
111b289aaf6SAxel Dörfler 		} else if (FindLatencyFor(output.destination, &latency, &unused)
112b289aaf6SAxel Dörfler 				== B_OK &&  latency > *_latency) {
113b289aaf6SAxel Dörfler 			*_latency = latency;
11460f15390Sbeveloper 		}
11560f15390Sbeveloper 	}
116332cc6bcSAxel Dörfler 	printf("BBufferProducer::GetLatency: node %" B_PRId32 ", name \"%s\" has "
117332cc6bcSAxel Dörfler 		"max latency %" B_PRId64 "\n", fNodeID, fName, *_latency);
11860f15390Sbeveloper 	return B_OK;
11952a38012Sejakowatz }
12052a38012Sejakowatz 
12152a38012Sejakowatz 
12252a38012Sejakowatz status_t
SetPlayRate(int32 numer,int32 denom)123b289aaf6SAxel Dörfler BBufferProducer::SetPlayRate(int32 numer, int32 denom)
12452a38012Sejakowatz {
12552a38012Sejakowatz 	CALLED();
12652a38012Sejakowatz 	// may be implemented by derived classes
12752a38012Sejakowatz 	return B_ERROR;
12852a38012Sejakowatz }
12952a38012Sejakowatz 
13052a38012Sejakowatz 
13152a38012Sejakowatz status_t
HandleMessage(int32 message,const void * data,size_t size)132b289aaf6SAxel Dörfler BBufferProducer::HandleMessage(int32 message, const void* data, size_t size)
13352a38012Sejakowatz {
134b289aaf6SAxel Dörfler 	PRINT(4, "BBufferProducer::HandleMessage %#lx, node %ld\n", message,
135b289aaf6SAxel Dörfler 		fNodeID);
136b289aaf6SAxel Dörfler 
13752a38012Sejakowatz 	switch (message) {
13860f15390Sbeveloper 		case PRODUCER_SET_RUN_MODE_DELAY:
13960f15390Sbeveloper 		{
140b289aaf6SAxel Dörfler 			const producer_set_run_mode_delay_command* command
141b289aaf6SAxel Dörfler 				= static_cast<const producer_set_run_mode_delay_command*>(data);
14260f15390Sbeveloper 			// when changing this, also change NODE_SET_RUN_MODE
14360f15390Sbeveloper 			fDelay = command->delay;
14460f15390Sbeveloper 			fRunMode = command->mode;
145f4ba347bSDario Casalinuovo 
146f4ba347bSDario Casalinuovo 			TRACE("PRODUCER_SET_RUN_MODE_DELAY: fDelay now %" B_PRId64 "\n",
147f4ba347bSDario Casalinuovo 				fDelay);
148f4ba347bSDario Casalinuovo 
14960f15390Sbeveloper 			SetRunMode(fRunMode);
15060f15390Sbeveloper 			return B_OK;
15160f15390Sbeveloper 		}
15252a38012Sejakowatz 
15352a38012Sejakowatz 		case PRODUCER_FORMAT_SUGGESTION_REQUESTED:
15452a38012Sejakowatz 		{
155b289aaf6SAxel Dörfler 			const producer_format_suggestion_requested_request* request
156b289aaf6SAxel Dörfler 				= static_cast<
157b289aaf6SAxel Dörfler 					const producer_format_suggestion_requested_request*>(data);
158dfb2ad61Sbeveloper 			producer_format_suggestion_requested_reply reply;
159b289aaf6SAxel Dörfler 			status_t status = FormatSuggestionRequested(request->type,
160b289aaf6SAxel Dörfler 				request->quality, &reply.format);
161b289aaf6SAxel Dörfler 			request->SendReply(status, &reply, sizeof(reply));
16252a38012Sejakowatz 			return B_OK;
16352a38012Sejakowatz 		}
16452a38012Sejakowatz 
16552a38012Sejakowatz 		case PRODUCER_FORMAT_PROPOSAL:
16652a38012Sejakowatz 		{
167b289aaf6SAxel Dörfler 			const producer_format_proposal_request* request
168b289aaf6SAxel Dörfler 				= static_cast<const producer_format_proposal_request*>(data);
1698c6a6096Sbeveloper 			producer_format_proposal_reply reply;
1708c6a6096Sbeveloper 			reply.format = request->format;
171b289aaf6SAxel Dörfler 			status_t status = FormatProposal(request->output, &reply.format);
172b289aaf6SAxel Dörfler 			request->SendReply(status, &reply, sizeof(reply));
17352a38012Sejakowatz 			return B_OK;
17452a38012Sejakowatz 		}
17552a38012Sejakowatz 
17652a38012Sejakowatz 		case PRODUCER_PREPARE_TO_CONNECT:
17752a38012Sejakowatz 		{
178b289aaf6SAxel Dörfler 			const producer_prepare_to_connect_request* request
179b289aaf6SAxel Dörfler 				= static_cast<const producer_prepare_to_connect_request*>(data);
1808c6a6096Sbeveloper 			producer_prepare_to_connect_reply reply;
1818c6a6096Sbeveloper 			reply.format = request->format;
1825ac4fbd7Sbeveloper 			reply.out_source = request->source;
1838c6a6096Sbeveloper 			memcpy(reply.name, request->name, B_MEDIA_NAME_LENGTH);
184b289aaf6SAxel Dörfler 			status_t status = PrepareToConnect(request->source,
185b289aaf6SAxel Dörfler 				request->destination, &reply.format, &reply.out_source,
186b289aaf6SAxel Dörfler 				reply.name);
187b289aaf6SAxel Dörfler 			request->SendReply(status, &reply, sizeof(reply));
18852a38012Sejakowatz 			return B_OK;
18952a38012Sejakowatz 		}
19052a38012Sejakowatz 
19152a38012Sejakowatz 		case PRODUCER_CONNECT:
19252a38012Sejakowatz 		{
193b289aaf6SAxel Dörfler 			const producer_connect_request* request
194b289aaf6SAxel Dörfler 				= static_cast<const producer_connect_request*>(data);
1958c6a6096Sbeveloper 			producer_connect_reply reply;
1968c6a6096Sbeveloper 			memcpy(reply.name, request->name, B_MEDIA_NAME_LENGTH);
197b289aaf6SAxel Dörfler 			Connect(request->error, request->source, request->destination,
198b289aaf6SAxel Dörfler 				request->format, reply.name);
1998c6a6096Sbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
20052a38012Sejakowatz 			return B_OK;
20152a38012Sejakowatz 		}
20252a38012Sejakowatz 
20352a38012Sejakowatz 		case PRODUCER_DISCONNECT:
20452a38012Sejakowatz 		{
205b289aaf6SAxel Dörfler 			const producer_disconnect_request* request
206b289aaf6SAxel Dörfler 				= static_cast<const producer_disconnect_request*>(data);
2079e9417d2Sbeveloper 			producer_disconnect_reply reply;
2088c6a6096Sbeveloper 			Disconnect(request->source, request->destination);
2099e9417d2Sbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
21052a38012Sejakowatz 			return B_OK;
21152a38012Sejakowatz 		}
21252a38012Sejakowatz 
21352a38012Sejakowatz 		case PRODUCER_GET_INITIAL_LATENCY:
21452a38012Sejakowatz 		{
215b289aaf6SAxel Dörfler 			const producer_get_initial_latency_request* request
216b289aaf6SAxel Dörfler 				= static_cast<
217b289aaf6SAxel Dörfler 					const producer_get_initial_latency_request*>(data);
218dfb2ad61Sbeveloper 			producer_get_initial_latency_reply reply;
21952a38012Sejakowatz 			reply.initial_latency = fInitialLatency;
22052a38012Sejakowatz 			reply.flags = fInitialFlags;
221dfb2ad61Sbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
22252a38012Sejakowatz 			return B_OK;
22352a38012Sejakowatz 		}
22452a38012Sejakowatz 
22552a38012Sejakowatz 		case PRODUCER_SET_PLAY_RATE:
22652a38012Sejakowatz 		{
227b289aaf6SAxel Dörfler 			const producer_set_play_rate_request* request
228b289aaf6SAxel Dörfler 				= static_cast<const producer_set_play_rate_request*>(data);
229dfb2ad61Sbeveloper 			producer_set_play_rate_reply reply;
230b289aaf6SAxel Dörfler 			status_t status = SetPlayRate(request->numer, request->denom);
231b289aaf6SAxel Dörfler 			request->SendReply(status, &reply, sizeof(reply));
23252a38012Sejakowatz 			return B_OK;
23352a38012Sejakowatz 		}
23452a38012Sejakowatz 
23552a38012Sejakowatz 		case PRODUCER_GET_LATENCY:
23652a38012Sejakowatz 		{
237b289aaf6SAxel Dörfler 			const producer_get_latency_request* request
238b289aaf6SAxel Dörfler 				= static_cast<const producer_get_latency_request*>(data);
239dfb2ad61Sbeveloper 			producer_get_latency_reply reply;
240b289aaf6SAxel Dörfler 			status_t status = GetLatency(&reply.latency);
241b289aaf6SAxel Dörfler 			request->SendReply(status, &reply, sizeof(reply));
24252a38012Sejakowatz 			return B_OK;
24352a38012Sejakowatz 		}
24452a38012Sejakowatz 
24552a38012Sejakowatz 		case PRODUCER_GET_NEXT_OUTPUT:
24652a38012Sejakowatz 		{
247b289aaf6SAxel Dörfler 			const producer_get_next_output_request* request
248b289aaf6SAxel Dörfler 				= static_cast<const producer_get_next_output_request*>(data);
2493620737cSbeveloper 			producer_get_next_output_reply reply;
2508c6a6096Sbeveloper 			reply.cookie = request->cookie;
251b289aaf6SAxel Dörfler 			status_t status = GetNextOutput(&reply.cookie, &reply.output);
252b289aaf6SAxel Dörfler 			request->SendReply(status, &reply, sizeof(reply));
25352a38012Sejakowatz 			return B_OK;
25452a38012Sejakowatz 		}
25552a38012Sejakowatz 
25652a38012Sejakowatz 		case PRODUCER_DISPOSE_OUTPUT_COOKIE:
25752a38012Sejakowatz 		{
258b289aaf6SAxel Dörfler 			const producer_dispose_output_cookie_request*request
259b289aaf6SAxel Dörfler 				= static_cast<
260b289aaf6SAxel Dörfler 					const producer_dispose_output_cookie_request*>(data);
2613620737cSbeveloper 			producer_dispose_output_cookie_reply reply;
2628c6a6096Sbeveloper 			DisposeOutputCookie(request->cookie);
2633620737cSbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
26452a38012Sejakowatz 			return B_OK;
26552a38012Sejakowatz 		}
26652a38012Sejakowatz 
26752a38012Sejakowatz 		case PRODUCER_SET_BUFFER_GROUP:
26852a38012Sejakowatz 		{
269b289aaf6SAxel Dörfler 			const producer_set_buffer_group_command* command
270b289aaf6SAxel Dörfler 				= static_cast<const producer_set_buffer_group_command*>(data);
271dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
27252a38012Sejakowatz 			BBufferGroup *group;
273b289aaf6SAxel Dörfler 			group = command->buffer_count != 0
274b289aaf6SAxel Dörfler 				? new BBufferGroup(command->buffer_count, command->buffers)
275b289aaf6SAxel Dörfler 				: NULL;
276714446cfSDario Casalinuovo 
2778bffda16SDario Casalinuovo 			if (group != NULL && group->InitCheck() != B_OK) {
278714446cfSDario Casalinuovo 				ERROR("BBufferProducer::HandleMessage PRODUCER_SET_BUFFER_GROUP"
279714446cfSDario Casalinuovo 					" group InitCheck() failed.\n");
280714446cfSDario Casalinuovo 				delete group;
2818bffda16SDario Casalinuovo 				group = NULL;
282714446cfSDario Casalinuovo 			}
283b289aaf6SAxel Dörfler 			status_t status = SetBufferGroup(command->source, group);
284dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
28552a38012Sejakowatz 				return B_OK;
286b289aaf6SAxel Dörfler 			replycommand.info.what
287b289aaf6SAxel Dörfler 				= media_request_info::B_SET_OUTPUT_BUFFERS_FOR;
288dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
289b289aaf6SAxel Dörfler 			replycommand.info.status = status;
290332cc6bcSAxel Dörfler 			replycommand.info.cookie = group;
291dfb2ad61Sbeveloper 			replycommand.info.user_data = command->user_data;
292dfb2ad61Sbeveloper 			replycommand.info.source = command->source;
293dfb2ad61Sbeveloper 			replycommand.info.destination = command->destination;
294b289aaf6SAxel Dörfler 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED,
295b289aaf6SAxel Dörfler 				&replycommand, sizeof(replycommand));
29652a38012Sejakowatz 			return B_OK;
29752a38012Sejakowatz 		}
29852a38012Sejakowatz 
29952a38012Sejakowatz 		case PRODUCER_FORMAT_CHANGE_REQUESTED:
30052a38012Sejakowatz 		{
301b289aaf6SAxel Dörfler 			const producer_format_change_requested_command* command
302b289aaf6SAxel Dörfler 				= static_cast<
303b289aaf6SAxel Dörfler 					const producer_format_change_requested_command*>(data);
304dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
305dfb2ad61Sbeveloper 			replycommand.info.format = command->format;
306b289aaf6SAxel Dörfler 			status_t status = FormatChangeRequested(command->source,
307b289aaf6SAxel Dörfler 				command->destination, &replycommand.info.format, NULL);
308dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
30952a38012Sejakowatz 				return B_OK;
310b289aaf6SAxel Dörfler 			replycommand.info.what
311b289aaf6SAxel Dörfler 				= media_request_info::B_REQUEST_FORMAT_CHANGE;
312dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
313b289aaf6SAxel Dörfler 			replycommand.info.status = status;
314dfb2ad61Sbeveloper 			//replycommand.info.cookie
315dfb2ad61Sbeveloper 			replycommand.info.user_data = command->user_data;
316dfb2ad61Sbeveloper 			replycommand.info.source = command->source;
317dfb2ad61Sbeveloper 			replycommand.info.destination = command->destination;
318b289aaf6SAxel Dörfler 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED,
319b289aaf6SAxel Dörfler 				&replycommand, sizeof(replycommand));
32052a38012Sejakowatz 			return B_OK;
32152a38012Sejakowatz 		}
32252a38012Sejakowatz 
32352a38012Sejakowatz 		case PRODUCER_VIDEO_CLIPPING_CHANGED:
32452a38012Sejakowatz 		{
325b289aaf6SAxel Dörfler 			const producer_video_clipping_changed_command* command
326b289aaf6SAxel Dörfler 				= static_cast<
327b289aaf6SAxel Dörfler 					const producer_video_clipping_changed_command*>(data);
328dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
329b289aaf6SAxel Dörfler 			status_t status = VideoClippingChanged(command->source,
330b289aaf6SAxel Dörfler 				command->short_count, (int16 *)command->shorts,
331b289aaf6SAxel Dörfler 				command->display, NULL);
332dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
33352a38012Sejakowatz 				return B_OK;
334b289aaf6SAxel Dörfler 			replycommand.info.what
335b289aaf6SAxel Dörfler 				= media_request_info::B_SET_VIDEO_CLIPPING_FOR;
336dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
337b289aaf6SAxel Dörfler 			replycommand.info.status = status;
338dfb2ad61Sbeveloper 			//replycommand.info.cookie
339dfb2ad61Sbeveloper 			replycommand.info.user_data = command->user_data;
340dfb2ad61Sbeveloper 			replycommand.info.source = command->source;
341dfb2ad61Sbeveloper 			replycommand.info.destination = command->destination;
342dfb2ad61Sbeveloper 			replycommand.info.format.type = B_MEDIA_RAW_VIDEO;
343dfb2ad61Sbeveloper 			replycommand.info.format.u.raw_video.display = command->display;
344b289aaf6SAxel Dörfler 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED,
345b289aaf6SAxel Dörfler 				&replycommand, sizeof(replycommand));
34652a38012Sejakowatz 			return B_OK;
34752a38012Sejakowatz 		}
34852a38012Sejakowatz 
34952a38012Sejakowatz 		case PRODUCER_ADDITIONAL_BUFFER_REQUESTED:
35052a38012Sejakowatz 		{
351b289aaf6SAxel Dörfler 			const producer_additional_buffer_requested_command* command
352b289aaf6SAxel Dörfler 				= static_cast<
353b289aaf6SAxel Dörfler 					const producer_additional_buffer_requested_command*>(data);
354b289aaf6SAxel Dörfler 			AdditionalBufferRequested(command->source, command->prev_buffer,
355b289aaf6SAxel Dörfler 				command->prev_time, command->has_seek_tag
356b289aaf6SAxel Dörfler 					? &command->prev_tag : NULL);
35752a38012Sejakowatz 			return B_OK;
35852a38012Sejakowatz 		}
35952a38012Sejakowatz 
36052a38012Sejakowatz 		case PRODUCER_LATENCY_CHANGED:
36152a38012Sejakowatz 		{
362b289aaf6SAxel Dörfler 			const producer_latency_changed_command* command
363b289aaf6SAxel Dörfler 				= static_cast<const producer_latency_changed_command*>(data);
364b289aaf6SAxel Dörfler 			LatencyChanged(command->source, command->destination,
365b289aaf6SAxel Dörfler 				command->latency, command->flags);
36652a38012Sejakowatz 			return B_OK;
36752a38012Sejakowatz 		}
36852a38012Sejakowatz 
36952a38012Sejakowatz 		case PRODUCER_LATE_NOTICE_RECEIVED:
37052a38012Sejakowatz 		{
371b289aaf6SAxel Dörfler 			const producer_late_notice_received_command* command
372b289aaf6SAxel Dörfler 				= static_cast<
373b289aaf6SAxel Dörfler 					const producer_late_notice_received_command*>(data);
374b289aaf6SAxel Dörfler 			LateNoticeReceived(command->source, command->how_much,
375b289aaf6SAxel Dörfler 				command->performance_time);
37652a38012Sejakowatz 			return B_OK;
37752a38012Sejakowatz 		}
37852a38012Sejakowatz 
37952a38012Sejakowatz 		case PRODUCER_ENABLE_OUTPUT:
38052a38012Sejakowatz 		{
381b289aaf6SAxel Dörfler 			const producer_enable_output_command* command
382b289aaf6SAxel Dörfler 				= static_cast<const producer_enable_output_command*>(data);
383dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
384dfb2ad61Sbeveloper 			EnableOutput(command->source, command->enabled, NULL);
385dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
38652a38012Sejakowatz 				return B_OK;
387b289aaf6SAxel Dörfler 
388dfb2ad61Sbeveloper 			replycommand.info.what = media_request_info::B_SET_OUTPUT_ENABLED;
389dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
390dfb2ad61Sbeveloper 			replycommand.info.status = B_OK;
391dfb2ad61Sbeveloper 			//replycommand.info.cookie
392dfb2ad61Sbeveloper 			replycommand.info.user_data = command->user_data;
393dfb2ad61Sbeveloper 			replycommand.info.source = command->source;
394dfb2ad61Sbeveloper 			replycommand.info.destination = command->destination;
395dfb2ad61Sbeveloper 			//replycommand.info.format
396b289aaf6SAxel Dörfler 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED,
397b289aaf6SAxel Dörfler 				&replycommand, sizeof(replycommand));
39852a38012Sejakowatz 			return B_OK;
39952a38012Sejakowatz 		}
400b289aaf6SAxel Dörfler 	}
40152a38012Sejakowatz 
40252a38012Sejakowatz 	return B_ERROR;
40352a38012Sejakowatz }
40452a38012Sejakowatz 
40552a38012Sejakowatz 
40652a38012Sejakowatz void
AdditionalBufferRequested(const media_source & source,media_buffer_id previousBuffer,bigtime_t previousTime,const media_seek_tag * previousTag)40752a38012Sejakowatz BBufferProducer::AdditionalBufferRequested(const media_source& source,
408b289aaf6SAxel Dörfler 	media_buffer_id previousBuffer, bigtime_t previousTime,
409b289aaf6SAxel Dörfler 	const media_seek_tag* previousTag)
41052a38012Sejakowatz {
41152a38012Sejakowatz 	CALLED();
41252a38012Sejakowatz 	// may be implemented by derived classes
41352a38012Sejakowatz }
41452a38012Sejakowatz 
41552a38012Sejakowatz 
41652a38012Sejakowatz void
LatencyChanged(const media_source & source,const media_destination & destination,bigtime_t newLatency,uint32 flags)41752a38012Sejakowatz BBufferProducer::LatencyChanged(const media_source& source,
418b289aaf6SAxel Dörfler 	const media_destination& destination, bigtime_t newLatency, uint32 flags)
41952a38012Sejakowatz {
42052a38012Sejakowatz 	CALLED();
42152a38012Sejakowatz 	// may be implemented by derived classes
42252a38012Sejakowatz }
42352a38012Sejakowatz 
42452a38012Sejakowatz 
42552a38012Sejakowatz status_t
SendBuffer(BBuffer * buffer,const media_source & source,const media_destination & destination)426b289aaf6SAxel Dörfler BBufferProducer::SendBuffer(BBuffer* buffer, const media_source& source,
42752a38012Sejakowatz 	const media_destination& destination)
42852a38012Sejakowatz {
42952a38012Sejakowatz 	CALLED();
43052a38012Sejakowatz 	if (destination == media_destination::null)
43152a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
432b289aaf6SAxel Dörfler 	if (source == media_source::null)
433b289aaf6SAxel Dörfler 		return B_MEDIA_BAD_SOURCE;
43452a38012Sejakowatz 	if (buffer == NULL)
43552a38012Sejakowatz 		return B_BAD_VALUE;
43652a38012Sejakowatz 
437dfb2ad61Sbeveloper 	consumer_buffer_received_command command;
438dfb2ad61Sbeveloper 	command.buffer = buffer->ID();
439b289aaf6SAxel Dörfler 	command.header = *buffer->Header();
440b289aaf6SAxel Dörfler 	command.header.buffer = command.buffer;
441b289aaf6SAxel Dörfler 	command.header.source_port = source.port;
442b289aaf6SAxel Dörfler 	command.header.source = source.id;
443dfb2ad61Sbeveloper 	command.header.destination = destination.id;
4441df08d39Sbeveloper 	command.header.owner = 0; // XXX fill with "buffer owner info area"
445b289aaf6SAxel Dörfler 	command.header.start_time += fDelay;
446b289aaf6SAxel Dörfler 		// time compensation as set by BMediaRoster::SetProducerRunModeDelay()
44752a38012Sejakowatz 
448a6d316d8Sbeveloper 	//printf("BBufferProducer::SendBuffer     node %2ld, buffer %2ld, start_time %12Ld with lateness %6Ld\n", ID(), buffer->Header()->buffer, command.header.start_time, TimeSource()->Now() - command.header.start_time);
449a6d316d8Sbeveloper 
450b289aaf6SAxel Dörfler 	return SendToPort(destination.port, CONSUMER_BUFFER_RECEIVED, &command,
451b289aaf6SAxel Dörfler 		sizeof(command));
45252a38012Sejakowatz }
45352a38012Sejakowatz 
45452a38012Sejakowatz 
45552a38012Sejakowatz status_t
SendDataStatus(int32 status,const media_destination & destination,bigtime_t atTime)45652a38012Sejakowatz BBufferProducer::SendDataStatus(int32 status,
457b289aaf6SAxel Dörfler 	const media_destination& destination, bigtime_t atTime)
45852a38012Sejakowatz {
45952a38012Sejakowatz 	CALLED();
46040f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(destination))
46152a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
46252a38012Sejakowatz 
463dfb2ad61Sbeveloper 	consumer_producer_data_status_command command;
464dfb2ad61Sbeveloper 	command.for_whom = destination;
465dfb2ad61Sbeveloper 	command.status = status;
466b289aaf6SAxel Dörfler 	command.at_performance_time = atTime;
46752a38012Sejakowatz 
468b289aaf6SAxel Dörfler 	return SendToPort(destination.port, CONSUMER_PRODUCER_DATA_STATUS, &command,
469b289aaf6SAxel Dörfler 		sizeof(command));
47052a38012Sejakowatz }
47152a38012Sejakowatz 
47252a38012Sejakowatz 
47352a38012Sejakowatz status_t
ProposeFormatChange(media_format * format,const media_destination & destination)47452a38012Sejakowatz BBufferProducer::ProposeFormatChange(media_format* format,
475b289aaf6SAxel Dörfler 	const media_destination& destination)
47652a38012Sejakowatz {
47752a38012Sejakowatz 	CALLED();
478b289aaf6SAxel Dörfler 	if (IS_INVALID_DESTINATION(destination))
47952a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
48052a38012Sejakowatz 
4818c6a6096Sbeveloper 	consumer_accept_format_request request;
4828c6a6096Sbeveloper 	consumer_accept_format_reply reply;
48352a38012Sejakowatz 
484b289aaf6SAxel Dörfler 	request.dest = destination;
4858c6a6096Sbeveloper 	request.format = *format;
486b289aaf6SAxel Dörfler 	status_t status = QueryPort(destination.port, CONSUMER_ACCEPT_FORMAT,
487b289aaf6SAxel Dörfler 		&request, sizeof(request), &reply, sizeof(reply));
488b289aaf6SAxel Dörfler 	if (status != B_OK)
489b289aaf6SAxel Dörfler 		return status;
49052a38012Sejakowatz 
49152a38012Sejakowatz 	*format = reply.format;
4928c6a6096Sbeveloper 	return B_OK;
49352a38012Sejakowatz }
49452a38012Sejakowatz 
49552a38012Sejakowatz 
49652a38012Sejakowatz status_t
ChangeFormat(const media_source & source,const media_destination & destination,media_format * format)497b289aaf6SAxel Dörfler BBufferProducer::ChangeFormat(const media_source& source,
498b289aaf6SAxel Dörfler 	const media_destination& destination, media_format* format)
49952a38012Sejakowatz {
50052a38012Sejakowatz 	CALLED();
501b289aaf6SAxel Dörfler 	if (IS_INVALID_SOURCE(source))
50252a38012Sejakowatz 		return B_MEDIA_BAD_SOURCE;
503b289aaf6SAxel Dörfler 	if (IS_INVALID_DESTINATION(destination))
50452a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
50552a38012Sejakowatz 
506dfb2ad61Sbeveloper 	consumer_format_changed_request request;
507dfb2ad61Sbeveloper 	consumer_format_changed_reply reply;
50852a38012Sejakowatz 
509b289aaf6SAxel Dörfler 	request.producer = source;
510b289aaf6SAxel Dörfler 	request.consumer = destination;
5118c6a6096Sbeveloper 	request.format = *format;
51252a38012Sejakowatz 
513dfb2ad61Sbeveloper 	// we use a request/reply to make this synchronous
514b289aaf6SAxel Dörfler 	return QueryPort(destination.port, CONSUMER_FORMAT_CHANGED, &request,
515b289aaf6SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
51652a38012Sejakowatz }
51752a38012Sejakowatz 
51852a38012Sejakowatz 
51952a38012Sejakowatz status_t
FindLatencyFor(const media_destination & destination,bigtime_t * _latency,media_node_id * _timesource)520b289aaf6SAxel Dörfler BBufferProducer::FindLatencyFor(const media_destination& destination,
521b289aaf6SAxel Dörfler 	bigtime_t* _latency, media_node_id* _timesource)
52252a38012Sejakowatz {
52352a38012Sejakowatz 	CALLED();
524b289aaf6SAxel Dörfler 	if (IS_INVALID_DESTINATION(destination))
52552a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
52652a38012Sejakowatz 
527dfb2ad61Sbeveloper 	consumer_get_latency_for_request request;
528dfb2ad61Sbeveloper 	consumer_get_latency_for_reply reply;
52952a38012Sejakowatz 
530b289aaf6SAxel Dörfler 	request.for_whom = destination;
53152a38012Sejakowatz 
532b289aaf6SAxel Dörfler 	status_t status = QueryPort(destination.port, CONSUMER_GET_LATENCY_FOR,
533b289aaf6SAxel Dörfler 		&request, sizeof(request), &reply, sizeof(reply));
534b289aaf6SAxel Dörfler 	if (status != B_OK)
535b289aaf6SAxel Dörfler 		return status;
53652a38012Sejakowatz 
537b289aaf6SAxel Dörfler 	*_latency = reply.latency;
538b289aaf6SAxel Dörfler 	*_timesource = reply.timesource;
539b289aaf6SAxel Dörfler 	return B_OK;
54052a38012Sejakowatz }
54152a38012Sejakowatz 
54252a38012Sejakowatz 
54352a38012Sejakowatz status_t
FindSeekTag(const media_destination & destination,bigtime_t targetTime,media_seek_tag * _tag,bigtime_t * _tagged_time,uint32 * _flags,uint32 flags)544b289aaf6SAxel Dörfler BBufferProducer::FindSeekTag(const media_destination& destination,
545b289aaf6SAxel Dörfler 	bigtime_t targetTime, media_seek_tag* _tag, bigtime_t* _tagged_time,
546b289aaf6SAxel Dörfler 	uint32* _flags, uint32 flags)
54752a38012Sejakowatz {
54852a38012Sejakowatz 	CALLED();
549b289aaf6SAxel Dörfler 	if (IS_INVALID_DESTINATION(destination))
55052a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
55152a38012Sejakowatz 
552dfb2ad61Sbeveloper 	consumer_seek_tag_requested_request request;
553dfb2ad61Sbeveloper 	consumer_seek_tag_requested_reply reply;
55452a38012Sejakowatz 
555b289aaf6SAxel Dörfler 	request.destination = destination;
556b289aaf6SAxel Dörfler 	request.target_time = targetTime;
557b289aaf6SAxel Dörfler 	request.flags = flags;
55852a38012Sejakowatz 
559b289aaf6SAxel Dörfler 	status_t status = QueryPort(destination.port, CONSUMER_SEEK_TAG_REQUESTED,
560b289aaf6SAxel Dörfler 		&request, sizeof(request), &reply, sizeof(reply));
561b289aaf6SAxel Dörfler 	if (status != B_OK)
562b289aaf6SAxel Dörfler 		return status;
56352a38012Sejakowatz 
564b289aaf6SAxel Dörfler 	*_tag = reply.seek_tag;
565b289aaf6SAxel Dörfler 	*_tagged_time = reply.tagged_time;
566b289aaf6SAxel Dörfler 	*_flags = reply.flags;
567b289aaf6SAxel Dörfler 	return B_OK;
56852a38012Sejakowatz }
56952a38012Sejakowatz 
57052a38012Sejakowatz 
57152a38012Sejakowatz void
SetInitialLatency(bigtime_t initialLatency,uint32 flags)572b289aaf6SAxel Dörfler BBufferProducer::SetInitialLatency(bigtime_t initialLatency, uint32 flags)
57352a38012Sejakowatz {
574b289aaf6SAxel Dörfler 	fInitialLatency = initialLatency;
57552a38012Sejakowatz 	fInitialFlags = flags;
57652a38012Sejakowatz }
57752a38012Sejakowatz 
578b289aaf6SAxel Dörfler 
579b289aaf6SAxel Dörfler // #pragma mark - private BBufferProducer
580b289aaf6SAxel Dörfler 
58152a38012Sejakowatz 
58252a38012Sejakowatz /*
58352a38012Sejakowatz private unimplemented
58452a38012Sejakowatz BBufferProducer::BBufferProducer()
58552a38012Sejakowatz BBufferProducer::BBufferProducer(const BBufferProducer &clone)
58652a38012Sejakowatz BBufferProducer & BBufferProducer::operator=(const BBufferProducer &clone)
58752a38012Sejakowatz */
58852a38012Sejakowatz 
_Reserved_BufferProducer_0(void *)58952a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_0(void*) { return B_ERROR; }
_Reserved_BufferProducer_1(void *)59052a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_1(void*) { return B_ERROR; }
_Reserved_BufferProducer_2(void *)59152a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_2(void*) { return B_ERROR; }
_Reserved_BufferProducer_3(void *)59252a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_3(void*) { return B_ERROR; }
_Reserved_BufferProducer_4(void *)59352a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_4(void*) { return B_ERROR; }
_Reserved_BufferProducer_5(void *)59452a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_5(void*) { return B_ERROR; }
_Reserved_BufferProducer_6(void *)59552a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_6(void*) { return B_ERROR; }
_Reserved_BufferProducer_7(void *)59652a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_7(void*) { return B_ERROR; }
_Reserved_BufferProducer_8(void *)59752a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_8(void*) { return B_ERROR; }
_Reserved_BufferProducer_9(void *)59852a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_9(void*) { return B_ERROR; }
_Reserved_BufferProducer_10(void *)59952a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_10(void*) { return B_ERROR; }
_Reserved_BufferProducer_11(void *)60052a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_11(void*) { return B_ERROR; }
_Reserved_BufferProducer_12(void *)60152a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_12(void*) { return B_ERROR; }
_Reserved_BufferProducer_13(void *)60252a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_13(void*) { return B_ERROR; }
_Reserved_BufferProducer_14(void *)60352a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_14(void*) { return B_ERROR; }
_Reserved_BufferProducer_15(void *)60452a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_15(void*) { return B_ERROR; }
60552a38012Sejakowatz 
60652a38012Sejakowatz 
607b289aaf6SAxel Dörfler //! Deprecated.
60852a38012Sejakowatz status_t
SendBuffer(BBuffer * buffer,const media_destination & destination)609b289aaf6SAxel Dörfler BBufferProducer::SendBuffer(BBuffer* buffer,
610b289aaf6SAxel Dörfler 	const media_destination& destination)
611b289aaf6SAxel Dörfler {
612b289aaf6SAxel Dörfler 	CALLED();
613b289aaf6SAxel Dörfler 
614b289aaf6SAxel Dörfler 	// Try to find the source - this is the best we can do
615b289aaf6SAxel Dörfler 	media_output output;
616b289aaf6SAxel Dörfler 	int32 cookie = 0;
617b289aaf6SAxel Dörfler 	status_t status = GetNextOutput(&cookie, &output);
618b289aaf6SAxel Dörfler 	if (status != B_OK)
619b289aaf6SAxel Dörfler 		return status;
620b289aaf6SAxel Dörfler 
621b289aaf6SAxel Dörfler 	return SendBuffer(buffer, output.source, destination);
622b289aaf6SAxel Dörfler }
623b289aaf6SAxel Dörfler 
624b289aaf6SAxel Dörfler 
625b289aaf6SAxel Dörfler status_t
clip_shorts_to_region(const int16 * data,int count,BRegion * output)626b289aaf6SAxel Dörfler BBufferProducer::clip_shorts_to_region(const int16* data, int count,
62752a38012Sejakowatz 	BRegion* output)
62852a38012Sejakowatz {
62952a38012Sejakowatz 	UNIMPLEMENTED();
63052a38012Sejakowatz 	return B_ERROR;
63152a38012Sejakowatz }
63252a38012Sejakowatz 
63352a38012Sejakowatz 
63452a38012Sejakowatz status_t
clip_region_to_shorts(const BRegion * input,int16 * data,int maxCount,int * _count)635b289aaf6SAxel Dörfler BBufferProducer::clip_region_to_shorts(const BRegion* input, int16* data,
636b289aaf6SAxel Dörfler 	int maxCount, int* _count)
63752a38012Sejakowatz {
63852a38012Sejakowatz 	UNIMPLEMENTED();
63952a38012Sejakowatz 	return B_ERROR;
64052a38012Sejakowatz }
641