1255a01c7Sbeveloper /* 2255a01c7Sbeveloper * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de> 3255a01c7Sbeveloper * 4255a01c7Sbeveloper * Permission is hereby granted, free of charge, to any person obtaining 5255a01c7Sbeveloper * a copy of this software and associated documentation files or portions 6255a01c7Sbeveloper * thereof (the "Software"), to deal in the Software without restriction, 7255a01c7Sbeveloper * including without limitation the rights to use, copy, modify, merge, 8255a01c7Sbeveloper * publish, distribute, sublicense, and/or sell copies of the Software, 9255a01c7Sbeveloper * and to permit persons to whom the Software is furnished to do so, subject 10255a01c7Sbeveloper * to the following conditions: 11255a01c7Sbeveloper * 12255a01c7Sbeveloper * * Redistributions of source code must retain the above copyright notice, 13255a01c7Sbeveloper * this list of conditions and the following disclaimer. 14255a01c7Sbeveloper * 15255a01c7Sbeveloper * * Redistributions in binary form must reproduce the above copyright notice 16255a01c7Sbeveloper * in the binary, as well as this list of conditions and the following 17255a01c7Sbeveloper * disclaimer in the documentation and/or other materials provided with 18255a01c7Sbeveloper * the distribution. 19255a01c7Sbeveloper * 20255a01c7Sbeveloper * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21255a01c7Sbeveloper * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22255a01c7Sbeveloper * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23255a01c7Sbeveloper * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24255a01c7Sbeveloper * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25255a01c7Sbeveloper * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26255a01c7Sbeveloper * THE SOFTWARE. 27255a01c7Sbeveloper * 28255a01c7Sbeveloper */ 29255a01c7Sbeveloper 30255a01c7Sbeveloper /* to comply with the license above, do not remove the following line */ 31d91580cdSbeveloper char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>"; 32255a01c7Sbeveloper 3352a38012Sejakowatz #include <MediaRoster.h> 3452a38012Sejakowatz #include <Locker.h> 3552a38012Sejakowatz #include <Message.h> 3652a38012Sejakowatz #include <Messenger.h> 3752a38012Sejakowatz #include <StopWatch.h> 3852a38012Sejakowatz #include <OS.h> 3952a38012Sejakowatz #include <String.h> 4052a38012Sejakowatz #include <TimeSource.h> 4160f15390Sbeveloper #include <ParameterWeb.h> 424d2d96e0Sbeveloper #include <BufferProducer.h> 434d2d96e0Sbeveloper #include <BufferConsumer.h> 4452a38012Sejakowatz #include "debug.h" 458b04ffc1Sbeveloper #include "MediaRosterEx.h" 4640f36b03Sbeveloper #include "MediaMisc.h" 4752a38012Sejakowatz #include "PortPool.h" 480a483e72SIngo Weinhold #include "ServerInterface.h" 49f4925104Sbeveloper #include "DataExchange.h" 5016b7eea4Sbeveloper #include "DormantNodeManager.h" 51f4925104Sbeveloper #include "Notifications.h" 52835140c8Sbeveloper #include "TimeSourceObjectManager.h" 5352a38012Sejakowatz 54f4925104Sbeveloper namespace BPrivate { namespace media { 5552a38012Sejakowatz 5652a38012Sejakowatz // the BMediaRoster destructor is private, 5752a38012Sejakowatz // but _DefaultDeleter is a friend class of 5852a38012Sejakowatz // the BMediaRoster an thus can delete it 598b04ffc1Sbeveloper class DefaultDeleter 6052a38012Sejakowatz { 6152a38012Sejakowatz public: 628b04ffc1Sbeveloper ~DefaultDeleter() 636396865dSbeveloper { 646396865dSbeveloper if (BMediaRoster::_sDefault) { 656396865dSbeveloper BMediaRoster::_sDefault->Lock(); 666396865dSbeveloper BMediaRoster::_sDefault->Quit(); 676396865dSbeveloper } 686396865dSbeveloper } 698b04ffc1Sbeveloper }; 7052a38012Sejakowatz 718b04ffc1Sbeveloper } } // BPrivate::media 728b04ffc1Sbeveloper using namespace BPrivate::media; 7352a38012Sejakowatz 748b04ffc1Sbeveloper // DefaultDeleter will delete the BMediaRoster object in it's destructor. 758b04ffc1Sbeveloper DefaultDeleter _deleter; 7652a38012Sejakowatz 77dcfb6bfcSJérôme Duval BMediaRosterEx::BMediaRosterEx(status_t * out_error) 78dcfb6bfcSJérôme Duval : BMediaRoster() 79dcfb6bfcSJérôme Duval { 80dcfb6bfcSJérôme Duval status_t rv; 81dcfb6bfcSJérôme Duval // register this application with the media server 82dcfb6bfcSJérôme Duval server_register_app_request request; 83dcfb6bfcSJérôme Duval server_register_app_reply reply; 84dcfb6bfcSJérôme Duval request.team = team; 85dcfb6bfcSJérôme Duval request.messenger = BMessenger(NULL, this); 86dcfb6bfcSJérôme Duval rv = QueryServer(SERVER_REGISTER_APP, &request, sizeof(request), &reply, sizeof(reply)); 87*8496c38aSbeveloper *out_error = (rv != B_OK) ? B_MEDIA_SYSTEM_FAILURE : B_OK; 88dcfb6bfcSJérôme Duval } 89dcfb6bfcSJérôme Duval 903620737cSbeveloper status_t 9154187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode *node) 9254187cc6Sbeveloper { 9354187cc6Sbeveloper BMediaAddOn *addon; 9454187cc6Sbeveloper media_addon_id addonid; 9554187cc6Sbeveloper int32 flavorid; 9654187cc6Sbeveloper addon = node->AddOn(&flavorid); 9754187cc6Sbeveloper if (!addon) { 9860f15390Sbeveloper // XXX this check incorrectly triggers on BeOS R5 BT848 node 995ac4fbd7Sbeveloper ERROR("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated from BMediaAddOn!\n", node->ID()); 10054187cc6Sbeveloper return B_ERROR; 10154187cc6Sbeveloper } 10254187cc6Sbeveloper addonid = addon->AddonID(); 10354187cc6Sbeveloper 10454187cc6Sbeveloper // XXX fix this 10554187cc6Sbeveloper printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid); 10654187cc6Sbeveloper return B_OK; 10754187cc6Sbeveloper } 10854187cc6Sbeveloper 10954187cc6Sbeveloper status_t 11054187cc6Sbeveloper BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage *out_msg) 11154187cc6Sbeveloper { 11254187cc6Sbeveloper // XXX fix this 11354187cc6Sbeveloper out_msg->MakeEmpty(); // to be fully R5 compliant 11454187cc6Sbeveloper printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid); 11554187cc6Sbeveloper return B_OK; 11654187cc6Sbeveloper } 11754187cc6Sbeveloper 11854187cc6Sbeveloper status_t 11973794717Sbeveloper BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid) 12054187cc6Sbeveloper { 12173794717Sbeveloper server_change_addon_flavor_instances_count_request request; 12273794717Sbeveloper server_change_addon_flavor_instances_count_reply reply; 12373794717Sbeveloper 12473794717Sbeveloper request.addonid = addonid; 12573794717Sbeveloper request.flavorid = flavorid; 12673794717Sbeveloper request.delta = 1; 12773794717Sbeveloper request.team = team; 12873794717Sbeveloper return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply)); 12954187cc6Sbeveloper } 13054187cc6Sbeveloper 13154187cc6Sbeveloper status_t 13273794717Sbeveloper BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid) 13354187cc6Sbeveloper { 13473794717Sbeveloper server_change_addon_flavor_instances_count_request request; 13573794717Sbeveloper server_change_addon_flavor_instances_count_reply reply; 13673794717Sbeveloper 13773794717Sbeveloper request.addonid = addonid; 13873794717Sbeveloper request.flavorid = flavorid; 13973794717Sbeveloper request.delta = -1; 14073794717Sbeveloper request.team = team; 14173794717Sbeveloper return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply)); 14254187cc6Sbeveloper } 14354187cc6Sbeveloper 14454187cc6Sbeveloper status_t 14554187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator) 14654187cc6Sbeveloper { 14754187cc6Sbeveloper server_set_node_creator_request request; 14854187cc6Sbeveloper server_set_node_creator_reply reply; 14954187cc6Sbeveloper 15054187cc6Sbeveloper request.node = node; 15154187cc6Sbeveloper request.creator = creator; 15254187cc6Sbeveloper return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request), &reply, sizeof(reply)); 15354187cc6Sbeveloper } 15454187cc6Sbeveloper 15554187cc6Sbeveloper status_t 1568b04ffc1Sbeveloper BMediaRosterEx::GetNode(node_type type, media_node * out_node, int32 * out_input_id, BString * out_input_name) 15752a38012Sejakowatz { 15852a38012Sejakowatz if (out_node == NULL) 15952a38012Sejakowatz return B_BAD_VALUE; 16052a38012Sejakowatz 1618c6a6096Sbeveloper server_get_node_request request; 1628c6a6096Sbeveloper server_get_node_reply reply; 16352a38012Sejakowatz status_t rv; 16452a38012Sejakowatz 1658c6a6096Sbeveloper request.type = type; 1669e9417d2Sbeveloper request.team = team; 1678c6a6096Sbeveloper rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, sizeof(reply)); 1688c6a6096Sbeveloper if (rv != B_OK) 1698c6a6096Sbeveloper return rv; 17052a38012Sejakowatz 17152a38012Sejakowatz *out_node = reply.node; 17252a38012Sejakowatz if (out_input_id) 17352a38012Sejakowatz *out_input_id = reply.input_id; 17452a38012Sejakowatz if (out_input_name) 17552a38012Sejakowatz *out_input_name = reply.input_name; 1768c6a6096Sbeveloper return rv; 17752a38012Sejakowatz } 17852a38012Sejakowatz 1793620737cSbeveloper status_t 1808b04ffc1Sbeveloper BMediaRosterEx::SetNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input) 18152a38012Sejakowatz { 1828c6a6096Sbeveloper server_set_node_request request; 1838c6a6096Sbeveloper server_set_node_reply reply; 18452a38012Sejakowatz 1858c6a6096Sbeveloper request.type = type; 1868c6a6096Sbeveloper request.use_node = node ? true : false; 18752a38012Sejakowatz if (node) 1888c6a6096Sbeveloper request.node = *node; 1898c6a6096Sbeveloper request.use_dni = info ? true : false; 19052a38012Sejakowatz if (info) 1918c6a6096Sbeveloper request.dni = *info; 1928c6a6096Sbeveloper request.use_input = input ? true : false; 19352a38012Sejakowatz if (input) 1948c6a6096Sbeveloper request.input = *input; 19552a38012Sejakowatz 1968c6a6096Sbeveloper return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, sizeof(reply)); 19752a38012Sejakowatz } 19852a38012Sejakowatz 1993620737cSbeveloper status_t 2008b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node & node, List<media_output> *list) 2013620737cSbeveloper { 2023620737cSbeveloper int32 cookie; 2033620737cSbeveloper status_t rv; 2043620737cSbeveloper status_t result; 2053620737cSbeveloper 2065ac4fbd7Sbeveloper PRINT(4, "BMediaRosterEx::GetAllOutputs() node %ld, port %ld\n", node.node, node.port); 2075ac4fbd7Sbeveloper 2083620737cSbeveloper result = B_OK; 2093620737cSbeveloper cookie = 0; 21076669a29Sbeveloper list->MakeEmpty(); 2113620737cSbeveloper for (;;) { 2123620737cSbeveloper producer_get_next_output_request request; 2133620737cSbeveloper producer_get_next_output_reply reply; 2143620737cSbeveloper request.cookie = cookie; 2150caff283Sbeveloper rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, sizeof(request), &reply, sizeof(reply)); 2163620737cSbeveloper if (rv != B_OK) 2173620737cSbeveloper break; 2183620737cSbeveloper cookie = reply.cookie; 21976669a29Sbeveloper if (!list->Insert(reply.output)) { 2205ac4fbd7Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 2213620737cSbeveloper result = B_ERROR; 2223620737cSbeveloper } 2235ac4fbd7Sbeveloper #if DEBUG >= 3 2245ac4fbd7Sbeveloper PRINT(3," next cookie %ld, ", cookie); 2255ac4fbd7Sbeveloper PRINT_OUTPUT("output ", reply.output); 2265ac4fbd7Sbeveloper #endif 2273620737cSbeveloper } 2283620737cSbeveloper 2293620737cSbeveloper producer_dispose_output_cookie_request request; 2303620737cSbeveloper producer_dispose_output_cookie_reply reply; 2310caff283Sbeveloper QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply)); 2323620737cSbeveloper 2333620737cSbeveloper return result; 2343620737cSbeveloper } 2353620737cSbeveloper 2363620737cSbeveloper status_t 2374d2d96e0Sbeveloper BMediaRosterEx::GetAllOutputs(BBufferProducer *node, List<media_output> *list) 2384d2d96e0Sbeveloper { 2394d2d96e0Sbeveloper int32 cookie; 2404d2d96e0Sbeveloper status_t result; 2414d2d96e0Sbeveloper 2424d2d96e0Sbeveloper PRINT(4, "BMediaRosterEx::GetAllOutputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort()); 2434d2d96e0Sbeveloper 2444d2d96e0Sbeveloper result = B_OK; 2454d2d96e0Sbeveloper cookie = 0; 2464d2d96e0Sbeveloper list->MakeEmpty(); 2474d2d96e0Sbeveloper for (;;) { 2484d2d96e0Sbeveloper media_output output; 2494d2d96e0Sbeveloper if (B_OK != node->GetNextOutput(&cookie, &output)) 2504d2d96e0Sbeveloper break; 2514d2d96e0Sbeveloper if (!list->Insert(output)) { 2524d2d96e0Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 2534d2d96e0Sbeveloper result = B_ERROR; 2544d2d96e0Sbeveloper } 2554d2d96e0Sbeveloper #if DEBUG >= 3 2564d2d96e0Sbeveloper PRINT(3," next cookie %ld, ", cookie); 2574d2d96e0Sbeveloper PRINT_OUTPUT("output ", output); 2584d2d96e0Sbeveloper #endif 2594d2d96e0Sbeveloper } 2604d2d96e0Sbeveloper node->DisposeOutputCookie(cookie); 2614d2d96e0Sbeveloper return result; 2624d2d96e0Sbeveloper } 2634d2d96e0Sbeveloper 2644d2d96e0Sbeveloper status_t 2658b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node & node, List<media_input> *list) 2663620737cSbeveloper { 2673620737cSbeveloper int32 cookie; 2683620737cSbeveloper status_t rv; 2693620737cSbeveloper status_t result; 2703620737cSbeveloper 2715ac4fbd7Sbeveloper PRINT(4, "BMediaRosterEx::GetAllInputs() node %ld, port %ld\n", node.node, node.port); 2725ac4fbd7Sbeveloper 2733620737cSbeveloper result = B_OK; 2743620737cSbeveloper cookie = 0; 27576669a29Sbeveloper list->MakeEmpty(); 2763620737cSbeveloper for (;;) { 2773620737cSbeveloper consumer_get_next_input_request request; 2783620737cSbeveloper consumer_get_next_input_reply reply; 2793620737cSbeveloper request.cookie = cookie; 2800caff283Sbeveloper rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, sizeof(request), &reply, sizeof(reply)); 2813620737cSbeveloper if (rv != B_OK) 2823620737cSbeveloper break; 2833620737cSbeveloper cookie = reply.cookie; 28476669a29Sbeveloper if (!list->Insert(reply.input)) { 2855ac4fbd7Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 2863620737cSbeveloper result = B_ERROR; 2873620737cSbeveloper } 2885ac4fbd7Sbeveloper #if DEBUG >= 3 2895ac4fbd7Sbeveloper PRINT(3," next cookie %ld, ", cookie); 2905ac4fbd7Sbeveloper PRINT_OUTPUT("input ", reply.input); 2915ac4fbd7Sbeveloper #endif 2923620737cSbeveloper } 2933620737cSbeveloper 2943620737cSbeveloper consumer_dispose_input_cookie_request request; 2953620737cSbeveloper consumer_dispose_input_cookie_reply reply; 2960caff283Sbeveloper QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply)); 2973620737cSbeveloper 2983620737cSbeveloper return result; 2993620737cSbeveloper } 3003620737cSbeveloper 3013620737cSbeveloper status_t 3024d2d96e0Sbeveloper BMediaRosterEx::GetAllInputs(BBufferConsumer *node, List<media_input> *list) 3034d2d96e0Sbeveloper { 3044d2d96e0Sbeveloper int32 cookie; 3054d2d96e0Sbeveloper status_t result; 3064d2d96e0Sbeveloper 3074d2d96e0Sbeveloper PRINT(4, "BMediaRosterEx::GetAllInputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort()); 3084d2d96e0Sbeveloper 3094d2d96e0Sbeveloper result = B_OK; 3104d2d96e0Sbeveloper cookie = 0; 3114d2d96e0Sbeveloper list->MakeEmpty(); 3124d2d96e0Sbeveloper for (;;) { 3134d2d96e0Sbeveloper media_input input; 3144d2d96e0Sbeveloper if (B_OK != node->GetNextInput(&cookie, &input)) 3154d2d96e0Sbeveloper break; 3164d2d96e0Sbeveloper if (!list->Insert(input)) { 3174d2d96e0Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 3184d2d96e0Sbeveloper result = B_ERROR; 3194d2d96e0Sbeveloper } 3204d2d96e0Sbeveloper #if DEBUG >= 3 3214d2d96e0Sbeveloper PRINT(3," next cookie %ld, ", cookie); 3224d2d96e0Sbeveloper PRINT_INPUT("input ", input); 3234d2d96e0Sbeveloper #endif 3244d2d96e0Sbeveloper } 3254d2d96e0Sbeveloper node->DisposeInputCookie(cookie); 3264d2d96e0Sbeveloper return result; 3274d2d96e0Sbeveloper } 3284d2d96e0Sbeveloper 3294d2d96e0Sbeveloper status_t 3308b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node & node, List<media_output> *list) 3313620737cSbeveloper { 3323620737cSbeveloper server_publish_outputs_request request; 3333620737cSbeveloper server_publish_outputs_reply reply; 3343620737cSbeveloper media_output *output; 3353620737cSbeveloper media_output *outputs; 3363620737cSbeveloper int32 count; 337a7b41a96Sbeveloper status_t rv; 3383620737cSbeveloper 33976669a29Sbeveloper count = list->CountItems(); 3403620737cSbeveloper TRACE("PublishOutputs: publishing %ld\n", count); 3413620737cSbeveloper 3423620737cSbeveloper request.node = node; 3433620737cSbeveloper request.count = count; 3443620737cSbeveloper if (count > MAX_OUTPUTS) { 3453620737cSbeveloper void *start_addr; 3463620737cSbeveloper size_t size; 34740f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_output)); 3483620737cSbeveloper request.area = create_area("publish outputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 3493620737cSbeveloper if (request.area < B_OK) { 3505ac4fbd7Sbeveloper ERROR("PublishOutputs: failed to create area, %#lx\n", request.area); 3513620737cSbeveloper return (status_t)request.area; 3523620737cSbeveloper } 3533620737cSbeveloper outputs = static_cast<media_output *>(start_addr); 3543620737cSbeveloper } else { 3553620737cSbeveloper request.area = -1; 3563620737cSbeveloper outputs = request.outputs; 3573620737cSbeveloper } 35876669a29Sbeveloper TRACE("PublishOutputs: area %ld\n", request.area); 3593620737cSbeveloper 36076669a29Sbeveloper int i; 36176669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&output); i++) { 36276669a29Sbeveloper ASSERT(i < count); 3633620737cSbeveloper outputs[i] = *output; 3643620737cSbeveloper } 3653620737cSbeveloper 366a7b41a96Sbeveloper rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), &reply, sizeof(reply)); 367a7b41a96Sbeveloper 368a7b41a96Sbeveloper if (request.area != -1) 369a7b41a96Sbeveloper delete_area(request.area); 370a7b41a96Sbeveloper 371a7b41a96Sbeveloper return rv; 3723620737cSbeveloper } 3733620737cSbeveloper 3743620737cSbeveloper status_t 3758b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node & node, List<media_input> *list) 3763620737cSbeveloper { 3773620737cSbeveloper server_publish_inputs_request request; 3783620737cSbeveloper server_publish_inputs_reply reply; 3793620737cSbeveloper media_input *input; 3803620737cSbeveloper media_input *inputs; 3813620737cSbeveloper int32 count; 382a7b41a96Sbeveloper status_t rv; 3833620737cSbeveloper 38476669a29Sbeveloper count = list->CountItems(); 3853620737cSbeveloper TRACE("PublishInputs: publishing %ld\n", count); 3863620737cSbeveloper 3873620737cSbeveloper request.node = node; 3883620737cSbeveloper request.count = count; 3893620737cSbeveloper if (count > MAX_INPUTS) { 3903620737cSbeveloper void *start_addr; 3913620737cSbeveloper size_t size; 39240f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_input)); 3933620737cSbeveloper request.area = create_area("publish inputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 3943620737cSbeveloper if (request.area < B_OK) { 3955ac4fbd7Sbeveloper ERROR("PublishInputs: failed to create area, %#lx\n", request.area); 3963620737cSbeveloper return (status_t)request.area; 3973620737cSbeveloper } 3983620737cSbeveloper inputs = static_cast<media_input *>(start_addr); 3993620737cSbeveloper } else { 4003620737cSbeveloper request.area = -1; 4013620737cSbeveloper inputs = request.inputs; 4023620737cSbeveloper } 40376669a29Sbeveloper TRACE("PublishInputs: area %ld\n", request.area); 4043620737cSbeveloper 40576669a29Sbeveloper int i; 40676669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&input); i++) { 40776669a29Sbeveloper ASSERT(i < count); 4083620737cSbeveloper inputs[i] = *input; 4093620737cSbeveloper } 4103620737cSbeveloper 411a7b41a96Sbeveloper rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), &reply, sizeof(reply)); 412a7b41a96Sbeveloper 413a7b41a96Sbeveloper if (request.area != -1) 414a7b41a96Sbeveloper delete_area(request.area); 415a7b41a96Sbeveloper 416a7b41a96Sbeveloper return rv; 4173620737cSbeveloper } 4183620737cSbeveloper 41952a38012Sejakowatz /************************************************************* 42052a38012Sejakowatz * public BMediaRoster 42152a38012Sejakowatz *************************************************************/ 42252a38012Sejakowatz 42352a38012Sejakowatz status_t 42452a38012Sejakowatz BMediaRoster::GetVideoInput(media_node * out_node) 42552a38012Sejakowatz { 42652a38012Sejakowatz CALLED(); 4278b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(VIDEO_INPUT, out_node); 42852a38012Sejakowatz } 42952a38012Sejakowatz 43052a38012Sejakowatz 43152a38012Sejakowatz status_t 43252a38012Sejakowatz BMediaRoster::GetAudioInput(media_node * out_node) 43352a38012Sejakowatz { 43452a38012Sejakowatz CALLED(); 4358b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_INPUT, out_node); 43652a38012Sejakowatz } 43752a38012Sejakowatz 43852a38012Sejakowatz 43952a38012Sejakowatz status_t 44052a38012Sejakowatz BMediaRoster::GetVideoOutput(media_node * out_node) 44152a38012Sejakowatz { 44252a38012Sejakowatz CALLED(); 4438b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, out_node); 44452a38012Sejakowatz } 44552a38012Sejakowatz 44652a38012Sejakowatz 44752a38012Sejakowatz status_t 44852a38012Sejakowatz BMediaRoster::GetAudioMixer(media_node * out_node) 44952a38012Sejakowatz { 45052a38012Sejakowatz CALLED(); 4518b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_MIXER, out_node); 45252a38012Sejakowatz } 45352a38012Sejakowatz 45452a38012Sejakowatz 45552a38012Sejakowatz status_t 45652a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node) 45752a38012Sejakowatz { 45852a38012Sejakowatz CALLED(); 4598b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, out_node); 46052a38012Sejakowatz } 46152a38012Sejakowatz 46252a38012Sejakowatz 46352a38012Sejakowatz status_t 46452a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node, 46552a38012Sejakowatz int32 * out_input_id, 46652a38012Sejakowatz BString * out_input_name) 46752a38012Sejakowatz { 46852a38012Sejakowatz CALLED(); 4698b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, out_node, out_input_id, out_input_name); 47052a38012Sejakowatz } 47152a38012Sejakowatz 47252a38012Sejakowatz 47352a38012Sejakowatz status_t 47452a38012Sejakowatz BMediaRoster::GetTimeSource(media_node * out_node) 47552a38012Sejakowatz { 47652a38012Sejakowatz CALLED(); 47786bce45bSbeveloper status_t rv; 47886bce45bSbeveloper 47986bce45bSbeveloper // XXX need to do this in a nicer way. 48086bce45bSbeveloper 48186bce45bSbeveloper rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, out_node); 48286bce45bSbeveloper if (rv != B_OK) 48386bce45bSbeveloper return rv; 48486bce45bSbeveloper 48586bce45bSbeveloper // We don't do reference counting for timesources, that's why we 48686bce45bSbeveloper // release the node immediately. 48786bce45bSbeveloper ReleaseNode(*out_node); 48886bce45bSbeveloper 48986bce45bSbeveloper // we need to remember to not use this node with server side reference counting 49086bce45bSbeveloper out_node->kind |= NODE_KIND_NO_REFCOUNTING; 49186bce45bSbeveloper 49286bce45bSbeveloper return B_OK; 49352a38012Sejakowatz } 49452a38012Sejakowatz 49552a38012Sejakowatz 49652a38012Sejakowatz status_t 49752a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node & producer) 49852a38012Sejakowatz { 49952a38012Sejakowatz CALLED(); 5008b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer); 50152a38012Sejakowatz } 50252a38012Sejakowatz 50352a38012Sejakowatz 50452a38012Sejakowatz status_t 50552a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info & producer) 50652a38012Sejakowatz { 50752a38012Sejakowatz CALLED(); 5088b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer); 50952a38012Sejakowatz } 51052a38012Sejakowatz 51152a38012Sejakowatz 51252a38012Sejakowatz status_t 51352a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node & producer) 51452a38012Sejakowatz { 51552a38012Sejakowatz CALLED(); 5168b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer); 51752a38012Sejakowatz } 51852a38012Sejakowatz 51952a38012Sejakowatz 52052a38012Sejakowatz status_t 52152a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info & producer) 52252a38012Sejakowatz { 52352a38012Sejakowatz CALLED(); 5248b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer); 52552a38012Sejakowatz } 52652a38012Sejakowatz 52752a38012Sejakowatz 52852a38012Sejakowatz status_t 52952a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node & consumer) 53052a38012Sejakowatz { 53152a38012Sejakowatz CALLED(); 5328b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer); 53352a38012Sejakowatz } 53452a38012Sejakowatz 53552a38012Sejakowatz 53652a38012Sejakowatz status_t 53752a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info & consumer) 53852a38012Sejakowatz { 53952a38012Sejakowatz CALLED(); 5408b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer); 54152a38012Sejakowatz } 54252a38012Sejakowatz 54352a38012Sejakowatz 54452a38012Sejakowatz status_t 54552a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node & consumer) 54652a38012Sejakowatz { 54752a38012Sejakowatz CALLED(); 5488b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer); 54952a38012Sejakowatz } 55052a38012Sejakowatz 55152a38012Sejakowatz 55252a38012Sejakowatz status_t 55352a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_input & input_to_output) 55452a38012Sejakowatz { 55552a38012Sejakowatz CALLED(); 5568b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input_to_output); 55752a38012Sejakowatz } 55852a38012Sejakowatz 55952a38012Sejakowatz 56052a38012Sejakowatz status_t 56152a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info & consumer) 56252a38012Sejakowatz { 56352a38012Sejakowatz CALLED(); 5648b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer); 56552a38012Sejakowatz } 56652a38012Sejakowatz 56752a38012Sejakowatz 56852a38012Sejakowatz status_t 56952a38012Sejakowatz BMediaRoster::GetNodeFor(media_node_id node, 57052a38012Sejakowatz media_node * clone) 57152a38012Sejakowatz { 5729e9417d2Sbeveloper CALLED(); 5739e9417d2Sbeveloper if (clone == NULL) 5749e9417d2Sbeveloper return B_BAD_VALUE; 5759e9417d2Sbeveloper if (node <= 0) 5769e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 5779e9417d2Sbeveloper 5789e9417d2Sbeveloper server_get_node_for_request request; 5799e9417d2Sbeveloper server_get_node_for_reply reply; 5809e9417d2Sbeveloper status_t rv; 5819e9417d2Sbeveloper 5829e9417d2Sbeveloper request.nodeid = node; 5839e9417d2Sbeveloper request.team = team; 5849e9417d2Sbeveloper 5859e9417d2Sbeveloper rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply)); 5869e9417d2Sbeveloper if (rv != B_OK) 5879e9417d2Sbeveloper return rv; 5889e9417d2Sbeveloper 5899e9417d2Sbeveloper *clone = reply.clone; 5909e9417d2Sbeveloper return B_OK; 59152a38012Sejakowatz } 59252a38012Sejakowatz 59352a38012Sejakowatz 59452a38012Sejakowatz status_t 59552a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node * clone) 59652a38012Sejakowatz { 59752a38012Sejakowatz CALLED(); 59886bce45bSbeveloper status_t rv; 59986bce45bSbeveloper 60086bce45bSbeveloper // XXX need to do this in a nicer way. 60186bce45bSbeveloper 60286bce45bSbeveloper rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone); 60386bce45bSbeveloper if (rv != B_OK) 60486bce45bSbeveloper return rv; 60586bce45bSbeveloper 60686bce45bSbeveloper // We don't do reference counting for timesources, that's why we 60786bce45bSbeveloper // release the node immediately. 60886bce45bSbeveloper ReleaseNode(*clone); 60986bce45bSbeveloper 61086bce45bSbeveloper // we need to remember to not use this node with server side reference counting 61186bce45bSbeveloper clone->kind |= NODE_KIND_NO_REFCOUNTING; 61286bce45bSbeveloper 61386bce45bSbeveloper return B_OK; 61452a38012Sejakowatz } 61552a38012Sejakowatz 61652a38012Sejakowatz 61752a38012Sejakowatz status_t 61852a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node & node) 61952a38012Sejakowatz { 6209e9417d2Sbeveloper CALLED(); 62140f36b03Sbeveloper if (IS_INVALID_NODE(node)) 6229e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 62352a38012Sejakowatz 62486bce45bSbeveloper if (node.kind & NODE_KIND_NO_REFCOUNTING) { 62586bce45bSbeveloper printf("BMediaRoster::ReleaseNode, trying to release reference counting disabled timesource, node %ld, port %ld, team %ld\n", node.node, node.port, team); 62686bce45bSbeveloper return B_OK; 62786bce45bSbeveloper } 62886bce45bSbeveloper 6299e9417d2Sbeveloper server_release_node_request request; 6309e9417d2Sbeveloper server_release_node_reply reply; 631cf4e2277Sbeveloper status_t rv; 6329e9417d2Sbeveloper 6339e9417d2Sbeveloper request.node = node; 6349e9417d2Sbeveloper request.team = team; 6359e9417d2Sbeveloper 63660f15390Sbeveloper TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n", node.node, node.port, team); 637cf4e2277Sbeveloper 638cf4e2277Sbeveloper rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, sizeof(reply)); 639cf4e2277Sbeveloper if (rv != B_OK) { 6405ac4fbd7Sbeveloper ERROR("BMediaRoster::ReleaseNode FAILED, node %ld, port %ld, team %ld!\n", node.node, node.port, team); 641cf4e2277Sbeveloper } 642cf4e2277Sbeveloper return rv; 6439e9417d2Sbeveloper } 64452a38012Sejakowatz 64552a38012Sejakowatz BTimeSource * 64652a38012Sejakowatz BMediaRoster::MakeTimeSourceFor(const media_node & for_node) 64752a38012Sejakowatz { 648f180ef79Sbeveloper // MakeTimeSourceFor() returns a BTimeSource object 649f180ef79Sbeveloper // corresponding to the specified node's time source. 650f180ef79Sbeveloper 651835140c8Sbeveloper CALLED(); 652f180ef79Sbeveloper 65392e575c1Sbeveloper if (IS_SYSTEM_TIMESOURCE(for_node)) { 654f180ef79Sbeveloper // special handling for the system time source 655f180ef79Sbeveloper TRACE("BMediaRoster::MakeTimeSourceFor, asked for system time source\n"); 656f180ef79Sbeveloper return MediaRosterEx(this)->MakeTimeSourceObject(NODE_SYSTEM_TIMESOURCE_ID); 657f180ef79Sbeveloper } 658f180ef79Sbeveloper 6595917dd5bSbeveloper if (IS_INVALID_NODE(for_node)) { 6605ac4fbd7Sbeveloper ERROR("BMediaRoster::MakeTimeSourceFor: for_node invalid, node %ld, port %ld, kinds 0x%lx\n", for_node.node, for_node.port, for_node.kind); 6615917dd5bSbeveloper return NULL; 6620e21b167Sbeveloper } 6630e21b167Sbeveloper 664f180ef79Sbeveloper TRACE("BMediaRoster::MakeTimeSourceFor: node %ld enter\n", for_node.node); 6655917dd5bSbeveloper 6665917dd5bSbeveloper node_get_timesource_request request; 6675917dd5bSbeveloper node_get_timesource_reply reply; 6685917dd5bSbeveloper BTimeSource *source; 6695917dd5bSbeveloper status_t rv; 6705917dd5bSbeveloper 67192e575c1Sbeveloper // ask the node to get it's current timesource id 6725917dd5bSbeveloper rv = QueryPort(for_node.port, NODE_GET_TIMESOURCE, &request, sizeof(request), &reply, sizeof(reply)); 6735917dd5bSbeveloper if (rv != B_OK) { 6745ac4fbd7Sbeveloper ERROR("BMediaRoster::MakeTimeSourceFor: request failed\n"); 6755917dd5bSbeveloper return NULL; 6765917dd5bSbeveloper } 6775917dd5bSbeveloper 6785917dd5bSbeveloper source = MediaRosterEx(this)->MakeTimeSourceObject(reply.timesource_id); 6795917dd5bSbeveloper 680f180ef79Sbeveloper TRACE("BMediaRoster::MakeTimeSourceFor: node %ld leave\n", for_node.node); 6815917dd5bSbeveloper 6825917dd5bSbeveloper return source; 6835917dd5bSbeveloper } 6845917dd5bSbeveloper 6855917dd5bSbeveloper BTimeSource * 6865917dd5bSbeveloper BMediaRosterEx::MakeTimeSourceObject(media_node_id timesource_id) 6875917dd5bSbeveloper { 6885917dd5bSbeveloper BTimeSource *source; 6895917dd5bSbeveloper media_node clone; 6905917dd5bSbeveloper status_t rv; 6915917dd5bSbeveloper 6925917dd5bSbeveloper rv = GetNodeFor(timesource_id, &clone); 6935917dd5bSbeveloper if (rv != B_OK) { 6945ac4fbd7Sbeveloper ERROR("BMediaRosterEx::MakeTimeSourceObject: GetNodeFor failed\n"); 6955917dd5bSbeveloper return NULL; 6965917dd5bSbeveloper } 6975917dd5bSbeveloper 6985917dd5bSbeveloper source = _TimeSourceObjectManager->GetTimeSource(clone); 6995917dd5bSbeveloper if (source == NULL) { 7005ac4fbd7Sbeveloper ERROR("BMediaRosterEx::MakeTimeSourceObject: GetTimeSource failed\n"); 7015917dd5bSbeveloper return NULL; 7025917dd5bSbeveloper } 7035917dd5bSbeveloper 70492e575c1Sbeveloper // XXX release? 70592e575c1Sbeveloper ReleaseNode(clone); 706287f7492Sbeveloper 707835140c8Sbeveloper return source; 70852a38012Sejakowatz } 70952a38012Sejakowatz 71052a38012Sejakowatz 71152a38012Sejakowatz status_t 71252a38012Sejakowatz BMediaRoster::Connect(const media_source & from, 71352a38012Sejakowatz const media_destination & to, 71452a38012Sejakowatz media_format * io_format, 71552a38012Sejakowatz media_output * out_output, 71652a38012Sejakowatz media_input * out_input) 71752a38012Sejakowatz { 718eae26d3dSbeveloper return BMediaRoster::Connect(from, to, io_format, out_output, out_input, 0); 719eae26d3dSbeveloper } 720eae26d3dSbeveloper 721eae26d3dSbeveloper 722eae26d3dSbeveloper status_t 723eae26d3dSbeveloper BMediaRoster::Connect(const media_source & from, 724eae26d3dSbeveloper const media_destination & to, 725eae26d3dSbeveloper media_format * io_format, 726eae26d3dSbeveloper media_output * out_output, 727eae26d3dSbeveloper media_input * out_input, 728eae26d3dSbeveloper uint32 in_flags, 729eae26d3dSbeveloper void * _reserved) 730eae26d3dSbeveloper { 73152a38012Sejakowatz CALLED(); 73252a38012Sejakowatz if (io_format == NULL || out_output == NULL || out_input == NULL) 73352a38012Sejakowatz return B_BAD_VALUE; 73440f36b03Sbeveloper if (IS_INVALID_SOURCE(from)) { 7355ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_source invalid\n"); 73652a38012Sejakowatz return B_MEDIA_BAD_SOURCE; 7379e9417d2Sbeveloper } 73840f36b03Sbeveloper if (IS_INVALID_DESTINATION(to)) { 7395ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_destination invalid\n"); 74052a38012Sejakowatz return B_MEDIA_BAD_DESTINATION; 7419e9417d2Sbeveloper } 74252a38012Sejakowatz 74352a38012Sejakowatz status_t rv; 7448c6a6096Sbeveloper producer_format_proposal_request request1; 7458c6a6096Sbeveloper producer_format_proposal_reply reply1; 74652a38012Sejakowatz 74769983609Sbeveloper PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::FormatProposal with format ", *io_format); 74869983609Sbeveloper 74952a38012Sejakowatz // BBufferProducer::FormatProposal 7508c6a6096Sbeveloper request1.output = from; 7518c6a6096Sbeveloper request1.format = *io_format; 7528c6a6096Sbeveloper rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, sizeof(request1), &reply1, sizeof(reply1)); 7538c6a6096Sbeveloper if (rv != B_OK) { 7545ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted after BBufferProducer::FormatProposal, status = %#lx\n",rv); 75552a38012Sejakowatz return rv; 75652a38012Sejakowatz } 7578c6a6096Sbeveloper // reply1.format now contains the format proposed by the producer 7588c6a6096Sbeveloper 7598c6a6096Sbeveloper consumer_accept_format_request request2; 7608c6a6096Sbeveloper consumer_accept_format_reply reply2; 7618c6a6096Sbeveloper 76269983609Sbeveloper PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::AcceptFormat with format ", reply1.format); 76369983609Sbeveloper 7648c6a6096Sbeveloper // BBufferConsumer::AcceptFormat 7658c6a6096Sbeveloper request2.dest = to; 7668c6a6096Sbeveloper request2.format = reply1.format; 7678c6a6096Sbeveloper rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, sizeof(request2), &reply2, sizeof(reply2)); 7688c6a6096Sbeveloper if (rv != B_OK) { 7695ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted after BBufferConsumer::AcceptFormat, status = %#lx\n",rv); 7708c6a6096Sbeveloper return rv; 7718c6a6096Sbeveloper } 7728c6a6096Sbeveloper // reply2.format now contains the format accepted by the consumer 7738c6a6096Sbeveloper 7748c6a6096Sbeveloper // BBufferProducer::PrepareToConnect 7758c6a6096Sbeveloper producer_prepare_to_connect_request request3; 7768c6a6096Sbeveloper producer_prepare_to_connect_reply reply3; 7778c6a6096Sbeveloper 77869983609Sbeveloper PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::PrepareToConnect with format", reply2.format); 77969983609Sbeveloper 7808c6a6096Sbeveloper request3.source = from; 7818c6a6096Sbeveloper request3.destination = to; 7828c6a6096Sbeveloper request3.format = reply2.format; 7838c6a6096Sbeveloper strcpy(request3.name, "XXX some default name"); // XXX fix this 7848c6a6096Sbeveloper rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, sizeof(request3), &reply3, sizeof(reply3)); 7858c6a6096Sbeveloper if (rv != B_OK) { 7865ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted after BBufferProducer::PrepareToConnect, status = %#lx\n",rv); 7878c6a6096Sbeveloper return rv; 7888c6a6096Sbeveloper } 7898c6a6096Sbeveloper // reply3.format is still our pretty media format 7908c6a6096Sbeveloper // reply3.out_source the real source to be used for the connection 7918c6a6096Sbeveloper // reply3.name the name BBufferConsumer::Connected will see in the outInput->name argument 7928c6a6096Sbeveloper 79369983609Sbeveloper 79469983609Sbeveloper // find the output and input nodes 79569983609Sbeveloper // XXX isn't there a easier way? 79669983609Sbeveloper media_node sourcenode; 79769983609Sbeveloper media_node destnode; 79869983609Sbeveloper GetNodeFor(NodeIDFor(from.port), &sourcenode); 79969983609Sbeveloper GetNodeFor(NodeIDFor(to.port), &destnode); 80069983609Sbeveloper ReleaseNode(sourcenode); 80169983609Sbeveloper ReleaseNode(destnode); 80269983609Sbeveloper 8038c6a6096Sbeveloper // BBufferConsumer::Connected 8048c6a6096Sbeveloper consumer_connected_request request4; 8058c6a6096Sbeveloper consumer_connected_reply reply4; 8068c6a6096Sbeveloper status_t con_status; 8078c6a6096Sbeveloper 80869983609Sbeveloper PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::Connected with format ", reply3.format); 80969983609Sbeveloper 81069983609Sbeveloper request4.input.node = destnode; 81169983609Sbeveloper request4.input.source = reply3.out_source; 81269983609Sbeveloper request4.input.destination = to; 81369983609Sbeveloper request4.input.format = reply3.format; 81469983609Sbeveloper strcpy(request4.input.name, reply3.name); 81569983609Sbeveloper 8168c6a6096Sbeveloper con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, sizeof(request4), &reply4, sizeof(reply4)); 8178c6a6096Sbeveloper if (con_status != B_OK) { 8185ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborting after BBufferConsumer::Connected, status = %#lx\n",con_status); 8198c6a6096Sbeveloper // we do NOT return here! 8208c6a6096Sbeveloper } 8218c6a6096Sbeveloper // con_status contains the status code to be supplied to BBufferProducer::Connect's status argument 8228c6a6096Sbeveloper // reply4.input contains the media_input that describes the connection from the consumer point of view 8238c6a6096Sbeveloper 8248c6a6096Sbeveloper // BBufferProducer::Connect 8258c6a6096Sbeveloper producer_connect_request request5; 8268c6a6096Sbeveloper producer_connect_reply reply5; 8278c6a6096Sbeveloper 82869983609Sbeveloper PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::Connect with format ", reply4.input.format); 82969983609Sbeveloper 8308c6a6096Sbeveloper request5.error = con_status; 8318c6a6096Sbeveloper request5.source = reply3.out_source; 8328c6a6096Sbeveloper request5.destination = reply4.input.destination; 83369983609Sbeveloper request5.format = reply4.input.format; 8348c6a6096Sbeveloper strcpy(request5.name, reply4.input.name); 8350caff283Sbeveloper rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, sizeof(request5), &reply5, sizeof(reply5)); 8368c6a6096Sbeveloper if (con_status != B_OK) { 8375ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted\n"); 8388c6a6096Sbeveloper return con_status; 8398c6a6096Sbeveloper } 8408c6a6096Sbeveloper if (rv != B_OK) { 8415ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted after BBufferProducer::Connect, status = %#lx\n",rv); 8428c6a6096Sbeveloper return rv; 8438c6a6096Sbeveloper } 8448c6a6096Sbeveloper // reply5.name contains the name assigned to the connection by the producer 8458c6a6096Sbeveloper 8468c6a6096Sbeveloper // initilize connection info 84769983609Sbeveloper *io_format = reply4.input.format; 8488c6a6096Sbeveloper *out_input = reply4.input; 8498c6a6096Sbeveloper out_output->node = sourcenode; 8508c6a6096Sbeveloper out_output->source = reply4.input.source; 8518c6a6096Sbeveloper out_output->destination = reply4.input.destination; 8528c6a6096Sbeveloper out_output->format = reply4.input.format; 8538c6a6096Sbeveloper strcpy(out_output->name, reply5.name); 8548c6a6096Sbeveloper 8558c6a6096Sbeveloper // the connection is now made 85669983609Sbeveloper printf("BMediaRoster::Connect connection established!\n"); 85769983609Sbeveloper PRINT_FORMAT(" format", *io_format); 85869983609Sbeveloper PRINT_INPUT(" input", *out_input); 85969983609Sbeveloper PRINT_OUTPUT(" output", *out_output); 8608c6a6096Sbeveloper 8618c6a6096Sbeveloper // XXX register connection with server 8629e9417d2Sbeveloper // XXX we should just send a notification, instead of republishing all endpoints 86376669a29Sbeveloper List<media_output> outlist; 86476669a29Sbeveloper List<media_input> inlist; 8658b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist)) 8668b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist); 8678b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist)) 8688b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(out_input->node, &inlist); 8698c6a6096Sbeveloper 8708c6a6096Sbeveloper 8718c6a6096Sbeveloper // XXX if (mute) BBufferProducer::EnableOutput(false) 8729e9417d2Sbeveloper if (in_flags & B_CONNECT_MUTED) { 8739e9417d2Sbeveloper } 8748c6a6096Sbeveloper 8758c6a6096Sbeveloper 8769e9417d2Sbeveloper // send a notification 8779e9417d2Sbeveloper BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, *io_format); 8789e9417d2Sbeveloper 8798c6a6096Sbeveloper return B_OK; 8808c6a6096Sbeveloper }; 88152a38012Sejakowatz 88252a38012Sejakowatz 88352a38012Sejakowatz status_t 8849e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid, 88552a38012Sejakowatz const media_source & source, 8869e9417d2Sbeveloper media_node_id destination_nodeid, 88752a38012Sejakowatz const media_destination & destination) 88852a38012Sejakowatz { 8899e9417d2Sbeveloper CALLED(); 89040f36b03Sbeveloper if (IS_INVALID_NODEID(source_nodeid)) { 8915ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: source media_node_id invalid\n"); 8929e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 8939e9417d2Sbeveloper } 89440f36b03Sbeveloper if (IS_INVALID_NODEID(destination_nodeid)) { 8955ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: destination media_node_id invalid\n"); 8969e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 8979e9417d2Sbeveloper } 89840f36b03Sbeveloper if (IS_INVALID_SOURCE(source)) { 8995ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_source invalid\n"); 9009e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 9019e9417d2Sbeveloper } 90240f36b03Sbeveloper if (IS_INVALID_DESTINATION(destination)) { 9035ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_destination invalid\n"); 9049e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 9059e9417d2Sbeveloper } 9069e9417d2Sbeveloper 9079e9417d2Sbeveloper producer_disconnect_request request2; 9089e9417d2Sbeveloper producer_disconnect_reply reply2; 9099e9417d2Sbeveloper consumer_disconnected_request request1; 9109e9417d2Sbeveloper consumer_disconnected_reply reply1; 9119e9417d2Sbeveloper status_t rv1, rv2; 9129e9417d2Sbeveloper 9139e9417d2Sbeveloper // XXX we should ask the server if this connection really exists 9149e9417d2Sbeveloper 9159e9417d2Sbeveloper request1.source = source; 9169e9417d2Sbeveloper request1.destination = destination; 9179e9417d2Sbeveloper request2.source = source; 9189e9417d2Sbeveloper request2.destination = destination; 9199e9417d2Sbeveloper 9209e9417d2Sbeveloper rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, sizeof(request1), &reply1, sizeof(reply1)); 9219e9417d2Sbeveloper rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, sizeof(request2), &reply2, sizeof(reply2)); 9229e9417d2Sbeveloper 9239e9417d2Sbeveloper // XXX unregister connection with server 9249e9417d2Sbeveloper // XXX we should just send a notification, instead of republishing all endpoints 92576669a29Sbeveloper List<media_output> outlist; 92676669a29Sbeveloper List<media_input> inlist; 9279e9417d2Sbeveloper media_node sourcenode; 9289e9417d2Sbeveloper media_node destnode; 9299e9417d2Sbeveloper if (B_OK == GetNodeFor(source_nodeid, &sourcenode)) { 9308b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist)) 9318b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist); 9329e9417d2Sbeveloper ReleaseNode(sourcenode); 9334f09fa2fSbeveloper } else { 9345ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: source GetNodeFor failed\n"); 9354f09fa2fSbeveloper } 9369e9417d2Sbeveloper if (B_OK == GetNodeFor(destination_nodeid, &destnode)) { 9378b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllInputs(destnode , &inlist)) 9388b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(destnode, &inlist); 9399e9417d2Sbeveloper ReleaseNode(destnode); 9404f09fa2fSbeveloper } else { 9415ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: dest GetNodeFor failed\n"); 9424f09fa2fSbeveloper } 9439e9417d2Sbeveloper 9449e9417d2Sbeveloper 9459e9417d2Sbeveloper // send a notification 9469e9417d2Sbeveloper BPrivate::media::notifications::ConnectionBroken(source, destination); 9479e9417d2Sbeveloper 9489e9417d2Sbeveloper return (rv1 != B_OK || rv2 != B_OK) ? B_ERROR : B_OK; 94952a38012Sejakowatz } 95052a38012Sejakowatz 95152a38012Sejakowatz 95252a38012Sejakowatz status_t 95352a38012Sejakowatz BMediaRoster::StartNode(const media_node & node, 95452a38012Sejakowatz bigtime_t at_performance_time) 95552a38012Sejakowatz { 95652a38012Sejakowatz CALLED(); 9579e9417d2Sbeveloper if (node.node <= 0) 95852a38012Sejakowatz return B_MEDIA_BAD_NODE; 95952a38012Sejakowatz 96060f15390Sbeveloper TRACE("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node, at_performance_time); 9610e21b167Sbeveloper 9626396865dSbeveloper node_start_command command; 9636396865dSbeveloper command.performance_time = at_performance_time; 96452a38012Sejakowatz 9656396865dSbeveloper return SendToPort(node.port, NODE_START, &command, sizeof(command)); 96652a38012Sejakowatz } 96752a38012Sejakowatz 96852a38012Sejakowatz 96952a38012Sejakowatz status_t 97052a38012Sejakowatz BMediaRoster::StopNode(const media_node & node, 97152a38012Sejakowatz bigtime_t at_performance_time, 97252a38012Sejakowatz bool immediate) 97352a38012Sejakowatz { 97452a38012Sejakowatz CALLED(); 97540f36b03Sbeveloper if (IS_INVALID_NODE(node)) 97652a38012Sejakowatz return B_MEDIA_BAD_NODE; 97752a38012Sejakowatz 97860f15390Sbeveloper TRACE("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node, at_performance_time, immediate ? "NOW" : ""); 9790e21b167Sbeveloper 9806396865dSbeveloper node_stop_command command; 9816396865dSbeveloper command.performance_time = at_performance_time; 9826396865dSbeveloper command.immediate = immediate; 98352a38012Sejakowatz 9846396865dSbeveloper return SendToPort(node.port, NODE_STOP, &command, sizeof(command)); 98552a38012Sejakowatz } 98652a38012Sejakowatz 98752a38012Sejakowatz 98852a38012Sejakowatz status_t 98952a38012Sejakowatz BMediaRoster::SeekNode(const media_node & node, 99052a38012Sejakowatz bigtime_t to_media_time, 99152a38012Sejakowatz bigtime_t at_performance_time) 99252a38012Sejakowatz { 99352a38012Sejakowatz CALLED(); 99440f36b03Sbeveloper if (IS_INVALID_NODE(node)) 99552a38012Sejakowatz return B_MEDIA_BAD_NODE; 99652a38012Sejakowatz 99760f15390Sbeveloper TRACE("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n", node.node, at_performance_time, to_media_time); 9980e21b167Sbeveloper 9996396865dSbeveloper node_seek_command command; 10006396865dSbeveloper command.media_time = to_media_time; 10016396865dSbeveloper command.performance_time = at_performance_time; 100252a38012Sejakowatz 10036396865dSbeveloper return SendToPort(node.port, NODE_SEEK, &command, sizeof(command)); 100452a38012Sejakowatz } 100552a38012Sejakowatz 100652a38012Sejakowatz 100752a38012Sejakowatz status_t 100852a38012Sejakowatz BMediaRoster::StartTimeSource(const media_node & node, 100952a38012Sejakowatz bigtime_t at_real_time) 101052a38012Sejakowatz { 101152a38012Sejakowatz CALLED(); 101260f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 101360f15390Sbeveloper // XXX debug this 10145ac4fbd7Sbeveloper //ERROR("BMediaRoster::StartTimeSource node %ld is system timesource\n", node.node); 101560f15390Sbeveloper return B_OK; 101660f15390Sbeveloper } 101792e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 101892e575c1Sbeveloper // // XXX debug this 101992e575c1Sbeveloper // ERROR("BMediaRoster::StartTimeSource node %ld is shadow timesource\n", node.node); 102092e575c1Sbeveloper // return B_OK; 102192e575c1Sbeveloper // } 102240f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 10235ac4fbd7Sbeveloper ERROR("BMediaRoster::StartTimeSource node %ld invalid\n", node.node); 102452a38012Sejakowatz return B_MEDIA_BAD_NODE; 10250e21b167Sbeveloper } 10260e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 10275ac4fbd7Sbeveloper ERROR("BMediaRoster::StartTimeSource node %ld is no timesource\n", node.node); 102852a38012Sejakowatz return B_MEDIA_BAD_NODE; 10290e21b167Sbeveloper } 10300e21b167Sbeveloper 103160f15390Sbeveloper TRACE("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node, at_real_time); 103252a38012Sejakowatz 103352a38012Sejakowatz BTimeSource::time_source_op_info msg; 103452a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_START; 103552a38012Sejakowatz msg.real_time = at_real_time; 103652a38012Sejakowatz 103752a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 103852a38012Sejakowatz } 103952a38012Sejakowatz 104052a38012Sejakowatz 104152a38012Sejakowatz status_t 104252a38012Sejakowatz BMediaRoster::StopTimeSource(const media_node & node, 104352a38012Sejakowatz bigtime_t at_real_time, 104452a38012Sejakowatz bool immediate) 104552a38012Sejakowatz { 104652a38012Sejakowatz CALLED(); 104760f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 104860f15390Sbeveloper // XXX debug this 10495ac4fbd7Sbeveloper //ERROR("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node); 105060f15390Sbeveloper return B_OK; 105160f15390Sbeveloper } 105292e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 105392e575c1Sbeveloper // // XXX debug this 105492e575c1Sbeveloper // ERROR("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node); 105592e575c1Sbeveloper // return B_OK; 105692e575c1Sbeveloper // } 105740f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 10585ac4fbd7Sbeveloper ERROR("BMediaRoster::StopTimeSource node %ld invalid\n", node.node); 105952a38012Sejakowatz return B_MEDIA_BAD_NODE; 10600e21b167Sbeveloper } 10610e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 10625ac4fbd7Sbeveloper ERROR("BMediaRoster::StopTimeSource node %ld is no timesource\n", node.node); 106352a38012Sejakowatz return B_MEDIA_BAD_NODE; 10640e21b167Sbeveloper } 10650e21b167Sbeveloper 106660f15390Sbeveloper TRACE("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n", node.node, at_real_time, immediate ? "NOW" : ""); 106752a38012Sejakowatz 106852a38012Sejakowatz BTimeSource::time_source_op_info msg; 106952a38012Sejakowatz msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY : BTimeSource::B_TIMESOURCE_STOP; 107052a38012Sejakowatz msg.real_time = at_real_time; 107152a38012Sejakowatz 107252a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 107352a38012Sejakowatz } 107452a38012Sejakowatz 107552a38012Sejakowatz 107652a38012Sejakowatz status_t 107752a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node & node, 107852a38012Sejakowatz bigtime_t to_performance_time, 107952a38012Sejakowatz bigtime_t at_real_time) 108052a38012Sejakowatz { 108152a38012Sejakowatz CALLED(); 108260f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 108360f15390Sbeveloper // XXX debug this 10845ac4fbd7Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node); 108560f15390Sbeveloper // you can't seek the system time source, but 108660f15390Sbeveloper // returning B_ERROR would break StampTV 108760f15390Sbeveloper return B_OK; 108860f15390Sbeveloper } 108992e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 109092e575c1Sbeveloper // // XXX debug this 109192e575c1Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node); 109292e575c1Sbeveloper // return B_OK; 109392e575c1Sbeveloper // } 109440f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 10955ac4fbd7Sbeveloper ERROR("BMediaRoster::SeekTimeSource node %ld invalid\n", node.node); 109652a38012Sejakowatz return B_MEDIA_BAD_NODE; 10970e21b167Sbeveloper } 10980e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 10995ac4fbd7Sbeveloper ERROR("BMediaRoster::SeekTimeSource node %ld is no timesource\n", node.node); 110052a38012Sejakowatz return B_MEDIA_BAD_NODE; 11010e21b167Sbeveloper } 11020e21b167Sbeveloper 110360f15390Sbeveloper TRACE("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n", node.node, at_real_time, to_performance_time); 110452a38012Sejakowatz 110552a38012Sejakowatz BTimeSource::time_source_op_info msg; 110652a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_SEEK; 110752a38012Sejakowatz msg.real_time = at_real_time; 110852a38012Sejakowatz msg.performance_time = to_performance_time; 110952a38012Sejakowatz 111052a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 111152a38012Sejakowatz } 111252a38012Sejakowatz 111352a38012Sejakowatz 111452a38012Sejakowatz status_t 111552a38012Sejakowatz BMediaRoster::SyncToNode(const media_node & node, 111652a38012Sejakowatz bigtime_t at_time, 111752a38012Sejakowatz bigtime_t timeout) 111852a38012Sejakowatz { 111952a38012Sejakowatz UNIMPLEMENTED(); 112060f15390Sbeveloper return B_OK; 112152a38012Sejakowatz } 112252a38012Sejakowatz 112352a38012Sejakowatz 112452a38012Sejakowatz status_t 112552a38012Sejakowatz BMediaRoster::SetRunModeNode(const media_node & node, 112652a38012Sejakowatz BMediaNode::run_mode mode) 112752a38012Sejakowatz { 112852a38012Sejakowatz CALLED(); 112940f36b03Sbeveloper if (IS_INVALID_NODE(node)) 113052a38012Sejakowatz return B_MEDIA_BAD_NODE; 113152a38012Sejakowatz 1132dfb2ad61Sbeveloper node_set_run_mode_command msg; 113352a38012Sejakowatz msg.mode = mode; 113452a38012Sejakowatz 113552a38012Sejakowatz return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg)); 113652a38012Sejakowatz } 113752a38012Sejakowatz 113852a38012Sejakowatz 113952a38012Sejakowatz status_t 114052a38012Sejakowatz BMediaRoster::PrerollNode(const media_node & node) 114152a38012Sejakowatz { 114252a38012Sejakowatz CALLED(); 114340f36b03Sbeveloper if (IS_INVALID_NODE(node)) 114452a38012Sejakowatz return B_MEDIA_BAD_NODE; 114552a38012Sejakowatz 114652a38012Sejakowatz char dummy; 114752a38012Sejakowatz return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy)); 114852a38012Sejakowatz } 114952a38012Sejakowatz 115052a38012Sejakowatz 115152a38012Sejakowatz status_t 115252a38012Sejakowatz BMediaRoster::RollNode(const media_node & node, 115352a38012Sejakowatz bigtime_t startPerformance, 115452a38012Sejakowatz bigtime_t stopPerformance, 115552a38012Sejakowatz bigtime_t atMediaTime) 115652a38012Sejakowatz { 115752a38012Sejakowatz UNIMPLEMENTED(); 115852a38012Sejakowatz return B_ERROR; 115952a38012Sejakowatz } 116052a38012Sejakowatz 116152a38012Sejakowatz 116252a38012Sejakowatz status_t 116352a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node & node, 116452a38012Sejakowatz bigtime_t delay, 116552a38012Sejakowatz BMediaNode::run_mode mode) 116652a38012Sejakowatz { 116760f15390Sbeveloper CALLED(); 116860f15390Sbeveloper if (IS_INVALID_NODE(node)) 116960f15390Sbeveloper return B_MEDIA_BAD_NODE; 117060f15390Sbeveloper if ((node.kind & B_BUFFER_PRODUCER) == 0) 117160f15390Sbeveloper return B_MEDIA_BAD_NODE; 117260f15390Sbeveloper 117360f15390Sbeveloper producer_set_run_mode_delay_command command; 117460f15390Sbeveloper command.mode = mode; 117560f15390Sbeveloper command.delay = delay; 117660f15390Sbeveloper 117760f15390Sbeveloper return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command, sizeof(command)); 117852a38012Sejakowatz } 117952a38012Sejakowatz 118052a38012Sejakowatz 118152a38012Sejakowatz status_t 118252a38012Sejakowatz BMediaRoster::SetProducerRate(const media_node & producer, 118352a38012Sejakowatz int32 numer, 118452a38012Sejakowatz int32 denom) 118552a38012Sejakowatz { 118652a38012Sejakowatz CALLED(); 118740f36b03Sbeveloper if (IS_INVALID_NODE(producer)) 118852a38012Sejakowatz return B_MEDIA_BAD_NODE; 118952a38012Sejakowatz if ((producer.kind & B_BUFFER_PRODUCER) == 0) 119052a38012Sejakowatz return B_MEDIA_BAD_NODE; 119152a38012Sejakowatz 1192dfb2ad61Sbeveloper producer_set_play_rate_request msg; 1193dfb2ad61Sbeveloper producer_set_play_rate_reply reply; 119452a38012Sejakowatz status_t rv; 119552a38012Sejakowatz int32 code; 119652a38012Sejakowatz 119752a38012Sejakowatz msg.numer = numer; 119852a38012Sejakowatz msg.denom = denom; 119952a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 120052a38012Sejakowatz rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg)); 120152a38012Sejakowatz if (rv != B_OK) { 120252a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 120352a38012Sejakowatz return rv; 120452a38012Sejakowatz } 120552a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 120652a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 120752a38012Sejakowatz return (rv < B_OK) ? rv : reply.result; 120852a38012Sejakowatz } 120952a38012Sejakowatz 121052a38012Sejakowatz 121152a38012Sejakowatz /* Nodes will have available inputs/outputs as long as they are capable */ 121252a38012Sejakowatz /* of accepting more connections. The node may create an additional */ 121352a38012Sejakowatz /* output or input as the currently available is taken into usage. */ 121452a38012Sejakowatz status_t 121552a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node & node, 121652a38012Sejakowatz live_node_info * out_live_info) 121752a38012Sejakowatz { 12189e9417d2Sbeveloper CALLED(); 12199e9417d2Sbeveloper if (out_live_info == NULL) 12209e9417d2Sbeveloper return B_BAD_VALUE; 122140f36b03Sbeveloper if (IS_INVALID_NODE(node)) 12229e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 12239e9417d2Sbeveloper 12249e9417d2Sbeveloper server_get_live_node_info_request request; 12259e9417d2Sbeveloper server_get_live_node_info_reply reply; 12269e9417d2Sbeveloper status_t rv; 12279e9417d2Sbeveloper 12289e9417d2Sbeveloper request.node = node; 12299e9417d2Sbeveloper 12301299bfb2Sbeveloper rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), &reply, sizeof(reply)); 12319e9417d2Sbeveloper if (rv != B_OK) 12329e9417d2Sbeveloper return rv; 12339e9417d2Sbeveloper 12349e9417d2Sbeveloper *out_live_info = reply.live_info; 12359e9417d2Sbeveloper return B_OK; 123652a38012Sejakowatz } 123752a38012Sejakowatz 123852a38012Sejakowatz 123952a38012Sejakowatz status_t 124052a38012Sejakowatz BMediaRoster::GetLiveNodes(live_node_info * out_live_nodes, 124152a38012Sejakowatz int32 * io_total_count, 124252a38012Sejakowatz const media_format * has_input, 124352a38012Sejakowatz const media_format * has_output, 124452a38012Sejakowatz const char * name, 124552a38012Sejakowatz uint64 node_kinds) 124652a38012Sejakowatz { 12479e9417d2Sbeveloper CALLED(); 12489e9417d2Sbeveloper if (out_live_nodes == NULL || io_total_count == NULL) 12499e9417d2Sbeveloper return B_BAD_VALUE; 12509e9417d2Sbeveloper if (*io_total_count <= 0) 12519e9417d2Sbeveloper return B_BAD_VALUE; 12529e9417d2Sbeveloper 12539e9417d2Sbeveloper // XXX we also support the wildcard search as GetDormantNodes does. This needs to be documented 12549e9417d2Sbeveloper 12559e9417d2Sbeveloper server_get_live_nodes_request request; 12569e9417d2Sbeveloper server_get_live_nodes_reply reply; 12579e9417d2Sbeveloper status_t rv; 12589e9417d2Sbeveloper 12599e9417d2Sbeveloper request.maxcount = *io_total_count; 12609e9417d2Sbeveloper request.has_input = (bool) has_input; 12619e9417d2Sbeveloper if (has_input) 12629e9417d2Sbeveloper request.inputformat = *has_input; // XXX we should not make a flat copy of media_format 12639e9417d2Sbeveloper request.has_output = (bool) has_output; 12649e9417d2Sbeveloper if (has_output) 12659e9417d2Sbeveloper request.outputformat = *has_output; // XXX we should not make a flat copy of media_format 12669e9417d2Sbeveloper request.has_name = (bool) name; 12679e9417d2Sbeveloper if (name) { 12689e9417d2Sbeveloper int len = strlen(name); 12699e9417d2Sbeveloper len = min_c(len, (int)sizeof(request.name) - 1); 12709e9417d2Sbeveloper memcpy(request.name, name, len); 12719e9417d2Sbeveloper request.name[len] = 0; 12729e9417d2Sbeveloper } 12739e9417d2Sbeveloper request.require_kinds = node_kinds; 12749e9417d2Sbeveloper 12759e9417d2Sbeveloper rv = QueryServer(SERVER_GET_LIVE_NODES, &request, sizeof(request), &reply, sizeof(reply)); 12769e9417d2Sbeveloper if (rv != B_OK) { 12775ac4fbd7Sbeveloper ERROR("BMediaRoster::GetLiveNodes failed querying server\n"); 12781299bfb2Sbeveloper *io_total_count = 0; 12799e9417d2Sbeveloper return rv; 12809e9417d2Sbeveloper } 12819e9417d2Sbeveloper 12829e9417d2Sbeveloper if (reply.count > MAX_LIVE_INFO) { 12839e9417d2Sbeveloper live_node_info *live_info; 12849e9417d2Sbeveloper area_id clone; 12859e9417d2Sbeveloper 12869e9417d2Sbeveloper clone = clone_area("live_node_info clone", reinterpret_cast<void **>(&live_info), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, reply.area); 12879e9417d2Sbeveloper if (clone < B_OK) { 12885ac4fbd7Sbeveloper ERROR("BMediaRoster::GetLiveNodes failed to clone area, %#lx\n", clone); 12899e9417d2Sbeveloper delete_area(reply.area); 12901299bfb2Sbeveloper *io_total_count = 0; 129152a38012Sejakowatz return B_ERROR; 129252a38012Sejakowatz } 129352a38012Sejakowatz 12949e9417d2Sbeveloper for (int32 i = 0; i < reply.count; i++) { 12959e9417d2Sbeveloper out_live_nodes[i] = live_info[i]; 12969e9417d2Sbeveloper } 12979e9417d2Sbeveloper 12989e9417d2Sbeveloper delete_area(clone); 12999e9417d2Sbeveloper delete_area(reply.area); 13009e9417d2Sbeveloper } else { 13019e9417d2Sbeveloper for (int32 i = 0; i < reply.count; i++) { 13029e9417d2Sbeveloper out_live_nodes[i] = reply.live_info[i]; 13039e9417d2Sbeveloper } 13049e9417d2Sbeveloper } 13059e9417d2Sbeveloper *io_total_count = reply.count; 13069e9417d2Sbeveloper 13079e9417d2Sbeveloper return B_OK; 13089e9417d2Sbeveloper } 13099e9417d2Sbeveloper 131052a38012Sejakowatz 131152a38012Sejakowatz status_t 131252a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node & node, 131352a38012Sejakowatz media_input * out_free_inputs, 131452a38012Sejakowatz int32 buf_num_inputs, 131552a38012Sejakowatz int32 * out_total_count, 131652a38012Sejakowatz media_type filter_type) 131752a38012Sejakowatz { 13183620737cSbeveloper CALLED(); 13195ac4fbd7Sbeveloper if (IS_INVALID_NODE(node)) { 13205ac4fbd7Sbeveloper ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld invalid\n", node.node, node.port); 13213620737cSbeveloper return B_MEDIA_BAD_NODE; 13225ac4fbd7Sbeveloper } 13235ac4fbd7Sbeveloper if ((node.kind & B_BUFFER_CONSUMER) == 0) { 13245ac4fbd7Sbeveloper ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld is not a consumer\n", node.node, node.port); 13255ac4fbd7Sbeveloper return B_MEDIA_BAD_NODE; 13265ac4fbd7Sbeveloper } 13273620737cSbeveloper if (out_free_inputs == NULL || out_total_count == NULL) 13283620737cSbeveloper return B_BAD_VALUE; 13293620737cSbeveloper 133076669a29Sbeveloper List<media_input> list; 13313620737cSbeveloper media_input *input; 13323620737cSbeveloper status_t rv; 13333620737cSbeveloper 13341299bfb2Sbeveloper *out_total_count = 0; 13351299bfb2Sbeveloper 13368b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 13373620737cSbeveloper if (B_OK != rv) 13383620737cSbeveloper return rv; 13393620737cSbeveloper 13405ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetFreeInputsFor node %ld, max %ld, filter-type %ld\n", node.node, buf_num_inputs, filter_type); 13415ac4fbd7Sbeveloper 134276669a29Sbeveloper int32 i; 1343b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 13443620737cSbeveloper if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != input->format.type) 13453620737cSbeveloper continue; // media_type used, but doesn't match 13463620737cSbeveloper if (input->source != media_source::null) 13473620737cSbeveloper continue; // consumer source already connected 13483620737cSbeveloper out_free_inputs[i] = *input; 13493620737cSbeveloper *out_total_count += 1; 13503620737cSbeveloper buf_num_inputs -= 1; 13515ac4fbd7Sbeveloper #if DEBUG >= 3 13525ac4fbd7Sbeveloper PRINT_OUTPUT(" input", out_free_inputs[i]); 13535ac4fbd7Sbeveloper #endif 13543620737cSbeveloper if (buf_num_inputs == 0) 13553620737cSbeveloper break; 1356b65a0ac5SJérôme Duval i++; 13573620737cSbeveloper } 13583620737cSbeveloper 13598b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 13603620737cSbeveloper return B_OK; 136152a38012Sejakowatz } 136252a38012Sejakowatz 136352a38012Sejakowatz 136452a38012Sejakowatz status_t 136552a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node & node, 136652a38012Sejakowatz media_input * out_active_inputs, 136752a38012Sejakowatz int32 buf_num_inputs, 136852a38012Sejakowatz int32 * out_total_count) 136952a38012Sejakowatz { 13703620737cSbeveloper CALLED(); 137140f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 13723620737cSbeveloper return B_MEDIA_BAD_NODE; 13733620737cSbeveloper if (out_active_inputs == NULL || out_total_count == NULL) 13743620737cSbeveloper return B_BAD_VALUE; 13753620737cSbeveloper 137676669a29Sbeveloper List<media_input> list; 13773620737cSbeveloper media_input *input; 13783620737cSbeveloper status_t rv; 13793620737cSbeveloper 13801299bfb2Sbeveloper *out_total_count = 0; 13811299bfb2Sbeveloper 13828b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 13833620737cSbeveloper if (B_OK != rv) 13843620737cSbeveloper return rv; 13853620737cSbeveloper 13865ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetConnectedInputsFor node %ld, max %ld\n", node.node, buf_num_inputs); 13875ac4fbd7Sbeveloper 138876669a29Sbeveloper int32 i; 1389b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 13903620737cSbeveloper if (input->source == media_source::null) 13913620737cSbeveloper continue; // consumer source not connected 13923620737cSbeveloper out_active_inputs[i] = *input; 13933620737cSbeveloper *out_total_count += 1; 13943620737cSbeveloper buf_num_inputs -= 1; 13955ac4fbd7Sbeveloper #if DEBUG >= 3 13965ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_active_inputs[i]); 13975ac4fbd7Sbeveloper #endif 13983620737cSbeveloper if (buf_num_inputs == 0) 13993620737cSbeveloper break; 1400b65a0ac5SJérôme Duval i++; 14013620737cSbeveloper } 14023620737cSbeveloper 14038b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 14043620737cSbeveloper return B_OK; 140552a38012Sejakowatz } 140652a38012Sejakowatz 140752a38012Sejakowatz 140852a38012Sejakowatz status_t 140952a38012Sejakowatz BMediaRoster::GetAllInputsFor(const media_node & node, 141052a38012Sejakowatz media_input * out_inputs, 141152a38012Sejakowatz int32 buf_num_inputs, 141252a38012Sejakowatz int32 * out_total_count) 141352a38012Sejakowatz { 141452a38012Sejakowatz CALLED(); 141540f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 141652a38012Sejakowatz return B_MEDIA_BAD_NODE; 141752a38012Sejakowatz if (out_inputs == NULL || out_total_count == NULL) 141852a38012Sejakowatz return B_BAD_VALUE; 141952a38012Sejakowatz 142076669a29Sbeveloper List<media_input> list; 14213620737cSbeveloper media_input *input; 142252a38012Sejakowatz status_t rv; 142352a38012Sejakowatz 14241299bfb2Sbeveloper *out_total_count = 0; 14251299bfb2Sbeveloper 14268b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 14273620737cSbeveloper if (B_OK != rv) 14283620737cSbeveloper return rv; 14293620737cSbeveloper 14305ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetAllInputsFor node %ld, max %ld\n", node.node, buf_num_inputs); 14315ac4fbd7Sbeveloper 143276669a29Sbeveloper int32 i; 143376669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&input); i++) { 14343620737cSbeveloper out_inputs[i] = *input; 143552a38012Sejakowatz *out_total_count += 1; 14363620737cSbeveloper buf_num_inputs -= 1; 14375ac4fbd7Sbeveloper #if DEBUG >= 3 14385ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_inputs[i]); 14395ac4fbd7Sbeveloper #endif 14403620737cSbeveloper if (buf_num_inputs == 0) 14413620737cSbeveloper break; 144252a38012Sejakowatz } 144352a38012Sejakowatz 14448b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 14453620737cSbeveloper return B_OK; 144652a38012Sejakowatz } 144752a38012Sejakowatz 144852a38012Sejakowatz 144952a38012Sejakowatz status_t 145052a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node & node, 145152a38012Sejakowatz media_output * out_free_outputs, 145252a38012Sejakowatz int32 buf_num_outputs, 145352a38012Sejakowatz int32 * out_total_count, 145452a38012Sejakowatz media_type filter_type) 145552a38012Sejakowatz { 14563620737cSbeveloper CALLED(); 145740f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 14583620737cSbeveloper return B_MEDIA_BAD_NODE; 14593620737cSbeveloper if (out_free_outputs == NULL || out_total_count == NULL) 14603620737cSbeveloper return B_BAD_VALUE; 14613620737cSbeveloper 146276669a29Sbeveloper List<media_output> list; 14633620737cSbeveloper media_output *output; 14643620737cSbeveloper status_t rv; 14653620737cSbeveloper 14661299bfb2Sbeveloper *out_total_count = 0; 14671299bfb2Sbeveloper 14688b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 14693620737cSbeveloper if (B_OK != rv) 14703620737cSbeveloper return rv; 14713620737cSbeveloper 14725ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetFreeOutputsFor node %ld, max %ld, filter-type %ld\n", node.node, buf_num_outputs, filter_type); 14735ac4fbd7Sbeveloper 147476669a29Sbeveloper int32 i; 1475b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 14763620737cSbeveloper if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != output->format.type) 14773620737cSbeveloper continue; // media_type used, but doesn't match 14783620737cSbeveloper if (output->destination != media_destination::null) 14793620737cSbeveloper continue; // producer destination already connected 14803620737cSbeveloper out_free_outputs[i] = *output; 14813620737cSbeveloper *out_total_count += 1; 14823620737cSbeveloper buf_num_outputs -= 1; 14835ac4fbd7Sbeveloper #if DEBUG >= 3 14845ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_free_outputs[i]); 14855ac4fbd7Sbeveloper #endif 14863620737cSbeveloper if (buf_num_outputs == 0) 14873620737cSbeveloper break; 1488b65a0ac5SJérôme Duval i++; 14893620737cSbeveloper } 14903620737cSbeveloper 14918b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 14923620737cSbeveloper return B_OK; 149352a38012Sejakowatz } 149452a38012Sejakowatz 149552a38012Sejakowatz 149652a38012Sejakowatz status_t 149752a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node & node, 149852a38012Sejakowatz media_output * out_active_outputs, 149952a38012Sejakowatz int32 buf_num_outputs, 150052a38012Sejakowatz int32 * out_total_count) 150152a38012Sejakowatz { 15023620737cSbeveloper CALLED(); 150340f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 15043620737cSbeveloper return B_MEDIA_BAD_NODE; 15053620737cSbeveloper if (out_active_outputs == NULL || out_total_count == NULL) 15063620737cSbeveloper return B_BAD_VALUE; 15073620737cSbeveloper 150876669a29Sbeveloper List<media_output> list; 15093620737cSbeveloper media_output *output; 15103620737cSbeveloper status_t rv; 15113620737cSbeveloper 15121299bfb2Sbeveloper *out_total_count = 0; 15131299bfb2Sbeveloper 15148b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 15153620737cSbeveloper if (B_OK != rv) 15163620737cSbeveloper return rv; 15173620737cSbeveloper 15185ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetConnectedOutputsFor node %ld, max %ld\n", node.node, buf_num_outputs); 15195ac4fbd7Sbeveloper 152076669a29Sbeveloper int32 i; 1521b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 15223620737cSbeveloper if (output->destination == media_destination::null) 15233620737cSbeveloper continue; // producer destination not connected 15243620737cSbeveloper out_active_outputs[i] = *output; 15253620737cSbeveloper *out_total_count += 1; 15263620737cSbeveloper buf_num_outputs -= 1; 15275ac4fbd7Sbeveloper #if DEBUG >= 3 15285ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_active_outputs[i]); 15295ac4fbd7Sbeveloper #endif 15303620737cSbeveloper if (buf_num_outputs == 0) 15313620737cSbeveloper break; 1532b65a0ac5SJérôme Duval i++; 15333620737cSbeveloper } 15343620737cSbeveloper 15358b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 15363620737cSbeveloper return B_OK; 153752a38012Sejakowatz } 153852a38012Sejakowatz 153952a38012Sejakowatz 154052a38012Sejakowatz status_t 154152a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node & node, 154252a38012Sejakowatz media_output * out_outputs, 154352a38012Sejakowatz int32 buf_num_outputs, 154452a38012Sejakowatz int32 * out_total_count) 154552a38012Sejakowatz { 154652a38012Sejakowatz CALLED(); 154740f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 154852a38012Sejakowatz return B_MEDIA_BAD_NODE; 154952a38012Sejakowatz if (out_outputs == NULL || out_total_count == NULL) 155052a38012Sejakowatz return B_BAD_VALUE; 155152a38012Sejakowatz 155276669a29Sbeveloper List<media_output> list; 15533620737cSbeveloper media_output *output; 155452a38012Sejakowatz status_t rv; 155552a38012Sejakowatz 15561299bfb2Sbeveloper *out_total_count = 0; 15571299bfb2Sbeveloper 15588b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 15593620737cSbeveloper if (B_OK != rv) 15603620737cSbeveloper return rv; 15613620737cSbeveloper 15625ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetAllOutputsFor node %ld, max %ld\n", node.node, buf_num_outputs); 15635ac4fbd7Sbeveloper 156476669a29Sbeveloper int32 i; 156576669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&output); i++) { 15663620737cSbeveloper out_outputs[i] = *output; 156752a38012Sejakowatz *out_total_count += 1; 15683620737cSbeveloper buf_num_outputs -= 1; 15695ac4fbd7Sbeveloper #if DEBUG >= 3 15705ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_outputs[i]); 15715ac4fbd7Sbeveloper #endif 15723620737cSbeveloper if (buf_num_outputs == 0) 15733620737cSbeveloper break; 157452a38012Sejakowatz } 157552a38012Sejakowatz 15768b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 15773620737cSbeveloper return B_OK; 157852a38012Sejakowatz } 157952a38012Sejakowatz 158052a38012Sejakowatz 158152a38012Sejakowatz status_t 158252a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where) 158352a38012Sejakowatz { 1584eae26d3dSbeveloper CALLED(); 1585eae26d3dSbeveloper if (!where.IsValid()) { 15865ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1587eae26d3dSbeveloper return B_BAD_VALUE; 1588eae26d3dSbeveloper } 1589f4925104Sbeveloper return BPrivate::media::notifications::Register(where, media_node::null, B_MEDIA_WILDCARD); 159052a38012Sejakowatz } 159152a38012Sejakowatz 159252a38012Sejakowatz 159352a38012Sejakowatz status_t 159452a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where, 159552a38012Sejakowatz int32 notificationType) 159652a38012Sejakowatz { 1597eae26d3dSbeveloper CALLED(); 1598eae26d3dSbeveloper if (!where.IsValid()) { 15995ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1600eae26d3dSbeveloper return B_BAD_VALUE; 1601eae26d3dSbeveloper } 1602f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) { 16035ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 1604eae26d3dSbeveloper return B_BAD_VALUE; 1605eae26d3dSbeveloper } 1606f4925104Sbeveloper return BPrivate::media::notifications::Register(where, media_node::null, notificationType); 160752a38012Sejakowatz } 160852a38012Sejakowatz 160952a38012Sejakowatz 161052a38012Sejakowatz status_t 161152a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where, 161252a38012Sejakowatz const media_node & node, 161352a38012Sejakowatz int32 notificationType) 161452a38012Sejakowatz { 1615eae26d3dSbeveloper CALLED(); 1616eae26d3dSbeveloper if (!where.IsValid()) { 16175ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1618eae26d3dSbeveloper return B_BAD_VALUE; 1619eae26d3dSbeveloper } 162040f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 16215ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: node invalid!\n"); 1622eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1623eae26d3dSbeveloper } 1624f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) { 16255ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 1626eae26d3dSbeveloper return B_BAD_VALUE; 1627eae26d3dSbeveloper } 1628f4925104Sbeveloper return BPrivate::media::notifications::Register(where, node, notificationType); 162952a38012Sejakowatz } 163052a38012Sejakowatz 163152a38012Sejakowatz 163252a38012Sejakowatz status_t 163352a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where) 163452a38012Sejakowatz { 1635eae26d3dSbeveloper CALLED(); 1636eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1637f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, media_node::null, B_MEDIA_WILDCARD); 163852a38012Sejakowatz } 163952a38012Sejakowatz 164052a38012Sejakowatz 164152a38012Sejakowatz status_t 164252a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where, 164352a38012Sejakowatz int32 notificationType) 164452a38012Sejakowatz { 1645eae26d3dSbeveloper CALLED(); 1646eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1647f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) { 16485ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 1649eae26d3dSbeveloper return B_BAD_VALUE; 1650eae26d3dSbeveloper } 1651f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, media_node::null, notificationType); 165252a38012Sejakowatz } 165352a38012Sejakowatz 165452a38012Sejakowatz 165552a38012Sejakowatz status_t 165652a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where, 165752a38012Sejakowatz const media_node & node, 165852a38012Sejakowatz int32 notificationType) 165952a38012Sejakowatz { 1660eae26d3dSbeveloper CALLED(); 1661eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 166240f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 16635ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: node invalid!\n"); 1664eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1665eae26d3dSbeveloper } 1666f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) { 16675ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 1668eae26d3dSbeveloper return B_BAD_VALUE; 1669eae26d3dSbeveloper } 1670f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, node, notificationType); 167152a38012Sejakowatz } 167252a38012Sejakowatz 167352a38012Sejakowatz 167452a38012Sejakowatz status_t 167552a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode * node) 167652a38012Sejakowatz { 167754187cc6Sbeveloper CALLED(); 167854187cc6Sbeveloper // addon-id = -1 (unused), addon-flavor-id = 0 (unused, too) 167954187cc6Sbeveloper return MediaRosterEx(this)->RegisterNode(node, -1, 0); 168054187cc6Sbeveloper } 168154187cc6Sbeveloper 168254187cc6Sbeveloper 168354187cc6Sbeveloper status_t 168454187cc6Sbeveloper BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 flavorid) 168554187cc6Sbeveloper { 168652a38012Sejakowatz CALLED(); 168752a38012Sejakowatz if (node == NULL) 168852a38012Sejakowatz return B_BAD_VALUE; 168952a38012Sejakowatz 169054187cc6Sbeveloper // some sanity check 169154187cc6Sbeveloper // I'm not sure if the media kit warrants to call BMediaNode::AddOn() here. 169254187cc6Sbeveloper // Perhaps we don't need it. 169354187cc6Sbeveloper { 16949e9417d2Sbeveloper BMediaAddOn *addon; 16959e9417d2Sbeveloper int32 addon_flavor_id; 16969e9417d2Sbeveloper media_addon_id addon_id; 16979e9417d2Sbeveloper addon_flavor_id = 0; 16989e9417d2Sbeveloper addon = node->AddOn(&addon_flavor_id); 16999e9417d2Sbeveloper addon_id = addon ? addon->AddonID() : -1; 170054187cc6Sbeveloper ASSERT(addonid == addon_id); 170154187cc6Sbeveloper ASSERT(flavorid == addon_flavor_id); 170254187cc6Sbeveloper } 170352a38012Sejakowatz 170454187cc6Sbeveloper status_t rv; 17059e9417d2Sbeveloper server_register_node_request request; 17069e9417d2Sbeveloper server_register_node_reply reply; 17079e9417d2Sbeveloper 170854187cc6Sbeveloper request.addon_id = addonid; 170954187cc6Sbeveloper request.addon_flavor_id = flavorid; 17109e9417d2Sbeveloper strcpy(request.name, node->Name()); 17119e9417d2Sbeveloper request.kinds = node->Kinds(); 17129e9417d2Sbeveloper request.port = node->ControlPort(); 17139e9417d2Sbeveloper request.team = team; 17149e9417d2Sbeveloper 17158b04ffc1Sbeveloper 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); 17161299bfb2Sbeveloper 17179e9417d2Sbeveloper rv = QueryServer(SERVER_REGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply)); 17189e9417d2Sbeveloper if (rv != B_OK) { 17195ac4fbd7Sbeveloper ERROR("BMediaRoster::RegisterNode: failed to register node %s (error %#lx)\n", node->Name(), rv); 17209e9417d2Sbeveloper return rv; 17219e9417d2Sbeveloper } 17229e9417d2Sbeveloper 17234295907bSbeveloper TRACE("BMediaRoster::RegisterNode: QueryServer SERVER_REGISTER_NODE finished\n"); 17244295907bSbeveloper 17258b04ffc1Sbeveloper // we are a friend class of BMediaNode and initialize this member variable 17269e9417d2Sbeveloper node->fNodeID = reply.nodeid; 17279e9417d2Sbeveloper ASSERT(reply.nodeid == node->Node().node); 17289e9417d2Sbeveloper ASSERT(reply.nodeid == node->ID()); 17299e9417d2Sbeveloper 17309e9417d2Sbeveloper // call the callback 17319e9417d2Sbeveloper node->NodeRegistered(); 17323620737cSbeveloper 17334295907bSbeveloper TRACE("BMediaRoster::RegisterNode: NodeRegistered callback finished\n"); 17344295907bSbeveloper 17350e21b167Sbeveloper // if the BMediaNode also inherits from BTimeSource, we need to call BTimeSource::FinishCreate() 17360e21b167Sbeveloper if (node->Kinds() & B_TIME_SOURCE) { 17370e21b167Sbeveloper BTimeSource *ts; 17380e21b167Sbeveloper ts = dynamic_cast<BTimeSource *>(node); 17390e21b167Sbeveloper if (ts) 17400e21b167Sbeveloper ts->FinishCreate(); 17410e21b167Sbeveloper } 17420e21b167Sbeveloper 17434295907bSbeveloper TRACE("BMediaRoster::RegisterNode: publishing inputs/outputs\n"); 17444295907bSbeveloper 17453620737cSbeveloper // register existing inputs and outputs with the 17463620737cSbeveloper // media_server, this allows GetLiveNodes() to work 17473620737cSbeveloper // with created, but unconnected nodes. 17484d2d96e0Sbeveloper // The node control loop might not be running, or might deadlock 17494d2d96e0Sbeveloper // if we send a message and wait for a reply here. 17504d2d96e0Sbeveloper // We have a pointer to the node, and thus call the functions directly 17514295907bSbeveloper 17523620737cSbeveloper if (node->Kinds() & B_BUFFER_PRODUCER) { 17534d2d96e0Sbeveloper BBufferProducer *bp; 17544d2d96e0Sbeveloper bp = dynamic_cast<BBufferProducer *>(node); 17554d2d96e0Sbeveloper if (bp) { 1756359ac306Sbeveloper List<media_output> list; 17574d2d96e0Sbeveloper if (B_OK == GetAllOutputs(bp, &list)) 1758359ac306Sbeveloper PublishOutputs(node->Node(), &list); 175921871f38Sbeveloper } 17604d2d96e0Sbeveloper } 176121871f38Sbeveloper if (node->Kinds() & B_BUFFER_CONSUMER) { 17624d2d96e0Sbeveloper BBufferConsumer *bc; 17634d2d96e0Sbeveloper bc = dynamic_cast<BBufferConsumer *>(node); 17644d2d96e0Sbeveloper if (bc) { 1765359ac306Sbeveloper List<media_input> list; 17664d2d96e0Sbeveloper if (B_OK == GetAllInputs(bc, &list)) 1767359ac306Sbeveloper PublishInputs(node->Node(), &list); 17683620737cSbeveloper } 17694d2d96e0Sbeveloper } 177021871f38Sbeveloper 17714295907bSbeveloper TRACE("BMediaRoster::RegisterNode: sending NodesCreated\n"); 17724295907bSbeveloper 17731299bfb2Sbeveloper BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1); 17744295907bSbeveloper 17754295907bSbeveloper TRACE("BMediaRoster::RegisterNode: finished\n"); 17764295907bSbeveloper 1777570f7d04Sbeveloper /* 1778570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id); 1779570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node this %p\n", node); 1780570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fConsumerThis %p\n", node->fConsumerThis); 1781570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fProducerThis %p\n", node->fProducerThis); 1782570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", node->fFileInterfaceThis); 1783570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fControllableThis %p\n", node->fControllableThis); 1784570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis %p\n", node->fTimeSourceThis); 1785570f7d04Sbeveloper */ 17869e9417d2Sbeveloper return B_OK; 178752a38012Sejakowatz } 178852a38012Sejakowatz 178952a38012Sejakowatz 179052a38012Sejakowatz status_t 179152a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode * node) 179252a38012Sejakowatz { 17939e9417d2Sbeveloper CALLED(); 17949e9417d2Sbeveloper if (node == NULL) 17959e9417d2Sbeveloper return B_BAD_VALUE; 17969e9417d2Sbeveloper 179760f15390Sbeveloper TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node); 179860f15390Sbeveloper 179986bce45bSbeveloper if (node->fKinds & NODE_KIND_NO_REFCOUNTING) { 180086bce45bSbeveloper printf("BMediaRoster::UnregisterNode, trying to unregister reference counting disabled timesource, node %ld, port %ld, team %ld\n", node->ID(), node->ControlPort(), team); 180186bce45bSbeveloper return B_OK; 180286bce45bSbeveloper } 18038b04ffc1Sbeveloper if (node->ID() == NODE_UNREGISTERED_ID) { 18045ac4fbd7Sbeveloper PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name '%s' already unregistered\n", node->ID(), node->Name()); 18059e9417d2Sbeveloper return B_OK; 18069e9417d2Sbeveloper } 180754187cc6Sbeveloper if (node->fRefCount != 0) { 18085ac4fbd7Sbeveloper PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name '%s' has local reference count of %ld\n", node->ID(), node->Name(), node->fRefCount); 180954187cc6Sbeveloper // no return here, we continue and unregister! 181054187cc6Sbeveloper } 181154187cc6Sbeveloper 181254187cc6Sbeveloper // Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node, BMessage *config) 181354187cc6Sbeveloper // if this node was instanciated by an add-on needs to be done *somewhere* 181454187cc6Sbeveloper // We can't do it here because it is already to late (destructor of the node 181554187cc6Sbeveloper // might have been called). 18169e9417d2Sbeveloper 18179e9417d2Sbeveloper server_unregister_node_request request; 18189e9417d2Sbeveloper server_unregister_node_reply reply; 18199e9417d2Sbeveloper status_t rv; 18209e9417d2Sbeveloper 18219e9417d2Sbeveloper request.nodeid = node->ID(); 18229e9417d2Sbeveloper request.team = team; 18239e9417d2Sbeveloper 18241299bfb2Sbeveloper // send a notification 18251299bfb2Sbeveloper BPrivate::media::notifications::NodesDeleted(&request.nodeid, 1); 18261299bfb2Sbeveloper 18279e9417d2Sbeveloper rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply)); 18289e9417d2Sbeveloper if (rv != B_OK) { 18295ac4fbd7Sbeveloper ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %ld, name '%s' (error %#lx)\n", node->ID(), node->Name(), rv); 18309e9417d2Sbeveloper return rv; 18319e9417d2Sbeveloper } 18329e9417d2Sbeveloper 183354187cc6Sbeveloper if (reply.addonid != -1) { 183454187cc6Sbeveloper // Small problem here, we can't use DormantNodeManager::PutAddon(), as 183554187cc6Sbeveloper // UnregisterNode() is called by a dormant node itself (by the destructor). 183654187cc6Sbeveloper // The add-on that contains the node needs to remain in memory until the 183754187cc6Sbeveloper // destructor execution is finished. 183854187cc6Sbeveloper // DormantNodeManager::PutAddonDelayed() will delay unloading. 183954187cc6Sbeveloper _DormantNodeManager->PutAddonDelayed(reply.addonid); 1840cf4e2277Sbeveloper 184173794717Sbeveloper rv = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount(reply.addonid, reply.flavorid); 184254187cc6Sbeveloper if (rv != B_OK) { 18435ac4fbd7Sbeveloper ERROR("BMediaRoster::UnregisterNode: DecrementAddonFlavorInstancesCount failed\n"); 184454187cc6Sbeveloper // this is really a problem, but we can't fail now 184554187cc6Sbeveloper } 18468b04ffc1Sbeveloper } 18479e9417d2Sbeveloper 18481299bfb2Sbeveloper // we are a friend class of BMediaNode and invalidate this member variable 18498b04ffc1Sbeveloper node->fNodeID = NODE_UNREGISTERED_ID; 18509e9417d2Sbeveloper 18519e9417d2Sbeveloper return B_OK; 185252a38012Sejakowatz } 185352a38012Sejakowatz 185452a38012Sejakowatz 185552a38012Sejakowatz // thread safe for multiple calls to Roster() 185652a38012Sejakowatz /* static */ BMediaRoster * 185752a38012Sejakowatz BMediaRoster::Roster(status_t *out_error) 185852a38012Sejakowatz { 185952a38012Sejakowatz static BLocker locker("BMediaRoster::Roster locker"); 186052a38012Sejakowatz locker.Lock(); 1861*8496c38aSbeveloper if (out_error) 1862*8496c38aSbeveloper *out_error = B_OK; 186352a38012Sejakowatz if (_sDefault == NULL) { 1864*8496c38aSbeveloper status_t err; 1865dcfb6bfcSJérôme Duval _sDefault = new BMediaRosterEx(&err); 1866dcfb6bfcSJérôme Duval if (err != B_OK) { 1867dcfb6bfcSJérôme Duval if (_sDefault) { 1868dcfb6bfcSJérôme Duval _sDefault->Lock(); 1869dcfb6bfcSJérôme Duval _sDefault->Quit(); 1870dcfb6bfcSJérôme Duval _sDefault = NULL; 1871dcfb6bfcSJérôme Duval } 1872*8496c38aSbeveloper if (out_error) 1873*8496c38aSbeveloper *out_error = err; 1874*8496c38aSbeveloper } 187552a38012Sejakowatz } 187652a38012Sejakowatz locker.Unlock(); 187752a38012Sejakowatz return _sDefault; 187852a38012Sejakowatz } 187952a38012Sejakowatz 188052a38012Sejakowatz 188152a38012Sejakowatz // won't create it if there isn't one 188252a38012Sejakowatz // not thread safe if you call Roster() at the same time 188352a38012Sejakowatz /* static */ BMediaRoster * 188452a38012Sejakowatz BMediaRoster::CurrentRoster() 188552a38012Sejakowatz { 188652a38012Sejakowatz return _sDefault; 188752a38012Sejakowatz } 188852a38012Sejakowatz 188952a38012Sejakowatz 189052a38012Sejakowatz status_t 189152a38012Sejakowatz BMediaRoster::SetTimeSourceFor(media_node_id node, 189252a38012Sejakowatz media_node_id time_source) 189352a38012Sejakowatz { 1894aac800c2Sbeveloper CALLED(); 189540f36b03Sbeveloper if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source)) 1896aac800c2Sbeveloper return B_BAD_VALUE; 1897aac800c2Sbeveloper 1898aac800c2Sbeveloper media_node clone; 1899aac800c2Sbeveloper status_t rv, result; 1900aac800c2Sbeveloper 19015917dd5bSbeveloper TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time source %ld\n", node, time_source); 19025917dd5bSbeveloper 19035917dd5bSbeveloper printf("BMediaRoster::SetTimeSourceFor: node %ld time source %ld enter\n", node, time_source); 19045917dd5bSbeveloper 190586bce45bSbeveloper // we need to get a clone of the node to have a port id 1906aac800c2Sbeveloper rv = GetNodeFor(node, &clone); 1907aac800c2Sbeveloper if (rv != B_OK) { 19085ac4fbd7Sbeveloper ERROR("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id %ld\n", node); 190952a38012Sejakowatz return B_ERROR; 191052a38012Sejakowatz } 191152a38012Sejakowatz 191286bce45bSbeveloper // we just send the request to set time_source-id as timesource to the node, 191386bce45bSbeveloper // the NODE_SET_TIMESOURCE handler code will do the real assignment 1914aac800c2Sbeveloper result = B_OK; 1915aac800c2Sbeveloper node_set_timesource_command cmd; 1916aac800c2Sbeveloper cmd.timesource_id = time_source; 1917aac800c2Sbeveloper rv = SendToPort(clone.port, NODE_SET_TIMESOURCE, &cmd, sizeof(cmd)); 1918aac800c2Sbeveloper if (rv != B_OK) { 19195ac4fbd7Sbeveloper ERROR("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE failed, node id %ld\n", node); 1920aac800c2Sbeveloper result = B_ERROR; 1921aac800c2Sbeveloper } 1922aac800c2Sbeveloper 192360f15390Sbeveloper // we release the clone 1924aac800c2Sbeveloper rv = ReleaseNode(clone); 1925aac800c2Sbeveloper if (rv != B_OK) { 19265ac4fbd7Sbeveloper ERROR("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id %ld\n", node); 1927aac800c2Sbeveloper result = B_ERROR; 1928aac800c2Sbeveloper } 1929aac800c2Sbeveloper 19305917dd5bSbeveloper printf("BMediaRoster::SetTimeSourceFor: node %ld time source %ld leave\n", node, time_source); 19315917dd5bSbeveloper 1932aac800c2Sbeveloper return result; 1933aac800c2Sbeveloper } 1934aac800c2Sbeveloper 193552a38012Sejakowatz 193652a38012Sejakowatz status_t 193752a38012Sejakowatz BMediaRoster::GetParameterWebFor(const media_node & node, 193852a38012Sejakowatz BParameterWeb ** out_web) 193952a38012Sejakowatz { 194028ad138aSbeveloper CALLED(); 194128ad138aSbeveloper if (out_web == NULL) 194228ad138aSbeveloper return B_BAD_VALUE; 194328ad138aSbeveloper if (IS_INVALID_NODE(node)) 194428ad138aSbeveloper return B_MEDIA_BAD_NODE; 194528ad138aSbeveloper if ((node.kind & B_CONTROLLABLE) == 0) 194628ad138aSbeveloper return B_MEDIA_BAD_NODE; 194728ad138aSbeveloper 194828ad138aSbeveloper controllable_get_parameter_web_request request; 194928ad138aSbeveloper controllable_get_parameter_web_reply reply; 195028ad138aSbeveloper 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}; 195128ad138aSbeveloper int32 size; 195228ad138aSbeveloper 195328ad138aSbeveloper // XXX it might be better to query the node for the (current) parameter size first 195428ad138aSbeveloper for (int i = 0; (size = requestsize[i]) != 0; i++) { 195528ad138aSbeveloper status_t rv; 195628ad138aSbeveloper area_id area; 195728ad138aSbeveloper void *data; 195828ad138aSbeveloper area = create_area("parameter web data", &data, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 195928ad138aSbeveloper if (area < B_OK) { 19605ac4fbd7Sbeveloper ERROR("BMediaRoster::GetParameterWebFor couldn't create area of size %ld\n", size); 196128ad138aSbeveloper return B_ERROR; 196228ad138aSbeveloper } 196328ad138aSbeveloper request.maxsize = size; 196428ad138aSbeveloper request.area = area; 196528ad138aSbeveloper rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request, sizeof(request), &reply, sizeof(reply)); 196628ad138aSbeveloper if (rv != B_OK) { 19675ac4fbd7Sbeveloper ERROR("BMediaRoster::GetParameterWebFor CONTROLLABLE_GET_PARAMETER_WEB failed\n"); 196828ad138aSbeveloper delete_area(area); 196928ad138aSbeveloper return B_ERROR; 197028ad138aSbeveloper } 197128ad138aSbeveloper if (reply.size == 0) { 197228ad138aSbeveloper // no parameter web available 197328ad138aSbeveloper // XXX should we return an error? 19745ac4fbd7Sbeveloper ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter web\n", node.node); 197528ad138aSbeveloper *out_web = new BParameterWeb(); 197628ad138aSbeveloper delete_area(area); 197760f15390Sbeveloper return B_OK; 197852a38012Sejakowatz } 197928ad138aSbeveloper if (reply.size > 0) { 198028ad138aSbeveloper // we got a flattened parameter web! 198128ad138aSbeveloper *out_web = new BParameterWeb(); 198228ad138aSbeveloper 1983d91580cdSbeveloper printf("BMediaRoster::GetParameterWebFor Unflattening %ld bytes, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx\n", 198428ad138aSbeveloper reply.size, ((uint32*)data)[0], ((uint32*)data)[1], ((uint32*)data)[2], ((uint32*)data)[3]); 198528ad138aSbeveloper 198628ad138aSbeveloper rv = (*out_web)->Unflatten(reply.code, data, reply.size); 198728ad138aSbeveloper if (rv != B_OK) { 19885ac4fbd7Sbeveloper ERROR("BMediaRoster::GetParameterWebFor Unflatten failed, %s\n", strerror(rv)); 198928ad138aSbeveloper delete_area(area); 199028ad138aSbeveloper delete *out_web; 199128ad138aSbeveloper return B_ERROR; 199228ad138aSbeveloper } 199328ad138aSbeveloper delete_area(area); 199428ad138aSbeveloper return B_OK; 199528ad138aSbeveloper } 199628ad138aSbeveloper delete_area(area); 199728ad138aSbeveloper ASSERT(reply.size == -1); 199828ad138aSbeveloper // parameter web data was too large 199928ad138aSbeveloper // loop and try a larger size 200028ad138aSbeveloper } 20015ac4fbd7Sbeveloper ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter web larger than %ld\n", node.node, size); 200228ad138aSbeveloper return B_ERROR; 200328ad138aSbeveloper } 200452a38012Sejakowatz 200552a38012Sejakowatz 200652a38012Sejakowatz status_t 200752a38012Sejakowatz BMediaRoster::StartControlPanel(const media_node & node, 200852a38012Sejakowatz BMessenger * out_messenger) 200952a38012Sejakowatz { 201052a38012Sejakowatz UNIMPLEMENTED(); 201152a38012Sejakowatz return B_ERROR; 201252a38012Sejakowatz } 201352a38012Sejakowatz 201452a38012Sejakowatz 201552a38012Sejakowatz status_t 201652a38012Sejakowatz BMediaRoster::GetDormantNodes(dormant_node_info * out_info, 201752a38012Sejakowatz int32 * io_count, 201852a38012Sejakowatz const media_format * has_input /* = NULL */, 201952a38012Sejakowatz const media_format * has_output /* = NULL */, 202052a38012Sejakowatz const char * name /* = NULL */, 202152a38012Sejakowatz uint64 require_kinds /* = NULL */, 202252a38012Sejakowatz uint64 deny_kinds /* = NULL */) 202352a38012Sejakowatz { 202452a38012Sejakowatz CALLED(); 202552a38012Sejakowatz if (out_info == NULL) 202652a38012Sejakowatz return B_BAD_VALUE; 202752a38012Sejakowatz if (io_count == NULL) 202852a38012Sejakowatz return B_BAD_VALUE; 202952a38012Sejakowatz if (*io_count <= 0) 203052a38012Sejakowatz return B_BAD_VALUE; 203152a38012Sejakowatz 203252a38012Sejakowatz xfer_server_get_dormant_nodes msg; 203352a38012Sejakowatz port_id port; 203452a38012Sejakowatz status_t rv; 203552a38012Sejakowatz 20364295907bSbeveloper port = find_port(MEDIA_SERVER_PORT_NAME); 203752a38012Sejakowatz if (port <= B_OK) 203852a38012Sejakowatz return B_ERROR; 203952a38012Sejakowatz 204052a38012Sejakowatz msg.maxcount = *io_count; 204152a38012Sejakowatz msg.has_input = (bool) has_input; 204252a38012Sejakowatz if (has_input) 204352a38012Sejakowatz msg.inputformat = *has_input; // XXX we should not make a flat copy of media_format 204452a38012Sejakowatz msg.has_output = (bool) has_output; 204552a38012Sejakowatz if (has_output) 204652a38012Sejakowatz msg.outputformat = *has_output;; // XXX we should not make a flat copy of media_format 204752a38012Sejakowatz msg.has_name = (bool) name; 204852a38012Sejakowatz if (name) { 20499e9417d2Sbeveloper int len = strlen(name); 20509e9417d2Sbeveloper len = min_c(len, (int)sizeof(msg.name) - 1); 205152a38012Sejakowatz memcpy(msg.name, name, len); 205252a38012Sejakowatz msg.name[len] = 0; 205352a38012Sejakowatz } 205452a38012Sejakowatz msg.require_kinds = require_kinds; 205552a38012Sejakowatz msg.deny_kinds = deny_kinds; 205652a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 205752a38012Sejakowatz 205852a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_NODES, &msg, sizeof(msg)); 205952a38012Sejakowatz if (rv != B_OK) { 206052a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 206152a38012Sejakowatz return rv; 206252a38012Sejakowatz } 206352a38012Sejakowatz 206452a38012Sejakowatz xfer_server_get_dormant_nodes_reply reply; 206552a38012Sejakowatz int32 code; 206652a38012Sejakowatz 206752a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 206852a38012Sejakowatz if (rv < B_OK) { 206952a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 207052a38012Sejakowatz return rv; 207152a38012Sejakowatz } 207252a38012Sejakowatz 207352a38012Sejakowatz *io_count = reply.count; 207452a38012Sejakowatz 207552a38012Sejakowatz if (*io_count > 0) { 207652a38012Sejakowatz rv = read_port(msg.reply_port, &code, out_info, *io_count * sizeof(dormant_node_info)); 207752a38012Sejakowatz if (rv < B_OK) 207852a38012Sejakowatz reply.result = rv; 207952a38012Sejakowatz } 208052a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 208152a38012Sejakowatz 208252a38012Sejakowatz return reply.result; 208352a38012Sejakowatz } 208452a38012Sejakowatz 20858b04ffc1Sbeveloper /* This function is used to do the real work of instantiating a dormant node. It is either 20868b04ffc1Sbeveloper * called by the media_addon_server to instantiate a global node, or it gets called from 20878b04ffc1Sbeveloper * BMediaRoster::InstantiateDormantNode() to create a local one. 20888b04ffc1Sbeveloper * 20898b04ffc1Sbeveloper * Checks concerning global/local are not done here. 20908b04ffc1Sbeveloper */ 209152a38012Sejakowatz status_t 209254187cc6Sbeveloper BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, team_id creator, media_node *out_node) 209352a38012Sejakowatz { 209454187cc6Sbeveloper // This function is always called from the correct context, if the node 209554187cc6Sbeveloper // is supposed to be global, it is called from the media_addon_server. 209654187cc6Sbeveloper 209752a38012Sejakowatz // if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that 209852a38012Sejakowatz // resides in the media_addon_server 209952a38012Sejakowatz 21008b04ffc1Sbeveloper // RegisterNode() must be called for nodes instantiated from add-ons, 21018b04ffc1Sbeveloper // since the media kit warrants that it's done automatically. 210252a38012Sejakowatz 210354187cc6Sbeveloper // addonid Indicates the ID number of the media add-on in which the node resides. 210454187cc6Sbeveloper // flavorid Indicates the internal ID number that the add-on uses to identify the flavor, 210554187cc6Sbeveloper // this is the number that was published by BMediaAddOn::GetFlavorAt() in the 21068b04ffc1Sbeveloper // flavor_info::internal_id field. 210754187cc6Sbeveloper // creator The creator team is -1 if nodes are created locally. If created globally, 210854187cc6Sbeveloper // it will contain (while called in media_addon_server context) the team-id of 210954187cc6Sbeveloper // the team that requested the instantiation. 21108b04ffc1Sbeveloper 211160f15390Sbeveloper TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld\n", addonid, flavorid); 21128b04ffc1Sbeveloper 21138b04ffc1Sbeveloper // Get flavor_info from the server 21148b04ffc1Sbeveloper dormant_flavor_info node_info; 21158c6a6096Sbeveloper status_t rv; 21168b04ffc1Sbeveloper rv = GetDormantFlavorInfo(addonid, flavorid, &node_info); 21178b04ffc1Sbeveloper if (rv != B_OK) { 21185ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", addonid, flavorid); 211952a38012Sejakowatz return B_ERROR; 212052a38012Sejakowatz } 21218b04ffc1Sbeveloper 2122908eaf85Sbeveloper //ASSERT(node_info.internal_id == flavorid); 2123908eaf85Sbeveloper if (node_info.internal_id != flavorid) { 21244d2d96e0Sbeveloper ERROR("############# BMediaRosterEx::InstantiateDormantNode failed: ID mismatch for addon-id %ld, flavor-id %ld, node_info.internal_id %ld, node_info.name %s\n", addonid, flavorid, node_info.internal_id, node_info.name); 2125908eaf85Sbeveloper return B_ERROR; 2126908eaf85Sbeveloper } 21278b04ffc1Sbeveloper 21288b04ffc1Sbeveloper // load the BMediaAddOn object 21298b04ffc1Sbeveloper BMediaAddOn *addon; 21308b04ffc1Sbeveloper addon = _DormantNodeManager->GetAddon(addonid); 21318b04ffc1Sbeveloper if (!addon) { 21325ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n"); 21338b04ffc1Sbeveloper return B_ERROR; 21348b04ffc1Sbeveloper } 21358b04ffc1Sbeveloper 213654187cc6Sbeveloper // Now we need to try to increment the use count of this addon flavor 213754187cc6Sbeveloper // in the server. This can fail if the total number instances of this 213854187cc6Sbeveloper // flavor is limited. 213973794717Sbeveloper rv = IncrementAddonFlavorInstancesCount(addonid, flavorid); 214054187cc6Sbeveloper if (rv != B_OK) { 21415ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode error: can't create more nodes for addon-id %ld, flavor-id %ld\n", addonid, flavorid); 214254187cc6Sbeveloper // Put the addon back into the pool 214354187cc6Sbeveloper _DormantNodeManager->PutAddon(addonid); 214454187cc6Sbeveloper return B_ERROR; 214554187cc6Sbeveloper } 214654187cc6Sbeveloper 21478b04ffc1Sbeveloper BMessage config; 214854187cc6Sbeveloper rv = LoadNodeConfiguration(addonid, flavorid, &config); 214954187cc6Sbeveloper if (rv != B_OK) { 21505ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: couldn't load configuration for addon-id %ld, flavor-id %ld\n", addonid, flavorid); 215154187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 215254187cc6Sbeveloper } 21538b04ffc1Sbeveloper 21548b04ffc1Sbeveloper BMediaNode *node; 21558b04ffc1Sbeveloper status_t out_error; 21568b04ffc1Sbeveloper 215754187cc6Sbeveloper out_error = B_OK; 21588b04ffc1Sbeveloper node = addon->InstantiateNodeFor(&node_info, &config, &out_error); 215916b7eea4Sbeveloper if (!node) { 21605ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor failed\n"); 216154187cc6Sbeveloper // Put the addon back into the pool 21628b04ffc1Sbeveloper _DormantNodeManager->PutAddon(addonid); 216354187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 216454187cc6Sbeveloper // server to compensate the increment done in the beginning. 216573794717Sbeveloper rv = DecrementAddonFlavorInstancesCount(addonid, flavorid); 216654187cc6Sbeveloper if (rv != B_OK) { 21675ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n"); 216816b7eea4Sbeveloper } 216954187cc6Sbeveloper return (out_error != B_OK) ? out_error : B_ERROR; 217054187cc6Sbeveloper } 217154187cc6Sbeveloper 217254187cc6Sbeveloper rv = RegisterNode(node, addonid, flavorid); 21738c6a6096Sbeveloper if (rv != B_OK) { 21745ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n"); 21758c6a6096Sbeveloper delete node; 217654187cc6Sbeveloper // Put the addon back into the pool 21778b04ffc1Sbeveloper _DormantNodeManager->PutAddon(addonid); 217854187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 217954187cc6Sbeveloper // server to compensate the increment done in the beginning. 218073794717Sbeveloper rv = DecrementAddonFlavorInstancesCount(addonid, flavorid); 218154187cc6Sbeveloper if (rv != B_OK) { 21825ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n"); 218354187cc6Sbeveloper } 21848c6a6096Sbeveloper return B_ERROR; 21858c6a6096Sbeveloper } 21868c6a6096Sbeveloper 218754187cc6Sbeveloper if (creator != -1) { 218854187cc6Sbeveloper // send a message to the server to assign team "creator" as creator of node "node->ID()" 218954187cc6Sbeveloper printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team %ld as creator of node %ld\n", creator, node->ID()); 219054187cc6Sbeveloper rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator); 219154187cc6Sbeveloper if (rv != B_OK) { 21925ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode failed to assign team %ld as creator of node %ld\n", creator, node->ID()); 219354187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 219454187cc6Sbeveloper } 219554187cc6Sbeveloper } 219654187cc6Sbeveloper 219754187cc6Sbeveloper // RegisterNode() does remember the add-on id in the server 219854187cc6Sbeveloper // and UnregisterNode() will call DormantNodeManager::PutAddon() 219954187cc6Sbeveloper // when the node is unregistered. 22008c6a6096Sbeveloper 220116b7eea4Sbeveloper *out_node = node->Node(); 2202cf4e2277Sbeveloper 220360f15390Sbeveloper 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); 2204cf4e2277Sbeveloper 220516b7eea4Sbeveloper return B_OK; 220616b7eea4Sbeveloper } 220752a38012Sejakowatz 220852a38012Sejakowatz 220952a38012Sejakowatz status_t 22108b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, 22118b04ffc1Sbeveloper media_node * out_node, 22128b04ffc1Sbeveloper uint32 flags /* currently 0 or B_FLAVOR_IS_GLOBAL or B_FLAVOR_IS_LOCAL */ ) 22138b04ffc1Sbeveloper { 22148b04ffc1Sbeveloper CALLED(); 22158b04ffc1Sbeveloper if (out_node == 0) 22168b04ffc1Sbeveloper return B_BAD_VALUE; 22178b04ffc1Sbeveloper if (in_info.addon <= 0) { 22185ac4fbd7Sbeveloper ERROR("BMediaRoster::InstantiateDormantNode error: addon-id %ld invalid.\n", in_info.addon); 22198b04ffc1Sbeveloper return B_BAD_VALUE; 22208b04ffc1Sbeveloper } 22218b04ffc1Sbeveloper 2222d91580cdSbeveloper printf("BMediaRoster::InstantiateDormantNode: addon-id %ld, flavor_id %ld, flags 0x%lX\n", in_info.addon, in_info.flavor_id, flags); 22238b04ffc1Sbeveloper 22248b04ffc1Sbeveloper // Get flavor_info from the server 22258b04ffc1Sbeveloper // XXX this is a little overhead, as we get the full blown dormant_flavor_info, 22268b04ffc1Sbeveloper // XXX but only need the flags. 22278b04ffc1Sbeveloper dormant_flavor_info node_info; 22288b04ffc1Sbeveloper status_t rv; 22298b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetDormantFlavorInfo(in_info.addon, in_info.flavor_id, &node_info); 22308b04ffc1Sbeveloper if (rv != B_OK) { 22315ac4fbd7Sbeveloper ERROR("BMediaRoster::InstantiateDormantNode: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", in_info.addon, in_info.flavor_id); 2232626824eaSbeveloper return B_NAME_NOT_FOUND; 22338b04ffc1Sbeveloper } 22348b04ffc1Sbeveloper 22358b04ffc1Sbeveloper ASSERT(node_info.internal_id == in_info.flavor_id); 22368b04ffc1Sbeveloper 2237d91580cdSbeveloper printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", flavor_flags 0x%lX, internal_id %ld, possible_count %ld\n", 22388b04ffc1Sbeveloper node_info.name, node_info.info, node_info.flavor_flags, node_info.internal_id, node_info.possible_count); 22398b04ffc1Sbeveloper 22408b04ffc1Sbeveloper #if DEBUG 22418b04ffc1Sbeveloper if (flags & B_FLAVOR_IS_LOCAL) 22428b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_LOCAL\n"); 22438b04ffc1Sbeveloper if (flags & B_FLAVOR_IS_GLOBAL) 22448b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_GLOBAL\n"); 22458b04ffc1Sbeveloper if (node_info.flavor_flags & B_FLAVOR_IS_LOCAL) 22468b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_LOCAL\n"); 22478b04ffc1Sbeveloper if (node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) 22488b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_GLOBAL\n"); 22498b04ffc1Sbeveloper #endif 22508b04ffc1Sbeveloper 22518b04ffc1Sbeveloper // Make sure that flags demanded by the dormant node and those requested 22528b04ffc1Sbeveloper // by the caller are not incompatible. 22538b04ffc1Sbeveloper if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) && (flags & B_FLAVOR_IS_LOCAL)) { 22545ac4fbd7Sbeveloper ERROR("BMediaRoster::InstantiateDormantNode: requested B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n"); 2255626824eaSbeveloper return B_NAME_NOT_FOUND; 22568b04ffc1Sbeveloper } 22578b04ffc1Sbeveloper if ((node_info.flavor_flags & B_FLAVOR_IS_LOCAL) && (flags & B_FLAVOR_IS_GLOBAL)) { 22585ac4fbd7Sbeveloper ERROR("BMediaRoster::InstantiateDormantNode: requested B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n"); 2259626824eaSbeveloper return B_NAME_NOT_FOUND; 22608b04ffc1Sbeveloper } 226154187cc6Sbeveloper 22628b04ffc1Sbeveloper // If either the node, or the caller requested to make the instance global 22638b04ffc1Sbeveloper // we will do it by forwarding this request into the media_addon_server, which 22648b04ffc1Sbeveloper // in turn will call BMediaRosterEx::InstantiateDormantNode to create the node 22658b04ffc1Sbeveloper // there and make it globally available. 22668b04ffc1Sbeveloper if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) || (flags & B_FLAVOR_IS_GLOBAL)) { 22678b04ffc1Sbeveloper 2268cf4e2277Sbeveloper printf("BMediaRoster::InstantiateDormantNode: creating global object in media_addon_server\n"); 2269cf4e2277Sbeveloper 22708b04ffc1Sbeveloper addonserver_instantiate_dormant_node_request request; 22718b04ffc1Sbeveloper addonserver_instantiate_dormant_node_reply reply; 22728b04ffc1Sbeveloper request.addonid = in_info.addon; 22738b04ffc1Sbeveloper request.flavorid = in_info.flavor_id; 227454187cc6Sbeveloper request.creator_team = team; // creator team is allowed to also release global nodes 22758b04ffc1Sbeveloper rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply)); 22768b04ffc1Sbeveloper if (rv == B_OK) { 22778b04ffc1Sbeveloper *out_node = reply.node; 22788b04ffc1Sbeveloper } 22798b04ffc1Sbeveloper 22808b04ffc1Sbeveloper } else { 22818b04ffc1Sbeveloper 228254187cc6Sbeveloper // creator team = -1, as this is a local node 2283626824eaSbeveloper rv = MediaRosterEx(this)->InstantiateDormantNode(in_info.addon, in_info.flavor_id, -1, out_node); 2284626824eaSbeveloper 22858b04ffc1Sbeveloper } 2286626824eaSbeveloper if (rv != B_OK) { 2287626824eaSbeveloper *out_node = media_node::null; 2288626824eaSbeveloper return B_NAME_NOT_FOUND; 2289626824eaSbeveloper } 2290626824eaSbeveloper return B_OK; 22918b04ffc1Sbeveloper } 22928b04ffc1Sbeveloper 22938b04ffc1Sbeveloper 22948b04ffc1Sbeveloper status_t 22958b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, 22968b04ffc1Sbeveloper media_node * out_node) 22978b04ffc1Sbeveloper { 22988b04ffc1Sbeveloper return InstantiateDormantNode(in_info, out_node, 0); 22998b04ffc1Sbeveloper } 23008b04ffc1Sbeveloper 23018b04ffc1Sbeveloper 23028b04ffc1Sbeveloper status_t 230352a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node & node, 230452a38012Sejakowatz dormant_node_info * out_info) 230552a38012Sejakowatz { 230685dfab2bSbeveloper CALLED(); 230785dfab2bSbeveloper if (out_info == NULL) 230885dfab2bSbeveloper return B_BAD_VALUE; 230940f36b03Sbeveloper if (IS_INVALID_NODE(node)) 231085dfab2bSbeveloper return B_MEDIA_BAD_NODE; 231152a38012Sejakowatz 231285dfab2bSbeveloper server_get_dormant_node_for_request request; 231385dfab2bSbeveloper server_get_dormant_node_for_reply reply; 231485dfab2bSbeveloper status_t rv; 231585dfab2bSbeveloper 231685dfab2bSbeveloper request.node = node; 231785dfab2bSbeveloper 23181299bfb2Sbeveloper rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply)); 231985dfab2bSbeveloper if (rv != B_OK) 232085dfab2bSbeveloper return rv; 232185dfab2bSbeveloper 232285dfab2bSbeveloper *out_info = reply.node_info; 232385dfab2bSbeveloper return B_OK; 232452a38012Sejakowatz } 232552a38012Sejakowatz 232652a38012Sejakowatz status_t 23278b04ffc1Sbeveloper BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonid, 23288b04ffc1Sbeveloper int32 flavorid, 232952a38012Sejakowatz dormant_flavor_info * out_flavor) 233052a38012Sejakowatz { 233152a38012Sejakowatz CALLED(); 23329bedd42cSbeveloper if (out_flavor == NULL) 23339bedd42cSbeveloper return B_BAD_VALUE; 233452a38012Sejakowatz 233552a38012Sejakowatz xfer_server_get_dormant_flavor_info msg; 233652a38012Sejakowatz xfer_server_get_dormant_flavor_info_reply *reply; 233752a38012Sejakowatz port_id port; 233852a38012Sejakowatz status_t rv; 233952a38012Sejakowatz int32 code; 234052a38012Sejakowatz 23414295907bSbeveloper port = find_port(MEDIA_SERVER_PORT_NAME); 234252a38012Sejakowatz if (port <= B_OK) 234352a38012Sejakowatz return B_ERROR; 234452a38012Sejakowatz 234552a38012Sejakowatz reply = (xfer_server_get_dormant_flavor_info_reply *) malloc(16000); 234652a38012Sejakowatz if (reply == 0) 234752a38012Sejakowatz return B_ERROR; 234852a38012Sejakowatz 23498b04ffc1Sbeveloper msg.addon = addonid; 23508b04ffc1Sbeveloper msg.flavor_id = flavorid; 235152a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 235252a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg)); 235352a38012Sejakowatz if (rv != B_OK) { 235452a38012Sejakowatz free(reply); 235552a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 235652a38012Sejakowatz return rv; 235752a38012Sejakowatz } 235852a38012Sejakowatz rv = read_port(msg.reply_port, &code, reply, 16000); 235952a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 236052a38012Sejakowatz 236152a38012Sejakowatz if (rv < B_OK) { 236252a38012Sejakowatz free(reply); 236352a38012Sejakowatz return rv; 236452a38012Sejakowatz } 236552a38012Sejakowatz 236652a38012Sejakowatz if (reply->result == B_OK) 236752a38012Sejakowatz rv = out_flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size); 236852a38012Sejakowatz else 236952a38012Sejakowatz rv = reply->result; 237052a38012Sejakowatz 237152a38012Sejakowatz free(reply); 237252a38012Sejakowatz return rv; 237352a38012Sejakowatz } 237452a38012Sejakowatz 23758b04ffc1Sbeveloper status_t 23768b04ffc1Sbeveloper BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info & in_dormant, 23778b04ffc1Sbeveloper dormant_flavor_info * out_flavor) 23788b04ffc1Sbeveloper { 23798b04ffc1Sbeveloper return MediaRosterEx(this)->GetDormantFlavorInfo(in_dormant.addon, in_dormant.flavor_id, out_flavor); 23808b04ffc1Sbeveloper } 238152a38012Sejakowatz 238260f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from 238360f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections. 238452a38012Sejakowatz status_t 238552a38012Sejakowatz BMediaRoster::GetLatencyFor(const media_node & producer, 238652a38012Sejakowatz bigtime_t * out_latency) 238752a38012Sejakowatz { 238860f15390Sbeveloper CALLED(); 238960f15390Sbeveloper if (out_latency == NULL) 239060f15390Sbeveloper return B_BAD_VALUE; 239160f15390Sbeveloper if (IS_INVALID_NODE(producer)) 239260f15390Sbeveloper return B_MEDIA_BAD_NODE; 239360f15390Sbeveloper if ((producer.kind & B_BUFFER_PRODUCER) == 0) 239460f15390Sbeveloper return B_MEDIA_BAD_NODE; 239560f15390Sbeveloper 239660f15390Sbeveloper producer_get_latency_request request; 239760f15390Sbeveloper producer_get_latency_reply reply; 239860f15390Sbeveloper status_t rv; 239960f15390Sbeveloper 240060f15390Sbeveloper rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request, sizeof(request), &reply, sizeof(reply)); 240160f15390Sbeveloper if (rv != B_OK) 240260f15390Sbeveloper return rv; 240360f15390Sbeveloper 240460f15390Sbeveloper *out_latency = reply.latency; 240560f15390Sbeveloper 240660f15390Sbeveloper printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency); 2407aac800c2Sbeveloper return B_OK; 240852a38012Sejakowatz } 240952a38012Sejakowatz 241052a38012Sejakowatz 241152a38012Sejakowatz status_t 241252a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node & producer, 241352a38012Sejakowatz bigtime_t * out_latency, 2414aac800c2Sbeveloper uint32 * out_flags /* = NULL */) 241552a38012Sejakowatz { 2416b65a0ac5SJérôme Duval CALLED(); 2417b65a0ac5SJérôme Duval if (out_latency == NULL) 2418b65a0ac5SJérôme Duval return B_BAD_VALUE; 2419b65a0ac5SJérôme Duval if (IS_INVALID_NODE(producer)) 2420b65a0ac5SJérôme Duval return B_MEDIA_BAD_NODE; 2421b65a0ac5SJérôme Duval if ((producer.kind & B_BUFFER_PRODUCER) == 0) 2422b65a0ac5SJérôme Duval return B_MEDIA_BAD_NODE; 2423b65a0ac5SJérôme Duval 2424b65a0ac5SJérôme Duval producer_get_initial_latency_request request; 2425b65a0ac5SJérôme Duval producer_get_initial_latency_reply reply; 2426b65a0ac5SJérôme Duval status_t rv; 2427b65a0ac5SJérôme Duval 2428b65a0ac5SJérôme Duval rv = QueryPort(producer.port, PRODUCER_GET_INITIAL_LATENCY, &request, sizeof(request), &reply, sizeof(reply)); 2429b65a0ac5SJérôme Duval if (rv != B_OK) 2430b65a0ac5SJérôme Duval return rv; 2431b65a0ac5SJérôme Duval 2432b65a0ac5SJérôme Duval *out_latency = reply.initial_latency; 2433aac800c2Sbeveloper if (out_flags) 2434b65a0ac5SJérôme Duval *out_flags = reply.flags; 2435b65a0ac5SJérôme Duval 2436b65a0ac5SJérôme Duval printf("BMediaRoster::GetInitialLatencyFor producer %ld has maximum initial latency %Ld\n", producer.node, *out_latency); 2437aac800c2Sbeveloper return B_OK; 243852a38012Sejakowatz } 243952a38012Sejakowatz 244052a38012Sejakowatz 244152a38012Sejakowatz status_t 244252a38012Sejakowatz BMediaRoster::GetStartLatencyFor(const media_node & time_source, 244352a38012Sejakowatz bigtime_t * out_latency) 244452a38012Sejakowatz { 2445fc8b28b6SJérôme Duval CALLED(); 2446fc8b28b6SJérôme Duval if (out_latency == NULL) 2447fc8b28b6SJérôme Duval return B_BAD_VALUE; 2448fc8b28b6SJérôme Duval if (IS_INVALID_NODE(time_source)) 2449fc8b28b6SJérôme Duval return B_MEDIA_BAD_NODE; 2450fc8b28b6SJérôme Duval if ((time_source.kind & B_TIME_SOURCE) == 0) 2451fc8b28b6SJérôme Duval return B_MEDIA_BAD_NODE; 2452fc8b28b6SJérôme Duval 2453fc8b28b6SJérôme Duval timesource_get_start_latency_request request; 2454fc8b28b6SJérôme Duval timesource_get_start_latency_reply reply; 2455fc8b28b6SJérôme Duval status_t rv; 2456fc8b28b6SJérôme Duval 2457fc8b28b6SJérôme Duval rv = QueryPort(time_source.port, TIMESOURCE_GET_START_LATENCY, &request, sizeof(request), &reply, sizeof(reply)); 2458fc8b28b6SJérôme Duval if (rv != B_OK) 2459fc8b28b6SJérôme Duval return rv; 2460fc8b28b6SJérôme Duval 2461fc8b28b6SJérôme Duval *out_latency = reply.start_latency; 2462fc8b28b6SJérôme Duval 2463fc8b28b6SJérôme Duval printf("BMediaRoster::GetStartLatencyFor timesource %ld has maximum initial latency %Ld\n", time_source.node, *out_latency); 2464aac800c2Sbeveloper return B_OK; 246552a38012Sejakowatz } 246652a38012Sejakowatz 246752a38012Sejakowatz 246852a38012Sejakowatz status_t 246952a38012Sejakowatz BMediaRoster::GetFileFormatsFor(const media_node & file_interface, 247052a38012Sejakowatz media_file_format * out_formats, 247152a38012Sejakowatz int32 * io_num_infos) 247252a38012Sejakowatz { 247352a38012Sejakowatz UNIMPLEMENTED(); 247452a38012Sejakowatz return B_ERROR; 247552a38012Sejakowatz } 247652a38012Sejakowatz 247752a38012Sejakowatz 247852a38012Sejakowatz status_t 247952a38012Sejakowatz BMediaRoster::SetRefFor(const media_node & file_interface, 248052a38012Sejakowatz const entry_ref & file, 248152a38012Sejakowatz bool create_and_truncate, 248252a38012Sejakowatz bigtime_t * out_length) /* if create is false */ 248352a38012Sejakowatz { 248452a38012Sejakowatz UNIMPLEMENTED(); 248552a38012Sejakowatz return B_ERROR; 248652a38012Sejakowatz } 248752a38012Sejakowatz 248852a38012Sejakowatz 248952a38012Sejakowatz status_t 249052a38012Sejakowatz BMediaRoster::GetRefFor(const media_node & node, 249152a38012Sejakowatz entry_ref * out_file, 249252a38012Sejakowatz BMimeType * mime_type) 249352a38012Sejakowatz { 249452a38012Sejakowatz UNIMPLEMENTED(); 249552a38012Sejakowatz return B_ERROR; 249652a38012Sejakowatz } 249752a38012Sejakowatz 249852a38012Sejakowatz 249952a38012Sejakowatz status_t 250052a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node & file_interface, 250152a38012Sejakowatz const entry_ref & file, 250252a38012Sejakowatz BMimeType * mime_type, 250352a38012Sejakowatz float * out_capability) 250452a38012Sejakowatz { 250552a38012Sejakowatz UNIMPLEMENTED(); 250652a38012Sejakowatz return B_ERROR; 250752a38012Sejakowatz } 250852a38012Sejakowatz 250952a38012Sejakowatz 251052a38012Sejakowatz /* This is the generic "here's a file, now can someone please play it" interface */ 251152a38012Sejakowatz status_t 251252a38012Sejakowatz BMediaRoster::SniffRef(const entry_ref & file, 251352a38012Sejakowatz uint64 require_node_kinds, /* if you need an EntityInterface or BufferConsumer or something */ 251452a38012Sejakowatz dormant_node_info * out_node, 251552a38012Sejakowatz BMimeType * mime_type) 251652a38012Sejakowatz { 251752a38012Sejakowatz UNIMPLEMENTED(); 251852a38012Sejakowatz return B_ERROR; 251952a38012Sejakowatz } 252052a38012Sejakowatz 252152a38012Sejakowatz 252252a38012Sejakowatz status_t 252352a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType & type, 252452a38012Sejakowatz uint64 require_node_kinds, 252552a38012Sejakowatz dormant_node_info * out_node) 252652a38012Sejakowatz { 252752a38012Sejakowatz UNIMPLEMENTED(); 252852a38012Sejakowatz return B_ERROR; 252952a38012Sejakowatz } 253052a38012Sejakowatz 253152a38012Sejakowatz 253252a38012Sejakowatz status_t 253352a38012Sejakowatz BMediaRoster::GetReadFileFormatsFor(const dormant_node_info & in_node, 253452a38012Sejakowatz media_file_format * out_read_formats, 253552a38012Sejakowatz int32 in_read_count, 253652a38012Sejakowatz int32 * out_read_count) 253752a38012Sejakowatz { 253852a38012Sejakowatz UNIMPLEMENTED(); 253952a38012Sejakowatz return B_ERROR; 254052a38012Sejakowatz } 254152a38012Sejakowatz 254252a38012Sejakowatz 254352a38012Sejakowatz status_t 254452a38012Sejakowatz BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info & in_node, 254552a38012Sejakowatz media_file_format * out_write_formats, 254652a38012Sejakowatz int32 in_write_count, 254752a38012Sejakowatz int32 * out_write_count) 254852a38012Sejakowatz { 254952a38012Sejakowatz UNIMPLEMENTED(); 255052a38012Sejakowatz return B_ERROR; 255152a38012Sejakowatz } 255252a38012Sejakowatz 255352a38012Sejakowatz 255452a38012Sejakowatz status_t 255552a38012Sejakowatz BMediaRoster::GetFormatFor(const media_output & output, 255652a38012Sejakowatz media_format * io_format, 255752a38012Sejakowatz uint32 flags) 255852a38012Sejakowatz { 25599bedd42cSbeveloper CALLED(); 25609bedd42cSbeveloper if (io_format == NULL) 25619bedd42cSbeveloper return B_BAD_VALUE; 25629bedd42cSbeveloper if ((output.node.kind & B_BUFFER_PRODUCER) == 0) 25639bedd42cSbeveloper return B_MEDIA_BAD_NODE; 25649bedd42cSbeveloper if (IS_INVALID_SOURCE(output.source)) 25659bedd42cSbeveloper return B_MEDIA_BAD_SOURCE; 25669bedd42cSbeveloper 25679bedd42cSbeveloper producer_format_suggestion_requested_request request; 25689bedd42cSbeveloper producer_format_suggestion_requested_reply reply; 25699bedd42cSbeveloper status_t rv; 25709bedd42cSbeveloper 25719bedd42cSbeveloper request.type = B_MEDIA_UNKNOWN_TYPE; 25729bedd42cSbeveloper request.quality = 0; // XXX what should this be? 25739bedd42cSbeveloper 25749bedd42cSbeveloper rv = QueryPort(output.source.port, PRODUCER_FORMAT_SUGGESTION_REQUESTED, &request, sizeof(request), &reply, sizeof(reply)); 25759bedd42cSbeveloper if (rv != B_OK) 25769bedd42cSbeveloper return rv; 25779bedd42cSbeveloper 25789bedd42cSbeveloper *io_format = reply.format; 25799bedd42cSbeveloper return B_OK; 258052a38012Sejakowatz } 258152a38012Sejakowatz 258252a38012Sejakowatz 258352a38012Sejakowatz status_t 258452a38012Sejakowatz BMediaRoster::GetFormatFor(const media_input & input, 258552a38012Sejakowatz media_format * io_format, 258652a38012Sejakowatz uint32 flags) 258752a38012Sejakowatz { 25889bedd42cSbeveloper CALLED(); 25899bedd42cSbeveloper if (io_format == NULL) 25909bedd42cSbeveloper return B_BAD_VALUE; 25919bedd42cSbeveloper if ((input.node.kind & B_BUFFER_CONSUMER) == 0) 25929bedd42cSbeveloper return B_MEDIA_BAD_NODE; 25939bedd42cSbeveloper if (IS_INVALID_DESTINATION(input.destination)) 25949bedd42cSbeveloper return B_MEDIA_BAD_DESTINATION; 25959bedd42cSbeveloper 25969bedd42cSbeveloper consumer_accept_format_request request; 25979bedd42cSbeveloper consumer_accept_format_reply reply; 25989bedd42cSbeveloper status_t rv; 25999bedd42cSbeveloper 26009bedd42cSbeveloper request.dest = input.destination; 26019bedd42cSbeveloper memset(&request.format, 0, sizeof(request.format)); // wildcard 26029bedd42cSbeveloper 26039bedd42cSbeveloper rv = QueryPort(input.destination.port, CONSUMER_ACCEPT_FORMAT, &request, sizeof(request), &reply, sizeof(reply)); 26049bedd42cSbeveloper if (rv != B_OK) 26059bedd42cSbeveloper return rv; 26069bedd42cSbeveloper 26079bedd42cSbeveloper *io_format = reply.format; 26089bedd42cSbeveloper return B_OK; 260952a38012Sejakowatz } 261052a38012Sejakowatz 261152a38012Sejakowatz 261252a38012Sejakowatz status_t 261352a38012Sejakowatz BMediaRoster::GetFormatFor(const media_node & node, 261452a38012Sejakowatz media_format * io_format, 261552a38012Sejakowatz float quality) 261652a38012Sejakowatz { 261752a38012Sejakowatz UNIMPLEMENTED(); 26189bedd42cSbeveloper if (io_format == NULL) 26199bedd42cSbeveloper return B_BAD_VALUE; 26209bedd42cSbeveloper if (IS_INVALID_NODE(node)) 26219bedd42cSbeveloper return B_MEDIA_BAD_NODE; 26229bedd42cSbeveloper if ((node.kind & (B_BUFFER_CONSUMER | B_BUFFER_PRODUCER)) == 0) 26239bedd42cSbeveloper return B_MEDIA_BAD_NODE; 26249bedd42cSbeveloper 26259bedd42cSbeveloper 262652a38012Sejakowatz return B_ERROR; 262752a38012Sejakowatz } 262852a38012Sejakowatz 262952a38012Sejakowatz 263052a38012Sejakowatz ssize_t 263152a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node & node, 263252a38012Sejakowatz media_node_attribute * outArray, 263352a38012Sejakowatz size_t inMaxCount) 263452a38012Sejakowatz { 263552a38012Sejakowatz UNIMPLEMENTED(); 263652a38012Sejakowatz return B_ERROR; 263752a38012Sejakowatz } 263852a38012Sejakowatz 263952a38012Sejakowatz 264052a38012Sejakowatz media_node_id 264152a38012Sejakowatz BMediaRoster::NodeIDFor(port_id source_or_destination_port) 264252a38012Sejakowatz { 26439e9417d2Sbeveloper CALLED(); 26449e9417d2Sbeveloper 26459e9417d2Sbeveloper server_node_id_for_request request; 26469e9417d2Sbeveloper server_node_id_for_reply reply; 26479e9417d2Sbeveloper status_t rv; 26489e9417d2Sbeveloper 26499e9417d2Sbeveloper request.port = source_or_destination_port; 26509e9417d2Sbeveloper 26519e9417d2Sbeveloper rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, sizeof(reply)); 26529e9417d2Sbeveloper if (rv != B_OK) { 26535ac4fbd7Sbeveloper ERROR("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv); 26549e9417d2Sbeveloper return -1; 26559e9417d2Sbeveloper } 26569e9417d2Sbeveloper 26579e9417d2Sbeveloper return reply.nodeid; 265852a38012Sejakowatz } 265952a38012Sejakowatz 266052a38012Sejakowatz 266152a38012Sejakowatz status_t 266252a38012Sejakowatz BMediaRoster::GetInstancesFor(media_addon_id addon, 266352a38012Sejakowatz int32 flavor, 266452a38012Sejakowatz media_node_id * out_id, 266552a38012Sejakowatz int32 * io_count) 266652a38012Sejakowatz { 266785dfab2bSbeveloper CALLED(); 26688b9700adSJérôme Duval if (out_id == NULL) 266985dfab2bSbeveloper return B_BAD_VALUE; 26708b9700adSJérôme Duval if (io_count && *io_count <= 0) 267185dfab2bSbeveloper return B_BAD_VALUE; 267285dfab2bSbeveloper 267385dfab2bSbeveloper server_get_instances_for_request request; 267485dfab2bSbeveloper server_get_instances_for_reply reply; 267585dfab2bSbeveloper status_t rv; 267685dfab2bSbeveloper 26778b9700adSJérôme Duval request.maxcount = (io_count ? *io_count : 1); 267885dfab2bSbeveloper request.addon_id = addon; 267985dfab2bSbeveloper request.addon_flavor_id = flavor; 268085dfab2bSbeveloper 268185dfab2bSbeveloper rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), &reply, sizeof(reply)); 268285dfab2bSbeveloper if (rv != B_OK) { 26835ac4fbd7Sbeveloper ERROR("BMediaRoster::GetLiveNodes failed\n"); 268485dfab2bSbeveloper return rv; 268552a38012Sejakowatz } 268652a38012Sejakowatz 26878b9700adSJérôme Duval if(io_count) 268885dfab2bSbeveloper *io_count = reply.count; 268985dfab2bSbeveloper if (reply.count > 0) 269085dfab2bSbeveloper memcpy(out_id, reply.node_id, sizeof(media_node_id) * reply.count); 269185dfab2bSbeveloper 269285dfab2bSbeveloper return B_OK; 269385dfab2bSbeveloper } 269452a38012Sejakowatz 269552a38012Sejakowatz 269652a38012Sejakowatz status_t 269752a38012Sejakowatz BMediaRoster::SetRealtimeFlags(uint32 in_enabled) 269852a38012Sejakowatz { 269952a38012Sejakowatz UNIMPLEMENTED(); 270052a38012Sejakowatz return B_ERROR; 270152a38012Sejakowatz } 270252a38012Sejakowatz 270352a38012Sejakowatz 270452a38012Sejakowatz status_t 270552a38012Sejakowatz BMediaRoster::GetRealtimeFlags(uint32 * out_enabled) 270652a38012Sejakowatz { 270752a38012Sejakowatz UNIMPLEMENTED(); 270852a38012Sejakowatz return B_ERROR; 270952a38012Sejakowatz } 271052a38012Sejakowatz 271152a38012Sejakowatz 271252a38012Sejakowatz ssize_t 271352a38012Sejakowatz BMediaRoster::AudioBufferSizeFor(int32 channel_count, 271452a38012Sejakowatz uint32 sample_format, 271552a38012Sejakowatz float frame_rate, 271652a38012Sejakowatz bus_type bus_kind) 271752a38012Sejakowatz { 2718df6c2e83Sbeveloper bigtime_t buffer_duration; 2719df6c2e83Sbeveloper ssize_t buffer_size; 2720df6c2e83Sbeveloper 2721df6c2e83Sbeveloper system_info info; 2722df6c2e83Sbeveloper get_system_info(&info); 2723df6c2e83Sbeveloper 2724df6c2e83Sbeveloper if (info.cpu_clock_speed > 2000000000) 2725df6c2e83Sbeveloper buffer_duration = 2500; 2726df6c2e83Sbeveloper else if (info.cpu_clock_speed > 1000000000) 2727df6c2e83Sbeveloper buffer_duration = 5000; 2728df6c2e83Sbeveloper else if (info.cpu_clock_speed > 600000000) 2729df6c2e83Sbeveloper buffer_duration = 10000; 2730df6c2e83Sbeveloper else if (info.cpu_clock_speed > 200000000) 2731df6c2e83Sbeveloper buffer_duration = 20000; 2732df6c2e83Sbeveloper else if (info.cpu_clock_speed > 100000000) 2733df6c2e83Sbeveloper buffer_duration = 30000; 2734df6c2e83Sbeveloper else 2735df6c2e83Sbeveloper buffer_duration = 50000; 2736df6c2e83Sbeveloper 2737df6c2e83Sbeveloper if ((bus_kind == B_ISA_BUS || bus_kind == B_PCMCIA_BUS) && buffer_duration < 25000) 2738df6c2e83Sbeveloper buffer_duration = 25000; 2739df6c2e83Sbeveloper 2740df6c2e83Sbeveloper buffer_size = (sample_format & 0xf) * channel_count * (ssize_t)((frame_rate * buffer_duration) / 1000000.0); 2741df6c2e83Sbeveloper 2742df6c2e83Sbeveloper printf("Suggested buffer duration %Ld, size %ld\n", buffer_duration, buffer_size); 2743df6c2e83Sbeveloper 2744df6c2e83Sbeveloper return buffer_size; 274552a38012Sejakowatz } 274652a38012Sejakowatz 274752a38012Sejakowatz 274852a38012Sejakowatz /* Use MediaFlags to inquire about specific features of the Media Kit. */ 274952a38012Sejakowatz /* Returns < 0 for "not present", positive size for output data size. */ 275052a38012Sejakowatz /* 0 means that the capability is present, but no data about it. */ 275152a38012Sejakowatz /* static */ ssize_t 275252a38012Sejakowatz BMediaRoster::MediaFlags(media_flags cap, 275352a38012Sejakowatz void * buf, 275452a38012Sejakowatz size_t maxSize) 275552a38012Sejakowatz { 275652a38012Sejakowatz UNIMPLEMENTED(); 275752a38012Sejakowatz return 0; 275852a38012Sejakowatz } 275952a38012Sejakowatz 276052a38012Sejakowatz 276152a38012Sejakowatz /* BLooper overrides */ 276252a38012Sejakowatz /* virtual */ void 276352a38012Sejakowatz BMediaRoster::MessageReceived(BMessage * message) 276452a38012Sejakowatz { 2765cf4e2277Sbeveloper switch (message->what) { 2766cf4e2277Sbeveloper case 'PING': 2767cf4e2277Sbeveloper { 27686396865dSbeveloper // media_server plays ping-pong with the BMediaRosters 27696396865dSbeveloper // to detect dead teams. Normal communication uses ports. 27706396865dSbeveloper static BMessage pong('PONG'); 27716396865dSbeveloper message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000); 27726396865dSbeveloper return; 27736396865dSbeveloper } 27746396865dSbeveloper 2775cf4e2277Sbeveloper case NODE_FINAL_RELEASE: 2776cf4e2277Sbeveloper { 2777cf4e2277Sbeveloper // this function is called by a BMediaNode to delete 2778cf4e2277Sbeveloper // itself, as this needs to be done from another thread 2779cf4e2277Sbeveloper // context, it is done here. 2780cf4e2277Sbeveloper // XXX If a node is released using BMediaRoster::ReleaseNode() 2781cf4e2277Sbeveloper // XXX instead of using BMediaNode::Release() / BMediaNode::Acquire() 2782cf4e2277Sbeveloper // XXX fRefCount of the BMediaNode will not be correct. 2783cf4e2277Sbeveloper 2784cf4e2277Sbeveloper BMediaNode *node; 2785cf4e2277Sbeveloper message->FindPointer("node", reinterpret_cast<void **>(&node)); 2786cf4e2277Sbeveloper 278754187cc6Sbeveloper TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE saving node %ld configuration\n", node->ID()); 278854187cc6Sbeveloper MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(node); 2789cf4e2277Sbeveloper 279054187cc6Sbeveloper TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing node %ld\n", node->ID()); 2791cf4e2277Sbeveloper node->DeleteHook(node); // we don't call Release(), see above! 2792cf4e2277Sbeveloper return; 2793cf4e2277Sbeveloper } 2794cf4e2277Sbeveloper } 27956396865dSbeveloper printf("BMediaRoster::MessageReceived: unknown message!\n"); 27966396865dSbeveloper message->PrintToStream(); 279752a38012Sejakowatz } 279852a38012Sejakowatz 279952a38012Sejakowatz /* virtual */ bool 280052a38012Sejakowatz BMediaRoster::QuitRequested() 280152a38012Sejakowatz { 280252a38012Sejakowatz UNIMPLEMENTED(); 280352a38012Sejakowatz return true; 280452a38012Sejakowatz } 280552a38012Sejakowatz 280652a38012Sejakowatz /* virtual */ BHandler * 280752a38012Sejakowatz BMediaRoster::ResolveSpecifier(BMessage *msg, 280852a38012Sejakowatz int32 index, 280952a38012Sejakowatz BMessage *specifier, 281052a38012Sejakowatz int32 form, 281152a38012Sejakowatz const char *property) 281252a38012Sejakowatz { 281352a38012Sejakowatz UNIMPLEMENTED(); 281452a38012Sejakowatz return 0; 281552a38012Sejakowatz } 281652a38012Sejakowatz 281752a38012Sejakowatz 281852a38012Sejakowatz /* virtual */ status_t 281952a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage *data) 282052a38012Sejakowatz { 282152a38012Sejakowatz UNIMPLEMENTED(); 282252a38012Sejakowatz return B_ERROR; 282352a38012Sejakowatz } 282452a38012Sejakowatz 282552a38012Sejakowatz 282652a38012Sejakowatz BMediaRoster::~BMediaRoster() 282752a38012Sejakowatz { 282852a38012Sejakowatz CALLED(); 28296396865dSbeveloper 28306396865dSbeveloper // unregister this application with the media server 28316396865dSbeveloper server_unregister_app_request request; 28326396865dSbeveloper server_unregister_app_reply reply; 28336396865dSbeveloper request.team = team; 28346396865dSbeveloper QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, sizeof(reply)); 283552a38012Sejakowatz } 283652a38012Sejakowatz 283752a38012Sejakowatz 283852a38012Sejakowatz /************************************************************* 283952a38012Sejakowatz * private BMediaRoster 284052a38012Sejakowatz *************************************************************/ 284152a38012Sejakowatz 284252a38012Sejakowatz // deprecated call 284352a38012Sejakowatz status_t 284452a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source & output, 284552a38012Sejakowatz BBufferGroup * group, 284652a38012Sejakowatz bool will_reclaim ) 284752a38012Sejakowatz { 284852a38012Sejakowatz UNIMPLEMENTED(); 28499e9417d2Sbeveloper debugger("BMediaRoster::SetOutputBuffersFor missing\n"); 285052a38012Sejakowatz return B_ERROR; 285152a38012Sejakowatz } 285252a38012Sejakowatz 285352a38012Sejakowatz 285452a38012Sejakowatz /* FBC stuffing (Mmmh, Stuffing!) */ 285552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; } 285652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; } 285752a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; } 285852a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; } 285952a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; } 286052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; } 286152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; } 286252a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; } 286352a38012Sejakowatz 286452a38012Sejakowatz 286552a38012Sejakowatz BMediaRoster::BMediaRoster() : 28666396865dSbeveloper BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, B_LOOPER_PORT_DEFAULT_CAPACITY) 286752a38012Sejakowatz { 286852a38012Sejakowatz CALLED(); 28696396865dSbeveloper 28706396865dSbeveloper // start the looper 28716396865dSbeveloper Run(); 287252a38012Sejakowatz } 287352a38012Sejakowatz 28746396865dSbeveloper 287552a38012Sejakowatz /* static */ status_t 287652a38012Sejakowatz BMediaRoster::ParseCommand(BMessage & reply) 287752a38012Sejakowatz { 287852a38012Sejakowatz UNIMPLEMENTED(); 287952a38012Sejakowatz return B_ERROR; 288052a38012Sejakowatz } 288152a38012Sejakowatz 288252a38012Sejakowatz 288352a38012Sejakowatz status_t 288452a38012Sejakowatz BMediaRoster::GetDefaultInfo(media_node_id for_default, 288552a38012Sejakowatz BMessage & out_config) 288652a38012Sejakowatz { 288752a38012Sejakowatz UNIMPLEMENTED(); 288852a38012Sejakowatz return B_ERROR; 288952a38012Sejakowatz } 289052a38012Sejakowatz 289152a38012Sejakowatz 289252a38012Sejakowatz 289352a38012Sejakowatz status_t 289452a38012Sejakowatz BMediaRoster::SetRunningDefault(media_node_id for_default, 289552a38012Sejakowatz const media_node & node) 289652a38012Sejakowatz { 289752a38012Sejakowatz UNIMPLEMENTED(); 289852a38012Sejakowatz return B_ERROR; 289952a38012Sejakowatz } 290052a38012Sejakowatz 290152a38012Sejakowatz 290252a38012Sejakowatz /************************************************************* 290352a38012Sejakowatz * static BMediaRoster variables 290452a38012Sejakowatz *************************************************************/ 290552a38012Sejakowatz 290652a38012Sejakowatz bool BMediaRoster::_isMediaServer; 290752a38012Sejakowatz port_id BMediaRoster::_mReplyPort; 290852a38012Sejakowatz int32 BMediaRoster::_mReplyPortRes; 290952a38012Sejakowatz int32 BMediaRoster::_mReplyPortUnavailCount; 291052a38012Sejakowatz BMediaRoster * BMediaRoster::_sDefault = NULL; 291152a38012Sejakowatz 2912