1 /* 2 * Copyright (c) 2003-2005, Haiku, Inc. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * Sikosis, Jérôme Duval 7 */ 8 9 10 #include "MediaWindow.h" 11 12 #include <stdio.h> 13 14 #include <Alert.h> 15 #include <Application.h> 16 #include <Autolock.h> 17 #include <Bitmap.h> 18 #include <Button.h> 19 #include <Catalog.h> 20 #include <Debug.h> 21 #include <Deskbar.h> 22 #include <GroupView.h> 23 #include <Locale.h> 24 #include <MediaRoster.h> 25 #include <MediaTheme.h> 26 #include <Resources.h> 27 #include <Roster.h> 28 #include <Screen.h> 29 #include <ScrollView.h> 30 #include <SeparatorView.h> 31 #include <SpaceLayoutItem.h> 32 #include <StorageKit.h> 33 #include <String.h> 34 #include <TextView.h> 35 36 #include "MediaIcons.h" 37 38 39 #undef B_TRANSLATE_CONTEXT 40 #define B_TRANSLATE_CONTEXT "Media Window" 41 42 43 const uint32 ML_SELECTED_NODE = 'MlSN'; 44 const uint32 ML_INIT_MEDIA = 'MlIM'; 45 46 47 MediaWindow::SmartNode::SmartNode(const BMessenger& notifyHandler) 48 : 49 fNode(NULL), 50 fMessenger(notifyHandler) 51 { 52 } 53 54 55 MediaWindow::SmartNode::~SmartNode() 56 { 57 _FreeNode(); 58 } 59 60 61 void 62 MediaWindow::SmartNode::SetTo(dormant_node_info* info) 63 { 64 _FreeNode(); 65 if (!info) 66 return; 67 68 fNode = new media_node(); 69 70 // TODO: check error codes 71 BMediaRoster* roster = BMediaRoster::Roster(); 72 73 media_node_id node_id; 74 if (roster->GetInstancesFor(info->addon, info->flavor_id, &node_id) == B_OK) 75 roster->GetNodeFor(node_id, fNode); 76 else 77 roster->InstantiateDormantNode(*info, fNode, B_FLAVOR_IS_GLOBAL); 78 roster->StartWatching(fMessenger, *fNode, B_MEDIA_WILDCARD); 79 } 80 81 82 void 83 MediaWindow::SmartNode::SetTo(const media_node& node) 84 { 85 _FreeNode(); 86 fNode = new media_node(node); 87 BMediaRoster* roster = BMediaRoster::Roster(); 88 roster->StartWatching(fMessenger, *fNode, B_MEDIA_WILDCARD); 89 } 90 91 92 bool 93 MediaWindow::SmartNode::IsSet() 94 { 95 return fNode != NULL; 96 } 97 98 99 MediaWindow::SmartNode::operator media_node() 100 { 101 if (fNode) 102 return *fNode; 103 media_node node; 104 return node; 105 } 106 107 108 void 109 MediaWindow::SmartNode::_FreeNode() 110 { 111 if (!IsSet()) 112 return; 113 // TODO: check error codes 114 BMediaRoster* roster = BMediaRoster::Roster(); 115 roster->StopWatching(fMessenger, *fNode, B_MEDIA_WILDCARD); 116 roster->ReleaseNode(*fNode); 117 delete fNode; 118 fNode = NULL; 119 } 120 121 122 // MediaWindow - Constructor 123 MediaWindow::MediaWindow(BRect frame) 124 : 125 BWindow (frame, B_TRANSLATE("Media"), B_TITLED_WINDOW, 126 B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS), 127 fCurrentNode(BMessenger(this)), 128 fParamWeb(NULL), 129 fAudioInputs(5, true), 130 fAudioOutputs(5, true), 131 fVideoInputs(5, true), 132 fVideoOutputs(5, true), 133 fAlert(NULL), 134 fInitCheck(B_OK) 135 { 136 InitWindow(); 137 } 138 139 140 status_t 141 MediaWindow::InitCheck() 142 { 143 return fInitCheck; 144 } 145 146 147 MediaWindow::~MediaWindow() 148 { 149 _EmptyNodeLists(); 150 _ClearParamView(); 151 delete fVideoView; 152 delete fAudioView; 153 154 char buffer[512]; 155 BRect rect = Frame(); 156 PRINT_OBJECT(rect); 157 sprintf(buffer, "# MediaPrefs Settings\n rect = %i,%i,%i,%i\n", 158 int(rect.left), int(rect.top), int(rect.right), int(rect.bottom)); 159 160 BPath path; 161 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { 162 path.Append(SETTINGS_FILE); 163 BFile file(path.Path(), B_READ_WRITE|B_CREATE_FILE|B_ERASE_FILE); 164 if (file.InitCheck()==B_OK) { 165 file.Write(buffer, strlen(buffer)); 166 } 167 } 168 } 169 170 171 void 172 MediaWindow::SelectNode(dormant_node_info* node) 173 { 174 fCurrentNode.SetTo(node); 175 _MakeParamView(); 176 fTitleView->SetLabel(node->name); 177 } 178 179 180 void 181 MediaWindow::SelectAudioSettings(const char* title) 182 { 183 fContentView->AddChild(fAudioView); 184 fTitleView->SetLabel(title); 185 } 186 187 188 void 189 MediaWindow::SelectVideoSettings(const char* title) 190 { 191 fContentView->AddChild(fVideoView); 192 fTitleView->SetLabel(title); 193 } 194 195 196 void 197 MediaWindow::SelectAudioMixer(const char* title) 198 { 199 media_node mixerNode; 200 BMediaRoster* roster = BMediaRoster::Roster(); 201 roster->GetAudioMixer(&mixerNode); 202 fCurrentNode.SetTo(mixerNode); 203 _MakeParamView(); 204 fTitleView->SetLabel(title); 205 } 206 207 208 void 209 MediaWindow::_FindNodes() 210 { 211 _FindNodes(B_MEDIA_RAW_AUDIO, B_PHYSICAL_OUTPUT, fAudioOutputs); 212 _FindNodes(B_MEDIA_RAW_AUDIO, B_PHYSICAL_INPUT, fAudioInputs); 213 _FindNodes(B_MEDIA_ENCODED_AUDIO, B_PHYSICAL_OUTPUT, fAudioOutputs); 214 _FindNodes(B_MEDIA_ENCODED_AUDIO, B_PHYSICAL_INPUT, fAudioInputs); 215 _FindNodes(B_MEDIA_RAW_VIDEO, B_PHYSICAL_OUTPUT, fVideoOutputs); 216 _FindNodes(B_MEDIA_RAW_VIDEO, B_PHYSICAL_INPUT, fVideoInputs); 217 _FindNodes(B_MEDIA_ENCODED_VIDEO, B_PHYSICAL_OUTPUT, fVideoOutputs); 218 _FindNodes(B_MEDIA_ENCODED_VIDEO, B_PHYSICAL_INPUT, fVideoInputs); 219 } 220 221 222 void 223 MediaWindow::_FindNodes(media_type type, uint64 kind, NodeList& into) 224 { 225 dormant_node_info node_info[64]; 226 int32 node_info_count = 64; 227 228 media_format format; 229 media_format* nodeInputFormat = NULL, *nodeOutputFormat = NULL; 230 format.type = type; 231 232 // output nodes must be BBufferConsumers => they have an input format 233 // input nodes must be BBufferProducers => they have an output format 234 if (kind & B_PHYSICAL_OUTPUT) 235 nodeInputFormat = &format; 236 else if (kind & B_PHYSICAL_INPUT) 237 nodeOutputFormat = &format; 238 else 239 return; 240 241 BMediaRoster* roster = BMediaRoster::Roster(); 242 243 if (roster->GetDormantNodes(node_info, &node_info_count, nodeInputFormat, 244 nodeOutputFormat, NULL, kind) != B_OK) { 245 // TODO: better error reporting! 246 fprintf(stderr, "error\n"); 247 return; 248 } 249 250 for (int32 i = 0; i < node_info_count; i++) { 251 PRINT(("node : %s, media_addon %i, flavor_id %i\n", 252 node_info[i].name, node_info[i].addon, node_info[i].flavor_id)); 253 254 dormant_node_info* info = new dormant_node_info(); 255 strncpy(info->name, node_info[i].name, B_MEDIA_NAME_LENGTH); 256 info->flavor_id = node_info[i].flavor_id; 257 info->addon = node_info[i].addon; 258 into.AddItem(info); 259 } 260 } 261 262 263 NodeListItem* 264 MediaWindow::_FindNodeListItem(dormant_node_info* info) 265 { 266 for (int32 i = 0; i < fListView->CountItems(); i++) { 267 MediaListItem* item 268 = static_cast<MediaListItem*>(fListView->ItemAt(i)); 269 dormant_node_info* itemInfo = item->NodeInfo(); 270 if (itemInfo && itemInfo->addon == info->addon 271 && itemInfo->flavor_id == info->flavor_id) { 272 return dynamic_cast<NodeListItem*>(item); 273 } 274 } 275 return NULL; 276 } 277 278 279 void 280 MediaWindow::_AddNodeItems(NodeList &list, MediaListItem::media_type type) 281 { 282 int32 count = list.CountItems(); 283 for (int32 i = 0; i < count; i++) { 284 dormant_node_info* info = list.ItemAt(i); 285 if (!_FindNodeListItem(info)) 286 fListView->AddItem(new NodeListItem(info, type)); 287 } 288 } 289 290 291 void 292 MediaWindow::_EmptyNodeLists() 293 { 294 fAudioOutputs.MakeEmpty(); 295 fAudioInputs.MakeEmpty(); 296 fVideoOutputs.MakeEmpty(); 297 fVideoInputs.MakeEmpty(); 298 } 299 300 301 void 302 MediaWindow::InitWindow() 303 { 304 const float scrollWidth = 9 * be_plain_font->Size() + 30; 305 306 fListView = new BListView("media_list_view"); 307 fListView->SetSelectionMessage(new BMessage(ML_SELECTED_NODE)); 308 309 // Add ScrollView to Media Menu 310 BScrollView* scrollView = new BScrollView("listscroller", 311 fListView, 0, false, false, B_FANCY_BORDER); 312 scrollView->SetExplicitMinSize(BSize(scrollWidth, B_SIZE_UNSET)); 313 scrollView->SetExplicitMaxSize(BSize(scrollWidth, B_SIZE_UNSET)); 314 315 // Create the Views 316 fBox = new BBox("background", B_WILL_DRAW | B_FRAME_EVENTS, 317 B_PLAIN_BORDER); 318 SetLayout(new BGroupLayout(B_HORIZONTAL)); 319 GetLayout()->AddView(fBox); 320 321 // StringViews 322 fTitleView = new BSeparatorView(B_HORIZONTAL, B_FANCY_BORDER); 323 fTitleView->SetLabel(B_TRANSLATE("Audio settings")); 324 fTitleView->SetFont(be_bold_font); 325 326 fContentView = new BBox("contentView", B_WILL_DRAW | B_FRAME_EVENTS, 327 B_NO_BORDER); 328 329 fAudioView = new SettingsView(false); 330 fVideoView = new SettingsView(true); 331 332 333 // Layout all views 334 BGroupView* rightView = new BGroupView(B_VERTICAL, 5); 335 rightView->GroupLayout()->SetInsets(14, 0, 0, 0); 336 rightView->GroupLayout()->AddView(fTitleView); 337 rightView->GroupLayout()->AddView(fContentView); 338 339 BGroupLayout* rootLayout = new BGroupLayout(B_HORIZONTAL); 340 rootLayout->SetInsets(14, 14, 14, 14); 341 fBox->SetLayout(rootLayout); 342 343 rootLayout->AddView(scrollView); 344 345 rootLayout->AddView(rightView); 346 347 // Start the window 348 fInitCheck = InitMedia(true); 349 if (fInitCheck != B_OK) { 350 PostMessage(B_QUIT_REQUESTED); 351 } else { 352 if (IsHidden()) 353 Show(); 354 } 355 } 356 357 358 // #pragma mark - 359 360 361 status_t 362 MediaWindow::InitMedia(bool first) 363 { 364 status_t err = B_OK; 365 BMediaRoster* roster = BMediaRoster::Roster(&err); 366 367 if (first && err != B_OK) { 368 BAlert* alert = new BAlert("start_media_server", 369 B_TRANSLATE("Could not connect to the media server.\n" 370 "Would you like to start it ?"), 371 B_TRANSLATE("Quit"), 372 B_TRANSLATE("Start media server"), NULL, 373 B_WIDTH_AS_USUAL, B_WARNING_ALERT); 374 if (alert->Go()==0) 375 return B_ERROR; 376 377 fAlert = new MediaAlert(BRect(0, 0, 300, 60), 378 "restart_alert", B_TRANSLATE( 379 "Restarting media services\nStarting media server" 380 B_UTF8_ELLIPSIS "\n")); 381 fAlert->Show(); 382 383 Show(); 384 385 launch_media_server(); 386 } 387 388 Lock(); 389 390 bool isVideoSelected = true; 391 if (!first && fListView->ItemAt(0) && fListView->ItemAt(0)->IsSelected()) 392 isVideoSelected = false; 393 394 if ((!first || (first && err) ) && fAlert) { 395 BAutolock locker(fAlert); 396 if (locker.IsLocked()) 397 fAlert->TextView()->SetText( 398 B_TRANSLATE("Ready for use" B_UTF8_ELLIPSIS)); 399 } 400 401 while (fListView->CountItems() > 0) 402 delete static_cast<MediaListItem*>(fListView->RemoveItem((int32)0)); 403 _EmptyNodeLists(); 404 405 // Grab Media Info 406 _FindNodes(); 407 408 // Add video nodes first. They might have an additional audio 409 // output or input, but still should be listed as video node. 410 _AddNodeItems(fVideoOutputs, MediaListItem::VIDEO_TYPE); 411 _AddNodeItems(fVideoInputs, MediaListItem::VIDEO_TYPE); 412 _AddNodeItems(fAudioOutputs, MediaListItem::AUDIO_TYPE); 413 _AddNodeItems(fAudioInputs, MediaListItem::AUDIO_TYPE); 414 415 fAudioView->AddNodes(fAudioOutputs, false); 416 fAudioView->AddNodes(fAudioInputs, true); 417 fVideoView->AddNodes(fVideoOutputs, false); 418 fVideoView->AddNodes(fVideoInputs, true); 419 420 // build our list view 421 DeviceListItem* audio = new DeviceListItem(B_TRANSLATE("Audio settings"), 422 MediaListItem::AUDIO_TYPE); 423 fListView->AddItem(audio); 424 425 MediaListItem* video = new DeviceListItem(B_TRANSLATE("Video settings"), 426 MediaListItem::VIDEO_TYPE); 427 fListView->AddItem(video); 428 429 MediaListItem* mixer = new AudioMixerListItem(B_TRANSLATE("Audio mixer")); 430 fListView->AddItem(mixer); 431 432 fListView->SortItems(&MediaListItem::Compare); 433 434 // Set default nodes for our setting views 435 media_node default_node; 436 dormant_node_info node_info; 437 int32 outputID; 438 BString outputName; 439 440 if (roster->GetAudioInput(&default_node) == B_OK) { 441 roster->GetDormantNodeFor(default_node, &node_info); 442 NodeListItem* item = _FindNodeListItem(&node_info); 443 if (item) 444 item->SetDefaultInput(true); 445 fAudioView->SetDefault(node_info, true); 446 } 447 448 if (roster->GetAudioOutput(&default_node, &outputID, &outputName)==B_OK) { 449 roster->GetDormantNodeFor(default_node, &node_info); 450 NodeListItem* item = _FindNodeListItem(&node_info); 451 if (item) 452 item->SetDefaultOutput(true); 453 fAudioView->SetDefault(node_info, false, outputID); 454 } 455 456 if (roster->GetVideoInput(&default_node)==B_OK) { 457 roster->GetDormantNodeFor(default_node, &node_info); 458 NodeListItem* item = _FindNodeListItem(&node_info); 459 if (item) 460 item->SetDefaultInput(true); 461 fVideoView->SetDefault(node_info, true); 462 } 463 464 if (roster->GetVideoOutput(&default_node)==B_OK) { 465 roster->GetDormantNodeFor(default_node, &node_info); 466 NodeListItem* item = _FindNodeListItem(&node_info); 467 if (item) 468 item->SetDefaultOutput(true); 469 fVideoView->SetDefault(node_info, false); 470 } 471 472 if (first) { 473 fListView->Select(fListView->IndexOf(mixer)); 474 } else { 475 if (!fAudioView->fRestartView->IsHidden()) 476 fAudioView->fRestartView->Hide(); 477 if (!fVideoView->fRestartView->IsHidden()) 478 fVideoView->fRestartView->Hide(); 479 480 if (isVideoSelected) 481 fListView->Select(fListView->IndexOf(video)); 482 else 483 fListView->Select(fListView->IndexOf(audio)); 484 } 485 486 if (fAlert) { 487 snooze(800000); 488 fAlert->PostMessage(B_QUIT_REQUESTED); 489 } 490 fAlert = NULL; 491 492 Unlock(); 493 494 return B_OK; 495 } 496 497 498 bool 499 MediaWindow::QuitRequested() 500 { 501 // stop watching the MediaRoster 502 fCurrentNode.SetTo(NULL); 503 be_app->PostMessage(B_QUIT_REQUESTED); 504 return true; 505 } 506 507 508 void 509 MediaWindow::FrameResized (float width, float height) 510 { 511 // This makes sure our SideBar colours down to the bottom when resized 512 BRect r; 513 r = Bounds(); 514 } 515 516 517 // ErrorAlert -- Displays a BAlert Box with a Custom Error or Debug Message 518 void 519 ErrorAlert(char* errorMessage) { 520 printf("%s\n", errorMessage); 521 BAlert* alert = new BAlert("BAlert", errorMessage, B_TRANSLATE("OK"), 522 NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); 523 alert->Go(); 524 exit(1); 525 } 526 527 528 void 529 MediaWindow::MessageReceived(BMessage* message) 530 { 531 switch(message->what) 532 { 533 case ML_INIT_MEDIA: 534 InitMedia(false); 535 break; 536 case ML_DEFAULTOUTPUT_CHANGE: 537 { 538 int32 index; 539 if (message->FindInt32("index", &index)!=B_OK) 540 break; 541 Settings2Item* item = static_cast<Settings2Item*>( 542 fAudioView->fChannelMenu->ItemAt(index)); 543 544 if (item) { 545 BMediaRoster* roster = BMediaRoster::Roster(); 546 roster->SetAudioOutput(*item->fInput); 547 548 if (fAudioView->fRestartView->IsHidden()) 549 fAudioView->fRestartView->Show(); 550 } else 551 fprintf(stderr, "Settings2Item not found\n"); 552 } 553 break; 554 case ML_DEFAULT_CHANGE: 555 { 556 bool isVideo = true; 557 bool isInput = true; 558 if (message->FindBool("isVideo", &isVideo)!=B_OK) 559 break; 560 if (message->FindBool("isInput", &isInput)!=B_OK) 561 break; 562 int32 index; 563 if (message->FindInt32("index", &index)!=B_OK) 564 break; 565 SettingsView* settingsView = isVideo ? fVideoView : fAudioView; 566 BMenu* menu = isInput ? settingsView->fInputMenu 567 : settingsView->fOutputMenu; 568 SettingsItem* item = static_cast<SettingsItem*>( 569 menu->ItemAt(index)); 570 571 if (item) { 572 PRINT(("isVideo %i isInput %i\n", isVideo, isInput)); 573 BMediaRoster* roster = BMediaRoster::Roster(); 574 if (isVideo) { 575 if (isInput) 576 roster->SetVideoInput(*item->fInfo); 577 else 578 roster->SetVideoOutput(*item->fInfo); 579 } else { 580 if (isInput) 581 roster->SetAudioInput(*item->fInfo); 582 else { 583 roster->SetAudioOutput(*item->fInfo); 584 fAudioView->SetDefault(*item->fInfo, false, 0); 585 } 586 } 587 588 NodeListItem* oldListItem = NULL; 589 MediaListItem::media_type mediaType = isVideo ? 590 MediaListItem::VIDEO_TYPE : MediaListItem::AUDIO_TYPE; 591 for (int32 j = 0; j < fListView->CountItems(); j++) { 592 NodeListItem* item = dynamic_cast<NodeListItem*>( 593 fListView->ItemAt(j)); 594 if (!oldListItem) 595 continue; 596 if (oldListItem->Type() != mediaType) 597 continue; 598 if (isInput && !oldListItem->IsDefaultInput()) { 599 oldListItem = item; 600 break; 601 } else if (!isInput && oldListItem->IsDefaultOutput()) { 602 oldListItem = item; 603 break; 604 } 605 } 606 if (oldListItem && isInput) 607 oldListItem->SetDefaultInput(false); 608 else if (oldListItem && !isInput) 609 oldListItem->SetDefaultOutput(false); 610 else 611 fprintf(stderr, "oldListItem not found\n"); 612 613 NodeListItem* listItem = _FindNodeListItem(item->fInfo); 614 if (listItem && isInput) 615 listItem->SetDefaultInput(true); 616 else if (listItem && !isInput) 617 listItem->SetDefaultOutput(true); 618 else 619 fprintf(stderr, "MediaListItem not found\n"); 620 fListView->Invalidate(); 621 622 if (settingsView->fRestartView->IsHidden()) 623 settingsView->fRestartView->Show(); 624 } else 625 fprintf(stderr, "SettingsItem not found\n"); 626 } 627 break; 628 case ML_RESTART_MEDIA_SERVER: 629 { 630 thread_id thread = spawn_thread(&MediaWindow::RestartMediaServices, 631 "restart_thread", B_NORMAL_PRIORITY, this); 632 if (thread < B_OK) 633 fprintf(stderr, "couldn't create restart thread\n"); 634 else 635 resume_thread(thread); 636 break; 637 } 638 case ML_SHOW_VOLUME_CONTROL: 639 { 640 BDeskbar deskbar; 641 if (fAudioView->fVolumeCheckBox->Value() == B_CONTROL_ON) { 642 BEntry entry("/bin/desklink", true); 643 int32 id; 644 entry_ref ref; 645 status_t status = entry.GetRef(&ref); 646 if (status == B_OK) 647 status = deskbar.AddItem(&ref, &id); 648 649 if (status != B_OK) { 650 fprintf(stderr, B_TRANSLATE( 651 "Couldn't add volume control in Deskbar: %s\n"), 652 strerror(status)); 653 } 654 } else { 655 status_t status = deskbar.RemoveItem("MediaReplicant"); 656 if (status != B_OK) { 657 fprintf(stderr, B_TRANSLATE( 658 "Couldn't remove volume control in Deskbar: %s\n"), 659 strerror(status)); 660 } 661 } 662 break; 663 } 664 case ML_ENABLE_REAL_TIME: 665 { 666 bool isVideo = true; 667 if (message->FindBool("isVideo", &isVideo) != B_OK) 668 break; 669 SettingsView* settingsView = isVideo ? fVideoView : fAudioView; 670 uint32 flags; 671 uint32 realtimeFlag = isVideo 672 ? B_MEDIA_REALTIME_VIDEO : B_MEDIA_REALTIME_AUDIO; 673 BMediaRoster* roster = BMediaRoster::Roster(); 674 roster->GetRealtimeFlags(&flags); 675 if (settingsView->fRealtimeCheckBox->Value() == B_CONTROL_ON) 676 flags |= realtimeFlag; 677 else 678 flags &= ~realtimeFlag; 679 roster->SetRealtimeFlags(flags); 680 } 681 break; 682 case B_MEDIA_WEB_CHANGED: 683 case ML_SELECTED_NODE: 684 { 685 PRINT_OBJECT(*message); 686 687 MediaListItem* item = static_cast<MediaListItem*>( 688 fListView->ItemAt(fListView->CurrentSelection())); 689 if (!item) 690 break; 691 692 fCurrentNode.SetTo(NULL); 693 _ClearParamView(); 694 item->AlterWindow(this); 695 } 696 break; 697 case B_SOME_APP_LAUNCHED: 698 { 699 PRINT_OBJECT(*message); 700 if (!fAlert) 701 break; 702 703 BString mimeSig; 704 if (message->FindString("be:signature", &mimeSig) == B_OK 705 && (mimeSig == "application/x-vnd.Be.addon-host" 706 || mimeSig == "application/x-vnd.Be.media-server")) { 707 fAlert->Lock(); 708 fAlert->TextView()->SetText( 709 B_TRANSLATE("Starting media server" B_UTF8_ELLIPSIS)); 710 fAlert->Unlock(); 711 } 712 } 713 break; 714 case B_SOME_APP_QUIT: 715 { 716 PRINT_OBJECT(*message); 717 BString mimeSig; 718 if (message->FindString("be:signature", &mimeSig) == B_OK) { 719 if (mimeSig == "application/x-vnd.Be.addon-host" 720 || mimeSig == "application/x-vnd.Be.media-server") { 721 BMediaRoster* roster = BMediaRoster::CurrentRoster(); 722 if (roster && roster->Lock()) 723 roster->Quit(); 724 } 725 } 726 727 } 728 break; 729 default: 730 BWindow::MessageReceived(message); 731 break; 732 } 733 } 734 735 status_t 736 MediaWindow::RestartMediaServices(void* data) 737 { 738 MediaWindow* window = (MediaWindow*)data; 739 window->fAlert = new MediaAlert(BRect(0, 0, 300, 60), 740 "restart_alert", B_TRANSLATE( 741 "Restarting media services\nShutting down media server\n")); 742 743 window->fAlert->Show(); 744 745 shutdown_media_server(B_INFINITE_TIMEOUT, MediaWindow::UpdateProgress, 746 window->fAlert); 747 748 { 749 BAutolock locker(window->fAlert); 750 if (locker.IsLocked()) 751 window->fAlert->TextView()->SetText( 752 B_TRANSLATE("Starting media server" B_UTF8_ELLIPSIS)); 753 } 754 launch_media_server(); 755 756 return window->PostMessage(ML_INIT_MEDIA); 757 } 758 759 760 bool 761 MediaWindow::UpdateProgress(int stage, const char * message, void * cookie) 762 { 763 MediaAlert* alert = static_cast<MediaAlert*>(cookie); 764 PRINT(("stage : %i\n", stage)); 765 const char* string = "Unknown stage"; 766 switch (stage) { 767 case 10: 768 string = B_TRANSLATE("Stopping media server" B_UTF8_ELLIPSIS); 769 break; 770 case 20: 771 string = B_TRANSLATE("Telling media_addon_server to quit."); 772 break; 773 case 40: 774 string = B_TRANSLATE("Waiting for media_server to quit."); 775 break; 776 case 70: 777 string = B_TRANSLATE("Cleaning up."); 778 break; 779 case 100: 780 string = B_TRANSLATE("Done shutting down."); 781 break; 782 } 783 784 BAutolock locker(alert); 785 if (locker.IsLocked()) 786 alert->TextView()->SetText(string); 787 return true; 788 } 789 790 791 void 792 MediaWindow::_ClearParamView() 793 { 794 BView* child = fContentView->ChildAt(0); 795 if (child) 796 child->RemoveSelf(); 797 if (child != fVideoView && child != fAudioView) 798 delete child; 799 delete fParamWeb; 800 fParamWeb = NULL; 801 } 802 803 804 void 805 MediaWindow::_MakeParamView() 806 { 807 if (!fCurrentNode.IsSet()) 808 return; 809 810 fParamWeb = NULL; 811 BMediaRoster* roster = BMediaRoster::Roster(); 812 if (roster->GetParameterWebFor(fCurrentNode, &fParamWeb) == B_OK) { 813 BView* paramView = BMediaTheme::ViewFor(fParamWeb); 814 if (paramView) { 815 fContentView->AddChild(paramView); 816 paramView->ResizeTo(1, 1); 817 // make sure we don't get stuck with a very large 818 // paramView 819 return; 820 } 821 } 822 _MakeEmptyParamView(); 823 824 } 825 826 827 void 828 MediaWindow::_MakeEmptyParamView() 829 { 830 fParamWeb = NULL; 831 832 BStringView* stringView = new BStringView("noControls", 833 B_TRANSLATE("This hardware has no controls.")); 834 835 BSize unlimited(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); 836 stringView->SetExplicitMaxSize(unlimited); 837 838 BAlignment centered(B_ALIGN_HORIZONTAL_CENTER, 839 B_ALIGN_VERTICAL_CENTER); 840 stringView->SetExplicitAlignment(centered); 841 stringView->SetAlignment(B_ALIGN_CENTER); 842 843 fContentView->AddChild(stringView); 844 845 rgb_color panel = stringView->LowColor(); 846 stringView->SetHighColor(tint_color(panel, 847 B_DISABLED_LABEL_TINT)); 848 } 849 850