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 void 660 MainWin::WindowActivated(bool active) 661 { 662 if (active) { 663 BScreen screen; 664 BRect screenFrame = screen.Frame(); 665 BRect frame = Frame(); 666 float diffX = 0.0; 667 float diffY = 0.0; 668 669 // If the frame if off the edge of the screen at all 670 // we will move it so all the window is on the screen. 671 if (frame.left < screenFrame.left) 672 // Move right 673 diffX = screenFrame.left - frame.left; 674 if (frame.top < screenFrame.top) 675 // Move down 676 diffY = screenFrame.top - frame.top; 677 if (frame.right > screenFrame.right) 678 // Move left 679 diffX = screenFrame.right - frame.right; 680 if (frame.bottom > screenFrame.bottom) 681 // Move up 682 diffY = screenFrame.bottom - frame.bottom; 683 684 MoveBy(diffX, diffY); 685 } 686 } 687 688 689 bool 690 MainWin::QuitRequested() 691 { 692 be_app->PostMessage(M_PLAYER_QUIT); 693 return true; 694 } 695 696 697 // #pragma mark - 698 699 700 void 701 MainWin::OpenFile(const entry_ref &ref) 702 { 703 printf("MainWin::OpenFile\n"); 704 705 status_t err = fController->SetTo(ref); 706 if (err != B_OK) { 707 if (fPlaylist->CountItems() == 1) { 708 // display error if this is the only file we're supposed to play 709 char s[300]; 710 sprintf(s, "Can't open file\n\n%s\n\nError 0x%08lx\n(%s)\n", 711 ref.name, err, strerror(err)); 712 (new BAlert("error", s, "OK"))->Go(); 713 } else { 714 // just go to the next file and don't bother user 715 fPlaylist->SetCurrentRefIndex(fPlaylist->CurrentRefIndex() + 1); 716 } 717 fHasFile = false; 718 fHasVideo = false; 719 fHasAudio = false; 720 SetTitle(NAME); 721 } else { 722 fHasFile = true; 723 fHasVideo = fController->VideoTrackCount() != 0; 724 fHasAudio = fController->AudioTrackCount() != 0; 725 SetTitle(ref.name); 726 } 727 _SetupWindow(); 728 } 729 730 731 void 732 MainWin::ShowFileInfo() 733 { 734 if (!fInfoWin) 735 fInfoWin = new InfoWin(Frame().LeftTop(), fController); 736 737 if (fInfoWin->Lock()) { 738 if (fInfoWin->IsHidden()) 739 fInfoWin->Show(); 740 else 741 fInfoWin->Activate(); 742 fInfoWin->Unlock(); 743 } 744 } 745 746 747 void 748 MainWin::ShowPlaylistWindow() 749 { 750 if (fPlaylistWindow->Lock()) { 751 if (fPlaylistWindow->IsHidden()) 752 fPlaylistWindow->Show(); 753 else 754 fPlaylistWindow->Activate(); 755 fPlaylistWindow->Unlock(); 756 } 757 } 758 759 760 void 761 MainWin::ShowSettingsWindow() 762 { 763 if (fSettingsWindow->Lock()) { 764 if (fSettingsWindow->IsHidden()) 765 fSettingsWindow->Show(); 766 else 767 fSettingsWindow->Activate(); 768 fSettingsWindow->Unlock(); 769 } 770 } 771 772 773 void 774 MainWin::VideoFormatChange(int width, int height, float width_scale, 775 float height_scale) 776 { 777 // called when video format or aspect ratio changes 778 779 printf("VideoFormatChange enter: width %d, height %d, width_scale %.6f, " 780 "height_scale %.6f\n", width, height, width_scale, height_scale); 781 782 if (width_scale < 1.0 && height_scale >= 1.0) { 783 width_scale = 1.0 / width_scale; 784 height_scale = 1.0 / height_scale; 785 printf("inverting! new values: width_scale %.6f, height_scale %.6f\n", 786 width_scale, height_scale); 787 } 788 789 fSourceWidth = width; 790 fSourceHeight = height; 791 fWidthScale = width_scale; 792 fHeightScale = height_scale; 793 794 FrameResized(Bounds().Width(), Bounds().Height()); 795 796 printf("VideoFormatChange leave\n"); 797 } 798 799 800 // #pragma mark - 801 802 803 void 804 MainWin::_RefsReceived(BMessage* msg) 805 { 806 // the playlist ist replaced by dropped files 807 // or the dropped files are appended to the end 808 // of the existing playlist if <shift> is pressed 809 int32 appendIndex = modifiers() & B_SHIFT_KEY ? 810 fPlaylist->CountItems() : -1; 811 msg->AddInt32("append_index", appendIndex); 812 813 // forward the message to the playlist window, 814 // so that undo/redo is used for modifying the playlist 815 fPlaylistWindow->PostMessage(msg); 816 } 817 818 819 void 820 MainWin::_SetupWindow() 821 { 822 printf("MainWin::_SetupWindow\n"); 823 // Populate the track menus 824 _SetupTrackMenus(); 825 // Enable both if a file was loaded 826 fAudioTrackMenu->SetEnabled(fHasFile); 827 fVideoTrackMenu->SetEnabled(fHasFile); 828 // Select first track (might be "none") in both 829 fAudioTrackMenu->ItemAt(0)->SetMarked(true); 830 fVideoTrackMenu->ItemAt(0)->SetMarked(true); 831 832 fVideoMenu->SetEnabled(fHasVideo); 833 fAudioMenu->SetEnabled(fHasAudio); 834 // fDebugMenu->SetEnabled(fHasVideo); 835 if (fHasVideo) { 836 fController->GetSize(&fSourceWidth, &fSourceHeight); 837 fWidthScale = 1.0; 838 fHeightScale = 1.0; 839 } else { 840 fSourceWidth = 0; 841 fSourceHeight = 0; 842 fWidthScale = 1.0; 843 fHeightScale = 1.0; 844 } 845 _UpdateControlsEnabledStatus(); 846 847 _ResizeWindow(100); 848 849 fVideoView->MakeFocus(); 850 } 851 852 853 void 854 MainWin::_CreateMenu() 855 { 856 fFileMenu = new BMenu(NAME); 857 fPlaylistMenu = new BMenu("Playlist"B_UTF8_ELLIPSIS); 858 fAudioMenu = new BMenu("Audio"); 859 fVideoMenu = new BMenu("Video"); 860 fSettingsMenu = new BMenu("Settings"); 861 fAudioTrackMenu = new BMenu("Track"); 862 fVideoTrackMenu = new BMenu("Track"); 863 // fDebugMenu = new BMenu("Debug"); 864 865 fMenuBar->AddItem(fFileMenu); 866 fMenuBar->AddItem(fAudioMenu); 867 fMenuBar->AddItem(fVideoMenu); 868 fMenuBar->AddItem(fSettingsMenu); 869 // fMenuBar->AddItem(fDebugMenu); 870 871 fFileMenu->AddItem(new BMenuItem("New Player"B_UTF8_ELLIPSIS, 872 new BMessage(M_FILE_NEWPLAYER), 'N')); 873 fFileMenu->AddSeparatorItem(); 874 875 // fFileMenu->AddItem(new BMenuItem("Open File"B_UTF8_ELLIPSIS, 876 // new BMessage(M_FILE_OPEN), 'O')); 877 // Add recent files 878 BRecentFilesList recentFiles(10, false, NULL, kAppSig); 879 BMenuItem *item = new BMenuItem(recentFiles.NewFileListMenu( 880 "Open File"B_UTF8_ELLIPSIS, new BMessage(B_REFS_RECEIVED), 881 NULL, this, 10, false, NULL, 0, kAppSig), new BMessage(M_FILE_OPEN)); 882 item->SetShortcut('O', 0); 883 fFileMenu->AddItem(item); 884 885 fFileMenu->AddItem(new BMenuItem("File Info"B_UTF8_ELLIPSIS, 886 new BMessage(M_FILE_INFO), 'I')); 887 fFileMenu->AddItem(fPlaylistMenu); 888 fPlaylistMenu->Superitem()->SetShortcut('P', B_COMMAND_KEY); 889 fPlaylistMenu->Superitem()->SetMessage(new BMessage(M_FILE_PLAYLIST)); 890 891 fFileMenu->AddSeparatorItem(); 892 fFileMenu->AddItem(new BMenuItem("About" NAME B_UTF8_ELLIPSIS, 893 new BMessage(B_ABOUT_REQUESTED))); 894 fFileMenu->AddSeparatorItem(); 895 fFileMenu->AddItem(new BMenuItem("Close", new BMessage(M_FILE_CLOSE), 'W')); 896 fFileMenu->AddItem(new BMenuItem("Quit", new BMessage(M_FILE_QUIT), 'Q')); 897 898 fPlaylistMenu->SetRadioMode(true); 899 900 fAudioMenu->AddItem(fAudioTrackMenu); 901 902 fVideoMenu->AddItem(fVideoTrackMenu); 903 fVideoMenu->AddSeparatorItem(); 904 fVideoMenu->AddItem(new BMenuItem("50% scale", 905 new BMessage(M_VIEW_50), '0')); 906 fVideoMenu->AddItem(new BMenuItem("100% scale", 907 new BMessage(M_VIEW_100), '1')); 908 fVideoMenu->AddItem(new BMenuItem("200% scale", 909 new BMessage(M_VIEW_200), '2')); 910 fVideoMenu->AddItem(new BMenuItem("300% scale", 911 new BMessage(M_VIEW_300), '3')); 912 fVideoMenu->AddItem(new BMenuItem("400% scale", 913 new BMessage(M_VIEW_400), '4')); 914 fVideoMenu->AddSeparatorItem(); 915 fVideoMenu->AddItem(new BMenuItem("Full Screen", 916 new BMessage(M_TOGGLE_FULLSCREEN), 'F')); 917 fVideoMenu->AddItem(new BMenuItem("Keep Aspect Ratio", 918 new BMessage(M_TOGGLE_KEEP_ASPECT_RATIO), 'K')); 919 920 fSettingsMenu->AddItem(new BMenuItem("No Menu", 921 new BMessage(M_TOGGLE_NO_MENU), 'M')); 922 fSettingsMenu->AddItem(new BMenuItem("No Border", 923 new BMessage(M_TOGGLE_NO_BORDER), 'B')); 924 fSettingsMenu->AddItem(new BMenuItem("No Controls", 925 new BMessage(M_TOGGLE_NO_CONTROLS), 'C')); 926 fSettingsMenu->AddItem(new BMenuItem("Always on Top", 927 new BMessage(M_TOGGLE_ALWAYS_ON_TOP), 'T')); 928 // fSettingsMenu->AddSeparatorItem(); 929 // fSettingsMenu->AddItem(new BMenuItem("Settings"B_UTF8_ELLIPSIS, 930 // new BMessage(M_SETTINGS), 'S')); 931 932 // fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.00000:1", 933 // new BMessage(M_ASPECT_100000_1))); 934 // fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.06666:1", 935 // new BMessage(M_ASPECT_106666_1))); 936 // fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.09091:1", 937 // new BMessage(M_ASPECT_109091_1))); 938 // fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.41176:1", 939 // new BMessage(M_ASPECT_141176_1))); 940 // fDebugMenu->AddItem(new BMenuItem("force 720 x 576, display aspect 4:3", 941 // new BMessage(M_ASPECT_720_576))); 942 // fDebugMenu->AddItem(new BMenuItem("force 704 x 576, display aspect 4:3", 943 // new BMessage(M_ASPECT_704_576))); 944 // fDebugMenu->AddItem(new BMenuItem("force 544 x 576, display aspect 4:3", 945 // new BMessage(M_ASPECT_544_576))); 946 947 fAudioTrackMenu->SetRadioMode(true); 948 fVideoTrackMenu->SetRadioMode(true); 949 } 950 951 952 void 953 MainWin::_SetupTrackMenus() 954 { 955 fAudioTrackMenu->RemoveItems(0, fAudioTrackMenu->CountItems(), true); 956 fVideoTrackMenu->RemoveItems(0, fVideoTrackMenu->CountItems(), true); 957 958 int c, i; 959 char s[100]; 960 961 c = fController->AudioTrackCount(); 962 for (i = 0; i < c; i++) { 963 sprintf(s, "Track %d", i + 1); 964 fAudioTrackMenu->AddItem(new BMenuItem(s, 965 new BMessage(M_SELECT_AUDIO_TRACK + i))); 966 } 967 if (!c) 968 fAudioTrackMenu->AddItem(new BMenuItem("none", new BMessage(M_DUMMY))); 969 970 c = fController->VideoTrackCount(); 971 for (i = 0; i < c; i++) { 972 sprintf(s, "Track %d", i + 1); 973 fVideoTrackMenu->AddItem(new BMenuItem(s, 974 new BMessage(M_SELECT_VIDEO_TRACK + i))); 975 } 976 if (!c) 977 fVideoTrackMenu->AddItem(new BMenuItem("none", new BMessage(M_DUMMY))); 978 } 979 980 981 void 982 MainWin::_SetWindowSizeLimits() 983 { 984 int minWidth = fNoControls ? MIN_WIDTH : fControlsWidth; 985 if (!fNoMenu) 986 minWidth = max_c(minWidth, fMenuBarWidth); 987 int minHeight = (fNoMenu ? 0 : fMenuBarHeight) 988 + (fNoControls ? 0 : fControlsHeight); 989 990 SetSizeLimits(minWidth - 1, 32000, minHeight - 1, fHasVideo ? 991 32000 : minHeight - 1); 992 } 993 994 995 void 996 MainWin::_ResizeWindow(int percent) 997 { 998 int video_width; 999 int video_height; 1000 1001 // Get required window size 1002 video_width = lround(fSourceWidth * fWidthScale); 1003 video_height = lround(fSourceHeight * fHeightScale); 1004 1005 video_width = (video_width * percent) / 100; 1006 video_height = (video_height * percent) / 100; 1007 1008 // Calculate and set the initial window size 1009 int width = max_c(fControlsWidth, video_width); 1010 int height = (fNoControls ? 0 : fControlsHeight) + video_height; 1011 if (!fNoMenu) { 1012 width = max_c(width, fMenuBarWidth); 1013 height += fMenuBarHeight; 1014 } 1015 _SetWindowSizeLimits(); 1016 ResizeTo(width - 1, height - 1); 1017 } 1018 1019 1020 void 1021 MainWin::_ResizeVideoView(int x, int y, int width, int height) 1022 { 1023 printf("_ResizeVideoView: %d,%d, width %d, height %d\n", x, y, 1024 width, height); 1025 1026 if (fKeepAspectRatio) { 1027 // Keep aspect ratio, place video view inside 1028 // the background area (may create black bars). 1029 float scaled_width = fSourceWidth * fWidthScale; 1030 float scaled_height = fSourceHeight * fHeightScale; 1031 float factor = min_c(width / scaled_width, height / scaled_height); 1032 int render_width = lround(scaled_width * factor); 1033 int render_height = lround(scaled_height * factor); 1034 if (render_width > width) 1035 render_width = width; 1036 if (render_height > height) 1037 render_height = height; 1038 1039 int x_ofs = x + (width - render_width) / 2; 1040 int y_ofs = y + (height - render_height) / 2; 1041 1042 fVideoView->MoveTo(x_ofs, y_ofs); 1043 fVideoView->ResizeTo(render_width - 1, render_height - 1); 1044 1045 } else { 1046 fVideoView->MoveTo(x, y); 1047 fVideoView->ResizeTo(width - 1, height - 1); 1048 } 1049 } 1050 1051 1052 // #pragma mark - 1053 1054 1055 void 1056 MainWin::_MouseDown(BMessage *msg, BView* originalHandler) 1057 { 1058 BPoint screen_where; 1059 uint32 buttons = msg->FindInt32("buttons"); 1060 1061 // On Zeta, only "screen_where" is relyable, "where" and "be:view_where" 1062 // seem to be broken 1063 if (B_OK != msg->FindPoint("screen_where", &screen_where)) { 1064 // Workaround for BeOS R5, it has no "screen_where" 1065 if (!originalHandler || msg->FindPoint("where", &screen_where) < B_OK) 1066 return; 1067 originalHandler->ConvertToScreen(&screen_where); 1068 } 1069 1070 // msg->PrintToStream(); 1071 1072 // if (1 == msg->FindInt32("buttons") && msg->FindInt32("clicks") == 1) { 1073 1074 if (1 == buttons && msg->FindInt32("clicks") % 2 == 0) { 1075 BRect r(screen_where.x - 1, screen_where.y - 1, screen_where.x + 1, 1076 screen_where.y + 1); 1077 if (r.Contains(fMouseDownMousePos)) { 1078 PostMessage(M_TOGGLE_FULLSCREEN); 1079 return; 1080 } 1081 } 1082 1083 if (2 == buttons && msg->FindInt32("clicks") % 2 == 0) { 1084 BRect r(screen_where.x - 1, screen_where.y - 1, screen_where.x + 1, 1085 screen_where.y + 1); 1086 if (r.Contains(fMouseDownMousePos)) { 1087 PostMessage(M_TOGGLE_NO_BORDER_NO_MENU_NO_CONTROLS); 1088 return; 1089 } 1090 } 1091 1092 /* 1093 // very broken in Zeta: 1094 fMouseDownMousePos = fVideoView->ConvertToScreen( 1095 msg->FindPoint("where")); 1096 */ 1097 fMouseDownMousePos = screen_where; 1098 fMouseDownWindowPos = Frame().LeftTop(); 1099 1100 if (buttons == 1 && !fIsFullscreen) { 1101 // start mouse tracking 1102 fVideoView->SetMouseEventMask(B_POINTER_EVENTS | B_NO_POINTER_HISTORY 1103 /* | B_LOCK_WINDOW_FOCUS */); 1104 fMouseDownTracking = true; 1105 } 1106 1107 // pop up a context menu if right mouse button is down for 200 ms 1108 1109 if ((buttons & 2) == 0) 1110 return; 1111 bigtime_t start = system_time(); 1112 bigtime_t delay = 200000; 1113 BPoint location; 1114 do { 1115 fVideoView->GetMouse(&location, &buttons); 1116 if ((buttons & 2) == 0) 1117 break; 1118 snooze(1000); 1119 } while (system_time() - start < delay); 1120 1121 if (buttons & 2) 1122 _ShowContextMenu(screen_where); 1123 } 1124 1125 1126 void 1127 MainWin::_MouseMoved(BMessage *msg, BView* originalHandler) 1128 { 1129 // msg->PrintToStream(); 1130 1131 BPoint mousePos; 1132 uint32 buttons = msg->FindInt32("buttons"); 1133 1134 if (1 == buttons && fMouseDownTracking && !fIsFullscreen) { 1135 /* 1136 // very broken in Zeta: 1137 BPoint mousePos = msg->FindPoint("where"); 1138 printf("view where: %.0f, %.0f => ", mousePos.x, mousePos.y); 1139 fVideoView->ConvertToScreen(&mousePos); 1140 */ 1141 // On Zeta, only "screen_where" is relyable, "where" 1142 // and "be:view_where" seem to be broken 1143 if (B_OK != msg->FindPoint("screen_where", &mousePos)) { 1144 // Workaround for BeOS R5, it has no "screen_where" 1145 if (!originalHandler || msg->FindPoint("where", &mousePos) < B_OK) 1146 return; 1147 originalHandler->ConvertToScreen(&mousePos); 1148 } 1149 // printf("screen where: %.0f, %.0f => ", mousePos.x, mousePos.y); 1150 float delta_x = mousePos.x - fMouseDownMousePos.x; 1151 float delta_y = mousePos.y - fMouseDownMousePos.y; 1152 float x = fMouseDownWindowPos.x + delta_x; 1153 float y = fMouseDownWindowPos.y + delta_y; 1154 // printf("move window to %.0f, %.0f\n", x, y); 1155 MoveTo(x, y); 1156 } 1157 } 1158 1159 1160 void 1161 MainWin::_MouseUp(BMessage *msg) 1162 { 1163 // msg->PrintToStream(); 1164 fMouseDownTracking = false; 1165 } 1166 1167 1168 void 1169 MainWin::_ShowContextMenu(const BPoint &screen_point) 1170 { 1171 printf("Show context menu\n"); 1172 BPopUpMenu *menu = new BPopUpMenu("context menu", false, false); 1173 BMenuItem *item; 1174 menu->AddItem(item = new BMenuItem("Full Screen", 1175 new BMessage(M_TOGGLE_FULLSCREEN), 'F')); 1176 item->SetMarked(fIsFullscreen); 1177 item->SetEnabled(fHasVideo); 1178 menu->AddItem(item = new BMenuItem("Keep Aspect Ratio", 1179 new BMessage(M_TOGGLE_KEEP_ASPECT_RATIO), 'K')); 1180 item->SetMarked(fKeepAspectRatio); 1181 item->SetEnabled(fHasVideo); 1182 1183 menu->AddSeparatorItem(); 1184 menu->AddItem(item = new BMenuItem("No Menu", 1185 new BMessage(M_TOGGLE_NO_MENU), 'M')); 1186 item->SetMarked(fNoMenu); 1187 menu->AddItem(item = new BMenuItem("No Border", 1188 new BMessage(M_TOGGLE_NO_BORDER), 'B')); 1189 item->SetMarked(fNoBorder); 1190 menu->AddItem(item = new BMenuItem("Always on Top", 1191 new BMessage(M_TOGGLE_ALWAYS_ON_TOP), 'T')); 1192 item->SetMarked(fAlwaysOnTop); 1193 1194 menu->AddSeparatorItem(); 1195 menu->AddItem(new BMenuItem("About" NAME B_UTF8_ELLIPSIS, 1196 new BMessage(B_ABOUT_REQUESTED))); 1197 menu->AddSeparatorItem(); 1198 menu->AddItem(new BMenuItem("Quit", new BMessage(M_FILE_QUIT), 'Q')); 1199 1200 menu->AddSeparatorItem(); 1201 menu->AddItem(new BMenuItem("pixel aspect ratio 1.00000:1", 1202 new BMessage(M_ASPECT_100000_1))); 1203 menu->AddItem(new BMenuItem("pixel aspect ratio 1.06666:1", 1204 new BMessage(M_ASPECT_106666_1))); 1205 menu->AddItem(new BMenuItem("pixel aspect ratio 1.09091:1", 1206 new BMessage(M_ASPECT_109091_1))); 1207 menu->AddItem(new BMenuItem("pixel aspect ratio 1.41176:1", 1208 new BMessage(M_ASPECT_141176_1))); 1209 menu->AddItem(new BMenuItem("force 720 x 576, display aspect 4:3", 1210 new BMessage(M_ASPECT_720_576))); 1211 menu->AddItem(new BMenuItem("force 704 x 576, display aspect 4:3", 1212 new BMessage(M_ASPECT_704_576))); 1213 menu->AddItem(new BMenuItem("force 544 x 576, display aspect 4:3", 1214 new BMessage(M_ASPECT_544_576))); 1215 1216 menu->SetTargetForItems(this); 1217 BRect r(screen_point.x - 5, screen_point.y - 5, screen_point.x + 5, 1218 screen_point.y + 5); 1219 menu->Go(screen_point, true, true, r, true); 1220 } 1221 1222 1223 /* Trap keys that are about to be send to background or renderer view. 1224 * Return B_OK if it shouldn't be passed to the view 1225 */ 1226 status_t 1227 MainWin::_KeyDown(BMessage *msg) 1228 { 1229 // msg->PrintToStream(); 1230 1231 uint32 key = msg->FindInt32("key"); 1232 uint32 raw_char = msg->FindInt32("raw_char"); 1233 uint32 modifiers = msg->FindInt32("modifiers"); 1234 1235 printf("key 0x%lx, raw_char 0x%lx, modifiers 0x%lx\n", key, raw_char, 1236 modifiers); 1237 1238 switch (raw_char) { 1239 case B_SPACE: 1240 if (fController->IsPaused() || fController->IsStopped()) 1241 fController->Play(); 1242 else 1243 fController->Pause(); 1244 return B_OK; 1245 1246 case B_ESCAPE: 1247 if (fIsFullscreen) { 1248 PostMessage(M_TOGGLE_FULLSCREEN); 1249 return B_OK; 1250 } else 1251 break; 1252 1253 case B_ENTER: // Enter / Return 1254 if (modifiers & B_COMMAND_KEY) { 1255 PostMessage(M_TOGGLE_FULLSCREEN); 1256 return B_OK; 1257 } else 1258 break; 1259 1260 case B_TAB: 1261 if ((modifiers & (B_COMMAND_KEY | B_CONTROL_KEY | B_OPTION_KEY 1262 | B_MENU_KEY)) == 0) { 1263 PostMessage(M_TOGGLE_FULLSCREEN); 1264 return B_OK; 1265 } else 1266 break; 1267 1268 case B_UP_ARROW: 1269 if (modifiers & B_COMMAND_KEY) { 1270 PostMessage(M_SKIP_NEXT); 1271 } else { 1272 PostMessage(M_VOLUME_UP); 1273 } 1274 return B_OK; 1275 1276 case B_DOWN_ARROW: 1277 if (modifiers & B_COMMAND_KEY) { 1278 PostMessage(M_SKIP_PREV); 1279 } else { 1280 PostMessage(M_VOLUME_DOWN); 1281 } 1282 return B_OK; 1283 1284 case B_RIGHT_ARROW: 1285 if (modifiers & B_COMMAND_KEY) { 1286 PostMessage(M_VOLUME_UP); 1287 } else { 1288 PostMessage(M_SKIP_NEXT); 1289 } 1290 return B_OK; 1291 1292 case B_LEFT_ARROW: 1293 if (modifiers & B_COMMAND_KEY) { 1294 PostMessage(M_VOLUME_DOWN); 1295 } else { 1296 PostMessage(M_SKIP_PREV); 1297 } 1298 return B_OK; 1299 1300 case B_PAGE_UP: 1301 PostMessage(M_SKIP_NEXT); 1302 return B_OK; 1303 1304 case B_PAGE_DOWN: 1305 PostMessage(M_SKIP_PREV); 1306 return B_OK; 1307 } 1308 1309 switch (key) { 1310 case 0x3a: // numeric keypad + 1311 if ((modifiers & B_COMMAND_KEY) == 0) { 1312 printf("if\n"); 1313 PostMessage(M_VOLUME_UP); 1314 return B_OK; 1315 } else { 1316 printf("else\n"); 1317 break; 1318 } 1319 1320 case 0x25: // numeric keypad - 1321 if ((modifiers & B_COMMAND_KEY) == 0) { 1322 PostMessage(M_VOLUME_DOWN); 1323 return B_OK; 1324 } else { 1325 break; 1326 } 1327 1328 case 0x38: // numeric keypad up arrow 1329 PostMessage(M_VOLUME_UP); 1330 return B_OK; 1331 1332 case 0x59: // numeric keypad down arrow 1333 PostMessage(M_VOLUME_DOWN); 1334 return B_OK; 1335 1336 case 0x39: // numeric keypad page up 1337 case 0x4a: // numeric keypad right arrow 1338 PostMessage(M_SKIP_NEXT); 1339 return B_OK; 1340 1341 case 0x5a: // numeric keypad page down 1342 case 0x48: // numeric keypad left arrow 1343 PostMessage(M_SKIP_PREV); 1344 return B_OK; 1345 } 1346 1347 return B_ERROR; 1348 } 1349 1350 1351 // #pragma mark - 1352 1353 1354 void 1355 MainWin::_ToggleNoBorderNoMenu() 1356 { 1357 if (!fNoMenu && !fNoBorder && !fNoControls) { 1358 PostMessage(M_TOGGLE_NO_MENU); 1359 PostMessage(M_TOGGLE_NO_BORDER); 1360 PostMessage(M_TOGGLE_NO_CONTROLS); 1361 } else { 1362 if (!fNoMenu) 1363 PostMessage(M_TOGGLE_NO_MENU); 1364 if (!fNoBorder) 1365 PostMessage(M_TOGGLE_NO_BORDER); 1366 if (!fNoControls) 1367 PostMessage(M_TOGGLE_NO_CONTROLS); 1368 } 1369 } 1370 1371 1372 void 1373 MainWin::_ToggleFullscreen() 1374 { 1375 printf("_ToggleFullscreen enter\n"); 1376 1377 if (!fHasVideo) { 1378 printf("_ToggleFullscreen - ignoring, as we don't have a video\n"); 1379 return; 1380 } 1381 1382 fIsFullscreen = !fIsFullscreen; 1383 1384 if (fIsFullscreen) { 1385 // switch to fullscreen 1386 1387 fSavedFrame = Frame(); 1388 printf("saving current frame: %d %d %d %d\n", int(fSavedFrame.left), 1389 int(fSavedFrame.top), int(fSavedFrame.right), 1390 int(fSavedFrame.bottom)); 1391 BScreen screen(this); 1392 BRect rect(screen.Frame()); 1393 1394 Hide(); 1395 MoveTo(rect.left, rect.top); 1396 ResizeTo(rect.Width(), rect.Height()); 1397 Show(); 1398 1399 } else { 1400 // switch back from full screen mode 1401 1402 Hide(); 1403 MoveTo(fSavedFrame.left, fSavedFrame.top); 1404 ResizeTo(fSavedFrame.Width(), fSavedFrame.Height()); 1405 Show(); 1406 } 1407 1408 _MarkSettingsItem(M_TOGGLE_FULLSCREEN, fIsFullscreen); 1409 1410 printf("_ToggleFullscreen leave\n"); 1411 } 1412 1413 void 1414 MainWin::_ToggleNoControls() 1415 { 1416 printf("_ToggleNoControls enter\n"); 1417 1418 if (fIsFullscreen) { 1419 // fullscreen is always without menu 1420 printf("_ToggleNoControls leave, doing nothing, we are fullscreen\n"); 1421 return; 1422 } 1423 1424 fNoControls = !fNoControls; 1425 _SetWindowSizeLimits(); 1426 1427 if (fNoControls) { 1428 ResizeBy(0, - fControlsHeight); 1429 } else { 1430 ResizeBy(0, fControlsHeight); 1431 } 1432 1433 _MarkSettingsItem(M_TOGGLE_NO_CONTROLS, fNoControls); 1434 1435 printf("_ToggleNoControls leave\n"); 1436 } 1437 1438 void 1439 MainWin::_ToggleNoMenu() 1440 { 1441 printf("_ToggleNoMenu enter\n"); 1442 1443 if (fIsFullscreen) { 1444 // fullscreen is always without menu 1445 printf("_ToggleNoMenu leave, doing nothing, we are fullscreen\n"); 1446 return; 1447 } 1448 1449 fNoMenu = !fNoMenu; 1450 _SetWindowSizeLimits(); 1451 1452 if (fNoMenu) { 1453 MoveBy(0, fMenuBarHeight); 1454 ResizeBy(0, - fMenuBarHeight); 1455 } else { 1456 MoveBy(0, - fMenuBarHeight); 1457 ResizeBy(0, fMenuBarHeight); 1458 } 1459 1460 _MarkSettingsItem(M_TOGGLE_NO_MENU, fNoMenu); 1461 1462 printf("_ToggleNoMenu leave\n"); 1463 } 1464 1465 1466 void 1467 MainWin::_ToggleNoBorder() 1468 { 1469 fNoBorder = !fNoBorder; 1470 SetLook(fNoBorder ? B_BORDERED_WINDOW_LOOK : B_TITLED_WINDOW_LOOK); 1471 1472 _MarkSettingsItem(M_TOGGLE_NO_BORDER, fNoBorder); 1473 } 1474 1475 1476 void 1477 MainWin::_ToggleAlwaysOnTop() 1478 { 1479 fAlwaysOnTop = !fAlwaysOnTop; 1480 SetFeel(fAlwaysOnTop ? B_FLOATING_ALL_WINDOW_FEEL : B_NORMAL_WINDOW_FEEL); 1481 1482 _MarkSettingsItem(M_TOGGLE_ALWAYS_ON_TOP, fAlwaysOnTop); 1483 } 1484 1485 1486 void 1487 MainWin::_ToggleKeepAspectRatio() 1488 { 1489 fKeepAspectRatio = !fKeepAspectRatio; 1490 FrameResized(Bounds().Width(), Bounds().Height()); 1491 1492 _MarkSettingsItem(M_TOGGLE_KEEP_ASPECT_RATIO, fKeepAspectRatio); 1493 } 1494 1495 1496 // #pragma mark - 1497 1498 1499 void 1500 MainWin::_UpdateControlsEnabledStatus() 1501 { 1502 uint32 enabledButtons = 0; 1503 if (fHasVideo || fHasAudio) { 1504 enabledButtons |= PLAYBACK_ENABLED | SEEK_ENABLED 1505 | SEEK_BACK_ENABLED | SEEK_FORWARD_ENABLED; 1506 } 1507 if (fHasAudio) 1508 enabledButtons |= VOLUME_ENABLED; 1509 1510 bool canSkipPrevious, canSkipNext; 1511 fPlaylist->GetSkipInfo(&canSkipPrevious, &canSkipNext); 1512 if (canSkipPrevious) 1513 enabledButtons |= SKIP_BACK_ENABLED; 1514 if (canSkipNext) 1515 enabledButtons |= SKIP_FORWARD_ENABLED; 1516 1517 fControls->SetEnabled(enabledButtons); 1518 } 1519 1520 1521 void 1522 MainWin::_UpdatePlaylistMenu() 1523 { 1524 if (!fPlaylist->Lock()) 1525 return; 1526 1527 fPlaylistMenu->RemoveItems(0, fPlaylistMenu->CountItems(), true); 1528 1529 int32 count = fPlaylist->CountItems(); 1530 for (int32 i = 0; i < count; i++) { 1531 entry_ref ref; 1532 if (fPlaylist->GetRefAt(i, &ref) < B_OK) 1533 continue; 1534 _AddPlaylistItem(ref, i); 1535 } 1536 fPlaylistMenu->SetTargetForItems(this); 1537 1538 _MarkPlaylistItem(fPlaylist->CurrentRefIndex()); 1539 1540 fPlaylist->Unlock(); 1541 } 1542 1543 1544 void 1545 MainWin::_AddPlaylistItem(const entry_ref& ref, int32 index) 1546 { 1547 BMessage* message = new BMessage(M_SET_PLAYLIST_POSITION); 1548 message->AddInt32("index", index); 1549 BMenuItem* item = new BMenuItem(ref.name, message); 1550 fPlaylistMenu->AddItem(item, index); 1551 } 1552 1553 1554 void 1555 MainWin::_RemovePlaylistItem(int32 index) 1556 { 1557 delete fPlaylistMenu->RemoveItem(index); 1558 } 1559 1560 1561 void 1562 MainWin::_MarkPlaylistItem(int32 index) 1563 { 1564 if (BMenuItem* item = fPlaylistMenu->ItemAt(index)) { 1565 item->SetMarked(true); 1566 // ... and in case the menu is currently on screen: 1567 if (fPlaylistMenu->LockLooper()) { 1568 fPlaylistMenu->Invalidate(); 1569 fPlaylistMenu->UnlockLooper(); 1570 } 1571 } 1572 } 1573 1574 1575 void 1576 MainWin::_MarkSettingsItem(uint32 command, bool mark) 1577 { 1578 if (BMenuItem* item = fSettingsMenu->FindItem(command)) 1579 item->SetMarked(mark); 1580 } 1581 1582 1583