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", */
|
B_MEDIA_NEW_PARAMETER_VALUE, /* N "node", "parameter", "when", */
|
||||||
/* "value" */
|
/* "value" */
|
||||||
B_MEDIA_NODE_STOPPED, /* N "node", "when" */
|
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" */
|
/* "be:gone_count" */
|
||||||
|
B_MEDIA_SERVER_STARTED,
|
||||||
|
B_MEDIA_SERVER_QUIT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,11 @@ namespace media {
|
|||||||
namespace dataexchange {
|
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
|
// BMessage based data exchange with the media_server
|
||||||
status_t SendToServer(BMessage* msg);
|
status_t SendToServer(BMessage* msg);
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ public:
|
|||||||
|
|
||||||
BTimeSource* MakeTimeSourceObject(media_node_id timesource_id);
|
BTimeSource* MakeTimeSourceObject(media_node_id timesource_id);
|
||||||
|
|
||||||
|
status_t BuildConnections();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class BMediaRoster;
|
friend class BMediaRoster;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,6 +32,12 @@ enum {
|
|||||||
MEDIA_ADD_ON_SERVER_PLAY_MEDIA = '_TRU'
|
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
|
// Raw port based communication
|
||||||
enum {
|
enum {
|
||||||
GENERAL_PURPOSE_WAKEUP = 0, // when no action but wait termination needed
|
GENERAL_PURPOSE_WAKEUP = 0, // when no action but wait termination needed
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ namespace dataexchange {
|
|||||||
|
|
||||||
|
|
||||||
static BMessenger sMediaServerMessenger;
|
static BMessenger sMediaServerMessenger;
|
||||||
|
static BMessenger sMediaRosterMessenger;
|
||||||
static port_id sMediaServerPort;
|
static port_id sMediaServerPort;
|
||||||
static port_id sMediaAddonServerPort;
|
static port_id sMediaAddonServerPort;
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ find_media_addon_server_port()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
InitDataExchange()
|
InitServerDataExchange()
|
||||||
{
|
{
|
||||||
sMediaServerMessenger = BMessenger(B_MEDIA_SERVER_SIGNATURE);
|
sMediaServerMessenger = BMessenger(B_MEDIA_SERVER_SIGNATURE);
|
||||||
find_media_server_port();
|
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
|
//! BMessage based data exchange with the media_server
|
||||||
status_t
|
status_t
|
||||||
SendToServer(BMessage* msg)
|
SendToServer(BMessage* msg)
|
||||||
|
|||||||
@@ -59,14 +59,15 @@ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002-2006 Marcus "
|
|||||||
|
|
||||||
#include <AppMisc.h>
|
#include <AppMisc.h>
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
#include <DataExchange.h>
|
#include <DataExchange.h>
|
||||||
|
#include <debug.h>
|
||||||
#include <DormantNodeManager.h>
|
#include <DormantNodeManager.h>
|
||||||
#include <MediaRosterEx.h>
|
|
||||||
#include <MediaMisc.h>
|
#include <MediaMisc.h>
|
||||||
|
#include <MediaRosterEx.h>
|
||||||
#include <Notifications.h>
|
#include <Notifications.h>
|
||||||
#include <ServerInterface.h>
|
#include <ServerInterface.h>
|
||||||
#include <SharedBufferList.h>
|
#include <SharedBufferList.h>
|
||||||
|
#include <TList.h>
|
||||||
|
|
||||||
#include "TimeSourceObjectManager.h"
|
#include "TimeSourceObjectManager.h"
|
||||||
|
|
||||||
@@ -75,6 +76,14 @@ namespace BPrivate {
|
|||||||
namespace media {
|
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.
|
// This class is provided to ensure the BMediaRoster is quit.
|
||||||
class MediaRosterUndertaker {
|
class MediaRosterUndertaker {
|
||||||
public:
|
public:
|
||||||
@@ -101,11 +110,25 @@ BMediaRosterEx::BMediaRosterEx(status_t* _error)
|
|||||||
:
|
:
|
||||||
BMediaRoster()
|
BMediaRoster()
|
||||||
{
|
{
|
||||||
InitDataExchange();
|
|
||||||
|
|
||||||
gDormantNodeManager = new DormantNodeManager;
|
gDormantNodeManager = new DormantNodeManager;
|
||||||
gTimeSourceObjectManager = new TimeSourceObjectManager;
|
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
|
// register this application with the media server
|
||||||
server_register_app_request request;
|
server_register_app_request request;
|
||||||
server_register_app_reply reply;
|
server_register_app_reply reply;
|
||||||
@@ -115,9 +138,9 @@ BMediaRosterEx::BMediaRosterEx(status_t* _error)
|
|||||||
status_t status = QueryServer(SERVER_REGISTER_APP, &request,
|
status_t status = QueryServer(SERVER_REGISTER_APP, &request,
|
||||||
sizeof(request), &reply, sizeof(reply));
|
sizeof(request), &reply, sizeof(reply));
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
*_error = B_MEDIA_SYSTEM_FAILURE;
|
return B_MEDIA_SYSTEM_FAILURE;
|
||||||
else
|
|
||||||
*_error = B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1902,6 +1925,10 @@ BMediaRoster::StartWatching(const BMessenger & where, int32 notificationType)
|
|||||||
ERROR("BMediaRoster::StartWatching: notificationType invalid!\n");
|
ERROR("BMediaRoster::StartWatching: notificationType invalid!\n");
|
||||||
return B_BAD_VALUE;
|
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,
|
return BPrivate::media::notifications::Register(where, media_node::null,
|
||||||
notificationType);
|
notificationType);
|
||||||
}
|
}
|
||||||
@@ -3308,6 +3335,119 @@ BMediaRoster::MessageReceived(BMessage* message)
|
|||||||
return;
|
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:
|
case NODE_FINAL_RELEASE:
|
||||||
{
|
{
|
||||||
// this function is called by a BMediaNode to delete
|
// this function is called by a BMediaNode to delete
|
||||||
@@ -3338,7 +3478,14 @@ BMediaRoster::MessageReceived(BMessage* message)
|
|||||||
bool
|
bool
|
||||||
BMediaRoster::QuitRequested()
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,15 @@ Register(const BMessenger& notifyHandler, const media_node& node,
|
|||||||
int32 notification)
|
int32 notification)
|
||||||
{
|
{
|
||||||
CALLED();
|
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);
|
BMessage msg(MEDIA_SERVER_REQUEST_NOTIFICATIONS);
|
||||||
msg.AddInt32(NOTIFICATION_PARAM_WHAT, notification);
|
msg.AddInt32(NOTIFICATION_PARAM_WHAT, notification);
|
||||||
msg.AddInt32(NOTIFICATION_PARAM_TEAM, BPrivate::current_team());
|
msg.AddInt32(NOTIFICATION_PARAM_TEAM, BPrivate::current_team());
|
||||||
@@ -73,6 +82,15 @@ Unregister(const BMessenger& notifyHandler, const media_node& node,
|
|||||||
int32 notification)
|
int32 notification)
|
||||||
{
|
{
|
||||||
CALLED();
|
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);
|
BMessage msg(MEDIA_SERVER_CANCEL_NOTIFICATIONS);
|
||||||
msg.AddInt32(NOTIFICATION_PARAM_WHAT, notification);
|
msg.AddInt32(NOTIFICATION_PARAM_WHAT, notification);
|
||||||
msg.AddInt32(NOTIFICATION_PARAM_TEAM, BPrivate::current_team());
|
msg.AddInt32(NOTIFICATION_PARAM_TEAM, BPrivate::current_team());
|
||||||
@@ -295,6 +313,11 @@ IsValidNotificationRequest(bool node_specific, int32 notification)
|
|||||||
case B_MEDIA_FLAVORS_CHANGED:
|
case B_MEDIA_FLAVORS_CHANGED:
|
||||||
return true;
|
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
|
// only valid for node specific watching
|
||||||
case B_MEDIA_PARAMETER_CHANGED:
|
case B_MEDIA_PARAMETER_CHANGED:
|
||||||
case B_MEDIA_FORMAT_CHANGED:
|
case B_MEDIA_FORMAT_CHANGED:
|
||||||
|
|||||||
Reference in New Issue
Block a user