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 773620737cSbeveloper status_t 7854187cc6Sbeveloper BMediaRosterEx::SaveNodeConfiguration(BMediaNode *node) 7954187cc6Sbeveloper { 8054187cc6Sbeveloper BMediaAddOn *addon; 8154187cc6Sbeveloper media_addon_id addonid; 8254187cc6Sbeveloper int32 flavorid; 8354187cc6Sbeveloper addon = node->AddOn(&flavorid); 8454187cc6Sbeveloper if (!addon) { 8560f15390Sbeveloper // XXX this check incorrectly triggers on BeOS R5 BT848 node 865ac4fbd7Sbeveloper ERROR("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated from BMediaAddOn!\n", node->ID()); 8754187cc6Sbeveloper return B_ERROR; 8854187cc6Sbeveloper } 8954187cc6Sbeveloper addonid = addon->AddonID(); 9054187cc6Sbeveloper 9154187cc6Sbeveloper // XXX fix this 9254187cc6Sbeveloper printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid); 9354187cc6Sbeveloper return B_OK; 9454187cc6Sbeveloper } 9554187cc6Sbeveloper 9654187cc6Sbeveloper status_t 9754187cc6Sbeveloper BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage *out_msg) 9854187cc6Sbeveloper { 9954187cc6Sbeveloper // XXX fix this 10054187cc6Sbeveloper out_msg->MakeEmpty(); // to be fully R5 compliant 10154187cc6Sbeveloper printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id %ld, flavor-id %ld config NOW!\n", addonid, flavorid); 10254187cc6Sbeveloper return B_OK; 10354187cc6Sbeveloper } 10454187cc6Sbeveloper 10554187cc6Sbeveloper status_t 10673794717Sbeveloper BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid) 10754187cc6Sbeveloper { 10873794717Sbeveloper server_change_addon_flavor_instances_count_request request; 10973794717Sbeveloper server_change_addon_flavor_instances_count_reply reply; 11073794717Sbeveloper 11173794717Sbeveloper request.addonid = addonid; 11273794717Sbeveloper request.flavorid = flavorid; 11373794717Sbeveloper request.delta = 1; 11473794717Sbeveloper request.team = team; 11573794717Sbeveloper return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply)); 11654187cc6Sbeveloper } 11754187cc6Sbeveloper 11854187cc6Sbeveloper status_t 11973794717Sbeveloper BMediaRosterEx::DecrementAddonFlavorInstancesCount(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 13254187cc6Sbeveloper BMediaRosterEx::SetNodeCreator(media_node_id node, team_id creator) 13354187cc6Sbeveloper { 13454187cc6Sbeveloper server_set_node_creator_request request; 13554187cc6Sbeveloper server_set_node_creator_reply reply; 13654187cc6Sbeveloper 13754187cc6Sbeveloper request.node = node; 13854187cc6Sbeveloper request.creator = creator; 13954187cc6Sbeveloper return QueryServer(SERVER_SET_NODE_CREATOR, &request, sizeof(request), &reply, sizeof(reply)); 14054187cc6Sbeveloper } 14154187cc6Sbeveloper 14254187cc6Sbeveloper status_t 1438b04ffc1Sbeveloper BMediaRosterEx::GetNode(node_type type, media_node * out_node, int32 * out_input_id, BString * out_input_name) 14452a38012Sejakowatz { 14552a38012Sejakowatz if (out_node == NULL) 14652a38012Sejakowatz return B_BAD_VALUE; 14752a38012Sejakowatz 1488c6a6096Sbeveloper server_get_node_request request; 1498c6a6096Sbeveloper server_get_node_reply reply; 15052a38012Sejakowatz status_t rv; 15152a38012Sejakowatz 1528c6a6096Sbeveloper request.type = type; 1539e9417d2Sbeveloper request.team = team; 1548c6a6096Sbeveloper rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, sizeof(reply)); 1558c6a6096Sbeveloper if (rv != B_OK) 1568c6a6096Sbeveloper return rv; 15752a38012Sejakowatz 15852a38012Sejakowatz *out_node = reply.node; 15952a38012Sejakowatz if (out_input_id) 16052a38012Sejakowatz *out_input_id = reply.input_id; 16152a38012Sejakowatz if (out_input_name) 16252a38012Sejakowatz *out_input_name = reply.input_name; 1638c6a6096Sbeveloper return rv; 16452a38012Sejakowatz } 16552a38012Sejakowatz 1663620737cSbeveloper status_t 1678b04ffc1Sbeveloper BMediaRosterEx::SetNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input) 16852a38012Sejakowatz { 1698c6a6096Sbeveloper server_set_node_request request; 1708c6a6096Sbeveloper server_set_node_reply reply; 17152a38012Sejakowatz 1728c6a6096Sbeveloper request.type = type; 1738c6a6096Sbeveloper request.use_node = node ? true : false; 17452a38012Sejakowatz if (node) 1758c6a6096Sbeveloper request.node = *node; 1768c6a6096Sbeveloper request.use_dni = info ? true : false; 17752a38012Sejakowatz if (info) 1788c6a6096Sbeveloper request.dni = *info; 1798c6a6096Sbeveloper request.use_input = input ? true : false; 18052a38012Sejakowatz if (input) 1818c6a6096Sbeveloper request.input = *input; 18252a38012Sejakowatz 1838c6a6096Sbeveloper return QueryServer(SERVER_SET_NODE, &request, sizeof(request), &reply, sizeof(reply)); 18452a38012Sejakowatz } 18552a38012Sejakowatz 1863620737cSbeveloper status_t 1878b04ffc1Sbeveloper BMediaRosterEx::GetAllOutputs(const media_node & node, List<media_output> *list) 1883620737cSbeveloper { 1893620737cSbeveloper int32 cookie; 1903620737cSbeveloper status_t rv; 1913620737cSbeveloper status_t result; 1923620737cSbeveloper 1935ac4fbd7Sbeveloper PRINT(4, "BMediaRosterEx::GetAllOutputs() node %ld, port %ld\n", node.node, node.port); 1945ac4fbd7Sbeveloper 1953620737cSbeveloper result = B_OK; 1963620737cSbeveloper cookie = 0; 19776669a29Sbeveloper list->MakeEmpty(); 1983620737cSbeveloper for (;;) { 1993620737cSbeveloper producer_get_next_output_request request; 2003620737cSbeveloper producer_get_next_output_reply reply; 2013620737cSbeveloper request.cookie = cookie; 2020caff283Sbeveloper rv = QueryPort(node.port, PRODUCER_GET_NEXT_OUTPUT, &request, sizeof(request), &reply, sizeof(reply)); 2033620737cSbeveloper if (rv != B_OK) 2043620737cSbeveloper break; 2053620737cSbeveloper cookie = reply.cookie; 20676669a29Sbeveloper if (!list->Insert(reply.output)) { 2075ac4fbd7Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 2083620737cSbeveloper result = B_ERROR; 2093620737cSbeveloper } 2105ac4fbd7Sbeveloper #if DEBUG >= 3 2115ac4fbd7Sbeveloper PRINT(3," next cookie %ld, ", cookie); 2125ac4fbd7Sbeveloper PRINT_OUTPUT("output ", reply.output); 2135ac4fbd7Sbeveloper #endif 2143620737cSbeveloper } 2153620737cSbeveloper 2163620737cSbeveloper producer_dispose_output_cookie_request request; 2173620737cSbeveloper producer_dispose_output_cookie_reply reply; 2180caff283Sbeveloper QueryPort(node.port, PRODUCER_DISPOSE_OUTPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply)); 2193620737cSbeveloper 2203620737cSbeveloper return result; 2213620737cSbeveloper } 2223620737cSbeveloper 2233620737cSbeveloper status_t 2244d2d96e0Sbeveloper BMediaRosterEx::GetAllOutputs(BBufferProducer *node, List<media_output> *list) 2254d2d96e0Sbeveloper { 2264d2d96e0Sbeveloper int32 cookie; 2274d2d96e0Sbeveloper status_t result; 2284d2d96e0Sbeveloper 2294d2d96e0Sbeveloper PRINT(4, "BMediaRosterEx::GetAllOutputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort()); 2304d2d96e0Sbeveloper 2314d2d96e0Sbeveloper result = B_OK; 2324d2d96e0Sbeveloper cookie = 0; 2334d2d96e0Sbeveloper list->MakeEmpty(); 2344d2d96e0Sbeveloper for (;;) { 2354d2d96e0Sbeveloper media_output output; 2364d2d96e0Sbeveloper if (B_OK != node->GetNextOutput(&cookie, &output)) 2374d2d96e0Sbeveloper break; 2384d2d96e0Sbeveloper if (!list->Insert(output)) { 2394d2d96e0Sbeveloper ERROR("GetAllOutputs: list->Insert failed\n"); 2404d2d96e0Sbeveloper result = B_ERROR; 2414d2d96e0Sbeveloper } 2424d2d96e0Sbeveloper #if DEBUG >= 3 2434d2d96e0Sbeveloper PRINT(3," next cookie %ld, ", cookie); 2444d2d96e0Sbeveloper PRINT_OUTPUT("output ", output); 2454d2d96e0Sbeveloper #endif 2464d2d96e0Sbeveloper } 2474d2d96e0Sbeveloper node->DisposeOutputCookie(cookie); 2484d2d96e0Sbeveloper return result; 2494d2d96e0Sbeveloper } 2504d2d96e0Sbeveloper 2514d2d96e0Sbeveloper status_t 2528b04ffc1Sbeveloper BMediaRosterEx::GetAllInputs(const media_node & node, List<media_input> *list) 2533620737cSbeveloper { 2543620737cSbeveloper int32 cookie; 2553620737cSbeveloper status_t rv; 2563620737cSbeveloper status_t result; 2573620737cSbeveloper 2585ac4fbd7Sbeveloper PRINT(4, "BMediaRosterEx::GetAllInputs() node %ld, port %ld\n", node.node, node.port); 2595ac4fbd7Sbeveloper 2603620737cSbeveloper result = B_OK; 2613620737cSbeveloper cookie = 0; 26276669a29Sbeveloper list->MakeEmpty(); 2633620737cSbeveloper for (;;) { 2643620737cSbeveloper consumer_get_next_input_request request; 2653620737cSbeveloper consumer_get_next_input_reply reply; 2663620737cSbeveloper request.cookie = cookie; 2670caff283Sbeveloper rv = QueryPort(node.port, CONSUMER_GET_NEXT_INPUT, &request, sizeof(request), &reply, sizeof(reply)); 2683620737cSbeveloper if (rv != B_OK) 2693620737cSbeveloper break; 2703620737cSbeveloper cookie = reply.cookie; 27176669a29Sbeveloper if (!list->Insert(reply.input)) { 2725ac4fbd7Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 2733620737cSbeveloper result = B_ERROR; 2743620737cSbeveloper } 2755ac4fbd7Sbeveloper #if DEBUG >= 3 2765ac4fbd7Sbeveloper PRINT(3," next cookie %ld, ", cookie); 2775ac4fbd7Sbeveloper PRINT_OUTPUT("input ", reply.input); 2785ac4fbd7Sbeveloper #endif 2793620737cSbeveloper } 2803620737cSbeveloper 2813620737cSbeveloper consumer_dispose_input_cookie_request request; 2823620737cSbeveloper consumer_dispose_input_cookie_reply reply; 2830caff283Sbeveloper QueryPort(node.port, CONSUMER_DISPOSE_INPUT_COOKIE, &request, sizeof(request), &reply, sizeof(reply)); 2843620737cSbeveloper 2853620737cSbeveloper return result; 2863620737cSbeveloper } 2873620737cSbeveloper 2883620737cSbeveloper status_t 2894d2d96e0Sbeveloper BMediaRosterEx::GetAllInputs(BBufferConsumer *node, List<media_input> *list) 2904d2d96e0Sbeveloper { 2914d2d96e0Sbeveloper int32 cookie; 2924d2d96e0Sbeveloper status_t result; 2934d2d96e0Sbeveloper 2944d2d96e0Sbeveloper PRINT(4, "BMediaRosterEx::GetAllInputs() (by pointer) node %ld, port %ld\n", node->ID(), node->ControlPort()); 2954d2d96e0Sbeveloper 2964d2d96e0Sbeveloper result = B_OK; 2974d2d96e0Sbeveloper cookie = 0; 2984d2d96e0Sbeveloper list->MakeEmpty(); 2994d2d96e0Sbeveloper for (;;) { 3004d2d96e0Sbeveloper media_input input; 3014d2d96e0Sbeveloper if (B_OK != node->GetNextInput(&cookie, &input)) 3024d2d96e0Sbeveloper break; 3034d2d96e0Sbeveloper if (!list->Insert(input)) { 3044d2d96e0Sbeveloper ERROR("GetAllInputs: list->Insert failed\n"); 3054d2d96e0Sbeveloper result = B_ERROR; 3064d2d96e0Sbeveloper } 3074d2d96e0Sbeveloper #if DEBUG >= 3 3084d2d96e0Sbeveloper PRINT(3," next cookie %ld, ", cookie); 3094d2d96e0Sbeveloper PRINT_INPUT("input ", input); 3104d2d96e0Sbeveloper #endif 3114d2d96e0Sbeveloper } 3124d2d96e0Sbeveloper node->DisposeInputCookie(cookie); 3134d2d96e0Sbeveloper return result; 3144d2d96e0Sbeveloper } 3154d2d96e0Sbeveloper 3164d2d96e0Sbeveloper status_t 3178b04ffc1Sbeveloper BMediaRosterEx::PublishOutputs(const media_node & node, List<media_output> *list) 3183620737cSbeveloper { 3193620737cSbeveloper server_publish_outputs_request request; 3203620737cSbeveloper server_publish_outputs_reply reply; 3213620737cSbeveloper media_output *output; 3223620737cSbeveloper media_output *outputs; 3233620737cSbeveloper int32 count; 324a7b41a96Sbeveloper status_t rv; 3253620737cSbeveloper 32676669a29Sbeveloper count = list->CountItems(); 3273620737cSbeveloper TRACE("PublishOutputs: publishing %ld\n", count); 3283620737cSbeveloper 3293620737cSbeveloper request.node = node; 3303620737cSbeveloper request.count = count; 3313620737cSbeveloper if (count > MAX_OUTPUTS) { 3323620737cSbeveloper void *start_addr; 3333620737cSbeveloper size_t size; 33440f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_output)); 3353620737cSbeveloper request.area = create_area("publish outputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 3363620737cSbeveloper if (request.area < B_OK) { 3375ac4fbd7Sbeveloper ERROR("PublishOutputs: failed to create area, %#lx\n", request.area); 3383620737cSbeveloper return (status_t)request.area; 3393620737cSbeveloper } 3403620737cSbeveloper outputs = static_cast<media_output *>(start_addr); 3413620737cSbeveloper } else { 3423620737cSbeveloper request.area = -1; 3433620737cSbeveloper outputs = request.outputs; 3443620737cSbeveloper } 34576669a29Sbeveloper TRACE("PublishOutputs: area %ld\n", request.area); 3463620737cSbeveloper 34776669a29Sbeveloper int i; 34876669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&output); i++) { 34976669a29Sbeveloper ASSERT(i < count); 3503620737cSbeveloper outputs[i] = *output; 3513620737cSbeveloper } 3523620737cSbeveloper 353a7b41a96Sbeveloper rv = QueryServer(SERVER_PUBLISH_OUTPUTS, &request, sizeof(request), &reply, sizeof(reply)); 354a7b41a96Sbeveloper 355a7b41a96Sbeveloper if (request.area != -1) 356a7b41a96Sbeveloper delete_area(request.area); 357a7b41a96Sbeveloper 358a7b41a96Sbeveloper return rv; 3593620737cSbeveloper } 3603620737cSbeveloper 3613620737cSbeveloper status_t 3628b04ffc1Sbeveloper BMediaRosterEx::PublishInputs(const media_node & node, List<media_input> *list) 3633620737cSbeveloper { 3643620737cSbeveloper server_publish_inputs_request request; 3653620737cSbeveloper server_publish_inputs_reply reply; 3663620737cSbeveloper media_input *input; 3673620737cSbeveloper media_input *inputs; 3683620737cSbeveloper int32 count; 369a7b41a96Sbeveloper status_t rv; 3703620737cSbeveloper 37176669a29Sbeveloper count = list->CountItems(); 3723620737cSbeveloper TRACE("PublishInputs: publishing %ld\n", count); 3733620737cSbeveloper 3743620737cSbeveloper request.node = node; 3753620737cSbeveloper request.count = count; 3763620737cSbeveloper if (count > MAX_INPUTS) { 3773620737cSbeveloper void *start_addr; 3783620737cSbeveloper size_t size; 37940f36b03Sbeveloper size = ROUND_UP_TO_PAGE(count * sizeof(media_input)); 3803620737cSbeveloper request.area = create_area("publish inputs", &start_addr, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 3813620737cSbeveloper if (request.area < B_OK) { 3825ac4fbd7Sbeveloper ERROR("PublishInputs: failed to create area, %#lx\n", request.area); 3833620737cSbeveloper return (status_t)request.area; 3843620737cSbeveloper } 3853620737cSbeveloper inputs = static_cast<media_input *>(start_addr); 3863620737cSbeveloper } else { 3873620737cSbeveloper request.area = -1; 3883620737cSbeveloper inputs = request.inputs; 3893620737cSbeveloper } 39076669a29Sbeveloper TRACE("PublishInputs: area %ld\n", request.area); 3913620737cSbeveloper 39276669a29Sbeveloper int i; 39376669a29Sbeveloper for (i = 0, list->Rewind(); list->GetNext(&input); i++) { 39476669a29Sbeveloper ASSERT(i < count); 3953620737cSbeveloper inputs[i] = *input; 3963620737cSbeveloper } 3973620737cSbeveloper 398a7b41a96Sbeveloper rv = QueryServer(SERVER_PUBLISH_INPUTS, &request, sizeof(request), &reply, sizeof(reply)); 399a7b41a96Sbeveloper 400a7b41a96Sbeveloper if (request.area != -1) 401a7b41a96Sbeveloper delete_area(request.area); 402a7b41a96Sbeveloper 403a7b41a96Sbeveloper return rv; 4043620737cSbeveloper } 4053620737cSbeveloper 40652a38012Sejakowatz /************************************************************* 40752a38012Sejakowatz * public BMediaRoster 40852a38012Sejakowatz *************************************************************/ 40952a38012Sejakowatz 41052a38012Sejakowatz status_t 41152a38012Sejakowatz BMediaRoster::GetVideoInput(media_node * out_node) 41252a38012Sejakowatz { 41352a38012Sejakowatz CALLED(); 4148b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(VIDEO_INPUT, out_node); 41552a38012Sejakowatz } 41652a38012Sejakowatz 41752a38012Sejakowatz 41852a38012Sejakowatz status_t 41952a38012Sejakowatz BMediaRoster::GetAudioInput(media_node * out_node) 42052a38012Sejakowatz { 42152a38012Sejakowatz CALLED(); 4228b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_INPUT, out_node); 42352a38012Sejakowatz } 42452a38012Sejakowatz 42552a38012Sejakowatz 42652a38012Sejakowatz status_t 42752a38012Sejakowatz BMediaRoster::GetVideoOutput(media_node * out_node) 42852a38012Sejakowatz { 42952a38012Sejakowatz CALLED(); 4308b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(VIDEO_OUTPUT, out_node); 43152a38012Sejakowatz } 43252a38012Sejakowatz 43352a38012Sejakowatz 43452a38012Sejakowatz status_t 43552a38012Sejakowatz BMediaRoster::GetAudioMixer(media_node * out_node) 43652a38012Sejakowatz { 43752a38012Sejakowatz CALLED(); 4388b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_MIXER, out_node); 43952a38012Sejakowatz } 44052a38012Sejakowatz 44152a38012Sejakowatz 44252a38012Sejakowatz status_t 44352a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node) 44452a38012Sejakowatz { 44552a38012Sejakowatz CALLED(); 4468b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT, out_node); 44752a38012Sejakowatz } 44852a38012Sejakowatz 44952a38012Sejakowatz 45052a38012Sejakowatz status_t 45152a38012Sejakowatz BMediaRoster::GetAudioOutput(media_node * out_node, 45252a38012Sejakowatz int32 * out_input_id, 45352a38012Sejakowatz BString * out_input_name) 45452a38012Sejakowatz { 45552a38012Sejakowatz CALLED(); 4568b04ffc1Sbeveloper return MediaRosterEx(this)->GetNode(AUDIO_OUTPUT_EX, out_node, out_input_id, out_input_name); 45752a38012Sejakowatz } 45852a38012Sejakowatz 45952a38012Sejakowatz 46052a38012Sejakowatz status_t 46152a38012Sejakowatz BMediaRoster::GetTimeSource(media_node * out_node) 46252a38012Sejakowatz { 46352a38012Sejakowatz CALLED(); 46486bce45bSbeveloper status_t rv; 46586bce45bSbeveloper 46686bce45bSbeveloper // XXX need to do this in a nicer way. 46786bce45bSbeveloper 46886bce45bSbeveloper rv = MediaRosterEx(this)->GetNode(TIME_SOURCE, out_node); 46986bce45bSbeveloper if (rv != B_OK) 47086bce45bSbeveloper return rv; 47186bce45bSbeveloper 47286bce45bSbeveloper // We don't do reference counting for timesources, that's why we 47386bce45bSbeveloper // release the node immediately. 47486bce45bSbeveloper ReleaseNode(*out_node); 47586bce45bSbeveloper 47686bce45bSbeveloper // we need to remember to not use this node with server side reference counting 47786bce45bSbeveloper out_node->kind |= NODE_KIND_NO_REFCOUNTING; 47886bce45bSbeveloper 47986bce45bSbeveloper return B_OK; 48052a38012Sejakowatz } 48152a38012Sejakowatz 48252a38012Sejakowatz 48352a38012Sejakowatz status_t 48452a38012Sejakowatz BMediaRoster::SetVideoInput(const media_node & producer) 48552a38012Sejakowatz { 48652a38012Sejakowatz CALLED(); 4878b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, &producer); 48852a38012Sejakowatz } 48952a38012Sejakowatz 49052a38012Sejakowatz 49152a38012Sejakowatz status_t 49252a38012Sejakowatz BMediaRoster::SetVideoInput(const dormant_node_info & producer) 49352a38012Sejakowatz { 49452a38012Sejakowatz CALLED(); 4958b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_INPUT, NULL, &producer); 49652a38012Sejakowatz } 49752a38012Sejakowatz 49852a38012Sejakowatz 49952a38012Sejakowatz status_t 50052a38012Sejakowatz BMediaRoster::SetAudioInput(const media_node & producer) 50152a38012Sejakowatz { 50252a38012Sejakowatz CALLED(); 5038b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, &producer); 50452a38012Sejakowatz } 50552a38012Sejakowatz 50652a38012Sejakowatz 50752a38012Sejakowatz status_t 50852a38012Sejakowatz BMediaRoster::SetAudioInput(const dormant_node_info & producer) 50952a38012Sejakowatz { 51052a38012Sejakowatz CALLED(); 5118b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_INPUT, NULL, &producer); 51252a38012Sejakowatz } 51352a38012Sejakowatz 51452a38012Sejakowatz 51552a38012Sejakowatz status_t 51652a38012Sejakowatz BMediaRoster::SetVideoOutput(const media_node & consumer) 51752a38012Sejakowatz { 51852a38012Sejakowatz CALLED(); 5198b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, &consumer); 52052a38012Sejakowatz } 52152a38012Sejakowatz 52252a38012Sejakowatz 52352a38012Sejakowatz status_t 52452a38012Sejakowatz BMediaRoster::SetVideoOutput(const dormant_node_info & consumer) 52552a38012Sejakowatz { 52652a38012Sejakowatz CALLED(); 5278b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(VIDEO_OUTPUT, NULL, &consumer); 52852a38012Sejakowatz } 52952a38012Sejakowatz 53052a38012Sejakowatz 53152a38012Sejakowatz status_t 53252a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_node & consumer) 53352a38012Sejakowatz { 53452a38012Sejakowatz CALLED(); 5358b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, &consumer); 53652a38012Sejakowatz } 53752a38012Sejakowatz 53852a38012Sejakowatz 53952a38012Sejakowatz status_t 54052a38012Sejakowatz BMediaRoster::SetAudioOutput(const media_input & input_to_output) 54152a38012Sejakowatz { 54252a38012Sejakowatz CALLED(); 5438b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, NULL, &input_to_output); 54452a38012Sejakowatz } 54552a38012Sejakowatz 54652a38012Sejakowatz 54752a38012Sejakowatz status_t 54852a38012Sejakowatz BMediaRoster::SetAudioOutput(const dormant_node_info & consumer) 54952a38012Sejakowatz { 55052a38012Sejakowatz CALLED(); 5518b04ffc1Sbeveloper return MediaRosterEx(this)->SetNode(AUDIO_OUTPUT, NULL, &consumer); 55252a38012Sejakowatz } 55352a38012Sejakowatz 55452a38012Sejakowatz 55552a38012Sejakowatz status_t 55652a38012Sejakowatz BMediaRoster::GetNodeFor(media_node_id node, 55752a38012Sejakowatz media_node * clone) 55852a38012Sejakowatz { 5599e9417d2Sbeveloper CALLED(); 5609e9417d2Sbeveloper if (clone == NULL) 5619e9417d2Sbeveloper return B_BAD_VALUE; 5629e9417d2Sbeveloper if (node <= 0) 5639e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 5649e9417d2Sbeveloper 5659e9417d2Sbeveloper server_get_node_for_request request; 5669e9417d2Sbeveloper server_get_node_for_reply reply; 5679e9417d2Sbeveloper status_t rv; 5689e9417d2Sbeveloper 5699e9417d2Sbeveloper request.nodeid = node; 5709e9417d2Sbeveloper request.team = team; 5719e9417d2Sbeveloper 5729e9417d2Sbeveloper rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply)); 5739e9417d2Sbeveloper if (rv != B_OK) 5749e9417d2Sbeveloper return rv; 5759e9417d2Sbeveloper 5769e9417d2Sbeveloper *clone = reply.clone; 5779e9417d2Sbeveloper return B_OK; 57852a38012Sejakowatz } 57952a38012Sejakowatz 58052a38012Sejakowatz 58152a38012Sejakowatz status_t 58252a38012Sejakowatz BMediaRoster::GetSystemTimeSource(media_node * clone) 58352a38012Sejakowatz { 58452a38012Sejakowatz CALLED(); 58586bce45bSbeveloper status_t rv; 58686bce45bSbeveloper 58786bce45bSbeveloper // XXX need to do this in a nicer way. 58886bce45bSbeveloper 58986bce45bSbeveloper rv = MediaRosterEx(this)->GetNode(SYSTEM_TIME_SOURCE, clone); 59086bce45bSbeveloper if (rv != B_OK) 59186bce45bSbeveloper return rv; 59286bce45bSbeveloper 59386bce45bSbeveloper // We don't do reference counting for timesources, that's why we 59486bce45bSbeveloper // release the node immediately. 59586bce45bSbeveloper ReleaseNode(*clone); 59686bce45bSbeveloper 59786bce45bSbeveloper // we need to remember to not use this node with server side reference counting 59886bce45bSbeveloper clone->kind |= NODE_KIND_NO_REFCOUNTING; 59986bce45bSbeveloper 60086bce45bSbeveloper return B_OK; 60152a38012Sejakowatz } 60252a38012Sejakowatz 60352a38012Sejakowatz 60452a38012Sejakowatz status_t 60552a38012Sejakowatz BMediaRoster::ReleaseNode(const media_node & node) 60652a38012Sejakowatz { 6079e9417d2Sbeveloper CALLED(); 60840f36b03Sbeveloper if (IS_INVALID_NODE(node)) 6099e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 61052a38012Sejakowatz 61186bce45bSbeveloper if (node.kind & NODE_KIND_NO_REFCOUNTING) { 61286bce45bSbeveloper printf("BMediaRoster::ReleaseNode, trying to release reference counting disabled timesource, node %ld, port %ld, team %ld\n", node.node, node.port, team); 61386bce45bSbeveloper return B_OK; 61486bce45bSbeveloper } 61586bce45bSbeveloper 6169e9417d2Sbeveloper server_release_node_request request; 6179e9417d2Sbeveloper server_release_node_reply reply; 618cf4e2277Sbeveloper status_t rv; 6199e9417d2Sbeveloper 6209e9417d2Sbeveloper request.node = node; 6219e9417d2Sbeveloper request.team = team; 6229e9417d2Sbeveloper 62360f15390Sbeveloper TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n", node.node, node.port, team); 624cf4e2277Sbeveloper 625cf4e2277Sbeveloper rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, sizeof(reply)); 626cf4e2277Sbeveloper if (rv != B_OK) { 6275ac4fbd7Sbeveloper ERROR("BMediaRoster::ReleaseNode FAILED, node %ld, port %ld, team %ld!\n", node.node, node.port, team); 628cf4e2277Sbeveloper } 629cf4e2277Sbeveloper return rv; 6309e9417d2Sbeveloper } 63152a38012Sejakowatz 63252a38012Sejakowatz BTimeSource * 63352a38012Sejakowatz BMediaRoster::MakeTimeSourceFor(const media_node & for_node) 63452a38012Sejakowatz { 635f180ef79Sbeveloper // MakeTimeSourceFor() returns a BTimeSource object 636f180ef79Sbeveloper // corresponding to the specified node's time source. 637f180ef79Sbeveloper 638835140c8Sbeveloper CALLED(); 639f180ef79Sbeveloper 64092e575c1Sbeveloper if (IS_SYSTEM_TIMESOURCE(for_node)) { 641f180ef79Sbeveloper // special handling for the system time source 642f180ef79Sbeveloper TRACE("BMediaRoster::MakeTimeSourceFor, asked for system time source\n"); 643f180ef79Sbeveloper return MediaRosterEx(this)->MakeTimeSourceObject(NODE_SYSTEM_TIMESOURCE_ID); 644f180ef79Sbeveloper } 645f180ef79Sbeveloper 6465917dd5bSbeveloper if (IS_INVALID_NODE(for_node)) { 6475ac4fbd7Sbeveloper ERROR("BMediaRoster::MakeTimeSourceFor: for_node invalid, node %ld, port %ld, kinds 0x%lx\n", for_node.node, for_node.port, for_node.kind); 6485917dd5bSbeveloper return NULL; 6490e21b167Sbeveloper } 6500e21b167Sbeveloper 651f180ef79Sbeveloper TRACE("BMediaRoster::MakeTimeSourceFor: node %ld enter\n", for_node.node); 6525917dd5bSbeveloper 6535917dd5bSbeveloper node_get_timesource_request request; 6545917dd5bSbeveloper node_get_timesource_reply reply; 6555917dd5bSbeveloper BTimeSource *source; 6565917dd5bSbeveloper status_t rv; 6575917dd5bSbeveloper 65892e575c1Sbeveloper // ask the node to get it's current timesource id 6595917dd5bSbeveloper rv = QueryPort(for_node.port, NODE_GET_TIMESOURCE, &request, sizeof(request), &reply, sizeof(reply)); 6605917dd5bSbeveloper if (rv != B_OK) { 6615ac4fbd7Sbeveloper ERROR("BMediaRoster::MakeTimeSourceFor: request failed\n"); 6625917dd5bSbeveloper return NULL; 6635917dd5bSbeveloper } 6645917dd5bSbeveloper 6655917dd5bSbeveloper source = MediaRosterEx(this)->MakeTimeSourceObject(reply.timesource_id); 6665917dd5bSbeveloper 667f180ef79Sbeveloper TRACE("BMediaRoster::MakeTimeSourceFor: node %ld leave\n", for_node.node); 6685917dd5bSbeveloper 6695917dd5bSbeveloper return source; 6705917dd5bSbeveloper } 6715917dd5bSbeveloper 6725917dd5bSbeveloper BTimeSource * 6735917dd5bSbeveloper BMediaRosterEx::MakeTimeSourceObject(media_node_id timesource_id) 6745917dd5bSbeveloper { 6755917dd5bSbeveloper BTimeSource *source; 6765917dd5bSbeveloper media_node clone; 6775917dd5bSbeveloper status_t rv; 6785917dd5bSbeveloper 6795917dd5bSbeveloper rv = GetNodeFor(timesource_id, &clone); 6805917dd5bSbeveloper if (rv != B_OK) { 6815ac4fbd7Sbeveloper ERROR("BMediaRosterEx::MakeTimeSourceObject: GetNodeFor failed\n"); 6825917dd5bSbeveloper return NULL; 6835917dd5bSbeveloper } 6845917dd5bSbeveloper 6855917dd5bSbeveloper source = _TimeSourceObjectManager->GetTimeSource(clone); 6865917dd5bSbeveloper if (source == NULL) { 6875ac4fbd7Sbeveloper ERROR("BMediaRosterEx::MakeTimeSourceObject: GetTimeSource failed\n"); 6885917dd5bSbeveloper return NULL; 6895917dd5bSbeveloper } 6905917dd5bSbeveloper 69192e575c1Sbeveloper // XXX release? 69292e575c1Sbeveloper ReleaseNode(clone); 693287f7492Sbeveloper 694835140c8Sbeveloper return source; 69552a38012Sejakowatz } 69652a38012Sejakowatz 69752a38012Sejakowatz 69852a38012Sejakowatz status_t 69952a38012Sejakowatz BMediaRoster::Connect(const media_source & from, 70052a38012Sejakowatz const media_destination & to, 70152a38012Sejakowatz media_format * io_format, 70252a38012Sejakowatz media_output * out_output, 70352a38012Sejakowatz media_input * out_input) 70452a38012Sejakowatz { 705eae26d3dSbeveloper return BMediaRoster::Connect(from, to, io_format, out_output, out_input, 0); 706eae26d3dSbeveloper } 707eae26d3dSbeveloper 708eae26d3dSbeveloper 709eae26d3dSbeveloper status_t 710eae26d3dSbeveloper BMediaRoster::Connect(const media_source & from, 711eae26d3dSbeveloper const media_destination & to, 712eae26d3dSbeveloper media_format * io_format, 713eae26d3dSbeveloper media_output * out_output, 714eae26d3dSbeveloper media_input * out_input, 715eae26d3dSbeveloper uint32 in_flags, 716eae26d3dSbeveloper void * _reserved) 717eae26d3dSbeveloper { 71852a38012Sejakowatz CALLED(); 71952a38012Sejakowatz if (io_format == NULL || out_output == NULL || out_input == NULL) 72052a38012Sejakowatz return B_BAD_VALUE; 72140f36b03Sbeveloper if (IS_INVALID_SOURCE(from)) { 7225ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_source invalid\n"); 72352a38012Sejakowatz return B_MEDIA_BAD_SOURCE; 7249e9417d2Sbeveloper } 72540f36b03Sbeveloper if (IS_INVALID_DESTINATION(to)) { 7265ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: media_destination invalid\n"); 72752a38012Sejakowatz return B_MEDIA_BAD_DESTINATION; 7289e9417d2Sbeveloper } 72952a38012Sejakowatz 73052a38012Sejakowatz status_t rv; 7318c6a6096Sbeveloper producer_format_proposal_request request1; 7328c6a6096Sbeveloper producer_format_proposal_reply reply1; 73352a38012Sejakowatz 73469983609Sbeveloper PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::FormatProposal with format ", *io_format); 73569983609Sbeveloper 73652a38012Sejakowatz // BBufferProducer::FormatProposal 7378c6a6096Sbeveloper request1.output = from; 7388c6a6096Sbeveloper request1.format = *io_format; 7398c6a6096Sbeveloper rv = QueryPort(from.port, PRODUCER_FORMAT_PROPOSAL, &request1, sizeof(request1), &reply1, sizeof(reply1)); 7408c6a6096Sbeveloper if (rv != B_OK) { 7415ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted after BBufferProducer::FormatProposal, status = %#lx\n",rv); 74252a38012Sejakowatz return rv; 74352a38012Sejakowatz } 7448c6a6096Sbeveloper // reply1.format now contains the format proposed by the producer 7458c6a6096Sbeveloper 7468c6a6096Sbeveloper consumer_accept_format_request request2; 7478c6a6096Sbeveloper consumer_accept_format_reply reply2; 7488c6a6096Sbeveloper 74969983609Sbeveloper PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::AcceptFormat with format ", reply1.format); 75069983609Sbeveloper 7518c6a6096Sbeveloper // BBufferConsumer::AcceptFormat 7528c6a6096Sbeveloper request2.dest = to; 7538c6a6096Sbeveloper request2.format = reply1.format; 7548c6a6096Sbeveloper rv = QueryPort(to.port, CONSUMER_ACCEPT_FORMAT, &request2, sizeof(request2), &reply2, sizeof(reply2)); 7558c6a6096Sbeveloper if (rv != B_OK) { 7565ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted after BBufferConsumer::AcceptFormat, status = %#lx\n",rv); 7578c6a6096Sbeveloper return rv; 7588c6a6096Sbeveloper } 7598c6a6096Sbeveloper // reply2.format now contains the format accepted by the consumer 7608c6a6096Sbeveloper 7618c6a6096Sbeveloper // BBufferProducer::PrepareToConnect 7628c6a6096Sbeveloper producer_prepare_to_connect_request request3; 7638c6a6096Sbeveloper producer_prepare_to_connect_reply reply3; 7648c6a6096Sbeveloper 76569983609Sbeveloper PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::PrepareToConnect with format", reply2.format); 76669983609Sbeveloper 7678c6a6096Sbeveloper request3.source = from; 7688c6a6096Sbeveloper request3.destination = to; 7698c6a6096Sbeveloper request3.format = reply2.format; 7708c6a6096Sbeveloper strcpy(request3.name, "XXX some default name"); // XXX fix this 7718c6a6096Sbeveloper rv = QueryPort(from.port, PRODUCER_PREPARE_TO_CONNECT, &request3, sizeof(request3), &reply3, sizeof(reply3)); 7728c6a6096Sbeveloper if (rv != B_OK) { 7735ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted after BBufferProducer::PrepareToConnect, status = %#lx\n",rv); 7748c6a6096Sbeveloper return rv; 7758c6a6096Sbeveloper } 7768c6a6096Sbeveloper // reply3.format is still our pretty media format 7778c6a6096Sbeveloper // reply3.out_source the real source to be used for the connection 7788c6a6096Sbeveloper // reply3.name the name BBufferConsumer::Connected will see in the outInput->name argument 7798c6a6096Sbeveloper 78069983609Sbeveloper 78169983609Sbeveloper // find the output and input nodes 78269983609Sbeveloper // XXX isn't there a easier way? 78369983609Sbeveloper media_node sourcenode; 78469983609Sbeveloper media_node destnode; 78569983609Sbeveloper GetNodeFor(NodeIDFor(from.port), &sourcenode); 78669983609Sbeveloper GetNodeFor(NodeIDFor(to.port), &destnode); 78769983609Sbeveloper ReleaseNode(sourcenode); 78869983609Sbeveloper ReleaseNode(destnode); 78969983609Sbeveloper 7908c6a6096Sbeveloper // BBufferConsumer::Connected 7918c6a6096Sbeveloper consumer_connected_request request4; 7928c6a6096Sbeveloper consumer_connected_reply reply4; 7938c6a6096Sbeveloper status_t con_status; 7948c6a6096Sbeveloper 79569983609Sbeveloper PRINT_FORMAT("BMediaRoster::Connect calling BBufferConsumer::Connected with format ", reply3.format); 79669983609Sbeveloper 79769983609Sbeveloper request4.input.node = destnode; 79869983609Sbeveloper request4.input.source = reply3.out_source; 79969983609Sbeveloper request4.input.destination = to; 80069983609Sbeveloper request4.input.format = reply3.format; 80169983609Sbeveloper strcpy(request4.input.name, reply3.name); 80269983609Sbeveloper 8038c6a6096Sbeveloper con_status = QueryPort(to.port, CONSUMER_CONNECTED, &request4, sizeof(request4), &reply4, sizeof(reply4)); 8048c6a6096Sbeveloper if (con_status != B_OK) { 8055ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborting after BBufferConsumer::Connected, status = %#lx\n",con_status); 8068c6a6096Sbeveloper // we do NOT return here! 8078c6a6096Sbeveloper } 8088c6a6096Sbeveloper // con_status contains the status code to be supplied to BBufferProducer::Connect's status argument 8098c6a6096Sbeveloper // reply4.input contains the media_input that describes the connection from the consumer point of view 8108c6a6096Sbeveloper 8118c6a6096Sbeveloper // BBufferProducer::Connect 8128c6a6096Sbeveloper producer_connect_request request5; 8138c6a6096Sbeveloper producer_connect_reply reply5; 8148c6a6096Sbeveloper 81569983609Sbeveloper PRINT_FORMAT("BMediaRoster::Connect calling BBufferProducer::Connect with format ", reply4.input.format); 81669983609Sbeveloper 8178c6a6096Sbeveloper request5.error = con_status; 8188c6a6096Sbeveloper request5.source = reply3.out_source; 8198c6a6096Sbeveloper request5.destination = reply4.input.destination; 82069983609Sbeveloper request5.format = reply4.input.format; 8218c6a6096Sbeveloper strcpy(request5.name, reply4.input.name); 8220caff283Sbeveloper rv = QueryPort(reply4.input.source.port, PRODUCER_CONNECT, &request5, sizeof(request5), &reply5, sizeof(reply5)); 8238c6a6096Sbeveloper if (con_status != B_OK) { 8245ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted\n"); 8258c6a6096Sbeveloper return con_status; 8268c6a6096Sbeveloper } 8278c6a6096Sbeveloper if (rv != B_OK) { 8285ac4fbd7Sbeveloper ERROR("BMediaRoster::Connect: aborted after BBufferProducer::Connect, status = %#lx\n",rv); 8298c6a6096Sbeveloper return rv; 8308c6a6096Sbeveloper } 8318c6a6096Sbeveloper // reply5.name contains the name assigned to the connection by the producer 8328c6a6096Sbeveloper 8338c6a6096Sbeveloper // initilize connection info 83469983609Sbeveloper *io_format = reply4.input.format; 8358c6a6096Sbeveloper *out_input = reply4.input; 8368c6a6096Sbeveloper out_output->node = sourcenode; 8378c6a6096Sbeveloper out_output->source = reply4.input.source; 8388c6a6096Sbeveloper out_output->destination = reply4.input.destination; 8398c6a6096Sbeveloper out_output->format = reply4.input.format; 8408c6a6096Sbeveloper strcpy(out_output->name, reply5.name); 8418c6a6096Sbeveloper 8428c6a6096Sbeveloper // the connection is now made 84369983609Sbeveloper printf("BMediaRoster::Connect connection established!\n"); 84469983609Sbeveloper PRINT_FORMAT(" format", *io_format); 84569983609Sbeveloper PRINT_INPUT(" input", *out_input); 84669983609Sbeveloper PRINT_OUTPUT(" output", *out_output); 8478c6a6096Sbeveloper 8488c6a6096Sbeveloper // XXX register connection with server 8499e9417d2Sbeveloper // XXX we should just send a notification, instead of republishing all endpoints 85076669a29Sbeveloper List<media_output> outlist; 85176669a29Sbeveloper List<media_input> inlist; 8528b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllOutputs(out_output->node , &outlist)) 8538b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(out_output->node , &outlist); 8548b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllInputs(out_input->node , &inlist)) 8558b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(out_input->node, &inlist); 8568c6a6096Sbeveloper 8578c6a6096Sbeveloper 8588c6a6096Sbeveloper // XXX if (mute) BBufferProducer::EnableOutput(false) 8599e9417d2Sbeveloper if (in_flags & B_CONNECT_MUTED) { 8609e9417d2Sbeveloper } 8618c6a6096Sbeveloper 8628c6a6096Sbeveloper 8639e9417d2Sbeveloper // send a notification 8649e9417d2Sbeveloper BPrivate::media::notifications::ConnectionMade(*out_input, *out_output, *io_format); 8659e9417d2Sbeveloper 8668c6a6096Sbeveloper return B_OK; 8678c6a6096Sbeveloper }; 86852a38012Sejakowatz 86952a38012Sejakowatz 87052a38012Sejakowatz status_t 8719e9417d2Sbeveloper BMediaRoster::Disconnect(media_node_id source_nodeid, 87252a38012Sejakowatz const media_source & source, 8739e9417d2Sbeveloper media_node_id destination_nodeid, 87452a38012Sejakowatz const media_destination & destination) 87552a38012Sejakowatz { 8769e9417d2Sbeveloper CALLED(); 87740f36b03Sbeveloper if (IS_INVALID_NODEID(source_nodeid)) { 8785ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: source media_node_id invalid\n"); 8799e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 8809e9417d2Sbeveloper } 88140f36b03Sbeveloper if (IS_INVALID_NODEID(destination_nodeid)) { 8825ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: destination media_node_id invalid\n"); 8839e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 8849e9417d2Sbeveloper } 88540f36b03Sbeveloper if (IS_INVALID_SOURCE(source)) { 8865ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_source invalid\n"); 8879e9417d2Sbeveloper return B_MEDIA_BAD_SOURCE; 8889e9417d2Sbeveloper } 88940f36b03Sbeveloper if (IS_INVALID_DESTINATION(destination)) { 8905ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: media_destination invalid\n"); 8919e9417d2Sbeveloper return B_MEDIA_BAD_DESTINATION; 8929e9417d2Sbeveloper } 8939e9417d2Sbeveloper 8949e9417d2Sbeveloper producer_disconnect_request request2; 8959e9417d2Sbeveloper producer_disconnect_reply reply2; 8969e9417d2Sbeveloper consumer_disconnected_request request1; 8979e9417d2Sbeveloper consumer_disconnected_reply reply1; 8989e9417d2Sbeveloper status_t rv1, rv2; 8999e9417d2Sbeveloper 9009e9417d2Sbeveloper // XXX we should ask the server if this connection really exists 9019e9417d2Sbeveloper 9029e9417d2Sbeveloper request1.source = source; 9039e9417d2Sbeveloper request1.destination = destination; 9049e9417d2Sbeveloper request2.source = source; 9059e9417d2Sbeveloper request2.destination = destination; 9069e9417d2Sbeveloper 9079e9417d2Sbeveloper rv1 = QueryPort(source.port, PRODUCER_DISCONNECT, &request1, sizeof(request1), &reply1, sizeof(reply1)); 9089e9417d2Sbeveloper rv2 = QueryPort(destination.port, CONSUMER_DISCONNECTED, &request2, sizeof(request2), &reply2, sizeof(reply2)); 9099e9417d2Sbeveloper 9109e9417d2Sbeveloper // XXX unregister connection with server 9119e9417d2Sbeveloper // XXX we should just send a notification, instead of republishing all endpoints 91276669a29Sbeveloper List<media_output> outlist; 91376669a29Sbeveloper List<media_input> inlist; 9149e9417d2Sbeveloper media_node sourcenode; 9159e9417d2Sbeveloper media_node destnode; 9169e9417d2Sbeveloper if (B_OK == GetNodeFor(source_nodeid, &sourcenode)) { 9178b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllOutputs(sourcenode , &outlist)) 9188b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(sourcenode , &outlist); 9199e9417d2Sbeveloper ReleaseNode(sourcenode); 9204f09fa2fSbeveloper } else { 9215ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: source GetNodeFor failed\n"); 9224f09fa2fSbeveloper } 9239e9417d2Sbeveloper if (B_OK == GetNodeFor(destination_nodeid, &destnode)) { 9248b04ffc1Sbeveloper if (B_OK == MediaRosterEx(this)->GetAllInputs(destnode , &inlist)) 9258b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(destnode, &inlist); 9269e9417d2Sbeveloper ReleaseNode(destnode); 9274f09fa2fSbeveloper } else { 9285ac4fbd7Sbeveloper ERROR("BMediaRoster::Disconnect: dest GetNodeFor failed\n"); 9294f09fa2fSbeveloper } 9309e9417d2Sbeveloper 9319e9417d2Sbeveloper 9329e9417d2Sbeveloper // send a notification 9339e9417d2Sbeveloper BPrivate::media::notifications::ConnectionBroken(source, destination); 9349e9417d2Sbeveloper 9359e9417d2Sbeveloper return (rv1 != B_OK || rv2 != B_OK) ? B_ERROR : B_OK; 93652a38012Sejakowatz } 93752a38012Sejakowatz 93852a38012Sejakowatz 93952a38012Sejakowatz status_t 94052a38012Sejakowatz BMediaRoster::StartNode(const media_node & node, 94152a38012Sejakowatz bigtime_t at_performance_time) 94252a38012Sejakowatz { 94352a38012Sejakowatz CALLED(); 9449e9417d2Sbeveloper if (node.node <= 0) 94552a38012Sejakowatz return B_MEDIA_BAD_NODE; 94652a38012Sejakowatz 94760f15390Sbeveloper TRACE("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node, at_performance_time); 9480e21b167Sbeveloper 9496396865dSbeveloper node_start_command command; 9506396865dSbeveloper command.performance_time = at_performance_time; 95152a38012Sejakowatz 9526396865dSbeveloper return SendToPort(node.port, NODE_START, &command, sizeof(command)); 95352a38012Sejakowatz } 95452a38012Sejakowatz 95552a38012Sejakowatz 95652a38012Sejakowatz status_t 95752a38012Sejakowatz BMediaRoster::StopNode(const media_node & node, 95852a38012Sejakowatz bigtime_t at_performance_time, 95952a38012Sejakowatz bool immediate) 96052a38012Sejakowatz { 96152a38012Sejakowatz CALLED(); 96240f36b03Sbeveloper if (IS_INVALID_NODE(node)) 96352a38012Sejakowatz return B_MEDIA_BAD_NODE; 96452a38012Sejakowatz 96560f15390Sbeveloper TRACE("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node, at_performance_time, immediate ? "NOW" : ""); 9660e21b167Sbeveloper 9676396865dSbeveloper node_stop_command command; 9686396865dSbeveloper command.performance_time = at_performance_time; 9696396865dSbeveloper command.immediate = immediate; 97052a38012Sejakowatz 9716396865dSbeveloper return SendToPort(node.port, NODE_STOP, &command, sizeof(command)); 97252a38012Sejakowatz } 97352a38012Sejakowatz 97452a38012Sejakowatz 97552a38012Sejakowatz status_t 97652a38012Sejakowatz BMediaRoster::SeekNode(const media_node & node, 97752a38012Sejakowatz bigtime_t to_media_time, 97852a38012Sejakowatz bigtime_t at_performance_time) 97952a38012Sejakowatz { 98052a38012Sejakowatz CALLED(); 98140f36b03Sbeveloper if (IS_INVALID_NODE(node)) 98252a38012Sejakowatz return B_MEDIA_BAD_NODE; 98352a38012Sejakowatz 98460f15390Sbeveloper TRACE("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n", node.node, at_performance_time, to_media_time); 9850e21b167Sbeveloper 9866396865dSbeveloper node_seek_command command; 9876396865dSbeveloper command.media_time = to_media_time; 9886396865dSbeveloper command.performance_time = at_performance_time; 98952a38012Sejakowatz 9906396865dSbeveloper return SendToPort(node.port, NODE_SEEK, &command, sizeof(command)); 99152a38012Sejakowatz } 99252a38012Sejakowatz 99352a38012Sejakowatz 99452a38012Sejakowatz status_t 99552a38012Sejakowatz BMediaRoster::StartTimeSource(const media_node & node, 99652a38012Sejakowatz bigtime_t at_real_time) 99752a38012Sejakowatz { 99852a38012Sejakowatz CALLED(); 99960f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 100060f15390Sbeveloper // XXX debug this 10015ac4fbd7Sbeveloper //ERROR("BMediaRoster::StartTimeSource node %ld is system timesource\n", node.node); 100260f15390Sbeveloper return B_OK; 100360f15390Sbeveloper } 100492e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 100592e575c1Sbeveloper // // XXX debug this 100692e575c1Sbeveloper // ERROR("BMediaRoster::StartTimeSource node %ld is shadow timesource\n", node.node); 100792e575c1Sbeveloper // return B_OK; 100892e575c1Sbeveloper // } 100940f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 10105ac4fbd7Sbeveloper ERROR("BMediaRoster::StartTimeSource node %ld invalid\n", node.node); 101152a38012Sejakowatz return B_MEDIA_BAD_NODE; 10120e21b167Sbeveloper } 10130e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 10145ac4fbd7Sbeveloper ERROR("BMediaRoster::StartTimeSource node %ld is no timesource\n", node.node); 101552a38012Sejakowatz return B_MEDIA_BAD_NODE; 10160e21b167Sbeveloper } 10170e21b167Sbeveloper 101860f15390Sbeveloper TRACE("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node, at_real_time); 101952a38012Sejakowatz 102052a38012Sejakowatz BTimeSource::time_source_op_info msg; 102152a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_START; 102252a38012Sejakowatz msg.real_time = at_real_time; 102352a38012Sejakowatz 102452a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 102552a38012Sejakowatz } 102652a38012Sejakowatz 102752a38012Sejakowatz 102852a38012Sejakowatz status_t 102952a38012Sejakowatz BMediaRoster::StopTimeSource(const media_node & node, 103052a38012Sejakowatz bigtime_t at_real_time, 103152a38012Sejakowatz bool immediate) 103252a38012Sejakowatz { 103352a38012Sejakowatz CALLED(); 103460f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 103560f15390Sbeveloper // XXX debug this 10365ac4fbd7Sbeveloper //ERROR("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node); 103760f15390Sbeveloper return B_OK; 103860f15390Sbeveloper } 103992e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 104092e575c1Sbeveloper // // XXX debug this 104192e575c1Sbeveloper // ERROR("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node); 104292e575c1Sbeveloper // return B_OK; 104392e575c1Sbeveloper // } 104440f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 10455ac4fbd7Sbeveloper ERROR("BMediaRoster::StopTimeSource node %ld invalid\n", node.node); 104652a38012Sejakowatz return B_MEDIA_BAD_NODE; 10470e21b167Sbeveloper } 10480e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 10495ac4fbd7Sbeveloper ERROR("BMediaRoster::StopTimeSource node %ld is no timesource\n", node.node); 105052a38012Sejakowatz return B_MEDIA_BAD_NODE; 10510e21b167Sbeveloper } 10520e21b167Sbeveloper 105360f15390Sbeveloper TRACE("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n", node.node, at_real_time, immediate ? "NOW" : ""); 105452a38012Sejakowatz 105552a38012Sejakowatz BTimeSource::time_source_op_info msg; 105652a38012Sejakowatz msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY : BTimeSource::B_TIMESOURCE_STOP; 105752a38012Sejakowatz msg.real_time = at_real_time; 105852a38012Sejakowatz 105952a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 106052a38012Sejakowatz } 106152a38012Sejakowatz 106252a38012Sejakowatz 106352a38012Sejakowatz status_t 106452a38012Sejakowatz BMediaRoster::SeekTimeSource(const media_node & node, 106552a38012Sejakowatz bigtime_t to_performance_time, 106652a38012Sejakowatz bigtime_t at_real_time) 106752a38012Sejakowatz { 106852a38012Sejakowatz CALLED(); 106960f15390Sbeveloper if (IS_SYSTEM_TIMESOURCE(node)) { 107060f15390Sbeveloper // XXX debug this 10715ac4fbd7Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node); 107260f15390Sbeveloper // you can't seek the system time source, but 107360f15390Sbeveloper // returning B_ERROR would break StampTV 107460f15390Sbeveloper return B_OK; 107560f15390Sbeveloper } 107692e575c1Sbeveloper // if (IS_SHADOW_TIMESOURCE(node)) { 107792e575c1Sbeveloper // // XXX debug this 107892e575c1Sbeveloper // ERROR("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node); 107992e575c1Sbeveloper // return B_OK; 108092e575c1Sbeveloper // } 108140f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 10825ac4fbd7Sbeveloper ERROR("BMediaRoster::SeekTimeSource node %ld invalid\n", node.node); 108352a38012Sejakowatz return B_MEDIA_BAD_NODE; 10840e21b167Sbeveloper } 10850e21b167Sbeveloper if ((node.kind & B_TIME_SOURCE) == 0) { 10865ac4fbd7Sbeveloper ERROR("BMediaRoster::SeekTimeSource node %ld is no timesource\n", node.node); 108752a38012Sejakowatz return B_MEDIA_BAD_NODE; 10880e21b167Sbeveloper } 10890e21b167Sbeveloper 109060f15390Sbeveloper TRACE("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n", node.node, at_real_time, to_performance_time); 109152a38012Sejakowatz 109252a38012Sejakowatz BTimeSource::time_source_op_info msg; 109352a38012Sejakowatz msg.op = BTimeSource::B_TIMESOURCE_SEEK; 109452a38012Sejakowatz msg.real_time = at_real_time; 109552a38012Sejakowatz msg.performance_time = to_performance_time; 109652a38012Sejakowatz 109752a38012Sejakowatz return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); 109852a38012Sejakowatz } 109952a38012Sejakowatz 110052a38012Sejakowatz 110152a38012Sejakowatz status_t 110252a38012Sejakowatz BMediaRoster::SyncToNode(const media_node & node, 110352a38012Sejakowatz bigtime_t at_time, 110452a38012Sejakowatz bigtime_t timeout) 110552a38012Sejakowatz { 110652a38012Sejakowatz UNIMPLEMENTED(); 110760f15390Sbeveloper return B_OK; 110852a38012Sejakowatz } 110952a38012Sejakowatz 111052a38012Sejakowatz 111152a38012Sejakowatz status_t 111252a38012Sejakowatz BMediaRoster::SetRunModeNode(const media_node & node, 111352a38012Sejakowatz BMediaNode::run_mode mode) 111452a38012Sejakowatz { 111552a38012Sejakowatz CALLED(); 111640f36b03Sbeveloper if (IS_INVALID_NODE(node)) 111752a38012Sejakowatz return B_MEDIA_BAD_NODE; 111852a38012Sejakowatz 1119dfb2ad61Sbeveloper node_set_run_mode_command msg; 112052a38012Sejakowatz msg.mode = mode; 112152a38012Sejakowatz 112252a38012Sejakowatz return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg)); 112352a38012Sejakowatz } 112452a38012Sejakowatz 112552a38012Sejakowatz 112652a38012Sejakowatz status_t 112752a38012Sejakowatz BMediaRoster::PrerollNode(const media_node & node) 112852a38012Sejakowatz { 112952a38012Sejakowatz CALLED(); 113040f36b03Sbeveloper if (IS_INVALID_NODE(node)) 113152a38012Sejakowatz return B_MEDIA_BAD_NODE; 113252a38012Sejakowatz 113352a38012Sejakowatz char dummy; 113452a38012Sejakowatz return write_port(node.port, NODE_PREROLL, &dummy, sizeof(dummy)); 113552a38012Sejakowatz } 113652a38012Sejakowatz 113752a38012Sejakowatz 113852a38012Sejakowatz status_t 113952a38012Sejakowatz BMediaRoster::RollNode(const media_node & node, 114052a38012Sejakowatz bigtime_t startPerformance, 114152a38012Sejakowatz bigtime_t stopPerformance, 114252a38012Sejakowatz bigtime_t atMediaTime) 114352a38012Sejakowatz { 114452a38012Sejakowatz UNIMPLEMENTED(); 114552a38012Sejakowatz return B_ERROR; 114652a38012Sejakowatz } 114752a38012Sejakowatz 114852a38012Sejakowatz 114952a38012Sejakowatz status_t 115052a38012Sejakowatz BMediaRoster::SetProducerRunModeDelay(const media_node & node, 115152a38012Sejakowatz bigtime_t delay, 115252a38012Sejakowatz BMediaNode::run_mode mode) 115352a38012Sejakowatz { 115460f15390Sbeveloper CALLED(); 115560f15390Sbeveloper if (IS_INVALID_NODE(node)) 115660f15390Sbeveloper return B_MEDIA_BAD_NODE; 115760f15390Sbeveloper if ((node.kind & B_BUFFER_PRODUCER) == 0) 115860f15390Sbeveloper return B_MEDIA_BAD_NODE; 115960f15390Sbeveloper 116060f15390Sbeveloper producer_set_run_mode_delay_command command; 116160f15390Sbeveloper command.mode = mode; 116260f15390Sbeveloper command.delay = delay; 116360f15390Sbeveloper 116460f15390Sbeveloper return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command, sizeof(command)); 116552a38012Sejakowatz } 116652a38012Sejakowatz 116752a38012Sejakowatz 116852a38012Sejakowatz status_t 116952a38012Sejakowatz BMediaRoster::SetProducerRate(const media_node & producer, 117052a38012Sejakowatz int32 numer, 117152a38012Sejakowatz int32 denom) 117252a38012Sejakowatz { 117352a38012Sejakowatz CALLED(); 117440f36b03Sbeveloper if (IS_INVALID_NODE(producer)) 117552a38012Sejakowatz return B_MEDIA_BAD_NODE; 117652a38012Sejakowatz if ((producer.kind & B_BUFFER_PRODUCER) == 0) 117752a38012Sejakowatz return B_MEDIA_BAD_NODE; 117852a38012Sejakowatz 1179dfb2ad61Sbeveloper producer_set_play_rate_request msg; 1180dfb2ad61Sbeveloper producer_set_play_rate_reply reply; 118152a38012Sejakowatz status_t rv; 118252a38012Sejakowatz int32 code; 118352a38012Sejakowatz 118452a38012Sejakowatz msg.numer = numer; 118552a38012Sejakowatz msg.denom = denom; 118652a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 118752a38012Sejakowatz rv = write_port(producer.node, PRODUCER_SET_PLAY_RATE, &msg, sizeof(msg)); 118852a38012Sejakowatz if (rv != B_OK) { 118952a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 119052a38012Sejakowatz return rv; 119152a38012Sejakowatz } 119252a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 119352a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 119452a38012Sejakowatz return (rv < B_OK) ? rv : reply.result; 119552a38012Sejakowatz } 119652a38012Sejakowatz 119752a38012Sejakowatz 119852a38012Sejakowatz /* Nodes will have available inputs/outputs as long as they are capable */ 119952a38012Sejakowatz /* of accepting more connections. The node may create an additional */ 120052a38012Sejakowatz /* output or input as the currently available is taken into usage. */ 120152a38012Sejakowatz status_t 120252a38012Sejakowatz BMediaRoster::GetLiveNodeInfo(const media_node & node, 120352a38012Sejakowatz live_node_info * out_live_info) 120452a38012Sejakowatz { 12059e9417d2Sbeveloper CALLED(); 12069e9417d2Sbeveloper if (out_live_info == NULL) 12079e9417d2Sbeveloper return B_BAD_VALUE; 120840f36b03Sbeveloper if (IS_INVALID_NODE(node)) 12099e9417d2Sbeveloper return B_MEDIA_BAD_NODE; 12109e9417d2Sbeveloper 12119e9417d2Sbeveloper server_get_live_node_info_request request; 12129e9417d2Sbeveloper server_get_live_node_info_reply reply; 12139e9417d2Sbeveloper status_t rv; 12149e9417d2Sbeveloper 12159e9417d2Sbeveloper request.node = node; 12169e9417d2Sbeveloper 12171299bfb2Sbeveloper rv = QueryServer(SERVER_GET_LIVE_NODE_INFO, &request, sizeof(request), &reply, sizeof(reply)); 12189e9417d2Sbeveloper if (rv != B_OK) 12199e9417d2Sbeveloper return rv; 12209e9417d2Sbeveloper 12219e9417d2Sbeveloper *out_live_info = reply.live_info; 12229e9417d2Sbeveloper return B_OK; 122352a38012Sejakowatz } 122452a38012Sejakowatz 122552a38012Sejakowatz 122652a38012Sejakowatz status_t 122752a38012Sejakowatz BMediaRoster::GetLiveNodes(live_node_info * out_live_nodes, 122852a38012Sejakowatz int32 * io_total_count, 122952a38012Sejakowatz const media_format * has_input, 123052a38012Sejakowatz const media_format * has_output, 123152a38012Sejakowatz const char * name, 123252a38012Sejakowatz uint64 node_kinds) 123352a38012Sejakowatz { 12349e9417d2Sbeveloper CALLED(); 12359e9417d2Sbeveloper if (out_live_nodes == NULL || io_total_count == NULL) 12369e9417d2Sbeveloper return B_BAD_VALUE; 12379e9417d2Sbeveloper if (*io_total_count <= 0) 12389e9417d2Sbeveloper return B_BAD_VALUE; 12399e9417d2Sbeveloper 12409e9417d2Sbeveloper // XXX we also support the wildcard search as GetDormantNodes does. This needs to be documented 12419e9417d2Sbeveloper 12429e9417d2Sbeveloper server_get_live_nodes_request request; 12439e9417d2Sbeveloper server_get_live_nodes_reply reply; 12449e9417d2Sbeveloper status_t rv; 12459e9417d2Sbeveloper 12469e9417d2Sbeveloper request.maxcount = *io_total_count; 12479e9417d2Sbeveloper request.has_input = (bool) has_input; 12489e9417d2Sbeveloper if (has_input) 12499e9417d2Sbeveloper request.inputformat = *has_input; // XXX we should not make a flat copy of media_format 12509e9417d2Sbeveloper request.has_output = (bool) has_output; 12519e9417d2Sbeveloper if (has_output) 12529e9417d2Sbeveloper request.outputformat = *has_output; // XXX we should not make a flat copy of media_format 12539e9417d2Sbeveloper request.has_name = (bool) name; 12549e9417d2Sbeveloper if (name) { 12559e9417d2Sbeveloper int len = strlen(name); 12569e9417d2Sbeveloper len = min_c(len, (int)sizeof(request.name) - 1); 12579e9417d2Sbeveloper memcpy(request.name, name, len); 12589e9417d2Sbeveloper request.name[len] = 0; 12599e9417d2Sbeveloper } 12609e9417d2Sbeveloper request.require_kinds = node_kinds; 12619e9417d2Sbeveloper 12629e9417d2Sbeveloper rv = QueryServer(SERVER_GET_LIVE_NODES, &request, sizeof(request), &reply, sizeof(reply)); 12639e9417d2Sbeveloper if (rv != B_OK) { 12645ac4fbd7Sbeveloper ERROR("BMediaRoster::GetLiveNodes failed querying server\n"); 12651299bfb2Sbeveloper *io_total_count = 0; 12669e9417d2Sbeveloper return rv; 12679e9417d2Sbeveloper } 12689e9417d2Sbeveloper 12699e9417d2Sbeveloper if (reply.count > MAX_LIVE_INFO) { 12709e9417d2Sbeveloper live_node_info *live_info; 12719e9417d2Sbeveloper area_id clone; 12729e9417d2Sbeveloper 12739e9417d2Sbeveloper clone = clone_area("live_node_info clone", reinterpret_cast<void **>(&live_info), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, reply.area); 12749e9417d2Sbeveloper if (clone < B_OK) { 12755ac4fbd7Sbeveloper ERROR("BMediaRoster::GetLiveNodes failed to clone area, %#lx\n", clone); 12769e9417d2Sbeveloper delete_area(reply.area); 12771299bfb2Sbeveloper *io_total_count = 0; 127852a38012Sejakowatz return B_ERROR; 127952a38012Sejakowatz } 128052a38012Sejakowatz 12819e9417d2Sbeveloper for (int32 i = 0; i < reply.count; i++) { 12829e9417d2Sbeveloper out_live_nodes[i] = live_info[i]; 12839e9417d2Sbeveloper } 12849e9417d2Sbeveloper 12859e9417d2Sbeveloper delete_area(clone); 12869e9417d2Sbeveloper delete_area(reply.area); 12879e9417d2Sbeveloper } else { 12889e9417d2Sbeveloper for (int32 i = 0; i < reply.count; i++) { 12899e9417d2Sbeveloper out_live_nodes[i] = reply.live_info[i]; 12909e9417d2Sbeveloper } 12919e9417d2Sbeveloper } 12929e9417d2Sbeveloper *io_total_count = reply.count; 12939e9417d2Sbeveloper 12949e9417d2Sbeveloper return B_OK; 12959e9417d2Sbeveloper } 12969e9417d2Sbeveloper 129752a38012Sejakowatz 129852a38012Sejakowatz status_t 129952a38012Sejakowatz BMediaRoster::GetFreeInputsFor(const media_node & node, 130052a38012Sejakowatz media_input * out_free_inputs, 130152a38012Sejakowatz int32 buf_num_inputs, 130252a38012Sejakowatz int32 * out_total_count, 130352a38012Sejakowatz media_type filter_type) 130452a38012Sejakowatz { 13053620737cSbeveloper CALLED(); 13065ac4fbd7Sbeveloper if (IS_INVALID_NODE(node)) { 13075ac4fbd7Sbeveloper ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld invalid\n", node.node, node.port); 13083620737cSbeveloper return B_MEDIA_BAD_NODE; 13095ac4fbd7Sbeveloper } 13105ac4fbd7Sbeveloper if ((node.kind & B_BUFFER_CONSUMER) == 0) { 13115ac4fbd7Sbeveloper ERROR("BMediaRoster::GetFreeInputsFor: node %ld, port %ld is not a consumer\n", node.node, node.port); 13125ac4fbd7Sbeveloper return B_MEDIA_BAD_NODE; 13135ac4fbd7Sbeveloper } 13143620737cSbeveloper if (out_free_inputs == NULL || out_total_count == NULL) 13153620737cSbeveloper return B_BAD_VALUE; 13163620737cSbeveloper 131776669a29Sbeveloper List<media_input> list; 13183620737cSbeveloper media_input *input; 13193620737cSbeveloper status_t rv; 13203620737cSbeveloper 13211299bfb2Sbeveloper *out_total_count = 0; 13221299bfb2Sbeveloper 13238b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 13243620737cSbeveloper if (B_OK != rv) 13253620737cSbeveloper return rv; 13263620737cSbeveloper 13275ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetFreeInputsFor node %ld, max %ld, filter-type %ld\n", node.node, buf_num_inputs, filter_type); 13285ac4fbd7Sbeveloper 132976669a29Sbeveloper int32 i; 1330b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 13313620737cSbeveloper if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != input->format.type) 13323620737cSbeveloper continue; // media_type used, but doesn't match 13333620737cSbeveloper if (input->source != media_source::null) 13343620737cSbeveloper continue; // consumer source already connected 13353620737cSbeveloper out_free_inputs[i] = *input; 13363620737cSbeveloper *out_total_count += 1; 13373620737cSbeveloper buf_num_inputs -= 1; 13385ac4fbd7Sbeveloper #if DEBUG >= 3 13395ac4fbd7Sbeveloper PRINT_OUTPUT(" input", out_free_inputs[i]); 13405ac4fbd7Sbeveloper #endif 13413620737cSbeveloper if (buf_num_inputs == 0) 13423620737cSbeveloper break; 1343b65a0ac5SJérôme Duval i++; 13443620737cSbeveloper } 13453620737cSbeveloper 13468b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 13473620737cSbeveloper return B_OK; 134852a38012Sejakowatz } 134952a38012Sejakowatz 135052a38012Sejakowatz 135152a38012Sejakowatz status_t 135252a38012Sejakowatz BMediaRoster::GetConnectedInputsFor(const media_node & node, 135352a38012Sejakowatz media_input * out_active_inputs, 135452a38012Sejakowatz int32 buf_num_inputs, 135552a38012Sejakowatz int32 * out_total_count) 135652a38012Sejakowatz { 13573620737cSbeveloper CALLED(); 135840f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 13593620737cSbeveloper return B_MEDIA_BAD_NODE; 13603620737cSbeveloper if (out_active_inputs == NULL || out_total_count == NULL) 13613620737cSbeveloper return B_BAD_VALUE; 13623620737cSbeveloper 136376669a29Sbeveloper List<media_input> list; 13643620737cSbeveloper media_input *input; 13653620737cSbeveloper status_t rv; 13663620737cSbeveloper 13671299bfb2Sbeveloper *out_total_count = 0; 13681299bfb2Sbeveloper 13698b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 13703620737cSbeveloper if (B_OK != rv) 13713620737cSbeveloper return rv; 13723620737cSbeveloper 13735ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetConnectedInputsFor node %ld, max %ld\n", node.node, buf_num_inputs); 13745ac4fbd7Sbeveloper 137576669a29Sbeveloper int32 i; 1376b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&input);) { 13773620737cSbeveloper if (input->source == media_source::null) 13783620737cSbeveloper continue; // consumer source not connected 13793620737cSbeveloper out_active_inputs[i] = *input; 13803620737cSbeveloper *out_total_count += 1; 13813620737cSbeveloper buf_num_inputs -= 1; 13825ac4fbd7Sbeveloper #if DEBUG >= 3 13835ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_active_inputs[i]); 13845ac4fbd7Sbeveloper #endif 13853620737cSbeveloper if (buf_num_inputs == 0) 13863620737cSbeveloper break; 1387b65a0ac5SJérôme Duval i++; 13883620737cSbeveloper } 13893620737cSbeveloper 13908b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 13913620737cSbeveloper return B_OK; 139252a38012Sejakowatz } 139352a38012Sejakowatz 139452a38012Sejakowatz 139552a38012Sejakowatz status_t 139652a38012Sejakowatz BMediaRoster::GetAllInputsFor(const media_node & node, 139752a38012Sejakowatz media_input * out_inputs, 139852a38012Sejakowatz int32 buf_num_inputs, 139952a38012Sejakowatz int32 * out_total_count) 140052a38012Sejakowatz { 140152a38012Sejakowatz CALLED(); 140240f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_CONSUMER) == 0) 140352a38012Sejakowatz return B_MEDIA_BAD_NODE; 140452a38012Sejakowatz if (out_inputs == NULL || out_total_count == NULL) 140552a38012Sejakowatz return B_BAD_VALUE; 140652a38012Sejakowatz 140776669a29Sbeveloper List<media_input> list; 14083620737cSbeveloper media_input *input; 140952a38012Sejakowatz status_t rv; 141052a38012Sejakowatz 14111299bfb2Sbeveloper *out_total_count = 0; 14121299bfb2Sbeveloper 14138b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllInputs(node, &list); 14143620737cSbeveloper if (B_OK != rv) 14153620737cSbeveloper return rv; 14163620737cSbeveloper 14175ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetAllInputsFor node %ld, max %ld\n", node.node, buf_num_inputs); 14185ac4fbd7Sbeveloper 141976669a29Sbeveloper int32 i; 142076669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&input); i++) { 14213620737cSbeveloper out_inputs[i] = *input; 142252a38012Sejakowatz *out_total_count += 1; 14233620737cSbeveloper buf_num_inputs -= 1; 14245ac4fbd7Sbeveloper #if DEBUG >= 3 14255ac4fbd7Sbeveloper PRINT_OUTPUT(" input ", out_inputs[i]); 14265ac4fbd7Sbeveloper #endif 14273620737cSbeveloper if (buf_num_inputs == 0) 14283620737cSbeveloper break; 142952a38012Sejakowatz } 143052a38012Sejakowatz 14318b04ffc1Sbeveloper MediaRosterEx(this)->PublishInputs(node, &list); 14323620737cSbeveloper return B_OK; 143352a38012Sejakowatz } 143452a38012Sejakowatz 143552a38012Sejakowatz 143652a38012Sejakowatz status_t 143752a38012Sejakowatz BMediaRoster::GetFreeOutputsFor(const media_node & node, 143852a38012Sejakowatz media_output * out_free_outputs, 143952a38012Sejakowatz int32 buf_num_outputs, 144052a38012Sejakowatz int32 * out_total_count, 144152a38012Sejakowatz media_type filter_type) 144252a38012Sejakowatz { 14433620737cSbeveloper CALLED(); 144440f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 14453620737cSbeveloper return B_MEDIA_BAD_NODE; 14463620737cSbeveloper if (out_free_outputs == NULL || out_total_count == NULL) 14473620737cSbeveloper return B_BAD_VALUE; 14483620737cSbeveloper 144976669a29Sbeveloper List<media_output> list; 14503620737cSbeveloper media_output *output; 14513620737cSbeveloper status_t rv; 14523620737cSbeveloper 14531299bfb2Sbeveloper *out_total_count = 0; 14541299bfb2Sbeveloper 14558b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 14563620737cSbeveloper if (B_OK != rv) 14573620737cSbeveloper return rv; 14583620737cSbeveloper 14595ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetFreeOutputsFor node %ld, max %ld, filter-type %ld\n", node.node, buf_num_outputs, filter_type); 14605ac4fbd7Sbeveloper 146176669a29Sbeveloper int32 i; 1462b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 14633620737cSbeveloper if (filter_type != B_MEDIA_UNKNOWN_TYPE && filter_type != output->format.type) 14643620737cSbeveloper continue; // media_type used, but doesn't match 14653620737cSbeveloper if (output->destination != media_destination::null) 14663620737cSbeveloper continue; // producer destination already connected 14673620737cSbeveloper out_free_outputs[i] = *output; 14683620737cSbeveloper *out_total_count += 1; 14693620737cSbeveloper buf_num_outputs -= 1; 14705ac4fbd7Sbeveloper #if DEBUG >= 3 14715ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_free_outputs[i]); 14725ac4fbd7Sbeveloper #endif 14733620737cSbeveloper if (buf_num_outputs == 0) 14743620737cSbeveloper break; 1475b65a0ac5SJérôme Duval i++; 14763620737cSbeveloper } 14773620737cSbeveloper 14788b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 14793620737cSbeveloper return B_OK; 148052a38012Sejakowatz } 148152a38012Sejakowatz 148252a38012Sejakowatz 148352a38012Sejakowatz status_t 148452a38012Sejakowatz BMediaRoster::GetConnectedOutputsFor(const media_node & node, 148552a38012Sejakowatz media_output * out_active_outputs, 148652a38012Sejakowatz int32 buf_num_outputs, 148752a38012Sejakowatz int32 * out_total_count) 148852a38012Sejakowatz { 14893620737cSbeveloper CALLED(); 149040f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 14913620737cSbeveloper return B_MEDIA_BAD_NODE; 14923620737cSbeveloper if (out_active_outputs == NULL || out_total_count == NULL) 14933620737cSbeveloper return B_BAD_VALUE; 14943620737cSbeveloper 149576669a29Sbeveloper List<media_output> list; 14963620737cSbeveloper media_output *output; 14973620737cSbeveloper status_t rv; 14983620737cSbeveloper 14991299bfb2Sbeveloper *out_total_count = 0; 15001299bfb2Sbeveloper 15018b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 15023620737cSbeveloper if (B_OK != rv) 15033620737cSbeveloper return rv; 15043620737cSbeveloper 15055ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetConnectedOutputsFor node %ld, max %ld\n", node.node, buf_num_outputs); 15065ac4fbd7Sbeveloper 150776669a29Sbeveloper int32 i; 1508b65a0ac5SJérôme Duval for (i = 0, list.Rewind(); list.GetNext(&output);) { 15093620737cSbeveloper if (output->destination == media_destination::null) 15103620737cSbeveloper continue; // producer destination not connected 15113620737cSbeveloper out_active_outputs[i] = *output; 15123620737cSbeveloper *out_total_count += 1; 15133620737cSbeveloper buf_num_outputs -= 1; 15145ac4fbd7Sbeveloper #if DEBUG >= 3 15155ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_active_outputs[i]); 15165ac4fbd7Sbeveloper #endif 15173620737cSbeveloper if (buf_num_outputs == 0) 15183620737cSbeveloper break; 1519b65a0ac5SJérôme Duval i++; 15203620737cSbeveloper } 15213620737cSbeveloper 15228b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 15233620737cSbeveloper return B_OK; 152452a38012Sejakowatz } 152552a38012Sejakowatz 152652a38012Sejakowatz 152752a38012Sejakowatz status_t 152852a38012Sejakowatz BMediaRoster::GetAllOutputsFor(const media_node & node, 152952a38012Sejakowatz media_output * out_outputs, 153052a38012Sejakowatz int32 buf_num_outputs, 153152a38012Sejakowatz int32 * out_total_count) 153252a38012Sejakowatz { 153352a38012Sejakowatz CALLED(); 153440f36b03Sbeveloper if (IS_INVALID_NODE(node) || (node.kind & B_BUFFER_PRODUCER) == 0) 153552a38012Sejakowatz return B_MEDIA_BAD_NODE; 153652a38012Sejakowatz if (out_outputs == NULL || out_total_count == NULL) 153752a38012Sejakowatz return B_BAD_VALUE; 153852a38012Sejakowatz 153976669a29Sbeveloper List<media_output> list; 15403620737cSbeveloper media_output *output; 154152a38012Sejakowatz status_t rv; 154252a38012Sejakowatz 15431299bfb2Sbeveloper *out_total_count = 0; 15441299bfb2Sbeveloper 15458b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetAllOutputs(node, &list); 15463620737cSbeveloper if (B_OK != rv) 15473620737cSbeveloper return rv; 15483620737cSbeveloper 15495ac4fbd7Sbeveloper PRINT(4, "BMediaRoster::GetAllOutputsFor node %ld, max %ld\n", node.node, buf_num_outputs); 15505ac4fbd7Sbeveloper 155176669a29Sbeveloper int32 i; 155276669a29Sbeveloper for (i = 0, list.Rewind(); list.GetNext(&output); i++) { 15533620737cSbeveloper out_outputs[i] = *output; 155452a38012Sejakowatz *out_total_count += 1; 15553620737cSbeveloper buf_num_outputs -= 1; 15565ac4fbd7Sbeveloper #if DEBUG >= 3 15575ac4fbd7Sbeveloper PRINT_OUTPUT(" output ", out_outputs[i]); 15585ac4fbd7Sbeveloper #endif 15593620737cSbeveloper if (buf_num_outputs == 0) 15603620737cSbeveloper break; 156152a38012Sejakowatz } 156252a38012Sejakowatz 15638b04ffc1Sbeveloper MediaRosterEx(this)->PublishOutputs(node, &list); 15643620737cSbeveloper return B_OK; 156552a38012Sejakowatz } 156652a38012Sejakowatz 156752a38012Sejakowatz 156852a38012Sejakowatz status_t 156952a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where) 157052a38012Sejakowatz { 1571eae26d3dSbeveloper CALLED(); 1572eae26d3dSbeveloper if (!where.IsValid()) { 15735ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1574eae26d3dSbeveloper return B_BAD_VALUE; 1575eae26d3dSbeveloper } 1576f4925104Sbeveloper return BPrivate::media::notifications::Register(where, media_node::null, B_MEDIA_WILDCARD); 157752a38012Sejakowatz } 157852a38012Sejakowatz 157952a38012Sejakowatz 158052a38012Sejakowatz status_t 158152a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where, 158252a38012Sejakowatz int32 notificationType) 158352a38012Sejakowatz { 1584eae26d3dSbeveloper CALLED(); 1585eae26d3dSbeveloper if (!where.IsValid()) { 15865ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1587eae26d3dSbeveloper return B_BAD_VALUE; 1588eae26d3dSbeveloper } 1589f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) { 15905ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 1591eae26d3dSbeveloper return B_BAD_VALUE; 1592eae26d3dSbeveloper } 1593f4925104Sbeveloper return BPrivate::media::notifications::Register(where, media_node::null, notificationType); 159452a38012Sejakowatz } 159552a38012Sejakowatz 159652a38012Sejakowatz 159752a38012Sejakowatz status_t 159852a38012Sejakowatz BMediaRoster::StartWatching(const BMessenger & where, 159952a38012Sejakowatz const media_node & node, 160052a38012Sejakowatz int32 notificationType) 160152a38012Sejakowatz { 1602eae26d3dSbeveloper CALLED(); 1603eae26d3dSbeveloper if (!where.IsValid()) { 16045ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: messenger invalid!\n"); 1605eae26d3dSbeveloper return B_BAD_VALUE; 1606eae26d3dSbeveloper } 160740f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 16085ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: node invalid!\n"); 1609eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1610eae26d3dSbeveloper } 1611f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) { 16125ac4fbd7Sbeveloper ERROR("BMediaRoster::StartWatching: notificationType invalid!\n"); 1613eae26d3dSbeveloper return B_BAD_VALUE; 1614eae26d3dSbeveloper } 1615f4925104Sbeveloper return BPrivate::media::notifications::Register(where, node, notificationType); 161652a38012Sejakowatz } 161752a38012Sejakowatz 161852a38012Sejakowatz 161952a38012Sejakowatz status_t 162052a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where) 162152a38012Sejakowatz { 1622eae26d3dSbeveloper CALLED(); 1623eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1624f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, media_node::null, B_MEDIA_WILDCARD); 162552a38012Sejakowatz } 162652a38012Sejakowatz 162752a38012Sejakowatz 162852a38012Sejakowatz status_t 162952a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where, 163052a38012Sejakowatz int32 notificationType) 163152a38012Sejakowatz { 1632eae26d3dSbeveloper CALLED(); 1633eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 1634f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(false, notificationType)) { 16355ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 1636eae26d3dSbeveloper return B_BAD_VALUE; 1637eae26d3dSbeveloper } 1638f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, media_node::null, notificationType); 163952a38012Sejakowatz } 164052a38012Sejakowatz 164152a38012Sejakowatz 164252a38012Sejakowatz status_t 164352a38012Sejakowatz BMediaRoster::StopWatching(const BMessenger & where, 164452a38012Sejakowatz const media_node & node, 164552a38012Sejakowatz int32 notificationType) 164652a38012Sejakowatz { 1647eae26d3dSbeveloper CALLED(); 1648eae26d3dSbeveloper // messenger may already be invalid, so we don't check this 164940f36b03Sbeveloper if (IS_INVALID_NODE(node)) { 16505ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: node invalid!\n"); 1651eae26d3dSbeveloper return B_MEDIA_BAD_NODE; 1652eae26d3dSbeveloper } 1653f4925104Sbeveloper if (false == BPrivate::media::notifications::IsValidNotificationRequest(true, notificationType)) { 16545ac4fbd7Sbeveloper ERROR("BMediaRoster::StopWatching: notificationType invalid!\n"); 1655eae26d3dSbeveloper return B_BAD_VALUE; 1656eae26d3dSbeveloper } 1657f4925104Sbeveloper return BPrivate::media::notifications::Unregister(where, node, notificationType); 165852a38012Sejakowatz } 165952a38012Sejakowatz 166052a38012Sejakowatz 166152a38012Sejakowatz status_t 166252a38012Sejakowatz BMediaRoster::RegisterNode(BMediaNode * node) 166352a38012Sejakowatz { 166454187cc6Sbeveloper CALLED(); 166554187cc6Sbeveloper // addon-id = -1 (unused), addon-flavor-id = 0 (unused, too) 166654187cc6Sbeveloper return MediaRosterEx(this)->RegisterNode(node, -1, 0); 166754187cc6Sbeveloper } 166854187cc6Sbeveloper 166954187cc6Sbeveloper 167054187cc6Sbeveloper status_t 167154187cc6Sbeveloper BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 flavorid) 167254187cc6Sbeveloper { 167352a38012Sejakowatz CALLED(); 167452a38012Sejakowatz if (node == NULL) 167552a38012Sejakowatz return B_BAD_VALUE; 167652a38012Sejakowatz 167754187cc6Sbeveloper // some sanity check 167854187cc6Sbeveloper // I'm not sure if the media kit warrants to call BMediaNode::AddOn() here. 167954187cc6Sbeveloper // Perhaps we don't need it. 168054187cc6Sbeveloper { 16819e9417d2Sbeveloper BMediaAddOn *addon; 16829e9417d2Sbeveloper int32 addon_flavor_id; 16839e9417d2Sbeveloper media_addon_id addon_id; 16849e9417d2Sbeveloper addon_flavor_id = 0; 16859e9417d2Sbeveloper addon = node->AddOn(&addon_flavor_id); 16869e9417d2Sbeveloper addon_id = addon ? addon->AddonID() : -1; 168754187cc6Sbeveloper ASSERT(addonid == addon_id); 168854187cc6Sbeveloper ASSERT(flavorid == addon_flavor_id); 168954187cc6Sbeveloper } 169052a38012Sejakowatz 169154187cc6Sbeveloper status_t rv; 16929e9417d2Sbeveloper server_register_node_request request; 16939e9417d2Sbeveloper server_register_node_reply reply; 16949e9417d2Sbeveloper 169554187cc6Sbeveloper request.addon_id = addonid; 169654187cc6Sbeveloper request.addon_flavor_id = flavorid; 16979e9417d2Sbeveloper strcpy(request.name, node->Name()); 16989e9417d2Sbeveloper request.kinds = node->Kinds(); 16999e9417d2Sbeveloper request.port = node->ControlPort(); 17009e9417d2Sbeveloper request.team = team; 17019e9417d2Sbeveloper 17028b04ffc1Sbeveloper 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); 17031299bfb2Sbeveloper 17049e9417d2Sbeveloper rv = QueryServer(SERVER_REGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply)); 17059e9417d2Sbeveloper if (rv != B_OK) { 17065ac4fbd7Sbeveloper ERROR("BMediaRoster::RegisterNode: failed to register node %s (error %#lx)\n", node->Name(), rv); 17079e9417d2Sbeveloper return rv; 17089e9417d2Sbeveloper } 17099e9417d2Sbeveloper 17104295907bSbeveloper TRACE("BMediaRoster::RegisterNode: QueryServer SERVER_REGISTER_NODE finished\n"); 17114295907bSbeveloper 17128b04ffc1Sbeveloper // we are a friend class of BMediaNode and initialize this member variable 17139e9417d2Sbeveloper node->fNodeID = reply.nodeid; 17149e9417d2Sbeveloper ASSERT(reply.nodeid == node->Node().node); 17159e9417d2Sbeveloper ASSERT(reply.nodeid == node->ID()); 17169e9417d2Sbeveloper 17179e9417d2Sbeveloper // call the callback 17189e9417d2Sbeveloper node->NodeRegistered(); 17193620737cSbeveloper 17204295907bSbeveloper TRACE("BMediaRoster::RegisterNode: NodeRegistered callback finished\n"); 17214295907bSbeveloper 17220e21b167Sbeveloper // if the BMediaNode also inherits from BTimeSource, we need to call BTimeSource::FinishCreate() 17230e21b167Sbeveloper if (node->Kinds() & B_TIME_SOURCE) { 17240e21b167Sbeveloper BTimeSource *ts; 17250e21b167Sbeveloper ts = dynamic_cast<BTimeSource *>(node); 17260e21b167Sbeveloper if (ts) 17270e21b167Sbeveloper ts->FinishCreate(); 17280e21b167Sbeveloper } 17290e21b167Sbeveloper 17304295907bSbeveloper TRACE("BMediaRoster::RegisterNode: publishing inputs/outputs\n"); 17314295907bSbeveloper 17323620737cSbeveloper // register existing inputs and outputs with the 17333620737cSbeveloper // media_server, this allows GetLiveNodes() to work 17343620737cSbeveloper // with created, but unconnected nodes. 17354d2d96e0Sbeveloper // The node control loop might not be running, or might deadlock 17364d2d96e0Sbeveloper // if we send a message and wait for a reply here. 17374d2d96e0Sbeveloper // We have a pointer to the node, and thus call the functions directly 17384295907bSbeveloper 17393620737cSbeveloper if (node->Kinds() & B_BUFFER_PRODUCER) { 17404d2d96e0Sbeveloper BBufferProducer *bp; 17414d2d96e0Sbeveloper bp = dynamic_cast<BBufferProducer *>(node); 17424d2d96e0Sbeveloper if (bp) { 1743359ac306Sbeveloper List<media_output> list; 17444d2d96e0Sbeveloper if (B_OK == GetAllOutputs(bp, &list)) 1745359ac306Sbeveloper PublishOutputs(node->Node(), &list); 174621871f38Sbeveloper } 17474d2d96e0Sbeveloper } 174821871f38Sbeveloper if (node->Kinds() & B_BUFFER_CONSUMER) { 17494d2d96e0Sbeveloper BBufferConsumer *bc; 17504d2d96e0Sbeveloper bc = dynamic_cast<BBufferConsumer *>(node); 17514d2d96e0Sbeveloper if (bc) { 1752359ac306Sbeveloper List<media_input> list; 17534d2d96e0Sbeveloper if (B_OK == GetAllInputs(bc, &list)) 1754359ac306Sbeveloper PublishInputs(node->Node(), &list); 17553620737cSbeveloper } 17564d2d96e0Sbeveloper } 175721871f38Sbeveloper 17584295907bSbeveloper TRACE("BMediaRoster::RegisterNode: sending NodesCreated\n"); 17594295907bSbeveloper 17601299bfb2Sbeveloper BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1); 17614295907bSbeveloper 17624295907bSbeveloper TRACE("BMediaRoster::RegisterNode: finished\n"); 17634295907bSbeveloper 1764570f7d04Sbeveloper /* 1765570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id); 1766570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node this %p\n", node); 1767570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fConsumerThis %p\n", node->fConsumerThis); 1768570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fProducerThis %p\n", node->fProducerThis); 1769570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fFileInterfaceThis %p\n", node->fFileInterfaceThis); 1770570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fControllableThis %p\n", node->fControllableThis); 1771570f7d04Sbeveloper TRACE("BMediaRoster::RegisterNode: node fTimeSourceThis %p\n", node->fTimeSourceThis); 1772570f7d04Sbeveloper */ 17739e9417d2Sbeveloper return B_OK; 177452a38012Sejakowatz } 177552a38012Sejakowatz 177652a38012Sejakowatz 177752a38012Sejakowatz status_t 177852a38012Sejakowatz BMediaRoster::UnregisterNode(BMediaNode * node) 177952a38012Sejakowatz { 17809e9417d2Sbeveloper CALLED(); 17819e9417d2Sbeveloper if (node == NULL) 17829e9417d2Sbeveloper return B_BAD_VALUE; 17839e9417d2Sbeveloper 178460f15390Sbeveloper TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node); 178560f15390Sbeveloper 178686bce45bSbeveloper if (node->fKinds & NODE_KIND_NO_REFCOUNTING) { 178786bce45bSbeveloper printf("BMediaRoster::UnregisterNode, trying to unregister reference counting disabled timesource, node %ld, port %ld, team %ld\n", node->ID(), node->ControlPort(), team); 178886bce45bSbeveloper return B_OK; 178986bce45bSbeveloper } 17908b04ffc1Sbeveloper if (node->ID() == NODE_UNREGISTERED_ID) { 17915ac4fbd7Sbeveloper PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name '%s' already unregistered\n", node->ID(), node->Name()); 17929e9417d2Sbeveloper return B_OK; 17939e9417d2Sbeveloper } 179454187cc6Sbeveloper if (node->fRefCount != 0) { 17955ac4fbd7Sbeveloper PRINT(1, "Warning: BMediaRoster::UnregisterNode: node id %ld, name '%s' has local reference count of %ld\n", node->ID(), node->Name(), node->fRefCount); 179654187cc6Sbeveloper // no return here, we continue and unregister! 179754187cc6Sbeveloper } 179854187cc6Sbeveloper 179954187cc6Sbeveloper // Calling BMediaAddOn::GetConfigurationFor(BMediaNode *node, BMessage *config) 180054187cc6Sbeveloper // if this node was instanciated by an add-on needs to be done *somewhere* 180154187cc6Sbeveloper // We can't do it here because it is already to late (destructor of the node 180254187cc6Sbeveloper // might have been called). 18039e9417d2Sbeveloper 18049e9417d2Sbeveloper server_unregister_node_request request; 18059e9417d2Sbeveloper server_unregister_node_reply reply; 18069e9417d2Sbeveloper status_t rv; 18079e9417d2Sbeveloper 18089e9417d2Sbeveloper request.nodeid = node->ID(); 18099e9417d2Sbeveloper request.team = team; 18109e9417d2Sbeveloper 18111299bfb2Sbeveloper // send a notification 18121299bfb2Sbeveloper BPrivate::media::notifications::NodesDeleted(&request.nodeid, 1); 18131299bfb2Sbeveloper 18149e9417d2Sbeveloper rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply)); 18159e9417d2Sbeveloper if (rv != B_OK) { 18165ac4fbd7Sbeveloper ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %ld, name '%s' (error %#lx)\n", node->ID(), node->Name(), rv); 18179e9417d2Sbeveloper return rv; 18189e9417d2Sbeveloper } 18199e9417d2Sbeveloper 182054187cc6Sbeveloper if (reply.addonid != -1) { 182154187cc6Sbeveloper // Small problem here, we can't use DormantNodeManager::PutAddon(), as 182254187cc6Sbeveloper // UnregisterNode() is called by a dormant node itself (by the destructor). 182354187cc6Sbeveloper // The add-on that contains the node needs to remain in memory until the 182454187cc6Sbeveloper // destructor execution is finished. 182554187cc6Sbeveloper // DormantNodeManager::PutAddonDelayed() will delay unloading. 182654187cc6Sbeveloper _DormantNodeManager->PutAddonDelayed(reply.addonid); 1827cf4e2277Sbeveloper 182873794717Sbeveloper rv = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount(reply.addonid, reply.flavorid); 182954187cc6Sbeveloper if (rv != B_OK) { 18305ac4fbd7Sbeveloper ERROR("BMediaRoster::UnregisterNode: DecrementAddonFlavorInstancesCount failed\n"); 183154187cc6Sbeveloper // this is really a problem, but we can't fail now 183254187cc6Sbeveloper } 18338b04ffc1Sbeveloper } 18349e9417d2Sbeveloper 18351299bfb2Sbeveloper // we are a friend class of BMediaNode and invalidate this member variable 18368b04ffc1Sbeveloper node->fNodeID = NODE_UNREGISTERED_ID; 18379e9417d2Sbeveloper 18389e9417d2Sbeveloper return B_OK; 183952a38012Sejakowatz } 184052a38012Sejakowatz 184152a38012Sejakowatz 184252a38012Sejakowatz // thread safe for multiple calls to Roster() 184352a38012Sejakowatz /* static */ BMediaRoster * 184452a38012Sejakowatz BMediaRoster::Roster(status_t* out_error) 184552a38012Sejakowatz { 184652a38012Sejakowatz static BLocker locker("BMediaRoster::Roster locker"); 184752a38012Sejakowatz locker.Lock(); 184852a38012Sejakowatz if (_sDefault == NULL) { 18498b04ffc1Sbeveloper _sDefault = new BMediaRosterEx(); 185052a38012Sejakowatz if (out_error != NULL) 185152a38012Sejakowatz *out_error = B_OK; 185252a38012Sejakowatz } else { 185352a38012Sejakowatz if (out_error != NULL) 185452a38012Sejakowatz *out_error = B_OK; 185552a38012Sejakowatz } 185652a38012Sejakowatz locker.Unlock(); 185752a38012Sejakowatz return _sDefault; 185852a38012Sejakowatz } 185952a38012Sejakowatz 186052a38012Sejakowatz 186152a38012Sejakowatz // won't create it if there isn't one 186252a38012Sejakowatz // not thread safe if you call Roster() at the same time 186352a38012Sejakowatz /* static */ BMediaRoster * 186452a38012Sejakowatz BMediaRoster::CurrentRoster() 186552a38012Sejakowatz { 186652a38012Sejakowatz return _sDefault; 186752a38012Sejakowatz } 186852a38012Sejakowatz 186952a38012Sejakowatz 187052a38012Sejakowatz status_t 187152a38012Sejakowatz BMediaRoster::SetTimeSourceFor(media_node_id node, 187252a38012Sejakowatz media_node_id time_source) 187352a38012Sejakowatz { 1874aac800c2Sbeveloper CALLED(); 187540f36b03Sbeveloper if (IS_INVALID_NODEID(node) || IS_INVALID_NODEID(time_source)) 1876aac800c2Sbeveloper return B_BAD_VALUE; 1877aac800c2Sbeveloper 1878aac800c2Sbeveloper media_node clone; 1879aac800c2Sbeveloper status_t rv, result; 1880aac800c2Sbeveloper 18815917dd5bSbeveloper TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time source %ld\n", node, time_source); 18825917dd5bSbeveloper 18835917dd5bSbeveloper printf("BMediaRoster::SetTimeSourceFor: node %ld time source %ld enter\n", node, time_source); 18845917dd5bSbeveloper 188586bce45bSbeveloper // we need to get a clone of the node to have a port id 1886aac800c2Sbeveloper rv = GetNodeFor(node, &clone); 1887aac800c2Sbeveloper if (rv != B_OK) { 18885ac4fbd7Sbeveloper ERROR("BMediaRoster::SetTimeSourceFor, GetNodeFor failed, node id %ld\n", node); 188952a38012Sejakowatz return B_ERROR; 189052a38012Sejakowatz } 189152a38012Sejakowatz 189286bce45bSbeveloper // we just send the request to set time_source-id as timesource to the node, 189386bce45bSbeveloper // the NODE_SET_TIMESOURCE handler code will do the real assignment 1894aac800c2Sbeveloper result = B_OK; 1895aac800c2Sbeveloper node_set_timesource_command cmd; 1896aac800c2Sbeveloper cmd.timesource_id = time_source; 1897aac800c2Sbeveloper rv = SendToPort(clone.port, NODE_SET_TIMESOURCE, &cmd, sizeof(cmd)); 1898aac800c2Sbeveloper if (rv != B_OK) { 18995ac4fbd7Sbeveloper ERROR("BMediaRoster::SetTimeSourceFor, sending NODE_SET_TIMESOURCE failed, node id %ld\n", node); 1900aac800c2Sbeveloper result = B_ERROR; 1901aac800c2Sbeveloper } 1902aac800c2Sbeveloper 190360f15390Sbeveloper // we release the clone 1904aac800c2Sbeveloper rv = ReleaseNode(clone); 1905aac800c2Sbeveloper if (rv != B_OK) { 19065ac4fbd7Sbeveloper ERROR("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id %ld\n", node); 1907aac800c2Sbeveloper result = B_ERROR; 1908aac800c2Sbeveloper } 1909aac800c2Sbeveloper 19105917dd5bSbeveloper printf("BMediaRoster::SetTimeSourceFor: node %ld time source %ld leave\n", node, time_source); 19115917dd5bSbeveloper 1912aac800c2Sbeveloper return result; 1913aac800c2Sbeveloper } 1914aac800c2Sbeveloper 191552a38012Sejakowatz 191652a38012Sejakowatz status_t 191752a38012Sejakowatz BMediaRoster::GetParameterWebFor(const media_node & node, 191852a38012Sejakowatz BParameterWeb ** out_web) 191952a38012Sejakowatz { 192028ad138aSbeveloper CALLED(); 192128ad138aSbeveloper if (out_web == NULL) 192228ad138aSbeveloper return B_BAD_VALUE; 192328ad138aSbeveloper if (IS_INVALID_NODE(node)) 192428ad138aSbeveloper return B_MEDIA_BAD_NODE; 192528ad138aSbeveloper if ((node.kind & B_CONTROLLABLE) == 0) 192628ad138aSbeveloper return B_MEDIA_BAD_NODE; 192728ad138aSbeveloper 192828ad138aSbeveloper controllable_get_parameter_web_request request; 192928ad138aSbeveloper controllable_get_parameter_web_reply reply; 193028ad138aSbeveloper 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}; 193128ad138aSbeveloper int32 size; 193228ad138aSbeveloper 193328ad138aSbeveloper // XXX it might be better to query the node for the (current) parameter size first 193428ad138aSbeveloper for (int i = 0; (size = requestsize[i]) != 0; i++) { 193528ad138aSbeveloper status_t rv; 193628ad138aSbeveloper area_id area; 193728ad138aSbeveloper void *data; 193828ad138aSbeveloper area = create_area("parameter web data", &data, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 193928ad138aSbeveloper if (area < B_OK) { 19405ac4fbd7Sbeveloper ERROR("BMediaRoster::GetParameterWebFor couldn't create area of size %ld\n", size); 194128ad138aSbeveloper return B_ERROR; 194228ad138aSbeveloper } 194328ad138aSbeveloper request.maxsize = size; 194428ad138aSbeveloper request.area = area; 194528ad138aSbeveloper rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request, sizeof(request), &reply, sizeof(reply)); 194628ad138aSbeveloper if (rv != B_OK) { 19475ac4fbd7Sbeveloper ERROR("BMediaRoster::GetParameterWebFor CONTROLLABLE_GET_PARAMETER_WEB failed\n"); 194828ad138aSbeveloper delete_area(area); 194928ad138aSbeveloper return B_ERROR; 195028ad138aSbeveloper } 195128ad138aSbeveloper if (reply.size == 0) { 195228ad138aSbeveloper // no parameter web available 195328ad138aSbeveloper // XXX should we return an error? 19545ac4fbd7Sbeveloper ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter web\n", node.node); 195528ad138aSbeveloper *out_web = new BParameterWeb(); 195628ad138aSbeveloper delete_area(area); 195760f15390Sbeveloper return B_OK; 195852a38012Sejakowatz } 195928ad138aSbeveloper if (reply.size > 0) { 196028ad138aSbeveloper // we got a flattened parameter web! 196128ad138aSbeveloper *out_web = new BParameterWeb(); 196228ad138aSbeveloper 1963d91580cdSbeveloper printf("BMediaRoster::GetParameterWebFor Unflattening %ld bytes, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx\n", 196428ad138aSbeveloper reply.size, ((uint32*)data)[0], ((uint32*)data)[1], ((uint32*)data)[2], ((uint32*)data)[3]); 196528ad138aSbeveloper 196628ad138aSbeveloper rv = (*out_web)->Unflatten(reply.code, data, reply.size); 196728ad138aSbeveloper if (rv != B_OK) { 19685ac4fbd7Sbeveloper ERROR("BMediaRoster::GetParameterWebFor Unflatten failed, %s\n", strerror(rv)); 196928ad138aSbeveloper delete_area(area); 197028ad138aSbeveloper delete *out_web; 197128ad138aSbeveloper return B_ERROR; 197228ad138aSbeveloper } 197328ad138aSbeveloper delete_area(area); 197428ad138aSbeveloper return B_OK; 197528ad138aSbeveloper } 197628ad138aSbeveloper delete_area(area); 197728ad138aSbeveloper ASSERT(reply.size == -1); 197828ad138aSbeveloper // parameter web data was too large 197928ad138aSbeveloper // loop and try a larger size 198028ad138aSbeveloper } 19815ac4fbd7Sbeveloper ERROR("BMediaRoster::GetParameterWebFor node %ld has no parameter web larger than %ld\n", node.node, size); 198228ad138aSbeveloper return B_ERROR; 198328ad138aSbeveloper } 198452a38012Sejakowatz 198552a38012Sejakowatz 198652a38012Sejakowatz status_t 198752a38012Sejakowatz BMediaRoster::StartControlPanel(const media_node & node, 198852a38012Sejakowatz BMessenger * out_messenger) 198952a38012Sejakowatz { 199052a38012Sejakowatz UNIMPLEMENTED(); 199152a38012Sejakowatz return B_ERROR; 199252a38012Sejakowatz } 199352a38012Sejakowatz 199452a38012Sejakowatz 199552a38012Sejakowatz status_t 199652a38012Sejakowatz BMediaRoster::GetDormantNodes(dormant_node_info * out_info, 199752a38012Sejakowatz int32 * io_count, 199852a38012Sejakowatz const media_format * has_input /* = NULL */, 199952a38012Sejakowatz const media_format * has_output /* = NULL */, 200052a38012Sejakowatz const char * name /* = NULL */, 200152a38012Sejakowatz uint64 require_kinds /* = NULL */, 200252a38012Sejakowatz uint64 deny_kinds /* = NULL */) 200352a38012Sejakowatz { 200452a38012Sejakowatz CALLED(); 200552a38012Sejakowatz if (out_info == NULL) 200652a38012Sejakowatz return B_BAD_VALUE; 200752a38012Sejakowatz if (io_count == NULL) 200852a38012Sejakowatz return B_BAD_VALUE; 200952a38012Sejakowatz if (*io_count <= 0) 201052a38012Sejakowatz return B_BAD_VALUE; 201152a38012Sejakowatz 201252a38012Sejakowatz xfer_server_get_dormant_nodes msg; 201352a38012Sejakowatz port_id port; 201452a38012Sejakowatz status_t rv; 201552a38012Sejakowatz 20164295907bSbeveloper port = find_port(MEDIA_SERVER_PORT_NAME); 201752a38012Sejakowatz if (port <= B_OK) 201852a38012Sejakowatz return B_ERROR; 201952a38012Sejakowatz 202052a38012Sejakowatz msg.maxcount = *io_count; 202152a38012Sejakowatz msg.has_input = (bool) has_input; 202252a38012Sejakowatz if (has_input) 202352a38012Sejakowatz msg.inputformat = *has_input; // XXX we should not make a flat copy of media_format 202452a38012Sejakowatz msg.has_output = (bool) has_output; 202552a38012Sejakowatz if (has_output) 202652a38012Sejakowatz msg.outputformat = *has_output;; // XXX we should not make a flat copy of media_format 202752a38012Sejakowatz msg.has_name = (bool) name; 202852a38012Sejakowatz if (name) { 20299e9417d2Sbeveloper int len = strlen(name); 20309e9417d2Sbeveloper len = min_c(len, (int)sizeof(msg.name) - 1); 203152a38012Sejakowatz memcpy(msg.name, name, len); 203252a38012Sejakowatz msg.name[len] = 0; 203352a38012Sejakowatz } 203452a38012Sejakowatz msg.require_kinds = require_kinds; 203552a38012Sejakowatz msg.deny_kinds = deny_kinds; 203652a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 203752a38012Sejakowatz 203852a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_NODES, &msg, sizeof(msg)); 203952a38012Sejakowatz if (rv != B_OK) { 204052a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 204152a38012Sejakowatz return rv; 204252a38012Sejakowatz } 204352a38012Sejakowatz 204452a38012Sejakowatz xfer_server_get_dormant_nodes_reply reply; 204552a38012Sejakowatz int32 code; 204652a38012Sejakowatz 204752a38012Sejakowatz rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); 204852a38012Sejakowatz if (rv < B_OK) { 204952a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 205052a38012Sejakowatz return rv; 205152a38012Sejakowatz } 205252a38012Sejakowatz 205352a38012Sejakowatz *io_count = reply.count; 205452a38012Sejakowatz 205552a38012Sejakowatz if (*io_count > 0) { 205652a38012Sejakowatz rv = read_port(msg.reply_port, &code, out_info, *io_count * sizeof(dormant_node_info)); 205752a38012Sejakowatz if (rv < B_OK) 205852a38012Sejakowatz reply.result = rv; 205952a38012Sejakowatz } 206052a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 206152a38012Sejakowatz 206252a38012Sejakowatz return reply.result; 206352a38012Sejakowatz } 206452a38012Sejakowatz 20658b04ffc1Sbeveloper /* This function is used to do the real work of instantiating a dormant node. It is either 20668b04ffc1Sbeveloper * called by the media_addon_server to instantiate a global node, or it gets called from 20678b04ffc1Sbeveloper * BMediaRoster::InstantiateDormantNode() to create a local one. 20688b04ffc1Sbeveloper * 20698b04ffc1Sbeveloper * Checks concerning global/local are not done here. 20708b04ffc1Sbeveloper */ 207152a38012Sejakowatz status_t 207254187cc6Sbeveloper BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, team_id creator, media_node *out_node) 207352a38012Sejakowatz { 207454187cc6Sbeveloper // This function is always called from the correct context, if the node 207554187cc6Sbeveloper // is supposed to be global, it is called from the media_addon_server. 207654187cc6Sbeveloper 207752a38012Sejakowatz // if B_FLAVOR_IS_GLOBAL, we need to use the BMediaAddOn object that 207852a38012Sejakowatz // resides in the media_addon_server 207952a38012Sejakowatz 20808b04ffc1Sbeveloper // RegisterNode() must be called for nodes instantiated from add-ons, 20818b04ffc1Sbeveloper // since the media kit warrants that it's done automatically. 208252a38012Sejakowatz 208354187cc6Sbeveloper // addonid Indicates the ID number of the media add-on in which the node resides. 208454187cc6Sbeveloper // flavorid Indicates the internal ID number that the add-on uses to identify the flavor, 208554187cc6Sbeveloper // this is the number that was published by BMediaAddOn::GetFlavorAt() in the 20868b04ffc1Sbeveloper // flavor_info::internal_id field. 208754187cc6Sbeveloper // creator The creator team is -1 if nodes are created locally. If created globally, 208854187cc6Sbeveloper // it will contain (while called in media_addon_server context) the team-id of 208954187cc6Sbeveloper // the team that requested the instantiation. 20908b04ffc1Sbeveloper 209160f15390Sbeveloper TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld\n", addonid, flavorid); 20928b04ffc1Sbeveloper 20938b04ffc1Sbeveloper // Get flavor_info from the server 20948b04ffc1Sbeveloper dormant_flavor_info node_info; 20958c6a6096Sbeveloper status_t rv; 20968b04ffc1Sbeveloper rv = GetDormantFlavorInfo(addonid, flavorid, &node_info); 20978b04ffc1Sbeveloper if (rv != B_OK) { 20985ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", addonid, flavorid); 209952a38012Sejakowatz return B_ERROR; 210052a38012Sejakowatz } 21018b04ffc1Sbeveloper 2102908eaf85Sbeveloper //ASSERT(node_info.internal_id == flavorid); 2103908eaf85Sbeveloper if (node_info.internal_id != flavorid) { 21044d2d96e0Sbeveloper 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); 2105908eaf85Sbeveloper return B_ERROR; 2106908eaf85Sbeveloper } 21078b04ffc1Sbeveloper 21088b04ffc1Sbeveloper // load the BMediaAddOn object 21098b04ffc1Sbeveloper BMediaAddOn *addon; 21108b04ffc1Sbeveloper addon = _DormantNodeManager->GetAddon(addonid); 21118b04ffc1Sbeveloper if (!addon) { 21125ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: GetAddon failed\n"); 21138b04ffc1Sbeveloper return B_ERROR; 21148b04ffc1Sbeveloper } 21158b04ffc1Sbeveloper 211654187cc6Sbeveloper // Now we need to try to increment the use count of this addon flavor 211754187cc6Sbeveloper // in the server. This can fail if the total number instances of this 211854187cc6Sbeveloper // flavor is limited. 211973794717Sbeveloper rv = IncrementAddonFlavorInstancesCount(addonid, flavorid); 212054187cc6Sbeveloper if (rv != B_OK) { 21215ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode error: can't create more nodes for addon-id %ld, flavor-id %ld\n", addonid, flavorid); 212254187cc6Sbeveloper // Put the addon back into the pool 212354187cc6Sbeveloper _DormantNodeManager->PutAddon(addonid); 212454187cc6Sbeveloper return B_ERROR; 212554187cc6Sbeveloper } 212654187cc6Sbeveloper 21278b04ffc1Sbeveloper BMessage config; 212854187cc6Sbeveloper rv = LoadNodeConfiguration(addonid, flavorid, &config); 212954187cc6Sbeveloper if (rv != B_OK) { 21305ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: couldn't load configuration for addon-id %ld, flavor-id %ld\n", addonid, flavorid); 213154187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 213254187cc6Sbeveloper } 21338b04ffc1Sbeveloper 21348b04ffc1Sbeveloper BMediaNode *node; 21358b04ffc1Sbeveloper status_t out_error; 21368b04ffc1Sbeveloper 213754187cc6Sbeveloper out_error = B_OK; 21388b04ffc1Sbeveloper node = addon->InstantiateNodeFor(&node_info, &config, &out_error); 213916b7eea4Sbeveloper if (!node) { 21405ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: InstantiateNodeFor failed\n"); 214154187cc6Sbeveloper // Put the addon back into the pool 21428b04ffc1Sbeveloper _DormantNodeManager->PutAddon(addonid); 214354187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 214454187cc6Sbeveloper // server to compensate the increment done in the beginning. 214573794717Sbeveloper rv = DecrementAddonFlavorInstancesCount(addonid, flavorid); 214654187cc6Sbeveloper if (rv != B_OK) { 21475ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n"); 214816b7eea4Sbeveloper } 214954187cc6Sbeveloper return (out_error != B_OK) ? out_error : B_ERROR; 215054187cc6Sbeveloper } 215154187cc6Sbeveloper 215254187cc6Sbeveloper rv = RegisterNode(node, addonid, flavorid); 21538c6a6096Sbeveloper if (rv != B_OK) { 21545ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: RegisterNode failed\n"); 21558c6a6096Sbeveloper delete node; 215654187cc6Sbeveloper // Put the addon back into the pool 21578b04ffc1Sbeveloper _DormantNodeManager->PutAddon(addonid); 215854187cc6Sbeveloper // We must decrement the use count of this addon flavor in the 215954187cc6Sbeveloper // server to compensate the increment done in the beginning. 216073794717Sbeveloper rv = DecrementAddonFlavorInstancesCount(addonid, flavorid); 216154187cc6Sbeveloper if (rv != B_OK) { 21625ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode: DecrementAddonFlavorInstancesCount failed\n"); 216354187cc6Sbeveloper } 21648c6a6096Sbeveloper return B_ERROR; 21658c6a6096Sbeveloper } 21668c6a6096Sbeveloper 216754187cc6Sbeveloper if (creator != -1) { 216854187cc6Sbeveloper // send a message to the server to assign team "creator" as creator of node "node->ID()" 216954187cc6Sbeveloper printf("!!! BMediaRosterEx::InstantiateDormantNode assigning team %ld as creator of node %ld\n", creator, node->ID()); 217054187cc6Sbeveloper rv = MediaRosterEx(this)->SetNodeCreator(node->ID(), creator); 217154187cc6Sbeveloper if (rv != B_OK) { 21725ac4fbd7Sbeveloper ERROR("BMediaRosterEx::InstantiateDormantNode failed to assign team %ld as creator of node %ld\n", creator, node->ID()); 217354187cc6Sbeveloper // do not return, this is a minor problem, not a reason to fail 217454187cc6Sbeveloper } 217554187cc6Sbeveloper } 217654187cc6Sbeveloper 217754187cc6Sbeveloper // RegisterNode() does remember the add-on id in the server 217854187cc6Sbeveloper // and UnregisterNode() will call DormantNodeManager::PutAddon() 217954187cc6Sbeveloper // when the node is unregistered. 21808c6a6096Sbeveloper 218116b7eea4Sbeveloper *out_node = node->Node(); 2182cf4e2277Sbeveloper 218360f15390Sbeveloper 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); 2184cf4e2277Sbeveloper 218516b7eea4Sbeveloper return B_OK; 218616b7eea4Sbeveloper } 218752a38012Sejakowatz 218852a38012Sejakowatz 218952a38012Sejakowatz status_t 21908b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, 21918b04ffc1Sbeveloper media_node * out_node, 21928b04ffc1Sbeveloper uint32 flags /* currently 0 or B_FLAVOR_IS_GLOBAL or B_FLAVOR_IS_LOCAL */ ) 21938b04ffc1Sbeveloper { 21948b04ffc1Sbeveloper CALLED(); 21958b04ffc1Sbeveloper if (out_node == 0) 21968b04ffc1Sbeveloper return B_BAD_VALUE; 21978b04ffc1Sbeveloper if (in_info.addon <= 0) { 21985ac4fbd7Sbeveloper ERROR("BMediaRoster::InstantiateDormantNode error: addon-id %ld invalid.\n", in_info.addon); 21998b04ffc1Sbeveloper return B_BAD_VALUE; 22008b04ffc1Sbeveloper } 22018b04ffc1Sbeveloper 2202d91580cdSbeveloper printf("BMediaRoster::InstantiateDormantNode: addon-id %ld, flavor_id %ld, flags 0x%lX\n", in_info.addon, in_info.flavor_id, flags); 22038b04ffc1Sbeveloper 22048b04ffc1Sbeveloper // Get flavor_info from the server 22058b04ffc1Sbeveloper // XXX this is a little overhead, as we get the full blown dormant_flavor_info, 22068b04ffc1Sbeveloper // XXX but only need the flags. 22078b04ffc1Sbeveloper dormant_flavor_info node_info; 22088b04ffc1Sbeveloper status_t rv; 22098b04ffc1Sbeveloper rv = MediaRosterEx(this)->GetDormantFlavorInfo(in_info.addon, in_info.flavor_id, &node_info); 22108b04ffc1Sbeveloper if (rv != B_OK) { 22115ac4fbd7Sbeveloper ERROR("BMediaRoster::InstantiateDormantNode: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", in_info.addon, in_info.flavor_id); 2212626824eaSbeveloper return B_NAME_NOT_FOUND; 22138b04ffc1Sbeveloper } 22148b04ffc1Sbeveloper 22158b04ffc1Sbeveloper ASSERT(node_info.internal_id == in_info.flavor_id); 22168b04ffc1Sbeveloper 2217d91580cdSbeveloper printf("BMediaRoster::InstantiateDormantNode: name \"%s\", info \"%s\", flavor_flags 0x%lX, internal_id %ld, possible_count %ld\n", 22188b04ffc1Sbeveloper node_info.name, node_info.info, node_info.flavor_flags, node_info.internal_id, node_info.possible_count); 22198b04ffc1Sbeveloper 22208b04ffc1Sbeveloper #if DEBUG 22218b04ffc1Sbeveloper if (flags & B_FLAVOR_IS_LOCAL) 22228b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_LOCAL\n"); 22238b04ffc1Sbeveloper if (flags & B_FLAVOR_IS_GLOBAL) 22248b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: caller requested B_FLAVOR_IS_GLOBAL\n"); 22258b04ffc1Sbeveloper if (node_info.flavor_flags & B_FLAVOR_IS_LOCAL) 22268b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_LOCAL\n"); 22278b04ffc1Sbeveloper if (node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) 22288b04ffc1Sbeveloper printf("BMediaRoster::InstantiateDormantNode: node requires B_FLAVOR_IS_GLOBAL\n"); 22298b04ffc1Sbeveloper #endif 22308b04ffc1Sbeveloper 22318b04ffc1Sbeveloper // Make sure that flags demanded by the dormant node and those requested 22328b04ffc1Sbeveloper // by the caller are not incompatible. 22338b04ffc1Sbeveloper if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) && (flags & B_FLAVOR_IS_LOCAL)) { 22345ac4fbd7Sbeveloper ERROR("BMediaRoster::InstantiateDormantNode: requested B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n"); 2235626824eaSbeveloper return B_NAME_NOT_FOUND; 22368b04ffc1Sbeveloper } 22378b04ffc1Sbeveloper if ((node_info.flavor_flags & B_FLAVOR_IS_LOCAL) && (flags & B_FLAVOR_IS_GLOBAL)) { 22385ac4fbd7Sbeveloper ERROR("BMediaRoster::InstantiateDormantNode: requested B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n"); 2239626824eaSbeveloper return B_NAME_NOT_FOUND; 22408b04ffc1Sbeveloper } 224154187cc6Sbeveloper 22428b04ffc1Sbeveloper // If either the node, or the caller requested to make the instance global 22438b04ffc1Sbeveloper // we will do it by forwarding this request into the media_addon_server, which 22448b04ffc1Sbeveloper // in turn will call BMediaRosterEx::InstantiateDormantNode to create the node 22458b04ffc1Sbeveloper // there and make it globally available. 22468b04ffc1Sbeveloper if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) || (flags & B_FLAVOR_IS_GLOBAL)) { 22478b04ffc1Sbeveloper 2248cf4e2277Sbeveloper printf("BMediaRoster::InstantiateDormantNode: creating global object in media_addon_server\n"); 2249cf4e2277Sbeveloper 22508b04ffc1Sbeveloper addonserver_instantiate_dormant_node_request request; 22518b04ffc1Sbeveloper addonserver_instantiate_dormant_node_reply reply; 22528b04ffc1Sbeveloper request.addonid = in_info.addon; 22538b04ffc1Sbeveloper request.flavorid = in_info.flavor_id; 225454187cc6Sbeveloper request.creator_team = team; // creator team is allowed to also release global nodes 22558b04ffc1Sbeveloper rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply)); 22568b04ffc1Sbeveloper if (rv == B_OK) { 22578b04ffc1Sbeveloper *out_node = reply.node; 22588b04ffc1Sbeveloper } 22598b04ffc1Sbeveloper 22608b04ffc1Sbeveloper } else { 22618b04ffc1Sbeveloper 226254187cc6Sbeveloper // creator team = -1, as this is a local node 2263626824eaSbeveloper rv = MediaRosterEx(this)->InstantiateDormantNode(in_info.addon, in_info.flavor_id, -1, out_node); 2264626824eaSbeveloper 22658b04ffc1Sbeveloper } 2266626824eaSbeveloper if (rv != B_OK) { 2267626824eaSbeveloper *out_node = media_node::null; 2268626824eaSbeveloper return B_NAME_NOT_FOUND; 2269626824eaSbeveloper } 2270626824eaSbeveloper return B_OK; 22718b04ffc1Sbeveloper } 22728b04ffc1Sbeveloper 22738b04ffc1Sbeveloper 22748b04ffc1Sbeveloper status_t 22758b04ffc1Sbeveloper BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, 22768b04ffc1Sbeveloper media_node * out_node) 22778b04ffc1Sbeveloper { 22788b04ffc1Sbeveloper return InstantiateDormantNode(in_info, out_node, 0); 22798b04ffc1Sbeveloper } 22808b04ffc1Sbeveloper 22818b04ffc1Sbeveloper 22828b04ffc1Sbeveloper status_t 228352a38012Sejakowatz BMediaRoster::GetDormantNodeFor(const media_node & node, 228452a38012Sejakowatz dormant_node_info * out_info) 228552a38012Sejakowatz { 228685dfab2bSbeveloper CALLED(); 228785dfab2bSbeveloper if (out_info == NULL) 228885dfab2bSbeveloper return B_BAD_VALUE; 228940f36b03Sbeveloper if (IS_INVALID_NODE(node)) 229085dfab2bSbeveloper return B_MEDIA_BAD_NODE; 229152a38012Sejakowatz 229285dfab2bSbeveloper server_get_dormant_node_for_request request; 229385dfab2bSbeveloper server_get_dormant_node_for_reply reply; 229485dfab2bSbeveloper status_t rv; 229585dfab2bSbeveloper 229685dfab2bSbeveloper request.node = node; 229785dfab2bSbeveloper 22981299bfb2Sbeveloper rv = QueryServer(SERVER_GET_DORMANT_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply)); 229985dfab2bSbeveloper if (rv != B_OK) 230085dfab2bSbeveloper return rv; 230185dfab2bSbeveloper 230285dfab2bSbeveloper *out_info = reply.node_info; 230385dfab2bSbeveloper return B_OK; 230452a38012Sejakowatz } 230552a38012Sejakowatz 230652a38012Sejakowatz status_t 23078b04ffc1Sbeveloper BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonid, 23088b04ffc1Sbeveloper int32 flavorid, 230952a38012Sejakowatz dormant_flavor_info * out_flavor) 231052a38012Sejakowatz { 231152a38012Sejakowatz CALLED(); 23129bedd42cSbeveloper if (out_flavor == NULL) 23139bedd42cSbeveloper return B_BAD_VALUE; 231452a38012Sejakowatz 231552a38012Sejakowatz xfer_server_get_dormant_flavor_info msg; 231652a38012Sejakowatz xfer_server_get_dormant_flavor_info_reply *reply; 231752a38012Sejakowatz port_id port; 231852a38012Sejakowatz status_t rv; 231952a38012Sejakowatz int32 code; 232052a38012Sejakowatz 23214295907bSbeveloper port = find_port(MEDIA_SERVER_PORT_NAME); 232252a38012Sejakowatz if (port <= B_OK) 232352a38012Sejakowatz return B_ERROR; 232452a38012Sejakowatz 232552a38012Sejakowatz reply = (xfer_server_get_dormant_flavor_info_reply *) malloc(16000); 232652a38012Sejakowatz if (reply == 0) 232752a38012Sejakowatz return B_ERROR; 232852a38012Sejakowatz 23298b04ffc1Sbeveloper msg.addon = addonid; 23308b04ffc1Sbeveloper msg.flavor_id = flavorid; 233152a38012Sejakowatz msg.reply_port = _PortPool->GetPort(); 233252a38012Sejakowatz rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg)); 233352a38012Sejakowatz if (rv != B_OK) { 233452a38012Sejakowatz free(reply); 233552a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 233652a38012Sejakowatz return rv; 233752a38012Sejakowatz } 233852a38012Sejakowatz rv = read_port(msg.reply_port, &code, reply, 16000); 233952a38012Sejakowatz _PortPool->PutPort(msg.reply_port); 234052a38012Sejakowatz 234152a38012Sejakowatz if (rv < B_OK) { 234252a38012Sejakowatz free(reply); 234352a38012Sejakowatz return rv; 234452a38012Sejakowatz } 234552a38012Sejakowatz 234652a38012Sejakowatz if (reply->result == B_OK) 234752a38012Sejakowatz rv = out_flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size); 234852a38012Sejakowatz else 234952a38012Sejakowatz rv = reply->result; 235052a38012Sejakowatz 235152a38012Sejakowatz free(reply); 235252a38012Sejakowatz return rv; 235352a38012Sejakowatz } 235452a38012Sejakowatz 23558b04ffc1Sbeveloper status_t 23568b04ffc1Sbeveloper BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info & in_dormant, 23578b04ffc1Sbeveloper dormant_flavor_info * out_flavor) 23588b04ffc1Sbeveloper { 23598b04ffc1Sbeveloper return MediaRosterEx(this)->GetDormantFlavorInfo(in_dormant.addon, in_dormant.flavor_id, out_flavor); 23608b04ffc1Sbeveloper } 236152a38012Sejakowatz 236260f15390Sbeveloper // Reports in outLatency the maximum latency found downstream from 236360f15390Sbeveloper // the specified BBufferProducer, producer, given the current connections. 236452a38012Sejakowatz status_t 236552a38012Sejakowatz BMediaRoster::GetLatencyFor(const media_node & producer, 236652a38012Sejakowatz bigtime_t * out_latency) 236752a38012Sejakowatz { 236860f15390Sbeveloper CALLED(); 236960f15390Sbeveloper if (out_latency == NULL) 237060f15390Sbeveloper return B_BAD_VALUE; 237160f15390Sbeveloper if (IS_INVALID_NODE(producer)) 237260f15390Sbeveloper return B_MEDIA_BAD_NODE; 237360f15390Sbeveloper if ((producer.kind & B_BUFFER_PRODUCER) == 0) 237460f15390Sbeveloper return B_MEDIA_BAD_NODE; 237560f15390Sbeveloper 237660f15390Sbeveloper producer_get_latency_request request; 237760f15390Sbeveloper producer_get_latency_reply reply; 237860f15390Sbeveloper status_t rv; 237960f15390Sbeveloper 238060f15390Sbeveloper rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request, sizeof(request), &reply, sizeof(reply)); 238160f15390Sbeveloper if (rv != B_OK) 238260f15390Sbeveloper return rv; 238360f15390Sbeveloper 238460f15390Sbeveloper *out_latency = reply.latency; 238560f15390Sbeveloper 238660f15390Sbeveloper printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency); 2387aac800c2Sbeveloper return B_OK; 238852a38012Sejakowatz } 238952a38012Sejakowatz 239052a38012Sejakowatz 239152a38012Sejakowatz status_t 239252a38012Sejakowatz BMediaRoster::GetInitialLatencyFor(const media_node & producer, 239352a38012Sejakowatz bigtime_t * out_latency, 2394aac800c2Sbeveloper uint32 * out_flags /* = NULL */) 239552a38012Sejakowatz { 2396b65a0ac5SJérôme Duval CALLED(); 2397b65a0ac5SJérôme Duval if (out_latency == NULL) 2398b65a0ac5SJérôme Duval return B_BAD_VALUE; 2399b65a0ac5SJérôme Duval if (IS_INVALID_NODE(producer)) 2400b65a0ac5SJérôme Duval return B_MEDIA_BAD_NODE; 2401b65a0ac5SJérôme Duval if ((producer.kind & B_BUFFER_PRODUCER) == 0) 2402b65a0ac5SJérôme Duval return B_MEDIA_BAD_NODE; 2403b65a0ac5SJérôme Duval 2404b65a0ac5SJérôme Duval producer_get_initial_latency_request request; 2405b65a0ac5SJérôme Duval producer_get_initial_latency_reply reply; 2406b65a0ac5SJérôme Duval status_t rv; 2407b65a0ac5SJérôme Duval 2408b65a0ac5SJérôme Duval rv = QueryPort(producer.port, PRODUCER_GET_INITIAL_LATENCY, &request, sizeof(request), &reply, sizeof(reply)); 2409b65a0ac5SJérôme Duval if (rv != B_OK) 2410b65a0ac5SJérôme Duval return rv; 2411b65a0ac5SJérôme Duval 2412b65a0ac5SJérôme Duval *out_latency = reply.initial_latency; 2413aac800c2Sbeveloper if (out_flags) 2414b65a0ac5SJérôme Duval *out_flags = reply.flags; 2415b65a0ac5SJérôme Duval 2416b65a0ac5SJérôme Duval printf("BMediaRoster::GetInitialLatencyFor producer %ld has maximum initial latency %Ld\n", producer.node, *out_latency); 2417aac800c2Sbeveloper return B_OK; 241852a38012Sejakowatz } 241952a38012Sejakowatz 242052a38012Sejakowatz 242152a38012Sejakowatz status_t 242252a38012Sejakowatz BMediaRoster::GetStartLatencyFor(const media_node & time_source, 242352a38012Sejakowatz bigtime_t * out_latency) 242452a38012Sejakowatz { 2425*fc8b28b6SJérôme Duval CALLED(); 2426*fc8b28b6SJérôme Duval if (out_latency == NULL) 2427*fc8b28b6SJérôme Duval return B_BAD_VALUE; 2428*fc8b28b6SJérôme Duval if (IS_INVALID_NODE(time_source)) 2429*fc8b28b6SJérôme Duval return B_MEDIA_BAD_NODE; 2430*fc8b28b6SJérôme Duval if ((time_source.kind & B_TIME_SOURCE) == 0) 2431*fc8b28b6SJérôme Duval return B_MEDIA_BAD_NODE; 2432*fc8b28b6SJérôme Duval 2433*fc8b28b6SJérôme Duval timesource_get_start_latency_request request; 2434*fc8b28b6SJérôme Duval timesource_get_start_latency_reply reply; 2435*fc8b28b6SJérôme Duval status_t rv; 2436*fc8b28b6SJérôme Duval 2437*fc8b28b6SJérôme Duval rv = QueryPort(time_source.port, TIMESOURCE_GET_START_LATENCY, &request, sizeof(request), &reply, sizeof(reply)); 2438*fc8b28b6SJérôme Duval if (rv != B_OK) 2439*fc8b28b6SJérôme Duval return rv; 2440*fc8b28b6SJérôme Duval 2441*fc8b28b6SJérôme Duval *out_latency = reply.start_latency; 2442*fc8b28b6SJérôme Duval 2443*fc8b28b6SJérôme Duval printf("BMediaRoster::GetStartLatencyFor timesource %ld has maximum initial latency %Ld\n", time_source.node, *out_latency); 2444aac800c2Sbeveloper return B_OK; 244552a38012Sejakowatz } 244652a38012Sejakowatz 244752a38012Sejakowatz 244852a38012Sejakowatz status_t 244952a38012Sejakowatz BMediaRoster::GetFileFormatsFor(const media_node & file_interface, 245052a38012Sejakowatz media_file_format * out_formats, 245152a38012Sejakowatz int32 * io_num_infos) 245252a38012Sejakowatz { 245352a38012Sejakowatz UNIMPLEMENTED(); 245452a38012Sejakowatz return B_ERROR; 245552a38012Sejakowatz } 245652a38012Sejakowatz 245752a38012Sejakowatz 245852a38012Sejakowatz status_t 245952a38012Sejakowatz BMediaRoster::SetRefFor(const media_node & file_interface, 246052a38012Sejakowatz const entry_ref & file, 246152a38012Sejakowatz bool create_and_truncate, 246252a38012Sejakowatz bigtime_t * out_length) /* if create is false */ 246352a38012Sejakowatz { 246452a38012Sejakowatz UNIMPLEMENTED(); 246552a38012Sejakowatz return B_ERROR; 246652a38012Sejakowatz } 246752a38012Sejakowatz 246852a38012Sejakowatz 246952a38012Sejakowatz status_t 247052a38012Sejakowatz BMediaRoster::GetRefFor(const media_node & node, 247152a38012Sejakowatz entry_ref * out_file, 247252a38012Sejakowatz BMimeType * mime_type) 247352a38012Sejakowatz { 247452a38012Sejakowatz UNIMPLEMENTED(); 247552a38012Sejakowatz return B_ERROR; 247652a38012Sejakowatz } 247752a38012Sejakowatz 247852a38012Sejakowatz 247952a38012Sejakowatz status_t 248052a38012Sejakowatz BMediaRoster::SniffRefFor(const media_node & file_interface, 248152a38012Sejakowatz const entry_ref & file, 248252a38012Sejakowatz BMimeType * mime_type, 248352a38012Sejakowatz float * out_capability) 248452a38012Sejakowatz { 248552a38012Sejakowatz UNIMPLEMENTED(); 248652a38012Sejakowatz return B_ERROR; 248752a38012Sejakowatz } 248852a38012Sejakowatz 248952a38012Sejakowatz 249052a38012Sejakowatz /* This is the generic "here's a file, now can someone please play it" interface */ 249152a38012Sejakowatz status_t 249252a38012Sejakowatz BMediaRoster::SniffRef(const entry_ref & file, 249352a38012Sejakowatz uint64 require_node_kinds, /* if you need an EntityInterface or BufferConsumer or something */ 249452a38012Sejakowatz dormant_node_info * out_node, 249552a38012Sejakowatz BMimeType * mime_type) 249652a38012Sejakowatz { 249752a38012Sejakowatz UNIMPLEMENTED(); 249852a38012Sejakowatz return B_ERROR; 249952a38012Sejakowatz } 250052a38012Sejakowatz 250152a38012Sejakowatz 250252a38012Sejakowatz status_t 250352a38012Sejakowatz BMediaRoster::GetDormantNodeForType(const BMimeType & type, 250452a38012Sejakowatz uint64 require_node_kinds, 250552a38012Sejakowatz dormant_node_info * out_node) 250652a38012Sejakowatz { 250752a38012Sejakowatz UNIMPLEMENTED(); 250852a38012Sejakowatz return B_ERROR; 250952a38012Sejakowatz } 251052a38012Sejakowatz 251152a38012Sejakowatz 251252a38012Sejakowatz status_t 251352a38012Sejakowatz BMediaRoster::GetReadFileFormatsFor(const dormant_node_info & in_node, 251452a38012Sejakowatz media_file_format * out_read_formats, 251552a38012Sejakowatz int32 in_read_count, 251652a38012Sejakowatz int32 * out_read_count) 251752a38012Sejakowatz { 251852a38012Sejakowatz UNIMPLEMENTED(); 251952a38012Sejakowatz return B_ERROR; 252052a38012Sejakowatz } 252152a38012Sejakowatz 252252a38012Sejakowatz 252352a38012Sejakowatz status_t 252452a38012Sejakowatz BMediaRoster::GetWriteFileFormatsFor(const dormant_node_info & in_node, 252552a38012Sejakowatz media_file_format * out_write_formats, 252652a38012Sejakowatz int32 in_write_count, 252752a38012Sejakowatz int32 * out_write_count) 252852a38012Sejakowatz { 252952a38012Sejakowatz UNIMPLEMENTED(); 253052a38012Sejakowatz return B_ERROR; 253152a38012Sejakowatz } 253252a38012Sejakowatz 253352a38012Sejakowatz 253452a38012Sejakowatz status_t 253552a38012Sejakowatz BMediaRoster::GetFormatFor(const media_output & output, 253652a38012Sejakowatz media_format * io_format, 253752a38012Sejakowatz uint32 flags) 253852a38012Sejakowatz { 25399bedd42cSbeveloper CALLED(); 25409bedd42cSbeveloper if (io_format == NULL) 25419bedd42cSbeveloper return B_BAD_VALUE; 25429bedd42cSbeveloper if ((output.node.kind & B_BUFFER_PRODUCER) == 0) 25439bedd42cSbeveloper return B_MEDIA_BAD_NODE; 25449bedd42cSbeveloper if (IS_INVALID_SOURCE(output.source)) 25459bedd42cSbeveloper return B_MEDIA_BAD_SOURCE; 25469bedd42cSbeveloper 25479bedd42cSbeveloper producer_format_suggestion_requested_request request; 25489bedd42cSbeveloper producer_format_suggestion_requested_reply reply; 25499bedd42cSbeveloper status_t rv; 25509bedd42cSbeveloper 25519bedd42cSbeveloper request.type = B_MEDIA_UNKNOWN_TYPE; 25529bedd42cSbeveloper request.quality = 0; // XXX what should this be? 25539bedd42cSbeveloper 25549bedd42cSbeveloper rv = QueryPort(output.source.port, PRODUCER_FORMAT_SUGGESTION_REQUESTED, &request, sizeof(request), &reply, sizeof(reply)); 25559bedd42cSbeveloper if (rv != B_OK) 25569bedd42cSbeveloper return rv; 25579bedd42cSbeveloper 25589bedd42cSbeveloper *io_format = reply.format; 25599bedd42cSbeveloper return B_OK; 256052a38012Sejakowatz } 256152a38012Sejakowatz 256252a38012Sejakowatz 256352a38012Sejakowatz status_t 256452a38012Sejakowatz BMediaRoster::GetFormatFor(const media_input & input, 256552a38012Sejakowatz media_format * io_format, 256652a38012Sejakowatz uint32 flags) 256752a38012Sejakowatz { 25689bedd42cSbeveloper CALLED(); 25699bedd42cSbeveloper if (io_format == NULL) 25709bedd42cSbeveloper return B_BAD_VALUE; 25719bedd42cSbeveloper if ((input.node.kind & B_BUFFER_CONSUMER) == 0) 25729bedd42cSbeveloper return B_MEDIA_BAD_NODE; 25739bedd42cSbeveloper if (IS_INVALID_DESTINATION(input.destination)) 25749bedd42cSbeveloper return B_MEDIA_BAD_DESTINATION; 25759bedd42cSbeveloper 25769bedd42cSbeveloper consumer_accept_format_request request; 25779bedd42cSbeveloper consumer_accept_format_reply reply; 25789bedd42cSbeveloper status_t rv; 25799bedd42cSbeveloper 25809bedd42cSbeveloper request.dest = input.destination; 25819bedd42cSbeveloper memset(&request.format, 0, sizeof(request.format)); // wildcard 25829bedd42cSbeveloper 25839bedd42cSbeveloper rv = QueryPort(input.destination.port, CONSUMER_ACCEPT_FORMAT, &request, sizeof(request), &reply, sizeof(reply)); 25849bedd42cSbeveloper if (rv != B_OK) 25859bedd42cSbeveloper return rv; 25869bedd42cSbeveloper 25879bedd42cSbeveloper *io_format = reply.format; 25889bedd42cSbeveloper return B_OK; 258952a38012Sejakowatz } 259052a38012Sejakowatz 259152a38012Sejakowatz 259252a38012Sejakowatz status_t 259352a38012Sejakowatz BMediaRoster::GetFormatFor(const media_node & node, 259452a38012Sejakowatz media_format * io_format, 259552a38012Sejakowatz float quality) 259652a38012Sejakowatz { 259752a38012Sejakowatz UNIMPLEMENTED(); 25989bedd42cSbeveloper if (io_format == NULL) 25999bedd42cSbeveloper return B_BAD_VALUE; 26009bedd42cSbeveloper if (IS_INVALID_NODE(node)) 26019bedd42cSbeveloper return B_MEDIA_BAD_NODE; 26029bedd42cSbeveloper if ((node.kind & (B_BUFFER_CONSUMER | B_BUFFER_PRODUCER)) == 0) 26039bedd42cSbeveloper return B_MEDIA_BAD_NODE; 26049bedd42cSbeveloper 26059bedd42cSbeveloper 260652a38012Sejakowatz return B_ERROR; 260752a38012Sejakowatz } 260852a38012Sejakowatz 260952a38012Sejakowatz 261052a38012Sejakowatz ssize_t 261152a38012Sejakowatz BMediaRoster::GetNodeAttributesFor(const media_node & node, 261252a38012Sejakowatz media_node_attribute * outArray, 261352a38012Sejakowatz size_t inMaxCount) 261452a38012Sejakowatz { 261552a38012Sejakowatz UNIMPLEMENTED(); 261652a38012Sejakowatz return B_ERROR; 261752a38012Sejakowatz } 261852a38012Sejakowatz 261952a38012Sejakowatz 262052a38012Sejakowatz media_node_id 262152a38012Sejakowatz BMediaRoster::NodeIDFor(port_id source_or_destination_port) 262252a38012Sejakowatz { 26239e9417d2Sbeveloper CALLED(); 26249e9417d2Sbeveloper 26259e9417d2Sbeveloper server_node_id_for_request request; 26269e9417d2Sbeveloper server_node_id_for_reply reply; 26279e9417d2Sbeveloper status_t rv; 26289e9417d2Sbeveloper 26299e9417d2Sbeveloper request.port = source_or_destination_port; 26309e9417d2Sbeveloper 26319e9417d2Sbeveloper rv = QueryServer(SERVER_NODE_ID_FOR, &request, sizeof(request), &reply, sizeof(reply)); 26329e9417d2Sbeveloper if (rv != B_OK) { 26335ac4fbd7Sbeveloper ERROR("BMediaRoster::NodeIDFor: failed (error %#lx)\n", rv); 26349e9417d2Sbeveloper return -1; 26359e9417d2Sbeveloper } 26369e9417d2Sbeveloper 26379e9417d2Sbeveloper return reply.nodeid; 263852a38012Sejakowatz } 263952a38012Sejakowatz 264052a38012Sejakowatz 264152a38012Sejakowatz status_t 264252a38012Sejakowatz BMediaRoster::GetInstancesFor(media_addon_id addon, 264352a38012Sejakowatz int32 flavor, 264452a38012Sejakowatz media_node_id * out_id, 264552a38012Sejakowatz int32 * io_count) 264652a38012Sejakowatz { 264785dfab2bSbeveloper CALLED(); 26488b9700adSJérôme Duval if (out_id == NULL) 264985dfab2bSbeveloper return B_BAD_VALUE; 26508b9700adSJérôme Duval if (io_count && *io_count <= 0) 265185dfab2bSbeveloper return B_BAD_VALUE; 265285dfab2bSbeveloper 265385dfab2bSbeveloper server_get_instances_for_request request; 265485dfab2bSbeveloper server_get_instances_for_reply reply; 265585dfab2bSbeveloper status_t rv; 265685dfab2bSbeveloper 26578b9700adSJérôme Duval request.maxcount = (io_count ? *io_count : 1); 265885dfab2bSbeveloper request.addon_id = addon; 265985dfab2bSbeveloper request.addon_flavor_id = flavor; 266085dfab2bSbeveloper 266185dfab2bSbeveloper rv = QueryServer(SERVER_GET_INSTANCES_FOR, &request, sizeof(request), &reply, sizeof(reply)); 266285dfab2bSbeveloper if (rv != B_OK) { 26635ac4fbd7Sbeveloper ERROR("BMediaRoster::GetLiveNodes failed\n"); 266485dfab2bSbeveloper return rv; 266552a38012Sejakowatz } 266652a38012Sejakowatz 26678b9700adSJérôme Duval if(io_count) 266885dfab2bSbeveloper *io_count = reply.count; 266985dfab2bSbeveloper if (reply.count > 0) 267085dfab2bSbeveloper memcpy(out_id, reply.node_id, sizeof(media_node_id) * reply.count); 267185dfab2bSbeveloper 267285dfab2bSbeveloper return B_OK; 267385dfab2bSbeveloper } 267452a38012Sejakowatz 267552a38012Sejakowatz 267652a38012Sejakowatz status_t 267752a38012Sejakowatz BMediaRoster::SetRealtimeFlags(uint32 in_enabled) 267852a38012Sejakowatz { 267952a38012Sejakowatz UNIMPLEMENTED(); 268052a38012Sejakowatz return B_ERROR; 268152a38012Sejakowatz } 268252a38012Sejakowatz 268352a38012Sejakowatz 268452a38012Sejakowatz status_t 268552a38012Sejakowatz BMediaRoster::GetRealtimeFlags(uint32 * out_enabled) 268652a38012Sejakowatz { 268752a38012Sejakowatz UNIMPLEMENTED(); 268852a38012Sejakowatz return B_ERROR; 268952a38012Sejakowatz } 269052a38012Sejakowatz 269152a38012Sejakowatz 269252a38012Sejakowatz ssize_t 269352a38012Sejakowatz BMediaRoster::AudioBufferSizeFor(int32 channel_count, 269452a38012Sejakowatz uint32 sample_format, 269552a38012Sejakowatz float frame_rate, 269652a38012Sejakowatz bus_type bus_kind) 269752a38012Sejakowatz { 269852a38012Sejakowatz UNIMPLEMENTED(); 269952a38012Sejakowatz return 4096; 270052a38012Sejakowatz } 270152a38012Sejakowatz 270252a38012Sejakowatz 270352a38012Sejakowatz /* Use MediaFlags to inquire about specific features of the Media Kit. */ 270452a38012Sejakowatz /* Returns < 0 for "not present", positive size for output data size. */ 270552a38012Sejakowatz /* 0 means that the capability is present, but no data about it. */ 270652a38012Sejakowatz /* static */ ssize_t 270752a38012Sejakowatz BMediaRoster::MediaFlags(media_flags cap, 270852a38012Sejakowatz void * buf, 270952a38012Sejakowatz size_t maxSize) 271052a38012Sejakowatz { 271152a38012Sejakowatz UNIMPLEMENTED(); 271252a38012Sejakowatz return 0; 271352a38012Sejakowatz } 271452a38012Sejakowatz 271552a38012Sejakowatz 271652a38012Sejakowatz /* BLooper overrides */ 271752a38012Sejakowatz /* virtual */ void 271852a38012Sejakowatz BMediaRoster::MessageReceived(BMessage * message) 271952a38012Sejakowatz { 2720cf4e2277Sbeveloper switch (message->what) { 2721cf4e2277Sbeveloper case 'PING': 2722cf4e2277Sbeveloper { 27236396865dSbeveloper // media_server plays ping-pong with the BMediaRosters 27246396865dSbeveloper // to detect dead teams. Normal communication uses ports. 27256396865dSbeveloper static BMessage pong('PONG'); 27266396865dSbeveloper message->SendReply(&pong, static_cast<BHandler *>(NULL), 2000000); 27276396865dSbeveloper return; 27286396865dSbeveloper } 27296396865dSbeveloper 2730cf4e2277Sbeveloper case NODE_FINAL_RELEASE: 2731cf4e2277Sbeveloper { 2732cf4e2277Sbeveloper // this function is called by a BMediaNode to delete 2733cf4e2277Sbeveloper // itself, as this needs to be done from another thread 2734cf4e2277Sbeveloper // context, it is done here. 2735cf4e2277Sbeveloper // XXX If a node is released using BMediaRoster::ReleaseNode() 2736cf4e2277Sbeveloper // XXX instead of using BMediaNode::Release() / BMediaNode::Acquire() 2737cf4e2277Sbeveloper // XXX fRefCount of the BMediaNode will not be correct. 2738cf4e2277Sbeveloper 2739cf4e2277Sbeveloper BMediaNode *node; 2740cf4e2277Sbeveloper message->FindPointer("node", reinterpret_cast<void **>(&node)); 2741cf4e2277Sbeveloper 274254187cc6Sbeveloper TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE saving node %ld configuration\n", node->ID()); 274354187cc6Sbeveloper MediaRosterEx(BMediaRoster::Roster())->SaveNodeConfiguration(node); 2744cf4e2277Sbeveloper 274554187cc6Sbeveloper TRACE("BMediaRoster::MessageReceived NODE_FINAL_RELEASE releasing node %ld\n", node->ID()); 2746cf4e2277Sbeveloper node->DeleteHook(node); // we don't call Release(), see above! 2747cf4e2277Sbeveloper return; 2748cf4e2277Sbeveloper } 2749cf4e2277Sbeveloper } 27506396865dSbeveloper printf("BMediaRoster::MessageReceived: unknown message!\n"); 27516396865dSbeveloper message->PrintToStream(); 275252a38012Sejakowatz } 275352a38012Sejakowatz 275452a38012Sejakowatz /* virtual */ bool 275552a38012Sejakowatz BMediaRoster::QuitRequested() 275652a38012Sejakowatz { 275752a38012Sejakowatz UNIMPLEMENTED(); 275852a38012Sejakowatz return true; 275952a38012Sejakowatz } 276052a38012Sejakowatz 276152a38012Sejakowatz /* virtual */ BHandler * 276252a38012Sejakowatz BMediaRoster::ResolveSpecifier(BMessage *msg, 276352a38012Sejakowatz int32 index, 276452a38012Sejakowatz BMessage *specifier, 276552a38012Sejakowatz int32 form, 276652a38012Sejakowatz const char *property) 276752a38012Sejakowatz { 276852a38012Sejakowatz UNIMPLEMENTED(); 276952a38012Sejakowatz return 0; 277052a38012Sejakowatz } 277152a38012Sejakowatz 277252a38012Sejakowatz 277352a38012Sejakowatz /* virtual */ status_t 277452a38012Sejakowatz BMediaRoster::GetSupportedSuites(BMessage *data) 277552a38012Sejakowatz { 277652a38012Sejakowatz UNIMPLEMENTED(); 277752a38012Sejakowatz return B_ERROR; 277852a38012Sejakowatz } 277952a38012Sejakowatz 278052a38012Sejakowatz 278152a38012Sejakowatz BMediaRoster::~BMediaRoster() 278252a38012Sejakowatz { 278352a38012Sejakowatz CALLED(); 27846396865dSbeveloper 27856396865dSbeveloper // unregister this application with the media server 27866396865dSbeveloper server_unregister_app_request request; 27876396865dSbeveloper server_unregister_app_reply reply; 27886396865dSbeveloper request.team = team; 27896396865dSbeveloper QueryServer(SERVER_UNREGISTER_APP, &request, sizeof(request), &reply, sizeof(reply)); 279052a38012Sejakowatz } 279152a38012Sejakowatz 279252a38012Sejakowatz 279352a38012Sejakowatz /************************************************************* 279452a38012Sejakowatz * private BMediaRoster 279552a38012Sejakowatz *************************************************************/ 279652a38012Sejakowatz 279752a38012Sejakowatz // deprecated call 279852a38012Sejakowatz status_t 279952a38012Sejakowatz BMediaRoster::SetOutputBuffersFor(const media_source & output, 280052a38012Sejakowatz BBufferGroup * group, 280152a38012Sejakowatz bool will_reclaim ) 280252a38012Sejakowatz { 280352a38012Sejakowatz UNIMPLEMENTED(); 28049e9417d2Sbeveloper debugger("BMediaRoster::SetOutputBuffersFor missing\n"); 280552a38012Sejakowatz return B_ERROR; 280652a38012Sejakowatz } 280752a38012Sejakowatz 280852a38012Sejakowatz 280952a38012Sejakowatz /* FBC stuffing (Mmmh, Stuffing!) */ 281052a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_0(void *) { return B_ERROR; } 281152a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_1(void *) { return B_ERROR; } 281252a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_2(void *) { return B_ERROR; } 281352a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_3(void *) { return B_ERROR; } 281452a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_4(void *) { return B_ERROR; } 281552a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_5(void *) { return B_ERROR; } 281652a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_6(void *) { return B_ERROR; } 281752a38012Sejakowatz status_t BMediaRoster::_Reserved_MediaRoster_7(void *) { return B_ERROR; } 281852a38012Sejakowatz 281952a38012Sejakowatz 282052a38012Sejakowatz BMediaRoster::BMediaRoster() : 28216396865dSbeveloper BLooper("_BMediaRoster_", B_URGENT_DISPLAY_PRIORITY, B_LOOPER_PORT_DEFAULT_CAPACITY) 282252a38012Sejakowatz { 282352a38012Sejakowatz CALLED(); 28246396865dSbeveloper 28256396865dSbeveloper // start the looper 28266396865dSbeveloper Run(); 28276396865dSbeveloper 28286396865dSbeveloper // register this application with the media server 28296396865dSbeveloper server_register_app_request request; 28306396865dSbeveloper server_register_app_reply reply; 28316396865dSbeveloper request.team = team; 28326396865dSbeveloper request.messenger = BMessenger(NULL, this); 28336396865dSbeveloper QueryServer(SERVER_REGISTER_APP, &request, sizeof(request), &reply, sizeof(reply)); 283452a38012Sejakowatz } 283552a38012Sejakowatz 28366396865dSbeveloper 283752a38012Sejakowatz /* static */ status_t 283852a38012Sejakowatz BMediaRoster::ParseCommand(BMessage & reply) 283952a38012Sejakowatz { 284052a38012Sejakowatz UNIMPLEMENTED(); 284152a38012Sejakowatz return B_ERROR; 284252a38012Sejakowatz } 284352a38012Sejakowatz 284452a38012Sejakowatz 284552a38012Sejakowatz status_t 284652a38012Sejakowatz BMediaRoster::GetDefaultInfo(media_node_id for_default, 284752a38012Sejakowatz BMessage & out_config) 284852a38012Sejakowatz { 284952a38012Sejakowatz UNIMPLEMENTED(); 285052a38012Sejakowatz return B_ERROR; 285152a38012Sejakowatz } 285252a38012Sejakowatz 285352a38012Sejakowatz 285452a38012Sejakowatz 285552a38012Sejakowatz status_t 285652a38012Sejakowatz BMediaRoster::SetRunningDefault(media_node_id for_default, 285752a38012Sejakowatz const media_node & node) 285852a38012Sejakowatz { 285952a38012Sejakowatz UNIMPLEMENTED(); 286052a38012Sejakowatz return B_ERROR; 286152a38012Sejakowatz } 286252a38012Sejakowatz 286352a38012Sejakowatz 286452a38012Sejakowatz /************************************************************* 286552a38012Sejakowatz * static BMediaRoster variables 286652a38012Sejakowatz *************************************************************/ 286752a38012Sejakowatz 286852a38012Sejakowatz bool BMediaRoster::_isMediaServer; 286952a38012Sejakowatz port_id BMediaRoster::_mReplyPort; 287052a38012Sejakowatz int32 BMediaRoster::_mReplyPortRes; 287152a38012Sejakowatz int32 BMediaRoster::_mReplyPortUnavailCount; 287252a38012Sejakowatz BMediaRoster * BMediaRoster::_sDefault = NULL; 287352a38012Sejakowatz 2874