BMediaRoster: Add B_MEDIA_SERVER_STARTED and B_MEDIA_SERVER_QUIT
* This is done by watching to registrar notifications and providing a minimal service to contact the media roster in private API. The roster use this service to automatically reconnect to the media_server.
This commit is contained in:
@@ -47,8 +47,10 @@ enum {
|
||||
B_MEDIA_NEW_PARAMETER_VALUE, /* N "node", "parameter", "when", */
|
||||
/* "value" */
|
||||
B_MEDIA_NODE_STOPPED, /* N "node", "when" */
|
||||
B_MEDIA_FLAVORS_CHANGED /* "be:addon_id", "be:new_count", */
|
||||
B_MEDIA_FLAVORS_CHANGED, /* "be:addon_id", "be:new_count", */
|
||||
/* "be:gone_count" */
|
||||
B_MEDIA_SERVER_STARTED,
|
||||
B_MEDIA_SERVER_QUIT
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,11 @@ namespace media {
|
||||
namespace dataexchange {
|
||||
|
||||
|
||||
void InitDataExchange();
|
||||
void InitServerDataExchange();
|
||||
void InitRosterDataExchange(const BMessenger& rosterMessenger);
|
||||
|
||||
// BMessage based data exchange with the current BMediaRoster
|
||||
status_t SendToRoster(BMessage* msg);
|
||||
|
||||
// BMessage based data exchange with the media_server
|
||||
status_t SendToServer(BMessage* msg);
|
||||
|
||||
@@ -88,6 +88,8 @@ public:
|
||||
|
||||
BTimeSource* MakeTimeSourceObject(media_node_id timesource_id);
|
||||
|
||||
status_t BuildConnections();
|
||||
|
||||
private:
|
||||
friend class BMediaRoster;
|
||||
};
|
||||
|
||||
@@ -32,6 +32,12 @@ enum {
|
||||
MEDIA_ADD_ON_SERVER_PLAY_MEDIA = '_TRU'
|
||||
};
|
||||
|
||||
enum {
|
||||
// local media services status notification service
|
||||
MEDIA_ROSTER_REQUEST_NOTIFICATIONS = 2000,
|
||||
MEDIA_ROSTER_CANCEL_NOTIFICATIONS
|
||||
};
|
||||
|
||||
// Raw port based communication
|
||||
enum {
|
||||
GENERAL_PURPOSE_WAKEUP = 0, // when no action but wait termination needed
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace dataexchange {
|
||||
|
||||
|
||||
static BMessenger sMediaServerMessenger;
|
||||
static BMessenger sMediaRosterMessenger;
|
||||
static port_id sMediaServerPort;
|
||||
static port_id sMediaAddonServerPort;
|
||||
|
||||
@@ -58,7 +59,7 @@ find_media_addon_server_port()
|
||||
|
||||
|
||||
void
|
||||
InitDataExchange()
|
||||
InitServerDataExchange()
|
||||
{
|
||||
sMediaServerMessenger = BMessenger(B_MEDIA_SERVER_SIGNATURE);
|
||||
find_media_server_port();
|
||||
@@ -66,6 +67,27 @@ InitDataExchange()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InitRosterDataExchange(const BMessenger& rosterMessenger)
|
||||
{
|
||||
sMediaRosterMessenger = rosterMessenger;
|
||||
}
|
||||
|
||||
|
||||
//! BMessage based data exchange with the local BMediaRoster
|
||||
status_t
|
||||
SendToRoster(BMessage* msg)
|
||||
{
|
||||
status_t status = sMediaRosterMessenger.SendMessage(msg,
|
||||
static_cast<BHandler*>(NULL), TIMEOUT);
|
||||
if (status != B_OK) {
|
||||
ERROR("SendToRoster: SendMessage failed: %s\n", strerror(status));
|
||||
DEBUG_ONLY(msg->PrintToStream());
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
//! BMessage based data exchange with the media_server
|
||||
status_t
|
||||
SendToServer(BMessage* msg)
|
||||
|
||||
@@ -59,14 +59,15 @@ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002-2006 Marcus "
|
||||
|
||||
#include <AppMisc.h>
|
||||
|
||||
#include <debug.h>
|
||||
#include <DataExchange.h>
|
||||
#include <debug.h>
|
||||
#include <DormantNodeManager.h>
|
||||
#include <MediaRosterEx.h>
|
||||
#include <MediaMisc.h>
|
||||
#include <MediaRosterEx.h>
|
||||
#include <Notifications.h>
|
||||
#include <ServerInterface.h>
|
||||
#include <SharedBufferList.h>
|
||||
#include <TList.h>
|
||||
|
||||
#include "TimeSourceObjectManager.h"
|
||||
|
||||
@@ -75,6 +76,14 @@ namespace BPrivate {
|
||||
namespace media {
|
||||
|
||||
|
||||
struct RosterNotification {
|
||||
BMessenger messenger;
|
||||
int32 what;
|
||||
};
|
||||
|
||||
static bool sServerIsUp = false;
|
||||
static List<RosterNotification> sNotificationList;
|
||||
|
||||
// This class is provided to ensure the BMediaRoster is quit.
|
||||
class MediaRosterUndertaker {
|
||||
public:
|
||||
@@ -101,11 +110,25 @@ BMediaRosterEx::BMediaRosterEx(status_t* _error)
|
||||
:
|
||||
BMediaRoster()
|
||||
{
|
||||
InitDataExchange();
|
||||
|
||||
gDormantNodeManager = new DormantNodeManager;
|
||||
gTimeSourceObjectManager = new TimeSourceObjectManager;
|
||||
|
||||
*_error = BuildConnections();
|
||||
|
||||
InitRosterDataExchange(BMessenger(this, this));
|
||||
|
||||
if (be_roster->StartWatching(BMessenger(this, this),
|
||||
B_REQUEST_LAUNCHED | B_REQUEST_QUIT) != B_OK)
|
||||
*_error = B_ERROR;
|
||||
|
||||
sServerIsUp = BMediaRoster::IsRunning();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMediaRosterEx::BuildConnections()
|
||||
{
|
||||
InitServerDataExchange();
|
||||
// register this application with the media server
|
||||
server_register_app_request request;
|
||||
server_register_app_reply reply;
|
||||
@@ -115,9 +138,9 @@ BMediaRosterEx::BMediaRosterEx(status_t* _error)
|
||||
status_t status = QueryServer(SERVER_REGISTER_APP, &request,
|
||||
sizeof(request), &reply, sizeof(reply));
|
||||
if (status != B_OK)
|
||||
*_error = B_MEDIA_SYSTEM_FAILURE;
|
||||
else
|
||||
*_error = B_OK;
|
||||
return B_MEDIA_SYSTEM_FAILURE;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1902,6 +1925,10 @@ BMediaRoster::StartWatching(const BMessenger & where, int32 notificationType)
|
||||
ERROR("BMediaRoster::StartWatching: notificationType invalid!\n");
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
// NOTE: we support only explicitly B_MEDIA_SERVER_STARTED/QUIT
|
||||
// notifications. This should be cleared in documentation.
|
||||
|
||||
return BPrivate::media::notifications::Register(where, media_node::null,
|
||||
notificationType);
|
||||
}
|
||||
@@ -3308,6 +3335,119 @@ BMediaRoster::MessageReceived(BMessage* message)
|
||||
return;
|
||||
}
|
||||
|
||||
case MEDIA_ROSTER_REQUEST_NOTIFICATIONS:
|
||||
{
|
||||
RosterNotification notification;
|
||||
if (message->FindInt32(NOTIFICATION_PARAM_WHAT, ¬ification.what)
|
||||
!= B_OK) {
|
||||
TRACE("BMediaRoster MEDIA_ROSTER_REQUEST_NOTIFICATIONS can't"
|
||||
"find what parameter");
|
||||
return;
|
||||
}
|
||||
if (message->FindMessenger(NOTIFICATION_PARAM_MESSENGER,
|
||||
¬ification.messenger) != B_OK) {
|
||||
TRACE("BMediaRoster MEDIA_ROSTER_REQUEST_NOTIFICATIONS can't"
|
||||
"find messenger");
|
||||
return;
|
||||
}
|
||||
sNotificationList.Insert(notification);
|
||||
return;
|
||||
}
|
||||
|
||||
case MEDIA_ROSTER_CANCEL_NOTIFICATIONS:
|
||||
{
|
||||
RosterNotification notification;
|
||||
if (message->FindInt32(NOTIFICATION_PARAM_WHAT, ¬ification.what)
|
||||
!= B_OK) {
|
||||
TRACE("BMediaRoster MEDIA_ROSTER_CANCEL_NOTIFICATIONS can't"
|
||||
"find what parameter");
|
||||
return;
|
||||
}
|
||||
if (message->FindMessenger(NOTIFICATION_PARAM_MESSENGER,
|
||||
¬ification.messenger) != B_OK) {
|
||||
TRACE("BMediaRoster MEDIA_ROSTER_CANCEL_NOTIFICATIONS can't"
|
||||
"find messenger");
|
||||
return;
|
||||
}
|
||||
for (int32 i = 0; i < sNotificationList.CountItems(); i++) {
|
||||
RosterNotification* current;
|
||||
if (sNotificationList.Get(i, ¤t) != true)
|
||||
return;
|
||||
if (current->what == notification.what
|
||||
&& current->messenger == notification.messenger) {
|
||||
sNotificationList.Remove(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case B_SOME_APP_LAUNCHED:
|
||||
{
|
||||
BString mimeSig;
|
||||
if (message->FindString("be:signature", &mimeSig) != B_OK)
|
||||
return;
|
||||
if (mimeSig != B_MEDIA_ADDON_SERVER_SIGNATURE
|
||||
&& mimeSig != B_MEDIA_SERVER_SIGNATURE)
|
||||
return;
|
||||
|
||||
TRACE("BMediaRoster::MessageReceived media services are going up.");
|
||||
|
||||
// Send the notification to our subscribers
|
||||
if (BMediaRoster::IsRunning()) {
|
||||
sServerIsUp = true;
|
||||
// Restore our friendship with the media servers
|
||||
if (MediaRosterEx(this)->BuildConnections() != B_OK) {
|
||||
TRACE("BMediaRoster::MessageReceived can't reconnect"
|
||||
"to media_server.");
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < sNotificationList.CountItems(); i++) {
|
||||
RosterNotification* current;
|
||||
if (sNotificationList.Get(i, ¤t) != true)
|
||||
return;
|
||||
if (current->what == B_MEDIA_SERVER_STARTED) {
|
||||
if (current->messenger.SendMessage(
|
||||
B_MEDIA_SERVER_STARTED) != B_OK) {
|
||||
if(!current->messenger.IsValid())
|
||||
sNotificationList.Remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case B_SOME_APP_QUIT:
|
||||
{
|
||||
BString mimeSig;
|
||||
if (message->FindString("be:signature", &mimeSig) != B_OK)
|
||||
return;
|
||||
if (mimeSig != B_MEDIA_ADDON_SERVER_SIGNATURE
|
||||
&& mimeSig != B_MEDIA_SERVER_SIGNATURE)
|
||||
return;
|
||||
|
||||
TRACE("BMediaRoster::MessageReceived media services are down.");
|
||||
|
||||
// Send the notification to our subscribers
|
||||
if (!BMediaRoster::IsRunning() && sServerIsUp == true) {
|
||||
sServerIsUp = false;
|
||||
for (int32 i = 0; i < sNotificationList.CountItems(); i++) {
|
||||
RosterNotification* current;
|
||||
if (sNotificationList.Get(i, ¤t) != true)
|
||||
return;
|
||||
if (current->what == B_MEDIA_SERVER_QUIT) {
|
||||
if (current->messenger.SendMessage(
|
||||
B_MEDIA_SERVER_QUIT) != B_OK) {
|
||||
if(!current->messenger.IsValid())
|
||||
sNotificationList.Remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case NODE_FINAL_RELEASE:
|
||||
{
|
||||
// this function is called by a BMediaNode to delete
|
||||
@@ -3338,7 +3478,14 @@ BMediaRoster::MessageReceived(BMessage* message)
|
||||
bool
|
||||
BMediaRoster::QuitRequested()
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
CALLED();
|
||||
|
||||
if (be_roster->StopWatching(BMessenger(this, this)) != B_OK)
|
||||
TRACE("Can't unregister roster notifications");
|
||||
|
||||
if (sNotificationList.CountItems() != 0)
|
||||
sNotificationList.MakeEmpty();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,15 @@ Register(const BMessenger& notifyHandler, const media_node& node,
|
||||
int32 notification)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
if (notification == B_MEDIA_SERVER_STARTED
|
||||
|| notification == B_MEDIA_SERVER_QUIT) {
|
||||
BMessage msg(MEDIA_ROSTER_REQUEST_NOTIFICATIONS);
|
||||
msg.AddInt32(NOTIFICATION_PARAM_WHAT, notification);
|
||||
msg.AddMessenger(NOTIFICATION_PARAM_MESSENGER, notifyHandler);
|
||||
return BPrivate::media::dataexchange::SendToRoster(&msg);
|
||||
}
|
||||
|
||||
BMessage msg(MEDIA_SERVER_REQUEST_NOTIFICATIONS);
|
||||
msg.AddInt32(NOTIFICATION_PARAM_WHAT, notification);
|
||||
msg.AddInt32(NOTIFICATION_PARAM_TEAM, BPrivate::current_team());
|
||||
@@ -73,6 +82,15 @@ Unregister(const BMessenger& notifyHandler, const media_node& node,
|
||||
int32 notification)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
if (notification == B_MEDIA_SERVER_STARTED
|
||||
|| notification == B_MEDIA_SERVER_QUIT) {
|
||||
BMessage msg(MEDIA_ROSTER_CANCEL_NOTIFICATIONS);
|
||||
msg.AddInt32(NOTIFICATION_PARAM_WHAT, notification);
|
||||
msg.AddMessenger(NOTIFICATION_PARAM_MESSENGER, notifyHandler);
|
||||
return BPrivate::media::dataexchange::SendToRoster(&msg);
|
||||
}
|
||||
|
||||
BMessage msg(MEDIA_SERVER_CANCEL_NOTIFICATIONS);
|
||||
msg.AddInt32(NOTIFICATION_PARAM_WHAT, notification);
|
||||
msg.AddInt32(NOTIFICATION_PARAM_TEAM, BPrivate::current_team());
|
||||
@@ -295,6 +313,11 @@ IsValidNotificationRequest(bool node_specific, int32 notification)
|
||||
case B_MEDIA_FLAVORS_CHANGED:
|
||||
return true;
|
||||
|
||||
// invalid if we watch for a specific node
|
||||
case B_MEDIA_SERVER_STARTED:
|
||||
case B_MEDIA_SERVER_QUIT:
|
||||
return !node_specific;
|
||||
|
||||
// only valid for node specific watching
|
||||
case B_MEDIA_PARAMETER_CHANGED:
|
||||
case B_MEDIA_FORMAT_CHANGED:
|
||||
|
||||
Reference in New Issue
Block a user