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