1 /* 2 * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files or portions 6 * thereof (the "Software"), to deal in the Software without restriction, 7 * including without limitation the rights to use, copy, modify, merge, 8 * publish, distribute, sublicense, and/or sell copies of the Software, 9 * and to permit persons to whom the Software is furnished to do so, subject 10 * to the following conditions: 11 * 12 * * Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * * Redistributions in binary form must reproduce the above copyright notice 16 * in the binary, as well as this list of conditions and the following 17 * disclaimer in the documentation and/or other materials provided with 18 * the distribution. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 * THE SOFTWARE. 27 * 28 */ 29 30 /* to comply with the license above, do not remove the following line */ 31 char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>"; 32 33 #include <Application.h> 34 #include <stdio.h> 35 #include <Messenger.h> 36 #include <MediaDefs.h> 37 #include <MediaFormats.h> 38 #include <Autolock.h> 39 #include <string.h> 40 #include "MMediaFilesManager.h" 41 #include "NotificationManager.h" 42 #include "ServerInterface.h" 43 #include "DataExchange.h" 44 #include "BufferManager.h" 45 #include "NodeManager.h" 46 #include "AddOnManager.h" 47 #include "AppManager.h" 48 #include "FormatManager.h" 49 #include "MediaMisc.h" 50 #include "media_server.h" 51 #include "debug.h" 52 53 /* 54 * 55 * An implementation of a new media_server for the OpenBeOS MediaKit 56 * Started by Marcus Overhagen <marcus@overhagen.de> on 2001-10-25 57 * 58 */ 59 60 AddOnManager * gAddOnManager; 61 AppManager * gAppManager; 62 BufferManager * gBufferManager; 63 FormatManager * gFormatManager; 64 MMediaFilesManager * gMMediaFilesManager; 65 NodeManager * gNodeManager; 66 NotificationManager * gNotificationManager; 67 68 namespace BPrivate { namespace media { 69 extern team_id team; 70 } } // BPrivate::media 71 72 73 #define REPLY_TIMEOUT ((bigtime_t)500000) 74 75 class ServerApp : BApplication 76 { 77 public: 78 ServerApp(); 79 ~ServerApp(); 80 81 bool QuitRequested(); 82 void HandleMessage(int32 code, void *data, size_t size); 83 void ArgvReceived(int32 argc, char **argv); 84 static int32 controlthread(void *arg); 85 // void StartSystemTimeSource(); 86 87 /* functionality not yet implemented 88 00014a00 T _ServerApp::_ServerApp(void) 89 00014e1c T _ServerApp::~_ServerApp(void) 90 00014ff4 T _ServerApp::MessageReceived(BMessage *); 91 00015840 T _ServerApp::QuitRequested(void) 92 00015b50 T _ServerApp::_DoNotify(command_data *) 93 00015d18 T _ServerApp::_UnregisterApp(long, bool) 94 00018e90 T _ServerApp::AddOnHost(void) 95 00019530 T _ServerApp::AboutRequested(void) 96 00019d04 T _ServerApp::AddPurgableBufferGroup(long, long, long, void *) 97 00019db8 T _ServerApp::CancelPurgableBufferGroupCleanup(long) 98 00019e50 T _ServerApp::DirtyWork(void) 99 0001a4bc T _ServerApp::ArgvReceived(long, char **) 100 0001a508 T _ServerApp::CleanupPurgedBufferGroup(_ServerApp::purgable_buffer_group const &, bool) 101 0001a5dc T _ServerApp::DirtyWorkLaunch(void *) 102 0001a634 T _ServerApp::SetQuitMode(bool) 103 0001a648 T _ServerApp::IsQuitMode(void) const 104 0001a658 T _ServerApp::BroadcastCurrentStateTo(BMessenger &) 105 0001adcc T _ServerApp::ReadyToRun(void) 106 */ 107 108 private: 109 port_id control_port; 110 thread_id control_thread; 111 112 BLocker *fLocker; 113 114 virtual void MessageReceived(BMessage *msg); 115 virtual void ReadyToRun(); 116 typedef BApplication inherited; 117 }; 118 119 ServerApp::ServerApp() 120 : BApplication(NEW_MEDIA_SERVER_SIGNATURE), 121 fLocker(new BLocker("media server locker")) 122 { 123 gNotificationManager = new NotificationManager; 124 gBufferManager = new BufferManager; 125 gAppManager = new AppManager; 126 gNodeManager = new NodeManager; 127 gMMediaFilesManager = new MMediaFilesManager; 128 gFormatManager = new FormatManager; 129 gAddOnManager = new AddOnManager; 130 131 control_port = create_port(64, MEDIA_SERVER_PORT_NAME); 132 control_thread = spawn_thread(controlthread, "media_server control", 105, this); 133 resume_thread(control_thread); 134 135 // StartSystemTimeSource(); 136 gNodeManager->LoadState(); 137 gFormatManager->LoadState(); 138 139 140 } 141 142 void ServerApp::ReadyToRun() 143 { 144 gAppManager->StartAddonServer(); 145 gAddOnManager->LoadState(); 146 } 147 148 ServerApp::~ServerApp() 149 { 150 TRACE("ServerApp::~ServerApp()\n"); 151 delete gAddOnManager; 152 delete gNotificationManager; 153 delete gBufferManager; 154 delete gAppManager; 155 delete gNodeManager; 156 delete gMMediaFilesManager; 157 delete gFormatManager; 158 delete fLocker; 159 delete_port(control_port); 160 status_t err; 161 wait_for_thread(control_thread,&err); 162 } 163 164 void ServerApp::ArgvReceived(int32 argc, char **argv) 165 { 166 for (int arg = 1; arg < argc; arg++) { 167 if (strstr(argv[arg], "dump")) { 168 gAppManager->Dump(); 169 gNodeManager->Dump(); 170 gBufferManager->Dump(); 171 gNotificationManager->Dump(); 172 gMMediaFilesManager->Dump(); 173 } 174 if (strstr(argv[arg], "buffer")) { 175 gBufferManager->Dump(); 176 } 177 if (strstr(argv[arg], "node")) { 178 gNodeManager->Dump(); 179 } 180 if (strstr(argv[arg], "quit")) { 181 PostMessage(B_QUIT_REQUESTED); 182 } 183 } 184 } 185 186 bool 187 ServerApp::QuitRequested() 188 { 189 TRACE("ServerApp::QuitRequested()\n"); 190 gMMediaFilesManager->SaveState(); 191 gNodeManager->SaveState(); 192 gFormatManager->SaveState(); 193 gAddOnManager->SaveState(); 194 gAppManager->TerminateAddonServer(); 195 return true; 196 } 197 198 /* 199 void 200 ServerApp::StartSystemTimeSource() 201 { 202 TRACE("StartSystemTimeSource enter\n"); 203 status_t rv; 204 205 TRACE("StartSystemTimeSource creating object\n"); 206 207 // register a dummy node 208 media_node node; 209 rv = gNodeManager->RegisterNode(&node.node, -1, 0, "System Clock", B_TIME_SOURCE, SYSTEM_TIMESOURCE_CONTROL_PORT, BPrivate::media::team); 210 ASSERT(rv == B_OK); 211 212 ASSERT(node.node == NODE_SYSTEM_TIMESOURCE_ID); 213 214 TRACE("StartSystemTimeSource setting as default\n"); 215 216 rv = gNodeManager->SetDefaultNode(SYSTEM_TIME_SOURCE, &node, NULL, NULL); 217 ASSERT(rv == B_OK); 218 219 TRACE("StartSystemTimeSource leave\n"); 220 } 221 */ 222 223 void 224 ServerApp::HandleMessage(int32 code, void *data, size_t size) 225 { 226 status_t rv; 227 TRACE("ServerApp::HandleMessage %#lx enter\n", code); 228 switch (code) { 229 case SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT: 230 { 231 const server_change_addon_flavor_instances_count_request *request = reinterpret_cast<const server_change_addon_flavor_instances_count_request *>(data); 232 server_change_addon_flavor_instances_count_reply reply; 233 ASSERT(request->delta == 1 || request->delta == -1); 234 if (request->delta == 1) 235 rv = gNodeManager->IncrementAddonFlavorInstancesCount(request->addonid, request->flavorid, request->team); 236 else 237 rv = gNodeManager->DecrementAddonFlavorInstancesCount(request->addonid, request->flavorid, request->team); 238 request->SendReply(rv, &reply, sizeof(reply)); 239 break; 240 } 241 242 case SERVER_RESCAN_DEFAULTS: 243 { 244 gNodeManager->RescanDefaultNodes(); 245 break; 246 } 247 248 case SERVER_REGISTER_ADDONSERVER: 249 { 250 const server_register_addonserver_request *request = reinterpret_cast<const server_register_addonserver_request *>(data); 251 server_register_addonserver_reply reply; 252 rv = gAppManager->RegisterAddonServer(request->team); 253 request->SendReply(rv, &reply, sizeof(reply)); 254 break; 255 } 256 257 case SERVER_REGISTER_APP: 258 { 259 const server_register_app_request *request = reinterpret_cast<const server_register_app_request *>(data); 260 server_register_app_reply reply; 261 rv = gAppManager->RegisterTeam(request->team, request->messenger); 262 request->SendReply(rv, &reply, sizeof(reply)); 263 break; 264 } 265 266 case SERVER_UNREGISTER_APP: 267 { 268 const server_unregister_app_request *request = reinterpret_cast<const server_unregister_app_request *>(data); 269 server_unregister_app_reply reply; 270 rv = gAppManager->UnregisterTeam(request->team); 271 request->SendReply(rv, &reply, sizeof(reply)); 272 break; 273 } 274 275 case SERVER_GET_MEDIAADDON_REF: 276 { 277 server_get_mediaaddon_ref_request *msg = (server_get_mediaaddon_ref_request *)data; 278 server_get_mediaaddon_ref_reply reply; 279 entry_ref tempref; 280 reply.result = gNodeManager->GetAddonRef(&tempref, msg->addonid); 281 reply.ref = tempref; 282 write_port(msg->reply_port, 0, &reply, sizeof(reply)); 283 break; 284 } 285 286 case SERVER_NODE_ID_FOR: 287 { 288 const server_node_id_for_request *request = reinterpret_cast<const server_node_id_for_request *>(data); 289 server_node_id_for_reply reply; 290 rv = gNodeManager->FindNodeId(&reply.nodeid, request->port); 291 request->SendReply(rv, &reply, sizeof(reply)); 292 break; 293 } 294 295 case SERVER_GET_LIVE_NODE_INFO: 296 { 297 const server_get_live_node_info_request *request = reinterpret_cast<const server_get_live_node_info_request *>(data); 298 server_get_live_node_info_reply reply; 299 rv = gNodeManager->GetLiveNodeInfo(&reply.live_info, request->node); 300 request->SendReply(rv, &reply, sizeof(reply)); 301 break; 302 } 303 304 case SERVER_GET_LIVE_NODES: 305 { 306 const server_get_live_nodes_request *request = reinterpret_cast<const server_get_live_nodes_request *>(data); 307 server_get_live_nodes_reply reply; 308 Stack<live_node_info> livenodes; 309 rv = gNodeManager->GetLiveNodes( 310 &livenodes, 311 request->maxcount, 312 request->has_input ? &request->inputformat : NULL, 313 request->has_output ? &request->outputformat : NULL, 314 request->has_name ? request->name : NULL, 315 request->require_kinds); 316 reply.count = livenodes.CountItems(); 317 if (reply.count <= MAX_LIVE_INFO) { 318 for (int32 index = 0; index < reply.count; index++) 319 livenodes.Pop(&reply.live_info[index]); 320 reply.area = -1; 321 } else { 322 // we create an area here, and pass it to the library, where it will be deleted. 323 live_node_info *start_addr; 324 size_t size; 325 size = ((reply.count * sizeof(live_node_info)) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); 326 reply.area = create_area("get live nodes", reinterpret_cast<void **>(&start_addr), B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 327 if (reply.area < B_OK) { 328 ERROR("SERVER_GET_LIVE_NODES: failed to create area, error %#lx\n", reply.area); 329 reply.count = 0; 330 rv = B_ERROR; 331 } else { 332 for (int32 index = 0; index < reply.count; index++) 333 livenodes.Pop(&start_addr[index]); 334 } 335 } 336 rv = request->SendReply(rv, &reply, sizeof(reply)); 337 if (rv != B_OK) 338 delete_area(reply.area); // if we couldn't send the message, delete the area 339 break; 340 } 341 342 case SERVER_GET_NODE_FOR: 343 { 344 const server_get_node_for_request *request = reinterpret_cast<const server_get_node_for_request *>(data); 345 server_get_node_for_reply reply; 346 rv = gNodeManager->GetCloneForId(&reply.clone, request->nodeid, request->team); 347 request->SendReply(rv, &reply, sizeof(reply)); 348 break; 349 } 350 351 case SERVER_RELEASE_NODE: 352 { 353 const server_release_node_request *request = reinterpret_cast<const server_release_node_request *>(data); 354 server_release_node_reply reply; 355 rv = gNodeManager->ReleaseNode(request->node, request->team); 356 request->SendReply(rv, &reply, sizeof(reply)); 357 break; 358 } 359 360 case SERVER_REGISTER_NODE: 361 { 362 const server_register_node_request *request = reinterpret_cast<const server_register_node_request *>(data); 363 server_register_node_reply reply; 364 rv = gNodeManager->RegisterNode(&reply.nodeid, request->addon_id, request->addon_flavor_id, request->name, request->kinds, request->port, request->team); 365 request->SendReply(rv, &reply, sizeof(reply)); 366 break; 367 } 368 369 case SERVER_UNREGISTER_NODE: 370 { 371 const server_unregister_node_request *request = reinterpret_cast<const server_unregister_node_request *>(data); 372 server_unregister_node_reply reply; 373 rv = gNodeManager->UnregisterNode(&reply.addonid, &reply.flavorid, request->nodeid, request->team); 374 request->SendReply(rv, &reply, sizeof(reply)); 375 break; 376 } 377 378 case SERVER_PUBLISH_INPUTS: 379 { 380 const server_publish_inputs_request *request = reinterpret_cast<const server_publish_inputs_request *>(data); 381 server_publish_inputs_reply reply; 382 if (request->count <= MAX_INPUTS) { 383 rv = gNodeManager->PublishInputs(request->node, request->inputs, request->count); 384 } else { 385 media_input *inputs; 386 area_id clone; 387 clone = clone_area("media_inputs clone", reinterpret_cast<void **>(&inputs), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, request->area); 388 if (clone < B_OK) { 389 ERROR("SERVER_PUBLISH_INPUTS: failed to clone area, error %#lx\n", clone); 390 rv = B_ERROR; 391 } else { 392 rv = gNodeManager->PublishInputs(request->node, inputs, request->count); 393 delete_area(clone); 394 } 395 } 396 request->SendReply(rv, &reply, sizeof(reply)); 397 break; 398 } 399 400 case SERVER_PUBLISH_OUTPUTS: 401 { 402 const server_publish_outputs_request *request = reinterpret_cast<const server_publish_outputs_request *>(data); 403 server_publish_outputs_reply reply; 404 if (request->count <= MAX_OUTPUTS) { 405 rv = gNodeManager->PublishOutputs(request->node, request->outputs, request->count); 406 } else { 407 media_output *outputs; 408 area_id clone; 409 clone = clone_area("media_outputs clone", reinterpret_cast<void **>(&outputs), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, request->area); 410 if (clone < B_OK) { 411 ERROR("SERVER_PUBLISH_OUTPUTS: failed to clone area, error %#lx\n", clone); 412 rv = B_ERROR; 413 } else { 414 rv = gNodeManager->PublishOutputs(request->node, outputs, request->count); 415 delete_area(clone); 416 } 417 } 418 request->SendReply(rv, &reply, sizeof(reply)); 419 break; 420 } 421 422 case SERVER_GET_NODE: 423 { 424 const server_get_node_request *request = reinterpret_cast<const server_get_node_request *>(data); 425 server_get_node_reply reply; 426 rv = gNodeManager->GetClone(&reply.node, reply.input_name, &reply.input_id, request->type, request->team); 427 request->SendReply(rv, &reply, sizeof(reply)); 428 break; 429 } 430 431 case SERVER_SET_NODE: 432 { 433 const server_set_node_request *request = reinterpret_cast<const server_set_node_request *>(data); 434 server_set_node_reply reply; 435 rv = gNodeManager->SetDefaultNode(request->type, request->use_node ? &request->node : NULL, request->use_dni ? &request->dni : NULL, request->use_input ? &request->input : NULL); 436 request->SendReply(rv, &reply, sizeof(reply)); 437 break; 438 } 439 440 case SERVER_GET_DORMANT_NODE_FOR: 441 { 442 const server_get_dormant_node_for_request *request = reinterpret_cast<const server_get_dormant_node_for_request *>(data); 443 server_get_dormant_node_for_reply reply; 444 rv = gNodeManager->GetDormantNodeInfo(&reply.node_info, request->node); 445 request->SendReply(rv, &reply, sizeof(reply)); 446 break; 447 } 448 449 case SERVER_GET_INSTANCES_FOR: 450 { 451 const server_get_instances_for_request *request = reinterpret_cast<const server_get_instances_for_request *>(data); 452 server_get_instances_for_reply reply; 453 rv = gNodeManager->GetInstances(reply.node_id, &reply.count, min_c(request->maxcount, MAX_NODE_ID), request->addon_id, request->addon_flavor_id); 454 if (reply.count == MAX_NODE_ID && request->maxcount > MAX_NODE_ID) { // XXX might be fixed by using an area 455 PRINT(1, "Warning: SERVER_GET_INSTANCES_FOR: returning possibly truncated list of node id's\n"); 456 } 457 request->SendReply(rv, &reply, sizeof(reply)); 458 break; 459 } 460 461 case SERVER_REGISTER_MEDIAADDON: 462 { 463 server_register_mediaaddon_request *msg = (server_register_mediaaddon_request *)data; 464 server_register_mediaaddon_reply reply; 465 gNodeManager->RegisterAddon(msg->ref, &reply.addonid); 466 write_port(msg->reply_port, 0, &reply, sizeof(reply)); 467 break; 468 } 469 470 case SERVER_UNREGISTER_MEDIAADDON: 471 { 472 server_unregister_mediaaddon_command *msg = (server_unregister_mediaaddon_command *)data; 473 gNodeManager->UnregisterAddon(msg->addonid); 474 break; 475 } 476 477 case SERVER_REGISTER_DORMANT_NODE: 478 { 479 xfer_server_register_dormant_node *msg = (xfer_server_register_dormant_node *)data; 480 dormant_flavor_info dfi; 481 if (msg->purge_id > 0) 482 gNodeManager->InvalidateDormantFlavorInfo(msg->purge_id); 483 rv = dfi.Unflatten(msg->dfi_type, &(msg->dfi), msg->dfi_size); 484 ASSERT(rv == B_OK); 485 gNodeManager->AddDormantFlavorInfo(dfi); 486 break; 487 } 488 489 case SERVER_GET_DORMANT_NODES: 490 { 491 xfer_server_get_dormant_nodes *msg = (xfer_server_get_dormant_nodes *)data; 492 xfer_server_get_dormant_nodes_reply reply; 493 dormant_node_info * infos = new dormant_node_info[msg->maxcount]; 494 reply.count = msg->maxcount; 495 reply.result = gNodeManager->GetDormantNodes( 496 infos, 497 &reply.count, 498 msg->has_input ? &msg->inputformat : NULL, 499 msg->has_output ? &msg->outputformat : NULL, 500 msg->has_name ? msg->name : NULL, 501 msg->require_kinds, 502 msg->deny_kinds); 503 if (reply.result != B_OK) 504 reply.count = 0; 505 write_port(msg->reply_port, 0, &reply, sizeof(reply)); 506 if (reply.count > 0) 507 write_port(msg->reply_port, 0, infos, reply.count * sizeof(dormant_node_info)); 508 delete [] infos; 509 break; 510 } 511 512 case SERVER_GET_DORMANT_FLAVOR_INFO: 513 { 514 xfer_server_get_dormant_flavor_info *msg = (xfer_server_get_dormant_flavor_info *)data; 515 dormant_flavor_info dfi; 516 status_t rv; 517 518 rv = gNodeManager->GetDormantFlavorInfoFor(msg->addon, msg->flavor_id, &dfi); 519 if (rv != B_OK) { 520 xfer_server_get_dormant_flavor_info_reply reply; 521 reply.result = rv; 522 write_port(msg->reply_port, 0, &reply, sizeof(reply)); 523 } else { 524 xfer_server_get_dormant_flavor_info_reply *reply; 525 int replysize; 526 replysize = sizeof(xfer_server_get_dormant_flavor_info_reply) + dfi.FlattenedSize(); 527 reply = (xfer_server_get_dormant_flavor_info_reply *)malloc(replysize); 528 529 reply->dfi_size = dfi.FlattenedSize(); 530 reply->dfi_type = dfi.TypeCode(); 531 reply->result = dfi.Flatten(reply->dfi, reply->dfi_size); 532 write_port(msg->reply_port, 0, reply, replysize); 533 free(reply); 534 } 535 break; 536 } 537 538 case SERVER_SET_NODE_CREATOR: 539 { 540 const server_set_node_creator_request *request = reinterpret_cast<const server_set_node_creator_request *>(data); 541 server_set_node_creator_reply reply; 542 rv = gNodeManager->SetNodeCreator(request->node, request->creator); 543 request->SendReply(rv, &reply, sizeof(reply)); 544 break; 545 } 546 547 case SERVER_GET_SHARED_BUFFER_AREA: 548 { 549 const server_get_shared_buffer_area_request *request = reinterpret_cast<const server_get_shared_buffer_area_request *>(data); 550 server_get_shared_buffer_area_reply reply; 551 552 reply.area = gBufferManager->SharedBufferListID(); 553 request->SendReply(B_OK, &reply, sizeof(reply)); 554 break; 555 } 556 557 case SERVER_REGISTER_BUFFER: 558 { 559 const server_register_buffer_request *request = reinterpret_cast<const server_register_buffer_request *>(data); 560 server_register_buffer_reply reply; 561 status_t status; 562 if (request->info.buffer == 0) { 563 reply.info = request->info; //size, offset, flags, area is kept 564 // get a new beuffer id into reply.info.buffer 565 status = gBufferManager->RegisterBuffer(request->team, request->info.size, request->info.flags, request->info.offset, request->info.area, &reply.info.buffer); 566 } else { 567 reply.info = request->info; //buffer id is kept 568 status = gBufferManager->RegisterBuffer(request->team, request->info.buffer, &reply.info.size, &reply.info.flags, &reply.info.offset, &reply.info.area); 569 } 570 request->SendReply(status, &reply, sizeof(reply)); 571 break; 572 } 573 574 case SERVER_UNREGISTER_BUFFER: 575 { 576 const server_unregister_buffer_command *cmd = reinterpret_cast<const server_unregister_buffer_command *>(data); 577 578 gBufferManager->UnregisterBuffer(cmd->team, cmd->bufferid); 579 break; 580 } 581 582 case SERVER_REWINDTYPES: 583 { 584 const server_rewindtypes_request *request = reinterpret_cast<const server_rewindtypes_request *>(data); 585 server_rewindtypes_reply reply; 586 587 BString **types = NULL; 588 589 rv = gMMediaFilesManager->RewindTypes( 590 &types, &reply.count); 591 if(reply.count>0) { 592 // we create an area here, and pass it to the library, where it will be deleted. 593 char *start_addr; 594 size_t size = ((reply.count * B_MEDIA_NAME_LENGTH) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); 595 reply.area = create_area("rewind types", reinterpret_cast<void **>(&start_addr), B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 596 if (reply.area < B_OK) { 597 ERROR("SERVER_REWINDTYPES: failed to create area, error %s\n", strerror(reply.area)); 598 reply.count = 0; 599 rv = B_ERROR; 600 } else { 601 for (int32 index = 0; index < reply.count; index++) 602 strncpy(start_addr + B_MEDIA_NAME_LENGTH * index, types[index]->String(), B_MEDIA_NAME_LENGTH); 603 } 604 } 605 606 delete types; 607 608 rv = request->SendReply(rv, &reply, sizeof(reply)); 609 if (rv != B_OK) 610 delete_area(reply.area); // if we couldn't send the message, delete the area 611 break; 612 } 613 614 case SERVER_REWINDREFS: 615 { 616 const server_rewindrefs_request *request = reinterpret_cast<const server_rewindrefs_request *>(data); 617 server_rewindrefs_reply reply; 618 619 BString **items = NULL; 620 621 rv = gMMediaFilesManager->RewindRefs(request->type, 622 &items, &reply.count); 623 // we create an area here, and pass it to the library, where it will be deleted. 624 if(reply.count>0) { 625 char *start_addr; 626 size_t size = ((reply.count * B_MEDIA_NAME_LENGTH) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); 627 reply.area = create_area("rewind refs", reinterpret_cast<void **>(&start_addr), B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 628 if (reply.area < B_OK) { 629 ERROR("SERVER_REWINDREFS: failed to create area, error %s\n", strerror(reply.area)); 630 reply.count = 0; 631 rv = B_ERROR; 632 } else { 633 for (int32 index = 0; index < reply.count; index++) 634 strncpy(start_addr + B_MEDIA_NAME_LENGTH * index, items[index]->String(), B_MEDIA_NAME_LENGTH); 635 } 636 } 637 638 delete items; 639 640 rv = request->SendReply(rv, &reply, sizeof(reply)); 641 if (rv != B_OK) 642 delete_area(reply.area); // if we couldn't send the message, delete the area 643 break; 644 } 645 646 case SERVER_GETREFFOR: 647 { 648 const server_getreffor_request *request = reinterpret_cast<const server_getreffor_request *>(data); 649 server_getreffor_reply reply; 650 entry_ref *ref; 651 652 rv = gMMediaFilesManager->GetRefFor(request->type, request->item, &ref); 653 if(rv==B_OK) { 654 reply.ref = *ref; 655 } 656 request->SendReply(rv, &reply, sizeof(reply)); 657 break; 658 } 659 660 case SERVER_SETREFFOR: 661 { 662 const server_setreffor_request *request = reinterpret_cast<const server_setreffor_request *>(data); 663 server_setreffor_reply reply; 664 entry_ref ref = request->ref; 665 666 rv = gMMediaFilesManager->SetRefFor(request->type, request->item, ref); 667 request->SendReply(rv, &reply, sizeof(reply)); 668 break; 669 } 670 671 case SERVER_REMOVEREFFOR: 672 { 673 const server_removereffor_request *request = reinterpret_cast<const server_removereffor_request *>(data); 674 server_removereffor_reply reply; 675 entry_ref ref = request->ref; 676 677 rv = gMMediaFilesManager->RemoveRefFor(request->type, request->item, ref); 678 request->SendReply(rv, &reply, sizeof(reply)); 679 break; 680 } 681 682 case SERVER_REMOVEITEM: 683 { 684 const server_removeitem_request *request = reinterpret_cast<const server_removeitem_request *>(data); 685 server_removeitem_reply reply; 686 687 rv = gMMediaFilesManager->RemoveItem(request->type, request->item); 688 request->SendReply(rv, &reply, sizeof(reply)); 689 break; 690 } 691 692 case SERVER_GET_READERS: 693 { 694 const server_get_readers_request *request = reinterpret_cast<const server_get_readers_request *>(data); 695 server_get_readers_reply reply; 696 rv = gAddOnManager->GetReaders(reply.ref, &reply.count, MAX_READERS); 697 request->SendReply(rv, &reply, sizeof(reply)); 698 break; 699 } 700 701 case SERVER_GET_DECODER_FOR_FORMAT: 702 { 703 const server_get_decoder_for_format_request *request = reinterpret_cast<const server_get_decoder_for_format_request *>(data); 704 server_get_decoder_for_format_reply reply; 705 rv = gAddOnManager->GetDecoderForFormat(&reply.ref, request->format); 706 request->SendReply(rv, &reply, sizeof(reply)); 707 break; 708 } 709 710 default: 711 printf("media_server: received unknown message code %#08lx\n",code); 712 } 713 TRACE("ServerApp::HandleMessage %#lx leave\n", code); 714 } 715 716 int32 717 ServerApp::controlthread(void *arg) 718 { 719 char data[B_MEDIA_MESSAGE_SIZE]; 720 ServerApp *app; 721 ssize_t size; 722 int32 code; 723 724 app = (ServerApp *)arg; 725 while ((size = read_port_etc(app->control_port, &code, data, sizeof(data), 0, 0)) > 0) 726 app->HandleMessage(code, data, size); 727 728 return 0; 729 } 730 731 void 732 ServerApp::MessageReceived(BMessage *msg) 733 { 734 TRACE("ServerApp::MessageReceived %lx enter\n", msg->what); 735 switch (msg->what) { 736 case MEDIA_SERVER_REQUEST_NOTIFICATIONS: 737 case MEDIA_SERVER_CANCEL_NOTIFICATIONS: 738 case MEDIA_SERVER_SEND_NOTIFICATIONS: 739 gNotificationManager->EnqueueMessage(msg); 740 break; 741 742 case MMEDIAFILESMANAGER_SAVE_TIMER: 743 gMMediaFilesManager->TimerMessage(); 744 break; 745 746 case MEDIA_SERVER_GET_FORMATS: 747 gFormatManager->GetFormats(*msg); 748 break; 749 750 case MEDIA_SERVER_MAKE_FORMAT_FOR: 751 gFormatManager->MakeFormatFor(*msg); 752 break; 753 754 default: 755 inherited::MessageReceived(msg); 756 //printf("\nnew media server: unknown message received\n"); 757 //msg->PrintToStream(); 758 break; 759 } 760 TRACE("ServerApp::MessageReceived %lx leave\n", msg->what); 761 } 762 763 int 764 main() 765 { 766 new ServerApp; 767 be_app->Run(); 768 delete be_app; 769 return 0; 770 } 771