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:
Dario Casalinuovo
2015-07-24 12:19:33 +02:00
parent e57acc3a99
commit 32afe10ab2
7 changed files with 217 additions and 11 deletions
+3 -1
View File
@@ -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
};
+5 -1
View File
@@ -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);
+2
View File
@@ -88,6 +88,8 @@ public:
BTimeSource* MakeTimeSourceObject(media_node_id timesource_id);
status_t BuildConnections();
private:
friend class BMediaRoster;
};
+6
View File
@@ -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
+23 -1
View File
@@ -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)
+155 -8
View File
@@ -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, &notification.what)
!= B_OK) {
TRACE("BMediaRoster MEDIA_ROSTER_REQUEST_NOTIFICATIONS can't"
"find what parameter");
return;
}
if (message->FindMessenger(NOTIFICATION_PARAM_MESSENGER,
&notification.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, &notification.what)
!= B_OK) {
TRACE("BMediaRoster MEDIA_ROSTER_CANCEL_NOTIFICATIONS can't"
"find what parameter");
return;
}
if (message->FindMessenger(NOTIFICATION_PARAM_MESSENGER,
&notification.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, &current) != 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, &current) != 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, &current) != 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;
}
+23
View File
@@ -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: