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