xref: /haiku/src/kits/media/BufferProducer.cpp (revision 60f15390cd7b83f1a8083d8530d7256aa1ea71e3)
152a38012Sejakowatz /***********************************************************************
252a38012Sejakowatz  * AUTHOR: Marcus Overhagen
352a38012Sejakowatz  *   FILE: BufferProducer.cpp
452a38012Sejakowatz  *  DESCR:
552a38012Sejakowatz  ***********************************************************************/
652a38012Sejakowatz #include <BufferProducer.h>
7*60f15390Sbeveloper #include <BufferConsumer.h>
852a38012Sejakowatz #include <BufferGroup.h>
952a38012Sejakowatz #include <Buffer.h>
1052a38012Sejakowatz #include "debug.h"
1140f36b03Sbeveloper #include "MediaMisc.h"
128c6a6096Sbeveloper #include "DataExchange.h"
1352a38012Sejakowatz 
1452a38012Sejakowatz /*************************************************************
1552a38012Sejakowatz  * protected BBufferProducer
1652a38012Sejakowatz  *************************************************************/
1752a38012Sejakowatz 
1852a38012Sejakowatz BBufferProducer::~BBufferProducer()
1952a38012Sejakowatz {
2052a38012Sejakowatz 	CALLED();
2152a38012Sejakowatz }
2252a38012Sejakowatz 
2352a38012Sejakowatz /*************************************************************
2452a38012Sejakowatz  * public BBufferProducer
2552a38012Sejakowatz  *************************************************************/
2652a38012Sejakowatz 
2752a38012Sejakowatz /* static */ status_t
2852a38012Sejakowatz BBufferProducer::ClipDataToRegion(int32 format,
2952a38012Sejakowatz 								  int32 size,
3063ffaa3eSbeveloper 								  const void *data,
3152a38012Sejakowatz 								  BRegion *region)
3252a38012Sejakowatz {
3352a38012Sejakowatz 	CALLED();
3452a38012Sejakowatz 
3552a38012Sejakowatz 	if (format != B_CLIP_SHORT_RUNS)
3652a38012Sejakowatz 		return B_MEDIA_BAD_CLIP_FORMAT;
3752a38012Sejakowatz 
3863ffaa3eSbeveloper 	return clip_shorts_to_region((const int16 *)data, size / sizeof(int16), region);
3952a38012Sejakowatz }
4052a38012Sejakowatz 
4152a38012Sejakowatz media_type
4252a38012Sejakowatz BBufferProducer::ProducerType()
4352a38012Sejakowatz {
4452a38012Sejakowatz 	CALLED();
4552a38012Sejakowatz 	return fProducerType;
4652a38012Sejakowatz }
4752a38012Sejakowatz 
4852a38012Sejakowatz /*************************************************************
4952a38012Sejakowatz  * protected BBufferProducer
5052a38012Sejakowatz  *************************************************************/
5152a38012Sejakowatz 
5252a38012Sejakowatz /* explicit */
5352a38012Sejakowatz BBufferProducer::BBufferProducer(media_type producer_type) :
5452a38012Sejakowatz 	BMediaNode("called by BBufferProducer"),
5552a38012Sejakowatz 	fProducerType(producer_type),
5652a38012Sejakowatz 	fInitialLatency(0),
57*60f15390Sbeveloper 	fInitialFlags(0),
58*60f15390Sbeveloper 	fDelay(0)
5952a38012Sejakowatz {
6052a38012Sejakowatz 	CALLED();
6152a38012Sejakowatz 
6252a38012Sejakowatz 	AddNodeKind(B_BUFFER_PRODUCER);
6352a38012Sejakowatz }
6452a38012Sejakowatz 
6552a38012Sejakowatz 
6652a38012Sejakowatz status_t
6752a38012Sejakowatz BBufferProducer::VideoClippingChanged(const media_source &for_source,
6852a38012Sejakowatz 									  int16 num_shorts,
6952a38012Sejakowatz 									  int16 *clip_data,
7052a38012Sejakowatz 									  const media_video_display_info &display,
7152a38012Sejakowatz 									  int32 *_deprecated_)
7252a38012Sejakowatz {
7352a38012Sejakowatz 	CALLED();
7452a38012Sejakowatz 	// may be implemented by derived classes
7552a38012Sejakowatz 	return B_ERROR;
7652a38012Sejakowatz }
7752a38012Sejakowatz 
7852a38012Sejakowatz 
7952a38012Sejakowatz status_t
8052a38012Sejakowatz BBufferProducer::GetLatency(bigtime_t *out_lantency)
8152a38012Sejakowatz {
82*60f15390Sbeveloper 	CALLED();
83*60f15390Sbeveloper 	// The default implementation of GetLatency() finds the maximum
8452a38012Sejakowatz 	// latency of your currently-available outputs by iterating over
8552a38012Sejakowatz 	// them, and returns that value in outLatency
8652a38012Sejakowatz 
87*60f15390Sbeveloper 	int32 cookie;
88*60f15390Sbeveloper 	bigtime_t latency;
89*60f15390Sbeveloper 	media_output output;
90*60f15390Sbeveloper 	media_node_id unused;
91*60f15390Sbeveloper 
92*60f15390Sbeveloper 	*out_lantency = 0;
93*60f15390Sbeveloper 	cookie = 0;
94*60f15390Sbeveloper 	while (B_OK == GetNextOutput(&cookie, &output)) {
95*60f15390Sbeveloper 		cookie++;
96*60f15390Sbeveloper 
97*60f15390Sbeveloper 		if (output.destination == media_destination::null)
98*60f15390Sbeveloper 			continue;
99*60f15390Sbeveloper 
100*60f15390Sbeveloper 		if (output.node.node == fNodeID) { // avoid port writes (deadlock) if loopback connection
101*60f15390Sbeveloper 			if (!fConsumerThis)
102*60f15390Sbeveloper 				fConsumerThis = dynamic_cast<BBufferConsumer *>(this);
103*60f15390Sbeveloper 			if (!fConsumerThis)
104*60f15390Sbeveloper 				continue;
105*60f15390Sbeveloper 			latency = 0;
106*60f15390Sbeveloper 			if (B_OK == fConsumerThis->GetLatencyFor(output.destination, &latency, &unused)) {
107*60f15390Sbeveloper 				if (latency > *out_lantency) {
108*60f15390Sbeveloper 					*out_lantency = latency;
109*60f15390Sbeveloper 				}
110*60f15390Sbeveloper 			}
111*60f15390Sbeveloper 		} else {
112*60f15390Sbeveloper 			if (B_OK == FindLatencyFor(output.destination, &latency, &unused)) {
113*60f15390Sbeveloper 				if (latency > *out_lantency) {
114*60f15390Sbeveloper 					*out_lantency = latency;
115*60f15390Sbeveloper 				}
116*60f15390Sbeveloper 			}
117*60f15390Sbeveloper 		}
118*60f15390Sbeveloper 	}
119*60f15390Sbeveloper 	printf("BBufferProducer::GetLatency: node %ld, name \"%s\" has max latency %Ld\n", fNodeID, fName, *out_lantency);
120*60f15390Sbeveloper 	return B_OK;
12152a38012Sejakowatz }
12252a38012Sejakowatz 
12352a38012Sejakowatz 
12452a38012Sejakowatz status_t
12552a38012Sejakowatz BBufferProducer::SetPlayRate(int32 numer,
12652a38012Sejakowatz 							 int32 denom)
12752a38012Sejakowatz {
12852a38012Sejakowatz 	CALLED();
12952a38012Sejakowatz 	// may be implemented by derived classes
13052a38012Sejakowatz 	return B_ERROR;
13152a38012Sejakowatz }
13252a38012Sejakowatz 
13352a38012Sejakowatz 
13452a38012Sejakowatz status_t
13552a38012Sejakowatz BBufferProducer::HandleMessage(int32 message,
136dfb2ad61Sbeveloper 							   const void *data,
13752a38012Sejakowatz 							   size_t size)
13852a38012Sejakowatz {
139353b9f6bSbeveloper 	INFO("BBufferProducer::HandleMessage %#lx, node %ld\n", message, fNodeID);
1408c6a6096Sbeveloper 	status_t rv;
14152a38012Sejakowatz 	switch (message) {
142*60f15390Sbeveloper 		case PRODUCER_SET_RUN_MODE_DELAY:
143*60f15390Sbeveloper 		{
144*60f15390Sbeveloper 			const producer_set_run_mode_delay_command *command = static_cast<const producer_set_run_mode_delay_command *>(data);
145*60f15390Sbeveloper 			// when changing this, also change NODE_SET_RUN_MODE
146*60f15390Sbeveloper 			fDelay = command->delay;
147*60f15390Sbeveloper 			fRunMode = command->mode;
148*60f15390Sbeveloper 			SetRunMode(fRunMode);
149*60f15390Sbeveloper 			return B_OK;
150*60f15390Sbeveloper 		}
15152a38012Sejakowatz 
15252a38012Sejakowatz 		case PRODUCER_FORMAT_SUGGESTION_REQUESTED:
15352a38012Sejakowatz 		{
154dfb2ad61Sbeveloper 			const producer_format_suggestion_requested_request *request = static_cast<const producer_format_suggestion_requested_request *>(data);
155dfb2ad61Sbeveloper 			producer_format_suggestion_requested_reply reply;
156dfb2ad61Sbeveloper 			rv = FormatSuggestionRequested(request->type, request->quality, &reply.format);
157dfb2ad61Sbeveloper 			request->SendReply(rv, &reply, sizeof(reply));
15852a38012Sejakowatz 			return B_OK;
15952a38012Sejakowatz 		}
16052a38012Sejakowatz 
16152a38012Sejakowatz 		case PRODUCER_FORMAT_PROPOSAL:
16252a38012Sejakowatz 		{
163dfb2ad61Sbeveloper 			const producer_format_proposal_request *request = static_cast<const producer_format_proposal_request *>(data);
1648c6a6096Sbeveloper 			producer_format_proposal_reply reply;
1658c6a6096Sbeveloper 			reply.format = request->format;
1668c6a6096Sbeveloper 			rv = FormatProposal(request->output, &reply.format);
1678c6a6096Sbeveloper 			request->SendReply(rv, &reply, sizeof(reply));
16852a38012Sejakowatz 			return B_OK;
16952a38012Sejakowatz 		}
17052a38012Sejakowatz 
17152a38012Sejakowatz 		case PRODUCER_PREPARE_TO_CONNECT:
17252a38012Sejakowatz 		{
173dfb2ad61Sbeveloper 			const producer_prepare_to_connect_request *request = static_cast<const producer_prepare_to_connect_request *>(data);
1748c6a6096Sbeveloper 			producer_prepare_to_connect_reply reply;
1758c6a6096Sbeveloper 			reply.format = request->format;
1768c6a6096Sbeveloper 			memcpy(reply.name, request->name, B_MEDIA_NAME_LENGTH);
1778c6a6096Sbeveloper 			rv = PrepareToConnect(request->source, request->destination, &reply.format, &reply.out_source, reply.name);
1788c6a6096Sbeveloper 			request->SendReply(rv, &reply, sizeof(reply));
17952a38012Sejakowatz 			return B_OK;
18052a38012Sejakowatz 		}
18152a38012Sejakowatz 
18252a38012Sejakowatz 		case PRODUCER_CONNECT:
18352a38012Sejakowatz 		{
184dfb2ad61Sbeveloper 			const producer_connect_request *request = static_cast<const producer_connect_request *>(data);
1858c6a6096Sbeveloper 			producer_connect_reply reply;
1868c6a6096Sbeveloper 			memcpy(reply.name, request->name, B_MEDIA_NAME_LENGTH);
1878c6a6096Sbeveloper 			Connect(request->error, request->source, request->destination, request->format, reply.name);
1888c6a6096Sbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
18952a38012Sejakowatz 			return B_OK;
19052a38012Sejakowatz 		}
19152a38012Sejakowatz 
19252a38012Sejakowatz 		case PRODUCER_DISCONNECT:
19352a38012Sejakowatz 		{
194dfb2ad61Sbeveloper 			const producer_disconnect_request *request = static_cast<const producer_disconnect_request *>(data);
1959e9417d2Sbeveloper 			producer_disconnect_reply reply;
1968c6a6096Sbeveloper 			Disconnect(request->source, request->destination);
1979e9417d2Sbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
19852a38012Sejakowatz 			return B_OK;
19952a38012Sejakowatz 		}
20052a38012Sejakowatz 
20152a38012Sejakowatz 		case PRODUCER_GET_INITIAL_LATENCY:
20252a38012Sejakowatz 		{
203dfb2ad61Sbeveloper 			const producer_get_initial_latency_request *request = static_cast<const producer_get_initial_latency_request *>(data);
204dfb2ad61Sbeveloper 			producer_get_initial_latency_reply reply;
20552a38012Sejakowatz 			reply.initial_latency = fInitialLatency;
20652a38012Sejakowatz 			reply.flags = fInitialFlags;
207dfb2ad61Sbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
20852a38012Sejakowatz 			return B_OK;
20952a38012Sejakowatz 		}
21052a38012Sejakowatz 
21152a38012Sejakowatz 		case PRODUCER_SET_PLAY_RATE:
21252a38012Sejakowatz 		{
213dfb2ad61Sbeveloper 			const producer_set_play_rate_request *request = static_cast<const producer_set_play_rate_request *>(data);
214dfb2ad61Sbeveloper 			producer_set_play_rate_reply reply;
215dfb2ad61Sbeveloper 			rv = SetPlayRate(request->numer, request->denom);
216dfb2ad61Sbeveloper 			request->SendReply(rv, &reply, sizeof(reply));
21752a38012Sejakowatz 			return B_OK;
21852a38012Sejakowatz 		}
21952a38012Sejakowatz 
22052a38012Sejakowatz 		case PRODUCER_GET_LATENCY:
22152a38012Sejakowatz 		{
222dfb2ad61Sbeveloper 			const producer_get_latency_request *request = static_cast<const producer_get_latency_request *>(data);
223dfb2ad61Sbeveloper 			producer_get_latency_reply reply;
224dfb2ad61Sbeveloper 			rv = GetLatency(&reply.latency);
225dfb2ad61Sbeveloper 			request->SendReply(rv, &reply, sizeof(reply));
22652a38012Sejakowatz 			return B_OK;
22752a38012Sejakowatz 		}
22852a38012Sejakowatz 
22952a38012Sejakowatz 		case PRODUCER_GET_NEXT_OUTPUT:
23052a38012Sejakowatz 		{
231dfb2ad61Sbeveloper 			const producer_get_next_output_request *request = static_cast<const producer_get_next_output_request *>(data);
2323620737cSbeveloper 			producer_get_next_output_reply reply;
2338c6a6096Sbeveloper 			reply.cookie = request->cookie;
2343620737cSbeveloper 			rv = GetNextOutput(&reply.cookie, &reply.output);
2353620737cSbeveloper 			request->SendReply(rv, &reply, sizeof(reply));
23652a38012Sejakowatz 			return B_OK;
23752a38012Sejakowatz 		}
23852a38012Sejakowatz 
23952a38012Sejakowatz 		case PRODUCER_DISPOSE_OUTPUT_COOKIE:
24052a38012Sejakowatz 		{
241dfb2ad61Sbeveloper 			const producer_dispose_output_cookie_request *request = static_cast<const producer_dispose_output_cookie_request *>(data);
2423620737cSbeveloper 			producer_dispose_output_cookie_reply reply;
2438c6a6096Sbeveloper 			DisposeOutputCookie(request->cookie);
2443620737cSbeveloper 			request->SendReply(B_OK, &reply, sizeof(reply));
24552a38012Sejakowatz 			return B_OK;
24652a38012Sejakowatz 		}
24752a38012Sejakowatz 
24852a38012Sejakowatz 		case PRODUCER_SET_BUFFER_GROUP:
24952a38012Sejakowatz 		{
250dfb2ad61Sbeveloper 			const producer_set_buffer_group_command *command = static_cast<const producer_set_buffer_group_command *>(data);
251dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
25252a38012Sejakowatz 			BBufferGroup *group;
253dfb2ad61Sbeveloper 			group = command->buffer_count != 0 ? new BBufferGroup(command->buffer_count, command->buffers) : NULL;
254dfb2ad61Sbeveloper 			rv = SetBufferGroup(command->source, group);
255dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
25652a38012Sejakowatz 				return B_OK;
257dfb2ad61Sbeveloper 			replycommand.info.what = media_request_info::B_SET_OUTPUT_BUFFERS_FOR;
258dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
259dfb2ad61Sbeveloper 			replycommand.info.status = rv;
260dfb2ad61Sbeveloper 			replycommand.info.cookie = (int32)group;
261dfb2ad61Sbeveloper 			replycommand.info.user_data = command->user_data;
262dfb2ad61Sbeveloper 			replycommand.info.source = command->source;
263dfb2ad61Sbeveloper 			replycommand.info.destination = command->destination;
264dfb2ad61Sbeveloper 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED, &replycommand, sizeof(replycommand));
26552a38012Sejakowatz 			return B_OK;
26652a38012Sejakowatz 		}
26752a38012Sejakowatz 
26852a38012Sejakowatz 		case PRODUCER_FORMAT_CHANGE_REQUESTED:
26952a38012Sejakowatz 		{
270dfb2ad61Sbeveloper 			const producer_format_change_requested_command *command = static_cast<const producer_format_change_requested_command *>(data);
271dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
272dfb2ad61Sbeveloper 			replycommand.info.format = command->format;
273dfb2ad61Sbeveloper 			rv = FormatChangeRequested(command->source, command->destination, &replycommand.info.format, NULL);
274dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
27552a38012Sejakowatz 				return B_OK;
276dfb2ad61Sbeveloper 			replycommand.info.what = media_request_info::B_REQUEST_FORMAT_CHANGE;
277dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
278dfb2ad61Sbeveloper 			replycommand.info.status = rv;
279dfb2ad61Sbeveloper 			//replycommand.info.cookie
280dfb2ad61Sbeveloper 			replycommand.info.user_data = command->user_data;
281dfb2ad61Sbeveloper 			replycommand.info.source = command->source;
282dfb2ad61Sbeveloper 			replycommand.info.destination = command->destination;
283dfb2ad61Sbeveloper 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED, &replycommand, sizeof(replycommand));
28452a38012Sejakowatz 			return B_OK;
28552a38012Sejakowatz 		}
28652a38012Sejakowatz 
28752a38012Sejakowatz 		case PRODUCER_VIDEO_CLIPPING_CHANGED:
28852a38012Sejakowatz 		{
289dfb2ad61Sbeveloper 			const producer_video_clipping_changed_command *command = static_cast<const producer_video_clipping_changed_command *>(data);
290dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
291dfb2ad61Sbeveloper 			rv = VideoClippingChanged(command->source, command->short_count, (int16 *)command->shorts, command->display, NULL);
292dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
29352a38012Sejakowatz 				return B_OK;
294dfb2ad61Sbeveloper 			replycommand.info.what = media_request_info::B_SET_VIDEO_CLIPPING_FOR;
295dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
296dfb2ad61Sbeveloper 			replycommand.info.status = rv;
297dfb2ad61Sbeveloper 			//replycommand.info.cookie
298dfb2ad61Sbeveloper 			replycommand.info.user_data = command->user_data;
299dfb2ad61Sbeveloper 			replycommand.info.source = command->source;
300dfb2ad61Sbeveloper 			replycommand.info.destination = command->destination;
301dfb2ad61Sbeveloper 			replycommand.info.format.type = B_MEDIA_RAW_VIDEO;
302dfb2ad61Sbeveloper 			replycommand.info.format.u.raw_video.display = command->display;
303dfb2ad61Sbeveloper 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED, &replycommand, sizeof(replycommand));
30452a38012Sejakowatz 			return B_OK;
30552a38012Sejakowatz 		}
30652a38012Sejakowatz 
30752a38012Sejakowatz 		case PRODUCER_ADDITIONAL_BUFFER_REQUESTED:
30852a38012Sejakowatz 		{
309dfb2ad61Sbeveloper 			const producer_additional_buffer_requested_command *command = static_cast<const producer_additional_buffer_requested_command *>(data);
310dfb2ad61Sbeveloper 			AdditionalBufferRequested(command->source, command->prev_buffer, command->prev_time, command->has_seek_tag ? &command->prev_tag : NULL);
31152a38012Sejakowatz 			return B_OK;
31252a38012Sejakowatz 		}
31352a38012Sejakowatz 
31452a38012Sejakowatz 		case PRODUCER_LATENCY_CHANGED:
31552a38012Sejakowatz 		{
316dfb2ad61Sbeveloper 			const producer_latency_changed_command *command = static_cast<const producer_latency_changed_command *>(data);
317dfb2ad61Sbeveloper 			LatencyChanged(command->source, command->destination, command->latency, command->flags);
31852a38012Sejakowatz 			return B_OK;
31952a38012Sejakowatz 		}
32052a38012Sejakowatz 
32152a38012Sejakowatz 		case PRODUCER_LATE_NOTICE_RECEIVED:
32252a38012Sejakowatz 		{
323dfb2ad61Sbeveloper 			const producer_late_notice_received_command *command = static_cast<const producer_late_notice_received_command *>(data);
324dfb2ad61Sbeveloper 			LateNoticeReceived(command->source, command->how_much, command->performance_time);
32552a38012Sejakowatz 			return B_OK;
32652a38012Sejakowatz 		}
32752a38012Sejakowatz 
32852a38012Sejakowatz 		case PRODUCER_ENABLE_OUTPUT:
32952a38012Sejakowatz 		{
330dfb2ad61Sbeveloper 			const producer_enable_output_command *command = static_cast<const producer_enable_output_command *>(data);
331dfb2ad61Sbeveloper 			node_request_completed_command replycommand;
332dfb2ad61Sbeveloper 			EnableOutput(command->source, command->enabled, NULL);
333dfb2ad61Sbeveloper 			if (command->destination == media_destination::null)
33452a38012Sejakowatz 				return B_OK;
335dfb2ad61Sbeveloper 			replycommand.info.what = media_request_info::B_SET_OUTPUT_ENABLED;
336dfb2ad61Sbeveloper 			replycommand.info.change_tag = command->change_tag;
337dfb2ad61Sbeveloper 			replycommand.info.status = B_OK;
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
343dfb2ad61Sbeveloper 			SendToPort(command->destination.port, NODE_REQUEST_COMPLETED, &replycommand, sizeof(replycommand));
34452a38012Sejakowatz 			return B_OK;
34552a38012Sejakowatz 		}
34652a38012Sejakowatz 
34752a38012Sejakowatz 	};
34852a38012Sejakowatz 	return B_ERROR;
34952a38012Sejakowatz }
35052a38012Sejakowatz 
35152a38012Sejakowatz 
35252a38012Sejakowatz void
35352a38012Sejakowatz BBufferProducer::AdditionalBufferRequested(const media_source &source,
35452a38012Sejakowatz 										   media_buffer_id prev_buffer,
35552a38012Sejakowatz 										   bigtime_t prev_time,
35652a38012Sejakowatz 										   const media_seek_tag *prev_tag)
35752a38012Sejakowatz {
35852a38012Sejakowatz 	CALLED();
35952a38012Sejakowatz 	// may be implemented by derived classes
36052a38012Sejakowatz }
36152a38012Sejakowatz 
36252a38012Sejakowatz 
36352a38012Sejakowatz void
36452a38012Sejakowatz BBufferProducer::LatencyChanged(const media_source &source,
36552a38012Sejakowatz 								const media_destination &destination,
36652a38012Sejakowatz 								bigtime_t new_latency,
36752a38012Sejakowatz 								uint32 flags)
36852a38012Sejakowatz {
36952a38012Sejakowatz 	CALLED();
37052a38012Sejakowatz 	// may be implemented by derived classes
37152a38012Sejakowatz }
37252a38012Sejakowatz 
37352a38012Sejakowatz 
37452a38012Sejakowatz status_t
37552a38012Sejakowatz BBufferProducer::SendBuffer(BBuffer *buffer,
37652a38012Sejakowatz 							const media_destination &destination)
37752a38012Sejakowatz {
37852a38012Sejakowatz 	CALLED();
37952a38012Sejakowatz 	if (destination == media_destination::null)
38052a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
38152a38012Sejakowatz 	if (buffer == NULL)
38252a38012Sejakowatz 		return B_BAD_VALUE;
38352a38012Sejakowatz 
384dfb2ad61Sbeveloper 	consumer_buffer_received_command command;
385dfb2ad61Sbeveloper 	command.buffer = buffer->ID();
386dfb2ad61Sbeveloper 	command.header = *(buffer->Header());
387dfb2ad61Sbeveloper 	command.header.buffer = command.buffer; // buffer->ID();
388dfb2ad61Sbeveloper 	command.header.destination = destination.id;
389*60f15390Sbeveloper 	command.header.start_time += fDelay; // time compensation as set by BMediaRoster::SetProducerRunModeDelay()
39052a38012Sejakowatz 
391dfb2ad61Sbeveloper 	return SendToPort(destination.port, CONSUMER_BUFFER_RECEIVED, &command, sizeof(command));
39252a38012Sejakowatz }
39352a38012Sejakowatz 
39452a38012Sejakowatz 
39552a38012Sejakowatz status_t
39652a38012Sejakowatz BBufferProducer::SendDataStatus(int32 status,
39752a38012Sejakowatz 								const media_destination &destination,
39852a38012Sejakowatz 								bigtime_t at_time)
39952a38012Sejakowatz {
40052a38012Sejakowatz 	CALLED();
40140f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(destination))
40252a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
40352a38012Sejakowatz 
404dfb2ad61Sbeveloper 	consumer_producer_data_status_command command;
405dfb2ad61Sbeveloper 	command.for_whom = destination;
406dfb2ad61Sbeveloper 	command.status = status;
407dfb2ad61Sbeveloper 	command.at_performance_time = at_time;
40852a38012Sejakowatz 
409dfb2ad61Sbeveloper 	return SendToPort(destination.port, CONSUMER_PRODUCER_DATA_STATUS, &command, sizeof(command));
41052a38012Sejakowatz }
41152a38012Sejakowatz 
41252a38012Sejakowatz 
41352a38012Sejakowatz status_t
41452a38012Sejakowatz BBufferProducer::ProposeFormatChange(media_format *format,
41552a38012Sejakowatz 									 const media_destination &for_destination)
41652a38012Sejakowatz {
41752a38012Sejakowatz 	CALLED();
41840f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(for_destination))
41952a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
42052a38012Sejakowatz 
4218c6a6096Sbeveloper 	consumer_accept_format_request request;
4228c6a6096Sbeveloper 	consumer_accept_format_reply reply;
42352a38012Sejakowatz 	status_t rv;
42452a38012Sejakowatz 
4258c6a6096Sbeveloper 	request.dest = for_destination;
4268c6a6096Sbeveloper 	request.format = *format;
4278c6a6096Sbeveloper 	rv = QueryPort(for_destination.port, CONSUMER_ACCEPT_FORMAT, &request, sizeof(request), &reply, sizeof(reply));
4288c6a6096Sbeveloper 	if (rv != B_OK)
42952a38012Sejakowatz 		return rv;
43052a38012Sejakowatz 
43152a38012Sejakowatz 	*format = reply.format;
4328c6a6096Sbeveloper 	return B_OK;
43352a38012Sejakowatz }
43452a38012Sejakowatz 
43552a38012Sejakowatz 
43652a38012Sejakowatz status_t
43752a38012Sejakowatz BBufferProducer::ChangeFormat(const media_source &for_source,
43852a38012Sejakowatz 							  const media_destination &for_destination,
43952a38012Sejakowatz 							  media_format *format)
44052a38012Sejakowatz {
44152a38012Sejakowatz 	CALLED();
44240f36b03Sbeveloper 	if (IS_INVALID_SOURCE(for_source))
44352a38012Sejakowatz 		return B_MEDIA_BAD_SOURCE;
44440f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(for_destination))
44552a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
44652a38012Sejakowatz 
447dfb2ad61Sbeveloper 	consumer_format_changed_request request;
448dfb2ad61Sbeveloper 	consumer_format_changed_reply reply;
44952a38012Sejakowatz 
4508c6a6096Sbeveloper 	request.producer = for_source;
4518c6a6096Sbeveloper 	request.consumer = for_destination;
4528c6a6096Sbeveloper 	request.format = *format;
45352a38012Sejakowatz 
454dfb2ad61Sbeveloper 	// we use a request/reply to make this synchronous
455dfb2ad61Sbeveloper 	return QueryPort(for_destination.port, CONSUMER_FORMAT_CHANGED, &request, sizeof(request), &reply, sizeof(reply));
45652a38012Sejakowatz }
45752a38012Sejakowatz 
45852a38012Sejakowatz 
45952a38012Sejakowatz status_t
46052a38012Sejakowatz BBufferProducer::FindLatencyFor(const media_destination &for_destination,
46152a38012Sejakowatz 								bigtime_t *out_latency,
46252a38012Sejakowatz 								media_node_id *out_timesource)
46352a38012Sejakowatz {
46452a38012Sejakowatz 	CALLED();
46540f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(for_destination))
46652a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
46752a38012Sejakowatz 
46852a38012Sejakowatz 	status_t rv;
469dfb2ad61Sbeveloper 	consumer_get_latency_for_request request;
470dfb2ad61Sbeveloper 	consumer_get_latency_for_reply reply;
47152a38012Sejakowatz 
4728c6a6096Sbeveloper 	request.for_whom = for_destination;
47352a38012Sejakowatz 
474dfb2ad61Sbeveloper 	rv = QueryPort(for_destination.port, CONSUMER_GET_LATENCY_FOR, &request, sizeof(request), &reply, sizeof(reply));
475dfb2ad61Sbeveloper 	if (rv != B_OK)
47652a38012Sejakowatz 		return rv;
47752a38012Sejakowatz 
47852a38012Sejakowatz 	*out_latency = reply.latency;
47952a38012Sejakowatz 	*out_timesource = reply.timesource;
480dfb2ad61Sbeveloper 	return rv;
48152a38012Sejakowatz }
48252a38012Sejakowatz 
48352a38012Sejakowatz 
48452a38012Sejakowatz status_t
48552a38012Sejakowatz BBufferProducer::FindSeekTag(const media_destination &for_destination,
48652a38012Sejakowatz 							 bigtime_t in_target_time,
48752a38012Sejakowatz 							 media_seek_tag *out_tag,
48852a38012Sejakowatz 							 bigtime_t *out_tagged_time,
48952a38012Sejakowatz 							 uint32 *out_flags,
49052a38012Sejakowatz 							 uint32 in_flags)
49152a38012Sejakowatz {
49252a38012Sejakowatz 	CALLED();
49340f36b03Sbeveloper 	if (IS_INVALID_DESTINATION(for_destination))
49452a38012Sejakowatz 		return B_MEDIA_BAD_DESTINATION;
49552a38012Sejakowatz 
49652a38012Sejakowatz 	status_t rv;
497dfb2ad61Sbeveloper 	consumer_seek_tag_requested_request request;
498dfb2ad61Sbeveloper 	consumer_seek_tag_requested_reply reply;
49952a38012Sejakowatz 
5008c6a6096Sbeveloper 	request.destination = for_destination;
5018c6a6096Sbeveloper 	request.target_time = in_target_time;
5028c6a6096Sbeveloper 	request.flags = in_flags;
50352a38012Sejakowatz 
504dfb2ad61Sbeveloper 	rv = QueryPort(for_destination.port, CONSUMER_SEEK_TAG_REQUESTED, &request, sizeof(request), &reply, sizeof(reply));
505dfb2ad61Sbeveloper 	if (rv != B_OK)
50652a38012Sejakowatz 		return rv;
50752a38012Sejakowatz 
50852a38012Sejakowatz 	*out_tag = reply.seek_tag;
50952a38012Sejakowatz 	*out_tagged_time = reply.tagged_time;
51052a38012Sejakowatz 	*out_flags = reply.flags;
511dfb2ad61Sbeveloper 	return rv;
51252a38012Sejakowatz }
51352a38012Sejakowatz 
51452a38012Sejakowatz 
51552a38012Sejakowatz void
51652a38012Sejakowatz BBufferProducer::SetInitialLatency(bigtime_t inInitialLatency,
51752a38012Sejakowatz 								   uint32 flags)
51852a38012Sejakowatz {
51952a38012Sejakowatz 	fInitialLatency = inInitialLatency;
52052a38012Sejakowatz 	fInitialFlags = flags;
52152a38012Sejakowatz }
52252a38012Sejakowatz 
52352a38012Sejakowatz /*************************************************************
52452a38012Sejakowatz  * private BBufferProducer
52552a38012Sejakowatz  *************************************************************/
52652a38012Sejakowatz 
52752a38012Sejakowatz /*
52852a38012Sejakowatz private unimplemented
52952a38012Sejakowatz BBufferProducer::BBufferProducer()
53052a38012Sejakowatz BBufferProducer::BBufferProducer(const BBufferProducer &clone)
53152a38012Sejakowatz BBufferProducer & BBufferProducer::operator=(const BBufferProducer &clone)
53252a38012Sejakowatz */
53352a38012Sejakowatz 
53452a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_0(void *) { return B_ERROR; }
53552a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_1(void *) { return B_ERROR; }
53652a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_2(void *) { return B_ERROR; }
53752a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_3(void *) { return B_ERROR; }
53852a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_4(void *) { return B_ERROR; }
53952a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_5(void *) { return B_ERROR; }
54052a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_6(void *) { return B_ERROR; }
54152a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_7(void *) { return B_ERROR; }
54252a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_8(void *) { return B_ERROR; }
54352a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_9(void *) { return B_ERROR; }
54452a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_10(void *) { return B_ERROR; }
54552a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_11(void *) { return B_ERROR; }
54652a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_12(void *) { return B_ERROR; }
54752a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_13(void *) { return B_ERROR; }
54852a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_14(void *) { return B_ERROR; }
54952a38012Sejakowatz status_t BBufferProducer::_Reserved_BufferProducer_15(void *) { return B_ERROR; }
55052a38012Sejakowatz 
55152a38012Sejakowatz 
55252a38012Sejakowatz status_t
55363ffaa3eSbeveloper BBufferProducer::clip_shorts_to_region(const int16 *data,
55452a38012Sejakowatz 									   int count,
55552a38012Sejakowatz 									   BRegion *output)
55652a38012Sejakowatz {
55752a38012Sejakowatz 	UNIMPLEMENTED();
55852a38012Sejakowatz 
55952a38012Sejakowatz 	return B_ERROR;
56052a38012Sejakowatz }
56152a38012Sejakowatz 
56252a38012Sejakowatz 
56352a38012Sejakowatz status_t
56452a38012Sejakowatz BBufferProducer::clip_region_to_shorts(const BRegion *input,
56563ffaa3eSbeveloper 									   int16 *data,
56652a38012Sejakowatz 									   int max_count,
56752a38012Sejakowatz 									   int *out_count)
56852a38012Sejakowatz {
56952a38012Sejakowatz 	UNIMPLEMENTED();
57052a38012Sejakowatz 
57152a38012Sejakowatz 	return B_ERROR;
57252a38012Sejakowatz }
57352a38012Sejakowatz 
574