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