Updated time source code to allow automatic starting and stopping of time sources.
Sending run mode changes and broadcasting of time changes is also implemented. For one reason or another, all this doesn't work right now. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2520 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
ffa7234e82
commit
7fd432700b
@ -22,6 +22,7 @@ namespace BPrivate { namespace media {
|
||||
class TimeSourceObject;
|
||||
class SystemTimeSourceObject;
|
||||
struct TimeSourceTransmit;
|
||||
struct SlaveNodes;
|
||||
} }
|
||||
|
||||
|
||||
@ -124,9 +125,9 @@ virtual status_t _Reserved_TimeSource_5(void *);
|
||||
bool fStarted;
|
||||
area_id fArea;
|
||||
volatile BPrivate::media::TimeSourceTransmit *fBuf;
|
||||
_BSlaveNodeStorageP * _mSlaveNodes;
|
||||
BPrivate::media::SlaveNodes *fSlaveNodes;
|
||||
|
||||
area_id _mOrigArea;
|
||||
area_id _reserved_area;
|
||||
bool fIsRealtime;
|
||||
bool _reserved_bool_[3];
|
||||
uint32 _reserved_time_source_[10];
|
||||
@ -142,6 +143,8 @@ virtual status_t AddMe(BMediaNode * node);
|
||||
void DirectStop(bigtime_t at, bool immediate);
|
||||
void DirectSeek(bigtime_t to, bigtime_t at);
|
||||
void DirectSetRunMode(run_mode mode);
|
||||
void DirectAddMe(const media_node &node);
|
||||
void DirectRemoveMe(const media_node &node);
|
||||
};
|
||||
|
||||
|
||||
|
@ -149,11 +149,13 @@ enum {
|
||||
FILEINTERFACE_MESSAGE_END,
|
||||
CONTROLLABLE_MESSAGE_START = 0x600,
|
||||
CONTROLLABLE_MESSAGE_END,
|
||||
TIMESOURECE_MESSAGE_START = 0x700,
|
||||
TIMESOURCE_MESSAGE_START = 0x700,
|
||||
|
||||
TIMESOURCE_OP, // datablock is a struct time_source_op_info
|
||||
TIMESOURCE_ADD_SLAVE_NODE,
|
||||
TIMESOURCE_REMOVE_SLAVE_NODE,
|
||||
|
||||
TIMESOURECE_MESSAGE_END,
|
||||
TIMESOURCE_MESSAGE_END,
|
||||
};
|
||||
|
||||
|
||||
@ -875,7 +877,14 @@ struct node_set_timesource_command : public command_data
|
||||
media_node_id timesource_id;
|
||||
};
|
||||
|
||||
struct timesource_add_slave_node_command : public command_data
|
||||
{
|
||||
media_node node;
|
||||
};
|
||||
|
||||
|
||||
struct timesource_remove_slave_node_command : public command_data
|
||||
{
|
||||
media_node node;
|
||||
};
|
||||
|
||||
#endif // _DATA_EXCHANGE_H
|
||||
|
@ -103,6 +103,12 @@ BMediaNode::~BMediaNode()
|
||||
// BeBook: by the BMediaNode destructor, but it might be convenient to call it sometime before
|
||||
// BeBook: you delete your node instance, depending on your implementation and circumstances.
|
||||
|
||||
// first we remove the time source
|
||||
if (fTimeSource) {
|
||||
fTimeSource->RemoveMe(this);
|
||||
fTimeSource->Release();
|
||||
}
|
||||
|
||||
// Attention! We do not unregister TimeSourceObject nodes,
|
||||
// or delete their control ports, since they are only a
|
||||
// shadow object, and the real one still exists
|
||||
@ -112,9 +118,6 @@ BMediaNode::~BMediaNode()
|
||||
if (fControlPort > 0)
|
||||
delete_port(fControlPort);
|
||||
}
|
||||
|
||||
if (fTimeSource)
|
||||
fTimeSource->Release();
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
@ -362,7 +365,7 @@ BMediaNode::WaitForMessage(bigtime_t waitUntil,
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
if (message > TIMESOURECE_MESSAGE_START && message < TIMESOURECE_MESSAGE_END) {
|
||||
if (message > TIMESOURCE_MESSAGE_START && message < TIMESOURCE_MESSAGE_END) {
|
||||
if (!fTimeSourceThis)
|
||||
fTimeSourceThis = dynamic_cast<BTimeSource *>(this);
|
||||
INFO("BMediaNode::WaitForMessage calling BTimeSource %p\n", fTimeSourceThis);
|
||||
@ -599,7 +602,7 @@ BMediaNode::HandleBadMessage(int32 code,
|
||||
CALLED();
|
||||
|
||||
TRACE("BMediaNode::HandleBadMessage: code %#08lx, buffer %p, size %ld\n", code, buffer, size);
|
||||
if (code < NODE_MESSAGE_START || code > TIMESOURECE_MESSAGE_END) {
|
||||
if (code < NODE_MESSAGE_START || code > TIMESOURCE_MESSAGE_END) {
|
||||
FATAL("BMediaNode::HandleBadMessage: unknown code!\n");
|
||||
} else {
|
||||
/* All messages targeted to nodes should be handled here,
|
||||
|
@ -4,9 +4,12 @@
|
||||
* DESCR:
|
||||
***********************************************************************/
|
||||
#include <TimeSource.h>
|
||||
#include <Autolock.h>
|
||||
#include <string.h>
|
||||
#include "debug.h"
|
||||
#include "DataExchange.h"
|
||||
#include "ServerInterface.h"
|
||||
#include "TimeSourceObject.h"
|
||||
|
||||
namespace BPrivate { namespace media {
|
||||
|
||||
@ -21,6 +24,15 @@ struct TimeSourceTransmit // sizeof() must be <= 4096
|
||||
float drift[INDEX_COUNT];
|
||||
};
|
||||
|
||||
struct SlaveNodes
|
||||
{
|
||||
#define SLAVE_NODES_COUNT 300
|
||||
BLocker locker;
|
||||
int32 count;
|
||||
media_node_id node_id[SLAVE_NODES_COUNT];
|
||||
port_id node_port[SLAVE_NODES_COUNT];
|
||||
};
|
||||
|
||||
} }
|
||||
|
||||
|
||||
@ -33,6 +45,8 @@ BTimeSource::~BTimeSource()
|
||||
CALLED();
|
||||
if (fArea > 0)
|
||||
delete_area(fArea);
|
||||
if (fSlaveNodes)
|
||||
free(fSlaveNodes);
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
@ -173,12 +187,23 @@ BTimeSource::BTimeSource() :
|
||||
fStarted(false),
|
||||
fArea(-1),
|
||||
fBuf(NULL),
|
||||
fSlaveNodes((BPrivate::media::SlaveNodes*)malloc(sizeof(BPrivate::media::SlaveNodes))),
|
||||
fIsRealtime(false)
|
||||
{
|
||||
CALLED();
|
||||
AddNodeKind(B_TIME_SOURCE);
|
||||
// printf("##### BTimeSource::BTimeSource() name %s, id %ld\n", Name(), ID());
|
||||
|
||||
if (fSlaveNodes == NULL) {
|
||||
FATAL("Error: BTimeSource::BTimeSource() fSlaveNodes == NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize the slave node storage
|
||||
fSlaveNodes->count = 0;
|
||||
memset(&fSlaveNodes->node_id, 0, SLAVE_NODES_COUNT * sizeof(media_node_id));
|
||||
memset(&fSlaveNodes->node_port, 0, SLAVE_NODES_COUNT * sizeof(port_id));
|
||||
|
||||
// This constructor is only called by real time sources that inherit
|
||||
// BTimeSource. We create the communication area in FinishCreate(),
|
||||
// since we don't have a correct ID() until this node is registered.
|
||||
@ -217,6 +242,20 @@ BTimeSource::HandleMessage(int32 message,
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
case TIMESOURCE_ADD_SLAVE_NODE:
|
||||
{
|
||||
const timesource_add_slave_node_command *data = static_cast<const timesource_add_slave_node_command *>(rawdata);
|
||||
DirectAddMe(data->node);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
case TIMESOURCE_REMOVE_SLAVE_NODE:
|
||||
{
|
||||
const timesource_remove_slave_node_command *data = static_cast<const timesource_remove_slave_node_command *>(rawdata);
|
||||
DirectRemoveMe(data->node);
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
return B_ERROR;
|
||||
}
|
||||
@ -247,16 +286,39 @@ void
|
||||
BTimeSource::BroadcastTimeWarp(bigtime_t at_real_time,
|
||||
bigtime_t new_performance_time)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
// call BMediaNode::TimeWarp() of all slaved nodes
|
||||
CALLED();
|
||||
// calls BMediaNode::TimeWarp() of all slaved nodes
|
||||
|
||||
BAutolock lock(fSlaveNodes->locker);
|
||||
|
||||
for (int i = 0, n = 0; i < SLAVE_NODES_COUNT && n != fSlaveNodes->count; i++) {
|
||||
if (fSlaveNodes->node_id[i] != 0) {
|
||||
node_time_warp_command cmd;
|
||||
cmd.at_real_time = at_real_time;
|
||||
cmd.to_performance_time = new_performance_time;
|
||||
SendToPort(fSlaveNodes->node_port[i], NODE_TIME_WARP, &cmd, sizeof(cmd));
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BTimeSource::SendRunMode(run_mode mode)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
CALLED();
|
||||
// send the run mode change to all slaved nodes
|
||||
|
||||
BAutolock lock(fSlaveNodes->locker);
|
||||
|
||||
for (int i = 0, n = 0; i < SLAVE_NODES_COUNT && n != fSlaveNodes->count; i++) {
|
||||
if (fSlaveNodes->node_id[i] != 0) {
|
||||
node_set_run_mode_command cmd;
|
||||
cmd.mode = mode;
|
||||
SendToPort(fSlaveNodes->node_port[i], NODE_SET_RUN_MODE, &cmd, sizeof(cmd));
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -290,6 +352,7 @@ BTimeSource::BTimeSource(media_node_id id) :
|
||||
fStarted(false),
|
||||
fArea(-1),
|
||||
fBuf(NULL),
|
||||
fSlaveNodes(NULL),
|
||||
fIsRealtime(false)
|
||||
{
|
||||
CALLED();
|
||||
@ -342,21 +405,95 @@ BTimeSource::FinishCreate()
|
||||
status_t
|
||||
BTimeSource::RemoveMe(BMediaNode *node)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
|
||||
return B_ERROR;
|
||||
CALLED();
|
||||
if (fKinds & NODE_KIND_SHADOW_TIMESOURCE) {
|
||||
timesource_remove_slave_node_command cmd;
|
||||
cmd.node = node->Node();
|
||||
SendToPort(fControlPort, TIMESOURCE_REMOVE_SLAVE_NODE, &cmd, sizeof(cmd));
|
||||
} else {
|
||||
DirectRemoveMe(node->Node());
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BTimeSource::AddMe(BMediaNode *node)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
|
||||
return B_ERROR;
|
||||
CALLED();
|
||||
if (fKinds & NODE_KIND_SHADOW_TIMESOURCE) {
|
||||
timesource_add_slave_node_command cmd;
|
||||
cmd.node = node->Node();
|
||||
SendToPort(fControlPort, TIMESOURCE_ADD_SLAVE_NODE, &cmd, sizeof(cmd));
|
||||
} else {
|
||||
DirectAddMe(node->Node());
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BTimeSource::DirectAddMe(const media_node &node)
|
||||
{
|
||||
CALLED();
|
||||
// XXX this code has race conditions and is pretty dumb, and it
|
||||
// XXX won't detect nodes that crash and don't remove themself.
|
||||
BAutolock lock(fSlaveNodes->locker);
|
||||
|
||||
if (fSlaveNodes->count == SLAVE_NODES_COUNT) {
|
||||
FATAL("BTimeSource::DirectAddMe out of slave node slots\n");
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < SLAVE_NODES_COUNT; i++) {
|
||||
if (fSlaveNodes->node_id[i] == 0) {
|
||||
fSlaveNodes->node_id[i] = node.node;
|
||||
fSlaveNodes->node_port[i] = node.port;
|
||||
fSlaveNodes->count += 1;
|
||||
if (fSlaveNodes->count == 1) {
|
||||
// start the time source
|
||||
time_source_op_info msg;
|
||||
msg.op = B_TIMESOURCE_START;
|
||||
msg.real_time = RealTime();
|
||||
printf("starting time source\n");
|
||||
write_port(fControlPort, TIMESOURCE_OP, &msg, sizeof(msg));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
FATAL("BTimeSource::DirectAddMe failed\n");
|
||||
}
|
||||
|
||||
void
|
||||
BTimeSource::DirectRemoveMe(const media_node &node)
|
||||
{
|
||||
// XXX this code has race conditions and is pretty dumb, and it
|
||||
// XXX won't detect nodes that crash and don't remove themself.
|
||||
CALLED();
|
||||
BAutolock lock(fSlaveNodes->locker);
|
||||
|
||||
if (fSlaveNodes->count == 0) {
|
||||
FATAL("BTimeSource::DirectRemoveMe no slots used\n");
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < SLAVE_NODES_COUNT; i++) {
|
||||
if (fSlaveNodes->node_id[i] == node.node && fSlaveNodes->node_port[i] == node.port) {
|
||||
fSlaveNodes->node_id[i] = 0;
|
||||
fSlaveNodes->node_port[i] = 0;
|
||||
fSlaveNodes->count -= 1;
|
||||
if (fSlaveNodes->count == 0) {
|
||||
// stop the time source
|
||||
time_source_op_info msg;
|
||||
msg.op = B_TIMESOURCE_STOP_IMMEDIATELY;
|
||||
msg.real_time = RealTime();
|
||||
printf("stopping time source\n");
|
||||
write_port(fControlPort, TIMESOURCE_OP, &msg, sizeof(msg));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
FATAL("BTimeSource::DirectRemoveMe failed\n");
|
||||
}
|
||||
|
||||
void
|
||||
BTimeSource::DirectStart(bigtime_t at)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user