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