diff --git a/headers/os/media/MediaRoster.h b/headers/os/media/MediaRoster.h index 477c7966ba..78f85b56a2 100644 --- a/headers/os/media/MediaRoster.h +++ b/headers/os/media/MediaRoster.h @@ -42,7 +42,11 @@ public: // same time. // Check if the media services are running. - static bool IsRunning(); + static bool IsRunning(); + + // This functions blocks until the media services are available, + // don't abuse of it. + static status_t SyncToServices(bigtime_t timeout = -1); // Getting common instances of system nodes: status_t GetVideoInput(media_node* _node); diff --git a/headers/private/media/ServerInterface.h b/headers/private/media/ServerInterface.h index 177b18a327..8ee1fe0705 100644 --- a/headers/private/media/ServerInterface.h +++ b/headers/private/media/ServerInterface.h @@ -28,6 +28,9 @@ enum { // add_system_beep_event() MEDIA_SERVER_ADD_SYSTEM_BEEP_EVENT, + // sent by the rescan thread + MEDIA_SERVER_RESCAN_COMPLETED, + // media add-on server MEDIA_ADD_ON_SERVER_PLAY_MEDIA = '_TRU' }; @@ -370,6 +373,7 @@ struct server_register_app_request : request_data { }; struct server_register_app_reply : reply_data { + sem_id global_synchro; }; struct server_unregister_app_request : request_data { diff --git a/src/kits/media/MediaRoster.cpp b/src/kits/media/MediaRoster.cpp index 61d8509b38..1410ec0973 100644 --- a/src/kits/media/MediaRoster.cpp +++ b/src/kits/media/MediaRoster.cpp @@ -107,6 +107,7 @@ static bool sServerIsUp = false; static List sNotificationList; static BLocker sInitLocker("BMediaRoster::Roster locker"); static List sRegisteredNodes; +static sem_id sGlobalSynchro = -1; class MediaRosterUndertaker { @@ -3344,6 +3345,27 @@ BMediaRoster::IsRunning() } +status_t +BMediaRoster::SyncToServices(bigtime_t timeout) +{ + if (!IsRunning()) + return B_ERROR; + + TRACE("BMediaRoster::SyncToServer: Syncing to the media server"); + + // This sem is valid only when the server started + // but it's not ready to supply the services. + if (sGlobalSynchro > -1) + acquire_sem_etc(sGlobalSynchro, 1, B_RELATIVE_TIMEOUT, timeout); + + // TODO: Ideally this function should take into account + // the startup latencies of the system nodes and sleep + // for the resulting sum. + + return B_OK; +} + + ssize_t BMediaRoster::AudioBufferSizeFor(int32 channelCount, uint32 sampleFormat, float frameRate, bus_type busKind) @@ -3445,7 +3467,9 @@ BMediaRoster::MessageReceived(BMessage* message) // Send the notification to our subscribers if (BMediaRoster::IsRunning()) { + SyncToServices(); sServerIsUp = true; + sGlobalSynchro = -1; // Wait for media services to wake up // TODO: This should be solved so that the server // have a way to notify us when the system is really diff --git a/src/servers/media/AppManager.cpp b/src/servers/media/AppManager.cpp index 761ddef7c8..b0ae0648a4 100644 --- a/src/servers/media/AppManager.cpp +++ b/src/servers/media/AppManager.cpp @@ -50,11 +50,14 @@ AppManager::AppManager() : BLocker("media app manager") { + fGlobalSynchro = create_sem(0, "media server global synchro"); } AppManager::~AppManager() { + if (fGlobalSynchro != -1) + delete_sem(fGlobalSynchro); } @@ -67,7 +70,8 @@ AppManager::HasTeam(team_id team) status_t -AppManager::RegisterTeam(team_id team, const BMessenger& messenger) +AppManager::RegisterTeam(team_id team, const BMessenger& messenger, + sem_id* sync) { BAutolock lock(this); @@ -84,6 +88,8 @@ AppManager::RegisterTeam(team_id team, const BMessenger& messenger) return B_NO_MEMORY; } + *sync = fGlobalSynchro; + return B_OK; } @@ -150,6 +156,13 @@ AppManager::Dump() } +void +AppManager::UnlockGlobalSynchro() +{ + delete_sem(fGlobalSynchro); +} + + void AppManager::_CleanupTeam(team_id team) { diff --git a/src/servers/media/AppManager.h b/src/servers/media/AppManager.h index 0bc57fb239..5fe9df2200 100644 --- a/src/servers/media/AppManager.h +++ b/src/servers/media/AppManager.h @@ -18,7 +18,7 @@ public: ~AppManager(); status_t RegisterTeam(team_id team, - const BMessenger& messenger); + const BMessenger& messenger, sem_id* sync); status_t UnregisterTeam(team_id team); bool HasTeam(team_id team); @@ -28,6 +28,8 @@ public: void Dump(); + void UnlockGlobalSynchro(); + private: void _CleanupTeam(team_id team); @@ -35,6 +37,7 @@ private: typedef std::map AppMap; AppMap fMap; + sem_id fGlobalSynchro; }; diff --git a/src/servers/media/DefaultManager.cpp b/src/servers/media/DefaultManager.cpp index 6e00e93ca8..a598225a4f 100644 --- a/src/servers/media/DefaultManager.cpp +++ b/src/servers/media/DefaultManager.cpp @@ -16,9 +16,11 @@ #include #include -#include "DormantNodeManager.h" -#include "NodeManager.h" #include "debug.h" +#include "DormantNodeManager.h" +#include "media_server.h" +#include "NodeManager.h" + /* no locking used in this file, we assume that the caller (NodeManager) does it. */ @@ -411,6 +413,9 @@ DefaultManager::_RescanThread() add_on_server_rescan_finished_notify_command cmd; SendToAddOnServer(ADD_ON_SERVER_RESCAN_FINISHED_NOTIFY, &cmd, sizeof(cmd)); + + BMessage msg(MEDIA_SERVER_RESCAN_COMPLETED); + be_app->PostMessage(&msg); } locker.Lock(); diff --git a/src/servers/media/media_server.cpp b/src/servers/media/media_server.cpp index 9ed51d5356..369bc77675 100644 --- a/src/servers/media/media_server.cpp +++ b/src/servers/media/media_server.cpp @@ -305,7 +305,7 @@ ServerApp::_HandleMessage(int32 code, const void* data, size_t size) server_register_app_reply reply; status_t status = gAppManager->RegisterTeam(request.team, - request.messenger); + request.messenger, &reply.global_synchro); request.SendReply(status, &reply, sizeof(reply)); break; } @@ -938,6 +938,12 @@ ServerApp::MessageReceived(BMessage* msg) gMediaFilesManager->HandleAddSystemBeepEvent(msg); break; + case MEDIA_SERVER_RESCAN_COMPLETED: + { + gAppManager->UnlockGlobalSynchro(); + break; + } + case B_SOME_APP_QUIT: { BString mimeSig;