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