1 #include <Application.h> 2 #include <stdio.h> 3 #include <Messenger.h> 4 #include <MediaDefs.h> 5 #include <MediaFormats.h> 6 #include <Autolock.h> 7 #include <string.h> 8 #include "NotificationManager.h" 9 #include "ServerInterface.h" 10 #include "DataExchange.h" 11 #include "BufferManager.h" 12 #include "NodeManager.h" 13 #include "AppManager.h" 14 #include "media_server.h" 15 #include "debug.h" 16 17 /* 18 * 19 * An implementation of a new media_server for the OpenBeOS MediaKit 20 * Started by Marcus Overhagen <marcus@overhagen.de> on 2001-10-25 21 * 22 * Communication with the OpenBeOS libmedia.so is done using BMessages 23 * sent to the server application, handled in XXX() 24 * functions. A simple BMessage reply is beeing send back. 25 * 26 * 27 * function names and class structure is loosely 28 * based on information acquired using: 29 * nm --demangle /boot/beos/system/servers/media_server | grep Server | sort 30 * nm --demangle /boot/beos/system/servers/media_server | grep Manager | sort 31 * 32 */ 33 34 NotificationManager *gNotificationManager; 35 BufferManager *gBufferManager; 36 AppManager *gAppManager; 37 NodeManager *gNodeManager; 38 39 40 #define REPLY_TIMEOUT ((bigtime_t)500000) 41 42 class ServerApp : BApplication 43 { 44 public: 45 ServerApp(); 46 ~ServerApp(); 47 48 bool QuitRequested(); 49 void HandleMessage(int32 code, void *data, size_t size); 50 void ArgvReceived(int32 argc, char **argv); 51 static int32 controlthread(void *arg); 52 53 /* functionality not yet implemented 54 00014a00 T _ServerApp::_ServerApp(void) 55 00014e1c T _ServerApp::~_ServerApp(void) 56 00014ff4 T _ServerApp::MessageReceived(BMessage *); 57 00015840 T _ServerApp::QuitRequested(void) 58 00015b50 T _ServerApp::_DoNotify(command_data *) 59 00015d18 T _ServerApp::_UnregisterApp(long, bool) 60 00018e90 T _ServerApp::AddOnHost(void) 61 00019530 T _ServerApp::AboutRequested(void) 62 00019d04 T _ServerApp::AddPurgableBufferGroup(long, long, long, void *) 63 00019db8 T _ServerApp::CancelPurgableBufferGroupCleanup(long) 64 00019e50 T _ServerApp::DirtyWork(void) 65 0001a4bc T _ServerApp::ArgvReceived(long, char **) 66 0001a508 T _ServerApp::CleanupPurgedBufferGroup(_ServerApp::purgable_buffer_group const &, bool) 67 0001a5dc T _ServerApp::DirtyWorkLaunch(void *) 68 0001a634 T _ServerApp::SetQuitMode(bool) 69 0001a648 T _ServerApp::IsQuitMode(void) const 70 0001a658 T _ServerApp::BroadcastCurrentStateTo(BMessenger &) 71 0001adcc T _ServerApp::ReadyToRun(void) 72 */ 73 74 private: 75 port_id control_port; 76 thread_id control_thread; 77 78 BLocker *fLocker; 79 80 void MessageReceived(BMessage *msg); 81 typedef BApplication inherited; 82 }; 83 84 ServerApp::ServerApp() 85 : BApplication(NEW_MEDIA_SERVER_SIGNATURE), 86 fLocker(new BLocker("media server locker")) 87 { 88 //load volume settings from config file 89 //mVolumeLeft = ???; 90 //mVolumeRight = ???; 91 92 gNotificationManager = new NotificationManager; 93 gBufferManager = new BufferManager; 94 gAppManager = new AppManager; 95 gNodeManager = new NodeManager; 96 97 control_port = create_port(64,"media_server port"); 98 control_thread = spawn_thread(controlthread, "media_server control", 105, this); 99 resume_thread(control_thread); 100 101 gAppManager->StartAddonServer(); 102 } 103 104 ServerApp::~ServerApp() 105 { 106 TRACE("ServerApp::~ServerApp()\n"); 107 delete gNotificationManager; 108 delete gBufferManager; 109 delete gAppManager; 110 delete gNodeManager; 111 delete fLocker; 112 delete_port(control_port); 113 status_t err; 114 wait_for_thread(control_thread,&err); 115 } 116 117 void ServerApp::ArgvReceived(int32 argc, char **argv) 118 { 119 for (int arg = 1; arg < argc; arg++) { 120 if (strstr(argv[arg], "dump")) { 121 gAppManager->Dump(); 122 gNodeManager->Dump(); 123 gBufferManager->Dump(); 124 gNotificationManager->Dump(); 125 } 126 if (strstr(argv[arg], "buffer")) { 127 gBufferManager->Dump(); 128 } 129 if (strstr(argv[arg], "node")) { 130 gNodeManager->Dump(); 131 } 132 if (strstr(argv[arg], "quit")) { 133 PostMessage(B_QUIT_REQUESTED); 134 } 135 } 136 } 137 138 bool 139 ServerApp::QuitRequested() 140 { 141 TRACE("ServerApp::QuitRequested()\n"); 142 gAppManager->TerminateAddonServer(); 143 return true; 144 } 145 146 void 147 ServerApp::HandleMessage(int32 code, void *data, size_t size) 148 { 149 status_t rv; 150 INFO("ServerApp::HandleMessage %#lx\n", code); 151 switch (code) { 152 case SERVER_REGISTER_ADDONSERVER: 153 { 154 const server_register_addonserver_request *request = reinterpret_cast<const server_register_addonserver_request *>(data); 155 server_register_addonserver_reply reply; 156 rv = gAppManager->RegisterAddonServer(request->team); 157 request->SendReply(rv, &reply, sizeof(reply)); 158 break; 159 } 160 161 case SERVER_REGISTER_APP: 162 { 163 const server_register_app_request *request = reinterpret_cast<const server_register_app_request *>(data); 164 server_register_app_reply reply; 165 rv = gAppManager->RegisterTeam(request->team, request->messenger); 166 request->SendReply(rv, &reply, sizeof(reply)); 167 break; 168 } 169 170 case SERVER_UNREGISTER_APP: 171 { 172 const server_unregister_app_request *request = reinterpret_cast<const server_unregister_app_request *>(data); 173 server_unregister_app_reply reply; 174 rv = gAppManager->UnregisterTeam(request->team); 175 request->SendReply(rv, &reply, sizeof(reply)); 176 break; 177 } 178 179 case SERVER_GET_MEDIAADDON_REF: 180 { 181 server_get_mediaaddon_ref_request *msg = (server_get_mediaaddon_ref_request *)data; 182 server_get_mediaaddon_ref_reply reply; 183 entry_ref tempref; 184 reply.result = gNodeManager->GetAddonRef(&tempref, msg->addonid); 185 reply.ref = tempref; 186 write_port(msg->reply_port, 0, &reply, sizeof(reply)); 187 break; 188 } 189 190 case SERVER_NODE_ID_FOR: 191 { 192 const server_node_id_for_request *request = reinterpret_cast<const server_node_id_for_request *>(data); 193 server_node_id_for_reply reply; 194 rv = gNodeManager->FindNodeId(&reply.nodeid, request->port); 195 request->SendReply(rv, &reply, sizeof(reply)); 196 break; 197 } 198 199 case SERVER_GET_LIVE_NODE_INFO: 200 { 201 const server_get_live_node_info_request *request = reinterpret_cast<const server_get_live_node_info_request *>(data); 202 server_get_live_node_info_reply reply; 203 rv = gNodeManager->GetLiveNodeInfo(&reply.live_info, request->node); 204 request->SendReply(rv, &reply, sizeof(reply)); 205 break; 206 } 207 208 case SERVER_GET_LIVE_NODES: 209 { 210 const server_get_live_nodes_request *request = reinterpret_cast<const server_get_live_nodes_request *>(data); 211 server_get_live_nodes_reply reply; 212 Stack<live_node_info> livenodes; 213 rv = gNodeManager->GetLiveNodes( 214 &livenodes, 215 request->maxcount, 216 request->has_input ? &request->inputformat : NULL, 217 request->has_output ? &request->outputformat : NULL, 218 request->has_name ? request->name : NULL, 219 request->require_kinds); 220 reply.count = livenodes.CountItems(); 221 if (reply.count <= MAX_LIVE_INFO) { 222 for (int32 index = 0; index < reply.count; index++) 223 livenodes.Pop(&reply.live_info[index]); 224 reply.area = -1; 225 } else { 226 // we create an area here, and pass it to the library, where it will be deleted. 227 live_node_info *start_addr; 228 size_t size; 229 size = ((reply.count * sizeof(live_node_info)) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); 230 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); 231 if (reply.area < B_OK) { 232 FATAL("SERVER_GET_LIVE_NODES: failed to create area, error %#lx\n", reply.area); 233 reply.count = 0; 234 rv = B_ERROR; 235 } else { 236 for (int32 index = 0; index < reply.count; index++) 237 livenodes.Pop(&start_addr[index]); 238 } 239 } 240 rv = request->SendReply(rv, &reply, sizeof(reply)); 241 if (rv != B_OK) 242 delete_area(reply.area); // if we couldn't send the message, delete the area 243 break; 244 } 245 246 case SERVER_GET_NODE_FOR: 247 { 248 const server_get_node_for_request *request = reinterpret_cast<const server_get_node_for_request *>(data); 249 server_get_node_for_reply reply; 250 rv = gNodeManager->GetCloneForId(&reply.clone, request->nodeid, request->team); 251 request->SendReply(rv, &reply, sizeof(reply)); 252 break; 253 } 254 255 case SERVER_RELEASE_NODE: 256 { 257 const server_release_node_request *request = reinterpret_cast<const server_release_node_request *>(data); 258 server_release_node_reply reply; 259 rv = gNodeManager->ReleaseNode(request->node, request->team); 260 request->SendReply(rv, &reply, sizeof(reply)); 261 break; 262 } 263 264 case SERVER_REGISTER_NODE: 265 { 266 const server_register_node_request *request = reinterpret_cast<const server_register_node_request *>(data); 267 server_register_node_reply reply; 268 rv = gNodeManager->RegisterNode(&reply.nodeid, request->addon_id, request->addon_flavor_id, request->name, request->kinds, request->port, request->team); 269 request->SendReply(rv, &reply, sizeof(reply)); 270 break; 271 } 272 273 case SERVER_UNREGISTER_NODE: 274 { 275 const server_unregister_node_request *request = reinterpret_cast<const server_unregister_node_request *>(data); 276 server_unregister_node_reply reply; 277 rv = gNodeManager->UnregisterNode(&reply.addon_id, request->nodeid, request->team); 278 request->SendReply(rv, &reply, sizeof(reply)); 279 break; 280 } 281 282 case SERVER_PUBLISH_INPUTS: 283 { 284 const server_publish_inputs_request *request = reinterpret_cast<const server_publish_inputs_request *>(data); 285 server_publish_inputs_reply reply; 286 if (request->count <= MAX_INPUTS) { 287 rv = gNodeManager->PublishInputs(request->node, request->inputs, request->count); 288 } else { 289 media_input *inputs; 290 area_id clone; 291 clone = clone_area("media_inputs clone", reinterpret_cast<void **>(&inputs), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, request->area); 292 if (clone < B_OK) { 293 FATAL("SERVER_PUBLISH_INPUTS: failed to clone area, error %#lx\n", clone); 294 rv = B_ERROR; 295 } else { 296 rv = gNodeManager->PublishInputs(request->node, inputs, request->count); 297 delete_area(clone); 298 } 299 } 300 request->SendReply(rv, &reply, sizeof(reply)); 301 break; 302 } 303 304 case SERVER_PUBLISH_OUTPUTS: 305 { 306 const server_publish_outputs_request *request = reinterpret_cast<const server_publish_outputs_request *>(data); 307 server_publish_outputs_reply reply; 308 if (request->count <= MAX_OUTPUTS) { 309 rv = gNodeManager->PublishOutputs(request->node, request->outputs, request->count); 310 } else { 311 media_output *outputs; 312 area_id clone; 313 clone = clone_area("media_outputs clone", reinterpret_cast<void **>(&outputs), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, request->area); 314 if (clone < B_OK) { 315 FATAL("SERVER_PUBLISH_OUTPUTS: failed to clone area, error %#lx\n", clone); 316 rv = B_ERROR; 317 } else { 318 rv = gNodeManager->PublishOutputs(request->node, outputs, request->count); 319 delete_area(clone); 320 } 321 } 322 request->SendReply(rv, &reply, sizeof(reply)); 323 break; 324 } 325 326 case SERVER_GET_NODE: 327 { 328 const server_get_node_request *request = reinterpret_cast<const server_get_node_request *>(data); 329 server_get_node_reply reply; 330 rv = gNodeManager->GetClone(&reply.node, reply.input_name, &reply.input_id, request->type, request->team); 331 request->SendReply(rv, &reply, sizeof(reply)); 332 break; 333 } 334 335 case SERVER_SET_NODE: 336 { 337 const server_set_node_request *request = reinterpret_cast<const server_set_node_request *>(data); 338 server_set_node_reply reply; 339 // XXX do something here 340 debugger("SERVER_SET_NODE seems to be needed\n"); 341 request->SendReply(B_OK, &reply, sizeof(reply)); 342 break; 343 } 344 345 case SERVER_GET_DORMANT_NODE_FOR: 346 { 347 const server_get_dormant_node_for_request *request = reinterpret_cast<const server_get_dormant_node_for_request *>(data); 348 server_get_dormant_node_for_reply reply; 349 rv = gNodeManager->GetDormantNodeInfo(&reply.node_info, request->node); 350 request->SendReply(rv, &reply, sizeof(reply)); 351 break; 352 } 353 354 case SERVER_GET_INSTANCES_FOR: 355 { 356 const server_get_instances_for_request *request = reinterpret_cast<const server_get_instances_for_request *>(data); 357 server_get_instances_for_reply reply; 358 rv = gNodeManager->GetInstances(reply.node_id, &reply.count, min_c(request->maxcount, MAX_NODE_ID), request->addon_id, request->addon_flavor_id); 359 if (reply.count == MAX_NODE_ID && request->maxcount > MAX_NODE_ID) { // XXX might be fixed by using an area 360 FATAL("SERVER_GET_INSTANCES_FOR: WARNING! returning possibly truncated list of node id's\n"); 361 } 362 request->SendReply(rv, &reply, sizeof(reply)); 363 break; 364 } 365 366 case SERVER_REGISTER_MEDIAADDON: 367 { 368 server_register_mediaaddon_request *msg = (server_register_mediaaddon_request *)data; 369 server_register_mediaaddon_reply reply; 370 gNodeManager->RegisterAddon(msg->ref, &reply.addonid); 371 write_port(msg->reply_port, 0, &reply, sizeof(reply)); 372 break; 373 } 374 375 case SERVER_UNREGISTER_MEDIAADDON: 376 { 377 server_unregister_mediaaddon_command *msg = (server_unregister_mediaaddon_command *)data; 378 gNodeManager->UnregisterAddon(msg->addonid); 379 break; 380 } 381 382 case SERVER_REGISTER_DORMANT_NODE: 383 { 384 xfer_server_register_dormant_node *msg = (xfer_server_register_dormant_node *)data; 385 dormant_flavor_info dfi; 386 if (msg->purge_id > 0) 387 gNodeManager->RemoveDormantFlavorInfo(msg->purge_id); 388 rv = dfi.Unflatten(msg->dfi_type, &(msg->dfi), msg->dfi_size); 389 ASSERT(rv == B_OK); 390 gNodeManager->AddDormantFlavorInfo(dfi); 391 break; 392 } 393 394 case SERVER_GET_DORMANT_NODES: 395 { 396 xfer_server_get_dormant_nodes *msg = (xfer_server_get_dormant_nodes *)data; 397 xfer_server_get_dormant_nodes_reply reply; 398 dormant_node_info * infos = new dormant_node_info[msg->maxcount]; 399 reply.count = msg->maxcount; 400 reply.result = gNodeManager->GetDormantNodes( 401 infos, 402 &reply.count, 403 msg->has_input ? &msg->inputformat : NULL, 404 msg->has_output ? &msg->outputformat : NULL, 405 msg->has_name ? msg->name : NULL, 406 msg->require_kinds, 407 msg->deny_kinds); 408 if (reply.result != B_OK) 409 reply.count = 0; 410 write_port(msg->reply_port, 0, &reply, sizeof(reply)); 411 if (reply.count > 0) 412 write_port(msg->reply_port, 0, infos, reply.count * sizeof(dormant_node_info)); 413 delete [] infos; 414 break; 415 } 416 417 case SERVER_GET_DORMANT_FLAVOR_INFO: 418 { 419 xfer_server_get_dormant_flavor_info *msg = (xfer_server_get_dormant_flavor_info *)data; 420 dormant_flavor_info dfi; 421 status_t rv; 422 423 rv = gNodeManager->GetDormantFlavorInfoFor(msg->addon, msg->flavor_id, &dfi); 424 if (rv != B_OK) { 425 xfer_server_get_dormant_flavor_info_reply reply; 426 reply.result = rv; 427 write_port(msg->reply_port, 0, &reply, sizeof(reply)); 428 } else { 429 xfer_server_get_dormant_flavor_info_reply *reply; 430 int replysize; 431 replysize = sizeof(xfer_server_get_dormant_flavor_info_reply) + dfi.FlattenedSize(); 432 reply = (xfer_server_get_dormant_flavor_info_reply *)malloc(replysize); 433 434 reply->dfi_size = dfi.FlattenedSize(); 435 reply->dfi_type = dfi.TypeCode(); 436 reply->result = dfi.Flatten(reply->dfi, reply->dfi_size); 437 write_port(msg->reply_port, 0, reply, replysize); 438 free(reply); 439 } 440 break; 441 } 442 443 case SERVER_GET_SHARED_BUFFER_AREA: 444 { 445 const server_get_shared_buffer_area_request *request = reinterpret_cast<const server_get_shared_buffer_area_request *>(data); 446 server_get_shared_buffer_area_reply reply; 447 448 reply.area = gBufferManager->SharedBufferListID(); 449 request->SendReply(B_OK, &reply, sizeof(reply)); 450 break; 451 } 452 453 case SERVER_REGISTER_BUFFER: 454 { 455 const server_register_buffer_request *request = reinterpret_cast<const server_register_buffer_request *>(data); 456 server_register_buffer_reply reply; 457 status_t status; 458 if (request->info.buffer == 0) { 459 reply.info = request->info; //size, offset, flags, area is kept 460 // get a new beuffer id into reply.info.buffer 461 status = gBufferManager->RegisterBuffer(request->team, request->info.size, request->info.flags, request->info.offset, request->info.area, &reply.info.buffer); 462 } else { 463 reply.info = request->info; //buffer id is kept 464 status = gBufferManager->RegisterBuffer(request->team, request->info.buffer, &reply.info.size, &reply.info.flags, &reply.info.offset, &reply.info.area); 465 } 466 request->SendReply(status, &reply, sizeof(reply)); 467 break; 468 } 469 470 case SERVER_UNREGISTER_BUFFER: 471 { 472 const server_unregister_buffer_command *cmd = reinterpret_cast<const server_unregister_buffer_command *>(data); 473 474 gBufferManager->UnregisterBuffer(cmd->team, cmd->bufferid); 475 break; 476 } 477 478 default: 479 printf("media_server: received unknown message code %#08lx\n",code); 480 } 481 } 482 483 int32 484 ServerApp::controlthread(void *arg) 485 { 486 char data[B_MEDIA_MESSAGE_SIZE]; 487 ServerApp *app; 488 ssize_t size; 489 int32 code; 490 491 app = (ServerApp *)arg; 492 while ((size = read_port_etc(app->control_port, &code, data, sizeof(data), 0, 0)) > 0) 493 app->HandleMessage(code, data, size); 494 495 return 0; 496 } 497 498 void ServerApp::MessageReceived(BMessage *msg) 499 { 500 switch (msg->what) { 501 case MEDIA_SERVER_REQUEST_NOTIFICATIONS: gNotificationManager->EnqueueMessage(msg); break; 502 case MEDIA_SERVER_CANCEL_NOTIFICATIONS: gNotificationManager->EnqueueMessage(msg); break; 503 case MEDIA_SERVER_SEND_NOTIFICATIONS: gNotificationManager->EnqueueMessage(msg); break; 504 default: 505 printf("\nnew media server: unknown message received\n"); 506 msg->PrintToStream(); 507 } 508 } 509 510 int main() 511 { 512 new ServerApp; 513 be_app->Run(); 514 delete be_app; 515 return 0; 516 } 517 518 519 /* 520 0001e260 T MBufferManager::MBufferManager(void) 521 0001e47c T MBufferManager::~MBufferManager(void) 522 0001e540 T MBufferManager::PrintToStream(void) 523 0001e6fc T MBufferManager::RecycleBuffersWithOwner(long, long) 524 0001ea00 T MBufferManager::RegisterBuffer(long, buffer_clone_info const *, long *, media_source const &) 525 0001f090 T MBufferManager::AcquireBuffer(long, long, media_source) 526 0001f28c T MBufferManager::ReleaseBuffer(long, long, bool, BMessage *, char const *) 527 0001fd0c T MBufferManager::PurgeTeamBufferGroups(long) 528 0001fdf0 T MBufferManager::RegisterBufferGroup(BMessage *, char const *, long) 529 0002007c T MBufferManager::_RemoveGroupFromClaimants(long, long, void *) 530 00020158 T MBufferManager::UnregisterBufferGroup(BMessage *, char const *, long) 531 0002028c T MBufferManager::_UnregisterBufferGroup(long, long) 532 000206f4 T MBufferManager::AddBuffersTo(BMessage *, char const *) 533 00020cd0 T MBufferManager::ReclaimBuffers(long const *, long, long, long) 534 00020f7c T MBufferManager::CleanupPurgedBufferGroup(long, long, long, void *, bool, BMessage &) 535 00021080 T MBufferManager::LoadState(void) 536 0002108c T MBufferManager::SaveState(void) 537 538 000210a0 T MDefaultManager::MDefaultManager(void) 539 0002123c T MDefaultManager::~MDefaultManager(void) 540 000212f4 T MDefaultManager::SaveState(void) 541 0002172c T MDefaultManager::LoadState(void) 542 00021de0 T MDefaultManager::SetDefault(long, BMessage &) 543 00022058 T MDefaultManager::SetRunningDefault(long, media_node const &) 544 000221a8 T MDefaultManager::RemoveRunningDefault(media_node const &) 545 000226ec T MDefaultManager::SetRealtimeFlags(unsigned long) 546 00022720 T MDefaultManager::GetRealtimeFlags(void) 547 00022730 T MDefaultManager::GetRunningDefault(long, media_node &) 548 000227d0 T MDefaultManager::RemoveDefault(long) 549 00022830 T MDefaultManager::GetDefault(long, BMessage &) 550 00022890 T MNotifierManager::MNotifierManager(void) 551 00022a5c T MNotifierManager::~MNotifierManager(void) 552 00022b20 T MNotifierManager::RegisterNotifier(long, BMessenger, media_node const *) 553 00022f50 T MNotifierManager::UnregisterNotifier(long, BMessenger, media_node const *) 554 00023f00 T MNotifierManager::BroadcastMessage(BMessage *, long long) 555 0002426c T MNotifierManager::regen_node_list(media_node const &) 556 000249b4 T MNotifierManager::get_node_messenger(media_node const &, get_messenger_a *) 557 00024a90 T MNotifierManager::HandleBroadcastError(BMessage *, BMessenger &, long, long long) 558 00024b34 T MNotifierManager::LoadState(void) 559 00024b40 T MNotifierManager::SaveState(void) 560 00024c5c T MMediaFilesManager::MMediaFilesManager(void) 561 00024dec T MMediaFilesManager::~MMediaFilesManager(void) 562 00024ea4 T MMediaFilesManager::SaveState(void) 563 00025b70 T MMediaFilesManager::LoadState(void) 564 00026668 T MMediaFilesManager::create_default_settings(void) 565 00027130 T MMediaFilesManager::GetTypes(BMessage &, BMessage &) 566 000271f8 T MMediaFilesManager::GetItems(BMessage &, BMessage &) 567 000274f0 T MMediaFilesManager::SetItem(BMessage &, BMessage &) 568 00027bc0 T MMediaFilesManager::ClearItem(BMessage &, BMessage &) 569 000288f4 T MMediaFilesManager::RemoveItem(BMessage &, BMessage &) 570 00028f0c T MMediaFilesManager::AddType(BMessage &, BMessage &) 571 */ 572 573