diff --git a/src/servers/media/DefaultManager.cpp b/src/servers/media/DefaultManager.cpp new file mode 100644 index 0000000000..a5806c2058 --- /dev/null +++ b/src/servers/media/DefaultManager.cpp @@ -0,0 +1,100 @@ +/* + * Copyright 2002, Marcus Overhagen. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#include +#include +#include "DefaultManager.h" +#include "debug.h" + +/* no locking used in this file, we assume that the caller (NodeManager) does it. + */ + +DefaultManager::DefaultManager() + : fSystemTimeSource(-1) +{ +} + +DefaultManager::~DefaultManager() +{ +} + +status_t +DefaultManager::LoadState() +{ +} + +status_t +DefaultManager::SaveState() +{ +} + +status_t +DefaultManager::Set(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input) +{ + switch (type) { + case VIDEO_INPUT: + case AUDIO_INPUT: + case VIDEO_OUTPUT: + case AUDIO_MIXER: + case AUDIO_OUTPUT: + case AUDIO_OUTPUT_EX: + case TIME_SOURCE: + return B_OK; + + case SYSTEM_TIME_SOURCE: //called by the media_server's ServerApp::StartSystemTimeSource() + { + ASSERT(fSystemTimeSource == -1); + ASSERT(node != 0); + fSystemTimeSource = node->node; + return B_OK; + } + + default: + { + FATAL("DefaultManager::Set Error: called with unknown type %d\n", type); + return B_ERROR; + } + } +} + +status_t +DefaultManager::Get(media_node_id *nodeid, char *input_name, int32 *input_id, node_type type) +{ + switch (type) { + case VIDEO_INPUT: + case AUDIO_INPUT: + case VIDEO_OUTPUT: + case AUDIO_MIXER: + case AUDIO_OUTPUT: + case AUDIO_OUTPUT_EX: + case TIME_SOURCE: + *nodeid = -1; + return B_OK; + + case SYSTEM_TIME_SOURCE: + *nodeid = fSystemTimeSource; + return B_OK; + + default: + { + FATAL("DefaultManager::Get Error: called with unknown type %d\n", type); + return B_ERROR; + } + } +} + +status_t +DefaultManager::Rescan() +{ +} + +void +DefaultManager::Dump() +{ +} + +void +DefaultManager::CleanupTeam(team_id team) +{ +} diff --git a/src/servers/media/DefaultManager.h b/src/servers/media/DefaultManager.h new file mode 100644 index 0000000000..d2978f9c3a --- /dev/null +++ b/src/servers/media/DefaultManager.h @@ -0,0 +1,29 @@ +/* + * Copyright 2002, Marcus Overhagen. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#include "TList.h" +#include "TMap.h" +#include "TStack.h" +#include "DataExchange.h" + +class DefaultManager +{ +public: + DefaultManager(); + ~DefaultManager(); + + status_t LoadState(); + status_t SaveState(); + + status_t Set(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input); + status_t Get(media_node_id *nodeid, char *input_name, int32 *input_id, node_type type); + status_t Rescan(); + + void Dump(); + + void CleanupTeam(team_id team); + +private: + media_node_id fSystemTimeSource; +}; diff --git a/src/servers/media/Jamfile b/src/servers/media/Jamfile index fd2f0d4291..1960a2fb2f 100644 --- a/src/servers/media/Jamfile +++ b/src/servers/media/Jamfile @@ -8,6 +8,7 @@ Server media_server : media_server.cpp AppManager.cpp BufferManager.cpp + DefaultManager.cpp NodeManager.cpp NotificationManager.cpp Queue.cpp diff --git a/src/servers/media/NodeManager.cpp b/src/servers/media/NodeManager.cpp index bd9f0ac1cd..f4c5edcaff 100644 --- a/src/servers/media/NodeManager.cpp +++ b/src/servers/media/NodeManager.cpp @@ -14,6 +14,8 @@ #include "debug.h" #include "NodeManager.h" +const char *get_node_type(node_type t); + NodeManager::NodeManager() : nextaddonid(1), nextnodeid(1) @@ -22,6 +24,7 @@ NodeManager::NodeManager() : fDormantFlavorList = new List; fAddonPathMap = new Map; fRegisteredNodeMap = new Map; + fDefaultManager = new DefaultManager; } @@ -31,6 +34,7 @@ NodeManager::~NodeManager() delete fDormantFlavorList; delete fAddonPathMap; delete fRegisteredNodeMap; + delete fDefaultManager; } @@ -175,13 +179,38 @@ NodeManager::GetCloneForId(media_node *node, media_node_id nodeid, team_id team) } +/* This function locates the default "node" for the requested "type" and returnes a clone. + * If the requested type is AUDIO_OUTPUT_EX, also "input_name" and "input_id" need to be set and returned, + * as this is required by BMediaRoster::GetAudioOutput(media_node *out_node, int32 *out_input_id, BString *out_input_name) + */ status_t NodeManager::GetClone(media_node *node, char *input_name, int32 *input_id, node_type type, team_id team) { BAutolock lock(fLocker); - FATAL("!!! NodeManager::GetClone not implemented\n"); - *node = media_node::null; - return B_ERROR; + status_t status; + media_node_id id; + + FATAL("NodeManager::GetClone enter: team %ld, type %d (%s)\n", team, type, get_node_type(type)); + + status = GetDefaultNode(&id, input_name, input_id, type); + if (status != B_OK) { + FATAL("NodeManager::GetClone Error: couldn't GetDefaultNode, team %ld, type %d (%s)\n", team, type, get_node_type(type)); + *node = media_node::null; + return status; + } + ASSERT(id > 0); + + status = GetCloneForId(node, id, team); + if (status != B_OK) { + FATAL("NodeManager::GetClone Error: couldn't GetCloneForId, id %ld, team %ld, type %d (%s)\n", id, team, type, get_node_type(type)); + *node = media_node::null; + return status; + } + ASSERT(id == node->node); + + FATAL("NodeManager::GetClone leave: node id %ld, node port %ld, node kind %Ld\n", node->node, node->port, node->kind); + + return B_OK; } @@ -560,11 +589,47 @@ NodeManager::GetDormantFlavorInfoFor(media_addon_id addon, return B_ERROR; } +status_t +NodeManager::SetDefaultNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input) +{ + BAutolock lock(fLocker); + return fDefaultManager->Set(type, node, info, input); +} + +status_t +NodeManager::GetDefaultNode(media_node_id *nodeid, char *input_name, int32 *input_id, node_type type) +{ + BAutolock lock(fLocker); + return fDefaultManager->Get(nodeid, input_name, input_id, type); +} + +status_t +NodeManager::RescanDefaultNodes() +{ + BAutolock lock(fLocker); + return fDefaultManager->Rescan(); +} + void NodeManager::CleanupTeam(team_id team) { BAutolock lock(fLocker); FATAL("NodeManager::CleanupTeam: should cleanup team %ld\n", team); + fDefaultManager->CleanupTeam(team); +} + +status_t +NodeManager::LoadState() +{ + BAutolock lock(fLocker); + return fDefaultManager->LoadState(); +} + +status_t +NodeManager::SaveState() +{ + BAutolock lock(fLocker); + return fDefaultManager->SaveState(); } void @@ -619,4 +684,23 @@ NodeManager::Dump() printf(" flavor-info \"%s\"\n", dfi->info); } printf("NodeManager: list end\n"); + fDefaultManager->Dump(); } + +const char * +get_node_type(node_type t) +{ + switch (t) { + #define CASE(c) case c: return #c; + CASE(VIDEO_INPUT) + CASE(AUDIO_INPUT) + CASE(VIDEO_OUTPUT) + CASE(AUDIO_MIXER) + CASE(AUDIO_OUTPUT) + CASE(AUDIO_OUTPUT_EX) + CASE(TIME_SOURCE) + CASE(SYSTEM_TIME_SOURCE) + default: "unknown"; + } +}; + diff --git a/src/servers/media/NodeManager.h b/src/servers/media/NodeManager.h index 296f172dc1..a17d1ca865 100644 --- a/src/servers/media/NodeManager.h +++ b/src/servers/media/NodeManager.h @@ -6,6 +6,7 @@ #include "TMap.h" #include "TStack.h" #include "DataExchange.h" +#include "DefaultManager.h" struct registered_node { @@ -47,7 +48,12 @@ public: void Dump(); + /* Management of system wide default nodes */ + status_t SetDefaultNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input); + status_t GetDefaultNode(media_node_id *nodeid, char *input_name, int32 *input_id, node_type type); + status_t RescanDefaultNodes(); + /* Management of live nodes */ status_t RegisterNode(media_node_id *nodeid, media_addon_id addon_id, int32 addon_flavor_id, const char *name, uint64 kinds, port_id port, team_id team); status_t UnregisterNode(media_addon_id *addon_id, media_node_id nodeid, team_id team); status_t GetCloneForId(media_node *node, media_node_id nodeid, team_id team); @@ -96,4 +102,5 @@ private: List *fDormantFlavorList; Map *fAddonPathMap; Map *fRegisteredNodeMap; + DefaultManager *fDefaultManager; }; diff --git a/src/servers/media/media_server.cpp b/src/servers/media/media_server.cpp index 0d053f9497..a64d6b6af1 100644 --- a/src/servers/media/media_server.cpp +++ b/src/servers/media/media_server.cpp @@ -14,6 +14,10 @@ #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 @@ -49,6 +53,7 @@ public: void HandleMessage(int32 code, void *data, size_t size); void ArgvReceived(int32 argc, char **argv); static int32 controlthread(void *arg); + void StartSystemTimeSource(); /* functionality not yet implemented 00014a00 T _ServerApp::_ServerApp(void) @@ -85,9 +90,6 @@ ServerApp::ServerApp() : BApplication(NEW_MEDIA_SERVER_SIGNATURE), fLocker(new BLocker("media server locker")) { - //load volume settings from config file - //mVolumeLeft = ???; - //mVolumeRight = ???; gNotificationManager = new NotificationManager; gBufferManager = new BufferManager; @@ -97,7 +99,9 @@ ServerApp::ServerApp() control_port = create_port(64,"media_server port"); control_thread = spawn_thread(controlthread, "media_server control", 105, this); resume_thread(control_thread); - + + StartSystemTimeSource(); + gNodeManager->LoadState(); gAppManager->StartAddonServer(); } @@ -139,16 +143,51 @@ bool ServerApp::QuitRequested() { TRACE("ServerApp::QuitRequested()\n"); + gNodeManager->SaveState(); gAppManager->TerminateAddonServer(); return true; } +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(); + + printf("StartSystemTimeSource setting as default\n"); + + rv = gNodeManager->SetDefaultNode(SYSTEM_TIME_SOURCE, &node, NULL, NULL); + ASSERT(rv == B_OK); + + printf("StartSystemTimeSource leave\n"); +} + void ServerApp::HandleMessage(int32 code, void *data, size_t size) { status_t rv; INFO("ServerApp::HandleMessage %#lx\n", code); switch (code) { + case SERVER_RESCAN_DEFAULTS: + { + gNodeManager->RescanDefaultNodes(); + break; + } + case SERVER_REGISTER_ADDONSERVER: { const server_register_addonserver_request *request = reinterpret_cast(data); @@ -336,9 +375,8 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) { const server_set_node_request *request = reinterpret_cast(data); server_set_node_reply reply; - // XXX do something here - debugger("SERVER_SET_NODE seems to be needed\n"); - request->SendReply(B_OK, &reply, sizeof(reply)); + rv = gNodeManager->SetDefaultNode(request->type, request->use_node ? &request->node : NULL, request->use_dni ? &request->dni : NULL, request->use_input ? &request->input : NULL); + request->SendReply(rv, &reply, sizeof(reply)); break; } diff --git a/src/servers/media_addon/main.cpp b/src/servers/media_addon/main.cpp index 5fdbd9e73a..3750eb468a 100644 --- a/src/servers/media_addon/main.cpp +++ b/src/servers/media_addon/main.cpp @@ -49,10 +49,12 @@ public: ino_t DirNodeUser; port_id control_port; thread_id control_thread; + bool fStartup; }; MediaAddonServer::MediaAddonServer(const char *sig) : - BApplication(sig) + BApplication(sig), + fStartup(true) { mediaroster = BMediaRoster::Roster(); filemap = new Map; @@ -140,6 +142,8 @@ MediaAddonServer::ReadyToRun() return; } + fStartup = true; + // load dormant media nodes node_ref nref; BEntry e("/boot/beos/system/add-ons/media"); @@ -155,6 +159,11 @@ MediaAddonServer::ReadyToRun() e2.GetNodeRef(&nref); DirNodeUser = nref.node; WatchDir(&e2); + + fStartup = false; + + server_rescan_defaults_command cmd; + SendToServer(SERVER_RESCAN_DEFAULTS, &cmd, sizeof(cmd)); } void @@ -318,6 +327,12 @@ flavor 0: return; } */ + + if (!fStartup) { + server_rescan_defaults_command cmd; + SendToServer(SERVER_RESCAN_DEFAULTS, &cmd, sizeof(cmd)); + } + _DormantNodeManager->PutAddon(id); }