Added automatic loading of physical input and output nodes.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3320 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -109,7 +109,7 @@ virtual status_t GetConfigurationFor(
|
|||||||
BMessage * into_message);
|
BMessage * into_message);
|
||||||
virtual bool WantsAutoStart();
|
virtual bool WantsAutoStart();
|
||||||
virtual status_t AutoStart(
|
virtual status_t AutoStart(
|
||||||
int in_count,
|
int in_index,
|
||||||
BMediaNode ** out_node,
|
BMediaNode ** out_node,
|
||||||
int32 * out_internal_id,
|
int32 * out_internal_id,
|
||||||
bool * out_has_more);
|
bool * out_has_more);
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ enum {
|
|||||||
NODE_SET_TIMESOURCE,
|
NODE_SET_TIMESOURCE,
|
||||||
NODE_REQUEST_COMPLETED,
|
NODE_REQUEST_COMPLETED,
|
||||||
NODE_FINAL_RELEASE,
|
NODE_FINAL_RELEASE,
|
||||||
|
NODE_PUBLISH_CONNECTIONS,
|
||||||
|
|
||||||
NODE_MESSAGE_END,
|
NODE_MESSAGE_END,
|
||||||
CONSUMER_MESSAGE_START = 0x300,
|
CONSUMER_MESSAGE_START = 0x300,
|
||||||
|
|||||||
@@ -21,7 +21,11 @@
|
|||||||
#define SYSTEM_TIMESOURCE_CONTROL_PORT -666
|
#define SYSTEM_TIMESOURCE_CONTROL_PORT -666
|
||||||
#define IS_SYSTEM_TIMESOURCE(_node) ((_node).node > 0 && (_node).port == SYSTEM_TIMESOURCE_CONTROL_PORT)
|
#define IS_SYSTEM_TIMESOURCE(_node) ((_node).node > 0 && (_node).port == SYSTEM_TIMESOURCE_CONTROL_PORT)
|
||||||
|
|
||||||
#define NODE_KIND_NO_REFCOUNTING 0x80000000
|
#define NODE_KIND_USER_MASK 0x00000000FFFFFFFFLL
|
||||||
|
#define NODE_KIND_COMPARE_MASK 0x000000007FFFFFFFLL
|
||||||
|
#define NODE_KIND_NO_REFCOUNTING 0x0000000080000000LL
|
||||||
|
#define NODE_KIND_SHADOW_TIMESOURCE 0x0000000100000000LL
|
||||||
|
#define NODE_KIND_SYSTEM_TIMESOURCE 0x0000000200000000LL
|
||||||
|
|
||||||
#define ROUND_UP_TO_PAGE(size) (((size) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1))
|
#define ROUND_UP_TO_PAGE(size) (((size) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1))
|
||||||
|
|
||||||
|
|||||||
@@ -1312,7 +1312,7 @@ BMediaRoster::GetFreeOutputsFor(const media_node & node,
|
|||||||
if (buf_num_outputs == 0)
|
if (buf_num_outputs == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaRosterEx(this)->PublishOutputs(node, &list);
|
MediaRosterEx(this)->PublishOutputs(node, &list);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -1550,21 +1550,38 @@ BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 fl
|
|||||||
ts->FinishCreate();
|
ts->FinishCreate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX XXX XXX
|
||||||
|
// Calling GetAllOutputs and GetAllInputs here,
|
||||||
|
// followed by PublishOutputs and PublishInputs,
|
||||||
|
// does not work, it is too early, and in some
|
||||||
|
// cases it will deadlock the node control thread.
|
||||||
|
|
||||||
|
// Posting a message to the roster thread here
|
||||||
|
// is also to early, the multi_audio add-on will
|
||||||
|
// no list any inputs
|
||||||
|
// XXX XXX XXX
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
BMessage msg(NODE_PUBLISH_CONNECTIONS);
|
||||||
|
media_node tempnode;
|
||||||
|
tempnode = node->Node();
|
||||||
|
msg.AddData("node", B_RAW_TYPE, &tempnode, sizeof(tempnode));
|
||||||
|
PostMessage(&msg);
|
||||||
|
*/
|
||||||
|
/*
|
||||||
// register existing inputs and outputs with the
|
// register existing inputs and outputs with the
|
||||||
// media_server, this allows GetLiveNodes() to work
|
// media_server, this allows GetLiveNodes() to work
|
||||||
// with created, but unconnected nodes.
|
// with created, but unconnected nodes.
|
||||||
if (node->Kinds() & B_BUFFER_PRODUCER) {
|
if (node->Kinds() & B_BUFFER_PRODUCER) {
|
||||||
Stack<media_output> stack;
|
List<media_output> list;
|
||||||
if (B_OK == GetAllOutputs(node->Node(), &stack))
|
if (B_OK == GetAllOutputs(node->Node(), &list))
|
||||||
PublishOutputs(node->Node(), &stack);
|
PublishOutputs(node->Node(), &list);
|
||||||
} else if (node->Kinds() & B_BUFFER_CONSUMER) {
|
} else if (node->Kinds() & B_BUFFER_CONSUMER) {
|
||||||
Stack<media_input> stack;
|
List<media_input> list;
|
||||||
if (B_OK == GetAllInputs(node->Node(), &stack))
|
if (B_OK == GetAllInputs(node->Node(), &list))
|
||||||
PublishInputs(node->Node(), &stack);
|
PublishInputs(node->Node(), &list);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1);
|
BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1);
|
||||||
/*
|
/*
|
||||||
TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id);
|
TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id);
|
||||||
@@ -2441,6 +2458,33 @@ BMediaRoster::MessageReceived(BMessage * message)
|
|||||||
message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000);
|
message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case NODE_PUBLISH_CONNECTIONS:
|
||||||
|
{
|
||||||
|
const void *data;
|
||||||
|
ssize_t numBytes;
|
||||||
|
media_node node;
|
||||||
|
|
||||||
|
printf("NODE_PUBLISH_CONNECTIONS enter\n");
|
||||||
|
|
||||||
|
message->FindData("node", B_RAW_TYPE, &data, &numBytes);
|
||||||
|
node = *(const media_node *)data;
|
||||||
|
|
||||||
|
// register existing inputs and outputs with the
|
||||||
|
// media_server, this allows GetLiveNodes() to work
|
||||||
|
// with created, but unconnected nodes.
|
||||||
|
if (node.kind & B_BUFFER_PRODUCER) {
|
||||||
|
List<media_output> outputlist;
|
||||||
|
if (B_OK == MediaRosterEx(this)->GetAllOutputs(node, &outputlist))
|
||||||
|
MediaRosterEx(this)->PublishOutputs(node, &outputlist);
|
||||||
|
} else if (node.kind & B_BUFFER_CONSUMER) {
|
||||||
|
List<media_input> inputlist;
|
||||||
|
if (B_OK == MediaRosterEx(this)->GetAllInputs(node, &inputlist))
|
||||||
|
MediaRosterEx(this)->PublishInputs(node, &inputlist);
|
||||||
|
}
|
||||||
|
printf("NODE_PUBLISH_CONNECTIONS leave\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case NODE_FINAL_RELEASE:
|
case NODE_FINAL_RELEASE:
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,10 +10,7 @@
|
|||||||
#define _TIME_SOURCE_OBJECT_H_
|
#define _TIME_SOURCE_OBJECT_H_
|
||||||
|
|
||||||
#include <TimeSource.h>
|
#include <TimeSource.h>
|
||||||
|
#include "MediaMisc.h"
|
||||||
#define NODE_KIND_USER_MASK 0x00000000FFFFFFFFLL
|
|
||||||
#define NODE_KIND_SHADOW_TIMESOURCE 0x0000000100000000LL
|
|
||||||
#define NODE_KIND_SYSTEM_TIMESOURCE 0x0000000200000000LL
|
|
||||||
|
|
||||||
namespace BPrivate { namespace media {
|
namespace BPrivate { namespace media {
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,16 @@ status_t AppManager::UnregisterTeam(team_id team)
|
|||||||
return is_removed ? B_OK : B_ERROR;
|
return is_removed ? B_OK : B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AppManager::SendMessage(team_id team, BMessage *msg)
|
||||||
|
{
|
||||||
|
BAutolock lock(fLocker);
|
||||||
|
App *app;
|
||||||
|
if (!fAppMap->Get(team, &app))
|
||||||
|
return B_ERROR;
|
||||||
|
return app->messenger.SendMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
void AppManager::RestartAddonServer()
|
void AppManager::RestartAddonServer()
|
||||||
{
|
{
|
||||||
static bigtime_t restart_period = 0;
|
static bigtime_t restart_period = 0;
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ public:
|
|||||||
void TerminateAddonServer();
|
void TerminateAddonServer();
|
||||||
team_id AddonServer();
|
team_id AddonServer();
|
||||||
|
|
||||||
|
status_t SendMessage(team_id team, BMessage *msg);
|
||||||
|
|
||||||
void Dump();
|
void Dump();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -6,15 +6,18 @@
|
|||||||
#include <MediaNode.h>
|
#include <MediaNode.h>
|
||||||
#include <MediaRoster.h>
|
#include <MediaRoster.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <String.h>
|
|
||||||
#include "DefaultManager.h"
|
#include "DefaultManager.h"
|
||||||
|
#include "NodeManager.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
extern NodeManager *gNodeManager;
|
||||||
|
|
||||||
/* no locking used in this file, we assume that the caller (NodeManager) does it.
|
/* no locking used in this file, we assume that the caller (NodeManager) does it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DefaultManager::DefaultManager()
|
DefaultManager::DefaultManager()
|
||||||
: fPhysicalVideoOut(-1),
|
: fMixerConnected(false),
|
||||||
|
fPhysicalVideoOut(-1),
|
||||||
fPhysicalVideoIn(-1),
|
fPhysicalVideoIn(-1),
|
||||||
fPhysicalAudioOut(-1),
|
fPhysicalAudioOut(-1),
|
||||||
fPhysicalAudioIn(-1),
|
fPhysicalAudioIn(-1),
|
||||||
@@ -153,11 +156,15 @@ void
|
|||||||
DefaultManager::RescanThread()
|
DefaultManager::RescanThread()
|
||||||
{
|
{
|
||||||
printf("DefaultManager::RescanThread() enter\n");
|
printf("DefaultManager::RescanThread() enter\n");
|
||||||
|
|
||||||
// We do not search for the system time source,
|
// We do not search for the system time source,
|
||||||
// it should already exist
|
// it should already exist
|
||||||
ASSERT(fSystemTimeSource != -1);
|
ASSERT(fSystemTimeSource != -1);
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) { // XXX ugly workaround
|
||||||
|
gNodeManager->UpdateNodeConnections(); // XXX ugly workaround
|
||||||
|
snooze(1000000); // XXX ugly workaround
|
||||||
|
|
||||||
if (fPhysicalVideoOut == -1)
|
if (fPhysicalVideoOut == -1)
|
||||||
FindPhysicalVideoOut();
|
FindPhysicalVideoOut();
|
||||||
if (fPhysicalVideoIn == -1)
|
if (fPhysicalVideoIn == -1)
|
||||||
@@ -168,144 +175,218 @@ DefaultManager::RescanThread()
|
|||||||
FindPhysicalAudioIn();
|
FindPhysicalAudioIn();
|
||||||
if (fAudioMixer == -1)
|
if (fAudioMixer == -1)
|
||||||
FindAudioMixer();
|
FindAudioMixer();
|
||||||
|
}
|
||||||
|
|
||||||
// The normal time source is searched for after the
|
// The normal time source is searched for after the
|
||||||
// Physical Audio Out has been created.
|
// Physical Audio Out has been created.
|
||||||
if (fTimeSource == -1)
|
if (fTimeSource == -1)
|
||||||
FindTimeSource();
|
FindTimeSource();
|
||||||
|
|
||||||
|
// Connect the mixer and physical audio out (soundcard)
|
||||||
|
if (!fMixerConnected && fAudioMixer != -1 && fPhysicalAudioOut != -1) {
|
||||||
|
fMixerConnected = B_OK == ConnectMixerToOutput();
|
||||||
|
if (!fMixerConnected)
|
||||||
|
FATAL("DefaultManager: failed to connect mixer and soundcard\n");
|
||||||
|
}
|
||||||
|
|
||||||
printf("DefaultManager::RescanThread() leave\n");
|
printf("DefaultManager::RescanThread() leave\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DefaultManager::FindPhysicalVideoOut()
|
DefaultManager::FindPhysicalVideoOut()
|
||||||
{
|
{
|
||||||
dormant_node_info info;
|
live_node_info info;
|
||||||
media_format input; /* a physical video output has a logical data input */
|
media_format input; /* a physical video output has a logical data input */
|
||||||
media_node node;
|
|
||||||
int32 count;
|
int32 count;
|
||||||
status_t rv;
|
status_t rv;
|
||||||
|
|
||||||
memset(&input, 0, sizeof(input));
|
memset(&input, 0, sizeof(input));
|
||||||
input.type = B_MEDIA_RAW_VIDEO;
|
input.type = B_MEDIA_RAW_VIDEO;
|
||||||
count = 1;
|
count = 1;
|
||||||
rv = BMediaRoster::Roster()->GetDormantNodes(&info, &count, &input, NULL, NULL, B_BUFFER_CONSUMER | B_PHYSICAL_OUTPUT);
|
rv = BMediaRoster::Roster()->GetLiveNodes(&info, &count, &input, NULL, NULL, B_BUFFER_CONSUMER | B_PHYSICAL_OUTPUT);
|
||||||
if (rv != B_OK || count != 1) {
|
if (rv != B_OK || count != 1) {
|
||||||
printf("Couldn't find physical video output node\n");
|
printf("Couldn't find physical video output node\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rv = BMediaRoster::Roster()->InstantiateDormantNode(info, &node, B_FLAVOR_IS_GLOBAL);
|
printf("Default physical video output created!\n");
|
||||||
if (rv != B_OK) {
|
fPhysicalVideoOut = info.node.node;
|
||||||
printf("Couldn't instantiate physical video output node\n");
|
|
||||||
} else {
|
|
||||||
printf("Default physical video output created!\n");
|
|
||||||
fPhysicalVideoOut = node.node;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DefaultManager::FindPhysicalVideoIn()
|
DefaultManager::FindPhysicalVideoIn()
|
||||||
{
|
{
|
||||||
dormant_node_info info;
|
live_node_info info;
|
||||||
media_format output; /* a physical video input has a logical data output */
|
media_format output; /* a physical video input has a logical data output */
|
||||||
media_node node;
|
|
||||||
int32 count;
|
int32 count;
|
||||||
status_t rv;
|
status_t rv;
|
||||||
|
|
||||||
memset(&output, 0, sizeof(output));
|
memset(&output, 0, sizeof(output));
|
||||||
output.type = B_MEDIA_RAW_VIDEO;
|
output.type = B_MEDIA_RAW_VIDEO;
|
||||||
count = 1;
|
count = 1;
|
||||||
rv = BMediaRoster::Roster()->GetDormantNodes(&info, &count, NULL, &output, NULL, B_BUFFER_PRODUCER | B_PHYSICAL_INPUT);
|
rv = BMediaRoster::Roster()->GetLiveNodes(&info, &count, NULL, &output, NULL, B_BUFFER_PRODUCER | B_PHYSICAL_INPUT);
|
||||||
if (rv != B_OK || count != 1) {
|
if (rv != B_OK || count != 1) {
|
||||||
printf("Couldn't find physical video input node\n");
|
printf("Couldn't find physical video input node\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rv = BMediaRoster::Roster()->InstantiateDormantNode(info, &node, B_FLAVOR_IS_GLOBAL);
|
printf("Default physical video input created!\n");
|
||||||
if (rv != B_OK) {
|
fPhysicalVideoIn = info.node.node;
|
||||||
printf("Couldn't instantiate physical video input node\n");
|
|
||||||
} else {
|
|
||||||
printf("Default physical video input created!\n");
|
|
||||||
fPhysicalVideoIn = node.node;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DefaultManager::FindPhysicalAudioOut()
|
DefaultManager::FindPhysicalAudioOut()
|
||||||
{
|
{
|
||||||
dormant_node_info info;
|
live_node_info info[2];
|
||||||
media_format input; /* a physical audio output has a logical data input */
|
media_format input; /* a physical audio output has a logical data input */
|
||||||
media_node node;
|
|
||||||
int32 count;
|
int32 count;
|
||||||
status_t rv;
|
status_t rv;
|
||||||
|
|
||||||
memset(&input, 0, sizeof(input));
|
memset(&input, 0, sizeof(input));
|
||||||
input.type = B_MEDIA_RAW_AUDIO;
|
input.type = B_MEDIA_RAW_AUDIO;
|
||||||
count = 1;
|
count = 2;
|
||||||
rv = BMediaRoster::Roster()->GetDormantNodes(&info, &count, &input, NULL, NULL, B_BUFFER_CONSUMER | B_PHYSICAL_OUTPUT);
|
rv = BMediaRoster::Roster()->GetLiveNodes(&info[0], &count, &input, NULL, NULL, B_BUFFER_CONSUMER | B_PHYSICAL_OUTPUT);
|
||||||
if (rv != B_OK || count != 1) {
|
if (rv != B_OK || count < 1) {
|
||||||
printf("Couldn't find physical audio output node\n");
|
printf("Couldn't find physical audio output node\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rv = BMediaRoster::Roster()->InstantiateDormantNode(info, &node, B_FLAVOR_IS_GLOBAL);
|
for (int i = 0; i < count; i++)
|
||||||
if (rv != B_OK) {
|
printf("info[%d].name %s\n", i, info[i].name);
|
||||||
printf("Couldn't instantiate physical audio output node\n");
|
|
||||||
} else {
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (0 == strcmp(info[i].name, "None Out")) // skip the Null audio driver
|
||||||
|
continue;
|
||||||
printf("Default physical audio output created!\n");
|
printf("Default physical audio output created!\n");
|
||||||
fPhysicalAudioOut = node.node;
|
fPhysicalAudioOut = info[i].node.node;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DefaultManager::FindPhysicalAudioIn()
|
DefaultManager::FindPhysicalAudioIn()
|
||||||
{
|
{
|
||||||
dormant_node_info info;
|
live_node_info info[2];
|
||||||
media_format output; /* a physical audio input has a logical data output */
|
media_format output; /* a physical audio input has a logical data output */
|
||||||
media_node node;
|
|
||||||
int32 count;
|
int32 count;
|
||||||
status_t rv;
|
status_t rv;
|
||||||
|
|
||||||
memset(&output, 0, sizeof(output));
|
memset(&output, 0, sizeof(output));
|
||||||
output.type = B_MEDIA_RAW_AUDIO;
|
output.type = B_MEDIA_RAW_AUDIO;
|
||||||
count = 1;
|
count = 2;
|
||||||
rv = BMediaRoster::Roster()->GetDormantNodes(&info, &count, NULL, &output, NULL, B_BUFFER_PRODUCER | B_PHYSICAL_INPUT);
|
rv = BMediaRoster::Roster()->GetLiveNodes(&info[0], &count, NULL, &output, NULL, B_BUFFER_PRODUCER | B_PHYSICAL_INPUT);
|
||||||
if (rv != B_OK || count != 1) {
|
if (rv != B_OK || count < 1) {
|
||||||
printf("Couldn't find physical audio input node\n");
|
printf("Couldn't find physical audio input node\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rv = BMediaRoster::Roster()->InstantiateDormantNode(info, &node, B_FLAVOR_IS_GLOBAL);
|
for (int i = 0; i < count; i++)
|
||||||
if (rv != B_OK) {
|
printf("info[%d].name %s\n", i, info[i].name);
|
||||||
printf("Couldn't instantiate physical audio input node\n");
|
|
||||||
} else {
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (0 == strcmp(info[i].name, "None In")) // skip the Null audio driver
|
||||||
|
continue;
|
||||||
printf("Default physical audio input created!\n");
|
printf("Default physical audio input created!\n");
|
||||||
fPhysicalAudioIn = node.node;
|
fPhysicalAudioIn = info[i].node.node;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DefaultManager::FindTimeSource()
|
DefaultManager::FindTimeSource()
|
||||||
{
|
{
|
||||||
|
live_node_info info;
|
||||||
|
media_format input; /* a physical audio output has a logical data input (DAC)*/
|
||||||
|
int32 count;
|
||||||
|
status_t rv;
|
||||||
|
|
||||||
|
/* We try to use the default physical audio out node,
|
||||||
|
* as it most likely is a timesource.
|
||||||
|
* XXX if that fails, we might use other audio or video clock timesources
|
||||||
|
*/
|
||||||
|
|
||||||
|
memset(&input, 0, sizeof(input));
|
||||||
|
input.type = B_MEDIA_RAW_AUDIO;
|
||||||
|
count = 1;
|
||||||
|
rv = BMediaRoster::Roster()->GetLiveNodes(&info, &count, &input, NULL, NULL, B_TIME_SOURCE | B_PHYSICAL_OUTPUT);
|
||||||
|
if (rv != B_OK || count != 1) {
|
||||||
|
printf("Couldn't find DAC timesource node\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fTimeSource = info.node.node;
|
||||||
|
printf("Default DAC timesource created!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DefaultManager::FindAudioMixer()
|
DefaultManager::FindAudioMixer()
|
||||||
{
|
{
|
||||||
dormant_node_info info;
|
live_node_info info;
|
||||||
media_node node;
|
|
||||||
int32 count;
|
int32 count;
|
||||||
status_t rv;
|
status_t rv;
|
||||||
|
|
||||||
count = 1;
|
count = 1;
|
||||||
rv = BMediaRoster::Roster()->GetDormantNodes(&info, &count, NULL, NULL, NULL, B_BUFFER_PRODUCER | B_BUFFER_CONSUMER | B_SYSTEM_MIXER);
|
rv = BMediaRoster::Roster()->GetLiveNodes(&info, &count, NULL, NULL, NULL, B_BUFFER_PRODUCER | B_BUFFER_CONSUMER | B_SYSTEM_MIXER);
|
||||||
if (rv != B_OK || count != 1) {
|
if (rv != B_OK || count != 1) {
|
||||||
printf("Couldn't find audio mixer node\n");
|
printf("Couldn't find audio mixer node\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rv = BMediaRoster::Roster()->InstantiateDormantNode(info, &node, B_FLAVOR_IS_GLOBAL);
|
fAudioMixer = info.node.node;
|
||||||
|
printf("Default audio mixer node created\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DefaultManager::ConnectMixerToOutput()
|
||||||
|
{
|
||||||
|
BMediaRoster *roster;
|
||||||
|
media_node mixer;
|
||||||
|
media_node soundcard;
|
||||||
|
media_input input;
|
||||||
|
media_output output;
|
||||||
|
media_format format;
|
||||||
|
int32 count;
|
||||||
|
status_t rv;
|
||||||
|
|
||||||
|
roster = BMediaRoster::Roster();
|
||||||
|
|
||||||
|
// XXX this connects to *any* physical output, but not it's default logical input
|
||||||
|
rv = roster->GetNodeFor(fPhysicalAudioOut, &soundcard);
|
||||||
if (rv != B_OK) {
|
if (rv != B_OK) {
|
||||||
printf("Couldn't instantiate audio mixer node\n");
|
printf("DefaultManager: failed to find soundcard (physical audio output)\n");
|
||||||
} else {
|
return B_ERROR;
|
||||||
printf("Default audio mixer created!\n");
|
|
||||||
fAudioMixer = node.node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rv = roster->GetNodeFor(fAudioMixer, &mixer);
|
||||||
|
if (rv != B_OK) {
|
||||||
|
roster->ReleaseNode(soundcard);
|
||||||
|
printf("DefaultManager: failed to find mixer\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we now have the mixer and soundcard nodes,
|
||||||
|
// find a free input/output and connect them
|
||||||
|
|
||||||
|
rv = roster->GetFreeOutputsFor(mixer, &output, 1, &count, B_MEDIA_RAW_AUDIO);
|
||||||
|
if (rv != B_OK || count != 1) {
|
||||||
|
printf("DefaultManager: can't find free mixer output\n");
|
||||||
|
rv = B_ERROR;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = roster->GetFreeInputsFor(soundcard, &input, 1, &count, B_MEDIA_RAW_AUDIO);
|
||||||
|
if (rv != B_OK || count != 1) {
|
||||||
|
printf("DefaultManager: can't find free soundcard input\n");
|
||||||
|
rv = B_ERROR;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&format, 0, sizeof(format));
|
||||||
|
format.type = B_MEDIA_RAW_AUDIO;
|
||||||
|
|
||||||
|
rv = roster->Connect(output.source, input.destination, &format, &output, &input);
|
||||||
|
if (rv != B_OK) {
|
||||||
|
printf("DefaultManager: connect failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
finish:
|
||||||
|
roster->ReleaseNode(mixer);
|
||||||
|
roster->ReleaseNode(soundcard);
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -317,3 +398,4 @@ void
|
|||||||
DefaultManager::CleanupTeam(team_id team)
|
DefaultManager::CleanupTeam(team_id team)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,14 +35,17 @@ private:
|
|||||||
void FindAudioMixer();
|
void FindAudioMixer();
|
||||||
void FindTimeSource();
|
void FindTimeSource();
|
||||||
|
|
||||||
|
status_t ConnectMixerToOutput();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
media_node_id fPhysicalVideoOut;
|
volatile bool fMixerConnected;
|
||||||
media_node_id fPhysicalVideoIn;
|
volatile media_node_id fPhysicalVideoOut;
|
||||||
media_node_id fPhysicalAudioOut;
|
volatile media_node_id fPhysicalVideoIn;
|
||||||
media_node_id fPhysicalAudioIn;
|
volatile media_node_id fPhysicalAudioOut;
|
||||||
media_node_id fSystemTimeSource;
|
volatile media_node_id fPhysicalAudioIn;
|
||||||
media_node_id fTimeSource;
|
volatile media_node_id fSystemTimeSource;
|
||||||
media_node_id fAudioMixer;
|
volatile media_node_id fTimeSource;
|
||||||
int32 fPhysicalAudioOutInputID;
|
volatile media_node_id fAudioMixer;
|
||||||
|
volatile int32 fPhysicalAudioOutInputID;
|
||||||
char fPhysicalAudioOutInputName[B_MEDIA_NAME_LENGTH];
|
char fPhysicalAudioOutInputName[B_MEDIA_NAME_LENGTH];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ static char __copyright[] = "Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@O
|
|||||||
#include "NodeManager.h"
|
#include "NodeManager.h"
|
||||||
#include "DefaultManager.h"
|
#include "DefaultManager.h"
|
||||||
#include "AppManager.h"
|
#include "AppManager.h"
|
||||||
|
#include "MediaMisc.h"
|
||||||
|
|
||||||
extern AppManager *gAppManager;
|
extern AppManager *gAppManager;
|
||||||
|
|
||||||
@@ -411,7 +412,7 @@ NodeManager::GetDormantNodeInfo(dormant_node_info *node_info, const media_node &
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
ASSERT(node.port == rn->port);
|
ASSERT(node.port == rn->port);
|
||||||
ASSERT(node.kind == rn->kinds);
|
ASSERT((node.kind & NODE_KIND_COMPARE_MASK) == (rn->kinds & NODE_KIND_COMPARE_MASK));
|
||||||
node_info->addon = rn->addon_id;
|
node_info->addon = rn->addon_id;
|
||||||
node_info->flavor_id = rn->addon_flavor_id;
|
node_info->flavor_id = rn->addon_flavor_id;
|
||||||
strcpy(node_info->name, rn->name);
|
strcpy(node_info->name, rn->name);
|
||||||
@@ -431,7 +432,7 @@ NodeManager::GetLiveNodeInfo(live_node_info *live_info, const media_node &node)
|
|||||||
for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) {
|
for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) {
|
||||||
if (rn->nodeid == node.node) {
|
if (rn->nodeid == node.node) {
|
||||||
ASSERT(node.port == rn->port);
|
ASSERT(node.port == rn->port);
|
||||||
ASSERT(node.kind == rn->kinds);
|
ASSERT((node.kind & NODE_KIND_COMPARE_MASK) == (rn->kinds & NODE_KIND_COMPARE_MASK));
|
||||||
live_info->node = node;
|
live_info->node = node;
|
||||||
live_info->hint_point = BPoint(0, 0);
|
live_info->hint_point = BPoint(0, 0);
|
||||||
strcpy(live_info->name, rn->name);
|
strcpy(live_info->name, rn->name);
|
||||||
@@ -468,6 +469,9 @@ NodeManager::GetLiveNodes(Stack<live_node_info> *livenodes, int32 maxcount, cons
|
|||||||
BAutolock lock(fLocker);
|
BAutolock lock(fLocker);
|
||||||
registered_node *rn;
|
registered_node *rn;
|
||||||
int namelen;
|
int namelen;
|
||||||
|
|
||||||
|
TRACE("NodeManager::GetLiveNodes: maxcount %d, in-format %p, out-format %p, name %s, require_kinds 0x%x\n",
|
||||||
|
maxcount, inputformat, outputformat, (name ? name : "NULL"), require_kinds);
|
||||||
|
|
||||||
// determine the count of byte to compare when checking for a name with(out) wildcard
|
// determine the count of byte to compare when checking for a name with(out) wildcard
|
||||||
if (name) {
|
if (name) {
|
||||||
@@ -539,6 +543,28 @@ NodeManager::GetLiveNodes(BMessage *msg)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NodeManager::UpdateNodeConnections()
|
||||||
|
{
|
||||||
|
// XXX this is only a workaround because the multi_audio
|
||||||
|
// XXX addon does not publish inputs right after creation :(
|
||||||
|
BAutolock lock(fLocker);
|
||||||
|
|
||||||
|
registered_node *rn;
|
||||||
|
for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) {
|
||||||
|
|
||||||
|
BMessage msg(NODE_PUBLISH_CONNECTIONS);
|
||||||
|
media_node tempnode;
|
||||||
|
tempnode.node = rn->nodeid;
|
||||||
|
tempnode.port = rn->port;
|
||||||
|
tempnode.kind = rn->kinds;
|
||||||
|
msg.AddData("node", B_RAW_TYPE, &tempnode, sizeof(tempnode));
|
||||||
|
|
||||||
|
gAppManager->SendMessage(rn->team, &msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* Registration of BMediaAddOns
|
* Registration of BMediaAddOns
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
@@ -964,11 +990,15 @@ NodeManager::Dump()
|
|||||||
printf(" media_input: node-id %ld, node-port %ld, source-port %ld, source-id %ld, dest-port %ld, dest-id %ld, name \"%s\"\n",
|
printf(" media_input: node-id %ld, node-port %ld, source-port %ld, source-id %ld, dest-port %ld, dest-id %ld, name \"%s\"\n",
|
||||||
input->node.node, input->node.port, input->source.port, input->source.id, input->destination.port, input->destination.id, input->name);
|
input->node.node, input->node.port, input->source.port, input->source.id, input->destination.port, input->destination.id, input->name);
|
||||||
}
|
}
|
||||||
|
if (rn->inputlist.IsEmpty())
|
||||||
|
printf(" media_input: none\n");
|
||||||
media_output *output;
|
media_output *output;
|
||||||
for (rn->outputlist.Rewind(); rn->outputlist.GetNext(&output); ) {
|
for (rn->outputlist.Rewind(); rn->outputlist.GetNext(&output); ) {
|
||||||
printf(" media_output: node-id %ld, node-port %ld, source-port %ld, source-id %ld, dest-port %ld, dest-id %ld, name \"%s\"\n",
|
printf(" media_output: node-id %ld, node-port %ld, source-port %ld, source-id %ld, dest-port %ld, dest-id %ld, name \"%s\"\n",
|
||||||
output->node.node, output->node.port, output->source.port, output->source.id, output->destination.port, output->destination.id, output->name);
|
output->node.node, output->node.port, output->source.port, output->source.id, output->destination.port, output->destination.id, output->name);
|
||||||
}
|
}
|
||||||
|
if (rn->outputlist.IsEmpty())
|
||||||
|
printf(" media_input: none\n");
|
||||||
}
|
}
|
||||||
printf("NodeManager: list end\n");
|
printf("NodeManager: list end\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|||||||
@@ -105,6 +105,8 @@ public:
|
|||||||
|
|
||||||
void CleanupTeam(team_id team);
|
void CleanupTeam(team_id team);
|
||||||
|
|
||||||
|
void UpdateNodeConnections();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
media_addon_id fNextAddOnID;
|
media_addon_id fNextAddOnID;
|
||||||
media_node_id fNextNodeID;
|
media_node_id fNextNodeID;
|
||||||
|
|||||||
@@ -55,6 +55,17 @@ static char __copyright[] = "Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@O
|
|||||||
|
|
||||||
void DumpFlavorInfo(const flavor_info *info);
|
void DumpFlavorInfo(const flavor_info *info);
|
||||||
|
|
||||||
|
struct AddOnInfo
|
||||||
|
{
|
||||||
|
media_addon_id id;
|
||||||
|
bool wants_autostart;
|
||||||
|
int32 flavor_count;
|
||||||
|
|
||||||
|
List<media_node> active_flavors;
|
||||||
|
|
||||||
|
BMediaAddOn *addon; // if != NULL, need to call _DormantNodeManager->PutAddon(id)
|
||||||
|
};
|
||||||
|
|
||||||
class MediaAddonServer : BApplication
|
class MediaAddonServer : BApplication
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -68,11 +79,16 @@ public:
|
|||||||
void AddOnRemoved(ino_t file_node);
|
void AddOnRemoved(ino_t file_node);
|
||||||
void HandleMessage(int32 code, const void *data, size_t size);
|
void HandleMessage(int32 code, const void *data, size_t size);
|
||||||
static int32 controlthread(void *arg);
|
static int32 controlthread(void *arg);
|
||||||
|
|
||||||
|
void PutAddonIfPossible(AddOnInfo *info);
|
||||||
|
void InstantiatePhysialInputsAndOutputs(AddOnInfo *info);
|
||||||
|
void InstantiateAutostartFlavors(AddOnInfo *info);
|
||||||
|
void DestroyInstantiatedFlavors(AddOnInfo *info);
|
||||||
|
|
||||||
void ScanAddOnFlavors(BMediaAddOn *addon);
|
void ScanAddOnFlavors(BMediaAddOn *addon);
|
||||||
|
|
||||||
Map<ino_t, media_addon_id> *filemap;
|
Map<ino_t, media_addon_id> *filemap;
|
||||||
Map<media_addon_id, int32> *flavorcountmap;
|
Map<media_addon_id, AddOnInfo> *infomap;
|
||||||
|
|
||||||
BMediaRoster *mediaroster;
|
BMediaRoster *mediaroster;
|
||||||
ino_t DirNodeSystem;
|
ino_t DirNodeSystem;
|
||||||
@@ -88,9 +104,9 @@ MediaAddonServer::MediaAddonServer(const char *sig) :
|
|||||||
{
|
{
|
||||||
mediaroster = BMediaRoster::Roster();
|
mediaroster = BMediaRoster::Roster();
|
||||||
filemap = new Map<ino_t, media_addon_id>;
|
filemap = new Map<ino_t, media_addon_id>;
|
||||||
flavorcountmap = new Map<media_addon_id, int32>;
|
infomap = new Map<media_addon_id, AddOnInfo>;
|
||||||
control_port = create_port(64,"media_addon_server port");
|
control_port = create_port(64, "media_addon_server port");
|
||||||
control_thread = spawn_thread(controlthread,"media_addon_server control",12,this);
|
control_thread = spawn_thread(controlthread, "media_addon_server control", 12, this);
|
||||||
resume_thread(control_thread);
|
resume_thread(control_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +122,7 @@ MediaAddonServer::~MediaAddonServer()
|
|||||||
_DormantNodeManager->UnregisterAddon(*id);
|
_DormantNodeManager->UnregisterAddon(*id);
|
||||||
|
|
||||||
delete filemap;
|
delete filemap;
|
||||||
delete flavorcountmap;
|
delete infomap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -160,6 +176,10 @@ MediaAddonServer::controlthread(void *arg)
|
|||||||
void
|
void
|
||||||
MediaAddonServer::ReadyToRun()
|
MediaAddonServer::ReadyToRun()
|
||||||
{
|
{
|
||||||
|
// the control thread is already running at this point,
|
||||||
|
// so we can talk to the media server and also receive
|
||||||
|
// commands for instantiation
|
||||||
|
|
||||||
// register with media_server
|
// register with media_server
|
||||||
server_register_addonserver_request request;
|
server_register_addonserver_request request;
|
||||||
server_register_addonserver_reply reply;
|
server_register_addonserver_reply reply;
|
||||||
@@ -172,7 +192,13 @@ MediaAddonServer::ReadyToRun()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fStartup = true;
|
ASSERT(fStartup == true);
|
||||||
|
|
||||||
|
// During startup, first all add-ons are loaded, then all
|
||||||
|
// nodes (flavors) representing physical inputs and outputs
|
||||||
|
// are instantiated. Next, all add-ons that need autostart
|
||||||
|
// will be autostarted. Finally, add-ons that don't have
|
||||||
|
// any active nodes (flavors) will be unloaded.
|
||||||
|
|
||||||
// load dormant media nodes
|
// load dormant media nodes
|
||||||
node_ref nref;
|
node_ref nref;
|
||||||
@@ -191,7 +217,21 @@ MediaAddonServer::ReadyToRun()
|
|||||||
WatchDir(&e2);
|
WatchDir(&e2);
|
||||||
|
|
||||||
fStartup = false;
|
fStartup = false;
|
||||||
|
|
||||||
|
AddOnInfo *info;
|
||||||
|
|
||||||
|
infomap->Rewind();
|
||||||
|
while (infomap->GetNext(&info))
|
||||||
|
InstantiatePhysialInputsAndOutputs(info);
|
||||||
|
|
||||||
|
infomap->Rewind();
|
||||||
|
while (infomap->GetNext(&info))
|
||||||
|
InstantiateAutostartFlavors(info);
|
||||||
|
|
||||||
|
infomap->Rewind();
|
||||||
|
while (infomap->GetNext(&info))
|
||||||
|
PutAddonIfPossible(info);
|
||||||
|
|
||||||
server_rescan_defaults_command cmd;
|
server_rescan_defaults_command cmd;
|
||||||
SendToServer(SERVER_RESCAN_DEFAULTS, &cmd, sizeof(cmd));
|
SendToServer(SERVER_RESCAN_DEFAULTS, &cmd, sizeof(cmd));
|
||||||
}
|
}
|
||||||
@@ -199,7 +239,7 @@ MediaAddonServer::ReadyToRun()
|
|||||||
void
|
void
|
||||||
MediaAddonServer::ScanAddOnFlavors(BMediaAddOn *addon)
|
MediaAddonServer::ScanAddOnFlavors(BMediaAddOn *addon)
|
||||||
{
|
{
|
||||||
int32 *flavorcount;
|
AddOnInfo *info;
|
||||||
int32 oldflavorcount;
|
int32 oldflavorcount;
|
||||||
int32 newflavorcount;
|
int32 newflavorcount;
|
||||||
media_addon_id addon_id;
|
media_addon_id addon_id;
|
||||||
@@ -223,11 +263,11 @@ MediaAddonServer::ScanAddOnFlavors(BMediaAddOn *addon)
|
|||||||
addon_id = addon->AddonID();
|
addon_id = addon->AddonID();
|
||||||
|
|
||||||
// update the cached flavor count, get oldflavorcount and newflavorcount
|
// update the cached flavor count, get oldflavorcount and newflavorcount
|
||||||
b = flavorcountmap->Get(addon->AddonID(), &flavorcount);
|
b = infomap->Get(addon_id, &info);
|
||||||
ASSERT(b);
|
ASSERT(b);
|
||||||
oldflavorcount = *flavorcount;
|
oldflavorcount = info->flavor_count;
|
||||||
newflavorcount = addon->CountFlavors();
|
newflavorcount = addon->CountFlavors();
|
||||||
*flavorcount = newflavorcount;
|
info->flavor_count = newflavorcount;
|
||||||
|
|
||||||
TRACE("%ld old flavors, %ld new flavors\n", oldflavorcount, newflavorcount);
|
TRACE("%ld old flavors, %ld new flavors\n", oldflavorcount, newflavorcount);
|
||||||
|
|
||||||
@@ -296,6 +336,8 @@ MediaAddonServer::AddOnAdded(const char *path, ino_t file_node)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRACE("MediaAddonServer::AddOnAdded: loading addon %d now...\n", id);
|
||||||
|
|
||||||
addon = _DormantNodeManager->GetAddon(id);
|
addon = _DormantNodeManager->GetAddon(id);
|
||||||
if (addon == NULL) {
|
if (addon == NULL) {
|
||||||
FATAL("MediaAddonServer::AddOnAdded: failed to get add-on %s\n", path);
|
FATAL("MediaAddonServer::AddOnAdded: failed to get add-on %s\n", path);
|
||||||
@@ -305,73 +347,142 @@ MediaAddonServer::AddOnAdded(const char *path, ino_t file_node)
|
|||||||
|
|
||||||
TRACE("MediaAddonServer::AddOnAdded: loading finished, id %ld\n", id);
|
TRACE("MediaAddonServer::AddOnAdded: loading finished, id %ld\n", id);
|
||||||
|
|
||||||
|
// put file's inode and addon's id into map
|
||||||
filemap->Insert(file_node, id);
|
filemap->Insert(file_node, id);
|
||||||
flavorcountmap->Insert(id, 0);
|
|
||||||
|
|
||||||
ScanAddOnFlavors(addon);
|
|
||||||
|
|
||||||
if (addon->WantsAutoStart())
|
// also create AddOnInfo struct and get a pointer so
|
||||||
|
// we can modify it
|
||||||
|
AddOnInfo tempinfo;
|
||||||
|
infomap->Insert(id, tempinfo);
|
||||||
|
AddOnInfo *info;
|
||||||
|
infomap->Get(id, &info);
|
||||||
|
|
||||||
|
// setup
|
||||||
|
info->id = id;
|
||||||
|
info->wants_autostart = false; // temporary default
|
||||||
|
info->flavor_count = 0;
|
||||||
|
info->addon = addon;
|
||||||
|
|
||||||
|
// scan the flavors
|
||||||
|
ScanAddOnFlavors(addon);
|
||||||
|
|
||||||
|
// need to call BMediaNode::WantsAutoStart()
|
||||||
|
// after the flavors have been scanned
|
||||||
|
info->wants_autostart = addon->WantsAutoStart();
|
||||||
|
|
||||||
|
if (info->wants_autostart)
|
||||||
FATAL("#### add-on %ld WantsAutoStart!\n", id);
|
FATAL("#### add-on %ld WantsAutoStart!\n", id);
|
||||||
|
|
||||||
/*
|
// During startup, first all add-ons are loaded, then all
|
||||||
* the mixer (which we can't load because of unresolved symbols)
|
// nodes (flavors) representing physical inputs and outputs
|
||||||
* is the only node that uses autostart (which is not implemented yet)
|
// are instantiated. Next, all add-ons that need autostart
|
||||||
*/
|
// will be autostarted. Finally, add-ons that don't have
|
||||||
|
// any active nodes (flavors) will be unloaded.
|
||||||
/*
|
|
||||||
loading BMediaAddOn from /boot/beos/system/add-ons/media/mixer.media_addon
|
|
||||||
adding media add-on -1
|
|
||||||
1 flavors:
|
|
||||||
flavor 0:
|
|
||||||
internal_id = 0
|
|
||||||
name = Be Audio Mixer
|
|
||||||
info = The system-wide sound mixer of the future.
|
|
||||||
flavor_flags = 0x0
|
|
||||||
kinds = 0x40003 B_BUFFER_PRODUCER B_BUFFER_CONSUMER B_SYSTEM_MIXER
|
|
||||||
in_format_count = 1
|
|
||||||
out_format_count = 1
|
|
||||||
#### WantsAutoStart!
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (addon->WantsAutoStart()) {
|
|
||||||
for (int32 index = 0; ;index++) {
|
|
||||||
BMediaNode *outNode;
|
|
||||||
int32 outInternalID;
|
|
||||||
bool outHasMore;
|
|
||||||
rv = addon->AutoStart(index, &outNode, &outInternalID, &outHasMore);
|
|
||||||
if (rv == B_OK) {
|
|
||||||
printf("started node %ld\n",index);
|
|
||||||
rv = mediaroster->RegisterNode(outNode);
|
|
||||||
if (rv != B_OK)
|
|
||||||
printf("failed to register node %ld\n",index);
|
|
||||||
if (!outHasMore)
|
|
||||||
// break;
|
|
||||||
return;
|
|
||||||
} else if (rv == B_MEDIA_ADDON_FAILED && outHasMore) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
// After startup is done, we simply do it for each new
|
||||||
|
// loaded add-on, too.
|
||||||
if (!fStartup) {
|
if (!fStartup) {
|
||||||
|
InstantiatePhysialInputsAndOutputs(info);
|
||||||
|
InstantiateAutostartFlavors(info);
|
||||||
|
PutAddonIfPossible(info);
|
||||||
|
|
||||||
|
// since something might have changed
|
||||||
server_rescan_defaults_command cmd;
|
server_rescan_defaults_command cmd;
|
||||||
SendToServer(SERVER_RESCAN_DEFAULTS, &cmd, sizeof(cmd));
|
SendToServer(SERVER_RESCAN_DEFAULTS, &cmd, sizeof(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
_DormantNodeManager->PutAddon(id);
|
// we do not call _DormantNodeManager->PutAddon(id)
|
||||||
|
// since it is done by PutAddonIfPossible()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaAddonServer::DestroyInstantiatedFlavors(AddOnInfo *info)
|
||||||
|
{
|
||||||
|
printf("MediaAddonServer::DestroyInstantiatedFlavors");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaAddonServer::PutAddonIfPossible(AddOnInfo *info)
|
||||||
|
{
|
||||||
|
if (info->addon && info->active_flavors.IsEmpty()) {
|
||||||
|
_DormantNodeManager->PutAddon(info->id);
|
||||||
|
info->addon = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaAddonServer::InstantiatePhysialInputsAndOutputs(AddOnInfo *info)
|
||||||
|
{
|
||||||
|
int count = info->addon->CountFlavors();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
const flavor_info *flavorinfo;
|
||||||
|
if (B_OK != info->addon->GetFlavorAt(i, &flavorinfo)) {
|
||||||
|
FATAL("MediaAddonServer::InstantiatePhysialInputsAndOutputs GetFlavorAt failed for index %d!\n", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (flavorinfo->kinds & (B_PHYSICAL_INPUT | B_PHYSICAL_OUTPUT)) {
|
||||||
|
media_node node;
|
||||||
|
status_t rv;
|
||||||
|
|
||||||
|
dormant_node_info dni;
|
||||||
|
dni.addon = info->id;
|
||||||
|
dni.flavor_id = flavorinfo->internal_id;
|
||||||
|
strcpy(dni.name, flavorinfo->name);
|
||||||
|
|
||||||
|
printf("MediaAddonServer::InstantiatePhysialInputsAndOutputs: \"%s\" is a physical input/output\n", flavorinfo->name);
|
||||||
|
rv = mediaroster->InstantiateDormantNode(dni, &node);
|
||||||
|
if (rv != B_OK) {
|
||||||
|
printf("Couldn't instantiate node\n");
|
||||||
|
} else {
|
||||||
|
printf("Node created!\n");
|
||||||
|
info->active_flavors.Insert(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaAddonServer::InstantiateAutostartFlavors(AddOnInfo *info)
|
||||||
|
{
|
||||||
|
if (!info->wants_autostart)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int32 index = 0; ;index++) {
|
||||||
|
BMediaNode *outNode;
|
||||||
|
int32 outInternalID;
|
||||||
|
bool outHasMore;
|
||||||
|
status_t rv;
|
||||||
|
printf("trying autostart of node %ld, index %ld\n", info->id, index);
|
||||||
|
rv = info->addon->AutoStart(index, &outNode, &outInternalID, &outHasMore);
|
||||||
|
if (rv == B_OK) {
|
||||||
|
printf("started node\n",index);
|
||||||
|
|
||||||
|
// XXX IncrementAddonFlavorInstancesCount
|
||||||
|
|
||||||
|
rv = MediaRosterEx(mediaroster)->RegisterNode(outNode, info->id, outInternalID);
|
||||||
|
if (rv != B_OK) {
|
||||||
|
printf("failed to register node %ld\n",index);
|
||||||
|
// XXX DecrementAddonFlavorInstancesCount
|
||||||
|
}
|
||||||
|
|
||||||
|
info->active_flavors.Insert(outNode->Node());
|
||||||
|
|
||||||
|
if (!outHasMore)
|
||||||
|
return;
|
||||||
|
} else if (rv == B_MEDIA_ADDON_FAILED && outHasMore) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MediaAddonServer::AddOnRemoved(ino_t file_node)
|
MediaAddonServer::AddOnRemoved(ino_t file_node)
|
||||||
{
|
{
|
||||||
media_addon_id *tempid;
|
media_addon_id *tempid;
|
||||||
media_addon_id id;
|
media_addon_id id;
|
||||||
|
AddOnInfo *info;
|
||||||
int32 *tempflavorcount;
|
int32 *tempflavorcount;
|
||||||
int32 oldflavorcount;
|
int32 oldflavorcount;
|
||||||
// XXX locking?
|
// XXX locking?
|
||||||
@@ -383,14 +494,22 @@ MediaAddonServer::AddOnRemoved(ino_t file_node)
|
|||||||
id = *tempid; // tempid pointer is invalid after Removing() it from the map
|
id = *tempid; // tempid pointer is invalid after Removing() it from the map
|
||||||
filemap->Remove(file_node);
|
filemap->Remove(file_node);
|
||||||
|
|
||||||
if (!flavorcountmap->Get(id, &tempflavorcount)) {
|
if (!infomap->Get(id, &info)) {
|
||||||
FATAL("MediaAddonServer::AddOnRemoved: couldn't get flavor count for add-on %ld\n", id);
|
FATAL("MediaAddonServer::AddOnRemoved: couldn't get addon info for add-on %ld\n", id);
|
||||||
oldflavorcount = 1000;
|
oldflavorcount = 1000;
|
||||||
} else {
|
} else {
|
||||||
oldflavorcount = *tempflavorcount; //same reason as above
|
oldflavorcount = info->flavor_count; //same reason as above
|
||||||
}
|
|
||||||
flavorcountmap->Remove(id);
|
|
||||||
|
|
||||||
|
DestroyInstantiatedFlavors(info);
|
||||||
|
PutAddonIfPossible(info);
|
||||||
|
|
||||||
|
if (info->addon) {
|
||||||
|
FATAL("MediaAddonServer::AddOnRemoved: couldn't unload addon %ld since flavors are in use\n", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
infomap->Remove(id);
|
||||||
_DormantNodeManager->UnregisterAddon(id);
|
_DormantNodeManager->UnregisterAddon(id);
|
||||||
|
|
||||||
BPrivate::media::notifications::FlavorsChanged(id, 0, oldflavorcount);
|
BPrivate::media::notifications::FlavorsChanged(id, 0, oldflavorcount);
|
||||||
|
|||||||
Reference in New Issue
Block a user