Files
haiku-beta6/src/kits/media/MediaClient.cpp
T

593 lines
9.4 KiB
C++
Executable File

/*
* Copyright 2015, Dario Casalinuovo. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "MediaClient.h"
#include <MediaConnection.h>
#include <MediaRoster.h>
#include <TimeSource.h>
#include "debug.h"
BMediaClient::BMediaClient(const char* name,
media_type type, media_client_kind kind)
:
fLastInputID(0),
fLastOutputID(0)
{
CALLED();
fNode = new BMediaClientNode(name, this, type);
_Init();
fClient.node = fNode->Node();
fClient.kind = kind;
}
BMediaClient::~BMediaClient()
{
CALLED();
_Deinit();
}
const media_client&
BMediaClient::Client() const
{
return fClient;
}
status_t
BMediaClient::InitCheck() const
{
CALLED();
return fInitErr;
}
media_client_kind
BMediaClient::Kind() const
{
CALLED();
return fClient.kind;
}
media_type
BMediaClient::MediaType() const
{
CALLED();
// Right now ConsumerType() and ProducerType() are the same.
return fNode->ConsumerType();
}
BMediaConnection*
BMediaClient::BeginConnection(media_connection_kind kind)
{
CALLED();
media_connection_id id;
if (kind == B_MEDIA_INPUT)
id = fLastInputID++;
else
id = fLastOutputID++;
BMediaConnection* conn = new BMediaConnection(this, kind, id);
AddConnection(conn);
return conn;
}
status_t
BMediaClient::Bind(BMediaConnection* input, BMediaConnection* output)
{
CALLED();
if (input->fOwner != this || output->fOwner != this)
return B_ERROR;
else if (!input->IsInput() || !output->IsOutput())
return B_ERROR;
if (input == NULL
|| output == NULL)
return B_ERROR;
// TODO: Implement binding one input to more outputs.
if (input->fBind != NULL
|| output->fBind != NULL)
return B_ERROR;
input->fBind = output;
output->fBind = input;
return B_OK;
}
status_t
BMediaClient::Unbind(BMediaConnection* input, BMediaConnection* output)
{
CALLED();
if (input->fOwner != this || output->fOwner != this)
return B_ERROR;
else if (!input->IsInput() || !output->IsOutput())
return B_ERROR;
if (input == NULL
|| input == NULL)
return B_ERROR;
input->fBind = NULL;
output->fBind = NULL;
return B_OK;
}
status_t
BMediaClient::Connect(BMediaConnection* ourConnection,
BMediaConnection* theirConnection)
{
CALLED();
return Connect(ourConnection, theirConnection->Connection());
}
status_t
BMediaClient::Connect(BMediaConnection* ourConnection,
const media_connection& theirConnection)
{
CALLED();
if (ourConnection->IsOutput() && theirConnection.IsInput())
return _ConnectInput(ourConnection, theirConnection);
else if (ourConnection->IsInput() && theirConnection.IsOutput())
return _ConnectOutput(ourConnection, theirConnection);
return B_ERROR;
}
status_t
BMediaClient::Connect(BMediaConnection* connection,
const media_client& client)
{
CALLED();
// TODO: implement this
return B_ERROR;
}
status_t
BMediaClient::Disconnect()
{
CALLED();
for (int32 i = 0; i < CountInputs(); i++)
InputAt(i)->Disconnect();
for (int32 i = 0; i < CountOutputs(); i++)
OutputAt(i)->Disconnect();
return B_OK;
}
status_t
BMediaClient::DisconnectConnection(BMediaConnection* conn)
{
CALLED();
return B_OK;
}
status_t
BMediaClient::ResetConnection(BMediaConnection* conn)
{
CALLED();
return B_OK;
}
status_t
BMediaClient::ReleaseConnection(BMediaConnection* conn)
{
CALLED();
return B_OK;
}
int32
BMediaClient::CountInputs() const
{
CALLED();
return fInputs.CountItems();
}
int32
BMediaClient::CountOutputs() const
{
CALLED();
return fOutputs.CountItems();
}
BMediaConnection*
BMediaClient::InputAt(int32 index) const
{
CALLED();
return fInputs.ItemAt(index);
}
BMediaConnection*
BMediaClient::OutputAt(int32 index) const
{
CALLED();
return fOutputs.ItemAt(index);
}
BMediaConnection*
BMediaClient::FindInput(const media_connection& input) const
{
CALLED();
if (!input.IsInput())
return NULL;
return FindInput(input.Destination());
}
BMediaConnection*
BMediaClient::FindOutput(const media_connection& output) const
{
CALLED();
if (!output.IsOutput())
return NULL;
return FindOutput(output.Source());
}
BMediaConnection*
BMediaClient::FindInput(const media_destination& dest) const
{
CALLED();
for (int32 i = 0; i < CountInputs(); i++) {
if (dest.id == InputAt(i)->Destination().id)
return InputAt(i);
}
return NULL;
}
BMediaConnection*
BMediaClient::FindOutput(const media_source& source) const
{
CALLED();
for (int32 i = 0; i < CountOutputs(); i++) {
if (source.id == OutputAt(i)->Source().id)
return OutputAt(i);
}
return NULL;
}
bool
BMediaClient::IsRunning() const
{
CALLED();
return fRunning;
}
status_t
BMediaClient::Start(bool force)
{
CALLED();
status_t err = B_OK;
for (int32 i = 0; i < CountOutputs(); i++) {
media_node remoteNode = OutputAt(i)->Connection().RemoteNode();
if (remoteNode.kind & B_TIME_SOURCE)
err = BMediaRoster::CurrentRoster()->StartTimeSource(
remoteNode, BTimeSource::RealTime());
else
err = BMediaRoster::CurrentRoster()->StartNode(
remoteNode, fNode->TimeSource()->Now());
}
err = BMediaRoster::CurrentRoster()->StartNode(
fNode->Node(), fNode->TimeSource()->Now());
if (err == B_OK)
fRunning = true;
else
fRunning = false;
return err;
}
status_t
BMediaClient::Stop(bool force)
{
CALLED();
status_t err = BMediaRoster::CurrentRoster()->StopNode(
fNode->Node(), fNode->TimeSource()->Now());
if (err == B_OK)
fRunning = false;
else
fRunning = true;
return err;
}
status_t
BMediaClient::Seek(bigtime_t mediaTime,
bigtime_t performanceTime)
{
CALLED();
return BMediaRoster::CurrentRoster()->SeekNode(fNode->Node(),
mediaTime, performanceTime);
}
status_t
BMediaClient::Roll(bigtime_t start, bigtime_t stop, bigtime_t seek)
{
CALLED();
return BMediaRoster::CurrentRoster()->RollNode(fNode->Node(),
start, stop, seek);
}
status_t
BMediaClient::Preroll()
{
CALLED();
return BMediaRoster::CurrentRoster()->PrerollNode(fNode->Node());
}
status_t
BMediaClient::SyncTo(bigtime_t performanceTime, bigtime_t timeout)
{
CALLED();
return BMediaRoster::CurrentRoster()->SyncToNode(fNode->Node(),
performanceTime, timeout);
}
BMediaNode::run_mode
BMediaClient::RunMode() const
{
CALLED();
return fNode->RunMode();
}
status_t
BMediaClient::SetRunMode(BMediaNode::run_mode mode)
{
CALLED();
return BMediaRoster::CurrentRoster()->SetRunModeNode(fNode->Node(), mode);
}
status_t
BMediaClient::SetTimeSource(const media_client& timesource)
{
CALLED();
return BMediaRoster::CurrentRoster()->SetTimeSourceFor(fNode->Node().node,
timesource.node.node);
}
void
BMediaClient::GetLatencyRange(bigtime_t* min, bigtime_t* max) const
{
CALLED();
*min = fMinLatency;
*max = fMaxLatency;
}
void
BMediaClient::SetLatencyRange(bigtime_t min, bigtime_t max)
{
CALLED();
fMinLatency = min;
fMaxLatency = max;
}
bigtime_t
BMediaClient::OfflineTime() const
{
CALLED();
return fOfflineTime;
}
bigtime_t
BMediaClient::PerformanceTime() const
{
CALLED();
return fPerformanceTime;
}
status_t
BMediaClient::SendBuffer(BBuffer* buffer, BMediaConnection* connection)
{
CALLED();
return fNode->SendBuffer(buffer, connection);
}
void
BMediaClient::AddConnection(BMediaConnection* connection)
{
CALLED();
if (connection->IsInput())
fInputs.AddItem(connection);
else
fOutputs.AddItem(connection);
}
void
BMediaClient::BufferReceived(BMediaConnection* connection,
BBuffer* buffer)
{
CALLED();
if (connection->fProcessHook != NULL)
connection->fProcessHook(connection, buffer);
}
BMediaAddOn*
BMediaClient::AddOn(int32* id) const
{
CALLED();
return NULL;
}
void
BMediaClient::SetNotificationHook(notify_hook notifyHook, void* cookie)
{
CALLED();
fNotifyHook = notifyHook;
fNotifyCookie = cookie;
}
void
BMediaClient::_Init()
{
CALLED();
fNotifyHook = NULL;
fNotifyCookie = NULL;
BMediaRoster* roster = BMediaRoster::Roster(&fInitErr);
if (fInitErr == B_OK && roster != NULL)
fInitErr = roster->RegisterNode(fNode);
}
void
BMediaClient::_Deinit()
{
CALLED();
if (fRunning)
Stop();
Disconnect();
fNode->Release();
}
status_t
BMediaClient::_ConnectInput(BMediaConnection* output,
const media_connection& input)
{
CALLED();
if (input.Destination() == media_destination::null)
return B_MEDIA_BAD_DESTINATION;
media_output ourOutput = output->Connection().MediaOutput();
media_input theirInput = input.MediaInput();
media_format format = output->AcceptedFormat();
return BMediaRoster::CurrentRoster()->Connect(ourOutput.source,
theirInput.destination, &format, &ourOutput, &theirInput,
BMediaRoster::B_CONNECT_MUTED);
}
status_t
BMediaClient::_ConnectOutput(BMediaConnection* input,
const media_connection& output)
{
CALLED();
if (output.Source() == media_source::null)
return B_MEDIA_BAD_SOURCE;
media_input ourInput = input->Connection().MediaInput();
media_output theirOutput = output.MediaOutput();
media_format format = input->AcceptedFormat();
// TODO manage the node problems
//fNode->ActivateInternalConnect(false);
return BMediaRoster::CurrentRoster()->Connect(theirOutput.source,
ourInput.destination, &format, &theirOutput, &ourInput,
BMediaRoster::B_CONNECT_MUTED);
}
void BMediaClient::_ReservedMediaClient0() {}
void BMediaClient::_ReservedMediaClient1() {}
void BMediaClient::_ReservedMediaClient2() {}
void BMediaClient::_ReservedMediaClient3() {}
void BMediaClient::_ReservedMediaClient4() {}
void BMediaClient::_ReservedMediaClient5() {}
void BMediaClient::_ReservedMediaClient6() {}
void BMediaClient::_ReservedMediaClient7() {}
void BMediaClient::_ReservedMediaClient8() {}
void BMediaClient::_ReservedMediaClient9() {}
void BMediaClient::_ReservedMediaClient10() {}