diff --git a/headers/private/media/MediaClient.h b/headers/private/media/MediaClient.h new file mode 100755 index 0000000000..312227b0df --- /dev/null +++ b/headers/private/media/MediaClient.h @@ -0,0 +1,257 @@ +/* + * Copyright 2015, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef _MEDIA_CLIENT_H +#define _MEDIA_CLIENT_H + +#include +#include + +#include +#include +#include +#include + +#include "MediaClientNode.h" + + +namespace BPrivate { namespace media { + +// The node can receive media data. +#define B_MEDIA_RECORDER 0x000000001 +// The node can send media data to another node. +#define B_MEDIA_PLAYER 0x000000002 +// The node specify a control GUI which can be used to configure it. +#define B_MEDIA_CONTROLLABLE 0x000000004 + +// TODO: Add file interface +// TODO: Offline mode is still missing + +// BMediaClient is a general purpose class allowing to create any kind +// of media_node. It automatically manage the expected behavior under +// different run modes, and allow to specify the different capabilities +// which you may want. It work with a central loop allowing to handle, +// calling the right callbacks automatically events at a certain +// performance_time. +class BMediaClient { +public: + enum notification { + B_WILL_START = 1, // performance_time + B_WILL_STOP, // performance_time immediate + B_WILL_SEEK, // performance_time media_time + B_WILL_TIMEWARP, // real_time performance_time + + B_FORMAT_SUGGESTION, // media_type type, int32 quality, + // media_format* format + }; + + typedef void (*notify_hook)(void* cookie, + notification what, + ...); + + // TODO: Should allow BControllable capabilities + BMediaClient(const char* name, + media_type type + = B_MEDIA_UNKNOWN_TYPE, + uint64 + capabilities = B_MEDIA_PLAYER + & B_MEDIA_RECORDER); + + virtual ~BMediaClient(); + + status_t InitCheck() const; + + // Return the capabilities of this BMediaClient instance. + uint64 Capabilities() const; + media_type Type() const; + + // To connect pass the BMediaConnection to this class or to another BMediaClient, + // also in another team the connection object will be valid. + // When those functions return, the BMediaConnection is added to the + // list and is visible to other nodes as not connected. + + // This is supplied to support generic connections not related + // to a certain destination or source node, however for various ambiguity + // reasons we want the BMediaConnection to be declared as input or output. + // You can pass the object returned by this function to another + // BMediaClient::BeginConnection() and then Connect(), so that it + // will automatically connect to this node. + virtual BMediaConnection* BeginConnection(media_connection_kind kind); + + // Those are used if you want to connect to a precise input/output of + // another node, the connection returned represents a remote input/output. + virtual BMediaConnection* BeginConnection(const media_input& input); + virtual BMediaConnection* BeginConnection(const media_output& output); + + // This is used when we want to connect us with another BMediaClient, the + // returned connection is the one you will use to call the Connect method + // and will represents it by the point of view of this node. Don't try to + // use directly connections built by another BMediaClient, it will fail, + // always pass between this function to get a local connection from the point + // of view of *this* node and then call Connect(). + virtual BMediaConnection* BeginConnection(BMediaConnection* connection); + + // Bind internally two connections of the same BMediaClient, so that the + // input will be automatically forwarded to the output just after the + // ProcessFunc is called. The buffer is automatically recycled too. + // Beware that the binding operation is valid only for local connections + // which belong to this node, otherwise return B_ERROR. + virtual status_t Bind(BMediaConnection* input, + BMediaConnection* output); + + virtual status_t Unbind(BMediaConnection* input, + BMediaConnection* output); + + // If the user want a particular format for a connection it should + // use BMediaConnection::SetAcceptedFormat(), if it's not specified + // BMediaClient::Format() will be used, in case both aren't specified + // an error is returned. The connection should always belong to this + // node, in any other case it will return an error. + virtual status_t Connect(BMediaConnection* ourConnection, + BMediaConnection* theirConnection); + + virtual status_t Connect(BMediaConnection* ourConnection, + const dormant_node_info& dormantInfo); + + virtual status_t Connect(BMediaConnection* ourConnection, + const media_node& node); + + // Disconnect any connection belonging to this object, to disconnect + // a single connection use BMediaConnection::Disconnect(). + virtual status_t Disconnect(); + + int32 CountConnections() const; + int32 CountInputs() const; + int32 CountOutputs() const; + BMediaConnection* InputAt(int32 index) const; + BMediaConnection* OutputAt(int32 index) const; + + BMediaConnection* FindConnection( + const media_destination& dest) const; + BMediaConnection* FindConnection( + const media_source& source) const; + + bool IsRunning() const; + + virtual status_t Start(bool force = false); + virtual status_t Stop(bool force = false); + status_t Seek(bigtime_t mediaTime, + bigtime_t performanceTime); + status_t Roll(bigtime_t start, bigtime_t stop, + bigtime_t seek); + status_t Preroll(); + status_t SyncTo(bigtime_t performanceTime, + bigtime_t timeout = -1); + + // It will be B_INCREASE_LATENCY by default + BMediaNode::run_mode RunMode() const; + status_t SetRunMode(BMediaNode::run_mode mode); + status_t SetTimeSource(media_node timesource); + + // Specify a latency range to allow the node behave correctly. + // Ideally the minimum latency should be the algorithmic latency you expect + // from the node and will be used as starting point. The max latency is the + // maximum acceptable by you, over that point the node will adjust it's + // performance time to recover if a big delay happen. + void SetLatencyRange(bigtime_t min, + bigtime_t max); + + void GetLatencyRange(bigtime_t* min, + bigtime_t* max) const; + + // When in B_OFFLINE it returns OfflineTime(). + bigtime_t OfflineTime() const; + // Return the current performance time handled by the object + // when run_mode != B_OFFLINE. + bigtime_t PerformanceTime() const; + + // When a connection is not binded with another, it's your job to send + // the buffer to the connection you want. You might want + // to ovverride it so that you can track something, in this case + // be sure to call the base version. + // Automatically recycle the BBuffer. + virtual status_t SendBuffer(BMediaConnection* connection, + BBuffer* buffer); + + // This is supplied to support using this class in a BMediaAddOn. + // Default version just return NULL. + virtual BMediaAddOn* AddOn(int32* id) const; + + void SetNotificationHook(notify_hook notifyHook = NULL, + void* cookie = NULL); + +protected: + virtual void BufferReceived(BMediaConnection* connection, + BBuffer* buffer); + + // This is used when the user want to override the BeginConnection + // mechanism, for example to supply your BMediaConnection derived + // class. Take ownership of the object. + virtual void AddConnection(BMediaConnection* connection); + + // Called from BMediaConnection + status_t DisconnectConnection(BMediaConnection* conn); + status_t ResetConnection(BMediaConnection* conn); + status_t ReleaseConnection(BMediaConnection* conn); +private: + + void _Init(); + void _Deinit(); + + status_t _TranslateConnection(BMediaConnection* dest, + BMediaConnection* source); + + status_t _Connect(BMediaConnection* conn, + media_node node); + status_t _ConnectInput(BMediaConnection* output, + BMediaConnection* input); + status_t _ConnectOutput(BMediaConnection* input, + BMediaConnection* output); + + status_t fInitErr; + + uint64 fCapabilities; + + bool fRunning; + BMediaClientNode* fNode; + + bigtime_t fPerformanceTime; + bigtime_t fOfflineTime; + + bigtime_t fMinLatency; + bigtime_t fMaxLatency; + + notify_hook fNotifyHook; + + void* fNotifyCookie; + + BObjectList fInputs; + BObjectList fOutputs; + + virtual void _ReservedMediaClient0(); + virtual void _ReservedMediaClient1(); + virtual void _ReservedMediaClient2(); + virtual void _ReservedMediaClient3(); + virtual void _ReservedMediaClient4(); + virtual void _ReservedMediaClient5(); + virtual void _ReservedMediaClient6(); + virtual void _ReservedMediaClient7(); + virtual void _ReservedMediaClient8(); + virtual void _ReservedMediaClient9(); + virtual void _ReservedMediaClient10(); + uint32 fPadding[64]; + + friend class BMediaClientNode; + friend class BMediaConnection; +}; + + +} + +} + +using namespace BPrivate::media; + +#endif diff --git a/headers/private/media/MediaClientNode.h b/headers/private/media/MediaClientNode.h new file mode 100755 index 0000000000..0ede0d14fe --- /dev/null +++ b/headers/private/media/MediaClientNode.h @@ -0,0 +1,151 @@ +/* + * Copyright 2015, Dario Casalinuovo. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef _MEDIA_CLIENT_NODE_H +#define _MEDIA_CLIENT_NODE_H + + +#include +#include +#include +#include +#include + + +namespace BPrivate { namespace media { + +class BMediaClient; +class BMediaConnection; + +class BMediaClientNode : public BBufferConsumer, public BBufferProducer, + public BMediaEventLooper { +public: + BMediaClientNode(const char* name, + BMediaClient* owner, + media_type type + = B_MEDIA_UNKNOWN_TYPE); + + // Various useful stuff + + status_t SendBuffer(BBuffer* buffer, BMediaConnection* conn); + +protected: + + virtual BMediaAddOn* AddOn(int32* id) const; + + virtual void NodeRegistered(); + + virtual void SetRunMode(run_mode mode); + + virtual void Start(bigtime_t performanceTime); + + virtual void Stop(bigtime_t performanceTime, + bool immediate); + + virtual void Seek(bigtime_t mediaTime, + bigtime_t performanceTime); + + virtual void TimeWarp(bigtime_t realTime, + bigtime_t performanceTime); + + virtual status_t HandleMessage(int32 message, + const void* data, + size_t size); + + // BBufferConsumer + + virtual status_t AcceptFormat(const media_destination& dest, + media_format* format); + + virtual status_t GetNextInput(int32* cookie, + media_input* input); + + virtual void DisposeInputCookie(int32 cookie); + + virtual void BufferReceived(BBuffer* buffer); + + virtual status_t GetLatencyFor(const media_destination& dest, + bigtime_t* latency, + media_node_id* timesource); + + virtual status_t Connected(const media_source& source, + const media_destination& where, + const media_format& format, + media_input* outInput); + + virtual void Disconnected(const media_source& source, + const media_destination& where); + + virtual status_t FormatChanged(const media_source& source, + const media_destination& consumer, + int32 tag, + const media_format& format); + + // BBufferProducer + + virtual status_t FormatSuggestionRequested(media_type type, + int32 quality, media_format* format); + virtual status_t FormatProposal(const media_source& source, + media_format *format); + virtual status_t FormatChangeRequested(const media_source& source, + const media_destination& dest, + media_format *format, + int32* _deprecated_); + virtual void LateNoticeReceived(const media_source& source, + bigtime_t late, bigtime_t when); + virtual status_t GetNextOutput(int32 *cookie, media_output *output); + virtual status_t DisposeOutputCookie(int32 cookie); + virtual status_t SetBufferGroup(const media_source& source, + BBufferGroup *group); + virtual status_t PrepareToConnect(const media_source& source, + const media_destination& dest, + media_format *format, + media_source *out_source, + char *name); + virtual void Connect(status_t status, + const media_source& source, + const media_destination& dest, + const media_format &format, + char* name); + virtual void Disconnect(const media_source& source, + const media_destination& dest); + virtual void EnableOutput(const media_source& source, + bool enabled, int32* _deprecated_); + virtual status_t GetLatency(bigtime_t *outLatency); + virtual void LatencyChanged( const media_source& source, + const media_destination& dest, + bigtime_t latency, uint32 flags); + + void ProducerDataStatus(const media_destination& dest, + int32 status, bigtime_t when); +protected: + virtual void HandleEvent(const media_timed_event *event, + bigtime_t late, + bool realTimeEvent=false); + + virtual ~BMediaClientNode(); + +private: + void _HandleBuffer(BBuffer* buffer); + void _ProduceNewBuffer(const media_timed_event* event, + bigtime_t late); + + void _HandleStart(bigtime_t performanceTime); + void _HandleStop(bigtime_t performanceTime, + bool immediate); + void _HandleSeek(bigtime_t mediaTime, + bigtime_t performanceTime); + void _HandleTimeWarp(bigtime_t realTime, + bigtime_t performanceTime); + + BMediaClient* fOwner; +}; + +} +} + +using namespace BPrivate::media; + +#endif diff --git a/headers/private/media/MediaConnection.h b/headers/private/media/MediaConnection.h new file mode 100644 index 0000000000..0bc2b5bebb --- /dev/null +++ b/headers/private/media/MediaConnection.h @@ -0,0 +1,195 @@ +/* + * Copyright 2015, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef _MEDIA_CONNECTION_H +#define _MEDIA_CONNECTION_H + +#include +#include + +#include "MediaClientNode.h" + + +namespace BPrivate { namespace media { + + +enum media_connection_kind { + B_MEDIA_INPUT = 0, + B_MEDIA_OUTPUT = 1 +}; + + +class BMediaClient; + +// The BMediaConnection class is the swiss knife of BMediaClient. +// It represents a connection between two nodes and allow to create complex +// nodes without dealing with the unneeded complexity. Two local connections, +// can be binded, this means that when you will receive a buffer A as input, +// the Process function will be called so that you can process the BBuffer, +// and once the function returns the output will be automatically forwarded +// to the connection B. +// If you don't bind a connection, you have to call yourself the +// BMediaClient::SendBuffer() method or call BMediaClient::Recycle to +// recycle the buffer when you don't want to do anything further. +class BMediaConnection { +public: + enum notification { + B_CONNECTED = 1, + B_DISCONNECTED, + + B_PREPARE_TO_CONNECT, // media_format* format, media_source* source, + // char* name + B_CONNECT, + B_DISCONNECT, + + B_FORMAT_PROPOSAL, // media_format* format + + B_ASK_FORMAT_CHANGE, + B_FORMAT_CHANGED, + B_ASK_TIMER + }; + + // This function is called when it has come the moment to handle a buffer. + typedef void (*process_hook)(BMediaConnection* connection, + BBuffer* buffer); + + // Used to notify or inquire the client about what to do when certain + // events happen. + typedef status_t (*notify_hook)(notification what, + BMediaConnection* connection, + ...); + + virtual ~BMediaConnection(); + + // TODO: while most of the objects for both kinds are common + // it would be worthwile to have a private implementation + // so that we can better model the differences and avoid + // problems. + bool IsOutput() const; + bool IsInput() const; + + const media_destination& Destination() const; + const media_source& Source() const; + + bool HasBinding() const; + BMediaConnection* Binding() const; + + // This allow to specify a format that will be used while + // connecting to another node. See BMediaClient::SetFormat. + void SetAcceptedFormat( + const media_format& format); + const media_format& AcceptedFormat() const; + + // Represents the buffer size used by the media_node + void SetBufferSize(size_t size); + size_t BufferSize() const; + + // Represents the duration of one buffer + void SetBufferDuration(bigtime_t duration); + bigtime_t BufferDuration() const; + + bool IsConnected() const; + + void SetOutputEnabled(bool enabled); + bool IsOutputEnabled() const; + + void SetCookie(void* cookie); + void* Cookie() const; + + // Disconnect this connection. + status_t Disconnect(); + + // TODO: We really need a Reset()? + // When you reset a connection it can be reused as it was brand new. + status_t Reset(); + + // Once you are done with this connection you release it, it automatically + // remove the object from the BMediaClient and free all used resources. + // This will make the connection to disappear completely, so if you + // want to preserve it for future connections just Disconnect() and + // Reset() it. + status_t Release(); + + // Use this to set your callbacks. + void SetHooks(process_hook processHook = NULL, + notify_hook notifyHook = NULL, + void* cookie = NULL); + +protected: + BMediaConnection(BMediaClient* owner, + media_connection_kind kind); + BMediaConnection(BMediaClient* owner, + const media_output& output); + BMediaConnection(BMediaClient* owner, + const media_input& input); + + // TODO: All notifications should be done into private callbacks like this. + void ConnectedCallback(const media_source& source, + const media_format& format); + void DisconnectedCallback(const media_source& source); + + void ConnectCallback(const media_destination& source); + void DisconnectCallback(const media_destination& source); + +private: + void BuildMediaOutput(media_output* output) const; + void BuildMediaInput(media_input* output) const; + + void _Init(); + + bool fConnected; + bool fOutputEnabled; + + media_connection_kind fKind; + BMediaClient* fOwner; + media_node fOwnerNode; + team_id fOwnerTeam; + + // A connection might be binded so that it will automatically + // forward or receive the data from/to a local BMediaConnection, + // see BMediaClient::Bind. + BMediaConnection* fBind; + + process_hook fProcessHook; + notify_hook fNotifyHook; + void* fBufferCookie; + + media_source fSource; + media_destination fDestination; + + // This represents the node at other end of connection. + media_node fRemoteNode; + + media_format fFormat; + size_t fBufferSize; + bigtime_t fBufferDuration; + + BBufferGroup* fBufferGroup; + + virtual void _ReservedMediaConnection0(); + virtual void _ReservedMediaConnection1(); + virtual void _ReservedMediaConnection2(); + virtual void _ReservedMediaConnection3(); + virtual void _ReservedMediaConnection4(); + virtual void _ReservedMediaConnection5(); + virtual void _ReservedMediaConnection6(); + virtual void _ReservedMediaConnection7(); + virtual void _ReservedMediaConnection8(); + virtual void _ReservedMediaConnection9(); + virtual void _ReservedMediaConnection10(); + uint32 fPadding[64]; + + friend class BMediaClient; + friend class BMediaClientNode; +}; + + +} + +} + +using namespace BPrivate::media; + +#endif diff --git a/src/kits/media/Jamfile b/src/kits/media/Jamfile index a23c54281d..4994e22249 100644 --- a/src/kits/media/Jamfile +++ b/src/kits/media/Jamfile @@ -23,9 +23,13 @@ for architectureObject in [ MultiArchSubDirSetup ] { # Private Media Kit !missing_symbols.cpp Deprecated.cpp - MediaRecorder.cpp - MediaIO.cpp + AdapterIO.cpp + MediaIO.cpp + MediaClient.cpp + MediaConnection.cpp + MediaRecorder.cpp + # Public Media Kit Buffer.cpp @@ -63,6 +67,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { DefaultMediaTheme.cpp DormantNodeManager.cpp FormatManager.cpp + MediaClientNode.cpp MediaRecorderNode.cpp Notifications.cpp request_data.cpp diff --git a/src/kits/media/MediaClient.cpp b/src/kits/media/MediaClient.cpp new file mode 100755 index 0000000000..810e383755 --- /dev/null +++ b/src/kits/media/MediaClient.cpp @@ -0,0 +1,617 @@ +/* + * Copyright 2015, Dario Casalinuovo. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "MediaClient.h" + +#include +#include + +#include "debug.h" + + +BMediaClient::BMediaClient(const char* name, + media_type type, uint64 capability) + : + fCapabilities(capability) +{ + CALLED(); + + fNode = new BMediaClientNode(name, this, type); + _Init(); +} + + +BMediaClient::~BMediaClient() +{ + CALLED(); + + _Deinit(); +} + + +status_t +BMediaClient::InitCheck() const +{ + CALLED(); + + return fInitErr; +} + + +uint64 +BMediaClient::Capabilities() const +{ + CALLED(); + + return fCapabilities; +} + + +media_type +BMediaClient::Type() const +{ + CALLED(); + + // Right now ConsumerType() and ProducerType() are the same. + return fNode->ConsumerType(); +} + + +BMediaConnection* +BMediaClient::BeginConnection(media_connection_kind kind) +{ + CALLED(); + + BMediaConnection* conn = new BMediaConnection(this, kind); + AddConnection(conn); + return conn; +} + + +BMediaConnection* +BMediaClient::BeginConnection(const media_input& input) +{ + CALLED(); + + BMediaConnection* conn = new BMediaConnection(this, input); + AddConnection(conn); + return conn; +} + + +BMediaConnection* +BMediaClient::BeginConnection(const media_output& output) +{ + CALLED(); + + BMediaConnection* conn = new BMediaConnection(this, output); + AddConnection(conn); + return conn; +} + + +BMediaConnection* +BMediaClient::BeginConnection(BMediaConnection* connection) +{ + CALLED(); + + if (connection->fOwner == this) + return NULL; + + BMediaConnection* ret = NULL; + if (_TranslateConnection(ret, connection) == B_OK) { + AddConnection(ret); + return ret; + } + return NULL; +} + + +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 + || input == 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(); + + 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 dormant_node_info& dormantInfo) +{ + CALLED(); + + media_node node; + status_t err = BMediaRoster::CurrentRoster()->InstantiateDormantNode( + dormantInfo, &node, B_FLAVOR_IS_GLOBAL); + + if (err != B_OK) + return err; + + return Connect(connection, node); +} + + +status_t +BMediaClient::Connect(BMediaConnection* connection, + const media_node& node) +{ + 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::CountConnections() const +{ + CALLED(); + + return fOutputs.CountItems()+fInputs.CountItems(); +} + + +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::FindConnection(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::FindConnection(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)->fRemoteNode; + 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(media_node timesource) +{ + CALLED(); + + return BMediaRoster::CurrentRoster()->SetTimeSourceFor(fNode->Node().node, + timesource.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(BMediaConnection* connection, BBuffer* buffer) +{ + 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::_TranslateConnection(BMediaConnection* dest, + BMediaConnection* source) +{ + CALLED(); + + return B_ERROR; +} + + +status_t +BMediaClient::_Connect(BMediaConnection* connection, + media_node node) +{ + CALLED(); + +} + + +status_t +BMediaClient::_ConnectInput(BMediaConnection* output, + BMediaConnection* input) +{ + CALLED(); + + return B_ERROR; +} + + +status_t +BMediaClient::_ConnectOutput(BMediaConnection* input, + BMediaConnection* output) +{ + CALLED(); + + if (output->Source() == media_source::null) + return B_MEDIA_BAD_SOURCE; + + media_input ourInput; + media_output theirOutput; + media_format format = input->AcceptedFormat(); + + input->BuildMediaInput(&ourInput); + output->BuildMediaOutput(&theirOutput); + + // 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() {} diff --git a/src/kits/media/MediaClientNode.cpp b/src/kits/media/MediaClientNode.cpp new file mode 100755 index 0000000000..68dc83ebb6 --- /dev/null +++ b/src/kits/media/MediaClientNode.cpp @@ -0,0 +1,657 @@ +/* + * Copyright 2015, Dario Casalinuovo. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "MediaClientNode.h" + +#include +#include +#include + +#include + +#include "debug.h" + +#define B_NEW_BUFFER (BTimedEventQueue::B_USER_EVENT + 1) + + +BMediaClientNode::BMediaClientNode(const char* name, + BMediaClient* owner, media_type type) + : + BMediaNode(name), + BBufferConsumer(type), + BBufferProducer(type), + BMediaEventLooper(), + fOwner(owner) +{ + CALLED(); + + // Configure the node to do the requested jobs + if (fOwner->Capabilities() & B_MEDIA_PLAYER) + AddNodeKind(B_BUFFER_PRODUCER); + if (fOwner->Capabilities() & B_MEDIA_RECORDER) + AddNodeKind(B_BUFFER_CONSUMER); + if (fOwner->Capabilities() & B_MEDIA_CONTROLLABLE) + AddNodeKind(B_CONTROLLABLE); +} + + +status_t +BMediaClientNode::SendBuffer(BBuffer* buffer, BMediaConnection* conn) +{ + return BBufferProducer::SendBuffer(buffer, conn->Source(), conn->Destination()); +} + + +BMediaAddOn* +BMediaClientNode::AddOn(int32* id) const +{ + CALLED(); + + return fOwner->AddOn(id); +} + + +void +BMediaClientNode::NodeRegistered() +{ + CALLED(); + + Run(); +} + + +void +BMediaClientNode::SetRunMode(run_mode mode) +{ + CALLED(); + + int32 priority; + if (mode == BMediaNode::B_OFFLINE) + priority = B_OFFLINE_PROCESSING; + else { + switch(ConsumerType()) { + case B_MEDIA_RAW_AUDIO: + case B_MEDIA_ENCODED_AUDIO: + priority = B_AUDIO_RECORDING; + break; + + case B_MEDIA_RAW_VIDEO: + case B_MEDIA_ENCODED_VIDEO: + priority = B_VIDEO_RECORDING; + break; + + default: + priority = B_DEFAULT_MEDIA_PRIORITY; + } + } + + SetPriority(suggest_thread_priority(priority)); + BMediaNode::SetRunMode(mode); +} + + +void +BMediaClientNode::Start(bigtime_t performanceTime) +{ + CALLED(); + + BMediaEventLooper::Start(performanceTime); + fOwner->fRunning = true; +} + + +void +BMediaClientNode::Stop(bigtime_t performanceTime, bool immediate) +{ + CALLED(); + + BMediaEventLooper::Stop(performanceTime, immediate); + fOwner->fRunning = false; +} + + +void +BMediaClientNode::Seek(bigtime_t mediaTime, bigtime_t performanceTime) +{ + CALLED(); + + BMediaEventLooper::Seek(mediaTime, performanceTime); +} + + +void +BMediaClientNode::TimeWarp(bigtime_t realTime, bigtime_t performanceTime) +{ + CALLED(); + + BMediaEventLooper::TimeWarp(realTime, performanceTime); +} + + +status_t +BMediaClientNode::HandleMessage(int32 message, + const void* data, size_t size) +{ + CALLED(); + + return B_ERROR; +} + + +status_t +BMediaClientNode::AcceptFormat(const media_destination& dest, + media_format* format) +{ + CALLED(); + + BMediaConnection* conn = fOwner->FindConnection(dest); + if (conn == NULL) + return B_MEDIA_BAD_DESTINATION; + + if (format_is_compatible(*format, conn->AcceptedFormat())) + return B_OK; + + *format = conn->AcceptedFormat(); + + return B_MEDIA_BAD_FORMAT; +} + + +status_t +BMediaClientNode::GetNextInput(int32* cookie, + media_input* input) +{ + CALLED(); + + if (fOwner->CountInputs() == 0) + return B_BAD_INDEX; + + if (*cookie < 0 || *cookie > fOwner->CountInputs()) { + *cookie = -1; + input = NULL; + } else { + BMediaConnection* conn = fOwner->InputAt(*cookie); + if (conn != NULL) { + conn->BuildMediaInput(input); + *cookie += 1; + return B_OK; + } + } + return B_BAD_INDEX; +} + + +void +BMediaClientNode::DisposeInputCookie(int32 cookie) +{ + CALLED(); + +} + + +void +BMediaClientNode::BufferReceived(BBuffer* buffer) +{ + CALLED(); + + EventQueue()->AddEvent(media_timed_event(buffer->Header()->start_time, + BTimedEventQueue::B_HANDLE_BUFFER, buffer, + BTimedEventQueue::B_RECYCLE_BUFFER)); +} + + +status_t +BMediaClientNode::GetLatencyFor(const media_destination& dest, + bigtime_t* latency, media_node_id* timesource) +{ + CALLED(); + + BMediaConnection* conn = fOwner->FindConnection(dest); + if (conn == NULL) + return B_MEDIA_BAD_DESTINATION; + + *latency = fOwner->fMaxLatency; + *timesource = TimeSource()->ID(); + return B_OK; +} + + +status_t +BMediaClientNode::Connected(const media_source& source, + const media_destination& where, const media_format& format, + media_input* outInput) +{ + CALLED(); + + BMediaConnection* conn = fOwner->FindConnection(where); + if (conn == NULL) + return B_MEDIA_BAD_DESTINATION; + + conn->ConnectedCallback(source, format); + conn->BuildMediaInput(outInput); + return B_OK; +} + + +void +BMediaClientNode::Disconnected(const media_source& source, + const media_destination& where) +{ + CALLED(); + + BMediaConnection* conn = fOwner->FindConnection(where); + if (conn == NULL) + return; + + conn->DisconnectedCallback(source); +} + + +status_t +BMediaClientNode::FormatChanged(const media_source& source, + const media_destination& consumer, + int32 tag, const media_format& format) +{ + CALLED(); + + BMediaConnection* conn = fOwner->FindConnection(consumer); + if (conn == NULL) + return B_MEDIA_BAD_DESTINATION; + + if (!format_is_compatible(format, conn->AcceptedFormat())) + return B_MEDIA_BAD_FORMAT; + + conn->SetAcceptedFormat(format); + + return B_OK; +} + + +status_t +BMediaClientNode::FormatSuggestionRequested(media_type type, + int32 quality, media_format* format) +{ + CALLED(); + + if (type != ConsumerType() + && type != ProducerType()) { + return B_MEDIA_BAD_FORMAT; + } + + if (fOwner->fNotifyHook != NULL) { + status_t result = B_OK; + (*fOwner->fNotifyHook)(fOwner->fNotifyCookie, + BMediaClient::B_FORMAT_SUGGESTION, + type, quality, format, &result); + return result; + } else { + // In that case we return just a very generic format. + media_format outFormat; + outFormat.type = fOwner->Type(); + *format = outFormat; + return B_OK; + } +} + + +status_t +BMediaClientNode::FormatProposal(const media_source& source, + media_format* format) +{ + CALLED(); + + BMediaConnection* conn = fOwner->FindConnection(source); + if (conn == NULL) + return B_MEDIA_BAD_DESTINATION; + + if (fOwner->fNotifyHook != NULL) { + return (*conn->fNotifyHook)(BMediaConnection::B_FORMAT_PROPOSAL, + conn, format); + } else + *format = conn->AcceptedFormat(); + + return B_OK; +} + + +status_t +BMediaClientNode::FormatChangeRequested(const media_source& source, + const media_destination& dest, media_format* format, + int32* _deprecated_) +{ + CALLED(); + + return B_ERROR; +} + + +void +BMediaClientNode::LateNoticeReceived(const media_source& source, + bigtime_t late, bigtime_t when) +{ + CALLED(); + +} + + +status_t +BMediaClientNode::GetNextOutput(int32* cookie, media_output* output) +{ + CALLED(); + + if (fOwner->CountOutputs() == 0) + return B_BAD_INDEX; + + if (*cookie < 0 || *cookie > fOwner->CountOutputs()) { + *cookie = -1; + output = NULL; + } else { + BMediaConnection* conn = fOwner->OutputAt(*cookie); + if (conn != NULL) { + conn->BuildMediaOutput(output); + *cookie += 1; + return B_OK; + } + } + return B_BAD_INDEX; +} + + +status_t +BMediaClientNode::DisposeOutputCookie(int32 cookie) +{ + CALLED(); + + return B_OK; +} + + +status_t +BMediaClientNode::SetBufferGroup(const media_source& source, BBufferGroup* group) +{ + CALLED(); + + BMediaConnection* conn = fOwner->FindConnection(source); + if (conn == NULL) + return B_MEDIA_BAD_SOURCE; + + if (group == conn->fBufferGroup) + return B_OK; + + delete conn->fBufferGroup; + + if (group != NULL) { + conn->fBufferGroup = group; + return B_OK; + } + + bigtime_t latency = 0; + GetLatency(&latency); + int32 count = int32(latency / conn->BufferDuration() + 2); + + if (count < 3) + count = 3; + + conn->fBufferGroup = new BBufferGroup(conn->BufferSize(), count); + if (conn->fBufferGroup == NULL) + return B_NO_MEMORY; + + return conn->fBufferGroup->InitCheck(); +} + + +status_t +BMediaClientNode::PrepareToConnect(const media_source& source, + const media_destination& dest, media_format* format, + media_source* out_source, char *name) +{ + CALLED(); + + BMediaConnection* conn = fOwner->FindConnection(source); + if (conn == NULL) + return B_MEDIA_BAD_SOURCE; + + if (conn->fDestination != media_destination::null) + return B_MEDIA_ALREADY_CONNECTED; + + if (format->type != fOwner->Type()) + return B_MEDIA_BAD_FORMAT; + + conn->fDestination = dest; + conn->SetAcceptedFormat(*format); + *out_source = conn->fSource; + strcpy(name, Name()); + return B_OK; +} + + +void +BMediaClientNode::Connect(status_t status, const media_source& source, + const media_destination& dest, const media_format& format, + char* name) +{ + CALLED(); + + BMediaConnection* conn = fOwner->FindConnection(source); + if (conn == NULL) + return; + + // Reset the connection to reuse it + if (status != B_OK) { + conn->Reset(); + return; + } + + conn->ConnectCallback(dest); + strcpy(name, Name()); + conn->SetAcceptedFormat(format); + + bigtime_t latency; + media_node_id id; + FindLatencyFor(dest, &latency, &id); + + bigtime_t duration = ((format.u.raw_audio.buffer_size * 1000000LL) + / ((format.u.raw_audio.format + & media_raw_audio_format::B_AUDIO_SIZE_MASK) + * format.u.raw_audio.channel_count)) + / (int32)format.u.raw_audio.frame_rate; + SetBufferDuration(duration); + SetEventLatency((3 * BufferDuration()) / 4); + // TODO: Allocate buffers, add correct latency estimate +} + + +void +BMediaClientNode::Disconnect(const media_source& source, + const media_destination& dest) +{ + CALLED(); + + BMediaConnection* conn = fOwner->FindConnection(source); + if (conn == NULL) + return; + + if (source == conn->fSource && dest == conn->fDestination) + conn->Reset(); + + conn->DisconnectCallback(dest); +} + + +void +BMediaClientNode::EnableOutput(const media_source& source, + bool enabled, int32* _deprecated_) +{ + CALLED(); + + BMediaConnection* conn = fOwner->FindConnection(source); + if (conn != NULL) { + conn->fOutputEnabled = enabled; + return; + } +} + + +status_t +BMediaClientNode::GetLatency(bigtime_t* outLatency) +{ + CALLED(); + + // TODO: finish latency handling + *outLatency = fOwner->fMinLatency; + return B_OK; +} + + +void +BMediaClientNode::LatencyChanged(const media_source& source, + const media_destination& dest, bigtime_t latency, uint32 flags) +{ + CALLED(); +} + + +void +BMediaClientNode::ProducerDataStatus(const media_destination& dest, + int32 status, bigtime_t when) +{ + CALLED(); +} + + +void +BMediaClientNode::HandleEvent(const media_timed_event* event, + bigtime_t late, bool realTimeEvent) +{ + CALLED(); + + switch (event->type) { + // This event is used for inputs which consumes buffers + // or binded connections which also sent them to an output. + case BTimedEventQueue::B_HANDLE_BUFFER: + _HandleBuffer((BBuffer*)event->pointer); + break; + + // This is used for connections which produce buffers only. + case B_NEW_BUFFER: + _ProduceNewBuffer(event, late); + break; + + case BTimedEventQueue::B_START: + { + if (RunState() != B_STARTED) + _HandleStart(event->event_time); + break; + } + + case BTimedEventQueue::B_STOP: + _HandleStop(event->event_time, true); + break; + + case BTimedEventQueue::B_SEEK: + _HandleSeek(event->event_time, event->bigdata); + break; + + case BTimedEventQueue::B_WARP: + _HandleTimeWarp(event->event_time, event->bigdata); + break; + } +} + + +BMediaClientNode::~BMediaClientNode() +{ + CALLED(); + + Quit(); +} + + +void +BMediaClientNode::_HandleBuffer(BBuffer* buffer) +{ + CALLED(); + + media_destination dest; + dest.id = buffer->Header()->destination; + BMediaConnection* conn = fOwner->FindConnection(dest); + + if (conn != NULL) + fOwner->BufferReceived(conn, buffer); + // TODO: this should be logged someway +} + + +void +BMediaClientNode::_ProduceNewBuffer(const media_timed_event* event, + bigtime_t late) +{ + CALLED(); + + if (RunState() != BMediaEventLooper::B_STARTED) + return; + + // We get the data through the event + // so that we know which connection + + // event.pointer == connection +} + + +void +BMediaClientNode::_HandleStart(bigtime_t performanceTime) +{ + CALLED(); + + if (fOwner->fNotifyHook != NULL) { + (*fOwner->fNotifyHook)(fOwner->fNotifyCookie, + BMediaClient::B_WILL_START, + performanceTime); + } +} + + +void +BMediaClientNode::_HandleStop(bigtime_t performanceTime, + bool immediate) +{ + CALLED(); + + if (fOwner->fNotifyHook != NULL) { + (*fOwner->fNotifyHook)(fOwner->fNotifyCookie, + BMediaClient::B_WILL_STOP, + performanceTime, immediate); + } + EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true, + BTimedEventQueue::B_HANDLE_BUFFER); +} + + +void +BMediaClientNode::_HandleSeek(bigtime_t mediaTime, + bigtime_t performanceTime) +{ + CALLED(); + + if (fOwner->fNotifyHook != NULL) { + (*fOwner->fNotifyHook)(fOwner->fNotifyCookie, + BMediaClient::B_WILL_SEEK, + performanceTime, mediaTime); + } +} + + +void +BMediaClientNode::_HandleTimeWarp(bigtime_t realTime, + bigtime_t performanceTime) +{ + CALLED(); + + if (fOwner->fNotifyHook != NULL) { + (*fOwner->fNotifyHook)(fOwner->fNotifyCookie, + BMediaClient::B_WILL_TIMEWARP, + realTime, performanceTime); + } +} diff --git a/src/kits/media/MediaConnection.cpp b/src/kits/media/MediaConnection.cpp new file mode 100644 index 0000000000..2e0e10d981 --- /dev/null +++ b/src/kits/media/MediaConnection.cpp @@ -0,0 +1,329 @@ +/* + * Copyright 2015, Dario Casalinuovo. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include + +#include + +#include "debug.h" + + +bool +BMediaConnection::IsOutput() const +{ + CALLED(); + + return fKind == B_MEDIA_OUTPUT; +} + + +bool +BMediaConnection::IsInput() const +{ + CALLED(); + + return fKind == B_MEDIA_INPUT; +} + + +void +BMediaConnection::BuildMediaOutput(media_output* output) const +{ + CALLED(); + + output->format = AcceptedFormat(); + output->node = fOwner->fNode->Node(); + output->source = fSource; + output->source.port = fOwner->fNode->ControlPort(); +} + + +void +BMediaConnection::BuildMediaInput(media_input* input) const +{ + CALLED(); + + input->format = AcceptedFormat(); + input->node = fOwner->fNode->Node(); + input->destination = fDestination; + input->destination.port = fOwner->fNode->ControlPort(); +} + + +const media_destination& +BMediaConnection::Destination() const +{ + CALLED(); + + return fDestination; +} + + +const media_source& +BMediaConnection::Source() const +{ + CALLED(); + + return fSource; +} + + +bool +BMediaConnection::HasBinding() const +{ + CALLED(); + + return fBind != NULL; +} + + +BMediaConnection* +BMediaConnection::Binding() const +{ + CALLED(); + + return fBind; +} + + +void +BMediaConnection::SetAcceptedFormat(const media_format& format) +{ + CALLED(); + + fFormat = format; +} + + +const media_format& +BMediaConnection::AcceptedFormat() const +{ + CALLED(); + + return fFormat; +} + + +bool +BMediaConnection::IsConnected() const +{ + CALLED(); + + return fConnected; +} + + +bool +BMediaConnection::IsOutputEnabled() const +{ + CALLED(); + + return fOutputEnabled; +} + + +void* +BMediaConnection::Cookie() const +{ + CALLED(); + + return fBufferCookie; +} + + +status_t +BMediaConnection::Disconnect() +{ + CALLED(); + + return fOwner->DisconnectConnection(this); +} + + +status_t +BMediaConnection::Reset() +{ + CALLED(); + + if (IsOutput()) + fDestination = media_destination::null; + else + fSource = media_source::null; + + delete fBufferGroup; + fBufferGroup = NULL; + + return fOwner->ResetConnection(this); +} + + +status_t +BMediaConnection::Release() +{ + CALLED(); + + return fOwner->ReleaseConnection(this); +} + + +void +BMediaConnection::SetHooks(process_hook processHook, + notify_hook notifyHook, void* cookie) +{ + CALLED(); + + fProcessHook = processHook; + fNotifyHook = notifyHook; + fBufferCookie = cookie; +} + + +BMediaConnection::BMediaConnection(BMediaClient* owner, + media_connection_kind kind) + : + fKind(kind), + fOwner(owner), + fBind(NULL) +{ + CALLED(); + + _Init(); +} + + +BMediaConnection::BMediaConnection(BMediaClient* owner, + const media_output& output) + : + fKind(B_MEDIA_OUTPUT), + fOwner(owner), + fBind(NULL) +{ + CALLED(); + + _Init(); +} + + +BMediaConnection::BMediaConnection(BMediaClient* owner, + const media_input& input) + : + fKind(B_MEDIA_INPUT), + fOwner(owner), + fBind(NULL) +{ + CALLED(); + + _Init(); +} + + +BMediaConnection::~BMediaConnection() +{ + CALLED(); + +} + + +void +BMediaConnection::SetBufferSize(size_t size) +{ + CALLED(); + + fBufferSize = size; +} + + +size_t +BMediaConnection::BufferSize() const +{ + CALLED(); + + return fBufferSize; +} + + +void +BMediaConnection::SetBufferDuration(bigtime_t duration) +{ + CALLED(); + + fBufferDuration = duration; +} + + +bigtime_t +BMediaConnection::BufferDuration() const +{ + CALLED(); + + return fBufferDuration; +} + + +void +BMediaConnection::ConnectedCallback(const media_source& source, + const media_format& format) +{ + fSource = source; + SetAcceptedFormat(format); + + if (fNotifyHook != NULL) + (*fNotifyHook)(B_CONNECTED, this); + + fConnected = true; +} + + +void +BMediaConnection::DisconnectedCallback(const media_source& source) +{ + fSource = media_source::null; + + if (fNotifyHook != NULL) + (*fNotifyHook)(B_DISCONNECTED, this); + + fConnected = false; +} + + +void +BMediaConnection::ConnectCallback(const media_destination& destination) +{ + fDestination = destination; +} + + +void +BMediaConnection::DisconnectCallback(const media_destination& destination) +{ + fDestination = destination; +} + + +void +BMediaConnection::_Init() +{ + CALLED(); + + fBufferGroup = NULL; + fNotifyHook = NULL; + fProcessHook = NULL; + + fSource = media_source::null; + fDestination = media_destination::null; +} + + +void BMediaConnection::_ReservedMediaConnection0() {} +void BMediaConnection::_ReservedMediaConnection1() {} +void BMediaConnection::_ReservedMediaConnection2() {} +void BMediaConnection::_ReservedMediaConnection3() {} +void BMediaConnection::_ReservedMediaConnection4() {} +void BMediaConnection::_ReservedMediaConnection5() {} +void BMediaConnection::_ReservedMediaConnection6() {} +void BMediaConnection::_ReservedMediaConnection7() {} +void BMediaConnection::_ReservedMediaConnection8() {} +void BMediaConnection::_ReservedMediaConnection9() {} +void BMediaConnection::_ReservedMediaConnection10() {}