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