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