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