2002-10-09 03:59:43 +04:00
|
|
|
/*
|
|
|
|
* Copyright 2002, Marcus Overhagen. All rights reserved.
|
|
|
|
* Distributed under the terms of the MIT License.
|
|
|
|
*/
|
2002-09-30 04:12:11 +04:00
|
|
|
#include <OS.h>
|
2002-10-02 05:08:54 +04:00
|
|
|
#include <Locker.h>
|
2002-09-30 04:12:11 +04:00
|
|
|
#include <Message.h>
|
2002-10-02 05:08:54 +04:00
|
|
|
#include <Messenger.h>
|
|
|
|
#include <MediaNode.h>
|
|
|
|
#include <Debug.h>
|
2002-10-09 03:59:43 +04:00
|
|
|
#include "debug.h"
|
2002-10-02 20:54:53 +04:00
|
|
|
#include "NodeManager.h"
|
2002-10-02 05:08:54 +04:00
|
|
|
#include "DataExchange.h"
|
2002-10-02 16:01:37 +04:00
|
|
|
#include "Notifications.h"
|
|
|
|
#include "NotificationManager.h"
|
2002-09-30 04:12:11 +04:00
|
|
|
#include "Queue.h"
|
|
|
|
|
2002-10-02 20:54:53 +04:00
|
|
|
extern NodeManager *gNodeManager;
|
2002-09-30 04:12:11 +04:00
|
|
|
|
2002-10-02 20:54:53 +04:00
|
|
|
|
|
|
|
#define NOTIFICATION_THREAD_PRIORITY 19
|
|
|
|
#define TIMEOUT 100000
|
2002-10-02 05:08:54 +04:00
|
|
|
|
2002-10-02 16:01:37 +04:00
|
|
|
NotificationManager::NotificationManager()
|
2002-09-30 04:12:11 +04:00
|
|
|
: fNotificationQueue(new Queue),
|
2002-10-02 05:08:54 +04:00
|
|
|
fNotificationThreadId(-1),
|
2002-10-02 20:54:53 +04:00
|
|
|
fLocker(new BLocker),
|
|
|
|
fNotificationList(new List<Notification>)
|
2002-09-30 04:12:11 +04:00
|
|
|
{
|
2002-10-02 16:01:37 +04:00
|
|
|
fNotificationThreadId = spawn_thread(NotificationManager::worker_thread, "notification broadcast", NOTIFICATION_THREAD_PRIORITY, this);
|
2002-09-30 04:12:11 +04:00
|
|
|
resume_thread(fNotificationThreadId);
|
|
|
|
}
|
|
|
|
|
2002-10-02 16:01:37 +04:00
|
|
|
NotificationManager::~NotificationManager()
|
2002-09-30 04:12:11 +04:00
|
|
|
{
|
|
|
|
// properly terminate the queue and wait until the worker thread has finished
|
|
|
|
status_t dummy;
|
|
|
|
fNotificationQueue->Terminate();
|
|
|
|
wait_for_thread(fNotificationThreadId, &dummy);
|
|
|
|
delete fNotificationQueue;
|
2002-10-02 05:08:54 +04:00
|
|
|
delete fLocker;
|
2002-10-02 20:54:53 +04:00
|
|
|
delete fNotificationList;
|
2002-10-02 05:08:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-10-02 16:01:37 +04:00
|
|
|
NotificationManager::EnqueueMessage(BMessage *msg)
|
2002-10-02 05:08:54 +04:00
|
|
|
{
|
|
|
|
// queue a copy of the message to be processed later
|
|
|
|
fNotificationQueue->AddItem(new BMessage(*msg));
|
2002-09-30 04:12:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-10-02 16:01:37 +04:00
|
|
|
NotificationManager::RequestNotifications(BMessage *msg)
|
2002-09-30 04:12:11 +04:00
|
|
|
{
|
2002-10-02 05:08:54 +04:00
|
|
|
BMessenger messenger;
|
|
|
|
const media_node *node;
|
|
|
|
ssize_t nodesize;
|
|
|
|
team_id team;
|
2002-10-02 16:01:37 +04:00
|
|
|
int32 what;
|
2002-10-02 05:08:54 +04:00
|
|
|
|
|
|
|
msg->FindMessenger(NOTIFICATION_PARAM_MESSENGER, &messenger);
|
|
|
|
msg->FindInt32(NOTIFICATION_PARAM_TEAM, &team);
|
2002-10-02 16:01:37 +04:00
|
|
|
msg->FindInt32(NOTIFICATION_PARAM_WHAT, &what);
|
2002-10-02 05:08:54 +04:00
|
|
|
msg->FindData("node", B_RAW_TYPE, reinterpret_cast<const void **>(&node), &nodesize);
|
2002-10-02 20:54:53 +04:00
|
|
|
ASSERT(nodesize == sizeof(media_node));
|
|
|
|
|
|
|
|
Notification n;
|
|
|
|
n.messenger = messenger;
|
|
|
|
n.node = *node;
|
|
|
|
n.what = what;
|
|
|
|
n.team = team;
|
2002-10-09 03:59:43 +04:00
|
|
|
|
|
|
|
TRACE("NotificationManager::RequestNotifications node %ld, team %ld, what %#lx\n",node->node, team, what);
|
2002-10-02 05:08:54 +04:00
|
|
|
|
2002-10-02 20:54:53 +04:00
|
|
|
fLocker->Lock();
|
|
|
|
fNotificationList->Insert(n);
|
|
|
|
fLocker->Unlock();
|
|
|
|
|
|
|
|
// send the initial B_MEDIA_NODE_CREATED containing all existing live nodes
|
|
|
|
BMessage initmsg(B_MEDIA_NODE_CREATED);
|
|
|
|
if (B_OK == gNodeManager->GetLiveNodes(&initmsg)) {
|
|
|
|
messenger.SendMessage(&initmsg, static_cast<BHandler *>(NULL), TIMEOUT);
|
|
|
|
}
|
2002-09-30 04:12:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-10-02 16:01:37 +04:00
|
|
|
NotificationManager::CancelNotifications(BMessage *msg)
|
2002-09-30 04:12:11 +04:00
|
|
|
{
|
2002-10-02 05:08:54 +04:00
|
|
|
BMessenger messenger;
|
|
|
|
const media_node *node;
|
|
|
|
ssize_t nodesize;
|
|
|
|
team_id team;
|
2002-10-02 16:01:37 +04:00
|
|
|
int32 what;
|
2002-10-02 05:08:54 +04:00
|
|
|
|
|
|
|
msg->FindMessenger(NOTIFICATION_PARAM_MESSENGER, &messenger);
|
|
|
|
msg->FindInt32(NOTIFICATION_PARAM_TEAM, &team);
|
2002-10-02 16:01:37 +04:00
|
|
|
msg->FindInt32(NOTIFICATION_PARAM_WHAT, &what);
|
2002-10-02 05:08:54 +04:00
|
|
|
msg->FindData("node", B_RAW_TYPE, reinterpret_cast<const void **>(&node), &nodesize);
|
2002-10-02 20:54:53 +04:00
|
|
|
ASSERT(nodesize == sizeof(media_node));
|
2002-10-09 03:59:43 +04:00
|
|
|
|
|
|
|
TRACE("NotificationManager::CancelNotifications node %ld, team %ld, what %#lx\n",node->node, team, what);
|
2002-10-02 20:54:53 +04:00
|
|
|
|
|
|
|
/* if what == B_MEDIA_WILDCARD && node == media_node::null
|
|
|
|
* => delete all notifications for the matching team & messenger
|
|
|
|
* else if what != B_MEDIA_WILDCARD && node == media_node::null
|
|
|
|
* => delete all notifications for the matching what & team & messenger
|
|
|
|
* else if what == B_MEDIA_WILDCARD && node != media_node::null
|
|
|
|
* => delete all notifications for the matching team & messenger & node
|
|
|
|
* else if what != B_MEDIA_WILDCARD && node != media_node::null
|
|
|
|
* => delete all notifications for the matching what & team & messenger & node
|
|
|
|
*/
|
|
|
|
|
|
|
|
fLocker->Lock();
|
|
|
|
|
|
|
|
Notification n;
|
|
|
|
for (int32 index = 0; fNotificationList->GetAt(index, &n); index++) {
|
|
|
|
bool remove;
|
|
|
|
if (what == B_MEDIA_WILDCARD && *node == media_node::null && team == n.team && messenger == n.messenger)
|
|
|
|
remove = true;
|
|
|
|
else if (what != B_MEDIA_WILDCARD && *node == media_node::null && what == n.what && team == n.team && messenger == n.messenger)
|
|
|
|
remove = true;
|
|
|
|
else if (what == B_MEDIA_WILDCARD && *node != media_node::null && team == n.team && messenger == n.messenger && n.node == *node)
|
|
|
|
remove = true;
|
|
|
|
else if (what != B_MEDIA_WILDCARD && *node != media_node::null && what == n.what && team == n.team && messenger == n.messenger && n.node == *node)
|
|
|
|
remove = true;
|
|
|
|
else
|
|
|
|
remove = false;
|
|
|
|
if (remove) {
|
|
|
|
if (fNotificationList->Remove(index)) {
|
|
|
|
index--;
|
|
|
|
} else {
|
|
|
|
ASSERT(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-10-02 05:08:54 +04:00
|
|
|
|
2002-10-02 20:54:53 +04:00
|
|
|
fLocker->Unlock();
|
2002-09-30 04:12:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-10-02 16:01:37 +04:00
|
|
|
NotificationManager::SendNotifications(BMessage *msg)
|
2002-09-30 04:12:11 +04:00
|
|
|
{
|
2002-10-02 20:54:53 +04:00
|
|
|
const media_source *source;
|
|
|
|
const media_destination *destination;
|
|
|
|
const media_node *node;
|
|
|
|
ssize_t size;
|
|
|
|
int32 what;
|
|
|
|
|
|
|
|
msg->FindInt32(NOTIFICATION_PARAM_WHAT, &what);
|
|
|
|
msg->RemoveName(NOTIFICATION_PARAM_WHAT);
|
|
|
|
msg->what = what;
|
|
|
|
|
2002-10-09 03:59:43 +04:00
|
|
|
TRACE("NotificationManager::SendNotifications what %#lx\n", what);
|
|
|
|
|
2002-10-02 20:54:53 +04:00
|
|
|
fLocker->Lock();
|
|
|
|
|
|
|
|
Notification n;
|
|
|
|
for (int32 index = 0; fNotificationList->GetAt(index, &n); index++) {
|
|
|
|
if (n.what != B_MEDIA_WILDCARD && n.what != what)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (what) {
|
|
|
|
case B_MEDIA_NODE_CREATED:
|
|
|
|
case B_MEDIA_NODE_DELETED:
|
|
|
|
case B_MEDIA_CONNECTION_MADE:
|
|
|
|
case B_MEDIA_CONNECTION_BROKEN:
|
|
|
|
case B_MEDIA_BUFFER_CREATED:
|
|
|
|
case B_MEDIA_BUFFER_DELETED:
|
|
|
|
case B_MEDIA_TRANSPORT_STATE:
|
|
|
|
case B_MEDIA_DEFAULT_CHANGED:
|
|
|
|
case B_MEDIA_FLAVORS_CHANGED:
|
|
|
|
if (n.node != media_node::null)
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case B_MEDIA_NEW_PARAMETER_VALUE:
|
|
|
|
case B_MEDIA_PARAMETER_CHANGED:
|
|
|
|
case B_MEDIA_NODE_STOPPED:
|
|
|
|
case B_MEDIA_WEB_CHANGED:
|
|
|
|
msg->FindData("node", B_RAW_TYPE, reinterpret_cast<const void **>(&node), &size);
|
|
|
|
ASSERT(size == sizeof(media_node));
|
|
|
|
if (n.node != *node)
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case B_MEDIA_FORMAT_CHANGED:
|
|
|
|
msg->FindData("source", B_RAW_TYPE, reinterpret_cast<const void **>(&source), &size);
|
|
|
|
ASSERT(size == sizeof(media_source));
|
|
|
|
msg->FindData("destination", B_RAW_TYPE, reinterpret_cast<const void **>(&destination), &size);
|
|
|
|
ASSERT(size == sizeof(media_destination));
|
|
|
|
if (n.node.port != source->port && n.node.port != destination->port)
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2002-10-09 03:59:43 +04:00
|
|
|
TRACE("NotificationManager::SendNotifications sending\n");
|
2002-10-02 20:54:53 +04:00
|
|
|
n.messenger.SendMessage(msg, static_cast<BHandler *>(NULL), TIMEOUT);
|
|
|
|
}
|
|
|
|
|
|
|
|
fLocker->Unlock();
|
2002-09-30 04:12:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-10-02 16:01:37 +04:00
|
|
|
NotificationManager::CleanupTeam(team_id team)
|
2002-09-30 04:12:11 +04:00
|
|
|
{
|
2002-10-09 03:59:43 +04:00
|
|
|
TRACE("NotificationManager::CleanupTeam team %ld\n", team);
|
2002-10-02 20:54:53 +04:00
|
|
|
fLocker->Lock();
|
2002-09-30 04:12:11 +04:00
|
|
|
|
2002-10-02 20:54:53 +04:00
|
|
|
Notification n;
|
|
|
|
for (int32 index = 0; fNotificationList->GetAt(index, &n); index++) {
|
|
|
|
if (n.team == team) {
|
|
|
|
if (fNotificationList->Remove(index)) {
|
|
|
|
index--;
|
|
|
|
} else {
|
|
|
|
ASSERT(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fLocker->Unlock();
|
2002-09-30 04:12:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-10-02 16:01:37 +04:00
|
|
|
NotificationManager::WorkerThread()
|
2002-09-30 04:12:11 +04:00
|
|
|
{
|
|
|
|
BMessage *msg;
|
|
|
|
while (NULL != (msg = static_cast<BMessage *>(fNotificationQueue->RemoveItem()))) {
|
2002-10-02 05:08:54 +04:00
|
|
|
switch (msg->what) {
|
|
|
|
case MEDIA_SERVER_REQUEST_NOTIFICATIONS:
|
|
|
|
RequestNotifications(msg);
|
|
|
|
break;
|
|
|
|
case MEDIA_SERVER_CANCEL_NOTIFICATIONS:
|
|
|
|
CancelNotifications(msg);
|
|
|
|
break;
|
|
|
|
case MEDIA_SERVER_SEND_NOTIFICATIONS:
|
|
|
|
SendNotifications(msg);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
debugger("bad notification message\n");
|
|
|
|
}
|
2002-09-30 04:12:11 +04:00
|
|
|
delete msg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int32
|
2002-10-02 16:01:37 +04:00
|
|
|
NotificationManager::worker_thread(void *arg)
|
2002-09-30 04:12:11 +04:00
|
|
|
{
|
2002-10-02 16:01:37 +04:00
|
|
|
static_cast<NotificationManager *>(arg)->WorkerThread();
|
2002-09-30 04:12:11 +04:00
|
|
|
return 0;
|
|
|
|
}
|