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