Files
haiku-beta6/src/kits/media/BufferProducer.cpp
T
Ingo Weinhold 0a483e7221 Fixed includes.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@86 a95241bf-73f2-0310-859d-f6bbb57e9c96
2002-07-11 19:54:41 +00:00

572 lines
16 KiB
C++

/***********************************************************************
* AUTHOR: Marcus Overhagen
* FILE: BufferProducer.cpp
* DESCR:
***********************************************************************/
#include <BufferProducer.h>
#include <BufferGroup.h>
#include <Buffer.h>
#include "PortPool.h"
#include "debug.h"
#include "ServerInterface.h"
/*************************************************************
* protected BBufferProducer
*************************************************************/
BBufferProducer::~BBufferProducer()
{
CALLED();
}
/*************************************************************
* public BBufferProducer
*************************************************************/
/* static */ status_t
BBufferProducer::ClipDataToRegion(int32 format,
int32 size,
const void *data,
BRegion *region)
{
CALLED();
if (format != B_CLIP_SHORT_RUNS)
return B_MEDIA_BAD_CLIP_FORMAT;
return clip_shorts_to_region((const int16 *)data, size / sizeof(int16), region);
}
media_type
BBufferProducer::ProducerType()
{
CALLED();
return fProducerType;
}
/*************************************************************
* protected BBufferProducer
*************************************************************/
/* explicit */
BBufferProducer::BBufferProducer(media_type producer_type) :
BMediaNode("called by BBufferProducer"),
fProducerType(producer_type),
fInitialLatency(0),
fInitialFlags(0)
{
CALLED();
AddNodeKind(B_BUFFER_PRODUCER);
}
status_t
BBufferProducer::VideoClippingChanged(const media_source &for_source,
int16 num_shorts,
int16 *clip_data,
const media_video_display_info &display,
int32 *_deprecated_)
{
CALLED();
// may be implemented by derived classes
return B_ERROR;
}
status_t
BBufferProducer::GetLatency(bigtime_t *out_lantency)
{
UNIMPLEMENTED();
// XXX The default implementation of GetLatency() finds the maximum
// latency of your currently-available outputs by iterating over
// them, and returns that value in outLatency
return B_ERROR;
}
status_t
BBufferProducer::SetPlayRate(int32 numer,
int32 denom)
{
CALLED();
// may be implemented by derived classes
return B_ERROR;
}
status_t
BBufferProducer::HandleMessage(int32 message,
const void *rawdata,
size_t size)
{
CALLED();
switch (message) {
case PRODUCER_FORMAT_SUGGESTION_REQUESTED:
{
const xfer_producer_format_suggestion_requested *data = (const xfer_producer_format_suggestion_requested *)rawdata;
xfer_producer_format_suggestion_requested_reply reply;
reply.result = FormatSuggestionRequested(data->type, data->quality, &reply.format);
write_port(data->reply_port, 0, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_FORMAT_PROPOSAL:
{
const xfer_producer_format_proposal *data = (const xfer_producer_format_proposal *)rawdata;
xfer_producer_format_proposal_reply reply;
reply.result = FormatProposal(data->output, (media_format *)&data->format);
write_port(data->reply_port, 0, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_PREPARE_TO_CONNECT:
{
const xfer_producer_prepare_to_connect *data = (const xfer_producer_prepare_to_connect *)rawdata;
xfer_producer_prepare_to_connect_reply reply;
reply.format = data->format;
reply.name[0] = 0;
reply.result = PrepareToConnect(data->source, data->destination, &reply.format, &reply.out_source, reply.name);
write_port(data->reply_port, 0, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_CONNECT:
{
const xfer_producer_connect *data = (const xfer_producer_connect *)rawdata;
xfer_producer_connect_reply reply;
memcpy(reply.name, data->name, B_MEDIA_NAME_LENGTH);
Connect(data->error, data->source, data->destination, data->format, reply.name);
write_port(data->reply_port, 0, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_DISCONNECT:
{
const xfer_producer_disconnect *data = (const xfer_producer_disconnect *)rawdata;
Disconnect(data->source, data->destination);
return B_OK;
}
case PRODUCER_GET_INITIAL_LATENCY:
{
const xfer_producer_get_initial_latency *data = (const xfer_producer_get_initial_latency *)rawdata;
xfer_producer_get_initial_latency_reply reply;
reply.initial_latency = fInitialLatency;
reply.flags = fInitialFlags;
write_port(data->reply_port, 0, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_SET_PLAY_RATE:
{
const xfer_producer_set_play_rate *data = (const xfer_producer_set_play_rate *)rawdata;
xfer_producer_set_play_rate_reply reply;
reply.result = SetPlayRate(data->numer, data->denom);
write_port(data->reply_port, 0, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_GET_LATENCY:
{
const xfer_producer_get_latency *data = (const xfer_producer_get_latency *)rawdata;
xfer_producer_get_latency_reply reply;
reply.result = GetLatency(&reply.latency);
write_port(data->reply_port, 0, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_GET_NEXT_OUTPUT:
{
const xfer_producer_get_next_output *data = (const xfer_producer_get_next_output *)rawdata;
xfer_producer_get_next_output_reply reply;
reply.cookie = data->cookie;
reply.result = GetNextOutput(&reply.cookie, &reply.output);
write_port(data->reply_port, 0, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_DISPOSE_OUTPUT_COOKIE:
{
const xfer_producer_dispose_output_cookie *data = (const xfer_producer_dispose_output_cookie *)rawdata;
DisposeOutputCookie(data->cookie);
return B_OK;
}
case PRODUCER_SET_BUFFER_GROUP:
{
const xfer_producer_set_buffer_group *data = (const xfer_producer_set_buffer_group *)rawdata;
xfer_node_request_completed reply;
BBufferGroup *group;
status_t rv;
group = data->buffer_count != 0 ? new BBufferGroup(data->buffer_count, data->buffers) : NULL;
rv = SetBufferGroup(data->source, group);
if (data->destination == media_destination::null)
return B_OK;
reply.info.what = media_request_info::B_SET_OUTPUT_BUFFERS_FOR;
reply.info.change_tag = data->change_tag;
reply.info.status = rv;
reply.info.cookie = (int32)group;
reply.info.user_data = data->user_data;
reply.info.source = data->source;
reply.info.destination = data->destination;
write_port(data->destination.port, NODE_REQUEST_COMPLETED, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_FORMAT_CHANGE_REQUESTED:
{
const xfer_producer_format_change_requested *data = (const xfer_producer_format_change_requested *)rawdata;
xfer_node_request_completed reply;
status_t rv;
reply.info.format = data->format;
rv = FormatChangeRequested(data->source, data->destination, &reply.info.format, NULL);
if (data->destination == media_destination::null)
return B_OK;
reply.info.what = media_request_info::B_REQUEST_FORMAT_CHANGE;
reply.info.change_tag = data->change_tag;
reply.info.status = rv;
//reply.info.cookie
reply.info.user_data = data->user_data;
reply.info.source = data->source;
reply.info.destination = data->destination;
write_port(data->destination.port, NODE_REQUEST_COMPLETED, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_VIDEO_CLIPPING_CHANGED:
{
const xfer_producer_video_clipping_changed *data = (const xfer_producer_video_clipping_changed *)rawdata;
xfer_node_request_completed reply;
status_t rv;
rv = VideoClippingChanged(data->source, data->short_count, (int16 *)data->shorts, data->display, NULL);
if (data->destination == media_destination::null)
return B_OK;
reply.info.what = media_request_info::B_SET_VIDEO_CLIPPING_FOR;
reply.info.change_tag = data->change_tag;
reply.info.status = rv;
//reply.info.cookie
reply.info.user_data = data->user_data;
reply.info.source = data->source;
reply.info.destination = data->destination;
reply.info.format.type = B_MEDIA_RAW_VIDEO;
reply.info.format.u.raw_video.display = data->display;
write_port(data->destination.port, NODE_REQUEST_COMPLETED, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_ADDITIONAL_BUFFER_REQUESTED:
{
const xfer_producer_additional_buffer_requested *data = (const xfer_producer_additional_buffer_requested *)rawdata;
AdditionalBufferRequested(data->source, data->prev_buffer, data->prev_time, data->has_seek_tag ? &data->prev_tag : NULL);
return B_OK;
}
case PRODUCER_LATENCY_CHANGED:
{
const xfer_producer_latency_changed *data = (const xfer_producer_latency_changed *)rawdata;
LatencyChanged(data->source, data->destination, data->latency, data->flags);
return B_OK;
}
case PRODUCER_LATE_NOTICE_RECEIVED:
{
const xfer_producer_late_notice_received *data = (const xfer_producer_late_notice_received *)rawdata;
LateNoticeReceived(data->source, data->how_much, data->performance_time);
return B_OK;
}
case PRODUCER_ENABLE_OUTPUT:
{
const xfer_producer_enable_output *data = (const xfer_producer_enable_output *)rawdata;
xfer_node_request_completed reply;
EnableOutput(data->source, data->enabled, NULL);
if (data->destination == media_destination::null)
return B_OK;
reply.info.what = media_request_info::B_SET_OUTPUT_ENABLED;
reply.info.change_tag = data->change_tag;
reply.info.status = B_OK;
//reply.info.cookie
reply.info.user_data = data->user_data;
reply.info.source = data->source;
reply.info.destination = data->destination;
//reply.info.format
write_port(data->destination.port, NODE_REQUEST_COMPLETED, &reply, sizeof(reply));
return B_OK;
}
};
return B_ERROR;
}
void
BBufferProducer::AdditionalBufferRequested(const media_source &source,
media_buffer_id prev_buffer,
bigtime_t prev_time,
const media_seek_tag *prev_tag)
{
CALLED();
// may be implemented by derived classes
}
void
BBufferProducer::LatencyChanged(const media_source &source,
const media_destination &destination,
bigtime_t new_latency,
uint32 flags)
{
CALLED();
// may be implemented by derived classes
}
status_t
BBufferProducer::SendBuffer(BBuffer *buffer,
const media_destination &destination)
{
CALLED();
if (destination == media_destination::null)
return B_MEDIA_BAD_DESTINATION;
if (buffer == NULL)
return B_BAD_VALUE;
xfer_consumer_buffer_received data;
data.buffer = buffer->ID();
data.header = *(buffer->Header());
data.header.buffer = data.buffer;
data.header.destination = destination.id;
return write_port(destination.port, CONSUMER_BUFFER_RECEIVED, &data, sizeof(data));
}
status_t
BBufferProducer::SendDataStatus(int32 status,
const media_destination &destination,
bigtime_t at_time)
{
CALLED();
if (destination == media_destination::null)
return B_MEDIA_BAD_DESTINATION;
xfer_consumer_producer_data_status data;
data.for_whom = destination;
data.status = status;
data.at_performance_time = at_time;
return write_port(destination.port, CONSUMER_PRODUCER_DATA_STATUS, &data, sizeof(data));
}
status_t
BBufferProducer::ProposeFormatChange(media_format *format,
const media_destination &for_destination)
{
CALLED();
if (for_destination == media_destination::null)
return B_MEDIA_BAD_DESTINATION;
status_t rv;
int32 code;
xfer_consumer_accept_format data;
xfer_consumer_accept_format_reply reply;
data.dest = for_destination;
data.format = *format;
data.reply_port = _PortPool->GetPort();
rv = write_port(for_destination.port, CONSUMER_ACCEPT_FORMAT, &data, sizeof(data));
if (rv != B_OK) {
_PortPool->PutPort(data.reply_port);
return rv;
}
rv = read_port(data.reply_port, &code, &reply, sizeof(reply));
_PortPool->PutPort(data.reply_port);
if (rv < B_OK)
return rv;
*format = reply.format;
return reply.result;
}
status_t
BBufferProducer::ChangeFormat(const media_source &for_source,
const media_destination &for_destination,
media_format *format)
{
CALLED();
if (for_source == media_source::null)
return B_MEDIA_BAD_SOURCE;
if (for_destination == media_destination::null)
return B_MEDIA_BAD_DESTINATION;
status_t rv;
int32 code;
xfer_consumer_format_changed data;
xfer_consumer_format_changed_reply reply;
data.producer = for_source;
data.consumer = for_destination;
data.format = *format;
data.reply_port = _PortPool->GetPort();
rv = write_port(for_destination.port, CONSUMER_FORMAT_CHANGED, &data, sizeof(data));
if (rv != B_OK) {
_PortPool->PutPort(data.reply_port);
return rv;
}
rv = read_port(data.reply_port, &code, &reply, sizeof(reply));
_PortPool->PutPort(data.reply_port);
if (rv < B_OK)
return rv;
return reply.result;
}
status_t
BBufferProducer::FindLatencyFor(const media_destination &for_destination,
bigtime_t *out_latency,
media_node_id *out_timesource)
{
CALLED();
if (for_destination == media_destination::null)
return B_MEDIA_BAD_DESTINATION;
status_t rv;
int32 code;
xfer_consumer_get_latency_for data;
xfer_consumer_get_latency_for_reply reply;
data.for_whom = for_destination;
data.reply_port = _PortPool->GetPort();
rv = write_port(for_destination.port, CONSUMER_GET_LATENCY_FOR, &data, sizeof(data));
if (rv != B_OK) {
_PortPool->PutPort(data.reply_port);
return rv;
}
rv = read_port(data.reply_port, &code, &reply, sizeof(reply));
_PortPool->PutPort(data.reply_port);
if (rv < B_OK)
return rv;
*out_latency = reply.latency;
*out_timesource = reply.timesource;
return reply.result;
}
status_t
BBufferProducer::FindSeekTag(const media_destination &for_destination,
bigtime_t in_target_time,
media_seek_tag *out_tag,
bigtime_t *out_tagged_time,
uint32 *out_flags,
uint32 in_flags)
{
CALLED();
if (for_destination == media_destination::null)
return B_MEDIA_BAD_DESTINATION;
status_t rv;
int32 code;
xfer_consumer_seek_tag_requested data;
xfer_consumer_seek_tag_requested_reply reply;
data.destination = for_destination;
data.target_time = in_target_time;
data.flags = in_flags;
data.reply_port = _PortPool->GetPort();
rv = write_port(for_destination.port, CONSUMER_SEEK_TAG_REQUESTED, &data, sizeof(data));
if (rv != B_OK) {
_PortPool->PutPort(data.reply_port);
return rv;
}
rv = read_port(data.reply_port, &code, &reply, sizeof(reply));
_PortPool->PutPort(data.reply_port);
if (rv < B_OK)
return rv;
*out_tag = reply.seek_tag;
*out_tagged_time = reply.tagged_time;
*out_flags = reply.flags;
return reply.result;
}
void
BBufferProducer::SetInitialLatency(bigtime_t inInitialLatency,
uint32 flags)
{
fInitialLatency = inInitialLatency;
fInitialFlags = flags;
}
/*************************************************************
* private BBufferProducer
*************************************************************/
/*
private unimplemented
BBufferProducer::BBufferProducer()
BBufferProducer::BBufferProducer(const BBufferProducer &clone)
BBufferProducer & BBufferProducer::operator=(const BBufferProducer &clone)
*/
status_t BBufferProducer::_Reserved_BufferProducer_0(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_1(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_2(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_3(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_4(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_5(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_6(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_7(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_8(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_9(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_10(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_11(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_12(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_13(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_14(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_15(void *) { return B_ERROR; }
status_t
BBufferProducer::clip_shorts_to_region(const int16 *data,
int count,
BRegion *output)
{
UNIMPLEMENTED();
return B_ERROR;
}
status_t
BBufferProducer::clip_region_to_shorts(const BRegion *input,
int16 *data,
int max_count,
int *out_count)
{
UNIMPLEMENTED();
return B_ERROR;
}