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