xref: /haiku/src/kits/media/BufferProducer.cpp (revision a6d316d89d8e5bc962cc70113e008f6363bad235)
1255a01c7Sbeveloper /*
2255a01c7Sbeveloper  * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>
3255a01c7Sbeveloper  *
4255a01c7Sbeveloper  * Permission is hereby granted, free of charge, to any person obtaining
5255a01c7Sbeveloper  * a copy of this software and associated documentation files or portions
6255a01c7Sbeveloper  * thereof (the "Software"), to deal in the Software without restriction,
7255a01c7Sbeveloper  * including without limitation the rights to use, copy, modify, merge,
8255a01c7Sbeveloper  * publish, distribute, sublicense, and/or sell copies of the Software,
9255a01c7Sbeveloper  * and to permit persons to whom the Software is furnished to do so, subject
10255a01c7Sbeveloper  * to the following conditions:
11255a01c7Sbeveloper  *
12255a01c7Sbeveloper  *  * Redistributions of source code must retain the above copyright notice,
13255a01c7Sbeveloper  *    this list of conditions and the following disclaimer.
14255a01c7Sbeveloper  *
15255a01c7Sbeveloper  *  * Redistributions in binary form must reproduce the above copyright notice
16255a01c7Sbeveloper  *    in the  binary, as well as this list of conditions and the following
17255a01c7Sbeveloper  *    disclaimer in the documentation and/or other materials provided with
18255a01c7Sbeveloper  *    the distribution.
19255a01c7Sbeveloper  *
20255a01c7Sbeveloper  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21255a01c7Sbeveloper  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22255a01c7Sbeveloper  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23255a01c7Sbeveloper  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24255a01c7Sbeveloper  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25255a01c7Sbeveloper  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26255a01c7Sbeveloper  * THE SOFTWARE.
27255a01c7Sbeveloper  *
28255a01c7Sbeveloper  */
29255a01c7Sbeveloper 
3052a38012Sejakowatz #include <BufferProducer.h>
3160f15390Sbeveloper #include <BufferConsumer.h>
3252a38012Sejakowatz #include <BufferGroup.h>
3352a38012Sejakowatz #include <Buffer.h>
3452a38012Sejakowatz #include "debug.h"
3540f36b03Sbeveloper #include "MediaMisc.h"
368c6a6096Sbeveloper #include "DataExchange.h"
3752a38012Sejakowatz 
3852a38012Sejakowatz /*************************************************************
3952a38012Sejakowatz  * protected BBufferProducer
4052a38012Sejakowatz  *************************************************************/
4152a38012Sejakowatz 
4252a38012Sejakowatz BBufferProducer::~BBufferProducer()
4352a38012Sejakowatz {
4452a38012Sejakowatz 	CALLED();
4552a38012Sejakowatz }
4652a38012Sejakowatz 
4752a38012Sejakowatz /*************************************************************
4852a38012Sejakowatz  * public BBufferProducer
4952a38012Sejakowatz  *************************************************************/
5052a38012Sejakowatz 
5152a38012Sejakowatz /* static */ status_t
5252a38012Sejakowatz BBufferProducer::ClipDataToRegion(int32 format,
5352a38012Sejakowatz 								  int32 size,
5463ffaa3eSbeveloper 								  const void *data,
5552a38012Sejakowatz 								  BRegion *region)
5652a38012Sejakowatz {
5752a38012Sejakowatz 	CALLED();
5852a38012Sejakowatz 
5952a38012Sejakowatz 	if (format != B_CLIP_SHORT_RUNS)
6052a38012Sejakowatz 		return B_MEDIA_BAD_CLIP_FORMAT;
6152a38012Sejakowatz 
6263ffaa3eSbeveloper 	return clip_shorts_to_region((const int16 *)data, size / sizeof(int16), region);
6352a38012Sejakowatz }
6452a38012Sejakowatz 
6552a38012Sejakowatz media_type
6652a38012Sejakowatz BBufferProducer::ProducerType()
6752a38012Sejakowatz {
6852a38012Sejakowatz 	CALLED();
6952a38012Sejakowatz 	return fProducerType;
7052a38012Sejakowatz }
7152a38012Sejakowatz 
7252a38012Sejakowatz /*************************************************************
7352a38012Sejakowatz  * protected BBufferProducer
7452a38012Sejakowatz  *************************************************************/
7552a38012Sejakowatz 
7652a38012Sejakowatz /* explicit */
7752a38012Sejakowatz BBufferProducer::BBufferProducer(media_type producer_type) :
7852a38012Sejakowatz 	BMediaNode("called by BBufferProducer"),
7952a38012Sejakowatz 	fProducerType(producer_type),
8052a38012Sejakowatz 	fInitialLatency(0),
8160f15390Sbeveloper 	fInitialFlags(0),
8260f15390Sbeveloper 	fDelay(0)
8352a38012Sejakowatz {
8452a38012Sejakowatz 	CALLED();
8552a38012Sejakowatz 
8652a38012Sejakowatz 	AddNodeKind(B_BUFFER_PRODUCER);
8752a38012Sejakowatz }
8852a38012Sejakowatz 
8952a38012Sejakowatz 
9052a38012Sejakowatz status_t
9152a38012Sejakowatz BBufferProducer::VideoClippingChanged(const media_source &for_source,
9252a38012Sejakowatz 									  int16 num_shorts,
9352a38012Sejakowatz 									  int16 *clip_data,
9452a38012Sejakowatz 									  const media_video_display_info &display,
9552a38012Sejakowatz 									  int32 *_deprecated_)
9652a38012Sejakowatz {
9752a38012Sejakowatz 	CALLED();
9852a38012Sejakowatz 	// may be implemented by derived classes
9952a38012Sejakowatz 	return B_ERROR;
10052a38012Sejakowatz }
10152a38012Sejakowatz 
10252a38012Sejakowatz 
10352a38012Sejakowatz status_t
10452a38012Sejakowatz BBufferProducer::GetLatency(bigtime_t *out_lantency)
10552a38012Sejakowatz {
10660f15390Sbeveloper 	CALLED();
10760f15390Sbeveloper 	// The default implementation of GetLatency() finds the maximum
10852a38012Sejakowatz 	// latency of your currently-available outputs by iterating over
10952a38012Sejakowatz 	// them, and returns that value in outLatency
11052a38012Sejakowatz 
11160f15390Sbeveloper 	int32 cookie;
11260f15390Sbeveloper 	bigtime_t latency;
11360f15390Sbeveloper 	media_output output;
11460f15390Sbeveloper 	media_node_id unused;
11560f15390Sbeveloper 
11660f15390Sbeveloper 	*out_lantency = 0;
11760f15390Sbeveloper 	cookie = 0;
11860f15390Sbeveloper 	while (B_OK == GetNextOutput(&cookie, &output)) {
11960f15390Sbeveloper 
12060f15390Sbeveloper 		if (output.destination == media_destination::null)
12160f15390Sbeveloper 			continue;
12260f15390Sbeveloper 
12360f15390Sbeveloper 		if (output.node.node == fNodeID) { // avoid port writes (deadlock) if loopback connection
12460f15390Sbeveloper 			if (!fConsumerThis)
12560f15390Sbeveloper 				fConsumerThis = dynamic_cast<BBufferConsumer *>(this);
12660f15390Sbeveloper 			if (!fConsumerThis)
12760f15390Sbeveloper 				continue;
12860f15390Sbeveloper 			latency = 0;
12960f15390Sbeveloper 			if (B_OK == fConsumerThis->GetLatencyFor(output.destination, &latency, &unused)) {
13060f15390Sbeveloper 				if (latency > *out_lantency) {
13160f15390Sbeveloper 					*out_lantency = latency;
13260f15390Sbeveloper 				}
13360f15390Sbeveloper 			}
13460f15390Sbeveloper 		} else {
13560f15390Sbeveloper 			if (B_OK == FindLatencyFor(output.destination, &latency, &unused)) {
13660f15390Sbeveloper 				if (latency > *out_lantency) {
13760f15390Sbeveloper 					*out_lantency = latency;
13860f15390Sbeveloper 				}
13960f15390Sbeveloper 			}
14060f15390Sbeveloper 		}
14160f15390Sbeveloper 	}
14260f15390Sbeveloper 	printf("BBufferProducer::GetLatency: node %ld, name \"%s\" has max latency %Ld\n", fNodeID, fName, *out_lantency);
14360f15390Sbeveloper 	return B_OK;
14452a38012Sejakowatz }
14552a38012Sejakowatz 
14652a38012Sejakowatz 
14752a38012Sejakowatz status_t
14852a38012Sejakowatz BBufferProducer::SetPlayRate(int32 numer,
14952a38012Sejakowatz 							 int32 denom)
15052a38012Sejakowatz {
15152a38012Sejakowatz 	CALLED();
15252a38012Sejakowatz 	// may be implemented by derived classes
15352a38012Sejakowatz 	return B_ERROR;
15452a38012Sejakowatz }
15552a38012Sejakowatz 
15652a38012Sejakowatz 
15752a38012Sejakowatz status_t
15852a38012Sejakowatz BBufferProducer::HandleMessage(int32 message,
159dfb2ad61Sbeveloper 							   const void *data,
16052a38012Sejakowatz 							   size_t size)
16152a38012Sejakowatz {
1625ac4fbd7Sbeveloper 	PRINT(4, "BBufferProducer::HandleMessage %#lx, node %ld\n", message, fNodeID);
1638c6a6096Sbeveloper 	status_t rv;
16452a38012Sejakowatz 	switch (message) {
16560f15390Sbeveloper 		case PRODUCER_SET_RUN_MODE_DELAY:
16660f15390Sbeveloper 		{
16760f15390Sbeveloper 			const producer_set_run_mode_delay_command *command = static_cast<const producer_set_run_mode_delay_command *>(data);
16860f15390Sbeveloper 			// when changing this, also change NODE_SET_RUN_MODE
16960f15390Sbeveloper 			fDelay = command->delay;
17060f15390Sbeveloper 			fRunMode = command->mode;
1711df08d39Sbeveloper 			TRACE("PRODUCER_SET_RUN_MODE_DELAY: fDelay now %Ld\n", fDelay);
17260f15390Sbeveloper 			SetRunMode(fRunMode);
17360f15390Sbeveloper 			return B_OK;
17460f15390Sbeveloper 		}
17552a38012Sejakowatz 
17652a38012Sejakowatz 		case PRODUCER_FORMAT_SUGGESTION_REQUESTED:
17752a38012Sejakowatz 		{
178dfb2ad61Sbeveloper 			const producer_format_suggestion_requested_request *request = static_cast<const producer_format_suggestion_requested_request *>(data);
179dfb2ad61Sbeveloper 			producer_format_suggestion_requested_reply reply;
180dfb2ad61Sbeveloper 			rv = FormatSuggestionRequested(request->type, request->quality, &reply.format);
181dfb2ad61Sbeveloper 			request->SendReply(rv, &reply, sizeof(reply));
18252a38012Sejakowatz 			return B_OK;
18352a38012Sejakowatz 		}
18452a38012Sejakowatz 
18552a38012Sejakowatz 		case PRODUCER_FORMAT_PROPOSAL:
18652a38012Sejakowatz 		{
187dfb2ad61Sbeveloper 			const producer_format_proposal_request *request = static_cast<const producer_format_proposal_request *>(data);
1888c6a6096Sbeveloper 			producer_format_proposal_reply reply;
1898c6a6096Sbeveloper 			reply.format = request->format;
1908c6a6096Sbeveloper 			rv = FormatProposal(request->output, &reply.format);
1918c6a6096Sbeveloper 			request->SendReply(rv, &reply, sizeof(reply));
19252a38012Sejakowatz 			return B_OK;
19352a38012Sejakowatz 		}
19452a38012Sejakowatz 
19552a38012Sejakowatz 		case PRODUCER_PREPARE_TO_CONNECT:
19652a38012Sejakowatz 		{
197dfb2ad61Sbeveloper 			const producer_prepare_to_connect_request *request = static_cast<const producer_prepare_to_connect_request *>(data);
1988c6a6096Sbeveloper 			producer_prepare_to_connect_reply reply;
1998c6a6096Sbeveloper 			reply.format = request->format;
2005ac4fbd7Sbeveloper 			reply.out_source = request->source;
2018c6a6096Sbeveloper 			memcpy(reply.name, request->name, B_MEDIA_NAME_LENGTH);
2028c6a6096Sbeveloper 			rv = PrepareToConnect(request->source, request->destination, &reply.format, &reply.out_source, reply.name);
2038c6a6096Sbeveloper 			request->SendReply(rv, &reply, sizeof(reply));
20452a38012Sejakowatz 			return B_OK;
20552a38012Sejakowatz 		}
20652a38012Sejakowatz 
20752a38012Sejakowatz 		case PRODUCER_CONNECT:
20852a38012Sejakowatz 		{
209dfb2ad61Sbeveloper 			const producer_connect_request *request = static_cast<const producer_connect_request *>(data);
2108c6a6096Sbeveloper 			producer_connect_reply reply;
2118c6a6096Sbeveloper 			memcpy(reply.name, request->name, B_MEDIA_NAME_LENGTH);
2128c6a6096Sbeveloper 			Connect(request->error, request->source, request->destination, request->format, reply.name);
2138c6a6096Sbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
21452a38012Sejakowatz 			return B_OK;
21552a38012Sejakowatz 		}
21652a38012Sejakowatz 
21752a38012Sejakowatz 		case PRODUCER_DISCONNECT:
21852a38012Sejakowatz 		{
219dfb2ad61Sbeveloper 			const producer_disconnect_request *request = static_cast<const producer_disconnect_request *>(data);
2209e9417d2Sbeveloper 			producer_disconnect_reply reply;
2218c6a6096Sbeveloper 			Disconnect(request->source, request->destination);
2229e9417d2Sbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
22352a38012Sejakowatz 			return B_OK;
22452a38012Sejakowatz 		}
22552a38012Sejakowatz 
22652a38012Sejakowatz 		case PRODUCER_GET_INITIAL_LATENCY:
22752a38012Sejakowatz 		{
228dfb2ad61Sbeveloper 			const producer_get_initial_latency_request *request = static_cast<const producer_get_initial_latency_request *>(data);
229dfb2ad61Sbeveloper 			producer_get_initial_latency_reply reply;
23052a38012Sejakowatz 			reply.initial_latency = fInitialLatency;
23152a38012Sejakowatz 			reply.flags = fInitialFlags;
232dfb2ad61Sbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
23352a38012Sejakowatz 			return B_OK;
23452a38012Sejakowatz 		}
23552a38012Sejakowatz 
23652a38012Sejakowatz 		case PRODUCER_SET_PLAY_RATE:
23752a38012Sejakowatz 		{
238dfb2ad61Sbeveloper 			const producer_set_play_rate_request *request = static_cast<const producer_set_play_rate_request *>(data);
239dfb2ad61Sbeveloper 			producer_set_play_rate_reply reply;
240dfb2ad61Sbeveloper 			rv = SetPlayRate(request->numer, request->denom);
241dfb2ad61Sbeveloper 			request->SendReply(rv, &reply, sizeof(reply));
24252a38012Sejakowatz 			return B_OK;
24352a38012Sejakowatz 		}
24452a38012Sejakowatz 
24552a38012Sejakowatz 		case PRODUCER_GET_LATENCY:
24652a38012Sejakowatz 		{
247dfb2ad61Sbeveloper 			const producer_get_latency_request *request = static_cast<const producer_get_latency_request *>(data);
248dfb2ad61Sbeveloper 			producer_get_latency_reply reply;
249dfb2ad61Sbeveloper 			rv = GetLatency(&reply.latency);
250dfb2ad61Sbeveloper 			request->SendReply(rv, &reply, sizeof(reply));
25152a38012Sejakowatz 			return B_OK;
25252a38012Sejakowatz 		}
25352a38012Sejakowatz 
25452a38012Sejakowatz 		case PRODUCER_GET_NEXT_OUTPUT:
25552a38012Sejakowatz 		{
256dfb2ad61Sbeveloper 			const producer_get_next_output_request *request = static_cast<const producer_get_next_output_request *>(data);
2573620737cSbeveloper 			producer_get_next_output_reply reply;
2588c6a6096Sbeveloper 			reply.cookie = request->cookie;
2593620737cSbeveloper 			rv = GetNextOutput(&reply.cookie, &reply.output);
2603620737cSbeveloper 			request->SendReply(rv, &reply, sizeof(reply));
26152a38012Sejakowatz 			return B_OK;
26252a38012Sejakowatz 		}
26352a38012Sejakowatz 
26452a38012Sejakowatz 		case PRODUCER_DISPOSE_OUTPUT_COOKIE:
26552a38012Sejakowatz 		{
266dfb2ad61Sbeveloper 			const producer_dispose_output_cookie_request *request = static_cast<const producer_dispose_output_cookie_request *>(data);
2673620737cSbeveloper 			producer_dispose_output_cookie_reply reply;
2688c6a6096Sbeveloper 			DisposeOutputCookie(request->cookie);
2693620737cSbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
27052a38012Sejakowatz 			return B_OK;
27152a38012Sejakowatz 		}
27252a38012Sejakowatz 
27352a38012Sejakowatz 		case PRODUCER_SET_BUFFER_GROUP:
27452a38012Sejakowatz 		{
275dfb2ad61Sbeveloper 			const producer_set_buffer_group_command *command = static_cast<const producer_set_buffer_group_command *>(data);
276dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
27752a38012Sejakowatz 			BBufferGroup *group;
278dfb2ad61Sbeveloper 			group = command->buffer_count != 0 ? new BBufferGroup(command->buffer_count, command->buffers) : NULL;
279dfb2ad61Sbeveloper 			rv = SetBufferGroup(command->source, group);
280dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
28152a38012Sejakowatz 				return B_OK;
282dfb2ad61Sbeveloper 			replycommand.info.what = media_request_info::B_SET_OUTPUT_BUFFERS_FOR;
283dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
284dfb2ad61Sbeveloper 			replycommand.info.status = rv;
285dfb2ad61Sbeveloper 			replycommand.info.cookie = (int32)group;
286dfb2ad61Sbeveloper 			replycommand.info.user_data = command->user_data;
287dfb2ad61Sbeveloper 			replycommand.info.source = command->source;
288dfb2ad61Sbeveloper 			replycommand.info.destination = command->destination;
289dfb2ad61Sbeveloper 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED, &replycommand, sizeof(replycommand));
29052a38012Sejakowatz 			return B_OK;
29152a38012Sejakowatz 		}
29252a38012Sejakowatz 
29352a38012Sejakowatz 		case PRODUCER_FORMAT_CHANGE_REQUESTED:
29452a38012Sejakowatz 		{
295dfb2ad61Sbeveloper 			const producer_format_change_requested_command *command = static_cast<const producer_format_change_requested_command *>(data);
296dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
297dfb2ad61Sbeveloper 			replycommand.info.format = command->format;
298dfb2ad61Sbeveloper 			rv = FormatChangeRequested(command->source, command->destination, &replycommand.info.format, NULL);
299dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
30052a38012Sejakowatz 				return B_OK;
301dfb2ad61Sbeveloper 			replycommand.info.what = media_request_info::B_REQUEST_FORMAT_CHANGE;
302dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
303dfb2ad61Sbeveloper 			replycommand.info.status = rv;
304dfb2ad61Sbeveloper 			//replycommand.info.cookie
305dfb2ad61Sbeveloper 			replycommand.info.user_data = command->user_data;
306dfb2ad61Sbeveloper 			replycommand.info.source = command->source;
307dfb2ad61Sbeveloper 			replycommand.info.destination = command->destination;
308dfb2ad61Sbeveloper 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED, &replycommand, sizeof(replycommand));
30952a38012Sejakowatz 			return B_OK;
31052a38012Sejakowatz 		}
31152a38012Sejakowatz 
31252a38012Sejakowatz 		case PRODUCER_VIDEO_CLIPPING_CHANGED:
31352a38012Sejakowatz 		{
314dfb2ad61Sbeveloper 			const producer_video_clipping_changed_command *command = static_cast<const producer_video_clipping_changed_command *>(data);
315dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
316dfb2ad61Sbeveloper 			rv = VideoClippingChanged(command->source, command->short_count, (int16 *)command->shorts, command->display, NULL);
317dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
31852a38012Sejakowatz 				return B_OK;
319dfb2ad61Sbeveloper 			replycommand.info.what = media_request_info::B_SET_VIDEO_CLIPPING_FOR;
320dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
321dfb2ad61Sbeveloper 			replycommand.info.status = rv;
322dfb2ad61Sbeveloper 			//replycommand.info.cookie
323dfb2ad61Sbeveloper 			replycommand.info.user_data = command->user_data;
324dfb2ad61Sbeveloper 			replycommand.info.source = command->source;
325dfb2ad61Sbeveloper 			replycommand.info.destination = command->destination;
326dfb2ad61Sbeveloper 			replycommand.info.format.type = B_MEDIA_RAW_VIDEO;
327dfb2ad61Sbeveloper 			replycommand.info.format.u.raw_video.display = command->display;
328dfb2ad61Sbeveloper 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED, &replycommand, sizeof(replycommand));
32952a38012Sejakowatz 			return B_OK;
33052a38012Sejakowatz 		}
33152a38012Sejakowatz 
33252a38012Sejakowatz 		case PRODUCER_ADDITIONAL_BUFFER_REQUESTED:
33352a38012Sejakowatz 		{
334dfb2ad61Sbeveloper 			const producer_additional_buffer_requested_command *command = static_cast<const producer_additional_buffer_requested_command *>(data);
335dfb2ad61Sbeveloper 			AdditionalBufferRequested(command->source, command->prev_buffer, command->prev_time, command->has_seek_tag ? &command->prev_tag : NULL);
33652a38012Sejakowatz 			return B_OK;
33752a38012Sejakowatz 		}
33852a38012Sejakowatz 
33952a38012Sejakowatz 		case PRODUCER_LATENCY_CHANGED:
34052a38012Sejakowatz 		{
341dfb2ad61Sbeveloper 			const producer_latency_changed_command *command = static_cast<const producer_latency_changed_command *>(data);
342dfb2ad61Sbeveloper 			LatencyChanged(command->source, command->destination, command->latency, command->flags);
34352a38012Sejakowatz 			return B_OK;
34452a38012Sejakowatz 		}
34552a38012Sejakowatz 
34652a38012Sejakowatz 		case PRODUCER_LATE_NOTICE_RECEIVED:
34752a38012Sejakowatz 		{
348dfb2ad61Sbeveloper 			const producer_late_notice_received_command *command = static_cast<const producer_late_notice_received_command *>(data);
349dfb2ad61Sbeveloper 			LateNoticeReceived(command->source, command->how_much, command->performance_time);
35052a38012Sejakowatz 			return B_OK;
35152a38012Sejakowatz 		}
35252a38012Sejakowatz 
35352a38012Sejakowatz 		case PRODUCER_ENABLE_OUTPUT:
35452a38012Sejakowatz 		{
355dfb2ad61Sbeveloper 			const producer_enable_output_command *command = static_cast<const producer_enable_output_command *>(data);
356dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
357dfb2ad61Sbeveloper 			EnableOutput(command->source, command->enabled, NULL);
358dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
35952a38012Sejakowatz 				return B_OK;
360dfb2ad61Sbeveloper 			replycommand.info.what = media_request_info::B_SET_OUTPUT_ENABLED;
361dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
362dfb2ad61Sbeveloper 			replycommand.info.status = B_OK;
363dfb2ad61Sbeveloper 			//replycommand.info.cookie
364dfb2ad61Sbeveloper 			replycommand.info.user_data = command->user_data;
365dfb2ad61Sbeveloper 			replycommand.info.source = command->source;
366dfb2ad61Sbeveloper 			replycommand.info.destination = command->destination;
367dfb2ad61Sbeveloper 			//replycommand.info.format
368dfb2ad61Sbeveloper 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED, &replycommand, sizeof(replycommand));
36952a38012Sejakowatz 			return B_OK;
37052a38012Sejakowatz 		}
37152a38012Sejakowatz 
37252a38012Sejakowatz 	};
37352a38012Sejakowatz 	return B_ERROR;
37452a38012Sejakowatz }
37552a38012Sejakowatz 
37652a38012Sejakowatz 
37752a38012Sejakowatz void
37852a38012Sejakowatz BBufferProducer::AdditionalBufferRequested(const media_source &source,
37952a38012Sejakowatz 										   media_buffer_id prev_buffer,
38052a38012Sejakowatz 										   bigtime_t prev_time,
38152a38012Sejakowatz 										   const media_seek_tag *prev_tag)
38252a38012Sejakowatz {
38352a38012Sejakowatz 	CALLED();
38452a38012Sejakowatz 	// may be implemented by derived classes
38552a38012Sejakowatz }
38652a38012Sejakowatz 
38752a38012Sejakowatz 
38852a38012Sejakowatz void
38952a38012Sejakowatz BBufferProducer::LatencyChanged(const media_source &source,
39052a38012Sejakowatz 								const media_destination &destination,
39152a38012Sejakowatz 								bigtime_t new_latency,
39252a38012Sejakowatz 								uint32 flags)
39352a38012Sejakowatz {
39452a38012Sejakowatz 	CALLED();
39552a38012Sejakowatz 	// may be implemented by derived classes
39652a38012Sejakowatz }
39752a38012Sejakowatz 
39852a38012Sejakowatz 
39952a38012Sejakowatz status_t
40052a38012Sejakowatz BBufferProducer::SendBuffer(BBuffer *buffer,
40152a38012Sejakowatz 							const media_destination &destination)
40252a38012Sejakowatz {
40352a38012Sejakowatz 	CALLED();
40452a38012Sejakowatz 	if (destination == media_destination::null)
40552a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
40652a38012Sejakowatz 	if (buffer == NULL)
40752a38012Sejakowatz 		return B_BAD_VALUE;
40852a38012Sejakowatz 
409dfb2ad61Sbeveloper 	consumer_buffer_received_command command;
410dfb2ad61Sbeveloper 	command.buffer = buffer->ID();
411dfb2ad61Sbeveloper 	command.header = *(buffer->Header());
412dfb2ad61Sbeveloper 	command.header.buffer = command.buffer; // buffer->ID();
413dfb2ad61Sbeveloper 	command.header.destination = destination.id;
4141df08d39Sbeveloper 	command.header.owner = 0; // XXX fill with "buffer owner info area"
41560f15390Sbeveloper 	command.header.start_time += fDelay; // time compensation as set by BMediaRoster::SetProducerRunModeDelay()
41652a38012Sejakowatz 
417*a6d316d8Sbeveloper 	//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);
418*a6d316d8Sbeveloper 
419dfb2ad61Sbeveloper 	return SendToPort(destination.port, CONSUMER_BUFFER_RECEIVED, &command, sizeof(command));
42052a38012Sejakowatz }
42152a38012Sejakowatz 
42252a38012Sejakowatz 
42352a38012Sejakowatz status_t
42452a38012Sejakowatz BBufferProducer::SendDataStatus(int32 status,
42552a38012Sejakowatz 								const media_destination &destination,
42652a38012Sejakowatz 								bigtime_t at_time)
42752a38012Sejakowatz {
42852a38012Sejakowatz 	CALLED();
42940f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(destination))
43052a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
43152a38012Sejakowatz 
432dfb2ad61Sbeveloper 	consumer_producer_data_status_command command;
433dfb2ad61Sbeveloper 	command.for_whom = destination;
434dfb2ad61Sbeveloper 	command.status = status;
435dfb2ad61Sbeveloper 	command.at_performance_time = at_time;
43652a38012Sejakowatz 
437dfb2ad61Sbeveloper 	return SendToPort(destination.port, CONSUMER_PRODUCER_DATA_STATUS, &command, sizeof(command));
43852a38012Sejakowatz }
43952a38012Sejakowatz 
44052a38012Sejakowatz 
44152a38012Sejakowatz status_t
44252a38012Sejakowatz BBufferProducer::ProposeFormatChange(media_format *format,
44352a38012Sejakowatz 									 const media_destination &for_destination)
44452a38012Sejakowatz {
44552a38012Sejakowatz 	CALLED();
44640f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(for_destination))
44752a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
44852a38012Sejakowatz 
4498c6a6096Sbeveloper 	consumer_accept_format_request request;
4508c6a6096Sbeveloper 	consumer_accept_format_reply reply;
45152a38012Sejakowatz 	status_t rv;
45252a38012Sejakowatz 
4538c6a6096Sbeveloper 	request.dest = for_destination;
4548c6a6096Sbeveloper 	request.format = *format;
4558c6a6096Sbeveloper 	rv = QueryPort(for_destination.port, CONSUMER_ACCEPT_FORMAT, &request, sizeof(request), &reply, sizeof(reply));
4568c6a6096Sbeveloper 	if (rv != B_OK)
45752a38012Sejakowatz 		return rv;
45852a38012Sejakowatz 
45952a38012Sejakowatz 	*format = reply.format;
4608c6a6096Sbeveloper 	return B_OK;
46152a38012Sejakowatz }
46252a38012Sejakowatz 
46352a38012Sejakowatz 
46452a38012Sejakowatz status_t
46552a38012Sejakowatz BBufferProducer::ChangeFormat(const media_source &for_source,
46652a38012Sejakowatz 							  const media_destination &for_destination,
46752a38012Sejakowatz 							  media_format *format)
46852a38012Sejakowatz {
46952a38012Sejakowatz 	CALLED();
47040f36b03Sbeveloper 	if (IS_INVALID_SOURCE(for_source))
47152a38012Sejakowatz 		return B_MEDIA_BAD_SOURCE;
47240f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(for_destination))
47352a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
47452a38012Sejakowatz 
475dfb2ad61Sbeveloper 	consumer_format_changed_request request;
476dfb2ad61Sbeveloper 	consumer_format_changed_reply reply;
47752a38012Sejakowatz 
4788c6a6096Sbeveloper 	request.producer = for_source;
4798c6a6096Sbeveloper 	request.consumer = for_destination;
4808c6a6096Sbeveloper 	request.format = *format;
48152a38012Sejakowatz 
482dfb2ad61Sbeveloper 	// we use a request/reply to make this synchronous
483dfb2ad61Sbeveloper 	return QueryPort(for_destination.port, CONSUMER_FORMAT_CHANGED, &request, sizeof(request), &reply, sizeof(reply));
48452a38012Sejakowatz }
48552a38012Sejakowatz 
48652a38012Sejakowatz 
48752a38012Sejakowatz status_t
48852a38012Sejakowatz BBufferProducer::FindLatencyFor(const media_destination &for_destination,
48952a38012Sejakowatz 								bigtime_t *out_latency,
49052a38012Sejakowatz 								media_node_id *out_timesource)
49152a38012Sejakowatz {
49252a38012Sejakowatz 	CALLED();
49340f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(for_destination))
49452a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
49552a38012Sejakowatz 
49652a38012Sejakowatz 	status_t rv;
497dfb2ad61Sbeveloper 	consumer_get_latency_for_request request;
498dfb2ad61Sbeveloper 	consumer_get_latency_for_reply reply;
49952a38012Sejakowatz 
5008c6a6096Sbeveloper 	request.for_whom = for_destination;
50152a38012Sejakowatz 
502dfb2ad61Sbeveloper 	rv = QueryPort(for_destination.port, CONSUMER_GET_LATENCY_FOR, &request, sizeof(request), &reply, sizeof(reply));
503dfb2ad61Sbeveloper 	if (rv != B_OK)
50452a38012Sejakowatz 		return rv;
50552a38012Sejakowatz 
50652a38012Sejakowatz 	*out_latency = reply.latency;
50752a38012Sejakowatz 	*out_timesource = reply.timesource;
508dfb2ad61Sbeveloper 	return rv;
50952a38012Sejakowatz }
51052a38012Sejakowatz 
51152a38012Sejakowatz 
51252a38012Sejakowatz status_t
51352a38012Sejakowatz BBufferProducer::FindSeekTag(const media_destination &for_destination,
51452a38012Sejakowatz 							 bigtime_t in_target_time,
51552a38012Sejakowatz 							 media_seek_tag *out_tag,
51652a38012Sejakowatz 							 bigtime_t *out_tagged_time,
51752a38012Sejakowatz 							 uint32 *out_flags,
51852a38012Sejakowatz 							 uint32 in_flags)
51952a38012Sejakowatz {
52052a38012Sejakowatz 	CALLED();
52140f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(for_destination))
52252a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
52352a38012Sejakowatz 
52452a38012Sejakowatz 	status_t rv;
525dfb2ad61Sbeveloper 	consumer_seek_tag_requested_request request;
526dfb2ad61Sbeveloper 	consumer_seek_tag_requested_reply reply;
52752a38012Sejakowatz 
5288c6a6096Sbeveloper 	request.destination = for_destination;
5298c6a6096Sbeveloper 	request.target_time = in_target_time;
5308c6a6096Sbeveloper 	request.flags = in_flags;
53152a38012Sejakowatz 
532dfb2ad61Sbeveloper 	rv = QueryPort(for_destination.port, CONSUMER_SEEK_TAG_REQUESTED, &request, sizeof(request), &reply, sizeof(reply));
533dfb2ad61Sbeveloper 	if (rv != B_OK)
53452a38012Sejakowatz 		return rv;
53552a38012Sejakowatz 
53652a38012Sejakowatz 	*out_tag = reply.seek_tag;
53752a38012Sejakowatz 	*out_tagged_time = reply.tagged_time;
53852a38012Sejakowatz 	*out_flags = reply.flags;
539dfb2ad61Sbeveloper 	return rv;
54052a38012Sejakowatz }
54152a38012Sejakowatz 
54252a38012Sejakowatz 
54352a38012Sejakowatz void
54452a38012Sejakowatz BBufferProducer::SetInitialLatency(bigtime_t inInitialLatency,
54552a38012Sejakowatz 								   uint32 flags)
54652a38012Sejakowatz {
54752a38012Sejakowatz 	fInitialLatency = inInitialLatency;
54852a38012Sejakowatz 	fInitialFlags = flags;
54952a38012Sejakowatz }
55052a38012Sejakowatz 
55152a38012Sejakowatz /*************************************************************
55252a38012Sejakowatz  * private BBufferProducer
55352a38012Sejakowatz  *************************************************************/
55452a38012Sejakowatz 
55552a38012Sejakowatz /*
55652a38012Sejakowatz private unimplemented
55752a38012Sejakowatz BBufferProducer::BBufferProducer()
55852a38012Sejakowatz BBufferProducer::BBufferProducer(const BBufferProducer &clone)
55952a38012Sejakowatz BBufferProducer & BBufferProducer::operator=(const BBufferProducer &clone)
56052a38012Sejakowatz */
56152a38012Sejakowatz 
56252a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_0(void *) { return B_ERROR; }
56352a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_1(void *) { return B_ERROR; }
56452a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_2(void *) { return B_ERROR; }
56552a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_3(void *) { return B_ERROR; }
56652a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_4(void *) { return B_ERROR; }
56752a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_5(void *) { return B_ERROR; }
56852a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_6(void *) { return B_ERROR; }
56952a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_7(void *) { return B_ERROR; }
57052a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_8(void *) { return B_ERROR; }
57152a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_9(void *) { return B_ERROR; }
57252a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_10(void *) { return B_ERROR; }
57352a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_11(void *) { return B_ERROR; }
57452a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_12(void *) { return B_ERROR; }
57552a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_13(void *) { return B_ERROR; }
57652a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_14(void *) { return B_ERROR; }
57752a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_15(void *) { return B_ERROR; }
57852a38012Sejakowatz 
57952a38012Sejakowatz 
58052a38012Sejakowatz status_t
58163ffaa3eSbeveloper BBufferProducer::clip_shorts_to_region(const int16 *data,
58252a38012Sejakowatz 									   int count,
58352a38012Sejakowatz 									   BRegion *output)
58452a38012Sejakowatz {
58552a38012Sejakowatz 	UNIMPLEMENTED();
58652a38012Sejakowatz 
58752a38012Sejakowatz 	return B_ERROR;
58852a38012Sejakowatz }
58952a38012Sejakowatz 
59052a38012Sejakowatz 
59152a38012Sejakowatz status_t
59252a38012Sejakowatz BBufferProducer::clip_region_to_shorts(const BRegion *input,
59363ffaa3eSbeveloper 									   int16 *data,
59452a38012Sejakowatz 									   int max_count,
59552a38012Sejakowatz 									   int *out_count)
59652a38012Sejakowatz {
59752a38012Sejakowatz 	UNIMPLEMENTED();
59852a38012Sejakowatz 
59952a38012Sejakowatz 	return B_ERROR;
60052a38012Sejakowatz }
60152a38012Sejakowatz 
602