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