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 685 686 void 687 MainWin::ShowPlaylistWindow() 688 { 689 if (fPlaylistWindow->Lock()) { 690 if (fPlaylistWindow->IsHidden()) 691 fPlaylistWindow->Show(); 692 else 693 fPlaylistWindow->Activate(); 694 fPlaylistWindow->Unlock(); 695 } 696 } 697 698 699 void 700 MainWin::VideoFormatChange(int width, int height, float width_scale, float height_scale) 701 { 702 // called when video format or aspect ratio changes 703 704 printf("VideoFormatChange enter: width %d, height %d, width_scale %.6f, height_scale %.6f\n", width, height, width_scale, height_scale); 705 706 if (width_scale < 1.0 && height_scale >= 1.0) { 707 width_scale = 1.0 / width_scale; 708 height_scale = 1.0 / height_scale; 709 printf("inverting! new values: width_scale %.6f, height_scale %.6f\n", width_scale, height_scale); 710 } 711 712 fSourceWidth = width; 713 fSourceHeight = height; 714 fWidthScale = width_scale; 715 fHeightScale = height_scale; 716 717 FrameResized(Bounds().Width(), Bounds().Height()); 718 719 printf("VideoFormatChange leave\n"); 720 } 721 722 723 // #pragma mark - 724 725 726 void 727 MainWin::_RefsReceived(BMessage* msg) 728 { 729 // the playlist ist replaced by dropped files 730 // or the dropped files are appended to the end 731 // of the existing playlist if <shift> is pressed 732 int32 appendIndex = modifiers() & B_SHIFT_KEY ? 733 fPlaylist->CountItems() : -1; 734 msg->AddInt32("append_index", appendIndex); 735 736 // forward the message to the playlist window, 737 // so that undo/redo is used for modifying the playlist 738 fPlaylistWindow->PostMessage(msg); 739 } 740 741 742 void 743 MainWin::_SetupWindow() 744 { 745 printf("MainWin::_SetupWindow\n"); 746 747 // Populate the track menus 748 _SetupTrackMenus(); 749 // Enable both if a file was loaded 750 fAudioTrackMenu->SetEnabled(fHasFile); 751 fVideoTrackMenu->SetEnabled(fHasFile); 752 // Select first track (might be "none") in both 753 fAudioTrackMenu->ItemAt(0)->SetMarked(true); 754 fVideoTrackMenu->ItemAt(0)->SetMarked(true); 755 756 fVideoMenu->SetEnabled(fHasVideo); 757 fAudioMenu->SetEnabled(fHasAudio); 758 fDebugMenu->SetEnabled(fHasVideo); 759 760 if (fHasVideo) { 761 fController->GetSize(&fSourceWidth, &fSourceHeight); 762 fWidthScale = 1.0; 763 fHeightScale = 1.0; 764 } else { 765 fSourceWidth = 0; 766 fSourceHeight = 0; 767 fWidthScale = 1.0; 768 fHeightScale = 1.0; 769 } 770 771 _UpdateControlsEnabledStatus(); 772 773 _ResizeWindow(100); 774 775 fVideoView->MakeFocus(); 776 } 777 778 779 void 780 MainWin::_CreateMenu() 781 { 782 fFileMenu = new BMenu(NAME); 783 fPlaylistMenu = new BMenu("Playlist"B_UTF8_ELLIPSIS); 784 fAudioMenu = new BMenu("Audio"); 785 fVideoMenu = new BMenu("Video"); 786 fSettingsMenu = new BMenu("Settings"); 787 fAudioTrackMenu = new BMenu("Track"); 788 fVideoTrackMenu = new BMenu("Track"); 789 fDebugMenu = new BMenu("Debug"); 790 791 fMenuBar->AddItem(fFileMenu); 792 fMenuBar->AddItem(fAudioMenu); 793 fMenuBar->AddItem(fVideoMenu); 794 fMenuBar->AddItem(fSettingsMenu); 795 // fMenuBar->AddItem(fDebugMenu); 796 797 fFileMenu->AddItem(new BMenuItem("New Player"B_UTF8_ELLIPSIS, new BMessage(M_FILE_NEWPLAYER), 'N', B_COMMAND_KEY)); 798 fFileMenu->AddSeparatorItem(); 799 fFileMenu->AddItem(new BMenuItem("Open File"B_UTF8_ELLIPSIS, new BMessage(M_FILE_OPEN), 'O', B_COMMAND_KEY)); 800 fFileMenu->AddItem(new BMenuItem("File Info"B_UTF8_ELLIPSIS, new BMessage(M_FILE_INFO), 'I', B_COMMAND_KEY)); 801 fFileMenu->AddItem(fPlaylistMenu); 802 fPlaylistMenu->Superitem()->SetShortcut('P', B_COMMAND_KEY); 803 fPlaylistMenu->Superitem()->SetMessage(new BMessage(M_FILE_PLAYLIST)); 804 805 fFileMenu->AddSeparatorItem(); 806 fFileMenu->AddItem(new BMenuItem("About" NAME B_UTF8_ELLIPSIS, 807 new BMessage(B_ABOUT_REQUESTED))); 808 fFileMenu->AddSeparatorItem(); 809 fFileMenu->AddItem(new BMenuItem("Close", new BMessage(M_FILE_CLOSE), 'W', B_COMMAND_KEY)); 810 fFileMenu->AddItem(new BMenuItem("Quit", new BMessage(M_FILE_QUIT), 'Q', B_COMMAND_KEY)); 811 812 fPlaylistMenu->SetRadioMode(true); 813 814 fAudioMenu->AddItem(fAudioTrackMenu); 815 816 fVideoMenu->AddItem(fVideoTrackMenu); 817 fVideoMenu->AddSeparatorItem(); 818 fVideoMenu->AddItem(new BMenuItem("50% scale", new BMessage(M_VIEW_50), '0', B_COMMAND_KEY)); 819 fVideoMenu->AddItem(new BMenuItem("100% scale", new BMessage(M_VIEW_100), '1', B_COMMAND_KEY)); 820 fVideoMenu->AddItem(new BMenuItem("200% scale", new BMessage(M_VIEW_200), '2', B_COMMAND_KEY)); 821 fVideoMenu->AddItem(new BMenuItem("300% scale", new BMessage(M_VIEW_300), '3', B_COMMAND_KEY)); 822 fVideoMenu->AddItem(new BMenuItem("400% scale", new BMessage(M_VIEW_400), '4', B_COMMAND_KEY)); 823 fVideoMenu->AddSeparatorItem(); 824 fVideoMenu->AddItem(new BMenuItem("Full Screen", new BMessage(M_TOGGLE_FULLSCREEN), 'F', B_COMMAND_KEY)); 825 fVideoMenu->AddItem(new BMenuItem("Keep Aspect Ratio", new BMessage(M_TOGGLE_KEEP_ASPECT_RATIO), 'K', B_COMMAND_KEY)); 826 827 fSettingsMenu->AddItem(new BMenuItem("No Menu", new BMessage(M_TOGGLE_NO_MENU), 'M', B_COMMAND_KEY)); 828 fSettingsMenu->AddItem(new BMenuItem("No Border", new BMessage(M_TOGGLE_NO_BORDER), 'B', B_COMMAND_KEY)); 829 fSettingsMenu->AddItem(new BMenuItem("No Controls", new BMessage(M_TOGGLE_NO_CONTROLS), 'C', B_COMMAND_KEY)); 830 fSettingsMenu->AddItem(new BMenuItem("Always on Top", new BMessage(M_TOGGLE_ALWAYS_ON_TOP), 'T', B_COMMAND_KEY)); 831 // fSettingsMenu->AddSeparatorItem(); 832 // fSettingsMenu->AddItem(new BMenuItem("Preferences"B_UTF8_ELLIPSIS, new BMessage(M_PREFERENCES), 'P', B_COMMAND_KEY)); 833 834 fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.00000:1", new BMessage(M_ASPECT_100000_1))); 835 fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.06666:1", new BMessage(M_ASPECT_106666_1))); 836 fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.09091:1", new BMessage(M_ASPECT_109091_1))); 837 fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.41176:1", new BMessage(M_ASPECT_141176_1))); 838 fDebugMenu->AddItem(new BMenuItem("force 720 x 576, display aspect 4:3", new BMessage(M_ASPECT_720_576))); 839 fDebugMenu->AddItem(new BMenuItem("force 704 x 576, display aspect 4:3", new BMessage(M_ASPECT_704_576))); 840 fDebugMenu->AddItem(new BMenuItem("force 544 x 576, display aspect 4:3", new BMessage(M_ASPECT_544_576))); 841 842 fAudioTrackMenu->SetRadioMode(true); 843 fVideoTrackMenu->SetRadioMode(true); 844 /* 845 fSettingsMenu->ItemAt(3)->SetMarked(fIsFullscreen); 846 fSettingsMenu->ItemAt(5)->SetMarked(fNoMenu); 847 fSettingsMenu->ItemAt(6)->SetMarked(fNoBorder); 848 fSettingsMenu->ItemAt(7)->SetMarked(fAlwaysOnTop); 849 fSettingsMenu->ItemAt(8)->SetMarked(fKeepAspectRatio); 850 fSettingsMenu->ItemAt(10)->SetEnabled(false); // XXX disable unused preference menu 851 */ 852 } 853 854 855 void 856 MainWin::_SetupTrackMenus() 857 { 858 fAudioTrackMenu->RemoveItems(0, fAudioTrackMenu->CountItems(), true); 859 fVideoTrackMenu->RemoveItems(0, fVideoTrackMenu->CountItems(), true); 860 861 int c, i; 862 char s[100]; 863 864 c = fController->AudioTrackCount(); 865 for (i = 0; i < c; i++) { 866 sprintf(s, "Track %d", i + 1); 867 fAudioTrackMenu->AddItem(new BMenuItem(s, new BMessage(M_SELECT_AUDIO_TRACK + i))); 868 } 869 if (!c) 870 fAudioTrackMenu->AddItem(new BMenuItem("none", new BMessage(M_DUMMY))); 871 872 c = fController->VideoTrackCount(); 873 for (i = 0; i < c; i++) { 874 sprintf(s, "Track %d", i + 1); 875 fVideoTrackMenu->AddItem(new BMenuItem(s, new BMessage(M_SELECT_VIDEO_TRACK + i))); 876 } 877 if (!c) 878 fVideoTrackMenu->AddItem(new BMenuItem("none", new BMessage(M_DUMMY))); 879 } 880 881 882 void 883 MainWin::_SetWindowSizeLimits() 884 { 885 int minWidth = fNoControls ? MIN_WIDTH : fControlsWidth; 886 if (!fNoMenu) 887 minWidth = max_c(minWidth, fMenuBarWidth); 888 int minHeight = (fNoMenu ? 0 : fMenuBarHeight) + (fNoControls ? 0 : fControlsHeight); 889 890 SetSizeLimits(minWidth - 1, 32000, minHeight - 1, fHasVideo ? 32000 : minHeight - 1); 891 } 892 893 894 void 895 MainWin::_ResizeWindow(int percent) 896 { 897 int video_width; 898 int video_height; 899 900 // Get required window size 901 video_width = lround(fSourceWidth * fWidthScale); 902 video_height = lround(fSourceHeight * fHeightScale); 903 904 video_width = (video_width * percent) / 100; 905 video_height = (video_height * percent) / 100; 906 907 // Calculate and set the initial window size 908 int width = max_c(fControlsWidth, video_width); 909 int height = (fNoControls ? 0 : fControlsHeight) + video_height; 910 if (!fNoMenu) { 911 width = max_c(width, fMenuBarWidth); 912 height += fMenuBarHeight; 913 } 914 _SetWindowSizeLimits(); 915 ResizeTo(width - 1, height - 1); 916 } 917 918 919 void 920 MainWin::_ResizeVideoView(int x, int y, int width, int height) 921 { 922 printf("_ResizeVideoView: %d,%d, width %d, height %d\n", x, y, width, height); 923 924 if (fKeepAspectRatio) { 925 // Keep aspect ratio, place video view inside 926 // the background area (may create black bars). 927 float scaled_width = fSourceWidth * fWidthScale; 928 float scaled_height = fSourceHeight * fHeightScale; 929 float factor = min_c(width / scaled_width, height / scaled_height); 930 int render_width = lround(scaled_width * factor); 931 int render_height = lround(scaled_height * factor); 932 if (render_width > width) 933 render_width = width; 934 if (render_height > height) 935 render_height = height; 936 937 int x_ofs = x + (width - render_width) / 2; 938 int y_ofs = y + (height - render_height) / 2; 939 940 fVideoView->MoveTo(x_ofs, y_ofs); 941 fVideoView->ResizeTo(render_width - 1, render_height - 1); 942 943 } else { 944 fVideoView->MoveTo(x, y); 945 fVideoView->ResizeTo(width - 1, height - 1); 946 } 947 } 948 949 950 // #pragma mark - 951 952 953 void 954 MainWin::_MouseDown(BMessage *msg, BView* originalHandler) 955 { 956 BPoint screen_where; 957 uint32 buttons = msg->FindInt32("buttons"); 958 959 // On Zeta, only "screen_where" is relyable, "where" and "be:view_where" seem to be broken 960 if (B_OK != msg->FindPoint("screen_where", &screen_where)) { 961 // Workaround for BeOS R5, it has no "screen_where" 962 if (!originalHandler || msg->FindPoint("where", &screen_where) < B_OK) 963 return; 964 originalHandler->ConvertToScreen(&screen_where); 965 } 966 967 // msg->PrintToStream(); 968 969 // if (1 == msg->FindInt32("buttons") && msg->FindInt32("clicks") == 1) { 970 971 if (1 == buttons && msg->FindInt32("clicks") % 2 == 0) { 972 BRect r(screen_where.x - 1, screen_where.y - 1, screen_where.x + 1, screen_where.y + 1); 973 if (r.Contains(fMouseDownMousePos)) { 974 PostMessage(M_TOGGLE_FULLSCREEN); 975 return; 976 } 977 } 978 979 if (2 == buttons && msg->FindInt32("clicks") % 2 == 0) { 980 BRect r(screen_where.x - 1, screen_where.y - 1, screen_where.x + 1, screen_where.y + 1); 981 if (r.Contains(fMouseDownMousePos)) { 982 PostMessage(M_TOGGLE_NO_BORDER_NO_MENU_NO_CONTROLS); 983 return; 984 } 985 } 986 987 /* 988 // very broken in Zeta: 989 fMouseDownMousePos = fVideoView->ConvertToScreen(msg->FindPoint("where")); 990 */ 991 fMouseDownMousePos = screen_where; 992 fMouseDownWindowPos = Frame().LeftTop(); 993 994 if (buttons == 1 && !fIsFullscreen) { 995 // start mouse tracking 996 fVideoView->SetMouseEventMask(B_POINTER_EVENTS | B_NO_POINTER_HISTORY /* | B_LOCK_WINDOW_FOCUS */); 997 fMouseDownTracking = true; 998 } 999 1000 // pop up a context menu if right mouse button is down for 200 ms 1001 1002 if ((buttons & 2) == 0) 1003 return; 1004 bigtime_t start = system_time(); 1005 bigtime_t delay = 200000; 1006 BPoint location; 1007 do { 1008 fVideoView->GetMouse(&location, &buttons); 1009 if ((buttons & 2) == 0) 1010 break; 1011 snooze(1000); 1012 } while (system_time() - start < delay); 1013 1014 if (buttons & 2) 1015 _ShowContextMenu(screen_where); 1016 } 1017 1018 1019 void 1020 MainWin::_MouseMoved(BMessage *msg, BView* originalHandler) 1021 { 1022 // msg->PrintToStream(); 1023 1024 BPoint mousePos; 1025 uint32 buttons = msg->FindInt32("buttons"); 1026 1027 if (1 == buttons && fMouseDownTracking && !fIsFullscreen) { 1028 /* 1029 // very broken in Zeta: 1030 BPoint mousePos = msg->FindPoint("where"); 1031 printf("view where: %.0f, %.0f => ", mousePos.x, mousePos.y); 1032 fVideoView->ConvertToScreen(&mousePos); 1033 */ 1034 // On Zeta, only "screen_where" is relyable, "where" 1035 // and "be:view_where" seem to be broken 1036 if (B_OK != msg->FindPoint("screen_where", &mousePos)) { 1037 // Workaround for BeOS R5, it has no "screen_where" 1038 if (!originalHandler || msg->FindPoint("where", &mousePos) < B_OK) 1039 return; 1040 originalHandler->ConvertToScreen(&mousePos); 1041 } 1042 // printf("screen where: %.0f, %.0f => ", mousePos.x, mousePos.y); 1043 float delta_x = mousePos.x - fMouseDownMousePos.x; 1044 float delta_y = mousePos.y - fMouseDownMousePos.y; 1045 float x = fMouseDownWindowPos.x + delta_x; 1046 float y = fMouseDownWindowPos.y + delta_y; 1047 // printf("move window to %.0f, %.0f\n", x, y); 1048 MoveTo(x, y); 1049 } 1050 } 1051 1052 1053 void 1054 MainWin::_MouseUp(BMessage *msg) 1055 { 1056 // msg->PrintToStream(); 1057 fMouseDownTracking = false; 1058 } 1059 1060 1061 void 1062 MainWin::_ShowContextMenu(const BPoint &screen_point) 1063 { 1064 printf("Show context menu\n"); 1065 BPopUpMenu *menu = new BPopUpMenu("context menu", false, false); 1066 BMenuItem *item; 1067 menu->AddItem(item = new BMenuItem("Full Screen", new BMessage(M_TOGGLE_FULLSCREEN), 'F', B_COMMAND_KEY)); 1068 item->SetMarked(fIsFullscreen); 1069 item->SetEnabled(fHasVideo); 1070 menu->AddItem(item = new BMenuItem("Keep Aspect Ratio", new BMessage(M_TOGGLE_KEEP_ASPECT_RATIO), 'K', B_COMMAND_KEY)); 1071 item->SetMarked(fKeepAspectRatio); 1072 item->SetEnabled(fHasVideo); 1073 1074 menu->AddSeparatorItem(); 1075 menu->AddItem(item = new BMenuItem("No Menu", new BMessage(M_TOGGLE_NO_MENU), 'M', B_COMMAND_KEY)); 1076 item->SetMarked(fNoMenu); 1077 menu->AddItem(item = new BMenuItem("No Border", new BMessage(M_TOGGLE_NO_BORDER), 'B', B_COMMAND_KEY)); 1078 item->SetMarked(fNoBorder); 1079 menu->AddItem(item = new BMenuItem("Always on Top", new BMessage(M_TOGGLE_ALWAYS_ON_TOP), 'T', B_COMMAND_KEY)); 1080 item->SetMarked(fAlwaysOnTop); 1081 1082 menu->AddSeparatorItem(); 1083 menu->AddItem(new BMenuItem("About" NAME B_UTF8_ELLIPSIS, 1084 new BMessage(B_ABOUT_REQUESTED))); 1085 menu->AddSeparatorItem(); 1086 menu->AddItem(new BMenuItem("Quit", new BMessage(M_FILE_QUIT), 'Q', B_COMMAND_KEY)); 1087 1088 menu->AddSeparatorItem(); 1089 menu->AddItem(new BMenuItem("pixel aspect ratio 1.00000:1", new BMessage(M_ASPECT_100000_1))); 1090 menu->AddItem(new BMenuItem("pixel aspect ratio 1.06666:1", new BMessage(M_ASPECT_106666_1))); 1091 menu->AddItem(new BMenuItem("pixel aspect ratio 1.09091:1", new BMessage(M_ASPECT_109091_1))); 1092 menu->AddItem(new BMenuItem("pixel aspect ratio 1.41176:1", new BMessage(M_ASPECT_141176_1))); 1093 menu->AddItem(new BMenuItem("force 720 x 576, display aspect 4:3", new BMessage(M_ASPECT_720_576))); 1094 menu->AddItem(new BMenuItem("force 704 x 576, display aspect 4:3", new BMessage(M_ASPECT_704_576))); 1095 menu->AddItem(new BMenuItem("force 544 x 576, display aspect 4:3", new BMessage(M_ASPECT_544_576))); 1096 1097 menu->SetTargetForItems(this); 1098 BRect r(screen_point.x - 5, screen_point.y - 5, screen_point.x + 5, screen_point.y + 5); 1099 menu->Go(screen_point, true, true, r, true); 1100 } 1101 1102 1103 /* Trap keys that are about to be send to background or renderer view. 1104 * Return B_OK if it shouldn't be passed to the view 1105 */ 1106 status_t 1107 MainWin::_KeyDown(BMessage *msg) 1108 { 1109 // msg->PrintToStream(); 1110 1111 uint32 key = msg->FindInt32("key"); 1112 uint32 raw_char = msg->FindInt32("raw_char"); 1113 uint32 modifiers = msg->FindInt32("modifiers"); 1114 1115 printf("key 0x%lx, raw_char 0x%lx, modifiers 0x%lx\n", key, raw_char, modifiers); 1116 1117 switch (raw_char) { 1118 case B_SPACE: 1119 if (fController->IsPaused() || fController->IsStopped()) 1120 fController->Play(); 1121 else 1122 fController->Pause(); 1123 return B_OK; 1124 1125 case B_ESCAPE: 1126 if (fIsFullscreen) { 1127 PostMessage(M_TOGGLE_FULLSCREEN); 1128 return B_OK; 1129 } else 1130 break; 1131 1132 case B_ENTER: // Enter / Return 1133 if (modifiers & B_COMMAND_KEY) { 1134 PostMessage(M_TOGGLE_FULLSCREEN); 1135 return B_OK; 1136 } else 1137 break; 1138 1139 case B_TAB: 1140 if ((modifiers & (B_COMMAND_KEY | B_CONTROL_KEY | B_OPTION_KEY | B_MENU_KEY)) == 0) { 1141 PostMessage(M_TOGGLE_FULLSCREEN); 1142 return B_OK; 1143 } else 1144 break; 1145 1146 case B_UP_ARROW: 1147 if (modifiers & B_COMMAND_KEY) { 1148 PostMessage(M_CHANNEL_NEXT); 1149 } else { 1150 PostMessage(M_VOLUME_UP); 1151 } 1152 return B_OK; 1153 1154 case B_DOWN_ARROW: 1155 if (modifiers & B_COMMAND_KEY) { 1156 PostMessage(M_CHANNEL_PREV); 1157 } else { 1158 PostMessage(M_VOLUME_DOWN); 1159 } 1160 return B_OK; 1161 1162 case B_RIGHT_ARROW: 1163 if (modifiers & B_COMMAND_KEY) { 1164 PostMessage(M_VOLUME_UP); 1165 } else { 1166 PostMessage(M_CHANNEL_NEXT); 1167 } 1168 return B_OK; 1169 1170 case B_LEFT_ARROW: 1171 if (modifiers & B_COMMAND_KEY) { 1172 PostMessage(M_VOLUME_DOWN); 1173 } else { 1174 PostMessage(M_CHANNEL_PREV); 1175 } 1176 return B_OK; 1177 1178 case B_PAGE_UP: 1179 PostMessage(M_CHANNEL_NEXT); 1180 return B_OK; 1181 1182 case B_PAGE_DOWN: 1183 PostMessage(M_CHANNEL_PREV); 1184 return B_OK; 1185 } 1186 1187 switch (key) { 1188 case 0x3a: // numeric keypad + 1189 if ((modifiers & B_COMMAND_KEY) == 0) { 1190 printf("if\n"); 1191 PostMessage(M_VOLUME_UP); 1192 return B_OK; 1193 } else { 1194 printf("else\n"); 1195 break; 1196 } 1197 1198 case 0x25: // numeric keypad - 1199 if ((modifiers & B_COMMAND_KEY) == 0) { 1200 PostMessage(M_VOLUME_DOWN); 1201 return B_OK; 1202 } else { 1203 break; 1204 } 1205 1206 case 0x38: // numeric keypad up arrow 1207 PostMessage(M_VOLUME_UP); 1208 return B_OK; 1209 1210 case 0x59: // numeric keypad down arrow 1211 PostMessage(M_VOLUME_DOWN); 1212 return B_OK; 1213 1214 case 0x39: // numeric keypad page up 1215 case 0x4a: // numeric keypad right arrow 1216 PostMessage(M_CHANNEL_NEXT); 1217 return B_OK; 1218 1219 case 0x5a: // numeric keypad page down 1220 case 0x48: // numeric keypad left arrow 1221 PostMessage(M_CHANNEL_PREV); 1222 return B_OK; 1223 } 1224 1225 return B_ERROR; 1226 } 1227 1228 1229 // #pragma mark - 1230 1231 1232 void 1233 MainWin::_ToggleNoBorderNoMenu() 1234 { 1235 if (!fNoMenu && !fNoBorder && !fNoControls) { 1236 PostMessage(M_TOGGLE_NO_MENU); 1237 PostMessage(M_TOGGLE_NO_BORDER); 1238 PostMessage(M_TOGGLE_NO_CONTROLS); 1239 } else { 1240 if (!fNoMenu) 1241 PostMessage(M_TOGGLE_NO_MENU); 1242 if (!fNoBorder) 1243 PostMessage(M_TOGGLE_NO_BORDER); 1244 if (!fNoControls) 1245 PostMessage(M_TOGGLE_NO_CONTROLS); 1246 } 1247 } 1248 1249 1250 void 1251 MainWin::_ToggleFullscreen() 1252 { 1253 printf("_ToggleFullscreen enter\n"); 1254 1255 if (!fHasVideo) { 1256 printf("_ToggleFullscreen - ignoring, as we don't have a video\n"); 1257 return; 1258 } 1259 1260 fIsFullscreen = !fIsFullscreen; 1261 1262 if (fIsFullscreen) { 1263 // switch to fullscreen 1264 1265 fSavedFrame = Frame(); 1266 printf("saving current frame: %d %d %d %d\n", int(fSavedFrame.left), int(fSavedFrame.top), int(fSavedFrame.right), int(fSavedFrame.bottom)); 1267 BScreen screen(this); 1268 BRect rect(screen.Frame()); 1269 1270 Hide(); 1271 MoveTo(rect.left, rect.top); 1272 ResizeTo(rect.Width(), rect.Height()); 1273 Show(); 1274 1275 } else { 1276 // switch back from full screen mode 1277 1278 Hide(); 1279 MoveTo(fSavedFrame.left, fSavedFrame.top); 1280 ResizeTo(fSavedFrame.Width(), fSavedFrame.Height()); 1281 Show(); 1282 } 1283 1284 printf("_ToggleFullscreen leave\n"); 1285 } 1286 1287 void 1288 MainWin::_ToggleNoControls() 1289 { 1290 printf("_ToggleNoControls enter\n"); 1291 1292 if (fIsFullscreen) { 1293 // fullscreen is always without menu 1294 printf("_ToggleNoControls leave, doing nothing, we are fullscreen\n"); 1295 return; 1296 } 1297 1298 fNoControls = !fNoControls; 1299 _SetWindowSizeLimits(); 1300 1301 if (fNoControls) { 1302 ResizeBy(0, - fControlsHeight); 1303 } else { 1304 ResizeBy(0, fControlsHeight); 1305 } 1306 1307 printf("_ToggleNoControls leave\n"); 1308 } 1309 1310 void 1311 MainWin::_ToggleNoMenu() 1312 { 1313 printf("_ToggleNoMenu enter\n"); 1314 1315 if (fIsFullscreen) { 1316 // fullscreen is always without menu 1317 printf("_ToggleNoMenu leave, doing nothing, we are fullscreen\n"); 1318 return; 1319 } 1320 1321 fNoMenu = !fNoMenu; 1322 _SetWindowSizeLimits(); 1323 1324 if (fNoMenu) { 1325 MoveBy(0, fMenuBarHeight); 1326 ResizeBy(0, - fMenuBarHeight); 1327 } else { 1328 MoveBy(0, - fMenuBarHeight); 1329 ResizeBy(0, fMenuBarHeight); 1330 } 1331 1332 printf("_ToggleNoMenu leave\n"); 1333 } 1334 1335 1336 void 1337 MainWin::_ToggleNoBorder() 1338 { 1339 printf("_ToggleNoBorder enter\n"); 1340 fNoBorder = !fNoBorder; 1341 SetLook(fNoBorder ? B_BORDERED_WINDOW_LOOK : B_TITLED_WINDOW_LOOK); 1342 printf("_ToggleNoBorder leave\n"); 1343 } 1344 1345 1346 void 1347 MainWin::_ToggleAlwaysOnTop() 1348 { 1349 printf("_ToggleAlwaysOnTop enter\n"); 1350 fAlwaysOnTop = !fAlwaysOnTop; 1351 SetFeel(fAlwaysOnTop ? B_FLOATING_ALL_WINDOW_FEEL : B_NORMAL_WINDOW_FEEL); 1352 printf("_ToggleAlwaysOnTop leave\n"); 1353 } 1354 1355 1356 void 1357 MainWin::_ToggleKeepAspectRatio() 1358 { 1359 printf("_ToggleKeepAspectRatio enter\n"); 1360 fKeepAspectRatio = !fKeepAspectRatio; 1361 FrameResized(Bounds().Width(), Bounds().Height()); 1362 printf("_ToggleKeepAspectRatio leave\n"); 1363 } 1364 1365 1366 // #pragma mark - 1367 1368 1369 void 1370 MainWin::_UpdateControlsEnabledStatus() 1371 { 1372 uint32 enabledButtons = 0; 1373 if (fHasVideo || fHasAudio) { 1374 enabledButtons |= PLAYBACK_ENABLED | SEEK_ENABLED 1375 | SEEK_BACK_ENABLED | SEEK_FORWARD_ENABLED; 1376 } 1377 if (fHasAudio) 1378 enabledButtons |= VOLUME_ENABLED; 1379 1380 bool canSkipPrevious, canSkipNext; 1381 fPlaylist->GetSkipInfo(&canSkipPrevious, &canSkipNext); 1382 if (canSkipPrevious) 1383 enabledButtons |= SKIP_BACK_ENABLED; 1384 if (canSkipNext) 1385 enabledButtons |= SKIP_FORWARD_ENABLED; 1386 1387 fControls->SetEnabled(enabledButtons); 1388 } 1389 1390 1391 void 1392 MainWin::_UpdatePlaylistMenu() 1393 { 1394 if (!fPlaylist->Lock()) 1395 return; 1396 1397 fPlaylistMenu->RemoveItems(0, fPlaylistMenu->CountItems(), true); 1398 1399 int32 count = fPlaylist->CountItems(); 1400 for (int32 i = 0; i < count; i++) { 1401 entry_ref ref; 1402 if (fPlaylist->GetRefAt(i, &ref) < B_OK) 1403 continue; 1404 _AddPlaylistItem(ref, i); 1405 } 1406 fPlaylistMenu->SetTargetForItems(this); 1407 1408 _MarkPlaylistItem(fPlaylist->CurrentRefIndex()); 1409 1410 fPlaylist->Unlock(); 1411 } 1412 1413 1414 void 1415 MainWin::_AddPlaylistItem(const entry_ref& ref, int32 index) 1416 { 1417 BMessage* message = new BMessage(M_SET_PLAYLIST_POSITION); 1418 message->AddInt32("index", index); 1419 BMenuItem* item = new BMenuItem(ref.name, message); 1420 fPlaylistMenu->AddItem(item, index); 1421 } 1422 1423 1424 void 1425 MainWin::_RemovePlaylistItem(int32 index) 1426 { 1427 delete fPlaylistMenu->RemoveItem(index); 1428 } 1429 1430 1431 void 1432 MainWin::_MarkPlaylistItem(int32 index) 1433 { 1434 if (BMenuItem* item = fPlaylistMenu->ItemAt(index)) { 1435 item->SetMarked(true); 1436 // ... and in case the menu is currently on screen: 1437 if (fPlaylistMenu->LockLooper()) { 1438 fPlaylistMenu->Invalidate(); 1439 fPlaylistMenu->UnlockLooper(); 1440 } 1441 } 1442 } 1443 1444 1445