152a38012Sejakowatz /*********************************************************************** 252a38012Sejakowatz * AUTHOR: Marcus Overhagen 352a38012Sejakowatz * FILE: MediaRoster.cpp 452a38012Sejakowatz * DESCR: 552a38012Sejakowatz ***********************************************************************/ 652a38012Sejakowatz #include <MediaRoster.h> 752a38012Sejakowatz #include <Locker.h> 852a38012Sejakowatz #include <Message.h> 952a38012Sejakowatz #include <Messenger.h> 1052a38012Sejakowatz #include <StopWatch.h> 1152a38012Sejakowatz #include <OS.h> 1252a38012Sejakowatz #include <String.h> 1352a38012Sejakowatz #include <TimeSource.h> 1460f15390Sbeveloper #include <ParameterWeb.h> 1552a38012Sejakowatz #include "debug.h" 168b04ffc1Sbeveloper #include "MediaRosterEx.h" 1740f36b03Sbeveloper #include "MediaMisc.h" 1852a38012Sejakowatz #include "PortPool.h" 190a483e72SIngo Weinhold #include "ServerInterface.h" 20f4925104Sbeveloper #include "DataExchange.h" 2116b7eea4Sbeveloper #include "DormantNodeManager.h" 22f4925104Sbeveloper #include "Notifications.h" 23835140c8Sbeveloper #include "TimeSourceObjectManager.h" 2452a38012Sejakowatz 25f4925104Sbeveloper namespace BPrivate { namespace media { 2652a38012Sejakowatz 2752a38012Sejakowatz // the BMediaRoster destructor is private, 2852a38012Sejakowatz // but _DefaultDeleter is a friend class of 2952a38012Sejakowatz // the BMediaRoster an thus can delete it 308b04ffc1Sbeveloper class DefaultDeleter 3152a38012Sejakowatz { 3252a38012Sejakowatz public: 338b04ffc1Sbeveloper ~DefaultDeleter() 346396865dSbeveloper { 356396865dSbeveloper if (BMediaRoster::_sDefault) { 366396865dSbeveloper BMediaRoster::_sDefault->Lock(); 376396865dSbeveloper BMediaRoster::_sDefault->Quit(); 386396865dSbeveloper } 396396865dSbeveloper } 408b04ffc1Sbeveloper }; 4152a38012Sejakowatz 428b04ffc1Sbeveloper } } // BPrivate::media 438b04ffc1Sbeveloper using namespace BPrivate::media; 4452a38012Sejakowatz 458b04ffc1Sbeveloper // DefaultDeleter will delete the BMediaRoster object in it's destructor. 468b04ffc1Sbeveloper DefaultDeleter _deleter; 4752a38012Sejakowatz 483620737cSbeveloper status_t 4954187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode *node) 5054187cc6Sbeveloper { 5154187cc6Sbeveloper BMediaAddOn *addon; 5254187cc6Sbeveloper media_addon_id addonid; 5354187cc6Sbeveloper int32 flavorid; 5454187cc6Sbeveloper addon = node->AddOn(&flavorid); 5554187cc6Sbeveloper if (!addon) { 5660f15390Sbeveloper // XXX this check incorrectly triggers on BeOS R5 BT848 node 5760f15390Sbeveloper FATAL("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated from BMediaAddOn!\n", node->ID()); 5854187cc6Sbeveloper return B_ERROR; 5954187cc6Sbeveloper } 6054187cc6Sbeveloper addonid = addon->AddonID(); 6154187cc6Sbeveloper 6254187cc6Sbeveloper // XXX fix this 6354187cc6Sbeveloper printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid); 6454187cc6Sbeveloper return B_OK; 6554187cc6Sbeveloper } 6654187cc6Sbeveloper 6754187cc6Sbeveloper status_t 6854187cc6Sbeveloper BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage *out_msg) 6954187cc6Sbeveloper { 7054187cc6Sbeveloper // XXX fix this 7154187cc6Sbeveloper out_msg->MakeEmpty(); // to be fully R5 compliant 7254187cc6Sbeveloper printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid); 7354187cc6Sbeveloper return B_OK; 7454187cc6Sbeveloper } 7554187cc6Sbeveloper 7654187cc6Sbeveloper status_t 7773794717Sbeveloper BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid) 7854187cc6Sbeveloper { 7973794717Sbeveloper server_change_addon_flavor_instances_count_request request; 8073794717Sbeveloper server_change_addon_flavor_instances_count_reply reply; 8173794717Sbeveloper 8273794717Sbeveloper request.addonid = addonid; 8373794717Sbeveloper request.flavorid = flavorid; 8473794717Sbeveloper request.delta = 1; 8573794717Sbeveloper request.team = team; 8673794717Sbeveloper return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply)); 8754187cc6Sbeveloper } 8854187cc6Sbeveloper 8954187cc6Sbeveloper status_t 9073794717Sbeveloper BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid) 9154187cc6Sbeveloper { 9273794717Sbeveloper server_change_addon_flavor_instances_count_request request; 9373794717Sbeveloper server_change_addon_flavor_instances_count_reply reply; 9473794717Sbeveloper 9573794717Sbeveloper request.addonid = addonid; 9673794717Sbeveloper request.flavorid = flavorid; 9773794717Sbeveloper request.delta = -1; 9873794717Sbeveloper request.team = team; 9973794717Sbeveloper return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply)); 10054187cc6Sbeveloper } 10154187cc6Sbeveloper 10254187cc6Sbeveloper status_t 10354187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator) 10454187cc6Sbeveloper { 10554187cc6Sbeveloper server_set_node_creator_request request; 10654187cc6Sbeveloper server_set_node_creator_reply reply; 10754187cc6Sbeveloper 10854187cc6Sbeveloper request.node = node; 10954187cc6Sbeveloper request.creator = creator; 11054187cc6Sbeveloper return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request), &reply, sizeof(reply)); 11154187cc6Sbeveloper } 11254187cc6Sbeveloper 11354187cc6Sbeveloper status_t 1148b04ffc1Sbeveloper BMediaRosterEx::GetNode(node_type type, media_node * out_node, int32 * out_input_id, BString * out_input_name) 11552a38012Sejakowatz { 11652a38012Sejakowatz if (out_node == NULL) 11752a38012Sejakowatz return B_BAD_VALUE; 11852a38012Sejakowatz 1198c6a6096Sbeveloper server_get_node_request request; 1208c6a6096Sbeveloper server_get_node_reply reply; 12152a38012Sejakowatz status_t rv; 12252a38012Sejakowatz 1238c6a6096Sbeveloper request.type = type; 1249e9417d2Sbeveloper request.team = team; 1258c6a6096Sbeveloper rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, sizeof(reply)); 1268c6a6096Sbeveloper if (rv != B_OK) 1278c6a6096Sbeveloper return rv; 12852a38012Sejakowatz 12952a38012Sejakowatz *out_node = reply.node; 13052a38012Sejakowatz if (out_input_id) 13152a38012Sejakowatz *out_input_id = reply.input_id; 13252a38012Sejakowatz if (out_input_name) 13352a38012Sejakowatz *out_input_name = reply.input_name; 1348c6a6096Sbeveloper return rv; 13552a38012Sejakowatz } 13652a38012Sejakowatz 1373620737cSbeveloper status_t 1388b04ffc1Sbeveloper BMediaRosterEx::SetNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input) 13952a38012Sejakowatz { 1408c6a6096Sbeveloper server_set_node_request request; 1418c6a6096Sbeveloper server_set_node_reply reply; 14252a38012Sejakowatz 1438c6a6096Sbeveloper request.type = type; 1448c6a6096Sbeveloper request.use_node = node ? true : false; 14552a38012Sejakowatz if (node) 1468c6a6096Sbeveloper request.node = *node; 1478c6a6096Sbeveloper request.use_dni = info ? true : false; 14852a38012Sejakowatz if (info) 1498c6a6096Sbeveloper request.dni = *info; 1508c6a6096Sbeveloper request.use_input = input ? true : false; 15152a38012Sejakowatz if (input) 1528c6a6096Sbeveloper request.input = *input; 15352a38012Sejakowatz 1548c6a6096Sbeveloper return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, sizeof(reply)); 15552a38012Sejakowatz } 15652a38012Sejakowatz 1573620737cSbeveloper status_t 1588b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node & node, List<media_output> *list) 1593620737cSbeveloper { 1603620737cSbeveloper int32 cookie; 1613620737cSbeveloper status_t rv; 1623620737cSbeveloper status_t result; 1633620737cSbeveloper 1643620737cSbeveloper result = B_OK; 1653620737cSbeveloper cookie = 0; 16676669a29Sbeveloper list->MakeEmpty(); 1673620737cSbeveloper for (;;) { 1683620737cSbeveloper producer_get_next_output_request request; 1693620737cSbeveloper producer_get_next_output_reply reply; 1703620737cSbeveloper request.cookie = cookie; 1710caff283Sbeveloper rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, sizeof(request), &reply, sizeof(reply)); 1723620737cSbeveloper if (rv != B_OK) 1733620737cSbeveloper break; 1743620737cSbeveloper cookie = reply.cookie; 17576669a29Sbeveloper if (!list->Insert(reply.output)) { 17676669a29Sbeveloper FATAL("GetAllOutputs: list->Insert failed\n"); 1773620737cSbeveloper result = B_ERROR; 1783620737cSbeveloper } 1793620737cSbeveloper } 1803620737cSbeveloper 1813620737cSbeveloper producer_dispose_output_cookie_request request; 1823620737cSbeveloper producer_dispose_output_cookie_reply reply; 1830caff283Sbeveloper QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply)); 1843620737cSbeveloper 1853620737cSbeveloper return result; 1863620737cSbeveloper } 1873620737cSbeveloper 1883620737cSbeveloper status_t 1898b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node & node, List<media_input> *list) 1903620737cSbeveloper { 1913620737cSbeveloper int32 cookie; 1923620737cSbeveloper status_t rv; 1933620737cSbeveloper status_t result; 1943620737cSbeveloper 1953620737cSbeveloper result = B_OK; 1963620737cSbeveloper cookie = 0; 19776669a29Sbeveloper list->MakeEmpty(); 1983620737cSbeveloper for (;;) { 1993620737cSbeveloper consumer_get_next_input_request request; 2003620737cSbeveloper consumer_get_next_input_reply reply; 2013620737cSbeveloper request.cookie = cookie; 2020caff283Sbeveloper rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, sizeof(request), &reply, sizeof(reply)); 2033620737cSbeveloper if (rv != B_OK) 2043620737cSbeveloper break; 2053620737cSbeveloper cookie = reply.cookie; 20676669a29Sbeveloper if (!list->Insert(reply.input)) { 20776669a29Sbeveloper FATAL("GetAllInputs: list->Insert failed\n"); 2083620737cSbeveloper result = B_ERROR; 2093620737cSbeveloper } 2103620737cSbeveloper } 2113620737cSbeveloper 2123620737cSbeveloper consumer_dispose_input_cookie_request request; 2133620737cSbeveloper consumer_dispose_input_cookie_reply reply; 2140caff283Sbeveloper QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply)); 2153620737cSbeveloper 2163620737cSbeveloper return result; 2173620737cSbeveloper } 2183620737cSbeveloper 2193620737cSbeveloper status_t 2208b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node & node, List<media_output> *list) 2213620737cSbeveloper { 2223620737cSbeveloper server_publish_outputs_request request; 2233620737cSbeveloper server_publish_outputs_reply reply; 2243620737cSbeveloper media_output *output; 2253620737cSbeveloper media_output *outputs; 2263620737cSbeveloper int32 count; 227a7b41a96Sbeveloper status_t rv; 2283620737cSbeveloper 22976669a29Sbeveloper count = list->CountItems(); 2303620737cSbeveloper TRACE("PublishOutputs: publishing %ld\n", count); 2313620737cSbeveloper 2323620737cSbeveloper request.node = node; 2333620737cSbeveloper request.count = count; 2343620737cSbeveloper if (count > MAX_OUTPUTS) { 2353620737cSbeveloper void *start_addr; 2363620737cSbeveloper size_t size; 23740f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_output)); 2383620737cSbeveloper request.area = create_area("publish outputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 2393620737cSbeveloper if (request.area < B_OK) { 240353b9f6bSbeveloper FATAL("PublishOutputs: failed to create area, %#lx\n", request.area); 2413620737cSbeveloper return (status_t)request.area; 2423620737cSbeveloper } 2433620737cSbeveloper outputs = static_cast<media_output *>(start_addr); 2443620737cSbeveloper } else { 2453620737cSbeveloper request.area = -1; 2463620737cSbeveloper outputs = request.outputs; 2473620737cSbeveloper } 24876669a29Sbeveloper TRACE("PublishOutputs: area %ld\n", request.area); 2493620737cSbeveloper 25076669a29Sbeveloper int i; 25176669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&output); i++) { 25276669a29Sbeveloper ASSERT(i < count); 2533620737cSbeveloper outputs[i] = *output; 2543620737cSbeveloper } 2553620737cSbeveloper 256a7b41a96Sbeveloper rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), &reply, sizeof(reply)); 257a7b41a96Sbeveloper 258a7b41a96Sbeveloper if (request.area != -1) 259a7b41a96Sbeveloper delete_area(request.area); 260a7b41a96Sbeveloper 261a7b41a96Sbeveloper return rv; 2623620737cSbeveloper } 2633620737cSbeveloper 2643620737cSbeveloper status_t 2658b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node & node, List<media_input> *list) 2663620737cSbeveloper { 2673620737cSbeveloper server_publish_inputs_request request; 2683620737cSbeveloper server_publish_inputs_reply reply; 2693620737cSbeveloper media_input *input; 2703620737cSbeveloper media_input *inputs; 2713620737cSbeveloper int32 count; 272a7b41a96Sbeveloper status_t rv; 2733620737cSbeveloper 27476669a29Sbeveloper count = list->CountItems(); 2753620737cSbeveloper TRACE("PublishInputs: publishing %ld\n", count); 2763620737cSbeveloper 2773620737cSbeveloper request.node = node; 2783620737cSbeveloper request.count = count; 2793620737cSbeveloper if (count > MAX_INPUTS) { 2803620737cSbeveloper void *start_addr; 2813620737cSbeveloper size_t size; 28240f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_input)); 2833620737cSbeveloper request.area = create_area("publish inputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 2843620737cSbeveloper if (request.area < B_OK) { 285353b9f6bSbeveloper FATAL("PublishInputs: failed to create area, %#lx\n", request.area); 2863620737cSbeveloper return (status_t)request.area; 2873620737cSbeveloper } 2883620737cSbeveloper inputs = static_cast<media_input *>(start_addr); 2893620737cSbeveloper } else { 2903620737cSbeveloper request.area = -1; 2913620737cSbeveloper inputs = request.inputs; 2923620737cSbeveloper } 29376669a29Sbeveloper TRACE("PublishInputs: area %ld\n", request.area); 2943620737cSbeveloper 29576669a29Sbeveloper int i; 29676669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&input); i++) { 29776669a29Sbeveloper ASSERT(i < count); 2983620737cSbeveloper inputs[i] = *input; 2993620737cSbeveloper } 3003620737cSbeveloper 301a7b41a96Sbeveloper rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), &reply, sizeof(reply)); 302a7b41a96Sbeveloper 303a7b41a96Sbeveloper if (request.area != -1) 304a7b41a96Sbeveloper delete_area(request.area); 305a7b41a96Sbeveloper 306a7b41a96Sbeveloper return rv; 3073620737cSbeveloper } 3083620737cSbeveloper 30952a38012Sejakowatz /************************************************************* 31052a38012Sejakowatz * public BMediaRoster 31152a38012Sejakowatz *************************************************************/ 31252a38012Sejakowatz 31352a38012Sejakowatz status_t 31452a38012Sejakowatz BMediaRoster::GetVideoInput(media_node * out_node) 31552a38012Sejakowatz { 31652a38012Sejakowatz CALLED(); 3178b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(VIDEO_INPUT, out_node); 31852a38012Sejakowatz } 31952a38012Sejakowatz 32052a38012Sejakowatz 32152a38012Sejakowatz status_t 32252a38012Sejakowatz BMediaRoster::GetAudioInput(media_node * out_node) 32352a38012Sejakowatz { 32452a38012Sejakowatz CALLED(); 3258b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_INPUT, out_node); 32652a38012Sejakowatz } 32752a38012Sejakowatz 32852a38012Sejakowatz 32952a38012Sejakowatz status_t 33052a38012Sejakowatz BMediaRoster::GetVideoOutput(media_node * out_node) 33152a38012Sejakowatz { 33252a38012Sejakowatz CALLED(); 3338b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, out_node); 33452a38012Sejakowatz } 33552a38012Sejakowatz 33652a38012Sejakowatz 33752a38012Sejakowatz status_t 33852a38012Sejakowatz BMediaRoster::GetAudioMixer(media_node * out_node) 33952a38012Sejakowatz { 34052a38012Sejakowatz CALLED(); 3418b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_MIXER, out_node); 34252a38012Sejakowatz } 34352a38012Sejakowatz 34452a38012Sejakowatz 34552a38012Sejakowatz status_t 34652a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node) 34752a38012Sejakowatz { 34852a38012Sejakowatz CALLED(); 3498b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, out_node); 35052a38012Sejakowatz } 35152a38012Sejakowatz 35252a38012Sejakowatz 35352a38012Sejakowatz status_t 35452a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node, 35552a38012Sejakowatz int32 * out_input_id, 35652a38012Sejakowatz BString * out_input_name) 35752a38012Sejakowatz { 35852a38012Sejakowatz CALLED(); 3598b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, out_node, out_input_id, out_input_name); 36052a38012Sejakowatz } 36152a38012Sejakowatz 36252a38012Sejakowatz 36352a38012Sejakowatz status_t 36452a38012Sejakowatz BMediaRoster::GetTimeSource(media_node * out_node) 36552a38012Sejakowatz { 36652a38012Sejakowatz CALLED(); 36786bce45bSbeveloper status_t rv; 36886bce45bSbeveloper 36986bce45bSbeveloper // XXX need to do this in a nicer way. 37086bce45bSbeveloper 37186bce45bSbeveloper rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, out_node); 37286bce45bSbeveloper if (rv != B_OK) 37386bce45bSbeveloper return rv; 37486bce45bSbeveloper 37586bce45bSbeveloper // We don't do reference counting for timesources, that's why we 37686bce45bSbeveloper // release the node immediately. 37786bce45bSbeveloper ReleaseNode(*out_node); 37886bce45bSbeveloper 37986bce45bSbeveloper // we need to remember to not use this node with server side reference counting 38086bce45bSbeveloper out_node->kind |= NODE_KIND_NO_REFCOUNTING; 38186bce45bSbeveloper 38286bce45bSbeveloper return B_OK; 38352a38012Sejakowatz } 38452a38012Sejakowatz 38552a38012Sejakowatz 38652a38012Sejakowatz status_t 38752a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node & producer) 38852a38012Sejakowatz { 38952a38012Sejakowatz CALLED(); 3908b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer); 39152a38012Sejakowatz } 39252a38012Sejakowatz 39352a38012Sejakowatz 39452a38012Sejakowatz status_t 39552a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info & producer) 39652a38012Sejakowatz { 39752a38012Sejakowatz CALLED(); 3988b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer); 39952a38012Sejakowatz } 40052a38012Sejakowatz 40152a38012Sejakowatz 40252a38012Sejakowatz status_t 40352a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node & producer) 40452a38012Sejakowatz { 40552a38012Sejakowatz CALLED(); 4068b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer); 40752a38012Sejakowatz } 40852a38012Sejakowatz 40952a38012Sejakowatz 41052a38012Sejakowatz status_t 41152a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info & producer) 41252a38012Sejakowatz { 41352a38012Sejakowatz CALLED(); 4148b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer); 41552a38012Sejakowatz } 41652a38012Sejakowatz 41752a38012Sejakowatz 41852a38012Sejakowatz status_t 41952a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node & consumer) 42052a38012Sejakowatz { 42152a38012Sejakowatz CALLED(); 4228b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer); 42352a38012Sejakowatz } 42452a38012Sejakowatz 42552a38012Sejakowatz 42652a38012Sejakowatz status_t 42752a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info & consumer) 42852a38012Sejakowatz { 42952a38012Sejakowatz CALLED(); 4308b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer); 43152a38012Sejakowatz } 43252a38012Sejakowatz 43352a38012Sejakowatz 43452a38012Sejakowatz status_t 43552a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node & consumer) 43652a38012Sejakowatz { 43752a38012Sejakowatz CALLED(); 4388b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer); 43952a38012Sejakowatz } 44052a38012Sejakowatz 44152a38012Sejakowatz 44252a38012Sejakowatz status_t 44352a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_input & input_to_output) 44452a38012Sejakowatz { 44552a38012Sejakowatz CALLED(); 4468b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input_to_output); 44752a38012Sejakowatz } 44852a38012Sejakowatz 44952a38012Sejakowatz 45052a38012Sejakowatz status_t 45152a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info & consumer) 45252a38012Sejakowatz { 45352a38012Sejakowatz CALLED(); 4548b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer); 45552a38012Sejakowatz } 45652a38012Sejakowatz 45752a38012Sejakowatz 45852a38012Sejakowatz status_t 45952a38012Sejakowatz BMediaRoster::GetNodeFor(media_node_id node, 46052a38012Sejakowatz media_node * clone) 46152a38012Sejakowatz { 4629e9417d2Sbeveloper CALLED(); 4639e9417d2Sbeveloper if (clone == NULL) 4649e9417d2Sbeveloper return B_BAD_VALUE; 4659e9417d2Sbeveloper if (node <= 0) 4669e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 4679e9417d2Sbeveloper 4689e9417d2Sbeveloper server_get_node_for_request request; 4699e9417d2Sbeveloper server_get_node_for_reply reply; 4709e9417d2Sbeveloper status_t rv; 4719e9417d2Sbeveloper 4729e9417d2Sbeveloper request.nodeid = node; 4739e9417d2Sbeveloper request.team = team; 4749e9417d2Sbeveloper 4759e9417d2Sbeveloper rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply)); 4769e9417d2Sbeveloper if (rv != B_OK) 4779e9417d2Sbeveloper return rv; 4789e9417d2Sbeveloper 4799e9417d2Sbeveloper *clone = reply.clone; 4809e9417d2Sbeveloper return B_OK; 48152a38012Sejakowatz } 48252a38012Sejakowatz 48352a38012Sejakowatz 48452a38012Sejakowatz status_t 48552a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node * clone) 48652a38012Sejakowatz { 48752a38012Sejakowatz CALLED(); 48886bce45bSbeveloper status_t rv; 48986bce45bSbeveloper 49086bce45bSbeveloper // XXX need to do this in a nicer way. 49186bce45bSbeveloper 49286bce45bSbeveloper rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone); 49386bce45bSbeveloper if (rv != B_OK) 49486bce45bSbeveloper return rv; 49586bce45bSbeveloper 49686bce45bSbeveloper // We don't do reference counting for timesources, that's why we 49786bce45bSbeveloper // release the node immediately. 49886bce45bSbeveloper ReleaseNode(*clone); 49986bce45bSbeveloper 50086bce45bSbeveloper // we need to remember to not use this node with server side reference counting 50186bce45bSbeveloper clone->kind |= NODE_KIND_NO_REFCOUNTING; 50286bce45bSbeveloper 50386bce45bSbeveloper return B_OK; 50452a38012Sejakowatz } 50552a38012Sejakowatz 50652a38012Sejakowatz 50752a38012Sejakowatz status_t 50852a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node & node) 50952a38012Sejakowatz { 5109e9417d2Sbeveloper CALLED(); 51140f36b03Sbeveloper if (IS_INVALID_NODE(node)) 5129e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 51352a38012Sejakowatz 51486bce45bSbeveloper if (node.kind & NODE_KIND_NO_REFCOUNTING) { 51586bce45bSbeveloper printf("BMediaRoster::ReleaseNode, trying to release reference counting disabled timesource, node %ld, port %ld, team %ld\n", node.node, node.port, team); 51686bce45bSbeveloper return B_OK; 51786bce45bSbeveloper } 51886bce45bSbeveloper 5199e9417d2Sbeveloper server_release_node_request request; 5209e9417d2Sbeveloper server_release_node_reply reply; 521cf4e2277Sbeveloper status_t rv; 5229e9417d2Sbeveloper 5239e9417d2Sbeveloper request.node = node; 5249e9417d2Sbeveloper request.team = team; 5259e9417d2Sbeveloper 52660f15390Sbeveloper TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n", node.node, node.port, team); 527cf4e2277Sbeveloper 528cf4e2277Sbeveloper rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, sizeof(reply)); 529cf4e2277Sbeveloper if (rv != B_OK) { 530cf4e2277Sbeveloper FATAL("BMediaRoster::ReleaseNode FAILED, node %ld, port %ld, team %ld!\n", node.node, node.port, team); 531cf4e2277Sbeveloper } 532cf4e2277Sbeveloper return rv; 5339e9417d2Sbeveloper } 53452a38012Sejakowatz 53552a38012Sejakowatz BTimeSource * 53652a38012Sejakowatz BMediaRoster::MakeTimeSourceFor(const media_node & for_node) 53752a38012Sejakowatz { 538835140c8Sbeveloper CALLED(); 539287f7492Sbeveloper 5400e21b167Sbeveloper BTimeSource *source; 541287f7492Sbeveloper 54260f15390Sbeveloper TRACE("BMediaRoster::MakeTimeSourceFor enter, node %ld, port %ld, kind %#lx\n", for_node.node, for_node.port, for_node.kind); 543287f7492Sbeveloper 5440e21b167Sbeveloper if (0 == (for_node.kind & B_TIME_SOURCE)) { 54560f15390Sbeveloper //FATAL("BMediaRoster::MakeTimeSourceFor, node %ld is not a timesource!\n", for_node.node); 5460e21b167Sbeveloper // XXX It appears that Cortex calls this function on every node, and expects 5470e21b167Sbeveloper // XXX to be returned a system time source if the for_node is not a timesource 5480e21b167Sbeveloper media_node clone; 5490e21b167Sbeveloper GetSystemTimeSource(&clone); 5500e21b167Sbeveloper source = _TimeSourceObjectManager->GetTimeSource(clone); 55186bce45bSbeveloper // ReleaseNode(clone); 5520e21b167Sbeveloper } else { 5530e21b167Sbeveloper source = _TimeSourceObjectManager->GetTimeSource(for_node); 5540e21b167Sbeveloper } 5550e21b167Sbeveloper 55660f15390Sbeveloper TRACE("BMediaRoster::MakeTimeSourceFor leave, node %ld, port %ld, kind %#lx\n", source->Node().node, source->Node().port, source->Node().kind); 557287f7492Sbeveloper 558835140c8Sbeveloper return source; 55952a38012Sejakowatz } 56052a38012Sejakowatz 56152a38012Sejakowatz 56252a38012Sejakowatz status_t 56352a38012Sejakowatz BMediaRoster::Connect(const media_source & from, 56452a38012Sejakowatz const media_destination & to, 56552a38012Sejakowatz media_format * io_format, 56652a38012Sejakowatz media_output * out_output, 56752a38012Sejakowatz media_input * out_input) 56852a38012Sejakowatz { 569eae26d3dSbeveloper return BMediaRoster::Connect(from, to, io_format, out_output, out_input, 0); 570eae26d3dSbeveloper } 571eae26d3dSbeveloper 572eae26d3dSbeveloper 573eae26d3dSbeveloper status_t 574eae26d3dSbeveloper BMediaRoster::Connect(const media_source & from, 575eae26d3dSbeveloper const media_destination & to, 576eae26d3dSbeveloper media_format * io_format, 577eae26d3dSbeveloper media_output * out_output, 578eae26d3dSbeveloper media_input * out_input, 579eae26d3dSbeveloper uint32 in_flags, 580eae26d3dSbeveloper void * _reserved) 581eae26d3dSbeveloper { 58252a38012Sejakowatz CALLED(); 58352a38012Sejakowatz if (io_format == NULL || out_output == NULL || out_input == NULL) 58452a38012Sejakowatz return B_BAD_VALUE; 58540f36b03Sbeveloper if (IS_INVALID_SOURCE(from)) { 586353b9f6bSbeveloper FATAL("BMediaRoster::Connect: media_source invalid\n"); 58752a38012Sejakowatz return B_MEDIA_BAD_SOURCE; 5889e9417d2Sbeveloper } 58940f36b03Sbeveloper if (IS_INVALID_DESTINATION(to)) { 590353b9f6bSbeveloper FATAL("BMediaRoster::Connect: media_destination invalid\n"); 59152a38012Sejakowatz return B_MEDIA_BAD_DESTINATION; 5929e9417d2Sbeveloper } 59352a38012Sejakowatz 59452a38012Sejakowatz status_t rv; 5958c6a6096Sbeveloper producer_format_proposal_request request1; 5968c6a6096Sbeveloper producer_format_proposal_reply reply1; 59752a38012Sejakowatz 59852a38012Sejakowatz // BBufferProducer::FormatProposal 5998c6a6096Sbeveloper request1.output = from; 6008c6a6096Sbeveloper request1.format = *io_format; 6018c6a6096Sbeveloper rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, sizeof(request1), &reply1, sizeof(reply1)); 6028c6a6096Sbeveloper if (rv != B_OK) { 603353b9f6bSbeveloper FATAL("BMediaRoster::Connect: aborted after BBufferProducer::FormatProposal, status = %#lx\n",rv); 60452a38012Sejakowatz return rv; 60552a38012Sejakowatz } 6068c6a6096Sbeveloper // reply1.format now contains the format proposed by the producer 6078c6a6096Sbeveloper 6088c6a6096Sbeveloper consumer_accept_format_request request2; 6098c6a6096Sbeveloper consumer_accept_format_reply reply2; 6108c6a6096Sbeveloper 6118c6a6096Sbeveloper // BBufferConsumer::AcceptFormat 6128c6a6096Sbeveloper request2.dest = to; 6138c6a6096Sbeveloper request2.format = reply1.format; 6148c6a6096Sbeveloper rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, sizeof(request2), &reply2, sizeof(reply2)); 6158c6a6096Sbeveloper if (rv != B_OK) { 616353b9f6bSbeveloper FATAL("BMediaRoster::Connect: aborted after BBufferConsumer::AcceptFormat, status = %#lx\n",rv); 6178c6a6096Sbeveloper return rv; 6188c6a6096Sbeveloper } 6198c6a6096Sbeveloper // reply2.format now contains the format accepted by the consumer 6208c6a6096Sbeveloper 6218c6a6096Sbeveloper // BBufferProducer::PrepareToConnect 6228c6a6096Sbeveloper producer_prepare_to_connect_request request3; 6238c6a6096Sbeveloper producer_prepare_to_connect_reply reply3; 6248c6a6096Sbeveloper 6258c6a6096Sbeveloper request3.source = from; 6268c6a6096Sbeveloper request3.destination = to; 6278c6a6096Sbeveloper request3.format = reply2.format; 6288c6a6096Sbeveloper strcpy(request3.name, "XXX some default name"); // XXX fix this 6298c6a6096Sbeveloper rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, sizeof(request3), &reply3, sizeof(reply3)); 6308c6a6096Sbeveloper if (rv != B_OK) { 631353b9f6bSbeveloper FATAL("BMediaRoster::Connect: aborted after BBufferProducer::PrepareToConnect, status = %#lx\n",rv); 6328c6a6096Sbeveloper return rv; 6338c6a6096Sbeveloper } 6348c6a6096Sbeveloper // reply3.format is still our pretty media format 6358c6a6096Sbeveloper // reply3.out_source the real source to be used for the connection 6368c6a6096Sbeveloper // reply3.name the name BBufferConsumer::Connected will see in the outInput->name argument 6378c6a6096Sbeveloper 6388c6a6096Sbeveloper // BBufferConsumer::Connected 6398c6a6096Sbeveloper consumer_connected_request request4; 6408c6a6096Sbeveloper consumer_connected_reply reply4; 6418c6a6096Sbeveloper status_t con_status; 6428c6a6096Sbeveloper 6438c6a6096Sbeveloper request4.producer = reply3.out_source; 6448c6a6096Sbeveloper request4.where = to; 6458c6a6096Sbeveloper request4.with_format = reply3.format; 6468c6a6096Sbeveloper con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, sizeof(request4), &reply4, sizeof(reply4)); 6478c6a6096Sbeveloper if (con_status != B_OK) { 648353b9f6bSbeveloper FATAL("BMediaRoster::Connect: aborting after BBufferConsumer::Connected, status = %#lx\n",con_status); 6498c6a6096Sbeveloper // we do NOT return here! 6508c6a6096Sbeveloper } 6518c6a6096Sbeveloper // con_status contains the status code to be supplied to BBufferProducer::Connect's status argument 6528c6a6096Sbeveloper // reply4.input contains the media_input that describes the connection from the consumer point of view 6538c6a6096Sbeveloper 6548c6a6096Sbeveloper // BBufferProducer::Connect 6558c6a6096Sbeveloper producer_connect_request request5; 6568c6a6096Sbeveloper producer_connect_reply reply5; 6578c6a6096Sbeveloper 6588c6a6096Sbeveloper request5.error = con_status; 6598c6a6096Sbeveloper request5.source = reply3.out_source; 6608c6a6096Sbeveloper request5.destination = reply4.input.destination; 6618c6a6096Sbeveloper request5.format = reply3.format; // XXX reply4.input.format ??? 6628c6a6096Sbeveloper strcpy(request5.name, reply4.input.name); 6630caff283Sbeveloper rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, sizeof(request5), &reply5, sizeof(reply5)); 6648c6a6096Sbeveloper if (con_status != B_OK) { 665353b9f6bSbeveloper FATAL("BMediaRoster::Connect: aborted\n"); 6668c6a6096Sbeveloper return con_status; 6678c6a6096Sbeveloper } 6688c6a6096Sbeveloper if (rv != B_OK) { 669353b9f6bSbeveloper FATAL("BMediaRoster::Connect: aborted after BBufferProducer::Connect, status = %#lx\n",rv); 6708c6a6096Sbeveloper return rv; 6718c6a6096Sbeveloper } 6728c6a6096Sbeveloper // reply5.name contains the name assigned to the connection by the producer 6738c6a6096Sbeveloper 6748c6a6096Sbeveloper // find the output node 6758c6a6096Sbeveloper // XXX isn't there a easier way? 6768c6a6096Sbeveloper media_node sourcenode; 6778c6a6096Sbeveloper GetNodeFor(NodeIDFor(from.port), &sourcenode); 6788c6a6096Sbeveloper ReleaseNode(sourcenode); 6798c6a6096Sbeveloper 6808c6a6096Sbeveloper // initilize connection info 6818c6a6096Sbeveloper *io_format = reply3.format; 6828c6a6096Sbeveloper *out_input = reply4.input; 6838c6a6096Sbeveloper out_output->node = sourcenode; 6848c6a6096Sbeveloper out_output->source = reply4.input.source; 6858c6a6096Sbeveloper out_output->destination = reply4.input.destination; 6868c6a6096Sbeveloper out_output->format = reply4.input.format; 6878c6a6096Sbeveloper strcpy(out_output->name, reply5.name); 6888c6a6096Sbeveloper 6898c6a6096Sbeveloper // the connection is now made 6908c6a6096Sbeveloper 6918c6a6096Sbeveloper 6928c6a6096Sbeveloper // XXX register connection with server 6939e9417d2Sbeveloper // XXX we should just send a notification, instead of republishing all endpoints 69476669a29Sbeveloper List<media_output> outlist; 69576669a29Sbeveloper List<media_input> inlist; 6968b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist)) 6978b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist); 6988b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist)) 6998b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(out_input->node, &inlist); 7008c6a6096Sbeveloper 7018c6a6096Sbeveloper 7028c6a6096Sbeveloper // XXX if (mute) BBufferProducer::EnableOutput(false) 7039e9417d2Sbeveloper if (in_flags & B_CONNECT_MUTED) { 7049e9417d2Sbeveloper } 7058c6a6096Sbeveloper 7068c6a6096Sbeveloper 7079e9417d2Sbeveloper // send a notification 7089e9417d2Sbeveloper BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, *io_format); 7099e9417d2Sbeveloper 7108c6a6096Sbeveloper return B_OK; 7118c6a6096Sbeveloper }; 71252a38012Sejakowatz 71352a38012Sejakowatz 71452a38012Sejakowatz status_t 7159e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid, 71652a38012Sejakowatz const media_source & source, 7179e9417d2Sbeveloper media_node_id destination_nodeid, 71852a38012Sejakowatz const media_destination & destination) 71952a38012Sejakowatz { 7209e9417d2Sbeveloper CALLED(); 72140f36b03Sbeveloper if (IS_INVALID_NODEID(source_nodeid)) { 722353b9f6bSbeveloper FATAL("BMediaRoster::Disconnect: source media_node_id invalid\n"); 7239e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 7249e9417d2Sbeveloper } 72540f36b03Sbeveloper if (IS_INVALID_NODEID(destination_nodeid)) { 72640f36b03Sbeveloper FATAL("BMediaRoster::Disconnect: destination media_node_id invalid\n"); 7279e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 7289e9417d2Sbeveloper } 72940f36b03Sbeveloper if (IS_INVALID_SOURCE(source)) { 730353b9f6bSbeveloper FATAL("BMediaRoster::Disconnect: media_source invalid\n"); 7319e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 7329e9417d2Sbeveloper } 73340f36b03Sbeveloper if (IS_INVALID_DESTINATION(destination)) { 734353b9f6bSbeveloper FATAL("BMediaRoster::Disconnect: media_destination invalid\n"); 7359e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 7369e9417d2Sbeveloper } 7379e9417d2Sbeveloper 7389e9417d2Sbeveloper producer_disconnect_request request2; 7399e9417d2Sbeveloper producer_disconnect_reply reply2; 7409e9417d2Sbeveloper consumer_disconnected_request request1; 7419e9417d2Sbeveloper consumer_disconnected_reply reply1; 7429e9417d2Sbeveloper status_t rv1, rv2; 7439e9417d2Sbeveloper 7449e9417d2Sbeveloper // XXX we should ask the server if this connection really exists 7459e9417d2Sbeveloper 7469e9417d2Sbeveloper request1.source = source; 7479e9417d2Sbeveloper request1.destination = destination; 7489e9417d2Sbeveloper request2.source = source; 7499e9417d2Sbeveloper request2.destination = destination; 7509e9417d2Sbeveloper 7519e9417d2Sbeveloper rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, sizeof(request1), &reply1, sizeof(reply1)); 7529e9417d2Sbeveloper rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, sizeof(request2), &reply2, sizeof(reply2)); 7539e9417d2Sbeveloper 7549e9417d2Sbeveloper // XXX unregister connection with server 7559e9417d2Sbeveloper // XXX we should just send a notification, instead of republishing all endpoints 75676669a29Sbeveloper List<media_output> outlist; 75776669a29Sbeveloper List<media_input> inlist; 7589e9417d2Sbeveloper media_node sourcenode; 7599e9417d2Sbeveloper media_node destnode; 7609e9417d2Sbeveloper if (B_OK == GetNodeFor(source_nodeid, &sourcenode)) { 7618b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist)) 7628b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist); 7639e9417d2Sbeveloper ReleaseNode(sourcenode); 764353b9f6bSbeveloper } else FATAL("BMediaRoster::Disconnect: source GetNodeFor failed\n"); 7659e9417d2Sbeveloper if (B_OK == GetNodeFor(destination_nodeid, &destnode)) { 7668b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllInputs(destnode , &inlist)) 7678b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(destnode, &inlist); 7689e9417d2Sbeveloper ReleaseNode(destnode); 769353b9f6bSbeveloper } else FATAL("BMediaRoster::Disconnect: dest GetNodeFor failed\n"); 7709e9417d2Sbeveloper 7719e9417d2Sbeveloper 7729e9417d2Sbeveloper // send a notification 7739e9417d2Sbeveloper BPrivate::media::notifications::ConnectionBroken(source, destination); 7749e9417d2Sbeveloper 7759e9417d2Sbeveloper return (rv1 != B_OK || rv2 != B_OK) ? B_ERROR : B_OK; 77652a38012Sejakowatz } 77752a38012Sejakowatz 77852a38012Sejakowatz 77952a38012Sejakowatz status_t 78052a38012Sejakowatz BMediaRoster::StartNode(const media_node & node, 78152a38012Sejakowatz bigtime_t at_performance_time) 78252a38012Sejakowatz { 78352a38012Sejakowatz CALLED(); 7849e9417d2Sbeveloper if (node.node <= 0) 78552a38012Sejakowatz return B_MEDIA_BAD_NODE; 78652a38012Sejakowatz 78760f15390Sbeveloper TRACE("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node, at_performance_time); 7880e21b167Sbeveloper 7896396865dSbeveloper node_start_command command; 7906396865dSbeveloper command.performance_time = at_performance_time; 79152a38012Sejakowatz 7926396865dSbeveloper return SendToPort(node.port, NODE_START, &command, sizeof(command)); 79352a38012Sejakowatz } 79452a38012Sejakowatz 79552a38012Sejakowatz 79652a38012Sejakowatz status_t 79752a38012Sejakowatz BMediaRoster::StopNode(const media_node & node, 79852a38012Sejakowatz bigtime_t at_performance_time, 79952a38012Sejakowatz bool immediate) 80052a38012Sejakowatz { 80152a38012Sejakowatz CALLED(); 80240f36b03Sbeveloper if (IS_INVALID_NODE(node)) 80352a38012Sejakowatz return B_MEDIA_BAD_NODE; 80452a38012Sejakowatz 80560f15390Sbeveloper TRACE("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node, at_performance_time, immediate ? "NOW" : ""); 8060e21b167Sbeveloper 8076396865dSbeveloper node_stop_command command; 8086396865dSbeveloper command.performance_time = at_performance_time; 8096396865dSbeveloper command.immediate = immediate; 81052a38012Sejakowatz 8116396865dSbeveloper return SendToPort(node.port, NODE_STOP, &command, sizeof(command)); 81252a38012Sejakowatz } 81352a38012Sejakowatz 81452a38012Sejakowatz 81552a38012Sejakowatz status_t 81652a38012Sejakowatz BMediaRoster::SeekNode(const media_node & node, 81752a38012Sejakowatz bigtime_t to_media_time, 81852a38012Sejakowatz bigtime_t at_performance_time) 81952a38012Sejakowatz { 82052a38012Sejakowatz CALLED(); 82140f36b03Sbeveloper if (IS_INVALID_NODE(node)) 82252a38012Sejakowatz return B_MEDIA_BAD_NODE; 82352a38012Sejakowatz 82460f15390Sbeveloper TRACE("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n", node.node, at_performance_time, to_media_time); 8250e21b167Sbeveloper 8266396865dSbeveloper node_seek_command command; 8276396865dSbeveloper command.media_time = to_media_time; 8286396865dSbeveloper command.performance_time = at_performance_time; 82952a38012Sejakowatz 8306396865dSbeveloper return SendToPort(node.port, NODE_SEEK, &command, sizeof(command)); 83152a38012Sejakowatz } 83252a38012Sejakowatz 83352a38012Sejakowatz 83452a38012Sejakowatz status_t 83552a38012Sejakowatz BMediaRoster::StartTimeSource(const media_node & node, 83652a38012Sejakowatz bigtime_t at_real_time) 83752a38012Sejakowatz { 83852a38012Sejakowatz CALLED(); 83960f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 84060f15390Sbeveloper // XXX debug this 84160f15390Sbeveloper //FATAL("BMediaRoster::StartTimeSource node %ld is system timesource\n", node.node); 84260f15390Sbeveloper return B_OK; 84360f15390Sbeveloper } 84460f15390Sbeveloper if (IS_SHADOW_TIMESOURCE(node)) { 84560f15390Sbeveloper // XXX debug this 84660f15390Sbeveloper FATAL("BMediaRoster::StartTimeSource node %ld is shadow timesource\n", node.node); 84760f15390Sbeveloper return B_OK; 84860f15390Sbeveloper } 84940f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 85060f15390Sbeveloper FATAL("BMediaRoster::StartTimeSource node %ld invalid\n", node.node); 85152a38012Sejakowatz return B_MEDIA_BAD_NODE; 8520e21b167Sbeveloper } 8530e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 85460f15390Sbeveloper FATAL("BMediaRoster::StartTimeSource node %ld is no timesource\n", node.node); 85552a38012Sejakowatz return B_MEDIA_BAD_NODE; 8560e21b167Sbeveloper } 8570e21b167Sbeveloper 85860f15390Sbeveloper TRACE("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node, at_real_time); 85952a38012Sejakowatz 86052a38012Sejakowatz BTimeSource::time_source_op_info msg; 86152a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_START; 86252a38012Sejakowatz msg.real_time = at_real_time; 86352a38012Sejakowatz 86452a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 86552a38012Sejakowatz } 86652a38012Sejakowatz 86752a38012Sejakowatz 86852a38012Sejakowatz status_t 86952a38012Sejakowatz BMediaRoster::StopTimeSource(const media_node & node, 87052a38012Sejakowatz bigtime_t at_real_time, 87152a38012Sejakowatz bool immediate) 87252a38012Sejakowatz { 87352a38012Sejakowatz CALLED(); 87460f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 87560f15390Sbeveloper // XXX debug this 87660f15390Sbeveloper //FATAL("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node); 87760f15390Sbeveloper return B_OK; 87860f15390Sbeveloper } 87960f15390Sbeveloper if (IS_SHADOW_TIMESOURCE(node)) { 88060f15390Sbeveloper // XXX debug this 88160f15390Sbeveloper FATAL("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node); 88260f15390Sbeveloper return B_OK; 88360f15390Sbeveloper } 88440f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 88560f15390Sbeveloper FATAL("BMediaRoster::StopTimeSource node %ld invalid\n", node.node); 88652a38012Sejakowatz return B_MEDIA_BAD_NODE; 8870e21b167Sbeveloper } 8880e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 88960f15390Sbeveloper FATAL("BMediaRoster::StopTimeSource node %ld is no timesource\n", node.node); 89052a38012Sejakowatz return B_MEDIA_BAD_NODE; 8910e21b167Sbeveloper } 8920e21b167Sbeveloper 89360f15390Sbeveloper TRACE("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n", node.node, at_real_time, immediate ? "NOW" : ""); 89452a38012Sejakowatz 89552a38012Sejakowatz BTimeSource::time_source_op_info msg; 89652a38012Sejakowatz msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY : BTimeSource::B_TIMESOURCE_STOP; 89752a38012Sejakowatz msg.real_time = at_real_time; 89852a38012Sejakowatz 89952a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 90052a38012Sejakowatz } 90152a38012Sejakowatz 90252a38012Sejakowatz 90352a38012Sejakowatz status_t 90452a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node & node, 90552a38012Sejakowatz bigtime_t to_performance_time, 90652a38012Sejakowatz bigtime_t at_real_time) 90752a38012Sejakowatz { 90852a38012Sejakowatz CALLED(); 90960f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 91060f15390Sbeveloper // XXX debug this 91160f15390Sbeveloper // FATAL("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node); 91260f15390Sbeveloper // you can't seek the system time source, but 91360f15390Sbeveloper // returning B_ERROR would break StampTV 91460f15390Sbeveloper return B_OK; 91560f15390Sbeveloper } 91660f15390Sbeveloper if (IS_SHADOW_TIMESOURCE(node)) { 91760f15390Sbeveloper // XXX debug this 91860f15390Sbeveloper FATAL("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node); 91960f15390Sbeveloper return B_OK; 92060f15390Sbeveloper } 92140f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 92260f15390Sbeveloper FATAL("BMediaRoster::SeekTimeSource node %ld invalid\n", node.node); 92352a38012Sejakowatz return B_MEDIA_BAD_NODE; 9240e21b167Sbeveloper } 9250e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 92660f15390Sbeveloper FATAL("BMediaRoster::SeekTimeSource node %ld is no timesource\n", node.node); 92752a38012Sejakowatz return B_MEDIA_BAD_NODE; 9280e21b167Sbeveloper } 9290e21b167Sbeveloper 93060f15390Sbeveloper TRACE("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n", node.node, at_real_time, to_performance_time); 93152a38012Sejakowatz 93252a38012Sejakowatz BTimeSource::time_source_op_info msg; 93352a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_SEEK; 93452a38012Sejakowatz msg.real_time = at_real_time; 93552a38012Sejakowatz msg.performance_time = to_performance_time; 93652a38012Sejakowatz 93752a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 93852a38012Sejakowatz } 93952a38012Sejakowatz 94052a38012Sejakowatz 94152a38012Sejakowatz status_t 94252a38012Sejakowatz BMediaRoster::SyncToNode(const media_node & node, 94352a38012Sejakowatz bigtime_t at_time, 94452a38012Sejakowatz bigtime_t timeout) 94552a38012Sejakowatz { 94652a38012Sejakowatz UNIMPLEMENTED(); 94760f15390Sbeveloper return B_OK; 94852a38012Sejakowatz } 94952a38012Sejakowatz 95052a38012Sejakowatz 95152a38012Sejakowatz status_t 95252a38012Sejakowatz BMediaRoster::SetRunModeNode(const media_node & node, 95352a38012Sejakowatz BMediaNode::run_mode mode) 95452a38012Sejakowatz { 95552a38012Sejakowatz CALLED(); 95640f36b03Sbeveloper if (IS_INVALID_NODE(node)) 95752a38012Sejakowatz return B_MEDIA_BAD_NODE; 95852a38012Sejakowatz 959dfb2ad61Sbeveloper node_set_run_mode_command msg; 96052a38012Sejakowatz msg.mode = mode; 96152a38012Sejakowatz 96252a38012Sejakowatz return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg)); 96352a38012Sejakowatz } 96452a38012Sejakowatz 96552a38012Sejakowatz 96652a38012Sejakowatz status_t 96752a38012Sejakowatz BMediaRoster::PrerollNode(const media_node & node) 96852a38012Sejakowatz { 96952a38012Sejakowatz CALLED(); 97040f36b03Sbeveloper if (IS_INVALID_NODE(node)) 97152a38012Sejakowatz return B_MEDIA_BAD_NODE; 97252a38012Sejakowatz 97352a38012Sejakowatz char dummy; 97452a38012Sejakowatz return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy)); 97552a38012Sejakowatz } 97652a38012Sejakowatz 97752a38012Sejakowatz 97852a38012Sejakowatz status_t 97952a38012Sejakowatz BMediaRoster::RollNode(const media_node & node, 98052a38012Sejakowatz bigtime_t startPerformance, 98152a38012Sejakowatz bigtime_t stopPerformance, 98252a38012Sejakowatz bigtime_t atMediaTime) 98352a38012Sejakowatz { 98452a38012Sejakowatz UNIMPLEMENTED(); 98552a38012Sejakowatz return B_ERROR; 98652a38012Sejakowatz } 98752a38012Sejakowatz 98852a38012Sejakowatz 98952a38012Sejakowatz status_t 99052a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node & node, 99152a38012Sejakowatz bigtime_t delay, 99252a38012Sejakowatz BMediaNode::run_mode mode) 99352a38012Sejakowatz { 99460f15390Sbeveloper CALLED(); 99560f15390Sbeveloper if (IS_INVALID_NODE(node)) 99660f15390Sbeveloper return B_MEDIA_BAD_NODE; 99760f15390Sbeveloper if ((node.kind & B_BUFFER_PRODUCER) == 0) 99860f15390Sbeveloper return B_MEDIA_BAD_NODE; 99960f15390Sbeveloper 100060f15390Sbeveloper producer_set_run_mode_delay_command command; 100160f15390Sbeveloper command.mode = mode; 100260f15390Sbeveloper command.delay = delay; 100360f15390Sbeveloper 100460f15390Sbeveloper return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command, sizeof(command)); 100552a38012Sejakowatz } 100652a38012Sejakowatz 100752a38012Sejakowatz 100852a38012Sejakowatz status_t 100952a38012Sejakowatz BMediaRoster::SetProducerRate(const media_node & producer, 101052a38012Sejakowatz int32 numer, 101152a38012Sejakowatz int32 denom) 101252a38012Sejakowatz { 101352a38012Sejakowatz CALLED(); 101440f36b03Sbeveloper if (IS_INVALID_NODE(producer)) 101552a38012Sejakowatz return B_MEDIA_BAD_NODE; 101652a38012Sejakowatz if ((producer.kind & B_BUFFER_PRODUCER) == 0) 101752a38012Sejakowatz return B_MEDIA_BAD_NODE; 101852a38012Sejakowatz 1019dfb2ad61Sbeveloper producer_set_play_rate_request msg; 1020dfb2ad61Sbeveloper producer_set_play_rate_reply reply; 102152a38012Sejakowatz status_t rv; 102252a38012Sejakowatz int32 code; 102352a38012Sejakowatz 102452a38012Sejakowatz msg.numer = numer; 102552a38012Sejakowatz msg.denom = denom; 102652a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 102752a38012Sejakowatz rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg)); 102852a38012Sejakowatz if (rv != B_OK) { 102952a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 103052a38012Sejakowatz return rv; 103152a38012Sejakowatz } 103252a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 103352a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 103452a38012Sejakowatz return (rv < B_OK) ? rv : reply.result; 103552a38012Sejakowatz } 103652a38012Sejakowatz 103752a38012Sejakowatz 103852a38012Sejakowatz /* Nodes will have available inputs/outputs as long as they are capable */ 103952a38012Sejakowatz /* of accepting more connections. The node may create an additional */ 104052a38012Sejakowatz /* output or input as the currently available is taken into usage. */ 104152a38012Sejakowatz status_t 104252a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node & node, 104352a38012Sejakowatz live_node_info * out_live_info) 104452a38012Sejakowatz { 10459e9417d2Sbeveloper CALLED(); 10469e9417d2Sbeveloper if (out_live_info == NULL) 10479e9417d2Sbeveloper return B_BAD_VALUE; 104840f36b03Sbeveloper if (IS_INVALID_NODE(node)) 10499e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 10509e9417d2Sbeveloper 10519e9417d2Sbeveloper server_get_live_node_info_request request; 10529e9417d2Sbeveloper server_get_live_node_info_reply reply; 10539e9417d2Sbeveloper status_t rv; 10549e9417d2Sbeveloper 10559e9417d2Sbeveloper request.node = node; 10569e9417d2Sbeveloper 10571299bfb2Sbeveloper rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), &reply, sizeof(reply)); 10589e9417d2Sbeveloper if (rv != B_OK) 10599e9417d2Sbeveloper return rv; 10609e9417d2Sbeveloper 10619e9417d2Sbeveloper *out_live_info = reply.live_info; 10629e9417d2Sbeveloper return B_OK; 106352a38012Sejakowatz } 106452a38012Sejakowatz 106552a38012Sejakowatz 106652a38012Sejakowatz status_t 106752a38012Sejakowatz BMediaRoster::GetLiveNodes(live_node_info * out_live_nodes, 106852a38012Sejakowatz int32 * io_total_count, 106952a38012Sejakowatz const media_format * has_input, 107052a38012Sejakowatz const media_format * has_output, 107152a38012Sejakowatz const char * name, 107252a38012Sejakowatz uint64 node_kinds) 107352a38012Sejakowatz { 10749e9417d2Sbeveloper CALLED(); 10759e9417d2Sbeveloper if (out_live_nodes == NULL || io_total_count == NULL) 10769e9417d2Sbeveloper return B_BAD_VALUE; 10779e9417d2Sbeveloper if (*io_total_count <= 0) 10789e9417d2Sbeveloper return B_BAD_VALUE; 10799e9417d2Sbeveloper 10809e9417d2Sbeveloper // XXX we also support the wildcard search as GetDormantNodes does. This needs to be documented 10819e9417d2Sbeveloper 10829e9417d2Sbeveloper server_get_live_nodes_request request; 10839e9417d2Sbeveloper server_get_live_nodes_reply reply; 10849e9417d2Sbeveloper status_t rv; 10859e9417d2Sbeveloper 10869e9417d2Sbeveloper request.maxcount = *io_total_count; 10879e9417d2Sbeveloper request.has_input = (bool) has_input; 10889e9417d2Sbeveloper if (has_input) 10899e9417d2Sbeveloper request.inputformat = *has_input; // XXX we should not make a flat copy of media_format 10909e9417d2Sbeveloper request.has_output = (bool) has_output; 10919e9417d2Sbeveloper if (has_output) 10929e9417d2Sbeveloper request.outputformat = *has_output; // XXX we should not make a flat copy of media_format 10939e9417d2Sbeveloper request.has_name = (bool) name; 10949e9417d2Sbeveloper if (name) { 10959e9417d2Sbeveloper int len = strlen(name); 10969e9417d2Sbeveloper len = min_c(len, (int)sizeof(request.name) - 1); 10979e9417d2Sbeveloper memcpy(request.name, name, len); 10989e9417d2Sbeveloper request.name[len] = 0; 10999e9417d2Sbeveloper } 11009e9417d2Sbeveloper request.require_kinds = node_kinds; 11019e9417d2Sbeveloper 11029e9417d2Sbeveloper rv = QueryServer(SERVER_GET_LIVE_NODES, &request, sizeof(request), &reply, sizeof(reply)); 11039e9417d2Sbeveloper if (rv != B_OK) { 1104353b9f6bSbeveloper FATAL("BMediaRoster::GetLiveNodes failed\n"); 11051299bfb2Sbeveloper *io_total_count = 0; 11069e9417d2Sbeveloper return rv; 11079e9417d2Sbeveloper } 11089e9417d2Sbeveloper 11099e9417d2Sbeveloper if (reply.count > MAX_LIVE_INFO) { 11109e9417d2Sbeveloper live_node_info *live_info; 11119e9417d2Sbeveloper area_id clone; 11129e9417d2Sbeveloper 11139e9417d2Sbeveloper clone = clone_area("live_node_info clone", reinterpret_cast<void **>(&live_info), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, reply.area); 11149e9417d2Sbeveloper if (clone < B_OK) { 1115353b9f6bSbeveloper FATAL("BMediaRoster::GetLiveNodes failed to clone area, %#lx\n", clone); 11169e9417d2Sbeveloper delete_area(reply.area); 11171299bfb2Sbeveloper *io_total_count = 0; 111852a38012Sejakowatz return B_ERROR; 111952a38012Sejakowatz } 112052a38012Sejakowatz 11219e9417d2Sbeveloper for (int32 i = 0; i < reply.count; i++) { 11229e9417d2Sbeveloper out_live_nodes[i] = live_info[i]; 11239e9417d2Sbeveloper } 11249e9417d2Sbeveloper 11259e9417d2Sbeveloper delete_area(clone); 11269e9417d2Sbeveloper delete_area(reply.area); 11279e9417d2Sbeveloper } else { 11289e9417d2Sbeveloper for (int32 i = 0; i < reply.count; i++) { 11299e9417d2Sbeveloper out_live_nodes[i] = reply.live_info[i]; 11309e9417d2Sbeveloper } 11319e9417d2Sbeveloper } 11329e9417d2Sbeveloper *io_total_count = reply.count; 11339e9417d2Sbeveloper 11349e9417d2Sbeveloper return B_OK; 11359e9417d2Sbeveloper } 11369e9417d2Sbeveloper 113752a38012Sejakowatz 113852a38012Sejakowatz status_t 113952a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node & node, 114052a38012Sejakowatz media_input * out_free_inputs, 114152a38012Sejakowatz int32 buf_num_inputs, 114252a38012Sejakowatz int32 * out_total_count, 114352a38012Sejakowatz media_type filter_type) 114452a38012Sejakowatz { 11453620737cSbeveloper CALLED(); 114640f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 11473620737cSbeveloper return B_MEDIA_BAD_NODE; 11483620737cSbeveloper if (out_free_inputs == NULL || out_total_count == NULL) 11493620737cSbeveloper return B_BAD_VALUE; 11503620737cSbeveloper 115176669a29Sbeveloper List<media_input> list; 11523620737cSbeveloper media_input *input; 11533620737cSbeveloper status_t rv; 11543620737cSbeveloper 11551299bfb2Sbeveloper *out_total_count = 0; 11561299bfb2Sbeveloper 11578b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 11583620737cSbeveloper if (B_OK != rv) 11593620737cSbeveloper return rv; 11603620737cSbeveloper 116176669a29Sbeveloper int32 i; 116276669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&input); i++) { 11633620737cSbeveloper if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != input->format.type) 11643620737cSbeveloper continue; // media_type used, but doesn't match 11653620737cSbeveloper if (input->source != media_source::null) 11663620737cSbeveloper continue; // consumer source already connected 11673620737cSbeveloper out_free_inputs[i] = *input; 11683620737cSbeveloper *out_total_count += 1; 11693620737cSbeveloper buf_num_inputs -= 1; 11703620737cSbeveloper if (buf_num_inputs == 0) 11713620737cSbeveloper break; 11723620737cSbeveloper } 11733620737cSbeveloper 11748b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 11753620737cSbeveloper return B_OK; 117652a38012Sejakowatz } 117752a38012Sejakowatz 117852a38012Sejakowatz 117952a38012Sejakowatz status_t 118052a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node & node, 118152a38012Sejakowatz media_input * out_active_inputs, 118252a38012Sejakowatz int32 buf_num_inputs, 118352a38012Sejakowatz int32 * out_total_count) 118452a38012Sejakowatz { 11853620737cSbeveloper CALLED(); 118640f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 11873620737cSbeveloper return B_MEDIA_BAD_NODE; 11883620737cSbeveloper if (out_active_inputs == NULL || out_total_count == NULL) 11893620737cSbeveloper return B_BAD_VALUE; 11903620737cSbeveloper 119176669a29Sbeveloper List<media_input> list; 11923620737cSbeveloper media_input *input; 11933620737cSbeveloper status_t rv; 11943620737cSbeveloper 11951299bfb2Sbeveloper *out_total_count = 0; 11961299bfb2Sbeveloper 11978b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 11983620737cSbeveloper if (B_OK != rv) 11993620737cSbeveloper return rv; 12003620737cSbeveloper 120176669a29Sbeveloper int32 i; 120276669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&input); i++) { 12033620737cSbeveloper if (input->source == media_source::null) 12043620737cSbeveloper continue; // consumer source not connected 12053620737cSbeveloper out_active_inputs[i] = *input; 12063620737cSbeveloper *out_total_count += 1; 12073620737cSbeveloper buf_num_inputs -= 1; 12083620737cSbeveloper if (buf_num_inputs == 0) 12093620737cSbeveloper break; 12103620737cSbeveloper } 12113620737cSbeveloper 12128b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 12133620737cSbeveloper return B_OK; 121452a38012Sejakowatz } 121552a38012Sejakowatz 121652a38012Sejakowatz 121752a38012Sejakowatz status_t 121852a38012Sejakowatz BMediaRoster::GetAllInputsFor(const media_node & node, 121952a38012Sejakowatz media_input * out_inputs, 122052a38012Sejakowatz int32 buf_num_inputs, 122152a38012Sejakowatz int32 * out_total_count) 122252a38012Sejakowatz { 122352a38012Sejakowatz CALLED(); 122440f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 122552a38012Sejakowatz return B_MEDIA_BAD_NODE; 122652a38012Sejakowatz if (out_inputs == NULL || out_total_count == NULL) 122752a38012Sejakowatz return B_BAD_VALUE; 122852a38012Sejakowatz 122976669a29Sbeveloper List<media_input> list; 12303620737cSbeveloper media_input *input; 123152a38012Sejakowatz status_t rv; 123252a38012Sejakowatz 12331299bfb2Sbeveloper *out_total_count = 0; 12341299bfb2Sbeveloper 12358b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 12363620737cSbeveloper if (B_OK != rv) 12373620737cSbeveloper return rv; 12383620737cSbeveloper 123976669a29Sbeveloper int32 i; 124076669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&input); i++) { 12413620737cSbeveloper out_inputs[i] = *input; 124252a38012Sejakowatz *out_total_count += 1; 12433620737cSbeveloper buf_num_inputs -= 1; 12443620737cSbeveloper if (buf_num_inputs == 0) 12453620737cSbeveloper break; 124652a38012Sejakowatz } 124752a38012Sejakowatz 12488b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 12493620737cSbeveloper return B_OK; 125052a38012Sejakowatz } 125152a38012Sejakowatz 125252a38012Sejakowatz 125352a38012Sejakowatz status_t 125452a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node & node, 125552a38012Sejakowatz media_output * out_free_outputs, 125652a38012Sejakowatz int32 buf_num_outputs, 125752a38012Sejakowatz int32 * out_total_count, 125852a38012Sejakowatz media_type filter_type) 125952a38012Sejakowatz { 12603620737cSbeveloper CALLED(); 126140f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 12623620737cSbeveloper return B_MEDIA_BAD_NODE; 12633620737cSbeveloper if (out_free_outputs == NULL || out_total_count == NULL) 12643620737cSbeveloper return B_BAD_VALUE; 12653620737cSbeveloper 126676669a29Sbeveloper List<media_output> list; 12673620737cSbeveloper media_output *output; 12683620737cSbeveloper status_t rv; 12693620737cSbeveloper 12701299bfb2Sbeveloper *out_total_count = 0; 12711299bfb2Sbeveloper 12728b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 12733620737cSbeveloper if (B_OK != rv) 12743620737cSbeveloper return rv; 12753620737cSbeveloper 127676669a29Sbeveloper int32 i; 127776669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&output); i++) { 12783620737cSbeveloper if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != output->format.type) 12793620737cSbeveloper continue; // media_type used, but doesn't match 12803620737cSbeveloper if (output->destination != media_destination::null) 12813620737cSbeveloper continue; // producer destination already connected 12823620737cSbeveloper out_free_outputs[i] = *output; 12833620737cSbeveloper *out_total_count += 1; 12843620737cSbeveloper buf_num_outputs -= 1; 12853620737cSbeveloper if (buf_num_outputs == 0) 12863620737cSbeveloper break; 12873620737cSbeveloper } 12883620737cSbeveloper 12898b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 12903620737cSbeveloper return B_OK; 129152a38012Sejakowatz } 129252a38012Sejakowatz 129352a38012Sejakowatz 129452a38012Sejakowatz status_t 129552a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node & node, 129652a38012Sejakowatz media_output * out_active_outputs, 129752a38012Sejakowatz int32 buf_num_outputs, 129852a38012Sejakowatz int32 * out_total_count) 129952a38012Sejakowatz { 13003620737cSbeveloper CALLED(); 130140f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 13023620737cSbeveloper return B_MEDIA_BAD_NODE; 13033620737cSbeveloper if (out_active_outputs == NULL || out_total_count == NULL) 13043620737cSbeveloper return B_BAD_VALUE; 13053620737cSbeveloper 130676669a29Sbeveloper List<media_output> list; 13073620737cSbeveloper media_output *output; 13083620737cSbeveloper status_t rv; 13093620737cSbeveloper 13101299bfb2Sbeveloper *out_total_count = 0; 13111299bfb2Sbeveloper 13128b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 13133620737cSbeveloper if (B_OK != rv) 13143620737cSbeveloper return rv; 13153620737cSbeveloper 131676669a29Sbeveloper int32 i; 131776669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&output); i++) { 13183620737cSbeveloper if (output->destination == media_destination::null) 13193620737cSbeveloper continue; // producer destination not connected 13203620737cSbeveloper out_active_outputs[i] = *output; 13213620737cSbeveloper *out_total_count += 1; 13223620737cSbeveloper buf_num_outputs -= 1; 13233620737cSbeveloper if (buf_num_outputs == 0) 13243620737cSbeveloper break; 13253620737cSbeveloper } 13263620737cSbeveloper 13278b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 13283620737cSbeveloper return B_OK; 132952a38012Sejakowatz } 133052a38012Sejakowatz 133152a38012Sejakowatz 133252a38012Sejakowatz status_t 133352a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node & node, 133452a38012Sejakowatz media_output * out_outputs, 133552a38012Sejakowatz int32 buf_num_outputs, 133652a38012Sejakowatz int32 * out_total_count) 133752a38012Sejakowatz { 133852a38012Sejakowatz CALLED(); 133940f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 134052a38012Sejakowatz return B_MEDIA_BAD_NODE; 134152a38012Sejakowatz if (out_outputs == NULL || out_total_count == NULL) 134252a38012Sejakowatz return B_BAD_VALUE; 134352a38012Sejakowatz 134476669a29Sbeveloper List<media_output> list; 13453620737cSbeveloper media_output *output; 134652a38012Sejakowatz status_t rv; 134752a38012Sejakowatz 13481299bfb2Sbeveloper *out_total_count = 0; 13491299bfb2Sbeveloper 13508b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 13513620737cSbeveloper if (B_OK != rv) 13523620737cSbeveloper return rv; 13533620737cSbeveloper 135476669a29Sbeveloper int32 i; 135576669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&output); i++) { 13563620737cSbeveloper out_outputs[i] = *output; 135752a38012Sejakowatz *out_total_count += 1; 13583620737cSbeveloper buf_num_outputs -= 1; 13593620737cSbeveloper if (buf_num_outputs == 0) 13603620737cSbeveloper break; 136152a38012Sejakowatz } 136252a38012Sejakowatz 13638b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 13643620737cSbeveloper return B_OK; 136552a38012Sejakowatz } 136652a38012Sejakowatz 136752a38012Sejakowatz 136852a38012Sejakowatz status_t 136952a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where) 137052a38012Sejakowatz { 1371eae26d3dSbeveloper CALLED(); 1372eae26d3dSbeveloper if (!where.IsValid()) { 1373353b9f6bSbeveloper FATAL("BMediaRoster::StartWatching: messenger invalid!\n"); 1374eae26d3dSbeveloper return B_BAD_VALUE; 1375eae26d3dSbeveloper } 1376f4925104Sbeveloper return BPrivate::media::notifications::Register(where, media_node::null, B_MEDIA_WILDCARD); 137752a38012Sejakowatz } 137852a38012Sejakowatz 137952a38012Sejakowatz 138052a38012Sejakowatz status_t 138152a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where, 138252a38012Sejakowatz int32 notificationType) 138352a38012Sejakowatz { 1384eae26d3dSbeveloper CALLED(); 1385eae26d3dSbeveloper if (!where.IsValid()) { 1386353b9f6bSbeveloper FATAL("BMediaRoster::StartWatching: messenger invalid!\n"); 1387eae26d3dSbeveloper return B_BAD_VALUE; 1388eae26d3dSbeveloper } 1389f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) { 1390353b9f6bSbeveloper FATAL("BMediaRoster::StartWatching: notificationType invalid!\n"); 1391eae26d3dSbeveloper return B_BAD_VALUE; 1392eae26d3dSbeveloper } 1393f4925104Sbeveloper return BPrivate::media::notifications::Register(where, media_node::null, notificationType); 139452a38012Sejakowatz } 139552a38012Sejakowatz 139652a38012Sejakowatz 139752a38012Sejakowatz status_t 139852a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where, 139952a38012Sejakowatz const media_node & node, 140052a38012Sejakowatz int32 notificationType) 140152a38012Sejakowatz { 1402eae26d3dSbeveloper CALLED(); 1403eae26d3dSbeveloper if (!where.IsValid()) { 1404353b9f6bSbeveloper FATAL("BMediaRoster::StartWatching: messenger invalid!\n"); 1405eae26d3dSbeveloper return B_BAD_VALUE; 1406eae26d3dSbeveloper } 140740f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 1408353b9f6bSbeveloper FATAL("BMediaRoster::StartWatching: node invalid!\n"); 1409eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1410eae26d3dSbeveloper } 1411f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) { 1412353b9f6bSbeveloper FATAL("BMediaRoster::StartWatching: notificationType invalid!\n"); 1413eae26d3dSbeveloper return B_BAD_VALUE; 1414eae26d3dSbeveloper } 1415f4925104Sbeveloper return BPrivate::media::notifications::Register(where, node, notificationType); 141652a38012Sejakowatz } 141752a38012Sejakowatz 141852a38012Sejakowatz 141952a38012Sejakowatz status_t 142052a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where) 142152a38012Sejakowatz { 1422eae26d3dSbeveloper CALLED(); 1423eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1424f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, media_node::null, B_MEDIA_WILDCARD); 142552a38012Sejakowatz } 142652a38012Sejakowatz 142752a38012Sejakowatz 142852a38012Sejakowatz status_t 142952a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where, 143052a38012Sejakowatz int32 notificationType) 143152a38012Sejakowatz { 1432eae26d3dSbeveloper CALLED(); 1433eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1434f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) { 1435353b9f6bSbeveloper FATAL("BMediaRoster::StopWatching: notificationType invalid!\n"); 1436eae26d3dSbeveloper return B_BAD_VALUE; 1437eae26d3dSbeveloper } 1438f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, media_node::null, notificationType); 143952a38012Sejakowatz } 144052a38012Sejakowatz 144152a38012Sejakowatz 144252a38012Sejakowatz status_t 144352a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where, 144452a38012Sejakowatz const media_node & node, 144552a38012Sejakowatz int32 notificationType) 144652a38012Sejakowatz { 1447eae26d3dSbeveloper CALLED(); 1448eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 144940f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 1450353b9f6bSbeveloper FATAL("BMediaRoster::StopWatching: node invalid!\n"); 1451eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1452eae26d3dSbeveloper } 1453f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) { 1454353b9f6bSbeveloper FATAL("BMediaRoster::StopWatching: notificationType invalid!\n"); 1455eae26d3dSbeveloper return B_BAD_VALUE; 1456eae26d3dSbeveloper } 1457f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, node, notificationType); 145852a38012Sejakowatz } 145952a38012Sejakowatz 146052a38012Sejakowatz 146152a38012Sejakowatz status_t 146252a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode * node) 146352a38012Sejakowatz { 146454187cc6Sbeveloper CALLED(); 146554187cc6Sbeveloper // addon-id = -1 (unused), addon-flavor-id = 0 (unused, too) 146654187cc6Sbeveloper return MediaRosterEx(this)->RegisterNode(node, -1, 0); 146754187cc6Sbeveloper } 146854187cc6Sbeveloper 146954187cc6Sbeveloper 147054187cc6Sbeveloper status_t 147154187cc6Sbeveloper BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 flavorid) 147254187cc6Sbeveloper { 147352a38012Sejakowatz CALLED(); 147452a38012Sejakowatz if (node == NULL) 147552a38012Sejakowatz return B_BAD_VALUE; 147652a38012Sejakowatz 147754187cc6Sbeveloper // some sanity check 147854187cc6Sbeveloper // I'm not sure if the media kit warrants to call BMediaNode::AddOn() here. 147954187cc6Sbeveloper // Perhaps we don't need it. 148054187cc6Sbeveloper { 14819e9417d2Sbeveloper BMediaAddOn *addon; 14829e9417d2Sbeveloper int32 addon_flavor_id; 14839e9417d2Sbeveloper media_addon_id addon_id; 14849e9417d2Sbeveloper addon_flavor_id = 0; 14859e9417d2Sbeveloper addon = node->AddOn(&addon_flavor_id); 14869e9417d2Sbeveloper addon_id = addon ? addon->AddonID() : -1; 148754187cc6Sbeveloper ASSERT(addonid == addon_id); 148854187cc6Sbeveloper ASSERT(flavorid == addon_flavor_id); 148954187cc6Sbeveloper } 149052a38012Sejakowatz 149154187cc6Sbeveloper status_t rv; 14929e9417d2Sbeveloper server_register_node_request request; 14939e9417d2Sbeveloper server_register_node_reply reply; 14949e9417d2Sbeveloper 149554187cc6Sbeveloper request.addon_id = addonid; 149654187cc6Sbeveloper request.addon_flavor_id = flavorid; 14979e9417d2Sbeveloper strcpy(request.name, node->Name()); 14989e9417d2Sbeveloper request.kinds = node->Kinds(); 14999e9417d2Sbeveloper request.port = node->ControlPort(); 15009e9417d2Sbeveloper request.team = team; 15019e9417d2Sbeveloper 15028b04ffc1Sbeveloper TRACE("BMediaRoster::RegisterNode: sending SERVER_REGISTER_NODE: port %ld, kinds 0x%Lx, team %ld, name '%s'\n", request.port, request.kinds, request.team, request.name); 15031299bfb2Sbeveloper 15049e9417d2Sbeveloper rv = QueryServer(SERVER_REGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply)); 15059e9417d2Sbeveloper if (rv != B_OK) { 1506353b9f6bSbeveloper FATAL("BMediaRoster::RegisterNode: failed to register node %s (error %#lx)\n", node->Name(), rv); 15079e9417d2Sbeveloper return rv; 15089e9417d2Sbeveloper } 15099e9417d2Sbeveloper 15108b04ffc1Sbeveloper // we are a friend class of BMediaNode and initialize this member variable 15119e9417d2Sbeveloper node->fNodeID = reply.nodeid; 15129e9417d2Sbeveloper ASSERT(reply.nodeid == node->Node().node); 15139e9417d2Sbeveloper ASSERT(reply.nodeid == node->ID()); 15149e9417d2Sbeveloper 15159e9417d2Sbeveloper // call the callback 15169e9417d2Sbeveloper node->NodeRegistered(); 15173620737cSbeveloper 15180e21b167Sbeveloper // if the BMediaNode also inherits from BTimeSource, we need to call BTimeSource::FinishCreate() 15190e21b167Sbeveloper if (node->Kinds() & B_TIME_SOURCE) { 15200e21b167Sbeveloper BTimeSource *ts; 15210e21b167Sbeveloper ts = dynamic_cast<BTimeSource *>(node); 15220e21b167Sbeveloper if (ts) 15230e21b167Sbeveloper ts->FinishCreate(); 15240e21b167Sbeveloper } 15250e21b167Sbeveloper 1526570f7d04Sbeveloper /* 15273620737cSbeveloper // register existing inputs and outputs with the 15283620737cSbeveloper // media_server, this allows GetLiveNodes() to work 15293620737cSbeveloper // with created, but unconnected nodes. 15303620737cSbeveloper if (node->Kinds() & B_BUFFER_PRODUCER) { 15313620737cSbeveloper Stack<media_output> stack; 15323620737cSbeveloper if (B_OK == GetAllOutputs(node->Node(), &stack)) 15333620737cSbeveloper PublishOutputs(node->Node(), &stack); 15343620737cSbeveloper } else if (node->Kinds() & B_BUFFER_CONSUMER) { 15353620737cSbeveloper Stack<media_input> stack; 15363620737cSbeveloper if (B_OK == GetAllInputs(node->Node(), &stack)) 15373620737cSbeveloper PublishInputs(node->Node(), &stack); 15383620737cSbeveloper } 1539570f7d04Sbeveloper */ 1540570f7d04Sbeveloper 15411299bfb2Sbeveloper BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1); 1542570f7d04Sbeveloper /* 1543570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id); 1544570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node this %p\n", node); 1545570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fConsumerThis %p\n", node->fConsumerThis); 1546570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fProducerThis %p\n", node->fProducerThis); 1547570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", node->fFileInterfaceThis); 1548570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fControllableThis %p\n", node->fControllableThis); 1549570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis %p\n", node->fTimeSourceThis); 1550570f7d04Sbeveloper */ 15519e9417d2Sbeveloper 15529e9417d2Sbeveloper return B_OK; 155352a38012Sejakowatz } 155452a38012Sejakowatz 155552a38012Sejakowatz 155652a38012Sejakowatz status_t 155752a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode * node) 155852a38012Sejakowatz { 15599e9417d2Sbeveloper CALLED(); 15609e9417d2Sbeveloper if (node == NULL) 15619e9417d2Sbeveloper return B_BAD_VALUE; 15629e9417d2Sbeveloper 156360f15390Sbeveloper TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node); 156460f15390Sbeveloper 156586bce45bSbeveloper if (node->fKinds & NODE_KIND_NO_REFCOUNTING) { 156686bce45bSbeveloper printf("BMediaRoster::UnregisterNode, trying to unregister reference counting disabled timesource, node %ld, port %ld, team %ld\n", node->ID(), node->ControlPort(), team); 156786bce45bSbeveloper return B_OK; 156886bce45bSbeveloper } 15698b04ffc1Sbeveloper if (node->ID() == NODE_UNREGISTERED_ID) { 15708b04ffc1Sbeveloper FATAL("BMediaRoster::UnregisterNode: Warning node id %ld, name '%s' already unregistered\n", node->ID(), node->Name()); 15719e9417d2Sbeveloper return B_OK; 15729e9417d2Sbeveloper } 157354187cc6Sbeveloper if (node->fRefCount != 0) { 157454187cc6Sbeveloper FATAL("BMediaRoster::UnregisterNode: Warning node id %ld, name '%s' has local reference count of %ld\n", node->ID(), node->Name(), node->fRefCount); 157554187cc6Sbeveloper // no return here, we continue and unregister! 157654187cc6Sbeveloper } 157754187cc6Sbeveloper 157854187cc6Sbeveloper // Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node, BMessage *config) 157954187cc6Sbeveloper // if this node was instanciated by an add-on needs to be done *somewhere* 158054187cc6Sbeveloper // We can't do it here because it is already to late (destructor of the node 158154187cc6Sbeveloper // might have been called). 15829e9417d2Sbeveloper 15839e9417d2Sbeveloper server_unregister_node_request request; 15849e9417d2Sbeveloper server_unregister_node_reply reply; 15859e9417d2Sbeveloper status_t rv; 15869e9417d2Sbeveloper 15879e9417d2Sbeveloper request.nodeid = node->ID(); 15889e9417d2Sbeveloper request.team = team; 15899e9417d2Sbeveloper 15901299bfb2Sbeveloper // send a notification 15911299bfb2Sbeveloper BPrivate::media::notifications::NodesDeleted(&request.nodeid, 1); 15921299bfb2Sbeveloper 15939e9417d2Sbeveloper rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply)); 15949e9417d2Sbeveloper if (rv != B_OK) { 15958b04ffc1Sbeveloper FATAL("BMediaRoster::UnregisterNode: failed to unregister node id %ld, name '%s' (error %#lx)\n", node->ID(), node->Name(), rv); 15969e9417d2Sbeveloper return rv; 15979e9417d2Sbeveloper } 15989e9417d2Sbeveloper 159954187cc6Sbeveloper if (reply.addonid != -1) { 160054187cc6Sbeveloper // Small problem here, we can't use DormantNodeManager::PutAddon(), as 160154187cc6Sbeveloper // UnregisterNode() is called by a dormant node itself (by the destructor). 160254187cc6Sbeveloper // The add-on that contains the node needs to remain in memory until the 160354187cc6Sbeveloper // destructor execution is finished. 160454187cc6Sbeveloper // DormantNodeManager::PutAddonDelayed() will delay unloading. 160554187cc6Sbeveloper _DormantNodeManager->PutAddonDelayed(reply.addonid); 1606cf4e2277Sbeveloper 160773794717Sbeveloper rv = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount(reply.addonid, reply.flavorid); 160854187cc6Sbeveloper if (rv != B_OK) { 160973794717Sbeveloper FATAL("BMediaRoster::UnregisterNode: DecrementAddonFlavorInstancesCount failed\n"); 161054187cc6Sbeveloper // this is really a problem, but we can't fail now 161154187cc6Sbeveloper } 16128b04ffc1Sbeveloper } 16139e9417d2Sbeveloper 16141299bfb2Sbeveloper // we are a friend class of BMediaNode and invalidate this member variable 16158b04ffc1Sbeveloper node->fNodeID = NODE_UNREGISTERED_ID; 16169e9417d2Sbeveloper 16179e9417d2Sbeveloper return B_OK; 161852a38012Sejakowatz } 161952a38012Sejakowatz 162052a38012Sejakowatz 162152a38012Sejakowatz // thread safe for multiple calls to Roster() 162252a38012Sejakowatz /* static */ BMediaRoster * 162352a38012Sejakowatz BMediaRoster::Roster(status_t* out_error) 162452a38012Sejakowatz { 162552a38012Sejakowatz static BLocker locker("BMediaRoster::Roster locker"); 162652a38012Sejakowatz locker.Lock(); 162752a38012Sejakowatz if (_sDefault == NULL) { 16288b04ffc1Sbeveloper _sDefault = new BMediaRosterEx(); 162952a38012Sejakowatz if (out_error != NULL) 163052a38012Sejakowatz *out_error = B_OK; 163152a38012Sejakowatz } else { 163252a38012Sejakowatz if (out_error != NULL) 163352a38012Sejakowatz *out_error = B_OK; 163452a38012Sejakowatz } 163552a38012Sejakowatz locker.Unlock(); 163652a38012Sejakowatz return _sDefault; 163752a38012Sejakowatz } 163852a38012Sejakowatz 163952a38012Sejakowatz 164052a38012Sejakowatz // won't create it if there isn't one 164152a38012Sejakowatz // not thread safe if you call Roster() at the same time 164252a38012Sejakowatz /* static */ BMediaRoster * 164352a38012Sejakowatz BMediaRoster::CurrentRoster() 164452a38012Sejakowatz { 164552a38012Sejakowatz return _sDefault; 164652a38012Sejakowatz } 164752a38012Sejakowatz 164852a38012Sejakowatz 164952a38012Sejakowatz status_t 165052a38012Sejakowatz BMediaRoster::SetTimeSourceFor(media_node_id node, 165152a38012Sejakowatz media_node_id time_source) 165252a38012Sejakowatz { 1653aac800c2Sbeveloper CALLED(); 165440f36b03Sbeveloper if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source)) 1655aac800c2Sbeveloper return B_BAD_VALUE; 1656aac800c2Sbeveloper 1657aac800c2Sbeveloper media_node clone; 1658aac800c2Sbeveloper status_t rv, result; 1659aac800c2Sbeveloper 166086bce45bSbeveloper // we need to get a clone of the node to have a port id 1661aac800c2Sbeveloper rv = GetNodeFor(node, &clone); 1662aac800c2Sbeveloper if (rv != B_OK) { 1663aac800c2Sbeveloper FATAL("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id %ld\n", node); 166452a38012Sejakowatz return B_ERROR; 166552a38012Sejakowatz } 166652a38012Sejakowatz 166760f15390Sbeveloper TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time source %ld\n", node, time_source); 166886bce45bSbeveloper 166986bce45bSbeveloper // we just send the request to set time_source-id as timesource to the node, 167086bce45bSbeveloper // the NODE_SET_TIMESOURCE handler code will do the real assignment 1671aac800c2Sbeveloper result = B_OK; 1672aac800c2Sbeveloper node_set_timesource_command cmd; 1673aac800c2Sbeveloper cmd.timesource_id = time_source; 1674aac800c2Sbeveloper rv = SendToPort(clone.port, NODE_SET_TIMESOURCE, &cmd, sizeof(cmd)); 1675aac800c2Sbeveloper if (rv != B_OK) { 1676aac800c2Sbeveloper FATAL("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE failed, node id %ld\n", node); 1677aac800c2Sbeveloper result = B_ERROR; 1678aac800c2Sbeveloper } 1679aac800c2Sbeveloper 168060f15390Sbeveloper // we release the clone 1681aac800c2Sbeveloper rv = ReleaseNode(clone); 1682aac800c2Sbeveloper if (rv != B_OK) { 1683aac800c2Sbeveloper FATAL("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id %ld\n", node); 1684aac800c2Sbeveloper result = B_ERROR; 1685aac800c2Sbeveloper } 1686aac800c2Sbeveloper 1687aac800c2Sbeveloper return result; 1688aac800c2Sbeveloper } 1689aac800c2Sbeveloper 169052a38012Sejakowatz 169152a38012Sejakowatz status_t 169252a38012Sejakowatz BMediaRoster::GetParameterWebFor(const media_node & node, 169352a38012Sejakowatz BParameterWeb ** out_web) 169452a38012Sejakowatz { 1695*28ad138aSbeveloper CALLED(); 1696*28ad138aSbeveloper if (out_web == NULL) 1697*28ad138aSbeveloper return B_BAD_VALUE; 1698*28ad138aSbeveloper if (IS_INVALID_NODE(node)) 1699*28ad138aSbeveloper return B_MEDIA_BAD_NODE; 1700*28ad138aSbeveloper if ((node.kind & B_CONTROLLABLE) == 0) 1701*28ad138aSbeveloper return B_MEDIA_BAD_NODE; 1702*28ad138aSbeveloper 1703*28ad138aSbeveloper controllable_get_parameter_web_request request; 1704*28ad138aSbeveloper controllable_get_parameter_web_reply reply; 1705*28ad138aSbeveloper int32 requestsize[] = {B_PAGE_SIZE, 4*B_PAGE_SIZE, 16*B_PAGE_SIZE, 64*B_PAGE_SIZE, 128*B_PAGE_SIZE, 256*B_PAGE_SIZE, 0}; 1706*28ad138aSbeveloper int32 size; 1707*28ad138aSbeveloper 1708*28ad138aSbeveloper // XXX it might be better to query the node for the (current) parameter size first 1709*28ad138aSbeveloper for (int i = 0; (size = requestsize[i]) != 0; i++) { 1710*28ad138aSbeveloper status_t rv; 1711*28ad138aSbeveloper area_id area; 1712*28ad138aSbeveloper void *data; 1713*28ad138aSbeveloper area = create_area("parameter web data", &data, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 1714*28ad138aSbeveloper if (area < B_OK) { 1715*28ad138aSbeveloper FATAL("BMediaRoster::GetParameterWebFor couldn't create area of size %ld\n", size); 1716*28ad138aSbeveloper return B_ERROR; 1717*28ad138aSbeveloper } 1718*28ad138aSbeveloper request.maxsize = size; 1719*28ad138aSbeveloper request.area = area; 1720*28ad138aSbeveloper rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request, sizeof(request), &reply, sizeof(reply)); 1721*28ad138aSbeveloper if (rv != B_OK) { 1722*28ad138aSbeveloper FATAL("BMediaRoster::GetParameterWebFor CONTROLLABLE_GET_PARAMETER_WEB failed\n"); 1723*28ad138aSbeveloper delete_area(area); 1724*28ad138aSbeveloper return B_ERROR; 1725*28ad138aSbeveloper } 1726*28ad138aSbeveloper if (reply.size == 0) { 1727*28ad138aSbeveloper // no parameter web available 1728*28ad138aSbeveloper // XXX should we return an error? 1729*28ad138aSbeveloper FATAL("BMediaRoster::GetParameterWebFor node %ld has no parameter web\n", node.node); 1730*28ad138aSbeveloper *out_web = new BParameterWeb(); 1731*28ad138aSbeveloper delete_area(area); 173260f15390Sbeveloper return B_OK; 173352a38012Sejakowatz } 1734*28ad138aSbeveloper if (reply.size > 0) { 1735*28ad138aSbeveloper // we got a flattened parameter web! 1736*28ad138aSbeveloper *out_web = new BParameterWeb(); 1737*28ad138aSbeveloper 1738*28ad138aSbeveloper printf("BMediaRoster::GetParameterWebFor Unflattening %ld bytes, 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", 1739*28ad138aSbeveloper reply.size, ((uint32*)data)[0], ((uint32*)data)[1], ((uint32*)data)[2], ((uint32*)data)[3]); 1740*28ad138aSbeveloper 1741*28ad138aSbeveloper rv = (*out_web)->Unflatten(reply.code, data, reply.size); 1742*28ad138aSbeveloper if (rv != B_OK) { 1743*28ad138aSbeveloper FATAL("BMediaRoster::GetParameterWebFor Unflatten failed, %s\n", strerror(rv)); 1744*28ad138aSbeveloper delete_area(area); 1745*28ad138aSbeveloper delete *out_web; 1746*28ad138aSbeveloper return B_ERROR; 1747*28ad138aSbeveloper } 1748*28ad138aSbeveloper delete_area(area); 1749*28ad138aSbeveloper return B_OK; 1750*28ad138aSbeveloper } 1751*28ad138aSbeveloper delete_area(area); 1752*28ad138aSbeveloper ASSERT(reply.size == -1); 1753*28ad138aSbeveloper // parameter web data was too large 1754*28ad138aSbeveloper // loop and try a larger size 1755*28ad138aSbeveloper } 1756*28ad138aSbeveloper FATAL("BMediaRoster::GetParameterWebFor node %ld has no parameter web larger than %ld\n", node.node, size); 1757*28ad138aSbeveloper return B_ERROR; 1758*28ad138aSbeveloper } 175952a38012Sejakowatz 176052a38012Sejakowatz 176152a38012Sejakowatz status_t 176252a38012Sejakowatz BMediaRoster::StartControlPanel(const media_node & node, 176352a38012Sejakowatz BMessenger * out_messenger) 176452a38012Sejakowatz { 176552a38012Sejakowatz UNIMPLEMENTED(); 176652a38012Sejakowatz return B_ERROR; 176752a38012Sejakowatz } 176852a38012Sejakowatz 176952a38012Sejakowatz 177052a38012Sejakowatz status_t 177152a38012Sejakowatz BMediaRoster::GetDormantNodes(dormant_node_info * out_info, 177252a38012Sejakowatz int32 * io_count, 177352a38012Sejakowatz const media_format * has_input /* = NULL */, 177452a38012Sejakowatz const media_format * has_output /* = NULL */, 177552a38012Sejakowatz const char * name /* = NULL */, 177652a38012Sejakowatz uint64 require_kinds /* = NULL */, 177752a38012Sejakowatz uint64 deny_kinds /* = NULL */) 177852a38012Sejakowatz { 177952a38012Sejakowatz CALLED(); 178052a38012Sejakowatz if (out_info == NULL) 178152a38012Sejakowatz return B_BAD_VALUE; 178252a38012Sejakowatz if (io_count == NULL) 178352a38012Sejakowatz return B_BAD_VALUE; 178452a38012Sejakowatz if (*io_count <= 0) 178552a38012Sejakowatz return B_BAD_VALUE; 178652a38012Sejakowatz 178752a38012Sejakowatz xfer_server_get_dormant_nodes msg; 178852a38012Sejakowatz port_id port; 178952a38012Sejakowatz status_t rv; 179052a38012Sejakowatz 179152a38012Sejakowatz port = find_port("media_server port"); 179252a38012Sejakowatz if (port <= B_OK) 179352a38012Sejakowatz return B_ERROR; 179452a38012Sejakowatz 179552a38012Sejakowatz msg.maxcount = *io_count; 179652a38012Sejakowatz msg.has_input = (bool) has_input; 179752a38012Sejakowatz if (has_input) 179852a38012Sejakowatz msg.inputformat = *has_input; // XXX we should not make a flat copy of media_format 179952a38012Sejakowatz msg.has_output = (bool) has_output; 180052a38012Sejakowatz if (has_output) 180152a38012Sejakowatz msg.outputformat = *has_output;; // XXX we should not make a flat copy of media_format 180252a38012Sejakowatz msg.has_name = (bool) name; 180352a38012Sejakowatz if (name) { 18049e9417d2Sbeveloper int len = strlen(name); 18059e9417d2Sbeveloper len = min_c(len, (int)sizeof(msg.name) - 1); 180652a38012Sejakowatz memcpy(msg.name, name, len); 180752a38012Sejakowatz msg.name[len] = 0; 180852a38012Sejakowatz } 180952a38012Sejakowatz msg.require_kinds = require_kinds; 181052a38012Sejakowatz msg.deny_kinds = deny_kinds; 181152a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 181252a38012Sejakowatz 181352a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_NODES, &msg, sizeof(msg)); 181452a38012Sejakowatz if (rv != B_OK) { 181552a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 181652a38012Sejakowatz return rv; 181752a38012Sejakowatz } 181852a38012Sejakowatz 181952a38012Sejakowatz xfer_server_get_dormant_nodes_reply reply; 182052a38012Sejakowatz int32 code; 182152a38012Sejakowatz 182252a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 182352a38012Sejakowatz if (rv < B_OK) { 182452a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 182552a38012Sejakowatz return rv; 182652a38012Sejakowatz } 182752a38012Sejakowatz 182852a38012Sejakowatz *io_count = reply.count; 182952a38012Sejakowatz 183052a38012Sejakowatz if (*io_count > 0) { 183152a38012Sejakowatz rv = read_port(msg.reply_port, &code, out_info, *io_count * sizeof(dormant_node_info)); 183252a38012Sejakowatz if (rv < B_OK) 183352a38012Sejakowatz reply.result = rv; 183452a38012Sejakowatz } 183552a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 183652a38012Sejakowatz 183752a38012Sejakowatz return reply.result; 183852a38012Sejakowatz } 183952a38012Sejakowatz 18408b04ffc1Sbeveloper /* This function is used to do the real work of instantiating a dormant node. It is either 18418b04ffc1Sbeveloper * called by the media_addon_server to instantiate a global node, or it gets called from 18428b04ffc1Sbeveloper * BMediaRoster::InstantiateDormantNode() to create a local one. 18438b04ffc1Sbeveloper * 18448b04ffc1Sbeveloper * Checks concerning global/local are not done here. 18458b04ffc1Sbeveloper */ 184652a38012Sejakowatz status_t 184754187cc6Sbeveloper BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, team_id creator, media_node *out_node) 184852a38012Sejakowatz { 184954187cc6Sbeveloper // This function is always called from the correct context, if the node 185054187cc6Sbeveloper // is supposed to be global, it is called from the media_addon_server. 185154187cc6Sbeveloper 185252a38012Sejakowatz // if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that 185352a38012Sejakowatz // resides in the media_addon_server 185452a38012Sejakowatz 18558b04ffc1Sbeveloper // RegisterNode() must be called for nodes instantiated from add-ons, 18568b04ffc1Sbeveloper // since the media kit warrants that it's done automatically. 185752a38012Sejakowatz 185854187cc6Sbeveloper // addonid Indicates the ID number of the media add-on in which the node resides. 185954187cc6Sbeveloper // flavorid Indicates the internal ID number that the add-on uses to identify the flavor, 186054187cc6Sbeveloper // this is the number that was published by BMediaAddOn::GetFlavorAt() in the 18618b04ffc1Sbeveloper // flavor_info::internal_id field. 186254187cc6Sbeveloper // creator The creator team is -1 if nodes are created locally. If created globally, 186354187cc6Sbeveloper // it will contain (while called in media_addon_server context) the team-id of 186454187cc6Sbeveloper // the team that requested the instantiation. 18658b04ffc1Sbeveloper 186660f15390Sbeveloper TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld\n", addonid, flavorid); 18678b04ffc1Sbeveloper 18688b04ffc1Sbeveloper // Get flavor_info from the server 18698b04ffc1Sbeveloper dormant_flavor_info node_info; 18708c6a6096Sbeveloper status_t rv; 18718b04ffc1Sbeveloper rv = GetDormantFlavorInfo(addonid, flavorid, &node_info); 18728b04ffc1Sbeveloper if (rv != B_OK) { 1873626824eaSbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", addonid, flavorid); 187452a38012Sejakowatz return B_ERROR; 187552a38012Sejakowatz } 18768b04ffc1Sbeveloper 18778b04ffc1Sbeveloper ASSERT(node_info.internal_id == flavorid); 18788b04ffc1Sbeveloper 18798b04ffc1Sbeveloper // load the BMediaAddOn object 18808b04ffc1Sbeveloper BMediaAddOn *addon; 18818b04ffc1Sbeveloper addon = _DormantNodeManager->GetAddon(addonid); 18828b04ffc1Sbeveloper if (!addon) { 18838b04ffc1Sbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n"); 18848b04ffc1Sbeveloper return B_ERROR; 18858b04ffc1Sbeveloper } 18868b04ffc1Sbeveloper 188754187cc6Sbeveloper // Now we need to try to increment the use count of this addon flavor 188854187cc6Sbeveloper // in the server. This can fail if the total number instances of this 188954187cc6Sbeveloper // flavor is limited. 189073794717Sbeveloper rv = IncrementAddonFlavorInstancesCount(addonid, flavorid); 189154187cc6Sbeveloper if (rv != B_OK) { 1892626824eaSbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode error: can't create more nodes for addon-id %ld, flavor-id %ld\n", addonid, flavorid); 189354187cc6Sbeveloper // Put the addon back into the pool 189454187cc6Sbeveloper _DormantNodeManager->PutAddon(addonid); 189554187cc6Sbeveloper return B_ERROR; 189654187cc6Sbeveloper } 189754187cc6Sbeveloper 18988b04ffc1Sbeveloper BMessage config; 189954187cc6Sbeveloper rv = LoadNodeConfiguration(addonid, flavorid, &config); 190054187cc6Sbeveloper if (rv != B_OK) { 190154187cc6Sbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode: couldn't load configuration for addon-id %ld, flavor-id %ld\n", addonid, flavorid); 190254187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 190354187cc6Sbeveloper } 19048b04ffc1Sbeveloper 19058b04ffc1Sbeveloper BMediaNode *node; 19068b04ffc1Sbeveloper status_t out_error; 19078b04ffc1Sbeveloper 190854187cc6Sbeveloper out_error = B_OK; 19098b04ffc1Sbeveloper node = addon->InstantiateNodeFor(&node_info, &config, &out_error); 191016b7eea4Sbeveloper if (!node) { 19118b04ffc1Sbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor failed\n"); 191254187cc6Sbeveloper // Put the addon back into the pool 19138b04ffc1Sbeveloper _DormantNodeManager->PutAddon(addonid); 191454187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 191554187cc6Sbeveloper // server to compensate the increment done in the beginning. 191673794717Sbeveloper rv = DecrementAddonFlavorInstancesCount(addonid, flavorid); 191754187cc6Sbeveloper if (rv != B_OK) { 191873794717Sbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n"); 191916b7eea4Sbeveloper } 192054187cc6Sbeveloper return (out_error != B_OK) ? out_error : B_ERROR; 192154187cc6Sbeveloper } 192254187cc6Sbeveloper 192354187cc6Sbeveloper rv = RegisterNode(node, addonid, flavorid); 19248c6a6096Sbeveloper if (rv != B_OK) { 19258b04ffc1Sbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n"); 19268c6a6096Sbeveloper delete node; 192754187cc6Sbeveloper // Put the addon back into the pool 19288b04ffc1Sbeveloper _DormantNodeManager->PutAddon(addonid); 192954187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 193054187cc6Sbeveloper // server to compensate the increment done in the beginning. 193173794717Sbeveloper rv = DecrementAddonFlavorInstancesCount(addonid, flavorid); 193254187cc6Sbeveloper if (rv != B_OK) { 193373794717Sbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n"); 193454187cc6Sbeveloper } 19358c6a6096Sbeveloper return B_ERROR; 19368c6a6096Sbeveloper } 19378c6a6096Sbeveloper 193854187cc6Sbeveloper if (creator != -1) { 193954187cc6Sbeveloper // send a message to the server to assign team "creator" as creator of node "node->ID()" 194054187cc6Sbeveloper printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team %ld as creator of node %ld\n", creator, node->ID()); 194154187cc6Sbeveloper rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator); 194254187cc6Sbeveloper if (rv != B_OK) { 194354187cc6Sbeveloper FATAL("BMediaRosterEx::InstantiateDormantNode failed to assign team %ld as creator of node %ld\n", creator, node->ID()); 194454187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 194554187cc6Sbeveloper } 194654187cc6Sbeveloper } 194754187cc6Sbeveloper 194854187cc6Sbeveloper // RegisterNode() does remember the add-on id in the server 194954187cc6Sbeveloper // and UnregisterNode() will call DormantNodeManager::PutAddon() 195054187cc6Sbeveloper // when the node is unregistered. 19518c6a6096Sbeveloper 195216b7eea4Sbeveloper *out_node = node->Node(); 1953cf4e2277Sbeveloper 195460f15390Sbeveloper TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld instanciated as node %ld, port %ld in team %ld\n", addonid, flavorid, out_node->node, out_node->port, team); 1955cf4e2277Sbeveloper 195616b7eea4Sbeveloper return B_OK; 195716b7eea4Sbeveloper } 195852a38012Sejakowatz 195952a38012Sejakowatz 196052a38012Sejakowatz status_t 19618b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, 19628b04ffc1Sbeveloper media_node * out_node, 19638b04ffc1Sbeveloper uint32 flags /* currently 0 or B_FLAVOR_IS_GLOBAL or B_FLAVOR_IS_LOCAL */ ) 19648b04ffc1Sbeveloper { 19658b04ffc1Sbeveloper CALLED(); 19668b04ffc1Sbeveloper if (out_node == 0) 19678b04ffc1Sbeveloper return B_BAD_VALUE; 19688b04ffc1Sbeveloper if (in_info.addon <= 0) { 19698b04ffc1Sbeveloper FATAL("BMediaRoster::InstantiateDormantNode error: addon-id %ld invalid.\n", in_info.addon); 19708b04ffc1Sbeveloper return B_BAD_VALUE; 19718b04ffc1Sbeveloper } 19728b04ffc1Sbeveloper 19738b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: addon-id %ld, flavor_id %ld, flags 0x%X\n", in_info.addon, in_info.flavor_id, flags); 19748b04ffc1Sbeveloper 19758b04ffc1Sbeveloper // Get flavor_info from the server 19768b04ffc1Sbeveloper // XXX this is a little overhead, as we get the full blown dormant_flavor_info, 19778b04ffc1Sbeveloper // XXX but only need the flags. 19788b04ffc1Sbeveloper dormant_flavor_info node_info; 19798b04ffc1Sbeveloper status_t rv; 19808b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetDormantFlavorInfo(in_info.addon, in_info.flavor_id, &node_info); 19818b04ffc1Sbeveloper if (rv != B_OK) { 1982626824eaSbeveloper FATAL("BMediaRoster::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", in_info.addon, in_info.flavor_id); 1983626824eaSbeveloper return B_NAME_NOT_FOUND; 19848b04ffc1Sbeveloper } 19858b04ffc1Sbeveloper 19868b04ffc1Sbeveloper ASSERT(node_info.internal_id == in_info.flavor_id); 19878b04ffc1Sbeveloper 19888b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", flavor_flags 0x%X, internal_id %ld, possible_count %ld\n", 19898b04ffc1Sbeveloper node_info.name, node_info.info, node_info.flavor_flags, node_info.internal_id, node_info.possible_count); 19908b04ffc1Sbeveloper 19918b04ffc1Sbeveloper #if DEBUG 19928b04ffc1Sbeveloper if (flags & B_FLAVOR_IS_LOCAL) 19938b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_LOCAL\n"); 19948b04ffc1Sbeveloper if (flags & B_FLAVOR_IS_GLOBAL) 19958b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_GLOBAL\n"); 19968b04ffc1Sbeveloper if (node_info.flavor_flags & B_FLAVOR_IS_LOCAL) 19978b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_LOCAL\n"); 19988b04ffc1Sbeveloper if (node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) 19998b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_GLOBAL\n"); 20008b04ffc1Sbeveloper #endif 20018b04ffc1Sbeveloper 20028b04ffc1Sbeveloper // Make sure that flags demanded by the dormant node and those requested 20038b04ffc1Sbeveloper // by the caller are not incompatible. 20048b04ffc1Sbeveloper if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) && (flags & B_FLAVOR_IS_LOCAL)) { 20058b04ffc1Sbeveloper FATAL("BMediaRoster::InstantiateDormantNode Error: requested B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n"); 2006626824eaSbeveloper return B_NAME_NOT_FOUND; 20078b04ffc1Sbeveloper } 20088b04ffc1Sbeveloper if ((node_info.flavor_flags & B_FLAVOR_IS_LOCAL) && (flags & B_FLAVOR_IS_GLOBAL)) { 20098b04ffc1Sbeveloper FATAL("BMediaRoster::InstantiateDormantNode Error: requested B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n"); 2010626824eaSbeveloper return B_NAME_NOT_FOUND; 20118b04ffc1Sbeveloper } 201254187cc6Sbeveloper 20138b04ffc1Sbeveloper // If either the node, or the caller requested to make the instance global 20148b04ffc1Sbeveloper // we will do it by forwarding this request into the media_addon_server, which 20158b04ffc1Sbeveloper // in turn will call BMediaRosterEx::InstantiateDormantNode to create the node 20168b04ffc1Sbeveloper // there and make it globally available. 20178b04ffc1Sbeveloper if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) || (flags & B_FLAVOR_IS_GLOBAL)) { 20188b04ffc1Sbeveloper 2019cf4e2277Sbeveloper printf("BMediaRoster::InstantiateDormantNode: creating global object in media_addon_server\n"); 2020cf4e2277Sbeveloper 20218b04ffc1Sbeveloper addonserver_instantiate_dormant_node_request request; 20228b04ffc1Sbeveloper addonserver_instantiate_dormant_node_reply reply; 20238b04ffc1Sbeveloper request.addonid = in_info.addon; 20248b04ffc1Sbeveloper request.flavorid = in_info.flavor_id; 202554187cc6Sbeveloper request.creator_team = team; // creator team is allowed to also release global nodes 20268b04ffc1Sbeveloper rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply)); 20278b04ffc1Sbeveloper if (rv == B_OK) { 20288b04ffc1Sbeveloper *out_node = reply.node; 20298b04ffc1Sbeveloper } 20308b04ffc1Sbeveloper 20318b04ffc1Sbeveloper } else { 20328b04ffc1Sbeveloper 203354187cc6Sbeveloper // creator team = -1, as this is a local node 2034626824eaSbeveloper rv = MediaRosterEx(this)->InstantiateDormantNode(in_info.addon, in_info.flavor_id, -1, out_node); 2035626824eaSbeveloper 20368b04ffc1Sbeveloper } 2037626824eaSbeveloper if (rv != B_OK) { 2038626824eaSbeveloper *out_node = media_node::null; 2039626824eaSbeveloper return B_NAME_NOT_FOUND; 2040626824eaSbeveloper } 2041626824eaSbeveloper return B_OK; 20428b04ffc1Sbeveloper } 20438b04ffc1Sbeveloper 20448b04ffc1Sbeveloper 20458b04ffc1Sbeveloper status_t 20468b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, 20478b04ffc1Sbeveloper media_node * out_node) 20488b04ffc1Sbeveloper { 20498b04ffc1Sbeveloper return InstantiateDormantNode(in_info, out_node, 0); 20508b04ffc1Sbeveloper } 20518b04ffc1Sbeveloper 20528b04ffc1Sbeveloper 20538b04ffc1Sbeveloper status_t 205452a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node & node, 205552a38012Sejakowatz dormant_node_info * out_info) 205652a38012Sejakowatz { 205785dfab2bSbeveloper CALLED(); 205885dfab2bSbeveloper if (out_info == NULL) 205985dfab2bSbeveloper return B_BAD_VALUE; 206040f36b03Sbeveloper if (IS_INVALID_NODE(node)) 206185dfab2bSbeveloper return B_MEDIA_BAD_NODE; 206252a38012Sejakowatz 206385dfab2bSbeveloper server_get_dormant_node_for_request request; 206485dfab2bSbeveloper server_get_dormant_node_for_reply reply; 206585dfab2bSbeveloper status_t rv; 206685dfab2bSbeveloper 206785dfab2bSbeveloper request.node = node; 206885dfab2bSbeveloper 20691299bfb2Sbeveloper rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply)); 207085dfab2bSbeveloper if (rv != B_OK) 207185dfab2bSbeveloper return rv; 207285dfab2bSbeveloper 207385dfab2bSbeveloper *out_info = reply.node_info; 207485dfab2bSbeveloper return B_OK; 207552a38012Sejakowatz } 207652a38012Sejakowatz 207752a38012Sejakowatz status_t 20788b04ffc1Sbeveloper BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonid, 20798b04ffc1Sbeveloper int32 flavorid, 208052a38012Sejakowatz dormant_flavor_info * out_flavor) 208152a38012Sejakowatz { 208252a38012Sejakowatz CALLED(); 208352a38012Sejakowatz 208452a38012Sejakowatz xfer_server_get_dormant_flavor_info msg; 208552a38012Sejakowatz xfer_server_get_dormant_flavor_info_reply *reply; 208652a38012Sejakowatz port_id port; 208752a38012Sejakowatz status_t rv; 208852a38012Sejakowatz int32 code; 208952a38012Sejakowatz 209052a38012Sejakowatz port = find_port("media_server port"); 209152a38012Sejakowatz if (port <= B_OK) 209252a38012Sejakowatz return B_ERROR; 209352a38012Sejakowatz 209452a38012Sejakowatz reply = (xfer_server_get_dormant_flavor_info_reply *) malloc(16000); 209552a38012Sejakowatz if (reply == 0) 209652a38012Sejakowatz return B_ERROR; 209752a38012Sejakowatz 20988b04ffc1Sbeveloper msg.addon = addonid; 20998b04ffc1Sbeveloper msg.flavor_id = flavorid; 210052a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 210152a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg)); 210252a38012Sejakowatz if (rv != B_OK) { 210352a38012Sejakowatz free(reply); 210452a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 210552a38012Sejakowatz return rv; 210652a38012Sejakowatz } 210752a38012Sejakowatz rv = read_port(msg.reply_port, &code, reply, 16000); 210852a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 210952a38012Sejakowatz 211052a38012Sejakowatz if (rv < B_OK) { 211152a38012Sejakowatz free(reply); 211252a38012Sejakowatz return rv; 211352a38012Sejakowatz } 211452a38012Sejakowatz 211552a38012Sejakowatz if (reply->result == B_OK) 211652a38012Sejakowatz rv = out_flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size); 211752a38012Sejakowatz else 211852a38012Sejakowatz rv = reply->result; 211952a38012Sejakowatz 212052a38012Sejakowatz free(reply); 212152a38012Sejakowatz return rv; 212252a38012Sejakowatz } 212352a38012Sejakowatz 21248b04ffc1Sbeveloper status_t 21258b04ffc1Sbeveloper BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info & in_dormant, 21268b04ffc1Sbeveloper dormant_flavor_info * out_flavor) 21278b04ffc1Sbeveloper { 21288b04ffc1Sbeveloper return MediaRosterEx(this)->GetDormantFlavorInfo(in_dormant.addon, in_dormant.flavor_id, out_flavor); 21298b04ffc1Sbeveloper } 213052a38012Sejakowatz 213160f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from 213260f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections. 213352a38012Sejakowatz status_t 213452a38012Sejakowatz BMediaRoster::GetLatencyFor(const media_node & producer, 213552a38012Sejakowatz bigtime_t * out_latency) 213652a38012Sejakowatz { 213760f15390Sbeveloper CALLED(); 213860f15390Sbeveloper if (out_latency == NULL) 213960f15390Sbeveloper return B_BAD_VALUE; 214060f15390Sbeveloper if (IS_INVALID_NODE(producer)) 214160f15390Sbeveloper return B_MEDIA_BAD_NODE; 214260f15390Sbeveloper if ((producer.kind & B_BUFFER_PRODUCER) == 0) 214360f15390Sbeveloper return B_MEDIA_BAD_NODE; 214460f15390Sbeveloper 214560f15390Sbeveloper producer_get_latency_request request; 214660f15390Sbeveloper producer_get_latency_reply reply; 214760f15390Sbeveloper status_t rv; 214860f15390Sbeveloper 214960f15390Sbeveloper rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request, sizeof(request), &reply, sizeof(reply)); 215060f15390Sbeveloper if (rv != B_OK) 215160f15390Sbeveloper return rv; 215260f15390Sbeveloper 215360f15390Sbeveloper *out_latency = reply.latency; 215460f15390Sbeveloper 215560f15390Sbeveloper printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency); 2156aac800c2Sbeveloper return B_OK; 215752a38012Sejakowatz } 215852a38012Sejakowatz 215952a38012Sejakowatz 216052a38012Sejakowatz status_t 216152a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node & producer, 216252a38012Sejakowatz bigtime_t * out_latency, 2163aac800c2Sbeveloper uint32 * out_flags /* = NULL */) 216452a38012Sejakowatz { 216552a38012Sejakowatz UNIMPLEMENTED(); 216660f15390Sbeveloper *out_latency = 5000; 2167aac800c2Sbeveloper if (out_flags) 216852a38012Sejakowatz *out_flags = 0; 2169aac800c2Sbeveloper return B_OK; 217052a38012Sejakowatz } 217152a38012Sejakowatz 217252a38012Sejakowatz 217352a38012Sejakowatz status_t 217452a38012Sejakowatz BMediaRoster::GetStartLatencyFor(const media_node & time_source, 217552a38012Sejakowatz bigtime_t * out_latency) 217652a38012Sejakowatz { 217752a38012Sejakowatz UNIMPLEMENTED(); 2178aac800c2Sbeveloper *out_latency = 5000; 2179aac800c2Sbeveloper return B_OK; 218052a38012Sejakowatz } 218152a38012Sejakowatz 218252a38012Sejakowatz 218352a38012Sejakowatz status_t 218452a38012Sejakowatz BMediaRoster::GetFileFormatsFor(const media_node & file_interface, 218552a38012Sejakowatz media_file_format * out_formats, 218652a38012Sejakowatz int32 * io_num_infos) 218752a38012Sejakowatz { 218852a38012Sejakowatz UNIMPLEMENTED(); 218952a38012Sejakowatz return B_ERROR; 219052a38012Sejakowatz } 219152a38012Sejakowatz 219252a38012Sejakowatz 219352a38012Sejakowatz status_t 219452a38012Sejakowatz BMediaRoster::SetRefFor(const media_node & file_interface, 219552a38012Sejakowatz const entry_ref & file, 219652a38012Sejakowatz bool create_and_truncate, 219752a38012Sejakowatz bigtime_t * out_length) /* if create is false */ 219852a38012Sejakowatz { 219952a38012Sejakowatz UNIMPLEMENTED(); 220052a38012Sejakowatz return B_ERROR; 220152a38012Sejakowatz } 220252a38012Sejakowatz 220352a38012Sejakowatz 220452a38012Sejakowatz status_t 220552a38012Sejakowatz BMediaRoster::GetRefFor(const media_node & node, 220652a38012Sejakowatz entry_ref * out_file, 220752a38012Sejakowatz BMimeType * mime_type) 220852a38012Sejakowatz { 220952a38012Sejakowatz UNIMPLEMENTED(); 221052a38012Sejakowatz return B_ERROR; 221152a38012Sejakowatz } 221252a38012Sejakowatz 221352a38012Sejakowatz 221452a38012Sejakowatz status_t 221552a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node & file_interface, 221652a38012Sejakowatz const entry_ref & file, 221752a38012Sejakowatz BMimeType * mime_type, 221852a38012Sejakowatz float * out_capability) 221952a38012Sejakowatz { 222052a38012Sejakowatz UNIMPLEMENTED(); 222152a38012Sejakowatz return B_ERROR; 222252a38012Sejakowatz } 222352a38012Sejakowatz 222452a38012Sejakowatz 222552a38012Sejakowatz /* This is the generic "here's a file, now can someone please play it" interface */ 222652a38012Sejakowatz status_t 222752a38012Sejakowatz BMediaRoster::SniffRef(const entry_ref & file, 222852a38012Sejakowatz uint64 require_node_kinds, /* if you need an EntityInterface or BufferConsumer or something */ 222952a38012Sejakowatz dormant_node_info * out_node, 223052a38012Sejakowatz BMimeType * mime_type) 223152a38012Sejakowatz { 223252a38012Sejakowatz UNIMPLEMENTED(); 223352a38012Sejakowatz return B_ERROR; 223452a38012Sejakowatz } 223552a38012Sejakowatz 223652a38012Sejakowatz 223752a38012Sejakowatz status_t 223852a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType & type, 223952a38012Sejakowatz uint64 require_node_kinds, 224052a38012Sejakowatz dormant_node_info * out_node) 224152a38012Sejakowatz { 224252a38012Sejakowatz UNIMPLEMENTED(); 224352a38012Sejakowatz return B_ERROR; 224452a38012Sejakowatz } 224552a38012Sejakowatz 224652a38012Sejakowatz 224752a38012Sejakowatz status_t 224852a38012Sejakowatz BMediaRoster::GetReadFileFormatsFor(const dormant_node_info & in_node, 224952a38012Sejakowatz media_file_format * out_read_formats, 225052a38012Sejakowatz int32 in_read_count, 225152a38012Sejakowatz int32 * out_read_count) 225252a38012Sejakowatz { 225352a38012Sejakowatz UNIMPLEMENTED(); 225452a38012Sejakowatz return B_ERROR; 225552a38012Sejakowatz } 225652a38012Sejakowatz 225752a38012Sejakowatz 225852a38012Sejakowatz status_t 225952a38012Sejakowatz BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info & in_node, 226052a38012Sejakowatz media_file_format * out_write_formats, 226152a38012Sejakowatz int32 in_write_count, 226252a38012Sejakowatz int32 * out_write_count) 226352a38012Sejakowatz { 226452a38012Sejakowatz UNIMPLEMENTED(); 226552a38012Sejakowatz return B_ERROR; 226652a38012Sejakowatz } 226752a38012Sejakowatz 226852a38012Sejakowatz 226952a38012Sejakowatz status_t 227052a38012Sejakowatz BMediaRoster::GetFormatFor(const media_output & output, 227152a38012Sejakowatz media_format * io_format, 227252a38012Sejakowatz uint32 flags) 227352a38012Sejakowatz { 227452a38012Sejakowatz UNIMPLEMENTED(); 227552a38012Sejakowatz return B_ERROR; 227652a38012Sejakowatz } 227752a38012Sejakowatz 227852a38012Sejakowatz 227952a38012Sejakowatz status_t 228052a38012Sejakowatz BMediaRoster::GetFormatFor(const media_input & input, 228152a38012Sejakowatz media_format * io_format, 228252a38012Sejakowatz uint32 flags) 228352a38012Sejakowatz { 228452a38012Sejakowatz UNIMPLEMENTED(); 228552a38012Sejakowatz return B_ERROR; 228652a38012Sejakowatz } 228752a38012Sejakowatz 228852a38012Sejakowatz 228952a38012Sejakowatz status_t 229052a38012Sejakowatz BMediaRoster::GetFormatFor(const media_node & node, 229152a38012Sejakowatz media_format * io_format, 229252a38012Sejakowatz float quality) 229352a38012Sejakowatz { 229452a38012Sejakowatz UNIMPLEMENTED(); 229552a38012Sejakowatz return B_ERROR; 229652a38012Sejakowatz } 229752a38012Sejakowatz 229852a38012Sejakowatz 229952a38012Sejakowatz ssize_t 230052a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node & node, 230152a38012Sejakowatz media_node_attribute * outArray, 230252a38012Sejakowatz size_t inMaxCount) 230352a38012Sejakowatz { 230452a38012Sejakowatz UNIMPLEMENTED(); 230552a38012Sejakowatz return B_ERROR; 230652a38012Sejakowatz } 230752a38012Sejakowatz 230852a38012Sejakowatz 230952a38012Sejakowatz media_node_id 231052a38012Sejakowatz BMediaRoster::NodeIDFor(port_id source_or_destination_port) 231152a38012Sejakowatz { 23129e9417d2Sbeveloper CALLED(); 23139e9417d2Sbeveloper 23149e9417d2Sbeveloper server_node_id_for_request request; 23159e9417d2Sbeveloper server_node_id_for_reply reply; 23169e9417d2Sbeveloper status_t rv; 23179e9417d2Sbeveloper 23189e9417d2Sbeveloper request.port = source_or_destination_port; 23199e9417d2Sbeveloper 23209e9417d2Sbeveloper rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, sizeof(reply)); 23219e9417d2Sbeveloper if (rv != B_OK) { 2322353b9f6bSbeveloper FATAL("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv); 23239e9417d2Sbeveloper return -1; 23249e9417d2Sbeveloper } 23259e9417d2Sbeveloper 23269e9417d2Sbeveloper return reply.nodeid; 232752a38012Sejakowatz } 232852a38012Sejakowatz 232952a38012Sejakowatz 233052a38012Sejakowatz status_t 233152a38012Sejakowatz BMediaRoster::GetInstancesFor(media_addon_id addon, 233252a38012Sejakowatz int32 flavor, 233352a38012Sejakowatz media_node_id * out_id, 233452a38012Sejakowatz int32 * io_count) 233552a38012Sejakowatz { 233685dfab2bSbeveloper CALLED(); 233785dfab2bSbeveloper if (out_id == NULL || io_count == NULL) 233885dfab2bSbeveloper return B_BAD_VALUE; 233985dfab2bSbeveloper if (*io_count <= 0) 234085dfab2bSbeveloper return B_BAD_VALUE; 234185dfab2bSbeveloper 234285dfab2bSbeveloper server_get_instances_for_request request; 234385dfab2bSbeveloper server_get_instances_for_reply reply; 234485dfab2bSbeveloper status_t rv; 234585dfab2bSbeveloper 234685dfab2bSbeveloper request.maxcount = *io_count; 234785dfab2bSbeveloper request.addon_id = addon; 234885dfab2bSbeveloper request.addon_flavor_id = flavor; 234985dfab2bSbeveloper 235085dfab2bSbeveloper rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), &reply, sizeof(reply)); 235185dfab2bSbeveloper if (rv != B_OK) { 2352353b9f6bSbeveloper FATAL("BMediaRoster::GetLiveNodes failed\n"); 235385dfab2bSbeveloper return rv; 235452a38012Sejakowatz } 235552a38012Sejakowatz 235685dfab2bSbeveloper *io_count = reply.count; 235785dfab2bSbeveloper if (reply.count > 0) 235885dfab2bSbeveloper memcpy(out_id, reply.node_id, sizeof(media_node_id) * reply.count); 235985dfab2bSbeveloper 236085dfab2bSbeveloper return B_OK; 236185dfab2bSbeveloper } 236252a38012Sejakowatz 236352a38012Sejakowatz 236452a38012Sejakowatz status_t 236552a38012Sejakowatz BMediaRoster::SetRealtimeFlags(uint32 in_enabled) 236652a38012Sejakowatz { 236752a38012Sejakowatz UNIMPLEMENTED(); 236852a38012Sejakowatz return B_ERROR; 236952a38012Sejakowatz } 237052a38012Sejakowatz 237152a38012Sejakowatz 237252a38012Sejakowatz status_t 237352a38012Sejakowatz BMediaRoster::GetRealtimeFlags(uint32 * out_enabled) 237452a38012Sejakowatz { 237552a38012Sejakowatz UNIMPLEMENTED(); 237652a38012Sejakowatz return B_ERROR; 237752a38012Sejakowatz } 237852a38012Sejakowatz 237952a38012Sejakowatz 238052a38012Sejakowatz ssize_t 238152a38012Sejakowatz BMediaRoster::AudioBufferSizeFor(int32 channel_count, 238252a38012Sejakowatz uint32 sample_format, 238352a38012Sejakowatz float frame_rate, 238452a38012Sejakowatz bus_type bus_kind) 238552a38012Sejakowatz { 238652a38012Sejakowatz UNIMPLEMENTED(); 238752a38012Sejakowatz return 4096; 238852a38012Sejakowatz } 238952a38012Sejakowatz 239052a38012Sejakowatz 239152a38012Sejakowatz /* Use MediaFlags to inquire about specific features of the Media Kit. */ 239252a38012Sejakowatz /* Returns < 0 for "not present", positive size for output data size. */ 239352a38012Sejakowatz /* 0 means that the capability is present, but no data about it. */ 239452a38012Sejakowatz /* static */ ssize_t 239552a38012Sejakowatz BMediaRoster::MediaFlags(media_flags cap, 239652a38012Sejakowatz void * buf, 239752a38012Sejakowatz size_t maxSize) 239852a38012Sejakowatz { 239952a38012Sejakowatz UNIMPLEMENTED(); 240052a38012Sejakowatz return 0; 240152a38012Sejakowatz } 240252a38012Sejakowatz 240352a38012Sejakowatz 240452a38012Sejakowatz /* BLooper overrides */ 240552a38012Sejakowatz /* virtual */ void 240652a38012Sejakowatz BMediaRoster::MessageReceived(BMessage * message) 240752a38012Sejakowatz { 2408cf4e2277Sbeveloper switch (message->what) { 2409cf4e2277Sbeveloper case 'PING': 2410cf4e2277Sbeveloper { 24116396865dSbeveloper // media_server plays ping-pong with the BMediaRosters 24126396865dSbeveloper // to detect dead teams. Normal communication uses ports. 24136396865dSbeveloper static BMessage pong('PONG'); 24146396865dSbeveloper message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000); 24156396865dSbeveloper return; 24166396865dSbeveloper } 24176396865dSbeveloper 2418cf4e2277Sbeveloper case NODE_FINAL_RELEASE: 2419cf4e2277Sbeveloper { 2420cf4e2277Sbeveloper // this function is called by a BMediaNode to delete 2421cf4e2277Sbeveloper // itself, as this needs to be done from another thread 2422cf4e2277Sbeveloper // context, it is done here. 2423cf4e2277Sbeveloper // XXX If a node is released using BMediaRoster::ReleaseNode() 2424cf4e2277Sbeveloper // XXX instead of using BMediaNode::Release() / BMediaNode::Acquire() 2425cf4e2277Sbeveloper // XXX fRefCount of the BMediaNode will not be correct. 2426cf4e2277Sbeveloper 2427cf4e2277Sbeveloper BMediaNode *node; 2428cf4e2277Sbeveloper message->FindPointer("node", reinterpret_cast<void **>(&node)); 2429cf4e2277Sbeveloper 243054187cc6Sbeveloper TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE saving node %ld configuration\n", node->ID()); 243154187cc6Sbeveloper MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(node); 2432cf4e2277Sbeveloper 243354187cc6Sbeveloper TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing node %ld\n", node->ID()); 2434cf4e2277Sbeveloper node->DeleteHook(node); // we don't call Release(), see above! 2435cf4e2277Sbeveloper return; 2436cf4e2277Sbeveloper } 2437cf4e2277Sbeveloper } 24386396865dSbeveloper printf("BMediaRoster::MessageReceived: unknown message!\n"); 24396396865dSbeveloper message->PrintToStream(); 244052a38012Sejakowatz } 244152a38012Sejakowatz 244252a38012Sejakowatz /* virtual */ bool 244352a38012Sejakowatz BMediaRoster::QuitRequested() 244452a38012Sejakowatz { 244552a38012Sejakowatz UNIMPLEMENTED(); 244652a38012Sejakowatz return true; 244752a38012Sejakowatz } 244852a38012Sejakowatz 244952a38012Sejakowatz /* virtual */ BHandler * 245052a38012Sejakowatz BMediaRoster::ResolveSpecifier(BMessage *msg, 245152a38012Sejakowatz int32 index, 245252a38012Sejakowatz BMessage *specifier, 245352a38012Sejakowatz int32 form, 245452a38012Sejakowatz const char *property) 245552a38012Sejakowatz { 245652a38012Sejakowatz UNIMPLEMENTED(); 245752a38012Sejakowatz return 0; 245852a38012Sejakowatz } 245952a38012Sejakowatz 246052a38012Sejakowatz 246152a38012Sejakowatz /* virtual */ status_t 246252a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage *data) 246352a38012Sejakowatz { 246452a38012Sejakowatz UNIMPLEMENTED(); 246552a38012Sejakowatz return B_ERROR; 246652a38012Sejakowatz } 246752a38012Sejakowatz 246852a38012Sejakowatz 246952a38012Sejakowatz BMediaRoster::~BMediaRoster() 247052a38012Sejakowatz { 247152a38012Sejakowatz CALLED(); 24726396865dSbeveloper 24736396865dSbeveloper // unregister this application with the media server 24746396865dSbeveloper server_unregister_app_request request; 24756396865dSbeveloper server_unregister_app_reply reply; 24766396865dSbeveloper request.team = team; 24776396865dSbeveloper QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, sizeof(reply)); 247852a38012Sejakowatz } 247952a38012Sejakowatz 248052a38012Sejakowatz 248152a38012Sejakowatz /************************************************************* 248252a38012Sejakowatz * private BMediaRoster 248352a38012Sejakowatz *************************************************************/ 248452a38012Sejakowatz 248552a38012Sejakowatz // deprecated call 248652a38012Sejakowatz status_t 248752a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source & output, 248852a38012Sejakowatz BBufferGroup * group, 248952a38012Sejakowatz bool will_reclaim ) 249052a38012Sejakowatz { 249152a38012Sejakowatz UNIMPLEMENTED(); 24929e9417d2Sbeveloper debugger("BMediaRoster::SetOutputBuffersFor missing\n"); 249352a38012Sejakowatz return B_ERROR; 249452a38012Sejakowatz } 249552a38012Sejakowatz 249652a38012Sejakowatz 249752a38012Sejakowatz /* FBC stuffing (Mmmh, Stuffing!) */ 249852a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; } 249952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; } 250052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; } 250152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; } 250252a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; } 250352a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; } 250452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; } 250552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; } 250652a38012Sejakowatz 250752a38012Sejakowatz 250852a38012Sejakowatz BMediaRoster::BMediaRoster() : 25096396865dSbeveloper BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, B_LOOPER_PORT_DEFAULT_CAPACITY) 251052a38012Sejakowatz { 251152a38012Sejakowatz CALLED(); 25126396865dSbeveloper 25136396865dSbeveloper // start the looper 25146396865dSbeveloper Run(); 25156396865dSbeveloper 25166396865dSbeveloper // register this application with the media server 25176396865dSbeveloper server_register_app_request request; 25186396865dSbeveloper server_register_app_reply reply; 25196396865dSbeveloper request.team = team; 25206396865dSbeveloper request.messenger = BMessenger(NULL, this); 25216396865dSbeveloper QueryServer(SERVER_REGISTER_APP, &request, sizeof(request), &reply, sizeof(reply)); 252252a38012Sejakowatz } 252352a38012Sejakowatz 25246396865dSbeveloper 252552a38012Sejakowatz /* static */ status_t 252652a38012Sejakowatz BMediaRoster::ParseCommand(BMessage & reply) 252752a38012Sejakowatz { 252852a38012Sejakowatz UNIMPLEMENTED(); 252952a38012Sejakowatz return B_ERROR; 253052a38012Sejakowatz } 253152a38012Sejakowatz 253252a38012Sejakowatz 253352a38012Sejakowatz status_t 253452a38012Sejakowatz BMediaRoster::GetDefaultInfo(media_node_id for_default, 253552a38012Sejakowatz BMessage & out_config) 253652a38012Sejakowatz { 253752a38012Sejakowatz UNIMPLEMENTED(); 253852a38012Sejakowatz return B_ERROR; 253952a38012Sejakowatz } 254052a38012Sejakowatz 254152a38012Sejakowatz 254252a38012Sejakowatz 254352a38012Sejakowatz status_t 254452a38012Sejakowatz BMediaRoster::SetRunningDefault(media_node_id for_default, 254552a38012Sejakowatz const media_node & node) 254652a38012Sejakowatz { 254752a38012Sejakowatz UNIMPLEMENTED(); 254852a38012Sejakowatz return B_ERROR; 254952a38012Sejakowatz } 255052a38012Sejakowatz 255152a38012Sejakowatz 255252a38012Sejakowatz /************************************************************* 255352a38012Sejakowatz * static BMediaRoster variables 255452a38012Sejakowatz *************************************************************/ 255552a38012Sejakowatz 255652a38012Sejakowatz bool BMediaRoster::_isMediaServer; 255752a38012Sejakowatz port_id BMediaRoster::_mReplyPort; 255852a38012Sejakowatz int32 BMediaRoster::_mReplyPortRes; 255952a38012Sejakowatz int32 BMediaRoster::_mReplyPortUnavailCount; 256052a38012Sejakowatz BMediaRoster * BMediaRoster::_sDefault = NULL; 256152a38012Sejakowatz 2562