Initial merge of the BMediaClient branch
* The BMediaClient is an higher level API to the media_kit. It corresponds to what the layout API was for the interface_kit. The main idea is to allow the developer concentrate only on higher level details and avoiding handle with the tricky parts of the media_kit. At the same time the general purpose node that is implemented inside would allow implementing the best techniques around thus at the same time reducing code duplication and increasing efficiency. * BMediaClient is WIP, this is the initial merge of the branch. The initial development stone was set long time ago and walked through various design/implementation phases.
This commit is contained in:
parent
956c2f5fb0
commit
9b410c41e8
257
headers/private/media/MediaClient.h
Executable file
257
headers/private/media/MediaClient.h
Executable file
@ -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 <ObjectList.h>
|
||||
#include <Buffer.h>
|
||||
|
||||
#include <MediaAddOn.h>
|
||||
#include <MediaConnection.h>
|
||||
#include <MediaDefs.h>
|
||||
#include <MediaNode.h>
|
||||
|
||||
#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<BMediaConnection> fInputs;
|
||||
BObjectList<BMediaConnection> 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
|
151
headers/private/media/MediaClientNode.h
Executable file
151
headers/private/media/MediaClientNode.h
Executable file
@ -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 <BufferConsumer.h>
|
||||
#include <BufferProducer.h>
|
||||
#include <Controllable.h>
|
||||
#include <MediaDefs.h>
|
||||
#include <MediaEventLooper.h>
|
||||
|
||||
|
||||
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
|
195
headers/private/media/MediaConnection.h
Normal file
195
headers/private/media/MediaConnection.h
Normal file
@ -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 <BufferGroup.h>
|
||||
#include <MediaDefs.h>
|
||||
|
||||
#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
|
@ -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
|
||||
|
617
src/kits/media/MediaClient.cpp
Executable file
617
src/kits/media/MediaClient.cpp
Executable file
@ -0,0 +1,617 @@
|
||||
/*
|
||||
* Copyright 2015, Dario Casalinuovo. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "MediaClient.h"
|
||||
|
||||
#include <MediaRoster.h>
|
||||
#include <TimeSource.h>
|
||||
|
||||
#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() {}
|
657
src/kits/media/MediaClientNode.cpp
Executable file
657
src/kits/media/MediaClientNode.cpp
Executable file
@ -0,0 +1,657 @@
|
||||
/*
|
||||
* Copyright 2015, Dario Casalinuovo. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "MediaClientNode.h"
|
||||
|
||||
#include <MediaClient.h>
|
||||
#include <scheduler.h>
|
||||
#include <TimeSource.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
329
src/kits/media/MediaConnection.cpp
Normal file
329
src/kits/media/MediaConnection.cpp
Normal file
@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright 2015, Dario Casalinuovo. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <MediaConnection.h>
|
||||
|
||||
#include <MediaClient.h>
|
||||
|
||||
#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() {}
|
Loading…
Reference in New Issue
Block a user