1 /* 2 * MainWin.cpp - Media Player for the Haiku Operating System 3 * 4 * Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de> 5 * Copyright (C) 2007-2008 Stephan Aßmus <superstippi@gmx.de> (GPL->MIT ok) 6 * Copyright (C) 2007-2008 Fredrik Modéen <fredrik@modeen.se> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * version 2 as published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 20 * USA. 21 * 22 */ 23 #include "MainWin.h" 24 25 #include <math.h> 26 #include <stdio.h> 27 #include <string.h> 28 29 #include <Alert.h> 30 #include <Application.h> 31 #include <Autolock.h> 32 #include <Debug.h> 33 #include <Menu.h> 34 #include <MenuBar.h> 35 #include <MenuItem.h> 36 #include <Messenger.h> 37 #include <PopUpMenu.h> 38 #include <RecentItems.h> 39 #include <Roster.h> 40 #include <Screen.h> 41 #include <String.h> 42 #include <View.h> 43 44 #include "ControllerObserver.h" 45 #include "MainApp.h" 46 #include "PlaylistObserver.h" 47 #include "PlaylistWindow.h" 48 #include "SettingsWindow.h" 49 50 #define NAME "MediaPlayer" 51 #define MIN_WIDTH 250 52 53 54 // XXX TODO: why is lround not defined? 55 #define lround(a) ((int)(0.99999 + (a))) 56 57 enum { 58 M_DUMMY = 0x100, 59 M_FILE_OPEN = 0x1000, 60 M_FILE_NEWPLAYER, 61 M_FILE_INFO, 62 M_FILE_PLAYLIST, 63 M_FILE_CLOSE, 64 M_FILE_QUIT, 65 M_VIEW_50, 66 M_VIEW_100, 67 M_VIEW_200, 68 M_VIEW_300, 69 M_VIEW_400, 70 M_TOGGLE_FULLSCREEN, 71 M_TOGGLE_NO_BORDER, 72 M_TOGGLE_NO_MENU, 73 M_TOGGLE_NO_CONTROLS, 74 M_TOGGLE_NO_BORDER_NO_MENU_NO_CONTROLS, 75 M_TOGGLE_ALWAYS_ON_TOP, 76 M_TOGGLE_KEEP_ASPECT_RATIO, 77 M_SETTINGS, 78 M_VOLUME_UP, 79 M_VOLUME_DOWN, 80 M_SKIP_NEXT, 81 M_SKIP_PREV, 82 M_ASPECT_100000_1, 83 M_ASPECT_106666_1, 84 M_ASPECT_109091_1, 85 M_ASPECT_141176_1, 86 M_ASPECT_720_576, 87 M_ASPECT_704_576, 88 M_ASPECT_544_576, 89 M_SELECT_AUDIO_TRACK = 0x00000800, 90 M_SELECT_AUDIO_TRACK_END = 0x00000fff, 91 M_SELECT_VIDEO_TRACK = 0x00010000, 92 M_SELECT_VIDEO_TRACK_END = 0x000fffff, 93 94 M_SET_PLAYLIST_POSITION 95 }; 96 97 //#define printf(a...) 98 99 100 MainWin::MainWin() 101 : BWindow(BRect(100,100,400,300), NAME, B_TITLED_WINDOW, 102 B_ASYNCHRONOUS_CONTROLS /* | B_WILL_ACCEPT_FIRST_CLICK */) 103 , fFilePanel(NULL) 104 , fInfoWin(NULL) 105 , fPlaylistWindow(NULL) 106 , fSettingsWindow(NULL) 107 , fHasFile(false) 108 , fHasVideo(false) 109 , fHasAudio(false) 110 , fPlaylist(new Playlist) 111 , fPlaylistObserver(new PlaylistObserver(this)) 112 , fController(new Controller) 113 , fControllerObserver(new ControllerObserver(this, 114 OBSERVE_FILE_CHANGES | OBSERVE_TRACK_CHANGES 115 | OBSERVE_PLAYBACK_STATE_CHANGES | OBSERVE_POSITION_CHANGES 116 | OBSERVE_VOLUME_CHANGES)) 117 , fIsFullscreen(false) 118 , fKeepAspectRatio(true) 119 , fAlwaysOnTop(false) 120 , fNoMenu(false) 121 , fNoBorder(false) 122 , fNoControls(false) 123 , fSourceWidth(0) 124 , fSourceHeight(0) 125 , fWidthScale(1.0) 126 , fHeightScale(1.0) 127 , fMouseDownTracking(false) 128 { 129 static int pos = 0; 130 MoveBy(pos * 25, pos * 25); 131 pos = (pos + 1) % 15; 132 133 BRect rect = Bounds(); 134 135 // background 136 fBackground = new BView(rect, "background", B_FOLLOW_ALL, 137 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE); 138 fBackground->SetViewColor(0,0,0); 139 AddChild(fBackground); 140 141 // menu 142 fMenuBar = new BMenuBar(fBackground->Bounds(), "menu"); 143 _CreateMenu(); 144 fBackground->AddChild(fMenuBar); 145 fMenuBar->ResizeToPreferred(); 146 fMenuBarWidth = (int)fMenuBar->Frame().Width() + 1; 147 fMenuBarHeight = (int)fMenuBar->Frame().Height() + 1; 148 fMenuBar->SetResizingMode(B_FOLLOW_NONE); 149 150 // video view 151 rect = BRect(0, fMenuBarHeight, fBackground->Bounds().right, 152 fMenuBarHeight + 10); 153 fVideoView = new VideoView(rect, "video display", B_FOLLOW_NONE, 154 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE); 155 fBackground->AddChild(fVideoView); 156 157 // controls 158 rect = BRect(0, fMenuBarHeight + 11, fBackground->Bounds().right, 159 fBackground->Bounds().bottom); 160 fControls = new ControllerView(rect, fController, fPlaylist); 161 fBackground->AddChild(fControls); 162 fControls->ResizeToPreferred(); 163 fControlsHeight = (int)fControls->Frame().Height() + 1; 164 fControlsWidth = (int)fControls->Frame().Width() + 1; 165 fControls->SetResizingMode(B_FOLLOW_BOTTOM | B_FOLLOW_LEFT_RIGHT); 166 // fControls->MoveTo(0, fBackground->Bounds().bottom - fControlsHeight + 1); 167 168 // fVideoView->ResizeTo(fBackground->Bounds().Width(), 169 // fBackground->Bounds().Height() - fMenuBarHeight - fControlsHeight); 170 171 fPlaylist->AddListener(fPlaylistObserver); 172 fController->SetVideoView(fVideoView); 173 fController->AddListener(fControllerObserver); 174 fVideoView->IsOverlaySupported(); 175 176 // printf("fMenuBarHeight %d\n", fMenuBarHeight); 177 // printf("fControlsHeight %d\n", fControlsHeight); 178 // printf("fControlsWidth %d\n", fControlsWidth); 179 180 _SetupWindow(); 181 182 // setup the settings window now, we need to have it 183 fSettingsWindow = new SettingsWindow(BRect(150, 150, 450, 520)); 184 fSettingsWindow->Hide(); 185 fSettingsWindow->Show(); 186 187 // setup the playlist window now, we need to have it 188 // running for the undo/redo playlist editing 189 fPlaylistWindow = new PlaylistWindow(BRect(150, 150, 500, 600), fPlaylist, 190 fController); 191 fPlaylistWindow->Hide(); 192 fPlaylistWindow->Show(); 193 // this makes sure the window thread is running without 194 // showing the window just yet 195 196 Show(); 197 } 198 199 200 MainWin::~MainWin() 201 { 202 printf("MainWin::~MainWin\n"); 203 204 fPlaylist->RemoveListener(fPlaylistObserver); 205 fController->RemoveListener(fControllerObserver); 206 207 // give the views a chance to detach from any notifiers 208 // before we delete them 209 fBackground->RemoveSelf(); 210 delete fBackground; 211 212 if (fInfoWin) { 213 fInfoWin->Lock(); 214 fInfoWin->Quit(); 215 } 216 if (fPlaylistWindow) { 217 fPlaylistWindow->Lock(); 218 fPlaylistWindow->Quit(); 219 } 220 221 if (fSettingsWindow) { 222 fSettingsWindow->Lock(); 223 fSettingsWindow->Quit(); 224 } 225 226 delete fPlaylist; 227 delete fController; 228 delete fFilePanel; 229 } 230 231 232 // #pragma mark - 233 234 235 void 236 MainWin::FrameResized(float new_width, float new_height) 237 { 238 if (new_width != Bounds().Width() || new_height != Bounds().Height()) { 239 debugger("size wrong\n"); 240 } 241 242 bool no_menu = fNoMenu || fIsFullscreen; 243 bool no_controls = fNoControls || fIsFullscreen; 244 245 printf("FrameResized enter: new_width %.0f, new_height %.0f\n", 246 new_width, new_height); 247 248 int max_video_width = int(new_width) + 1; 249 int max_video_height = int(new_height) + 1 250 - (no_menu ? 0 : fMenuBarHeight) 251 - (no_controls ? 0 : fControlsHeight); 252 253 ASSERT(max_video_height >= 0); 254 255 int y = 0; 256 257 if (no_menu) { 258 if (!fMenuBar->IsHidden()) 259 fMenuBar->Hide(); 260 } else { 261 // fMenuBar->MoveTo(0, y); 262 fMenuBar->ResizeTo(new_width, fMenuBarHeight - 1); 263 if (fMenuBar->IsHidden()) 264 fMenuBar->Show(); 265 y += fMenuBarHeight; 266 } 267 268 if (max_video_height == 0) { 269 if (!fVideoView->IsHidden()) 270 fVideoView->Hide(); 271 } else { 272 // fVideoView->MoveTo(0, y); 273 // fVideoView->ResizeTo(max_video_width - 1, max_video_height - 1); 274 _ResizeVideoView(0, y, max_video_width, max_video_height); 275 if (fVideoView->IsHidden()) 276 fVideoView->Show(); 277 y += max_video_height; 278 } 279 280 if (no_controls) { 281 if (!fControls->IsHidden()) 282 fControls->Hide(); 283 } else { 284 fControls->MoveTo(0, y); 285 fControls->ResizeTo(new_width, fControlsHeight - 1); 286 if (fControls->IsHidden()) 287 fControls->Show(); 288 // y += fControlsHeight; 289 } 290 291 printf("FrameResized leave\n"); 292 } 293 294 295 void 296 MainWin::Zoom(BPoint rec_position, float rec_width, float rec_height) 297 { 298 PostMessage(M_TOGGLE_FULLSCREEN); 299 } 300 301 302 void 303 MainWin::DispatchMessage(BMessage *msg, BHandler *handler) 304 { 305 if ((msg->what == B_MOUSE_DOWN) 306 && (handler == fBackground || handler == fVideoView 307 || handler == fControls)) 308 _MouseDown(msg, dynamic_cast<BView*>(handler)); 309 310 if ((msg->what == B_MOUSE_MOVED) 311 && (handler == fBackground || handler == fVideoView 312 || handler == fControls)) 313 _MouseMoved(msg, dynamic_cast<BView*>(handler)); 314 315 if ((msg->what == B_MOUSE_UP) 316 && (handler == fBackground || handler == fVideoView)) 317 _MouseUp(msg); 318 319 if ((msg->what == B_KEY_DOWN) 320 && (handler == fBackground || handler == fVideoView)) { 321 322 // special case for PrintScreen key 323 if (msg->FindInt32("key") == B_PRINT_KEY) { 324 fVideoView->OverlayScreenshotPrepare(); 325 BWindow::DispatchMessage(msg, handler); 326 fVideoView->OverlayScreenshotCleanup(); 327 return; 328 } 329 330 // every other key gets dispatched to our _KeyDown first 331 if (_KeyDown(msg) == B_OK) { 332 // it got handled, don't pass it on 333 return; 334 } 335 } 336 337 BWindow::DispatchMessage(msg, handler); 338 } 339 340 341 void 342 MainWin::MessageReceived(BMessage *msg) 343 { 344 // msg->PrintToStream(); 345 switch (msg->what) { 346 case B_REFS_RECEIVED: 347 printf("MainWin::MessageReceived: B_REFS_RECEIVED\n"); 348 _RefsReceived(msg); 349 break; 350 case B_SIMPLE_DATA: 351 printf("MainWin::MessageReceived: B_SIMPLE_DATA\n"); 352 if (msg->HasRef("refs")) { 353 // add to recent documents as it's not done with drag-n-drop 354 entry_ref ref; 355 for (int32 i = 0; msg->FindRef("refs", i, &ref) == B_OK; i++) { 356 be_roster->AddToRecentDocuments(&ref, kAppSig); 357 } 358 _RefsReceived(msg); 359 } 360 break; 361 362 case M_MEDIA_SERVER_STARTED: 363 // fController->... 364 break; 365 366 case M_MEDIA_SERVER_QUIT: 367 // fController->... 368 break; 369 370 // PlaylistObserver messages 371 case MSG_PLAYLIST_REF_ADDED: { 372 entry_ref ref; 373 int32 index; 374 if (msg->FindRef("refs", &ref) == B_OK 375 && msg->FindInt32("index", &index) == B_OK) { 376 _AddPlaylistItem(ref, index); 377 } 378 break; 379 } 380 case MSG_PLAYLIST_REF_REMOVED: { 381 int32 index; 382 if (msg->FindInt32("index", &index) == B_OK) { 383 _RemovePlaylistItem(index); 384 } 385 break; 386 } 387 case MSG_PLAYLIST_CURRENT_REF_CHANGED: { 388 BAutolock _(fPlaylist); 389 390 int32 index; 391 if (msg->FindInt32("index", &index) < B_OK 392 || index != fPlaylist->CurrentRefIndex()) 393 break; 394 entry_ref ref; 395 if (fPlaylist->GetRefAt(index, &ref) == B_OK) { 396 printf("open ref: %s\n", ref.name); 397 OpenFile(ref); 398 _MarkPlaylistItem(index); 399 } 400 break; 401 } 402 403 // ControllerObserver messages 404 case MSG_CONTROLLER_FILE_FINISHED: 405 fPlaylist->SetCurrentRefIndex(fPlaylist->CurrentRefIndex() + 1); 406 break; 407 case MSG_CONTROLLER_FILE_CHANGED: 408 // TODO: move all other GUI changes as a reaction to this 409 // notification 410 // _UpdatePlaylistMenu(); 411 break; 412 case MSG_CONTROLLER_VIDEO_TRACK_CHANGED: { 413 int32 index; 414 if (msg->FindInt32("index", &index) == B_OK) { 415 BMenuItem* item = fVideoTrackMenu->ItemAt(index); 416 if (item) 417 item->SetMarked(true); 418 } 419 break; 420 } 421 case MSG_CONTROLLER_AUDIO_TRACK_CHANGED: { 422 int32 index; 423 if (msg->FindInt32("index", &index) == B_OK) { 424 BMenuItem* item = fAudioTrackMenu->ItemAt(index); 425 if (item) 426 item->SetMarked(true); 427 } 428 break; 429 } 430 case MSG_CONTROLLER_PLAYBACK_STATE_CHANGED: { 431 uint32 state; 432 if (msg->FindInt32("state", (int32*)&state) == B_OK) 433 fControls->SetPlaybackState(state); 434 break; 435 } 436 case MSG_CONTROLLER_POSITION_CHANGED: { 437 float position; 438 if (msg->FindFloat("position", &position) == B_OK) 439 fControls->SetPosition(position); 440 break; 441 } 442 case MSG_CONTROLLER_VOLUME_CHANGED: { 443 float volume; 444 if (msg->FindFloat("volume", &volume) == B_OK) 445 fControls->SetVolume(volume); 446 break; 447 } 448 case MSG_CONTROLLER_MUTED_CHANGED: { 449 bool muted; 450 if (msg->FindBool("muted", &muted) == B_OK) 451 fControls->SetMuted(muted); 452 break; 453 } 454 455 // menu item messages 456 case M_FILE_NEWPLAYER: 457 gMainApp->NewWindow(); 458 break; 459 case M_FILE_OPEN: 460 if (!fFilePanel) { 461 fFilePanel = new BFilePanel(); 462 fFilePanel->SetTarget(BMessenger(0, this)); 463 fFilePanel->SetPanelDirectory("/boot/home/"); 464 } 465 fFilePanel->Show(); 466 break; 467 case M_FILE_INFO: 468 ShowFileInfo(); 469 break; 470 case M_FILE_PLAYLIST: 471 ShowPlaylistWindow(); 472 break; 473 case B_ABOUT_REQUESTED: 474 BAlert *alert; 475 alert = new BAlert("about", NAME"\n\n Written by Marcus Overhagen " 476 ", Stephan Aßmus and Frederik Modéen", "Thanks"); 477 if (fAlwaysOnTop) { 478 _ToggleAlwaysOnTop(); 479 alert->Go(); 480 _ToggleAlwaysOnTop(); 481 } else { 482 alert->Go(); 483 } 484 break; 485 case M_FILE_CLOSE: 486 PostMessage(B_QUIT_REQUESTED); 487 break; 488 case M_FILE_QUIT: 489 be_app->PostMessage(B_QUIT_REQUESTED); 490 break; 491 492 case M_TOGGLE_FULLSCREEN: 493 _ToggleFullscreen(); 494 break; 495 496 case M_TOGGLE_NO_MENU: 497 _ToggleNoMenu(); 498 break; 499 500 case M_TOGGLE_NO_CONTROLS: 501 _ToggleNoControls(); 502 break; 503 504 case M_TOGGLE_NO_BORDER: 505 _ToggleNoBorder(); 506 break; 507 508 case M_TOGGLE_ALWAYS_ON_TOP: 509 _ToggleAlwaysOnTop(); 510 break; 511 512 case M_TOGGLE_KEEP_ASPECT_RATIO: 513 _ToggleKeepAspectRatio(); 514 break; 515 516 case M_TOGGLE_NO_BORDER_NO_MENU_NO_CONTROLS: 517 _ToggleNoBorderNoMenu(); 518 break; 519 520 case M_VIEW_50: 521 if (!fHasVideo) 522 break; 523 if (fIsFullscreen) 524 _ToggleFullscreen(); 525 _ResizeWindow(50); 526 break; 527 528 case M_VIEW_100: 529 if (!fHasVideo) 530 break; 531 if (fIsFullscreen) 532 _ToggleFullscreen(); 533 _ResizeWindow(100); 534 break; 535 536 case M_VIEW_200: 537 if (!fHasVideo) 538 break; 539 if (fIsFullscreen) 540 _ToggleFullscreen(); 541 _ResizeWindow(200); 542 break; 543 544 case M_VIEW_300: 545 if (!fHasVideo) 546 break; 547 if (fIsFullscreen) 548 _ToggleFullscreen(); 549 _ResizeWindow(300); 550 break; 551 552 case M_VIEW_400: 553 if (!fHasVideo) 554 break; 555 if (fIsFullscreen) 556 _ToggleFullscreen(); 557 _ResizeWindow(400); 558 break; 559 560 /* 561 562 case B_ACQUIRE_OVERLAY_LOCK: 563 printf("B_ACQUIRE_OVERLAY_LOCK\n"); 564 fVideoView->OverlayLockAcquire(); 565 break; 566 567 case B_RELEASE_OVERLAY_LOCK: 568 printf("B_RELEASE_OVERLAY_LOCK\n"); 569 fVideoView->OverlayLockRelease(); 570 break; 571 572 case B_MOUSE_WHEEL_CHANGED: 573 { 574 printf("B_MOUSE_WHEEL_CHANGED\n"); 575 float dx = msg->FindFloat("be:wheel_delta_x"); 576 float dy = msg->FindFloat("be:wheel_delta_y"); 577 bool inv = modifiers() & B_COMMAND_KEY; 578 if (dx > 0.1) PostMessage(inv ? M_VOLUME_DOWN : M_SKIP_PREV); 579 if (dx < -0.1) PostMessage(inv ? M_VOLUME_UP : M_SKIP_NEXT); 580 if (dy > 0.1) PostMessage(inv ? M_SKIP_PREV : M_VOLUME_DOWN); 581 if (dy < -0.1) PostMessage(inv ? M_SKIP_NEXT : M_VOLUME_UP); 582 break; 583 } 584 */ 585 case M_SKIP_NEXT: 586 fControls->SkipForward(); 587 break; 588 589 case M_SKIP_PREV: 590 fControls->SkipBackward(); 591 break; 592 593 case M_VOLUME_UP: 594 fController->VolumeUp(); 595 break; 596 597 case M_VOLUME_DOWN: 598 fController->VolumeDown(); 599 break; 600 601 case M_ASPECT_100000_1: 602 VideoFormatChange(fSourceWidth, fSourceHeight, 1.0, 1.0); 603 break; 604 605 case M_ASPECT_106666_1: 606 VideoFormatChange(fSourceWidth, fSourceHeight, 1.06666, 1.0); 607 break; 608 609 case M_ASPECT_109091_1: 610 VideoFormatChange(fSourceWidth, fSourceHeight, 1.09091, 1.0); 611 break; 612 613 case M_ASPECT_141176_1: 614 VideoFormatChange(fSourceWidth, fSourceHeight, 1.41176, 1.0); 615 break; 616 617 case M_ASPECT_720_576: 618 VideoFormatChange(720, 576, 1.06666, 1.0); 619 break; 620 621 case M_ASPECT_704_576: 622 VideoFormatChange(704, 576, 1.09091, 1.0); 623 break; 624 625 case M_ASPECT_544_576: 626 VideoFormatChange(544, 576, 1.41176, 1.0); 627 break; 628 629 case M_SETTINGS: 630 ShowSettingsWindow(); 631 break; 632 /* 633 default: 634 if (msg->what >= M_SELECT_CHANNEL 635 && msg->what <= M_SELECT_CHANNEL_END) { 636 SelectChannel(msg->what - M_SELECT_CHANNEL); 637 break; 638 } 639 if (msg->what >= M_SELECT_INTERFACE 640 && msg->what <= M_SELECT_INTERFACE_END) { 641 SelectInterface(msg->what - M_SELECT_INTERFACE - 1); 642 break; 643 } 644 */ 645 case M_SET_PLAYLIST_POSITION: { 646 int32 index; 647 if (msg->FindInt32("index", &index) == B_OK) 648 fPlaylist->SetCurrentRefIndex(index); 649 break; 650 } 651 652 default: 653 // let BWindow handle the rest 654 BWindow::MessageReceived(msg); 655 } 656 } 657 658 659 bool 660 MainWin::QuitRequested() 661 { 662 be_app->PostMessage(M_PLAYER_QUIT); 663 return true; 664 } 665 666 667 // #pragma mark - 668 669 670 void 671 MainWin::OpenFile(const entry_ref &ref) 672 { 673 printf("MainWin::OpenFile\n"); 674 675 status_t err = fController->SetTo(ref); 676 if (err != B_OK) { 677 if (fPlaylist->CountItems() == 1) { 678 // display error if this is the only file we're supposed to play 679 char s[300]; 680 sprintf(s, "Can't open file\n\n%s\n\nError 0x%08lx\n(%s)\n", 681 ref.name, err, strerror(err)); 682 (new BAlert("error", s, "OK"))->Go(); 683 } else { 684 // just go to the next file and don't bother user 685 fPlaylist->SetCurrentRefIndex(fPlaylist->CurrentRefIndex() + 1); 686 } 687 fHasFile = false; 688 fHasVideo = false; 689 fHasAudio = false; 690 SetTitle(NAME); 691 } else { 692 fHasFile = true; 693 fHasVideo = fController->VideoTrackCount() != 0; 694 fHasAudio = fController->AudioTrackCount() != 0; 695 SetTitle(ref.name); 696 } 697 _SetupWindow(); 698 } 699 700 701 void 702 MainWin::ShowFileInfo() 703 { 704 if (!fInfoWin) 705 fInfoWin = new InfoWin(Frame().LeftTop(), fController); 706 707 if (fInfoWin->Lock()) { 708 if (fInfoWin->IsHidden()) 709 fInfoWin->Show(); 710 else 711 fInfoWin->Activate(); 712 fInfoWin->Unlock(); 713 } 714 } 715 716 717 void 718 MainWin::ShowPlaylistWindow() 719 { 720 if (fPlaylistWindow->Lock()) { 721 if (fPlaylistWindow->IsHidden()) 722 fPlaylistWindow->Show(); 723 else 724 fPlaylistWindow->Activate(); 725 fPlaylistWindow->Unlock(); 726 } 727 } 728 729 730 void 731 MainWin::ShowSettingsWindow() 732 { 733 if (fSettingsWindow->Lock()) { 734 if (fSettingsWindow->IsHidden()) 735 fSettingsWindow->Show(); 736 else 737 fSettingsWindow->Activate(); 738 fSettingsWindow->Unlock(); 739 } 740 } 741 742 743 void 744 MainWin::VideoFormatChange(int width, int height, float width_scale, 745 float height_scale) 746 { 747 // called when video format or aspect ratio changes 748 749 printf("VideoFormatChange enter: width %d, height %d, width_scale %.6f, " 750 "height_scale %.6f\n", width, height, width_scale, height_scale); 751 752 if (width_scale < 1.0 && height_scale >= 1.0) { 753 width_scale = 1.0 / width_scale; 754 height_scale = 1.0 / height_scale; 755 printf("inverting! new values: width_scale %.6f, height_scale %.6f\n", 756 width_scale, height_scale); 757 } 758 759 fSourceWidth = width; 760 fSourceHeight = height; 761 fWidthScale = width_scale; 762 fHeightScale = height_scale; 763 764 FrameResized(Bounds().Width(), Bounds().Height()); 765 766 printf("VideoFormatChange leave\n"); 767 } 768 769 770 // #pragma mark - 771 772 773 void 774 MainWin::_RefsReceived(BMessage* msg) 775 { 776 // the playlist ist replaced by dropped files 777 // or the dropped files are appended to the end 778 // of the existing playlist if <shift> is pressed 779 int32 appendIndex = modifiers() & B_SHIFT_KEY ? 780 fPlaylist->CountItems() : -1; 781 msg->AddInt32("append_index", appendIndex); 782 783 // forward the message to the playlist window, 784 // so that undo/redo is used for modifying the playlist 785 fPlaylistWindow->PostMessage(msg); 786 } 787 788 789 void 790 MainWin::_SetupWindow() 791 { 792 printf("MainWin::_SetupWindow\n"); 793 // Populate the track menus 794 _SetupTrackMenus(); 795 // Enable both if a file was loaded 796 fAudioTrackMenu->SetEnabled(fHasFile); 797 fVideoTrackMenu->SetEnabled(fHasFile); 798 // Select first track (might be "none") in both 799 fAudioTrackMenu->ItemAt(0)->SetMarked(true); 800 fVideoTrackMenu->ItemAt(0)->SetMarked(true); 801 802 fVideoMenu->SetEnabled(fHasVideo); 803 fAudioMenu->SetEnabled(fHasAudio); 804 // fDebugMenu->SetEnabled(fHasVideo); 805 if (fHasVideo) { 806 fController->GetSize(&fSourceWidth, &fSourceHeight); 807 fWidthScale = 1.0; 808 fHeightScale = 1.0; 809 } else { 810 fSourceWidth = 0; 811 fSourceHeight = 0; 812 fWidthScale = 1.0; 813 fHeightScale = 1.0; 814 } 815 _UpdateControlsEnabledStatus(); 816 817 _ResizeWindow(100); 818 819 fVideoView->MakeFocus(); 820 } 821 822 823 void 824 MainWin::_CreateMenu() 825 { 826 fFileMenu = new BMenu(NAME); 827 fPlaylistMenu = new BMenu("Playlist"B_UTF8_ELLIPSIS); 828 fAudioMenu = new BMenu("Audio"); 829 fVideoMenu = new BMenu("Video"); 830 fSettingsMenu = new BMenu("Settings"); 831 fAudioTrackMenu = new BMenu("Track"); 832 fVideoTrackMenu = new BMenu("Track"); 833 // fDebugMenu = new BMenu("Debug"); 834 835 fMenuBar->AddItem(fFileMenu); 836 fMenuBar->AddItem(fAudioMenu); 837 fMenuBar->AddItem(fVideoMenu); 838 fMenuBar->AddItem(fSettingsMenu); 839 // fMenuBar->AddItem(fDebugMenu); 840 841 fFileMenu->AddItem(new BMenuItem("New Player"B_UTF8_ELLIPSIS, 842 new BMessage(M_FILE_NEWPLAYER), 'N')); 843 fFileMenu->AddSeparatorItem(); 844 845 // fFileMenu->AddItem(new BMenuItem("Open File"B_UTF8_ELLIPSIS, 846 // new BMessage(M_FILE_OPEN), 'O')); 847 // Add recent files 848 BRecentFilesList recentFiles(10, false, NULL, kAppSig); 849 BMenuItem *item = new BMenuItem(recentFiles.NewFileListMenu( 850 "Open File"B_UTF8_ELLIPSIS, new BMessage(B_REFS_RECEIVED), 851 NULL, this, 10, false, NULL, 0, kAppSig), new BMessage(M_FILE_OPEN)); 852 item->SetShortcut('O', 0); 853 fFileMenu->AddItem(item); 854 855 fFileMenu->AddItem(new BMenuItem("File Info"B_UTF8_ELLIPSIS, 856 new BMessage(M_FILE_INFO), 'I')); 857 fFileMenu->AddItem(fPlaylistMenu); 858 fPlaylistMenu->Superitem()->SetShortcut('P', B_COMMAND_KEY); 859 fPlaylistMenu->Superitem()->SetMessage(new BMessage(M_FILE_PLAYLIST)); 860 861 fFileMenu->AddSeparatorItem(); 862 fFileMenu->AddItem(new BMenuItem("About" NAME B_UTF8_ELLIPSIS, 863 new BMessage(B_ABOUT_REQUESTED))); 864 fFileMenu->AddSeparatorItem(); 865 fFileMenu->AddItem(new BMenuItem("Close", new BMessage(M_FILE_CLOSE), 'W')); 866 fFileMenu->AddItem(new BMenuItem("Quit", new BMessage(M_FILE_QUIT), 'Q')); 867 868 fPlaylistMenu->SetRadioMode(true); 869 870 fAudioMenu->AddItem(fAudioTrackMenu); 871 872 fVideoMenu->AddItem(fVideoTrackMenu); 873 fVideoMenu->AddSeparatorItem(); 874 fVideoMenu->AddItem(new BMenuItem("50% scale", 875 new BMessage(M_VIEW_50), '0')); 876 fVideoMenu->AddItem(new BMenuItem("100% scale", 877 new BMessage(M_VIEW_100), '1')); 878 fVideoMenu->AddItem(new BMenuItem("200% scale", 879 new BMessage(M_VIEW_200), '2')); 880 fVideoMenu->AddItem(new BMenuItem("300% scale", 881 new BMessage(M_VIEW_300), '3')); 882 fVideoMenu->AddItem(new BMenuItem("400% scale", 883 new BMessage(M_VIEW_400), '4')); 884 fVideoMenu->AddSeparatorItem(); 885 fVideoMenu->AddItem(new BMenuItem("Full Screen", 886 new BMessage(M_TOGGLE_FULLSCREEN), 'F')); 887 fVideoMenu->AddItem(new BMenuItem("Keep Aspect Ratio", 888 new BMessage(M_TOGGLE_KEEP_ASPECT_RATIO), 'K')); 889 890 fSettingsMenu->AddItem(new BMenuItem("No Menu", 891 new BMessage(M_TOGGLE_NO_MENU), 'M')); 892 fSettingsMenu->AddItem(new BMenuItem("No Border", 893 new BMessage(M_TOGGLE_NO_BORDER), 'B')); 894 fSettingsMenu->AddItem(new BMenuItem("No Controls", 895 new BMessage(M_TOGGLE_NO_CONTROLS), 'C')); 896 fSettingsMenu->AddItem(new BMenuItem("Always on Top", 897 new BMessage(M_TOGGLE_ALWAYS_ON_TOP), 'T')); 898 // fSettingsMenu->AddSeparatorItem(); 899 // fSettingsMenu->AddItem(new BMenuItem("Settings"B_UTF8_ELLIPSIS, 900 // new BMessage(M_SETTINGS), 'S')); 901 902 // fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.00000:1", 903 // new BMessage(M_ASPECT_100000_1))); 904 // fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.06666:1", 905 // new BMessage(M_ASPECT_106666_1))); 906 // fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.09091:1", 907 // new BMessage(M_ASPECT_109091_1))); 908 // fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.41176:1", 909 // new BMessage(M_ASPECT_141176_1))); 910 // fDebugMenu->AddItem(new BMenuItem("force 720 x 576, display aspect 4:3", 911 // new BMessage(M_ASPECT_720_576))); 912 // fDebugMenu->AddItem(new BMenuItem("force 704 x 576, display aspect 4:3", 913 // new BMessage(M_ASPECT_704_576))); 914 // fDebugMenu->AddItem(new BMenuItem("force 544 x 576, display aspect 4:3", 915 // new BMessage(M_ASPECT_544_576))); 916 917 fAudioTrackMenu->SetRadioMode(true); 918 fVideoTrackMenu->SetRadioMode(true); 919 } 920 921 922 void 923 MainWin::_SetupTrackMenus() 924 { 925 fAudioTrackMenu->RemoveItems(0, fAudioTrackMenu->CountItems(), true); 926 fVideoTrackMenu->RemoveItems(0, fVideoTrackMenu->CountItems(), true); 927 928 int c, i; 929 char s[100]; 930 931 c = fController->AudioTrackCount(); 932 for (i = 0; i < c; i++) { 933 sprintf(s, "Track %d", i + 1); 934 fAudioTrackMenu->AddItem(new BMenuItem(s, 935 new BMessage(M_SELECT_AUDIO_TRACK + i))); 936 } 937 if (!c) 938 fAudioTrackMenu->AddItem(new BMenuItem("none", new BMessage(M_DUMMY))); 939 940 c = fController->VideoTrackCount(); 941 for (i = 0; i < c; i++) { 942 sprintf(s, "Track %d", i + 1); 943 fVideoTrackMenu->AddItem(new BMenuItem(s, 944 new BMessage(M_SELECT_VIDEO_TRACK + i))); 945 } 946 if (!c) 947 fVideoTrackMenu->AddItem(new BMenuItem("none", new BMessage(M_DUMMY))); 948 } 949 950 951 void 952 MainWin::_SetWindowSizeLimits() 953 { 954 int minWidth = fNoControls ? MIN_WIDTH : fControlsWidth; 955 if (!fNoMenu) 956 minWidth = max_c(minWidth, fMenuBarWidth); 957 int minHeight = (fNoMenu ? 0 : fMenuBarHeight) 958 + (fNoControls ? 0 : fControlsHeight); 959 960 SetSizeLimits(minWidth - 1, 32000, minHeight - 1, fHasVideo ? 961 32000 : minHeight - 1); 962 } 963 964 965 void 966 MainWin::_ResizeWindow(int percent) 967 { 968 int video_width; 969 int video_height; 970 971 // Get required window size 972 video_width = lround(fSourceWidth * fWidthScale); 973 video_height = lround(fSourceHeight * fHeightScale); 974 975 video_width = (video_width * percent) / 100; 976 video_height = (video_height * percent) / 100; 977 978 // Calculate and set the initial window size 979 int width = max_c(fControlsWidth, video_width); 980 int height = (fNoControls ? 0 : fControlsHeight) + video_height; 981 if (!fNoMenu) { 982 width = max_c(width, fMenuBarWidth); 983 height += fMenuBarHeight; 984 } 985 _SetWindowSizeLimits(); 986 ResizeTo(width - 1, height - 1); 987 } 988 989 990 void 991 MainWin::_ResizeVideoView(int x, int y, int width, int height) 992 { 993 printf("_ResizeVideoView: %d,%d, width %d, height %d\n", x, y, 994 width, height); 995 996 if (fKeepAspectRatio) { 997 // Keep aspect ratio, place video view inside 998 // the background area (may create black bars). 999 float scaled_width = fSourceWidth * fWidthScale; 1000 float scaled_height = fSourceHeight * fHeightScale; 1001 float factor = min_c(width / scaled_width, height / scaled_height); 1002 int render_width = lround(scaled_width * factor); 1003 int render_height = lround(scaled_height * factor); 1004 if (render_width > width) 1005 render_width = width; 1006 if (render_height > height) 1007 render_height = height; 1008 1009 int x_ofs = x + (width - render_width) / 2; 1010 int y_ofs = y + (height - render_height) / 2; 1011 1012 fVideoView->MoveTo(x_ofs, y_ofs); 1013 fVideoView->ResizeTo(render_width - 1, render_height - 1); 1014 1015 } else { 1016 fVideoView->MoveTo(x, y); 1017 fVideoView->ResizeTo(width - 1, height - 1); 1018 } 1019 } 1020 1021 1022 // #pragma mark - 1023 1024 1025 void 1026 MainWin::_MouseDown(BMessage *msg, BView* originalHandler) 1027 { 1028 BPoint screen_where; 1029 uint32 buttons = msg->FindInt32("buttons"); 1030 1031 // On Zeta, only "screen_where" is relyable, "where" and "be:view_where" 1032 // seem to be broken 1033 if (B_OK != msg->FindPoint("screen_where", &screen_where)) { 1034 // Workaround for BeOS R5, it has no "screen_where" 1035 if (!originalHandler || msg->FindPoint("where", &screen_where) < B_OK) 1036 return; 1037 originalHandler->ConvertToScreen(&screen_where); 1038 } 1039 1040 // msg->PrintToStream(); 1041 1042 // if (1 == msg->FindInt32("buttons") && msg->FindInt32("clicks") == 1) { 1043 1044 if (1 == buttons && msg->FindInt32("clicks") % 2 == 0) { 1045 BRect r(screen_where.x - 1, screen_where.y - 1, screen_where.x + 1, 1046 screen_where.y + 1); 1047 if (r.Contains(fMouseDownMousePos)) { 1048 PostMessage(M_TOGGLE_FULLSCREEN); 1049 return; 1050 } 1051 } 1052 1053 if (2 == buttons && msg->FindInt32("clicks") % 2 == 0) { 1054 BRect r(screen_where.x - 1, screen_where.y - 1, screen_where.x + 1, 1055 screen_where.y + 1); 1056 if (r.Contains(fMouseDownMousePos)) { 1057 PostMessage(M_TOGGLE_NO_BORDER_NO_MENU_NO_CONTROLS); 1058 return; 1059 } 1060 } 1061 1062 /* 1063 // very broken in Zeta: 1064 fMouseDownMousePos = fVideoView->ConvertToScreen( 1065 msg->FindPoint("where")); 1066 */ 1067 fMouseDownMousePos = screen_where; 1068 fMouseDownWindowPos = Frame().LeftTop(); 1069 1070 if (buttons == 1 && !fIsFullscreen) { 1071 // start mouse tracking 1072 fVideoView->SetMouseEventMask(B_POINTER_EVENTS | B_NO_POINTER_HISTORY 1073 /* | B_LOCK_WINDOW_FOCUS */); 1074 fMouseDownTracking = true; 1075 } 1076 1077 // pop up a context menu if right mouse button is down for 200 ms 1078 1079 if ((buttons & 2) == 0) 1080 return; 1081 bigtime_t start = system_time(); 1082 bigtime_t delay = 200000; 1083 BPoint location; 1084 do { 1085 fVideoView->GetMouse(&location, &buttons); 1086 if ((buttons & 2) == 0) 1087 break; 1088 snooze(1000); 1089 } while (system_time() - start < delay); 1090 1091 if (buttons & 2) 1092 _ShowContextMenu(screen_where); 1093 } 1094 1095 1096 void 1097 MainWin::_MouseMoved(BMessage *msg, BView* originalHandler) 1098 { 1099 // msg->PrintToStream(); 1100 1101 BPoint mousePos; 1102 uint32 buttons = msg->FindInt32("buttons"); 1103 1104 if (1 == buttons && fMouseDownTracking && !fIsFullscreen) { 1105 /* 1106 // very broken in Zeta: 1107 BPoint mousePos = msg->FindPoint("where"); 1108 printf("view where: %.0f, %.0f => ", mousePos.x, mousePos.y); 1109 fVideoView->ConvertToScreen(&mousePos); 1110 */ 1111 // On Zeta, only "screen_where" is relyable, "where" 1112 // and "be:view_where" seem to be broken 1113 if (B_OK != msg->FindPoint("screen_where", &mousePos)) { 1114 // Workaround for BeOS R5, it has no "screen_where" 1115 if (!originalHandler || msg->FindPoint("where", &mousePos) < B_OK) 1116 return; 1117 originalHandler->ConvertToScreen(&mousePos); 1118 } 1119 // printf("screen where: %.0f, %.0f => ", mousePos.x, mousePos.y); 1120 float delta_x = mousePos.x - fMouseDownMousePos.x; 1121 float delta_y = mousePos.y - fMouseDownMousePos.y; 1122 float x = fMouseDownWindowPos.x + delta_x; 1123 float y = fMouseDownWindowPos.y + delta_y; 1124 // printf("move window to %.0f, %.0f\n", x, y); 1125 MoveTo(x, y); 1126 } 1127 } 1128 1129 1130 void 1131 MainWin::_MouseUp(BMessage *msg) 1132 { 1133 // msg->PrintToStream(); 1134 fMouseDownTracking = false; 1135 } 1136 1137 1138 void 1139 MainWin::_ShowContextMenu(const BPoint &screen_point) 1140 { 1141 printf("Show context menu\n"); 1142 BPopUpMenu *menu = new BPopUpMenu("context menu", false, false); 1143 BMenuItem *item; 1144 menu->AddItem(item = new BMenuItem("Full Screen", 1145 new BMessage(M_TOGGLE_FULLSCREEN), 'F')); 1146 item->SetMarked(fIsFullscreen); 1147 item->SetEnabled(fHasVideo); 1148 menu->AddItem(item = new BMenuItem("Keep Aspect Ratio", 1149 new BMessage(M_TOGGLE_KEEP_ASPECT_RATIO), 'K')); 1150 item->SetMarked(fKeepAspectRatio); 1151 item->SetEnabled(fHasVideo); 1152 1153 menu->AddSeparatorItem(); 1154 menu->AddItem(item = new BMenuItem("No Menu", 1155 new BMessage(M_TOGGLE_NO_MENU), 'M')); 1156 item->SetMarked(fNoMenu); 1157 menu->AddItem(item = new BMenuItem("No Border", 1158 new BMessage(M_TOGGLE_NO_BORDER), 'B')); 1159 item->SetMarked(fNoBorder); 1160 menu->AddItem(item = new BMenuItem("Always on Top", 1161 new BMessage(M_TOGGLE_ALWAYS_ON_TOP), 'T')); 1162 item->SetMarked(fAlwaysOnTop); 1163 1164 menu->AddSeparatorItem(); 1165 menu->AddItem(new BMenuItem("About" NAME B_UTF8_ELLIPSIS, 1166 new BMessage(B_ABOUT_REQUESTED))); 1167 menu->AddSeparatorItem(); 1168 menu->AddItem(new BMenuItem("Quit", new BMessage(M_FILE_QUIT), 'Q')); 1169 1170 menu->AddSeparatorItem(); 1171 menu->AddItem(new BMenuItem("pixel aspect ratio 1.00000:1", 1172 new BMessage(M_ASPECT_100000_1))); 1173 menu->AddItem(new BMenuItem("pixel aspect ratio 1.06666:1", 1174 new BMessage(M_ASPECT_106666_1))); 1175 menu->AddItem(new BMenuItem("pixel aspect ratio 1.09091:1", 1176 new BMessage(M_ASPECT_109091_1))); 1177 menu->AddItem(new BMenuItem("pixel aspect ratio 1.41176:1", 1178 new BMessage(M_ASPECT_141176_1))); 1179 menu->AddItem(new BMenuItem("force 720 x 576, display aspect 4:3", 1180 new BMessage(M_ASPECT_720_576))); 1181 menu->AddItem(new BMenuItem("force 704 x 576, display aspect 4:3", 1182 new BMessage(M_ASPECT_704_576))); 1183 menu->AddItem(new BMenuItem("force 544 x 576, display aspect 4:3", 1184 new BMessage(M_ASPECT_544_576))); 1185 1186 menu->SetTargetForItems(this); 1187 BRect r(screen_point.x - 5, screen_point.y - 5, screen_point.x + 5, 1188 screen_point.y + 5); 1189 menu->Go(screen_point, true, true, r, true); 1190 } 1191 1192 1193 /* Trap keys that are about to be send to background or renderer view. 1194 * Return B_OK if it shouldn't be passed to the view 1195 */ 1196 status_t 1197 MainWin::_KeyDown(BMessage *msg) 1198 { 1199 // msg->PrintToStream(); 1200 1201 uint32 key = msg->FindInt32("key"); 1202 uint32 raw_char = msg->FindInt32("raw_char"); 1203 uint32 modifiers = msg->FindInt32("modifiers"); 1204 1205 printf("key 0x%lx, raw_char 0x%lx, modifiers 0x%lx\n", key, raw_char, 1206 modifiers); 1207 1208 switch (raw_char) { 1209 case B_SPACE: 1210 if (fController->IsPaused() || fController->IsStopped()) 1211 fController->Play(); 1212 else 1213 fController->Pause(); 1214 return B_OK; 1215 1216 case B_ESCAPE: 1217 if (fIsFullscreen) { 1218 PostMessage(M_TOGGLE_FULLSCREEN); 1219 return B_OK; 1220 } else 1221 break; 1222 1223 case B_ENTER: // Enter / Return 1224 if (modifiers & B_COMMAND_KEY) { 1225 PostMessage(M_TOGGLE_FULLSCREEN); 1226 return B_OK; 1227 } else 1228 break; 1229 1230 case B_TAB: 1231 if ((modifiers & (B_COMMAND_KEY | B_CONTROL_KEY | B_OPTION_KEY 1232 | B_MENU_KEY)) == 0) { 1233 PostMessage(M_TOGGLE_FULLSCREEN); 1234 return B_OK; 1235 } else 1236 break; 1237 1238 case B_UP_ARROW: 1239 if (modifiers & B_COMMAND_KEY) { 1240 PostMessage(M_SKIP_NEXT); 1241 } else { 1242 PostMessage(M_VOLUME_UP); 1243 } 1244 return B_OK; 1245 1246 case B_DOWN_ARROW: 1247 if (modifiers & B_COMMAND_KEY) { 1248 PostMessage(M_SKIP_PREV); 1249 } else { 1250 PostMessage(M_VOLUME_DOWN); 1251 } 1252 return B_OK; 1253 1254 case B_RIGHT_ARROW: 1255 if (modifiers & B_COMMAND_KEY) { 1256 PostMessage(M_VOLUME_UP); 1257 } else { 1258 PostMessage(M_SKIP_NEXT); 1259 } 1260 return B_OK; 1261 1262 case B_LEFT_ARROW: 1263 if (modifiers & B_COMMAND_KEY) { 1264 PostMessage(M_VOLUME_DOWN); 1265 } else { 1266 PostMessage(M_SKIP_PREV); 1267 } 1268 return B_OK; 1269 1270 case B_PAGE_UP: 1271 PostMessage(M_SKIP_NEXT); 1272 return B_OK; 1273 1274 case B_PAGE_DOWN: 1275 PostMessage(M_SKIP_PREV); 1276 return B_OK; 1277 } 1278 1279 switch (key) { 1280 case 0x3a: // numeric keypad + 1281 if ((modifiers & B_COMMAND_KEY) == 0) { 1282 printf("if\n"); 1283 PostMessage(M_VOLUME_UP); 1284 return B_OK; 1285 } else { 1286 printf("else\n"); 1287 break; 1288 } 1289 1290 case 0x25: // numeric keypad - 1291 if ((modifiers & B_COMMAND_KEY) == 0) { 1292 PostMessage(M_VOLUME_DOWN); 1293 return B_OK; 1294 } else { 1295 break; 1296 } 1297 1298 case 0x38: // numeric keypad up arrow 1299 PostMessage(M_VOLUME_UP); 1300 return B_OK; 1301 1302 case 0x59: // numeric keypad down arrow 1303 PostMessage(M_VOLUME_DOWN); 1304 return B_OK; 1305 1306 case 0x39: // numeric keypad page up 1307 case 0x4a: // numeric keypad right arrow 1308 PostMessage(M_SKIP_NEXT); 1309 return B_OK; 1310 1311 case 0x5a: // numeric keypad page down 1312 case 0x48: // numeric keypad left arrow 1313 PostMessage(M_SKIP_PREV); 1314 return B_OK; 1315 } 1316 1317 return B_ERROR; 1318 } 1319 1320 1321 // #pragma mark - 1322 1323 1324 void 1325 MainWin::_ToggleNoBorderNoMenu() 1326 { 1327 if (!fNoMenu && !fNoBorder && !fNoControls) { 1328 PostMessage(M_TOGGLE_NO_MENU); 1329 PostMessage(M_TOGGLE_NO_BORDER); 1330 PostMessage(M_TOGGLE_NO_CONTROLS); 1331 } else { 1332 if (!fNoMenu) 1333 PostMessage(M_TOGGLE_NO_MENU); 1334 if (!fNoBorder) 1335 PostMessage(M_TOGGLE_NO_BORDER); 1336 if (!fNoControls) 1337 PostMessage(M_TOGGLE_NO_CONTROLS); 1338 } 1339 } 1340 1341 1342 void 1343 MainWin::_ToggleFullscreen() 1344 { 1345 printf("_ToggleFullscreen enter\n"); 1346 1347 if (!fHasVideo) { 1348 printf("_ToggleFullscreen - ignoring, as we don't have a video\n"); 1349 return; 1350 } 1351 1352 fIsFullscreen = !fIsFullscreen; 1353 1354 if (fIsFullscreen) { 1355 // switch to fullscreen 1356 1357 fSavedFrame = Frame(); 1358 printf("saving current frame: %d %d %d %d\n", int(fSavedFrame.left), 1359 int(fSavedFrame.top), int(fSavedFrame.right), 1360 int(fSavedFrame.bottom)); 1361 BScreen screen(this); 1362 BRect rect(screen.Frame()); 1363 1364 Hide(); 1365 MoveTo(rect.left, rect.top); 1366 ResizeTo(rect.Width(), rect.Height()); 1367 Show(); 1368 1369 } else { 1370 // switch back from full screen mode 1371 1372 Hide(); 1373 MoveTo(fSavedFrame.left, fSavedFrame.top); 1374 ResizeTo(fSavedFrame.Width(), fSavedFrame.Height()); 1375 Show(); 1376 } 1377 1378 _MarkSettingsItem(M_TOGGLE_FULLSCREEN, fIsFullscreen); 1379 1380 printf("_ToggleFullscreen leave\n"); 1381 } 1382 1383 void 1384 MainWin::_ToggleNoControls() 1385 { 1386 printf("_ToggleNoControls enter\n"); 1387 1388 if (fIsFullscreen) { 1389 // fullscreen is always without menu 1390 printf("_ToggleNoControls leave, doing nothing, we are fullscreen\n"); 1391 return; 1392 } 1393 1394 fNoControls = !fNoControls; 1395 _SetWindowSizeLimits(); 1396 1397 if (fNoControls) { 1398 ResizeBy(0, - fControlsHeight); 1399 } else { 1400 ResizeBy(0, fControlsHeight); 1401 } 1402 1403 _MarkSettingsItem(M_TOGGLE_NO_CONTROLS, fNoControls); 1404 1405 printf("_ToggleNoControls leave\n"); 1406 } 1407 1408 void 1409 MainWin::_ToggleNoMenu() 1410 { 1411 printf("_ToggleNoMenu enter\n"); 1412 1413 if (fIsFullscreen) { 1414 // fullscreen is always without menu 1415 printf("_ToggleNoMenu leave, doing nothing, we are fullscreen\n"); 1416 return; 1417 } 1418 1419 fNoMenu = !fNoMenu; 1420 _SetWindowSizeLimits(); 1421 1422 if (fNoMenu) { 1423 MoveBy(0, fMenuBarHeight); 1424 ResizeBy(0, - fMenuBarHeight); 1425 } else { 1426 MoveBy(0, - fMenuBarHeight); 1427 ResizeBy(0, fMenuBarHeight); 1428 } 1429 1430 _MarkSettingsItem(M_TOGGLE_NO_MENU, fNoMenu); 1431 1432 printf("_ToggleNoMenu leave\n"); 1433 } 1434 1435 1436 void 1437 MainWin::_ToggleNoBorder() 1438 { 1439 fNoBorder = !fNoBorder; 1440 SetLook(fNoBorder ? B_BORDERED_WINDOW_LOOK : B_TITLED_WINDOW_LOOK); 1441 1442 _MarkSettingsItem(M_TOGGLE_NO_BORDER, fNoBorder); 1443 } 1444 1445 1446 void 1447 MainWin::_ToggleAlwaysOnTop() 1448 { 1449 fAlwaysOnTop = !fAlwaysOnTop; 1450 SetFeel(fAlwaysOnTop ? B_FLOATING_ALL_WINDOW_FEEL : B_NORMAL_WINDOW_FEEL); 1451 1452 _MarkSettingsItem(M_TOGGLE_ALWAYS_ON_TOP, fAlwaysOnTop); 1453 } 1454 1455 1456 void 1457 MainWin::_ToggleKeepAspectRatio() 1458 { 1459 fKeepAspectRatio = !fKeepAspectRatio; 1460 FrameResized(Bounds().Width(), Bounds().Height()); 1461 1462 _MarkSettingsItem(M_TOGGLE_KEEP_ASPECT_RATIO, fKeepAspectRatio); 1463 } 1464 1465 1466 // #pragma mark - 1467 1468 1469 void 1470 MainWin::_UpdateControlsEnabledStatus() 1471 { 1472 uint32 enabledButtons = 0; 1473 if (fHasVideo || fHasAudio) { 1474 enabledButtons |= PLAYBACK_ENABLED | SEEK_ENABLED 1475 | SEEK_BACK_ENABLED | SEEK_FORWARD_ENABLED; 1476 } 1477 if (fHasAudio) 1478 enabledButtons |= VOLUME_ENABLED; 1479 1480 bool canSkipPrevious, canSkipNext; 1481 fPlaylist->GetSkipInfo(&canSkipPrevious, &canSkipNext); 1482 if (canSkipPrevious) 1483 enabledButtons |= SKIP_BACK_ENABLED; 1484 if (canSkipNext) 1485 enabledButtons |= SKIP_FORWARD_ENABLED; 1486 1487 fControls->SetEnabled(enabledButtons); 1488 } 1489 1490 1491 void 1492 MainWin::_UpdatePlaylistMenu() 1493 { 1494 if (!fPlaylist->Lock()) 1495 return; 1496 1497 fPlaylistMenu->RemoveItems(0, fPlaylistMenu->CountItems(), true); 1498 1499 int32 count = fPlaylist->CountItems(); 1500 for (int32 i = 0; i < count; i++) { 1501 entry_ref ref; 1502 if (fPlaylist->GetRefAt(i, &ref) < B_OK) 1503 continue; 1504 _AddPlaylistItem(ref, i); 1505 } 1506 fPlaylistMenu->SetTargetForItems(this); 1507 1508 _MarkPlaylistItem(fPlaylist->CurrentRefIndex()); 1509 1510 fPlaylist->Unlock(); 1511 } 1512 1513 1514 void 1515 MainWin::_AddPlaylistItem(const entry_ref& ref, int32 index) 1516 { 1517 BMessage* message = new BMessage(M_SET_PLAYLIST_POSITION); 1518 message->AddInt32("index", index); 1519 BMenuItem* item = new BMenuItem(ref.name, message); 1520 fPlaylistMenu->AddItem(item, index); 1521 } 1522 1523 1524 void 1525 MainWin::_RemovePlaylistItem(int32 index) 1526 { 1527 delete fPlaylistMenu->RemoveItem(index); 1528 } 1529 1530 1531 void 1532 MainWin::_MarkPlaylistItem(int32 index) 1533 { 1534 if (BMenuItem* item = fPlaylistMenu->ItemAt(index)) { 1535 item->SetMarked(true); 1536 // ... and in case the menu is currently on screen: 1537 if (fPlaylistMenu->LockLooper()) { 1538 fPlaylistMenu->Invalidate(); 1539 fPlaylistMenu->UnlockLooper(); 1540 } 1541 } 1542 } 1543 1544 1545 void 1546 MainWin::_MarkSettingsItem(uint32 command, bool mark) 1547 { 1548 if (BMenuItem* item = fSettingsMenu->FindItem(command)) 1549 item->SetMarked(mark); 1550 } 1551 1552 1553