xref: /haiku/src/kits/media/BufferProducer.cpp (revision b289aaf66bbf6e173aa90fa194fc256965f1b34d)
1255a01c7Sbeveloper /*
2*b289aaf6SAxel Dörfler  * Copyright 2002-2010, Haiku.
3*b289aaf6SAxel Dörfler  * Distributed under the terms of the MIT License.
4255a01c7Sbeveloper  *
5*b289aaf6SAxel Dörfler  * Authors:
6*b289aaf6SAxel Dörfler  *		Marcus Overhagen, <Marcus@Overhagen.de>
7*b289aaf6SAxel Dörfler  *		Axel Dörfler, axeld@pinc-software.de.
8255a01c7Sbeveloper  */
9255a01c7Sbeveloper 
10*b289aaf6SAxel Dörfler 
11*b289aaf6SAxel Dörfler #include <Buffer.h>
1260f15390Sbeveloper #include <BufferConsumer.h>
1352a38012Sejakowatz #include <BufferGroup.h>
14*b289aaf6SAxel Dörfler #include <BufferProducer.h>
1552a38012Sejakowatz 
16*b289aaf6SAxel Dörfler #include "debug.h"
17*b289aaf6SAxel Dörfler #include "DataExchange.h"
18*b289aaf6SAxel Dörfler #include "MediaMisc.h"
19*b289aaf6SAxel Dörfler 
20*b289aaf6SAxel Dörfler 
21*b289aaf6SAxel Dörfler // #pragma mark - protected BBufferProducer
22*b289aaf6SAxel Dörfler 
2352a38012Sejakowatz 
2452a38012Sejakowatz BBufferProducer::~BBufferProducer()
2552a38012Sejakowatz {
2652a38012Sejakowatz 	CALLED();
2752a38012Sejakowatz }
2852a38012Sejakowatz 
29*b289aaf6SAxel Dörfler 
30*b289aaf6SAxel Dörfler // #pragma mark - public BBufferProducer
31*b289aaf6SAxel Dörfler 
3252a38012Sejakowatz 
3352a38012Sejakowatz /*static*/ status_t
34*b289aaf6SAxel Dörfler BBufferProducer::ClipDataToRegion(int32 format, int32 size, const void* data,
3552a38012Sejakowatz 	BRegion* region)
3652a38012Sejakowatz {
3752a38012Sejakowatz 	CALLED();
3852a38012Sejakowatz 
3952a38012Sejakowatz 	if (format != B_CLIP_SHORT_RUNS)
4052a38012Sejakowatz 		return B_MEDIA_BAD_CLIP_FORMAT;
4152a38012Sejakowatz 
42*b289aaf6SAxel Dörfler 	return clip_shorts_to_region((const int16*)data, size / sizeof(int16),
43*b289aaf6SAxel Dörfler 		region);
4452a38012Sejakowatz }
4552a38012Sejakowatz 
46*b289aaf6SAxel Dörfler 
4752a38012Sejakowatz media_type
4852a38012Sejakowatz BBufferProducer::ProducerType()
4952a38012Sejakowatz {
5052a38012Sejakowatz 	CALLED();
5152a38012Sejakowatz 	return fProducerType;
5252a38012Sejakowatz }
5352a38012Sejakowatz 
5452a38012Sejakowatz 
55*b289aaf6SAxel Dörfler // #pragma mark - protected BBufferProducer
56*b289aaf6SAxel Dörfler 
57*b289aaf6SAxel Dörfler 
58*b289aaf6SAxel Dörfler BBufferProducer::BBufferProducer(media_type producer_type)
59*b289aaf6SAxel Dörfler 	:
6052a38012Sejakowatz 	BMediaNode("called by BBufferProducer"),
6152a38012Sejakowatz 	fProducerType(producer_type),
6252a38012Sejakowatz 	fInitialLatency(0),
6360f15390Sbeveloper 	fInitialFlags(0),
6460f15390Sbeveloper 	fDelay(0)
6552a38012Sejakowatz {
6652a38012Sejakowatz 	CALLED();
6752a38012Sejakowatz 
6852a38012Sejakowatz 	AddNodeKind(B_BUFFER_PRODUCER);
6952a38012Sejakowatz }
7052a38012Sejakowatz 
7152a38012Sejakowatz 
7252a38012Sejakowatz status_t
73*b289aaf6SAxel Dörfler BBufferProducer::VideoClippingChanged(const media_source& source,
74*b289aaf6SAxel Dörfler 	int16 numShorts, int16* clipData, const media_video_display_info& display,
75*b289aaf6SAxel Dörfler 	int32* /*_deprecated_*/)
7652a38012Sejakowatz {
7752a38012Sejakowatz 	CALLED();
7852a38012Sejakowatz 	// may be implemented by derived classes
7952a38012Sejakowatz 	return B_ERROR;
8052a38012Sejakowatz }
8152a38012Sejakowatz 
8252a38012Sejakowatz 
8352a38012Sejakowatz status_t
84*b289aaf6SAxel Dörfler BBufferProducer::GetLatency(bigtime_t* _latency)
8552a38012Sejakowatz {
8660f15390Sbeveloper 	CALLED();
8760f15390Sbeveloper 	// The default implementation of GetLatency() finds the maximum
8852a38012Sejakowatz 	// latency of your currently-available outputs by iterating over
8952a38012Sejakowatz 	// them, and returns that value in outLatency
9052a38012Sejakowatz 
9160f15390Sbeveloper 	int32 cookie;
9260f15390Sbeveloper 	bigtime_t latency;
9360f15390Sbeveloper 	media_output output;
9460f15390Sbeveloper 	media_node_id unused;
9560f15390Sbeveloper 
96*b289aaf6SAxel Dörfler 	*_latency = 0;
9760f15390Sbeveloper 	cookie = 0;
98*b289aaf6SAxel Dörfler 	while (GetNextOutput(&cookie, &output) == B_OK) {
9960f15390Sbeveloper 		if (output.destination == media_destination::null)
10060f15390Sbeveloper 			continue;
10160f15390Sbeveloper 
102*b289aaf6SAxel Dörfler 		if (output.node.node == fNodeID) {
103*b289aaf6SAxel Dörfler 			// avoid port writes (deadlock) if loopback connection
104*b289aaf6SAxel Dörfler 			if (fConsumerThis == NULL)
10560f15390Sbeveloper 				fConsumerThis = dynamic_cast<BBufferConsumer*>(this);
106*b289aaf6SAxel Dörfler 			if (fConsumerThis == NULL)
10760f15390Sbeveloper 				continue;
108*b289aaf6SAxel Dörfler 
10960f15390Sbeveloper 			latency = 0;
110*b289aaf6SAxel Dörfler 			if (fConsumerThis->GetLatencyFor(output.destination, &latency,
111*b289aaf6SAxel Dörfler 					&unused) == B_OK && latency > *_latency) {
112*b289aaf6SAxel Dörfler 				*_latency = latency;
113*b289aaf6SAxel Dörfler 			}
114*b289aaf6SAxel Dörfler 		} else if (FindLatencyFor(output.destination, &latency, &unused)
115*b289aaf6SAxel Dörfler 				== B_OK &&  latency > *_latency) {
116*b289aaf6SAxel Dörfler 			*_latency = latency;
11760f15390Sbeveloper 		}
11860f15390Sbeveloper 	}
119*b289aaf6SAxel Dörfler 	printf("BBufferProducer::GetLatency: node %ld, name \"%s\" has max latency %Ld\n", fNodeID, fName, *_latency);
12060f15390Sbeveloper 	return B_OK;
12152a38012Sejakowatz }
12252a38012Sejakowatz 
12352a38012Sejakowatz 
12452a38012Sejakowatz status_t
125*b289aaf6SAxel Dörfler BBufferProducer::SetPlayRate(int32 numer, int32 denom)
12652a38012Sejakowatz {
12752a38012Sejakowatz 	CALLED();
12852a38012Sejakowatz 	// may be implemented by derived classes
12952a38012Sejakowatz 	return B_ERROR;
13052a38012Sejakowatz }
13152a38012Sejakowatz 
13252a38012Sejakowatz 
13352a38012Sejakowatz status_t
134*b289aaf6SAxel Dörfler BBufferProducer::HandleMessage(int32 message, const void* data, size_t size)
13552a38012Sejakowatz {
136*b289aaf6SAxel Dörfler 	PRINT(4, "BBufferProducer::HandleMessage %#lx, node %ld\n", message,
137*b289aaf6SAxel Dörfler 		fNodeID);
138*b289aaf6SAxel Dörfler 
13952a38012Sejakowatz 	switch (message) {
14060f15390Sbeveloper 		case PRODUCER_SET_RUN_MODE_DELAY:
14160f15390Sbeveloper 		{
142*b289aaf6SAxel Dörfler 			const producer_set_run_mode_delay_command* command
143*b289aaf6SAxel Dörfler 				= static_cast<const producer_set_run_mode_delay_command*>(data);
14460f15390Sbeveloper 			// when changing this, also change NODE_SET_RUN_MODE
14560f15390Sbeveloper 			fDelay = command->delay;
14660f15390Sbeveloper 			fRunMode = command->mode;
1471df08d39Sbeveloper 			TRACE("PRODUCER_SET_RUN_MODE_DELAY: fDelay now %Ld\n", fDelay);
14860f15390Sbeveloper 			SetRunMode(fRunMode);
14960f15390Sbeveloper 			return B_OK;
15060f15390Sbeveloper 		}
15152a38012Sejakowatz 
15252a38012Sejakowatz 		case PRODUCER_FORMAT_SUGGESTION_REQUESTED:
15352a38012Sejakowatz 		{
154*b289aaf6SAxel Dörfler 			const producer_format_suggestion_requested_request* request
155*b289aaf6SAxel Dörfler 				= static_cast<
156*b289aaf6SAxel Dörfler 					const producer_format_suggestion_requested_request*>(data);
157dfb2ad61Sbeveloper 			producer_format_suggestion_requested_reply reply;
158*b289aaf6SAxel Dörfler 			status_t status = FormatSuggestionRequested(request->type,
159*b289aaf6SAxel Dörfler 				request->quality, &reply.format);
160*b289aaf6SAxel Dörfler 			request->SendReply(status, &reply, sizeof(reply));
16152a38012Sejakowatz 			return B_OK;
16252a38012Sejakowatz 		}
16352a38012Sejakowatz 
16452a38012Sejakowatz 		case PRODUCER_FORMAT_PROPOSAL:
16552a38012Sejakowatz 		{
166*b289aaf6SAxel Dörfler 			const producer_format_proposal_request* request
167*b289aaf6SAxel Dörfler 				= static_cast<const producer_format_proposal_request*>(data);
1688c6a6096Sbeveloper 			producer_format_proposal_reply reply;
1698c6a6096Sbeveloper 			reply.format = request->format;
170*b289aaf6SAxel Dörfler 			status_t status = FormatProposal(request->output, &reply.format);
171*b289aaf6SAxel Dörfler 			request->SendReply(status, &reply, sizeof(reply));
17252a38012Sejakowatz 			return B_OK;
17352a38012Sejakowatz 		}
17452a38012Sejakowatz 
17552a38012Sejakowatz 		case PRODUCER_PREPARE_TO_CONNECT:
17652a38012Sejakowatz 		{
177*b289aaf6SAxel Dörfler 			const producer_prepare_to_connect_request* request
178*b289aaf6SAxel Dörfler 				= static_cast<const producer_prepare_to_connect_request*>(data);
1798c6a6096Sbeveloper 			producer_prepare_to_connect_reply reply;
1808c6a6096Sbeveloper 			reply.format = request->format;
1815ac4fbd7Sbeveloper 			reply.out_source = request->source;
1828c6a6096Sbeveloper 			memcpy(reply.name, request->name, B_MEDIA_NAME_LENGTH);
183*b289aaf6SAxel Dörfler 			status_t status = PrepareToConnect(request->source,
184*b289aaf6SAxel Dörfler 				request->destination, &reply.format, &reply.out_source,
185*b289aaf6SAxel Dörfler 				reply.name);
186*b289aaf6SAxel Dörfler 			request->SendReply(status, &reply, sizeof(reply));
18752a38012Sejakowatz 			return B_OK;
18852a38012Sejakowatz 		}
18952a38012Sejakowatz 
19052a38012Sejakowatz 		case PRODUCER_CONNECT:
19152a38012Sejakowatz 		{
192*b289aaf6SAxel Dörfler 			const producer_connect_request* request
193*b289aaf6SAxel Dörfler 				= static_cast<const producer_connect_request*>(data);
1948c6a6096Sbeveloper 			producer_connect_reply reply;
1958c6a6096Sbeveloper 			memcpy(reply.name, request->name, B_MEDIA_NAME_LENGTH);
196*b289aaf6SAxel Dörfler 			Connect(request->error, request->source, request->destination,
197*b289aaf6SAxel Dörfler 				request->format, reply.name);
1988c6a6096Sbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
19952a38012Sejakowatz 			return B_OK;
20052a38012Sejakowatz 		}
20152a38012Sejakowatz 
20252a38012Sejakowatz 		case PRODUCER_DISCONNECT:
20352a38012Sejakowatz 		{
204*b289aaf6SAxel Dörfler 			const producer_disconnect_request* request
205*b289aaf6SAxel Dörfler 				= static_cast<const producer_disconnect_request*>(data);
2069e9417d2Sbeveloper 			producer_disconnect_reply reply;
2078c6a6096Sbeveloper 			Disconnect(request->source, request->destination);
2089e9417d2Sbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
20952a38012Sejakowatz 			return B_OK;
21052a38012Sejakowatz 		}
21152a38012Sejakowatz 
21252a38012Sejakowatz 		case PRODUCER_GET_INITIAL_LATENCY:
21352a38012Sejakowatz 		{
214*b289aaf6SAxel Dörfler 			const producer_get_initial_latency_request* request
215*b289aaf6SAxel Dörfler 				= static_cast<
216*b289aaf6SAxel Dörfler 					const producer_get_initial_latency_request*>(data);
217dfb2ad61Sbeveloper 			producer_get_initial_latency_reply reply;
21852a38012Sejakowatz 			reply.initial_latency = fInitialLatency;
21952a38012Sejakowatz 			reply.flags = fInitialFlags;
220dfb2ad61Sbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
22152a38012Sejakowatz 			return B_OK;
22252a38012Sejakowatz 		}
22352a38012Sejakowatz 
22452a38012Sejakowatz 		case PRODUCER_SET_PLAY_RATE:
22552a38012Sejakowatz 		{
226*b289aaf6SAxel Dörfler 			const producer_set_play_rate_request* request
227*b289aaf6SAxel Dörfler 				= static_cast<const producer_set_play_rate_request*>(data);
228dfb2ad61Sbeveloper 			producer_set_play_rate_reply reply;
229*b289aaf6SAxel Dörfler 			status_t status = SetPlayRate(request->numer, request->denom);
230*b289aaf6SAxel Dörfler 			request->SendReply(status, &reply, sizeof(reply));
23152a38012Sejakowatz 			return B_OK;
23252a38012Sejakowatz 		}
23352a38012Sejakowatz 
23452a38012Sejakowatz 		case PRODUCER_GET_LATENCY:
23552a38012Sejakowatz 		{
236*b289aaf6SAxel Dörfler 			const producer_get_latency_request* request
237*b289aaf6SAxel Dörfler 				= static_cast<const producer_get_latency_request*>(data);
238dfb2ad61Sbeveloper 			producer_get_latency_reply reply;
239*b289aaf6SAxel Dörfler 			status_t status = GetLatency(&reply.latency);
240*b289aaf6SAxel Dörfler 			request->SendReply(status, &reply, sizeof(reply));
24152a38012Sejakowatz 			return B_OK;
24252a38012Sejakowatz 		}
24352a38012Sejakowatz 
24452a38012Sejakowatz 		case PRODUCER_GET_NEXT_OUTPUT:
24552a38012Sejakowatz 		{
246*b289aaf6SAxel Dörfler 			const producer_get_next_output_request* request
247*b289aaf6SAxel Dörfler 				= static_cast<const producer_get_next_output_request*>(data);
2483620737cSbeveloper 			producer_get_next_output_reply reply;
2498c6a6096Sbeveloper 			reply.cookie = request->cookie;
250*b289aaf6SAxel Dörfler 			status_t status = GetNextOutput(&reply.cookie, &reply.output);
251*b289aaf6SAxel Dörfler 			request->SendReply(status, &reply, sizeof(reply));
25252a38012Sejakowatz 			return B_OK;
25352a38012Sejakowatz 		}
25452a38012Sejakowatz 
25552a38012Sejakowatz 		case PRODUCER_DISPOSE_OUTPUT_COOKIE:
25652a38012Sejakowatz 		{
257*b289aaf6SAxel Dörfler 			const producer_dispose_output_cookie_request*request
258*b289aaf6SAxel Dörfler 				= static_cast<
259*b289aaf6SAxel Dörfler 					const producer_dispose_output_cookie_request*>(data);
2603620737cSbeveloper 			producer_dispose_output_cookie_reply reply;
2618c6a6096Sbeveloper 			DisposeOutputCookie(request->cookie);
2623620737cSbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
26352a38012Sejakowatz 			return B_OK;
26452a38012Sejakowatz 		}
26552a38012Sejakowatz 
26652a38012Sejakowatz 		case PRODUCER_SET_BUFFER_GROUP:
26752a38012Sejakowatz 		{
268*b289aaf6SAxel Dörfler 			const producer_set_buffer_group_command* command
269*b289aaf6SAxel Dörfler 				= static_cast<const producer_set_buffer_group_command*>(data);
270dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
27152a38012Sejakowatz 			BBufferGroup *group;
272*b289aaf6SAxel Dörfler 			group = command->buffer_count != 0
273*b289aaf6SAxel Dörfler 				? new BBufferGroup(command->buffer_count, command->buffers)
274*b289aaf6SAxel Dörfler 				: NULL;
275*b289aaf6SAxel Dörfler 			status_t status = SetBufferGroup(command->source, group);
276dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
27752a38012Sejakowatz 				return B_OK;
278*b289aaf6SAxel Dörfler 			replycommand.info.what
279*b289aaf6SAxel Dörfler 				= media_request_info::B_SET_OUTPUT_BUFFERS_FOR;
280dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
281*b289aaf6SAxel Dörfler 			replycommand.info.status = status;
282dfb2ad61Sbeveloper 			replycommand.info.cookie = (int32)group;
283dfb2ad61Sbeveloper 			replycommand.info.user_data = command->user_data;
284dfb2ad61Sbeveloper 			replycommand.info.source = command->source;
285dfb2ad61Sbeveloper 			replycommand.info.destination = command->destination;
286*b289aaf6SAxel Dörfler 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED,
287*b289aaf6SAxel Dörfler 				&replycommand, sizeof(replycommand));
28852a38012Sejakowatz 			return B_OK;
28952a38012Sejakowatz 		}
29052a38012Sejakowatz 
29152a38012Sejakowatz 		case PRODUCER_FORMAT_CHANGE_REQUESTED:
29252a38012Sejakowatz 		{
293*b289aaf6SAxel Dörfler 			const producer_format_change_requested_command* command
294*b289aaf6SAxel Dörfler 				= static_cast<
295*b289aaf6SAxel Dörfler 					const producer_format_change_requested_command*>(data);
296dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
297dfb2ad61Sbeveloper 			replycommand.info.format = command->format;
298*b289aaf6SAxel Dörfler 			status_t status = FormatChangeRequested(command->source,
299*b289aaf6SAxel Dörfler 				command->destination, &replycommand.info.format, NULL);
300dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
30152a38012Sejakowatz 				return B_OK;
302*b289aaf6SAxel Dörfler 			replycommand.info.what
303*b289aaf6SAxel Dörfler 				= media_request_info::B_REQUEST_FORMAT_CHANGE;
304dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
305*b289aaf6SAxel Dörfler 			replycommand.info.status = status;
306dfb2ad61Sbeveloper 			//replycommand.info.cookie
307dfb2ad61Sbeveloper 			replycommand.info.user_data = command->user_data;
308dfb2ad61Sbeveloper 			replycommand.info.source = command->source;
309dfb2ad61Sbeveloper 			replycommand.info.destination = command->destination;
310*b289aaf6SAxel Dörfler 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED,
311*b289aaf6SAxel Dörfler 				&replycommand, sizeof(replycommand));
31252a38012Sejakowatz 			return B_OK;
31352a38012Sejakowatz 		}
31452a38012Sejakowatz 
31552a38012Sejakowatz 		case PRODUCER_VIDEO_CLIPPING_CHANGED:
31652a38012Sejakowatz 		{
317*b289aaf6SAxel Dörfler 			const producer_video_clipping_changed_command* command
318*b289aaf6SAxel Dörfler 				= static_cast<
319*b289aaf6SAxel Dörfler 					const producer_video_clipping_changed_command*>(data);
320dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
321*b289aaf6SAxel Dörfler 			status_t status = VideoClippingChanged(command->source,
322*b289aaf6SAxel Dörfler 				command->short_count, (int16 *)command->shorts,
323*b289aaf6SAxel Dörfler 				command->display, NULL);
324dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
32552a38012Sejakowatz 				return B_OK;
326*b289aaf6SAxel Dörfler 			replycommand.info.what
327*b289aaf6SAxel Dörfler 				= media_request_info::B_SET_VIDEO_CLIPPING_FOR;
328dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
329*b289aaf6SAxel Dörfler 			replycommand.info.status = status;
330dfb2ad61Sbeveloper 			//replycommand.info.cookie
331dfb2ad61Sbeveloper 			replycommand.info.user_data = command->user_data;
332dfb2ad61Sbeveloper 			replycommand.info.source = command->source;
333dfb2ad61Sbeveloper 			replycommand.info.destination = command->destination;
334dfb2ad61Sbeveloper 			replycommand.info.format.type = B_MEDIA_RAW_VIDEO;
335dfb2ad61Sbeveloper 			replycommand.info.format.u.raw_video.display = command->display;
336*b289aaf6SAxel Dörfler 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED,
337*b289aaf6SAxel Dörfler 				&replycommand, sizeof(replycommand));
33852a38012Sejakowatz 			return B_OK;
33952a38012Sejakowatz 		}
34052a38012Sejakowatz 
34152a38012Sejakowatz 		case PRODUCER_ADDITIONAL_BUFFER_REQUESTED:
34252a38012Sejakowatz 		{
343*b289aaf6SAxel Dörfler 			const producer_additional_buffer_requested_command* command
344*b289aaf6SAxel Dörfler 				= static_cast<
345*b289aaf6SAxel Dörfler 					const producer_additional_buffer_requested_command*>(data);
346*b289aaf6SAxel Dörfler 			AdditionalBufferRequested(command->source, command->prev_buffer,
347*b289aaf6SAxel Dörfler 				command->prev_time, command->has_seek_tag
348*b289aaf6SAxel Dörfler 					? &command->prev_tag : NULL);
34952a38012Sejakowatz 			return B_OK;
35052a38012Sejakowatz 		}
35152a38012Sejakowatz 
35252a38012Sejakowatz 		case PRODUCER_LATENCY_CHANGED:
35352a38012Sejakowatz 		{
354*b289aaf6SAxel Dörfler 			const producer_latency_changed_command* command
355*b289aaf6SAxel Dörfler 				= static_cast<const producer_latency_changed_command*>(data);
356*b289aaf6SAxel Dörfler 			LatencyChanged(command->source, command->destination,
357*b289aaf6SAxel Dörfler 				command->latency, command->flags);
35852a38012Sejakowatz 			return B_OK;
35952a38012Sejakowatz 		}
36052a38012Sejakowatz 
36152a38012Sejakowatz 		case PRODUCER_LATE_NOTICE_RECEIVED:
36252a38012Sejakowatz 		{
363*b289aaf6SAxel Dörfler 			const producer_late_notice_received_command* command
364*b289aaf6SAxel Dörfler 				= static_cast<
365*b289aaf6SAxel Dörfler 					const producer_late_notice_received_command*>(data);
366*b289aaf6SAxel Dörfler 			LateNoticeReceived(command->source, command->how_much,
367*b289aaf6SAxel Dörfler 				command->performance_time);
36852a38012Sejakowatz 			return B_OK;
36952a38012Sejakowatz 		}
37052a38012Sejakowatz 
37152a38012Sejakowatz 		case PRODUCER_ENABLE_OUTPUT:
37252a38012Sejakowatz 		{
373*b289aaf6SAxel Dörfler 			const producer_enable_output_command* command
374*b289aaf6SAxel Dörfler 				= static_cast<const producer_enable_output_command*>(data);
375dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
376dfb2ad61Sbeveloper 			EnableOutput(command->source, command->enabled, NULL);
377dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
37852a38012Sejakowatz 				return B_OK;
379*b289aaf6SAxel Dörfler 
380dfb2ad61Sbeveloper 			replycommand.info.what = media_request_info::B_SET_OUTPUT_ENABLED;
381dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
382dfb2ad61Sbeveloper 			replycommand.info.status = B_OK;
383dfb2ad61Sbeveloper 			//replycommand.info.cookie
384dfb2ad61Sbeveloper 			replycommand.info.user_data = command->user_data;
385dfb2ad61Sbeveloper 			replycommand.info.source = command->source;
386dfb2ad61Sbeveloper 			replycommand.info.destination = command->destination;
387dfb2ad61Sbeveloper 			//replycommand.info.format
388*b289aaf6SAxel Dörfler 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED,
389*b289aaf6SAxel Dörfler 				&replycommand, sizeof(replycommand));
39052a38012Sejakowatz 			return B_OK;
39152a38012Sejakowatz 		}
392*b289aaf6SAxel Dörfler 	}
39352a38012Sejakowatz 
39452a38012Sejakowatz 	return B_ERROR;
39552a38012Sejakowatz }
39652a38012Sejakowatz 
39752a38012Sejakowatz 
39852a38012Sejakowatz void
39952a38012Sejakowatz BBufferProducer::AdditionalBufferRequested(const media_source& source,
400*b289aaf6SAxel Dörfler 	media_buffer_id previousBuffer, bigtime_t previousTime,
401*b289aaf6SAxel Dörfler 	const media_seek_tag* previousTag)
40252a38012Sejakowatz {
40352a38012Sejakowatz 	CALLED();
40452a38012Sejakowatz 	// may be implemented by derived classes
40552a38012Sejakowatz }
40652a38012Sejakowatz 
40752a38012Sejakowatz 
40852a38012Sejakowatz void
40952a38012Sejakowatz BBufferProducer::LatencyChanged(const media_source& source,
410*b289aaf6SAxel Dörfler 	const media_destination& destination, bigtime_t newLatency, uint32 flags)
41152a38012Sejakowatz {
41252a38012Sejakowatz 	CALLED();
41352a38012Sejakowatz 	// may be implemented by derived classes
41452a38012Sejakowatz }
41552a38012Sejakowatz 
41652a38012Sejakowatz 
41752a38012Sejakowatz status_t
418*b289aaf6SAxel Dörfler BBufferProducer::SendBuffer(BBuffer* buffer, const media_source& source,
41952a38012Sejakowatz 	const media_destination& destination)
42052a38012Sejakowatz {
42152a38012Sejakowatz 	CALLED();
42252a38012Sejakowatz 	if (destination == media_destination::null)
42352a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
424*b289aaf6SAxel Dörfler 	if (source == media_source::null)
425*b289aaf6SAxel Dörfler 		return B_MEDIA_BAD_SOURCE;
42652a38012Sejakowatz 	if (buffer == NULL)
42752a38012Sejakowatz 		return B_BAD_VALUE;
42852a38012Sejakowatz 
429dfb2ad61Sbeveloper 	consumer_buffer_received_command command;
430dfb2ad61Sbeveloper 	command.buffer = buffer->ID();
431*b289aaf6SAxel Dörfler 	command.header = *buffer->Header();
432*b289aaf6SAxel Dörfler 	command.header.buffer = command.buffer;
433*b289aaf6SAxel Dörfler 	command.header.source_port = source.port;
434*b289aaf6SAxel Dörfler 	command.header.source = source.id;
435dfb2ad61Sbeveloper 	command.header.destination = destination.id;
4361df08d39Sbeveloper 	command.header.owner = 0; // XXX fill with "buffer owner info area"
437*b289aaf6SAxel Dörfler 	command.header.start_time += fDelay;
438*b289aaf6SAxel Dörfler 		// time compensation as set by BMediaRoster::SetProducerRunModeDelay()
43952a38012Sejakowatz 
440a6d316d8Sbeveloper 	//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);
441a6d316d8Sbeveloper 
442*b289aaf6SAxel Dörfler 	return SendToPort(destination.port, CONSUMER_BUFFER_RECEIVED, &command,
443*b289aaf6SAxel Dörfler 		sizeof(command));
44452a38012Sejakowatz }
44552a38012Sejakowatz 
44652a38012Sejakowatz 
44752a38012Sejakowatz status_t
44852a38012Sejakowatz BBufferProducer::SendDataStatus(int32 status,
449*b289aaf6SAxel Dörfler 	const media_destination& destination, bigtime_t atTime)
45052a38012Sejakowatz {
45152a38012Sejakowatz 	CALLED();
45240f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(destination))
45352a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
45452a38012Sejakowatz 
455dfb2ad61Sbeveloper 	consumer_producer_data_status_command command;
456dfb2ad61Sbeveloper 	command.for_whom = destination;
457dfb2ad61Sbeveloper 	command.status = status;
458*b289aaf6SAxel Dörfler 	command.at_performance_time = atTime;
45952a38012Sejakowatz 
460*b289aaf6SAxel Dörfler 	return SendToPort(destination.port, CONSUMER_PRODUCER_DATA_STATUS, &command,
461*b289aaf6SAxel Dörfler 		sizeof(command));
46252a38012Sejakowatz }
46352a38012Sejakowatz 
46452a38012Sejakowatz 
46552a38012Sejakowatz status_t
46652a38012Sejakowatz BBufferProducer::ProposeFormatChange(media_format* format,
467*b289aaf6SAxel Dörfler 	const media_destination& destination)
46852a38012Sejakowatz {
46952a38012Sejakowatz 	CALLED();
470*b289aaf6SAxel Dörfler 	if (IS_INVALID_DESTINATION(destination))
47152a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
47252a38012Sejakowatz 
4738c6a6096Sbeveloper 	consumer_accept_format_request request;
4748c6a6096Sbeveloper 	consumer_accept_format_reply reply;
47552a38012Sejakowatz 
476*b289aaf6SAxel Dörfler 	request.dest = destination;
4778c6a6096Sbeveloper 	request.format = *format;
478*b289aaf6SAxel Dörfler 	status_t status = QueryPort(destination.port, CONSUMER_ACCEPT_FORMAT,
479*b289aaf6SAxel Dörfler 		&request, sizeof(request), &reply, sizeof(reply));
480*b289aaf6SAxel Dörfler 	if (status != B_OK)
481*b289aaf6SAxel Dörfler 		return status;
48252a38012Sejakowatz 
48352a38012Sejakowatz 	*format = reply.format;
4848c6a6096Sbeveloper 	return B_OK;
48552a38012Sejakowatz }
48652a38012Sejakowatz 
48752a38012Sejakowatz 
48852a38012Sejakowatz status_t
489*b289aaf6SAxel Dörfler BBufferProducer::ChangeFormat(const media_source& source,
490*b289aaf6SAxel Dörfler 	const media_destination& destination, media_format* format)
49152a38012Sejakowatz {
49252a38012Sejakowatz 	CALLED();
493*b289aaf6SAxel Dörfler 	if (IS_INVALID_SOURCE(source))
49452a38012Sejakowatz 		return B_MEDIA_BAD_SOURCE;
495*b289aaf6SAxel Dörfler 	if (IS_INVALID_DESTINATION(destination))
49652a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
49752a38012Sejakowatz 
498dfb2ad61Sbeveloper 	consumer_format_changed_request request;
499dfb2ad61Sbeveloper 	consumer_format_changed_reply reply;
50052a38012Sejakowatz 
501*b289aaf6SAxel Dörfler 	request.producer = source;
502*b289aaf6SAxel Dörfler 	request.consumer = destination;
5038c6a6096Sbeveloper 	request.format = *format;
50452a38012Sejakowatz 
505dfb2ad61Sbeveloper 	// we use a request/reply to make this synchronous
506*b289aaf6SAxel Dörfler 	return QueryPort(destination.port, CONSUMER_FORMAT_CHANGED, &request,
507*b289aaf6SAxel Dörfler 		sizeof(request), &reply, sizeof(reply));
50852a38012Sejakowatz }
50952a38012Sejakowatz 
51052a38012Sejakowatz 
51152a38012Sejakowatz status_t
512*b289aaf6SAxel Dörfler BBufferProducer::FindLatencyFor(const media_destination& destination,
513*b289aaf6SAxel Dörfler 	bigtime_t* _latency, media_node_id* _timesource)
51452a38012Sejakowatz {
51552a38012Sejakowatz 	CALLED();
516*b289aaf6SAxel Dörfler 	if (IS_INVALID_DESTINATION(destination))
51752a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
51852a38012Sejakowatz 
519dfb2ad61Sbeveloper 	consumer_get_latency_for_request request;
520dfb2ad61Sbeveloper 	consumer_get_latency_for_reply reply;
52152a38012Sejakowatz 
522*b289aaf6SAxel Dörfler 	request.for_whom = destination;
52352a38012Sejakowatz 
524*b289aaf6SAxel Dörfler 	status_t status = QueryPort(destination.port, CONSUMER_GET_LATENCY_FOR,
525*b289aaf6SAxel Dörfler 		&request, sizeof(request), &reply, sizeof(reply));
526*b289aaf6SAxel Dörfler 	if (status != B_OK)
527*b289aaf6SAxel Dörfler 		return status;
52852a38012Sejakowatz 
529*b289aaf6SAxel Dörfler 	*_latency = reply.latency;
530*b289aaf6SAxel Dörfler 	*_timesource = reply.timesource;
531*b289aaf6SAxel Dörfler 	return B_OK;
53252a38012Sejakowatz }
53352a38012Sejakowatz 
53452a38012Sejakowatz 
53552a38012Sejakowatz status_t
536*b289aaf6SAxel Dörfler BBufferProducer::FindSeekTag(const media_destination& destination,
537*b289aaf6SAxel Dörfler 	bigtime_t targetTime, media_seek_tag* _tag, bigtime_t* _tagged_time,
538*b289aaf6SAxel Dörfler 	uint32* _flags, uint32 flags)
53952a38012Sejakowatz {
54052a38012Sejakowatz 	CALLED();
541*b289aaf6SAxel Dörfler 	if (IS_INVALID_DESTINATION(destination))
54252a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
54352a38012Sejakowatz 
544dfb2ad61Sbeveloper 	consumer_seek_tag_requested_request request;
545dfb2ad61Sbeveloper 	consumer_seek_tag_requested_reply reply;
54652a38012Sejakowatz 
547*b289aaf6SAxel Dörfler 	request.destination = destination;
548*b289aaf6SAxel Dörfler 	request.target_time = targetTime;
549*b289aaf6SAxel Dörfler 	request.flags = flags;
55052a38012Sejakowatz 
551*b289aaf6SAxel Dörfler 	status_t status = QueryPort(destination.port, CONSUMER_SEEK_TAG_REQUESTED,
552*b289aaf6SAxel Dörfler 		&request, sizeof(request), &reply, sizeof(reply));
553*b289aaf6SAxel Dörfler 	if (status != B_OK)
554*b289aaf6SAxel Dörfler 		return status;
55552a38012Sejakowatz 
556*b289aaf6SAxel Dörfler 	*_tag = reply.seek_tag;
557*b289aaf6SAxel Dörfler 	*_tagged_time = reply.tagged_time;
558*b289aaf6SAxel Dörfler 	*_flags = reply.flags;
559*b289aaf6SAxel Dörfler 	return B_OK;
56052a38012Sejakowatz }
56152a38012Sejakowatz 
56252a38012Sejakowatz 
56352a38012Sejakowatz void
564*b289aaf6SAxel Dörfler BBufferProducer::SetInitialLatency(bigtime_t initialLatency, uint32 flags)
56552a38012Sejakowatz {
566*b289aaf6SAxel Dörfler 	fInitialLatency = initialLatency;
56752a38012Sejakowatz 	fInitialFlags = flags;
56852a38012Sejakowatz }
56952a38012Sejakowatz 
570*b289aaf6SAxel Dörfler 
571*b289aaf6SAxel Dörfler // #pragma mark - private BBufferProducer
572*b289aaf6SAxel Dörfler 
57352a38012Sejakowatz 
57452a38012Sejakowatz /*
57552a38012Sejakowatz private unimplemented
57652a38012Sejakowatz BBufferProducer::BBufferProducer()
57752a38012Sejakowatz BBufferProducer::BBufferProducer(const BBufferProducer &clone)
57852a38012Sejakowatz BBufferProducer & BBufferProducer::operator=(const BBufferProducer &clone)
57952a38012Sejakowatz */
58052a38012Sejakowatz 
58152a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_0(void*) { return B_ERROR; }
58252a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_1(void*) { return B_ERROR; }
58352a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_2(void*) { return B_ERROR; }
58452a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_3(void*) { return B_ERROR; }
58552a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_4(void*) { return B_ERROR; }
58652a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_5(void*) { return B_ERROR; }
58752a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_6(void*) { return B_ERROR; }
58852a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_7(void*) { return B_ERROR; }
58952a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_8(void*) { return B_ERROR; }
59052a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_9(void*) { return B_ERROR; }
59152a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_10(void*) { return B_ERROR; }
59252a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_11(void*) { return B_ERROR; }
59352a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_12(void*) { return B_ERROR; }
59452a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_13(void*) { return B_ERROR; }
59552a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_14(void*) { return B_ERROR; }
59652a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_15(void*) { return B_ERROR; }
59752a38012Sejakowatz 
59852a38012Sejakowatz 
599*b289aaf6SAxel Dörfler //! Deprecated.
60052a38012Sejakowatz status_t
601*b289aaf6SAxel Dörfler BBufferProducer::SendBuffer(BBuffer* buffer,
602*b289aaf6SAxel Dörfler 	const media_destination& destination)
603*b289aaf6SAxel Dörfler {
604*b289aaf6SAxel Dörfler 	CALLED();
605*b289aaf6SAxel Dörfler 
606*b289aaf6SAxel Dörfler 	// Try to find the source - this is the best we can do
607*b289aaf6SAxel Dörfler 	media_output output;
608*b289aaf6SAxel Dörfler 	int32 cookie = 0;
609*b289aaf6SAxel Dörfler 	status_t status = GetNextOutput(&cookie, &output);
610*b289aaf6SAxel Dörfler 	if (status != B_OK)
611*b289aaf6SAxel Dörfler 		return status;
612*b289aaf6SAxel Dörfler 
613*b289aaf6SAxel Dörfler 	return SendBuffer(buffer, output.source, destination);
614*b289aaf6SAxel Dörfler }
615*b289aaf6SAxel Dörfler 
616*b289aaf6SAxel Dörfler 
617*b289aaf6SAxel Dörfler status_t
618*b289aaf6SAxel Dörfler BBufferProducer::clip_shorts_to_region(const int16* data, int count,
61952a38012Sejakowatz 	BRegion* output)
62052a38012Sejakowatz {
62152a38012Sejakowatz 	UNIMPLEMENTED();
62252a38012Sejakowatz 	return B_ERROR;
62352a38012Sejakowatz }
62452a38012Sejakowatz 
62552a38012Sejakowatz 
62652a38012Sejakowatz status_t
627*b289aaf6SAxel Dörfler BBufferProducer::clip_region_to_shorts(const BRegion* input, int16* data,
628*b289aaf6SAxel Dörfler 	int maxCount, int* _count)
62952a38012Sejakowatz {
63052a38012Sejakowatz 	UNIMPLEMENTED();
63152a38012Sejakowatz 	return B_ERROR;
63252a38012Sejakowatz }
633