From f506f3056fce86ec83341eb39e5d1fbbc469ecf7 Mon Sep 17 00:00:00 2001 From: Dario Casalinuovo Date: Thu, 24 Nov 2016 00:19:06 +0100 Subject: [PATCH] MediaClient: Improve internals and API * Capabilities() become Kind() * Use media_client and media_connection to better model the different situations of the API. Reduce code duplication and move media_kit structs/methods into private. * Various API and beauty improvements. * Introduce id management for media_connections. * Fix different issues preventing to correctly begin a connection. --- headers/private/media/MediaClient.h | 70 ++++----- headers/private/media/MediaConnection.h | 53 +++---- src/kits/media/Jamfile | 1 + src/kits/media/MediaClient.cpp | 139 +++++++----------- src/kits/media/MediaClientNode.cpp | 25 ++-- src/kits/media/MediaConnection.cpp | 183 ++++++++++-------------- 6 files changed, 194 insertions(+), 277 deletions(-) diff --git a/headers/private/media/MediaClient.h b/headers/private/media/MediaClient.h index 44d8fd550c..f1e9f0da59 100755 --- a/headers/private/media/MediaClient.h +++ b/headers/private/media/MediaClient.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -19,19 +20,6 @@ namespace BPrivate { namespace media { -typedef int32 media_client_kind; - -enum media_client_kinds { - // The node can receive media data. - B_MEDIA_RECORDER = 0x000000001, - // The node can send media data to another node. - B_MEDIA_PLAYER = 0x000000002, - // The node specify a control GUI which can be used to configure it. - 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 @@ -56,20 +44,25 @@ public: ...); // TODO: Should allow BControllable capabilities + // TODO: Add file interface + // TODO: Offline mode is still missing + BMediaClient(const char* name, media_type type = B_MEDIA_UNKNOWN_TYPE, media_client_kind - capabilities = B_MEDIA_PLAYER + kind = B_MEDIA_PLAYER & B_MEDIA_RECORDER); virtual ~BMediaClient(); - status_t InitCheck() const; + const media_client& Client() const; // Return the capabilities of this BMediaClient instance. - media_client_kind Capabilities() const; - media_type Type() const; + media_client_kind Kind() const; + media_type MediaType() const; + + status_t InitCheck() const; // To connect pass the BMediaConnection to this class or to another BMediaClient, // also in another team the connection object will be valid. @@ -84,11 +77,6 @@ public: // 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); - // 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. @@ -110,18 +98,20 @@ public: BMediaConnection* theirConnection); virtual status_t Connect(BMediaConnection* ourConnection, - const dormant_node_info& dormantInfo); + const media_connection& theirConnection); + // Find a free input/output and try to connect to the media_client, + // return meaningful error otherwise. virtual status_t Connect(BMediaConnection* ourConnection, - const media_node& node); + const media_client& client); // 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; @@ -164,14 +154,6 @@ public: // 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(BBuffer* buffer, - BMediaConnection* connection); - // This is supplied to support using this class in a BMediaAddOn. // Default version just return NULL. virtual BMediaAddOn* AddOn(int32* id) const; @@ -180,6 +162,13 @@ public: void* cookie = NULL); protected: + // 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. + virtual status_t SendBuffer(BBuffer* buffer, + BMediaConnection* connection); + virtual void BufferReceived(BMediaConnection* connection, BBuffer* buffer); @@ -192,24 +181,20 @@ protected: 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); + const media_connection& input); status_t _ConnectOutput(BMediaConnection* input, - BMediaConnection* output); + const media_connection& output); status_t fInitErr; - media_client_kind fCapabilities; + media_client fClient; bool fRunning; BMediaClientNode* fNode; @@ -227,6 +212,9 @@ private: BObjectList fInputs; BObjectList fOutputs; + int32 fLastInputID; + int32 fLastOutputID; + virtual void _ReservedMediaClient0(); virtual void _ReservedMediaClient1(); virtual void _ReservedMediaClient2(); diff --git a/headers/private/media/MediaConnection.h b/headers/private/media/MediaConnection.h index 0bc2b5bebb..85a388976a 100644 --- a/headers/private/media/MediaConnection.h +++ b/headers/private/media/MediaConnection.h @@ -9,20 +9,15 @@ #include #include +#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, @@ -51,7 +46,8 @@ public: B_ASK_TIMER }; - // This function is called when it has come the moment to handle a buffer. + + // This function is called when it is the moment to handle a buffer. typedef void (*process_hook)(BMediaConnection* connection, BBuffer* buffer); @@ -63,15 +59,16 @@ public: virtual ~BMediaConnection(); + const media_connection& Connection() const; + media_connection_id Id() const; + const char* Name() const; + // 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 IsOutput() const; bool HasBinding() const; BMediaConnection* Binding() const; @@ -119,11 +116,8 @@ public: protected: BMediaConnection(BMediaClient* owner, - media_connection_kind kind); - BMediaConnection(BMediaClient* owner, - const media_output& output); - BMediaConnection(BMediaClient* owner, - const media_input& input); + media_connection_kind kind, + media_connection_id id); // TODO: All notifications should be done into private callbacks like this. void ConnectedCallback(const media_source& source, @@ -134,18 +128,17 @@ protected: void DisconnectCallback(const media_destination& source); private: - void BuildMediaOutput(media_output* output) const; - void BuildMediaInput(media_input* output) const; + media_input MediaInput() const; + media_output MediaOutput() const; + + const media_source& Source() const; + const media_destination& Destination() const; void _Init(); - bool fConnected; - bool fOutputEnabled; + media_connection fConnection; - 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, @@ -156,18 +149,14 @@ private: 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; + bool fConnected; + bool fOutputEnabled; + virtual void _ReservedMediaConnection0(); virtual void _ReservedMediaConnection1(); virtual void _ReservedMediaConnection2(); diff --git a/src/kits/media/Jamfile b/src/kits/media/Jamfile index 4994e22249..a977729988 100644 --- a/src/kits/media/Jamfile +++ b/src/kits/media/Jamfile @@ -27,6 +27,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { AdapterIO.cpp MediaIO.cpp MediaClient.cpp + MediaClientDefs.cpp MediaConnection.cpp MediaRecorder.cpp diff --git a/src/kits/media/MediaClient.cpp b/src/kits/media/MediaClient.cpp index 3c5255b85b..cca4444200 100755 --- a/src/kits/media/MediaClient.cpp +++ b/src/kits/media/MediaClient.cpp @@ -5,6 +5,8 @@ #include "MediaClient.h" +#include + #include #include @@ -12,14 +14,18 @@ BMediaClient::BMediaClient(const char* name, - media_type type, media_client_kind capabilities) + media_type type, media_client_kind kind) : - fCapabilities(capabilities) + fLastInputID(0), + fLastOutputID(0) { CALLED(); fNode = new BMediaClientNode(name, this, type); _Init(); + + fClient.node = fNode->Node(); + fClient.kind = kind; } @@ -31,6 +37,13 @@ BMediaClient::~BMediaClient() } +const media_client& +BMediaClient::Client() const +{ + return fClient; +} + + status_t BMediaClient::InitCheck() const { @@ -41,16 +54,16 @@ BMediaClient::InitCheck() const media_client_kind -BMediaClient::Capabilities() const +BMediaClient::Kind() const { CALLED(); - return fCapabilities; + return fClient.kind; } media_type -BMediaClient::Type() const +BMediaClient::MediaType() const { CALLED(); @@ -64,29 +77,13 @@ BMediaClient::BeginConnection(media_connection_kind kind) { CALLED(); - BMediaConnection* conn = new BMediaConnection(this, kind); - AddConnection(conn); - return conn; -} + media_connection_id id; + if (kind == B_MEDIA_INPUT) + id = fLastInputID++; + else + id = fLastOutputID++; - -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); + BMediaConnection* conn = new BMediaConnection(this, kind, id); AddConnection(conn); return conn; } @@ -143,9 +140,19 @@ BMediaClient::Connect(BMediaConnection* ourConnection, { CALLED(); - if (ourConnection->IsOutput() && theirConnection->IsInput()) + 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()) + else if (ourConnection->IsInput() && theirConnection.IsOutput()) return _ConnectOutput(ourConnection, theirConnection); return B_ERROR; @@ -154,24 +161,7 @@ BMediaClient::Connect(BMediaConnection* ourConnection, 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) + const media_client& client) { CALLED(); @@ -223,15 +213,6 @@ BMediaClient::ReleaseConnection(BMediaConnection* conn) } -int32 -BMediaClient::CountConnections() const -{ - CALLED(); - - return fOutputs.CountItems()+fInputs.CountItems(); -} - - int32 BMediaClient::CountInputs() const { @@ -310,7 +291,7 @@ BMediaClient::Start(bool force) status_t err = B_OK; for (int32 i = 0; i < CountOutputs(); i++) { - media_node remoteNode = OutputAt(i)->fRemoteNode; + media_node remoteNode = OutputAt(i)->Connection().RemoteNode(); if (remoteNode.kind & B_TIME_SOURCE) err = BMediaRoster::CurrentRoster()->StartTimeSource( remoteNode, BTimeSource::RealTime()); @@ -533,52 +514,38 @@ BMediaClient::_Deinit() } -status_t -BMediaClient::_TranslateConnection(BMediaConnection* dest, - BMediaConnection* source) -{ - CALLED(); - - return B_ERROR; -} - - -status_t -BMediaClient::_Connect(BMediaConnection* connection, - media_node node) -{ - CALLED(); - - return B_ERROR; -} - - status_t BMediaClient::_ConnectInput(BMediaConnection* output, - BMediaConnection* input) + const media_connection& input) { CALLED(); - return B_ERROR; + 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, - BMediaConnection* output) + const media_connection& output) { CALLED(); - if (output->Source() == media_source::null) + if (output.Source() == media_source::null) return B_MEDIA_BAD_SOURCE; - media_input ourInput; - media_output theirOutput; + media_input ourInput = input->Connection().MediaInput(); + media_output theirOutput = output.MediaOutput(); media_format format = input->AcceptedFormat(); - input->BuildMediaInput(&ourInput); - output->BuildMediaOutput(&theirOutput); - // TODO manage the node problems //fNode->ActivateInternalConnect(false); diff --git a/src/kits/media/MediaClientNode.cpp b/src/kits/media/MediaClientNode.cpp index 68dc83ebb6..e0dab9cda0 100755 --- a/src/kits/media/MediaClientNode.cpp +++ b/src/kits/media/MediaClientNode.cpp @@ -6,6 +6,7 @@ #include "MediaClientNode.h" #include +#include #include #include @@ -28,11 +29,11 @@ BMediaClientNode::BMediaClientNode(const char* name, CALLED(); // Configure the node to do the requested jobs - if (fOwner->Capabilities() & B_MEDIA_PLAYER) + if (fOwner->Kind() & B_MEDIA_PLAYER) AddNodeKind(B_BUFFER_PRODUCER); - if (fOwner->Capabilities() & B_MEDIA_RECORDER) + if (fOwner->Kind() & B_MEDIA_RECORDER) AddNodeKind(B_BUFFER_CONSUMER); - if (fOwner->Capabilities() & B_MEDIA_CONTROLLABLE) + if (fOwner->Kind() & B_MEDIA_CONTROLLABLE) AddNodeKind(B_CONTROLLABLE); } @@ -174,7 +175,7 @@ BMediaClientNode::GetNextInput(int32* cookie, } else { BMediaConnection* conn = fOwner->InputAt(*cookie); if (conn != NULL) { - conn->BuildMediaInput(input); + *input = conn->MediaInput(); *cookie += 1; return B_OK; } @@ -230,7 +231,7 @@ BMediaClientNode::Connected(const media_source& source, return B_MEDIA_BAD_DESTINATION; conn->ConnectedCallback(source, format); - conn->BuildMediaInput(outInput); + *outInput = conn->MediaInput(); return B_OK; } @@ -289,7 +290,7 @@ BMediaClientNode::FormatSuggestionRequested(media_type type, } else { // In that case we return just a very generic format. media_format outFormat; - outFormat.type = fOwner->Type(); + outFormat.type = fOwner->MediaType(); *format = outFormat; return B_OK; } @@ -350,7 +351,7 @@ BMediaClientNode::GetNextOutput(int32* cookie, media_output* output) } else { BMediaConnection* conn = fOwner->OutputAt(*cookie); if (conn != NULL) { - conn->BuildMediaOutput(output); + *output = conn->MediaOutput(); *cookie += 1; return B_OK; } @@ -413,15 +414,15 @@ BMediaClientNode::PrepareToConnect(const media_source& source, if (conn == NULL) return B_MEDIA_BAD_SOURCE; - if (conn->fDestination != media_destination::null) + if (conn->Destination() != media_destination::null) return B_MEDIA_ALREADY_CONNECTED; - if (format->type != fOwner->Type()) + if (format->type != fOwner->MediaType()) return B_MEDIA_BAD_FORMAT; - conn->fDestination = dest; + conn->fConnection.destination = dest; conn->SetAcceptedFormat(*format); - *out_source = conn->fSource; + *out_source = conn->Source(); strcpy(name, Name()); return B_OK; } @@ -473,7 +474,7 @@ BMediaClientNode::Disconnect(const media_source& source, if (conn == NULL) return; - if (source == conn->fSource && dest == conn->fDestination) + if (source == conn->Source() && dest == conn->Destination()) conn->Reset(); conn->DisconnectCallback(dest); diff --git a/src/kits/media/MediaConnection.cpp b/src/kits/media/MediaConnection.cpp index 2e0e10d981..e820037f61 100644 --- a/src/kits/media/MediaConnection.cpp +++ b/src/kits/media/MediaConnection.cpp @@ -5,17 +5,59 @@ #include -#include - #include "debug.h" +BMediaConnection::BMediaConnection(BMediaClient* owner, + media_connection_kind kind, + media_connection_id id) + : + fOwner(owner), + fBind(NULL) +{ + CALLED(); + + _Init(); + + fConnection.kind = kind; + fConnection.id = id; + fConnection.client = fOwner->Client(); + + if (IsOutput()) { + fConnection.source.port = fOwner->fNode->ControlPort(); + fConnection.source.id = fConnection.id; + + fConnection.destination = media_destination::null; + } else { + // IsInput() + fConnection.destination.port = fOwner->fNode->ControlPort(); + fConnection.destination.id = fConnection.id; + + fConnection.source = media_source::null; + } +} + + +BMediaConnection::~BMediaConnection() +{ + CALLED(); + +} + + +const media_connection& +BMediaConnection::Connection() const +{ + return fConnection; +} + + bool BMediaConnection::IsOutput() const { CALLED(); - return fKind == B_MEDIA_OUTPUT; + return fConnection.IsOutput(); } @@ -24,49 +66,7 @@ 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; + return fConnection.IsInput(); } @@ -93,7 +93,7 @@ BMediaConnection::SetAcceptedFormat(const media_format& format) { CALLED(); - fFormat = format; + fConnection.format = format; } @@ -102,7 +102,7 @@ BMediaConnection::AcceptedFormat() const { CALLED(); - return fFormat; + return fConnection.format; } @@ -147,11 +147,6 @@ BMediaConnection::Reset() { CALLED(); - if (IsOutput()) - fDestination = media_destination::null; - else - fSource = media_source::null; - delete fBufferGroup; fBufferGroup = NULL; @@ -180,52 +175,6 @@ BMediaConnection::SetHooks(process_hook processHook, } -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) { @@ -266,7 +215,7 @@ void BMediaConnection::ConnectedCallback(const media_source& source, const media_format& format) { - fSource = source; + fConnection.source = source; SetAcceptedFormat(format); if (fNotifyHook != NULL) @@ -279,8 +228,6 @@ BMediaConnection::ConnectedCallback(const media_source& source, void BMediaConnection::DisconnectedCallback(const media_source& source) { - fSource = media_source::null; - if (fNotifyHook != NULL) (*fNotifyHook)(B_DISCONNECTED, this); @@ -291,14 +238,13 @@ BMediaConnection::DisconnectedCallback(const media_source& source) void BMediaConnection::ConnectCallback(const media_destination& destination) { - fDestination = destination; + fConnection.destination = destination; } void BMediaConnection::DisconnectCallback(const media_destination& destination) { - fDestination = destination; } @@ -310,9 +256,34 @@ BMediaConnection::_Init() fBufferGroup = NULL; fNotifyHook = NULL; fProcessHook = NULL; +} - fSource = media_source::null; - fDestination = media_destination::null; + +media_input +BMediaConnection::MediaInput() const +{ + return fConnection.MediaInput(); +} + + +media_output +BMediaConnection::MediaOutput() const +{ + return fConnection.MediaOutput(); +} + + +const media_source& +BMediaConnection::Source() const +{ + return fConnection.Source(); +} + + +const media_destination& +BMediaConnection::Destination() const +{ + return fConnection.Destination(); }