shutdown_media_server: Finalize rework of synchronization
* When the user isn't requesting a custom notification, it will be a BMediaRoster job to do it. * Reintroduce BMediaRoster::SyncToServices, this time based on local message passing rather than a global semaphore. * SyncToServices is used in launch_media_server to make the process more launch_daemon safe and faster in the average case. * It was an error to add notifications in the media_server. * Fixes #12717.
This commit is contained in:
parent
721adc92d3
commit
76889670db
@ -44,6 +44,10 @@ public:
|
|||||||
// Check if the media services are running.
|
// Check if the media services are running.
|
||||||
static bool IsRunning();
|
static bool IsRunning();
|
||||||
|
|
||||||
|
// Wait until the media_server is running or the specified timeout
|
||||||
|
// is reached.
|
||||||
|
status_t SyncToServices(bigtime_t timeout);
|
||||||
|
|
||||||
// Getting common instances of system nodes:
|
// Getting common instances of system nodes:
|
||||||
status_t GetVideoInput(media_node* _node);
|
status_t GetVideoInput(media_node* _node);
|
||||||
status_t GetAudioInput(media_node* _node);
|
status_t GetAudioInput(media_node* _node);
|
||||||
|
@ -95,7 +95,13 @@ public:
|
|||||||
void RegisterLocalNode(BMediaNode* node);
|
void RegisterLocalNode(BMediaNode* node);
|
||||||
void UnregisterLocalNode(BMediaNode* node);
|
void UnregisterLocalNode(BMediaNode* node);
|
||||||
|
|
||||||
|
void EnableLaunchNotification(bool enable,
|
||||||
|
bool autoExit);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool fLaunchNotification;
|
||||||
|
bool fAutoExit;
|
||||||
|
|
||||||
friend class BMediaRoster;
|
friend class BMediaRoster;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,7 +40,10 @@ enum {
|
|||||||
enum {
|
enum {
|
||||||
// local media services status notification service
|
// local media services status notification service
|
||||||
MEDIA_ROSTER_REQUEST_NOTIFICATIONS = 2000,
|
MEDIA_ROSTER_REQUEST_NOTIFICATIONS = 2000,
|
||||||
MEDIA_ROSTER_CANCEL_NOTIFICATIONS
|
MEDIA_ROSTER_CANCEL_NOTIFICATIONS,
|
||||||
|
|
||||||
|
// used to sync with media services startup
|
||||||
|
MEDIA_ROSTER_REGISTER_SYNC
|
||||||
};
|
};
|
||||||
|
|
||||||
// Raw port based communication
|
// Raw port based communication
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "DataExchange.h"
|
#include "DataExchange.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "MediaMisc.h"
|
#include "MediaMisc.h"
|
||||||
|
#include "MediaRosterEx.h"
|
||||||
|
|
||||||
|
|
||||||
#define META_DATA_MAX_SIZE (16 << 20)
|
#define META_DATA_MAX_SIZE (16 << 20)
|
||||||
@ -1301,6 +1302,15 @@ shutdown_media_server(bigtime_t timeout,
|
|||||||
status_t err;
|
status_t err;
|
||||||
bool shutdown = false;
|
bool shutdown = false;
|
||||||
|
|
||||||
|
BMediaRoster* roster = BMediaRoster::Roster();
|
||||||
|
if (roster == NULL)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
if (progress == NULL && roster->Lock()) {
|
||||||
|
MediaRosterEx(roster)->EnableLaunchNotification(true, true);
|
||||||
|
roster->Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
if ((err = msg.AddBool("be:_user_request", true)) != B_OK)
|
if ((err = msg.AddBool("be:_user_request", true)) != B_OK)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -1323,8 +1333,8 @@ shutdown_media_server(bigtime_t timeout,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
shutdown = false;
|
|
||||||
if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
|
if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
|
||||||
|
shutdown = false;
|
||||||
BMessenger messenger(B_MEDIA_ADDON_SERVER_SIGNATURE);
|
BMessenger messenger(B_MEDIA_ADDON_SERVER_SIGNATURE);
|
||||||
progress_shutdown(40, progress, cookie);
|
progress_shutdown(40, progress, cookie);
|
||||||
|
|
||||||
@ -1391,41 +1401,49 @@ launch_media_server(bigtime_t timeout,
|
|||||||
if (BMediaRoster::IsRunning())
|
if (BMediaRoster::IsRunning())
|
||||||
return B_ALREADY_RUNNING;
|
return B_ALREADY_RUNNING;
|
||||||
|
|
||||||
|
status_t err = B_MEDIA_SYSTEM_FAILURE;
|
||||||
|
BMediaRoster* roster = BMediaRoster::Roster(&err);
|
||||||
|
if (roster == NULL || err != B_OK)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (progress == NULL && roster->Lock()) {
|
||||||
|
MediaRosterEx(roster)->EnableLaunchNotification(true, true);
|
||||||
|
roster->Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
// The media_server crashed
|
// The media_server crashed
|
||||||
if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
|
if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
|
||||||
progress_startup(10, progress, cookie);
|
progress_startup(10, progress, cookie);
|
||||||
kill_team(be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE));
|
kill_team(be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE));
|
||||||
snooze(1000000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The media_addon_server crashed
|
// The media_addon_server crashed
|
||||||
if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) {
|
if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) {
|
||||||
progress_startup(20, progress, cookie);
|
progress_startup(20, progress, cookie);
|
||||||
kill_team(be_roster->TeamFor(B_MEDIA_SERVER_SIGNATURE));
|
kill_team(be_roster->TeamFor(B_MEDIA_SERVER_SIGNATURE));
|
||||||
snooze(1000000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t err = be_roster->Launch(B_MEDIA_SERVER_SIGNATURE);
|
progress_startup(50, progress, cookie);
|
||||||
if (err != B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = B_MEDIA_SYSTEM_FAILURE;
|
err = roster->SyncToServices(2000000);
|
||||||
for (int i = 0; i < 15; i++) {
|
if (err != B_OK) {
|
||||||
snooze(2000000);
|
// At this point, it might be that the launch_daemon isn't
|
||||||
|
// restarting us, then we'll attempt at launching the server
|
||||||
|
// ourselves.
|
||||||
|
status_t err = be_roster->Launch(B_MEDIA_SERVER_SIGNATURE);
|
||||||
|
if (err != B_OK)
|
||||||
|
return err;
|
||||||
|
|
||||||
BMessage msg(1); // this is a hack
|
if (roster->SyncToServices(2000000) != B_OK)
|
||||||
BMessage reply;
|
err = B_MEDIA_SYSTEM_FAILURE;
|
||||||
BMessenger messenger(B_MEDIA_ADDON_SERVER_SIGNATURE);
|
|
||||||
|
|
||||||
if (messenger.IsValid()) {
|
|
||||||
messenger.SendMessage(&msg, &reply, 2000000, 2000000);
|
|
||||||
err = B_OK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err != B_OK)
|
if (err != B_OK)
|
||||||
progress_startup(90, progress, cookie);
|
progress_startup(90, progress, cookie);
|
||||||
|
else if (progress != NULL) {
|
||||||
|
progress_startup(100, progress, cookie);
|
||||||
|
err = B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,11 @@ struct RosterNotification {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct SyncedMessage {
|
||||||
|
BMessage* message;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct LocalNode {
|
struct LocalNode {
|
||||||
LocalNode(BMediaNode* local_node)
|
LocalNode(BMediaNode* local_node)
|
||||||
:
|
:
|
||||||
@ -107,6 +112,7 @@ static bool sServerIsUp = false;
|
|||||||
static List<RosterNotification> sNotificationList;
|
static List<RosterNotification> sNotificationList;
|
||||||
static BLocker sInitLocker("BMediaRoster::Roster locker");
|
static BLocker sInitLocker("BMediaRoster::Roster locker");
|
||||||
static List<LocalNode> sRegisteredNodes;
|
static List<LocalNode> sRegisteredNodes;
|
||||||
|
static List<SyncedMessage> sSyncedMessages;
|
||||||
|
|
||||||
|
|
||||||
class MediaRosterUndertaker {
|
class MediaRosterUndertaker {
|
||||||
@ -148,7 +154,9 @@ using namespace BPrivate::media;
|
|||||||
|
|
||||||
BMediaRosterEx::BMediaRosterEx(status_t* _error)
|
BMediaRosterEx::BMediaRosterEx(status_t* _error)
|
||||||
:
|
:
|
||||||
BMediaRoster()
|
BMediaRoster(),
|
||||||
|
fLaunchNotification(false),
|
||||||
|
fAutoExit(false)
|
||||||
{
|
{
|
||||||
gDormantNodeManager = new DormantNodeManager();
|
gDormantNodeManager = new DormantNodeManager();
|
||||||
gTimeSourceObjectManager = new TimeSourceObjectManager();
|
gTimeSourceObjectManager = new TimeSourceObjectManager();
|
||||||
@ -230,6 +238,17 @@ BMediaRosterEx::UnregisterLocalNode(BMediaNode* node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMediaRosterEx::EnableLaunchNotification(bool enable, bool autoExit)
|
||||||
|
{
|
||||||
|
// NOTE: in theory, we should personalize it depending on each
|
||||||
|
// request, but we are using it just in launch/shutdown_media_server,
|
||||||
|
// so we are enough safe to don't care about that.
|
||||||
|
fLaunchNotification = enable;
|
||||||
|
fAutoExit = autoExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMediaRosterEx::SaveNodeConfiguration(BMediaNode* node)
|
BMediaRosterEx::SaveNodeConfiguration(BMediaNode* node)
|
||||||
{
|
{
|
||||||
@ -3344,6 +3363,26 @@ BMediaRoster::IsRunning()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMediaRoster::SyncToServices(bigtime_t timeout)
|
||||||
|
{
|
||||||
|
BMessenger messenger(this);
|
||||||
|
BMessage msg(MEDIA_ROSTER_REGISTER_SYNC);
|
||||||
|
BMessage reply;
|
||||||
|
|
||||||
|
if (!messenger.IsValid())
|
||||||
|
return B_MEDIA_SYSTEM_FAILURE;
|
||||||
|
|
||||||
|
status_t ret = messenger.SendMessage(&msg, &reply, timeout, timeout);
|
||||||
|
if (ret == B_TIMED_OUT || reply.what == B_NO_REPLY)
|
||||||
|
return B_TIMED_OUT;
|
||||||
|
else if (ret != B_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
BMediaRoster::AudioBufferSizeFor(int32 channelCount, uint32 sampleFormat,
|
BMediaRoster::AudioBufferSizeFor(int32 channelCount, uint32 sampleFormat,
|
||||||
float frameRate, bus_type busKind)
|
float frameRate, bus_type busKind)
|
||||||
@ -3432,6 +3471,20 @@ BMediaRoster::MessageReceived(BMessage* message)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MEDIA_ROSTER_REGISTER_SYNC:
|
||||||
|
{
|
||||||
|
BMessage reply;
|
||||||
|
if (sServerIsUp)
|
||||||
|
message->SendReply(&reply);
|
||||||
|
else {
|
||||||
|
DetachCurrentMessage();
|
||||||
|
SyncedMessage msg;
|
||||||
|
msg.message = message;
|
||||||
|
sSyncedMessages.Insert(msg);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case B_SOME_APP_LAUNCHED:
|
case B_SOME_APP_LAUNCHED:
|
||||||
{
|
{
|
||||||
BString mimeSig;
|
BString mimeSig;
|
||||||
@ -3493,6 +3546,22 @@ BMediaRoster::MessageReceived(BMessage* message)
|
|||||||
TRACE("BMediaRoster::MessageReceived media services are"
|
TRACE("BMediaRoster::MessageReceived media services are"
|
||||||
" finally up.");
|
" finally up.");
|
||||||
|
|
||||||
|
if (MediaRosterEx(this)->fLaunchNotification) {
|
||||||
|
progress_startup(100, NULL, NULL);
|
||||||
|
if (MediaRosterEx(this)->fAutoExit)
|
||||||
|
MediaRosterEx(this)->fLaunchNotification = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BMessage reply;
|
||||||
|
for (int32 i = 0; i < sSyncedMessages.CountItems(); i++) {
|
||||||
|
SyncedMessage* msg;
|
||||||
|
if (sSyncedMessages.Get(i, &msg) != true)
|
||||||
|
return;
|
||||||
|
msg->message->SendReply(&reply);
|
||||||
|
delete msg->message;
|
||||||
|
sSyncedMessages.Remove(i);
|
||||||
|
}
|
||||||
|
|
||||||
// Send the notification to our subscribers
|
// Send the notification to our subscribers
|
||||||
for (int32 i = 0; i < sNotificationList.CountItems(); i++) {
|
for (int32 i = 0; i < sNotificationList.CountItems(); i++) {
|
||||||
RosterNotification* current;
|
RosterNotification* current;
|
||||||
@ -3506,6 +3575,7 @@ BMediaRoster::MessageReceived(BMessage* message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case NODE_FINAL_RELEASE:
|
case NODE_FINAL_RELEASE:
|
||||||
|
@ -143,8 +143,6 @@ ServerApp::ReadyToRun()
|
|||||||
{
|
{
|
||||||
gNodeManager->LoadState();
|
gNodeManager->LoadState();
|
||||||
|
|
||||||
progress_startup(50, NULL, NULL);
|
|
||||||
|
|
||||||
// make sure any previous media_addon_server is gone
|
// make sure any previous media_addon_server is gone
|
||||||
_QuitAddOnServer();
|
_QuitAddOnServer();
|
||||||
// and start a new one
|
// and start a new one
|
||||||
@ -941,11 +939,8 @@ ServerApp::MessageReceived(BMessage* msg)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MEDIA_SERVER_RESCAN_COMPLETED:
|
case MEDIA_SERVER_RESCAN_COMPLETED:
|
||||||
{
|
|
||||||
gAppManager->NotifyRosters();
|
gAppManager->NotifyRosters();
|
||||||
progress_startup(100, NULL, NULL);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case B_SOME_APP_QUIT:
|
case B_SOME_APP_QUIT:
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user