diff --git a/headers/os/media/MediaNode.h b/headers/os/media/MediaNode.h index 90cbdff256..b67b26af13 100644 --- a/headers/os/media/MediaNode.h +++ b/headers/os/media/MediaNode.h @@ -111,7 +111,7 @@ struct media_node_attribute }; -namespace BPrivate { namespace media { class TimeSourceObject; } } +namespace BPrivate { namespace media { class TimeSourceObject; class SystemTimeSourceObject; } } class BMediaNode @@ -256,6 +256,7 @@ private: friend class MNodeManager; friend class BBufferProducer; // for getting _mNodeID friend class BPrivate::media::TimeSourceObject; + friend class BPrivate::media::SystemTimeSourceObject; // Deprecated in 4.1 int32 IncrementChangeTag(); diff --git a/headers/os/media/TimeSource.h b/headers/os/media/TimeSource.h index 44e24dc512..0dac761380 100644 --- a/headers/os/media/TimeSource.h +++ b/headers/os/media/TimeSource.h @@ -18,6 +18,7 @@ class _BSlaveNodeStorageP; struct _time_transmit_buf; +namespace BPrivate { namespace media { class TimeSourceObject; class SystemTimeSourceObject; } } class BTimeSource : @@ -100,6 +101,8 @@ private: friend class BMediaNode; friend class BMediaRoster; friend class _ServerApp; + friend class BPrivate::media::TimeSourceObject; + friend class BPrivate::media::SystemTimeSourceObject; BTimeSource( /* private unimplemented */ const BTimeSource & clone); diff --git a/src/kits/media/Jamfile b/src/kits/media/Jamfile index d7ad510640..689e9a74eb 100644 --- a/src/kits/media/Jamfile +++ b/src/kits/media/Jamfile @@ -47,7 +47,6 @@ SharedLibrary media : DormantNodeManager.cpp Notifications.cpp PortPool.cpp - SystemTimeSource.cpp SharedBufferList.cpp TrackReader.cpp TimedEventQueuePrivate.cpp diff --git a/src/kits/media/MediaNode.cpp b/src/kits/media/MediaNode.cpp index 40f8ba59a1..6a80c6d253 100644 --- a/src/kits/media/MediaNode.cpp +++ b/src/kits/media/MediaNode.cpp @@ -13,7 +13,6 @@ #include #include "debug.h" #include "DataExchange.h" -#include "SystemTimeSource.h" #include "ServerInterface.h" #include "Notifications.h" @@ -101,10 +100,12 @@ BMediaNode::~BMediaNode() // BeBook: UnregisterNode() unregisters a node from the Media Server. It's called automatically // 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. - (BMediaRoster::Roster())->UnregisterNode(this); + // BeBook: you delete your node instance, depending on your implementation and circumstances. + // ATT! We do not unregister TimeSourceObject nodes (identified by fControlPort == -999666) + if (fControlPort != -999666) // must match value in TimeSourceObject::TimeSourceObject() + (BMediaRoster::Roster())->UnregisterNode(this); - if (fControlPort != -1) + if (fControlPort > 0) delete_port(fControlPort); if (fTimeSource) fTimeSource->Release(); diff --git a/src/kits/media/MediaRoster.cpp b/src/kits/media/MediaRoster.cpp index 2004b3cb8d..e34875b021 100644 --- a/src/kits/media/MediaRoster.cpp +++ b/src/kits/media/MediaRoster.cpp @@ -14,11 +14,11 @@ #include "debug.h" #include "TList.h" #include "PortPool.h" -#include "SystemTimeSource.h" #include "ServerInterface.h" #include "DataExchange.h" #include "DormantNodeManager.h" #include "Notifications.h" +#include "TimeSourceObjectManager.h" namespace BPrivate { namespace media { extern team_id team; @@ -437,17 +437,15 @@ BMediaRoster::ReleaseNode(const media_node & node) BTimeSource * BMediaRoster::MakeTimeSourceFor(const media_node & for_node) { - BROKEN(); + CALLED(); printf("BMediaRoster::MakeTimeSourceFor enter, node %ld, port %ld, kind %#lx\n", for_node.node, for_node.port, for_node.kind); - static BTimeSource *source = 0; - if (source == 0) - source = new _SysTimeSource(); + BTimeSource *source = _TimeSourceObjectManager->GetTimeSource(for_node); printf("BMediaRoster::MakeTimeSourceFor leave, node %ld, port %ld, kind %#lx\n", source->Node().node, source->Node().port, source->Node().kind); - return dynamic_cast(source->Acquire()); + return source; } diff --git a/src/kits/media/SystemTimeSource.cpp b/src/kits/media/SystemTimeSource.cpp deleted file mode 100644 index f5d73934e5..0000000000 --- a/src/kits/media/SystemTimeSource.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2002 Marcus Overhagen. All Rights Reserved. - * This file may be used under the terms of the OpenBeOS License. - * - * The realtime BTimeSource - ***********************************************************************/ - -// XXX This works only as long a BTimeSource is only supporting realtime - -#include -#include -#include -#include "SystemTimeSource.h" - -_SysTimeSource::_SysTimeSource() : - BMediaNode("system time source") -{ - printf("_SysTimeSource::_SysTimeSource enter\n"); - BMediaRoster::Roster()->RegisterNode(this); // XXX - printf("_SysTimeSource::_SysTimeSource leave\n"); -} - -/* virtual */ status_t -_SysTimeSource::SnoozeUntil( - bigtime_t performance_time, - bigtime_t with_latency, - bool retry_signals) -{ - bigtime_t time = performance_time - with_latency; - status_t err; - do { - err = snooze_until(time, B_SYSTEM_TIMEBASE); - } while (err == B_INTERRUPTED && retry_signals); - return err; -} - -/* virtual */ status_t -_SysTimeSource::TimeSourceOp( - const time_source_op_info & op, - void * _reserved) -{ - return B_OK; -} - -/* virtual */ BMediaAddOn* -_SysTimeSource::AddOn(int32 * internal_id) const -{ - return NULL; -} diff --git a/src/kits/media/SystemTimeSource.h b/src/kits/media/SystemTimeSource.h deleted file mode 100644 index 6585f4fe46..0000000000 --- a/src/kits/media/SystemTimeSource.h +++ /dev/null @@ -1,31 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2002 Marcus Overhagen. All Rights Reserved. - * This file may be used under the terms of the OpenBeOS License. - * - * The realtime BTimeSource - ***********************************************************************/ -#ifndef _SYSTEM_TIME_SOURCE_H_ -#define _SYSTEM_TIME_SOURCE_H_ - -#include - -class _SysTimeSource : public BTimeSource -{ -public: - _SysTimeSource(); - - virtual status_t SnoozeUntil( - bigtime_t performance_time, - bigtime_t with_latency = 0, - bool retry_signals = false); -protected: - virtual status_t TimeSourceOp( - const time_source_op_info & op, - void * _reserved); - -virtual BMediaAddOn* AddOn( - int32 * internal_id) const; - -}; - -#endif diff --git a/src/kits/media/TimeSourceObject.cpp b/src/kits/media/TimeSourceObject.cpp index 0dc300bf9c..bdc18d2f6b 100644 --- a/src/kits/media/TimeSourceObject.cpp +++ b/src/kits/media/TimeSourceObject.cpp @@ -11,14 +11,17 @@ #include #include #include "TimeSourceObject.h" +#include "TimeSourceObjectManager.h" -TimeSourceObject::TimeSourceObject(const media_node &node) : - BMediaNode("some timesource object") +TimeSourceObject::TimeSourceObject(media_node_id id) : + BMediaNode("some timesource object", id, B_TIME_SOURCE), + BTimeSource(id) { - printf("TimeSourceObject::TimeSourceObject enter\n"); + printf("TimeSourceObject::TimeSourceObject enter, id = %ld\n", id); delete_port(fControlPort); - fControlPort = -999666; - printf("TimeSourceObject::TimeSourceObject leave\n"); + fControlPort = -999666; // must match value in BMediaNode::~BMediaNode() + ASSERT(id == fNodeID); + printf("TimeSourceObject::TimeSourceObject leave, node id %ld\n", fNodeID); } /* virtual */ status_t @@ -27,7 +30,12 @@ TimeSourceObject::SnoozeUntil( bigtime_t with_latency, bool retry_signals) { - return B_ERROR; + bigtime_t time = performance_time - with_latency; + status_t err; + do { + err = snooze_until(time, B_SYSTEM_TIMEBASE); + } while (err == B_INTERRUPTED && retry_signals); + return err; } /* virtual */ status_t @@ -39,7 +47,44 @@ TimeSourceObject::TimeSourceOp( } /* virtual */ BMediaAddOn* -TimeSourceObject::AddOn(int32 * internal_id) const +TimeSourceObject::AddOn(int32 *internal_id) const { + if (internal_id) + *internal_id = 0; return NULL; } + +/* virtual */ status_t +TimeSourceObject::DeleteHook(BMediaNode * node) +{ + printf("TimeSourceObject::DeleteHook enter\n"); + _TimeSourceObjectManager->ObjectDeleted(this); + BTimeSource::DeleteHook(node); + printf("TimeSourceObject::DeleteHook leave\n"); +} + + +SystemTimeSourceObject::SystemTimeSourceObject(media_node_id id) + : BMediaNode("System Time Source", id, B_TIME_SOURCE), + TimeSourceObject(id) +{ + printf("SystemTimeSourceObject::SystemTimeSourceObject enter, id = %ld\n", id); + + printf("SystemTimeSourceObject::SystemTimeSourceObject leave, node id %ld\n", ID()); +} + +/* virtual */ status_t +SystemTimeSourceObject::SnoozeUntil( + bigtime_t performance_time, + bigtime_t with_latency = 0, + bool retry_signals = false) +{ + return TimeSourceObject::SnoozeUntil(performance_time, with_latency, retry_signals); +} + +/* virtual */ status_t +SystemTimeSourceObject::DeleteHook(BMediaNode * node) +{ + FATAL("SystemTimeSourceObject::DeleteHook called\n"); + return B_ERROR; +} diff --git a/src/kits/media/TimeSourceObject.h b/src/kits/media/TimeSourceObject.h index cf1e652d22..c7282ce62b 100644 --- a/src/kits/media/TimeSourceObject.h +++ b/src/kits/media/TimeSourceObject.h @@ -16,20 +16,39 @@ namespace BPrivate { namespace media { class TimeSourceObject : public BTimeSource { public: - TimeSourceObject(const media_node &node); + TimeSourceObject(media_node_id id); virtual status_t SnoozeUntil( bigtime_t performance_time, bigtime_t with_latency = 0, bool retry_signals = false); + protected: virtual status_t TimeSourceOp( const time_source_op_info & op, void * _reserved); -virtual BMediaAddOn* AddOn( + virtual BMediaAddOn* AddOn( int32 * internal_id) const; + // override from BMediaNode + virtual status_t DeleteHook(BMediaNode * node); +}; + +class SystemTimeSourceObject : public TimeSourceObject +{ +public: + SystemTimeSourceObject(media_node_id id); + + virtual status_t SnoozeUntil( + bigtime_t performance_time, + bigtime_t with_latency = 0, + bool retry_signals = false); + +protected: + // override from BMediaNode + virtual status_t DeleteHook(BMediaNode * node); + }; } } using namespace BPrivate::media; diff --git a/src/kits/media/TimeSourceObjectManager.cpp b/src/kits/media/TimeSourceObjectManager.cpp index 6d7d79de90..fdf17a66d6 100644 --- a/src/kits/media/TimeSourceObjectManager.cpp +++ b/src/kits/media/TimeSourceObjectManager.cpp @@ -7,5 +7,105 @@ #include #include #include +#include #include "TimeSourceObjectManager.h" +#include "TimeSourceObject.h" +#include "debug.h" + +static BPrivate::media::TimeSourceObjectManager manager; +BPrivate::media::TimeSourceObjectManager *_TimeSourceObjectManager = &manager; + +namespace BPrivate { +namespace media { + +TimeSourceObjectManager::TimeSourceObjectManager() + : fSystemTimeSource(0), + fSystemTimeSourceID(0) +{ + fLock = new BLocker("timesource object manager locker"); + fMap = new Map; +} + + +TimeSourceObjectManager::~TimeSourceObjectManager() +{ + delete fLock; + + // force unloading all currently loaded + BTimeSource **pts; + for (fMap->Rewind(); fMap->GetNext(&pts); ) { + FATAL("Forcing release of TimeSource id %ld...\n", (*pts)->ID()); + int debugcnt = 0; + while ((*pts)->Release() != NULL) + debugcnt++; + FATAL("Forcing release of TimeSource done, released %d times\n", debugcnt); + } + + delete fMap; +} + +BTimeSource * +TimeSourceObjectManager::GetTimeSource(const media_node &node) +{ + BAutolock lock(fLock); + + printf("TimeSourceObjectManager::GetTimeSource, node id %ld\n", node.node); + + if (fSystemTimeSource == 0) { + media_node clone; + status_t rv; + rv = BMediaRoster::Roster()->GetSystemTimeSource(&clone); + if (rv != B_OK) { + FATAL("TimeSourceObjectManager::GetTimeSource, GetSystemTimeSource failed\n"); + return NULL; + } + fSystemTimeSourceID = clone.node; + fSystemTimeSource = new SystemTimeSourceObject(fSystemTimeSourceID); + ASSERT(fSystemTimeSourceID == fSystemTimeSource->ID()); + } + + if (node.node == fSystemTimeSourceID) + return dynamic_cast(fSystemTimeSource->Acquire()); + + BTimeSource **pts; + if (fMap->Get(node.node, &pts)) + return dynamic_cast((*pts)->Acquire()); + + media_node clone; + status_t rv; + + rv = BMediaRoster::Roster()->GetNodeFor(node.node, &clone); + if (rv != B_OK) { + FATAL("TimeSourceObjectManager::GetTimeSource, GetNodeFor %ld failed\n", node.node); + return NULL; + } + + BTimeSource *ts; + ts = new TimeSourceObject(clone.node); + fMap->Insert(clone.node, ts); + return ts; +} + +void +TimeSourceObjectManager::ObjectDeleted(BTimeSource *timesource) +{ + BAutolock lock(fLock); + + printf("TimeSourceObjectManager::ObjectDeleted, node id %ld\n", timesource->ID()); + + bool b; + b = fMap->Remove(timesource->ID()); + if (!b) { + FATAL("TimeSourceObjectManager::ObjectDeleted, Remove failed\n"); + } + + status_t rv; + rv = BMediaRoster::Roster()->ReleaseNode(timesource->Node()); + if (rv != B_OK) { + FATAL("TimeSourceObjectManager::ObjectDeleted, ReleaseNode failed\n"); + } +} + +}; // namespace media +}; // namespace BPrivate diff --git a/src/kits/media/TimeSourceObjectManager.h b/src/kits/media/TimeSourceObjectManager.h index 6d83ec6f9b..20a5fb50b6 100644 --- a/src/kits/media/TimeSourceObjectManager.h +++ b/src/kits/media/TimeSourceObjectManager.h @@ -6,4 +6,30 @@ #ifndef _TIME_SOURCE_OBJECT_MANAGER_H_ #define _TIME_SOURCE_OBJECT_MANAGER_H_ +#include "TMap.h" + +namespace BPrivate { +namespace media { + +class TimeSourceObjectManager +{ +public: + TimeSourceObjectManager(); + ~TimeSourceObjectManager(); + + BTimeSource *GetTimeSource(const media_node &node); + void ObjectDeleted(BTimeSource *timesource); + +private: + Map *fMap; + BLocker *fLock; + BTimeSource *fSystemTimeSource; + media_node_id fSystemTimeSourceID; +}; + +}; // namespace media +}; // namespace BPrivate + +extern BPrivate::media::TimeSourceObjectManager *_TimeSourceObjectManager; + #endif diff --git a/src/servers/media/DefaultManager.cpp b/src/servers/media/DefaultManager.cpp index a5806c2058..65454f8b0b 100644 --- a/src/servers/media/DefaultManager.cpp +++ b/src/servers/media/DefaultManager.cpp @@ -22,11 +22,13 @@ DefaultManager::~DefaultManager() status_t DefaultManager::LoadState() { + return B_OK; } status_t DefaultManager::SaveState() { + return B_OK; } status_t @@ -40,7 +42,7 @@ DefaultManager::Set(node_type type, const media_node *node, const dormant_node_i case AUDIO_OUTPUT: case AUDIO_OUTPUT_EX: case TIME_SOURCE: - return B_OK; + return B_ERROR; case SYSTEM_TIME_SOURCE: //called by the media_server's ServerApp::StartSystemTimeSource() { @@ -68,10 +70,10 @@ DefaultManager::Get(media_node_id *nodeid, char *input_name, int32 *input_id, no case AUDIO_MIXER: case AUDIO_OUTPUT: case AUDIO_OUTPUT_EX: - case TIME_SOURCE: - *nodeid = -1; - return B_OK; + *nodeid = -999; + return B_ERROR; + case TIME_SOURCE: case SYSTEM_TIME_SOURCE: *nodeid = fSystemTimeSource; return B_OK; @@ -87,6 +89,7 @@ DefaultManager::Get(media_node_id *nodeid, char *input_name, int32 *input_id, no status_t DefaultManager::Rescan() { + return B_OK; } void diff --git a/src/servers/media/NodeManager.cpp b/src/servers/media/NodeManager.cpp index f4c5edcaff..0e5a813525 100644 --- a/src/servers/media/NodeManager.cpp +++ b/src/servers/media/NodeManager.cpp @@ -208,7 +208,7 @@ NodeManager::GetClone(media_node *node, char *input_name, int32 *input_id, node_ } ASSERT(id == node->node); - FATAL("NodeManager::GetClone leave: node id %ld, node port %ld, node kind %Ld\n", node->node, node->port, node->kind); + FATAL("NodeManager::GetClone leave: node id %ld, node port %ld, node kind %#lx\n", node->node, node->port, node->kind); return B_OK; } @@ -700,7 +700,7 @@ get_node_type(node_type t) CASE(AUDIO_OUTPUT_EX) CASE(TIME_SOURCE) CASE(SYSTEM_TIME_SOURCE) - default: "unknown"; + default: return "unknown"; } }; diff --git a/src/servers/media/media_server.cpp b/src/servers/media/media_server.cpp index a64d6b6af1..76f4b4f527 100644 --- a/src/servers/media/media_server.cpp +++ b/src/servers/media/media_server.cpp @@ -14,10 +14,6 @@ #include "media_server.h" #include "debug.h" -#include "/boot/home/develop/openbeos/current/src/kits/media/SystemTimeSource.h" -#include -#include - /* * * An implementation of a new media_server for the OpenBeOS MediaKit @@ -152,21 +148,14 @@ void ServerApp::StartSystemTimeSource() { printf("StartSystemTimeSource enter\n"); - media_node node; status_t rv; - BTimeSource *source; printf("StartSystemTimeSource creating object\n"); - source = new _SysTimeSource; - - printf("StartSystemTimeSource registering\n"); - - BMediaRoster::Roster()->RegisterNode(source); - - printf("StartSystemTimeSource getting Node()\n"); - - node = source->Node(); + // register a dummy node + media_node node; + rv = gNodeManager->RegisterNode(&node.node, -1, 0, "Fake System Time Source", B_TIME_SOURCE, -1, -1); + ASSERT(rv == B_OK); printf("StartSystemTimeSource setting as default\n");