1 /* 2 * MainWin.cpp - Media Player for the Haiku Operating System 3 * 4 * Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * version 2 as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 * 19 */ 20 #include "MainWin.h" 21 #include "MainApp.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 #define NAME "MediaPlayer" 39 #define MIN_WIDTH 250 40 41 42 // XXX TODO: why is lround not defined? 43 #define lround(a) ((int)(0.99999 + (a))) 44 45 enum 46 { 47 M_DUMMY = 0x100, 48 M_FILE_OPEN = 0x1000, 49 M_FILE_NEWPLAYER, 50 M_FILE_INFO, 51 M_FILE_ABOUT, 52 M_FILE_CLOSE, 53 M_FILE_QUIT, 54 M_VIEW_50, 55 M_VIEW_100, 56 M_VIEW_200, 57 M_VIEW_300, 58 M_VIEW_400, 59 M_TOGGLE_FULLSCREEN, 60 M_TOGGLE_NO_BORDER, 61 M_TOGGLE_NO_MENU, 62 M_TOGGLE_NO_CONTROLS, 63 M_TOGGLE_NO_BORDER_NO_MENU_NO_CONTROLS, 64 M_TOGGLE_ALWAYS_ON_TOP, 65 M_TOGGLE_KEEP_ASPECT_RATIO, 66 M_PREFERENCES, 67 M_VOLUME_UP, 68 M_VOLUME_DOWN, 69 M_CHANNEL_NEXT, 70 M_CHANNEL_PREV, 71 M_ASPECT_100000_1, 72 M_ASPECT_106666_1, 73 M_ASPECT_109091_1, 74 M_ASPECT_141176_1, 75 M_ASPECT_720_576, 76 M_ASPECT_704_576, 77 M_ASPECT_544_576, 78 M_SELECT_AUDIO_TRACK = 0x00000800, 79 M_SELECT_AUDIO_TRACK_END = 0x00000fff, 80 M_SELECT_VIDEO_TRACK = 0x00010000, 81 M_SELECT_VIDEO_TRACK_END = 0x000fffff, 82 }; 83 84 //#define printf(a...) 85 86 87 MainWin::MainWin() 88 : BWindow(BRect(100,100,350,300), NAME, B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS /* | B_WILL_ACCEPT_FIRST_CLICK */) 89 , fFilePanel(NULL) 90 , fHasFile(false) 91 , fHasVideo(false) 92 , fPlaylist(new Playlist) 93 , fController(new Controller) 94 , fIsFullscreen(false) 95 , fKeepAspectRatio(true) 96 , fAlwaysOnTop(false) 97 , fNoMenu(false) 98 , fNoBorder(false) 99 , fNoControls(false) 100 , fSourceWidth(0) 101 , fSourceHeight(0) 102 , fWidthScale(1.0) 103 , fHeightScale(1.0) 104 , fMouseDownTracking(false) 105 { 106 static int pos = 0; 107 MoveBy(pos * 25, pos * 25); 108 pos = (pos + 1) % 15; 109 110 BRect rect = Bounds(); 111 112 // background 113 fBackground = new BView(rect, "background", B_FOLLOW_ALL, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE); 114 fBackground->SetViewColor(0,0,0); 115 AddChild(fBackground); 116 117 // menu 118 fMenuBar = new BMenuBar(fBackground->Bounds(), "menu"); 119 CreateMenu(); 120 fBackground->AddChild(fMenuBar); 121 fMenuBar->ResizeToPreferred(); 122 fMenuBarHeight = (int)fMenuBar->Frame().Height() + 1; 123 fMenuBar->SetResizingMode(B_FOLLOW_NONE); 124 125 // video view 126 rect = BRect(0, fMenuBarHeight, fBackground->Bounds().right, fMenuBarHeight + 10); 127 fVideoView = new VideoView(rect, "video display", B_FOLLOW_NONE, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE); 128 fBackground->AddChild(fVideoView); 129 130 // controls 131 rect = BRect(0, fMenuBarHeight + 11, fBackground->Bounds().right, fBackground->Bounds().bottom); 132 fControls = new ControllerView(rect, fController, fPlaylist, this); 133 fBackground->AddChild(fControls); 134 fControls->ResizeToPreferred(); 135 fControlsHeight = (int)fControls->Frame().Height() + 1; 136 fControlsWidth = (int)fControls->Frame().Width() + 1; 137 fControls->SetResizingMode(B_FOLLOW_BOTTOM | B_FOLLOW_LEFT_RIGHT); 138 // fControls->MoveTo(0, fBackground->Bounds().bottom - fControlsHeight + 1); 139 140 // fVideoView->ResizeTo(fBackground->Bounds().Width(), fBackground->Bounds().Height() - fMenuBarHeight - fControlsHeight); 141 142 fController->SetVideoView(fVideoView); 143 fVideoView->IsOverlaySupported(); 144 145 printf("fMenuBarHeight %d\n", fMenuBarHeight); 146 printf("fControlsHeight %d\n", fControlsHeight); 147 printf("fControlsWidth %d\n", fControlsWidth); 148 149 SetupWindow(); 150 151 Show(); 152 } 153 154 155 MainWin::~MainWin() 156 { 157 printf("MainWin::~MainWin\n"); 158 delete fPlaylist; 159 delete fController; 160 delete fFilePanel; 161 } 162 163 164 void 165 MainWin::OpenFile(const entry_ref &ref) 166 { 167 printf("MainWin::OpenFile\n"); 168 169 status_t err = fController->SetTo(ref); 170 if (err != B_OK) { 171 char s[300]; 172 sprintf(s, "Can't open file\n\n%s\n\nError 0x%08lx\n(%s)\n", 173 ref.name, err, strerror(err)); 174 (new BAlert("error", s, "OK"))->Go(); 175 fHasFile = false; 176 fHasVideo = false; 177 SetTitle(NAME); 178 } else { 179 fHasFile = true; 180 fHasVideo = fController->VideoTrackCount() != 0; 181 SetTitle(ref.name); 182 } 183 SetupWindow(); 184 } 185 186 void 187 MainWin::SetupWindow() 188 { 189 printf("MainWin::SetupWindow\n"); 190 191 // Pupulate the track menus 192 SetupTrackMenus(); 193 // Enable both if a file was loaded 194 fAudioMenu->SetEnabled(fHasFile); 195 fVideoMenu->SetEnabled(fHasFile); 196 // Select first track (might be "none") in both 197 fAudioMenu->ItemAt(0)->SetMarked(true); 198 fVideoMenu->ItemAt(0)->SetMarked(true); 199 200 if (fHasVideo) { 201 fSourceWidth = 320; 202 fSourceHeight = 240; 203 fWidthScale = 1.24; 204 fHeightScale = 1.35; 205 } else { 206 fSourceWidth = 0; 207 fSourceHeight = 0; 208 fWidthScale = 1.0; 209 fHeightScale = 1.0; 210 } 211 212 ResizeWindow(100); 213 214 fVideoView->MakeFocus(); 215 } 216 217 218 void 219 MainWin::ResizeWindow(int percent) 220 { 221 int video_width; 222 int video_height; 223 224 // Get required window size 225 video_width = lround(fSourceWidth * fWidthScale); 226 video_height = lround(fSourceHeight * fHeightScale); 227 228 video_width = (video_width * percent) / 100; 229 video_height = (video_height * percent) / 100; 230 231 // Calculate and set the initial window size 232 int width = max_c(fControlsWidth, video_width); 233 int height = (fNoMenu ? 0 : fMenuBarHeight) + (fNoControls ? 0 : fControlsHeight) + video_height; 234 SetWindowSizeLimits(); 235 ResizeTo(width - 1, height - 1); 236 } 237 238 239 void 240 MainWin::SetWindowSizeLimits() 241 { 242 int min_width = fNoControls ? MIN_WIDTH : fControlsWidth; 243 int min_height = (fNoMenu ? 0 : fMenuBarHeight) + (fNoControls ? 0 : fControlsHeight); 244 245 SetSizeLimits(min_width - 1, 32000, min_height - 1, fHasVideo ? 32000 : min_height - 1); 246 } 247 248 249 void 250 MainWin::CreateMenu() 251 { 252 fFileMenu = new BMenu(NAME); 253 fViewMenu = new BMenu("View"); 254 fSettingsMenu = new BMenu("Settings"); 255 fAudioMenu = new BMenu("Audio Track"); 256 fVideoMenu = new BMenu("Video Track"); 257 fDebugMenu = new BMenu("Debug"); 258 259 fMenuBar->AddItem(fFileMenu); 260 fMenuBar->AddItem(fViewMenu); 261 fMenuBar->AddItem(fSettingsMenu); 262 fMenuBar->AddItem(fDebugMenu); 263 264 fFileMenu->AddItem(new BMenuItem("New Player", new BMessage(M_FILE_NEWPLAYER), 'N', B_COMMAND_KEY)); 265 fFileMenu->AddSeparatorItem(); 266 fFileMenu->AddItem(new BMenuItem("Open File"B_UTF8_ELLIPSIS, new BMessage(M_FILE_OPEN), 'O', B_COMMAND_KEY)); 267 fFileMenu->AddItem(new BMenuItem("File Info"B_UTF8_ELLIPSIS, new BMessage(M_FILE_INFO), 'I', B_COMMAND_KEY)); 268 fFileMenu->AddSeparatorItem(); 269 fFileMenu->AddItem(new BMenuItem("About", new BMessage(M_FILE_ABOUT), 'A', B_COMMAND_KEY)); 270 fFileMenu->AddSeparatorItem(); 271 fFileMenu->AddItem(new BMenuItem("Close", new BMessage(M_FILE_CLOSE), 'W', B_COMMAND_KEY)); 272 fFileMenu->AddItem(new BMenuItem("Quit", new BMessage(M_FILE_QUIT), 'Q', B_COMMAND_KEY)); 273 274 fViewMenu->AddItem(new BMenuItem("50% scale", new BMessage(M_VIEW_50), '0', B_COMMAND_KEY)); 275 fViewMenu->AddItem(new BMenuItem("100% scale", new BMessage(M_VIEW_100), '1', B_COMMAND_KEY)); 276 fViewMenu->AddItem(new BMenuItem("200% scale", new BMessage(M_VIEW_200), '2', B_COMMAND_KEY)); 277 fViewMenu->AddItem(new BMenuItem("300% scale", new BMessage(M_VIEW_300), '3', B_COMMAND_KEY)); 278 fViewMenu->AddItem(new BMenuItem("400% scale", new BMessage(M_VIEW_400), '4', B_COMMAND_KEY)); 279 fViewMenu->AddSeparatorItem(); 280 fViewMenu->AddItem(new BMenuItem("Full Screen", new BMessage(M_TOGGLE_FULLSCREEN), 'F', B_COMMAND_KEY)); 281 // fViewMenu->SetRadioMode(true); 282 // fViewMenu->AddSeparatorItem(); 283 // fViewMenu->AddItem(new BMenuItem("Always on Top", new BMessage(M_TOGGLE_ALWAYS_ON_TOP), 'T', B_COMMAND_KEY)); 284 285 fSettingsMenu->AddItem(fAudioMenu); 286 fSettingsMenu->AddItem(fVideoMenu); 287 fSettingsMenu->AddSeparatorItem(); 288 fSettingsMenu->AddItem(new BMenuItem("No Menu", new BMessage(M_TOGGLE_NO_MENU), 'M', B_COMMAND_KEY)); 289 fSettingsMenu->AddItem(new BMenuItem("No Border", new BMessage(M_TOGGLE_NO_BORDER), 'B', B_COMMAND_KEY)); 290 fSettingsMenu->AddItem(new BMenuItem("No Controls", new BMessage(M_TOGGLE_NO_CONTROLS), 'C', B_COMMAND_KEY)); 291 fSettingsMenu->AddItem(new BMenuItem("Always on Top", new BMessage(M_TOGGLE_ALWAYS_ON_TOP), 'T', B_COMMAND_KEY)); 292 fSettingsMenu->AddItem(new BMenuItem("Keep Aspect Ratio", new BMessage(M_TOGGLE_KEEP_ASPECT_RATIO), 'K', B_COMMAND_KEY)); 293 fSettingsMenu->AddSeparatorItem(); 294 fSettingsMenu->AddItem(new BMenuItem("Preferences"B_UTF8_ELLIPSIS, new BMessage(M_PREFERENCES), 'P', B_COMMAND_KEY)); 295 296 fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.00000:1", new BMessage(M_ASPECT_100000_1))); 297 fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.06666:1", new BMessage(M_ASPECT_106666_1))); 298 fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.09091:1", new BMessage(M_ASPECT_109091_1))); 299 fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.41176:1", new BMessage(M_ASPECT_141176_1))); 300 fDebugMenu->AddItem(new BMenuItem("force 720 x 576, display aspect 4:3", new BMessage(M_ASPECT_720_576))); 301 fDebugMenu->AddItem(new BMenuItem("force 704 x 576, display aspect 4:3", new BMessage(M_ASPECT_704_576))); 302 fDebugMenu->AddItem(new BMenuItem("force 544 x 576, display aspect 4:3", new BMessage(M_ASPECT_544_576))); 303 304 fAudioMenu->SetRadioMode(true); 305 fVideoMenu->SetRadioMode(true); 306 /* 307 fSettingsMenu->ItemAt(3)->SetMarked(fIsFullscreen); 308 fSettingsMenu->ItemAt(5)->SetMarked(fNoMenu); 309 fSettingsMenu->ItemAt(6)->SetMarked(fNoBorder); 310 fSettingsMenu->ItemAt(7)->SetMarked(fAlwaysOnTop); 311 fSettingsMenu->ItemAt(8)->SetMarked(fKeepAspectRatio); 312 fSettingsMenu->ItemAt(10)->SetEnabled(false); // XXX disable unused preference menu 313 */ 314 } 315 316 317 void 318 MainWin::SetupTrackMenus() 319 { 320 fAudioMenu->RemoveItems(0, fAudioMenu->CountItems(), true); 321 fVideoMenu->RemoveItems(0, fVideoMenu->CountItems(), true); 322 323 int c, i; 324 char s[100]; 325 326 c = fController->AudioTrackCount(); 327 for (i = 0; i < c; i++) { 328 sprintf(s, "Track %d", i + 1); 329 fAudioMenu->AddItem(new BMenuItem(s, new BMessage(M_SELECT_AUDIO_TRACK + i))); 330 } 331 if (!c) 332 fAudioMenu->AddItem(new BMenuItem("none", new BMessage(M_DUMMY))); 333 334 c = fController->VideoTrackCount(); 335 for (i = 0; i < c; i++) { 336 sprintf(s, "Track %d", i + 1); 337 fVideoMenu->AddItem(new BMenuItem(s, new BMessage(M_SELECT_VIDEO_TRACK + i))); 338 } 339 if (!c) 340 fVideoMenu->AddItem(new BMenuItem("none", new BMessage(M_DUMMY))); 341 } 342 343 344 bool 345 MainWin::QuitRequested() 346 { 347 be_app->PostMessage(M_PLAYER_QUIT); 348 return true; 349 } 350 351 352 void 353 MainWin::MouseDown(BMessage *msg) 354 { 355 BPoint screen_where; 356 uint32 buttons = msg->FindInt32("buttons"); 357 358 // On Zeta, only "screen_where" is relyable, "where" and "be:view_where" seem to be broken 359 if (B_OK != msg->FindPoint("screen_where", &screen_where)) { 360 // Workaround for BeOS R5, it has no "screen_where" 361 fVideoView->GetMouse(&screen_where, &buttons, false); 362 fVideoView->ConvertToScreen(&screen_where); 363 } 364 365 // msg->PrintToStream(); 366 367 // if (1 == msg->FindInt32("buttons") && msg->FindInt32("clicks") == 1) { 368 369 if (1 == buttons && msg->FindInt32("clicks") % 2 == 0) { 370 BRect r(screen_where.x - 1, screen_where.y - 1, screen_where.x + 1, screen_where.y + 1); 371 if (r.Contains(fMouseDownMousePos)) { 372 PostMessage(M_TOGGLE_FULLSCREEN); 373 return; 374 } 375 } 376 377 if (2 == buttons && msg->FindInt32("clicks") % 2 == 0) { 378 BRect r(screen_where.x - 1, screen_where.y - 1, screen_where.x + 1, screen_where.y + 1); 379 if (r.Contains(fMouseDownMousePos)) { 380 PostMessage(M_TOGGLE_NO_BORDER_NO_MENU_NO_CONTROLS); 381 return; 382 } 383 } 384 385 /* 386 // very broken in Zeta: 387 fMouseDownMousePos = fVideoView->ConvertToScreen(msg->FindPoint("where")); 388 */ 389 fMouseDownMousePos = screen_where; 390 fMouseDownWindowPos = Frame().LeftTop(); 391 392 if (buttons == 1 && !fIsFullscreen) { 393 // start mouse tracking 394 fVideoView->SetMouseEventMask(B_POINTER_EVENTS | B_NO_POINTER_HISTORY /* | B_LOCK_WINDOW_FOCUS */); 395 fMouseDownTracking = true; 396 } 397 398 // pop up a context menu if right mouse button is down for 200 ms 399 400 if ((buttons & 2) == 0) 401 return; 402 bigtime_t start = system_time(); 403 bigtime_t delay = 200000; 404 BPoint location; 405 do { 406 fVideoView->GetMouse(&location, &buttons); 407 if ((buttons & 2) == 0) 408 break; 409 snooze(1000); 410 } while (system_time() - start < delay); 411 412 if (buttons & 2) 413 ShowContextMenu(screen_where); 414 } 415 416 417 void 418 MainWin::MouseMoved(BMessage *msg) 419 { 420 // msg->PrintToStream(); 421 422 BPoint mousePos; 423 uint32 buttons = msg->FindInt32("buttons"); 424 425 if (1 == buttons && fMouseDownTracking && !fIsFullscreen) { 426 /* 427 // very broken in Zeta: 428 BPoint mousePos = msg->FindPoint("where"); 429 printf("view where: %.0f, %.0f => ", mousePos.x, mousePos.y); 430 fVideoView->ConvertToScreen(&mousePos); 431 */ 432 // On Zeta, only "screen_where" is relyable, "where" and "be:view_where" seem to be broken 433 if (B_OK != msg->FindPoint("screen_where", &mousePos)) { 434 // Workaround for BeOS R5, it has no "screen_where" 435 fVideoView->GetMouse(&mousePos, &buttons, false); 436 fVideoView->ConvertToScreen(&mousePos); 437 } 438 // printf("screen where: %.0f, %.0f => ", mousePos.x, mousePos.y); 439 float delta_x = mousePos.x - fMouseDownMousePos.x; 440 float delta_y = mousePos.y - fMouseDownMousePos.y; 441 float x = fMouseDownWindowPos.x + delta_x; 442 float y = fMouseDownWindowPos.y + delta_y; 443 // printf("move window to %.0f, %.0f\n", x, y); 444 MoveTo(x, y); 445 } 446 } 447 448 449 void 450 MainWin::MouseUp(BMessage *msg) 451 { 452 // msg->PrintToStream(); 453 fMouseDownTracking = false; 454 } 455 456 457 void 458 MainWin::ShowContextMenu(const BPoint &screen_point) 459 { 460 printf("Show context menu\n"); 461 BPopUpMenu *menu = new BPopUpMenu("context menu", false, false); 462 BMenuItem *item; 463 menu->AddItem(item = new BMenuItem("Full Screen", new BMessage(M_TOGGLE_FULLSCREEN), 'F', B_COMMAND_KEY)); 464 item->SetMarked(fIsFullscreen); 465 menu->AddSeparatorItem(); 466 menu->AddItem(item = new BMenuItem("No Menu", new BMessage(M_TOGGLE_NO_MENU), 'M', B_COMMAND_KEY)); 467 item->SetMarked(fNoMenu); 468 menu->AddItem(item = new BMenuItem("No Border", new BMessage(M_TOGGLE_NO_BORDER), 'B', B_COMMAND_KEY)); 469 item->SetMarked(fNoBorder); 470 menu->AddItem(item = new BMenuItem("Always on Top", new BMessage(M_TOGGLE_ALWAYS_ON_TOP), 'T', B_COMMAND_KEY)); 471 item->SetMarked(fAlwaysOnTop); 472 menu->AddItem(item = new BMenuItem("Keep Aspect Ratio", new BMessage(M_TOGGLE_KEEP_ASPECT_RATIO), 'K', B_COMMAND_KEY)); 473 item->SetMarked(fKeepAspectRatio); 474 menu->AddSeparatorItem(); 475 menu->AddItem(new BMenuItem("About", new BMessage(M_FILE_ABOUT), 'A', B_COMMAND_KEY)); 476 menu->AddSeparatorItem(); 477 menu->AddItem(new BMenuItem("Quit", new BMessage(M_FILE_QUIT), 'Q', B_COMMAND_KEY)); 478 479 menu->AddSeparatorItem(); 480 menu->AddItem(new BMenuItem("pixel aspect ratio 1.00000:1", new BMessage(M_ASPECT_100000_1))); 481 menu->AddItem(new BMenuItem("pixel aspect ratio 1.06666:1", new BMessage(M_ASPECT_106666_1))); 482 menu->AddItem(new BMenuItem("pixel aspect ratio 1.09091:1", new BMessage(M_ASPECT_109091_1))); 483 menu->AddItem(new BMenuItem("pixel aspect ratio 1.41176:1", new BMessage(M_ASPECT_141176_1))); 484 menu->AddItem(new BMenuItem("force 720 x 576, display aspect 4:3", new BMessage(M_ASPECT_720_576))); 485 menu->AddItem(new BMenuItem("force 704 x 576, display aspect 4:3", new BMessage(M_ASPECT_704_576))); 486 menu->AddItem(new BMenuItem("force 544 x 576, display aspect 4:3", new BMessage(M_ASPECT_544_576))); 487 488 menu->SetTargetForItems(this); 489 BRect r(screen_point.x - 5, screen_point.y - 5, screen_point.x + 5, screen_point.y + 5); 490 menu->Go(screen_point, true, true, r, true); 491 } 492 493 494 void 495 MainWin::VideoFormatChange(int width, int height, float width_scale, float height_scale) 496 { 497 // called when video format or aspect ratio changes 498 499 printf("VideoFormatChange enter: width %d, height %d, width_scale %.6f, height_scale %.6f\n", width, height, width_scale, height_scale); 500 501 if (width_scale < 1.0 && height_scale >= 1.0) { 502 width_scale = 1.0 / width_scale; 503 height_scale = 1.0 / height_scale; 504 printf("inverting! new values: width_scale %.6f, height_scale %.6f\n", width_scale, height_scale); 505 } 506 507 fSourceWidth = width; 508 fSourceHeight = height; 509 fWidthScale = width_scale; 510 fHeightScale = height_scale; 511 512 FrameResized(Bounds().Width(), Bounds().Height()); 513 514 printf("VideoFormatChange leave\n"); 515 } 516 517 518 void 519 MainWin::Zoom(BPoint rec_position, float rec_width, float rec_height) 520 { 521 PostMessage(M_TOGGLE_FULLSCREEN); 522 } 523 524 525 void 526 MainWin::FrameResized(float new_width, float new_height) 527 { 528 if (new_width != Bounds().Width() || new_height != Bounds().Height()) { 529 debugger("size wrong\n"); 530 } 531 532 bool no_menu = fNoMenu || fIsFullscreen; 533 bool no_controls = fNoControls || fIsFullscreen; 534 535 printf("FrameResized enter: new_width %.0f, new_height %.0f\n", new_width, new_height); 536 537 int max_video_width = int(new_width) + 1; 538 int max_video_height = int(new_height) + 1 - (no_menu ? 0 : fMenuBarHeight) - (no_controls ? 0 : fControlsHeight); 539 540 ASSERT(max_video_height >= 0); 541 542 int y = 0; 543 544 if (no_menu) { 545 if (!fMenuBar->IsHidden()) 546 fMenuBar->Hide(); 547 } else { 548 // fMenuBar->MoveTo(0, y); 549 fMenuBar->ResizeTo(new_width, fMenuBarHeight - 1); 550 if (fMenuBar->IsHidden()) 551 fMenuBar->Show(); 552 y += fMenuBarHeight; 553 } 554 555 if (max_video_height == 0) { 556 if (!fVideoView->IsHidden()) 557 fVideoView->Hide(); 558 } else { 559 // fVideoView->MoveTo(0, y); 560 // fVideoView->ResizeTo(max_video_width - 1, max_video_height - 1); 561 ResizeVideoView(0, y, max_video_width, max_video_height); 562 if (fVideoView->IsHidden()) 563 fVideoView->Show(); 564 y += max_video_height; 565 } 566 567 if (no_controls) { 568 if (!fControls->IsHidden()) 569 fControls->Hide(); 570 } else { 571 fControls->MoveTo(0, y); 572 fControls->ResizeTo(new_width, fControlsHeight - 1); 573 if (fControls->IsHidden()) 574 fControls->Show(); 575 // y += fControlsHeight; 576 } 577 578 printf("FrameResized leave\n"); 579 } 580 581 582 void 583 MainWin::ShowFileInfo() 584 { 585 } 586 587 588 void 589 MainWin::ResizeVideoView(int x, int y, int width, int height) 590 { 591 printf("ResizeVideoView: %d,%d, width %d, height %d\n", x, y, width, height); 592 593 if (fKeepAspectRatio) { 594 // Keep aspect ratio, place video view inside 595 // the background area (may create black bars). 596 float scaled_width = fSourceWidth * fWidthScale; 597 float scaled_height = fSourceHeight * fHeightScale; 598 float factor = min_c(width / scaled_width, height / scaled_height); 599 int render_width = lround(scaled_width * factor); 600 int render_height = lround(scaled_height * factor); 601 if (render_width > width) 602 render_width = width; 603 if (render_height > height) 604 render_height = height; 605 606 int x_ofs = x + (width - render_width) / 2; 607 int y_ofs = y + (height - render_height) / 2; 608 609 fVideoView->MoveTo(x_ofs, y_ofs); 610 fVideoView->ResizeTo(render_width - 1, render_height - 1); 611 612 } else { 613 fVideoView->MoveTo(x, y); 614 fVideoView->ResizeTo(width - 1, height - 1); 615 } 616 } 617 618 619 void 620 MainWin::ToggleNoBorderNoMenu() 621 { 622 if (!fNoMenu && !fNoBorder && !fNoControls) { 623 PostMessage(M_TOGGLE_NO_MENU); 624 PostMessage(M_TOGGLE_NO_BORDER); 625 PostMessage(M_TOGGLE_NO_CONTROLS); 626 } else { 627 if (!fNoMenu) 628 PostMessage(M_TOGGLE_NO_MENU); 629 if (!fNoBorder) 630 PostMessage(M_TOGGLE_NO_BORDER); 631 if (!fNoControls) 632 PostMessage(M_TOGGLE_NO_CONTROLS); 633 } 634 } 635 636 637 void 638 MainWin::ToggleFullscreen() 639 { 640 printf("ToggleFullscreen enter\n"); 641 642 if (!fHasVideo) { 643 printf("ToggleFullscreen - ignoring, as we don't have a video\n"); 644 return; 645 } 646 647 fIsFullscreen = !fIsFullscreen; 648 649 if (fIsFullscreen) { 650 // switch to fullscreen 651 652 fSavedFrame = Frame(); 653 printf("saving current frame: %d %d %d %d\n", int(fSavedFrame.left), int(fSavedFrame.top), int(fSavedFrame.right), int(fSavedFrame.bottom)); 654 BScreen screen(this); 655 BRect rect(screen.Frame()); 656 657 Hide(); 658 MoveTo(rect.left, rect.top); 659 ResizeTo(rect.Width(), rect.Height()); 660 Show(); 661 662 } else { 663 // switch back from full screen mode 664 665 Hide(); 666 MoveTo(fSavedFrame.left, fSavedFrame.top); 667 ResizeTo(fSavedFrame.Width(), fSavedFrame.Height()); 668 Show(); 669 } 670 671 printf("ToggleFullscreen leave\n"); 672 } 673 674 void 675 MainWin::ToggleNoControls() 676 { 677 printf("ToggleNoControls enter\n"); 678 679 if (fIsFullscreen) { 680 // fullscreen is always without menu 681 printf("ToggleNoControls leave, doing nothing, we are fullscreen\n"); 682 return; 683 } 684 685 fNoControls = !fNoControls; 686 SetWindowSizeLimits(); 687 688 if (fNoControls) { 689 ResizeBy(0, - fControlsHeight); 690 } else { 691 ResizeBy(0, fControlsHeight); 692 } 693 694 printf("ToggleNoControls leave\n"); 695 } 696 697 void 698 MainWin::ToggleNoMenu() 699 { 700 printf("ToggleNoMenu enter\n"); 701 702 if (fIsFullscreen) { 703 // fullscreen is always without menu 704 printf("ToggleNoMenu leave, doing nothing, we are fullscreen\n"); 705 return; 706 } 707 708 fNoMenu = !fNoMenu; 709 SetWindowSizeLimits(); 710 711 if (fNoMenu) { 712 MoveBy(0, fMenuBarHeight); 713 ResizeBy(0, - fMenuBarHeight); 714 } else { 715 MoveBy(0, - fMenuBarHeight); 716 ResizeBy(0, fMenuBarHeight); 717 } 718 719 printf("ToggleNoMenu leave\n"); 720 } 721 722 723 void 724 MainWin::ToggleNoBorder() 725 { 726 printf("ToggleNoBorder enter\n"); 727 fNoBorder = !fNoBorder; 728 SetLook(fNoBorder ? B_BORDERED_WINDOW_LOOK : B_TITLED_WINDOW_LOOK); 729 printf("ToggleNoBorder leave\n"); 730 } 731 732 733 void 734 MainWin::ToggleAlwaysOnTop() 735 { 736 printf("ToggleAlwaysOnTop enter\n"); 737 fAlwaysOnTop = !fAlwaysOnTop; 738 SetFeel(fAlwaysOnTop ? B_FLOATING_ALL_WINDOW_FEEL : B_NORMAL_WINDOW_FEEL); 739 printf("ToggleAlwaysOnTop leave\n"); 740 } 741 742 743 void 744 MainWin::ToggleKeepAspectRatio() 745 { 746 printf("ToggleKeepAspectRatio enter\n"); 747 fKeepAspectRatio = !fKeepAspectRatio; 748 FrameResized(Bounds().Width(), Bounds().Height()); 749 printf("ToggleKeepAspectRatio leave\n"); 750 } 751 752 753 void 754 MainWin::RefsReceived(BMessage *msg) 755 { 756 printf("MainWin::RefsReceived\n"); 757 758 // the playlist ist replaced by dropped files 759 760 fPlaylist->MakeEmpty(); 761 762 entry_ref ref; 763 for (int i = 0; B_OK == msg->FindRef("refs", i, &ref); i++) { 764 BEntry entry(&ref, true); 765 if (!entry.Exists() || !entry.IsFile()) 766 continue; 767 fPlaylist->AddRef(ref); 768 } 769 770 fPlaylist->Sort(); 771 772 // open first file 773 if (fPlaylist->NextRef(&ref) == B_OK) 774 OpenFile(ref); 775 776 } 777 778 779 /* Trap keys that are about to be send to background or renderer view. 780 * Return B_OK if it shouldn't be passed to the view 781 */ 782 status_t 783 MainWin::KeyDown(BMessage *msg) 784 { 785 // msg->PrintToStream(); 786 787 uint32 key = msg->FindInt32("key"); 788 uint32 raw_char = msg->FindInt32("raw_char"); 789 uint32 modifiers = msg->FindInt32("modifiers"); 790 791 printf("key 0x%lx, raw_char 0x%lx, modifiers 0x%lx\n", key, raw_char, modifiers); 792 793 switch (raw_char) { 794 case B_SPACE: 795 PostMessage(M_TOGGLE_NO_BORDER_NO_MENU_NO_CONTROLS); 796 return B_OK; 797 798 case B_ESCAPE: 799 if (fIsFullscreen) { 800 PostMessage(M_TOGGLE_FULLSCREEN); 801 return B_OK; 802 } else 803 break; 804 805 case B_ENTER: // Enter / Return 806 if (modifiers & B_COMMAND_KEY) { 807 PostMessage(M_TOGGLE_FULLSCREEN); 808 return B_OK; 809 } else 810 break; 811 812 case B_TAB: 813 if ((modifiers & (B_COMMAND_KEY | B_CONTROL_KEY | B_OPTION_KEY | B_MENU_KEY)) == 0) { 814 PostMessage(M_TOGGLE_FULLSCREEN); 815 return B_OK; 816 } else 817 break; 818 819 case B_UP_ARROW: 820 if (modifiers & B_COMMAND_KEY) { 821 PostMessage(M_CHANNEL_NEXT); 822 } else { 823 PostMessage(M_VOLUME_UP); 824 } 825 return B_OK; 826 827 case B_DOWN_ARROW: 828 if (modifiers & B_COMMAND_KEY) { 829 PostMessage(M_CHANNEL_PREV); 830 } else { 831 PostMessage(M_VOLUME_DOWN); 832 } 833 return B_OK; 834 835 case B_RIGHT_ARROW: 836 if (modifiers & B_COMMAND_KEY) { 837 PostMessage(M_VOLUME_UP); 838 } else { 839 PostMessage(M_CHANNEL_NEXT); 840 } 841 return B_OK; 842 843 case B_LEFT_ARROW: 844 if (modifiers & B_COMMAND_KEY) { 845 PostMessage(M_VOLUME_DOWN); 846 } else { 847 PostMessage(M_CHANNEL_PREV); 848 } 849 return B_OK; 850 851 case B_PAGE_UP: 852 PostMessage(M_CHANNEL_NEXT); 853 return B_OK; 854 855 case B_PAGE_DOWN: 856 PostMessage(M_CHANNEL_PREV); 857 return B_OK; 858 } 859 860 switch (key) { 861 case 0x3a: // numeric keypad + 862 if ((modifiers & B_COMMAND_KEY) == 0) { 863 printf("if\n"); 864 PostMessage(M_VOLUME_UP); 865 return B_OK; 866 } else { 867 printf("else\n"); 868 break; 869 } 870 871 case 0x25: // numeric keypad - 872 if ((modifiers & B_COMMAND_KEY) == 0) { 873 PostMessage(M_VOLUME_DOWN); 874 return B_OK; 875 } else { 876 break; 877 } 878 879 case 0x38: // numeric keypad up arrow 880 PostMessage(M_VOLUME_UP); 881 return B_OK; 882 883 case 0x59: // numeric keypad down arrow 884 PostMessage(M_VOLUME_DOWN); 885 return B_OK; 886 887 case 0x39: // numeric keypad page up 888 case 0x4a: // numeric keypad right arrow 889 PostMessage(M_CHANNEL_NEXT); 890 return B_OK; 891 892 case 0x5a: // numeric keypad page down 893 case 0x48: // numeric keypad left arrow 894 PostMessage(M_CHANNEL_PREV); 895 return B_OK; 896 } 897 898 return B_ERROR; 899 } 900 901 902 void 903 MainWin::DispatchMessage(BMessage *msg, BHandler *handler) 904 { 905 if ((msg->what == B_MOUSE_DOWN) && (handler == fBackground || handler == fVideoView)) 906 MouseDown(msg); 907 if ((msg->what == B_MOUSE_MOVED) && (handler == fBackground || handler == fVideoView)) 908 MouseMoved(msg); 909 if ((msg->what == B_MOUSE_UP) && (handler == fBackground || handler == fVideoView)) 910 MouseUp(msg); 911 912 if ((msg->what == B_KEY_DOWN) && (handler == fBackground || handler == fVideoView)) { 913 914 // special case for PrintScreen key 915 if (msg->FindInt32("key") == B_PRINT_KEY) { 916 fVideoView->OverlayScreenshotPrepare(); 917 BWindow::DispatchMessage(msg, handler); 918 fVideoView->OverlayScreenshotCleanup(); 919 return; 920 } 921 922 // every other key gets dispatched to our KeyDown first 923 if (KeyDown(msg) == B_OK) { 924 // it got handled, don't pass it on 925 return; 926 } 927 } 928 929 BWindow::DispatchMessage(msg, handler); 930 } 931 932 933 void 934 MainWin::MessageReceived(BMessage *msg) 935 { 936 switch (msg->what) { 937 case B_REFS_RECEIVED: 938 printf("MainWin::MessageReceived: B_REFS_RECEIVED\n"); 939 RefsReceived(msg); 940 break; 941 case B_SIMPLE_DATA: 942 printf("MainWin::MessageReceived: B_SIMPLE_DATA\n"); 943 if (msg->HasRef("refs")) 944 RefsReceived(msg); 945 break; 946 case M_FILE_NEWPLAYER: 947 gMainApp->NewWindow(); 948 break; 949 case M_FILE_OPEN: 950 if (!fFilePanel) { 951 fFilePanel = new BFilePanel(); 952 fFilePanel->SetTarget(BMessenger(0, this)); 953 fFilePanel->SetPanelDirectory("/boot/home/"); 954 } 955 fFilePanel->Show(); 956 break; 957 case M_FILE_INFO: 958 ShowFileInfo(); 959 break; 960 case M_FILE_ABOUT: 961 BAlert *alert; 962 alert = new BAlert("about", NAME"\n\n Written by Marcus Overhagen","Thanks"); 963 if (fAlwaysOnTop) { 964 ToggleAlwaysOnTop(); 965 alert->Go(); 966 ToggleAlwaysOnTop(); 967 } else { 968 alert->Go(); 969 } 970 break; 971 case M_FILE_CLOSE: 972 PostMessage(B_QUIT_REQUESTED); 973 break; 974 case M_FILE_QUIT: 975 be_app->PostMessage(B_QUIT_REQUESTED); 976 break; 977 978 case M_TOGGLE_FULLSCREEN: 979 ToggleFullscreen(); 980 // fSettingsMenu->ItemAt(1)->SetMarked(fIsFullscreen); 981 break; 982 983 case M_TOGGLE_NO_MENU: 984 ToggleNoMenu(); 985 // fSettingsMenu->ItemAt(3)->SetMarked(fNoMenu); 986 break; 987 988 case M_TOGGLE_NO_CONTROLS: 989 ToggleNoControls(); 990 // fSettingsMenu->ItemAt(3)->SetMarked(fNoControls); 991 break; 992 993 case M_TOGGLE_NO_BORDER: 994 ToggleNoBorder(); 995 // fSettingsMenu->ItemAt(4)->SetMarked(fNoBorder); 996 break; 997 998 case M_TOGGLE_ALWAYS_ON_TOP: 999 ToggleAlwaysOnTop(); 1000 // fSettingsMenu->ItemAt(5)->SetMarked(fAlwaysOnTop); 1001 break; 1002 1003 case M_TOGGLE_KEEP_ASPECT_RATIO: 1004 ToggleKeepAspectRatio(); 1005 // fSettingsMenu->ItemAt(6)->SetMarked(fKeepAspectRatio); 1006 break; 1007 1008 case M_TOGGLE_NO_BORDER_NO_MENU_NO_CONTROLS: 1009 ToggleNoBorderNoMenu(); 1010 break; 1011 1012 case M_VIEW_50: 1013 if (!fHasVideo) 1014 break; 1015 if (fIsFullscreen) 1016 ToggleFullscreen(); 1017 ResizeWindow(50); 1018 break; 1019 1020 case M_VIEW_100: 1021 if (!fHasVideo) 1022 break; 1023 if (fIsFullscreen) 1024 ToggleFullscreen(); 1025 ResizeWindow(100); 1026 break; 1027 1028 case M_VIEW_200: 1029 if (!fHasVideo) 1030 break; 1031 if (fIsFullscreen) 1032 ToggleFullscreen(); 1033 ResizeWindow(200); 1034 break; 1035 1036 case M_VIEW_300: 1037 if (!fHasVideo) 1038 break; 1039 if (fIsFullscreen) 1040 ToggleFullscreen(); 1041 ResizeWindow(300); 1042 break; 1043 1044 case M_VIEW_400: 1045 if (!fHasVideo) 1046 break; 1047 if (fIsFullscreen) 1048 ToggleFullscreen(); 1049 ResizeWindow(400); 1050 break; 1051 1052 /* 1053 1054 case B_ACQUIRE_OVERLAY_LOCK: 1055 printf("B_ACQUIRE_OVERLAY_LOCK\n"); 1056 fVideoView->OverlayLockAcquire(); 1057 break; 1058 1059 case B_RELEASE_OVERLAY_LOCK: 1060 printf("B_RELEASE_OVERLAY_LOCK\n"); 1061 fVideoView->OverlayLockRelease(); 1062 break; 1063 1064 case B_MOUSE_WHEEL_CHANGED: 1065 { 1066 printf("B_MOUSE_WHEEL_CHANGED\n"); 1067 float dx = msg->FindFloat("be:wheel_delta_x"); 1068 float dy = msg->FindFloat("be:wheel_delta_y"); 1069 bool inv = modifiers() & B_COMMAND_KEY; 1070 if (dx > 0.1) PostMessage(inv ? M_VOLUME_DOWN : M_CHANNEL_PREV); 1071 if (dx < -0.1) PostMessage(inv ? M_VOLUME_UP : M_CHANNEL_NEXT); 1072 if (dy > 0.1) PostMessage(inv ? M_CHANNEL_PREV : M_VOLUME_DOWN); 1073 if (dy < -0.1) PostMessage(inv ? M_CHANNEL_NEXT : M_VOLUME_UP); 1074 break; 1075 } 1076 1077 case M_CHANNEL_NEXT: 1078 { 1079 printf("M_CHANNEL_NEXT\n"); 1080 int chan = fController->CurrentChannel(); 1081 if (chan != -1) { 1082 chan++; 1083 if (chan < fController->ChannelCount()) 1084 SelectChannel(chan); 1085 } 1086 break; 1087 } 1088 1089 case M_CHANNEL_PREV: 1090 { 1091 printf("M_CHANNEL_PREV\n"); 1092 int chan = fController->CurrentChannel(); 1093 if (chan != -1) { 1094 chan--; 1095 if (chan >= 0) 1096 SelectChannel(chan); 1097 } 1098 break; 1099 } 1100 1101 case M_VOLUME_UP: 1102 printf("M_VOLUME_UP\n"); 1103 fController->VolumeUp(); 1104 break; 1105 1106 case M_VOLUME_DOWN: 1107 printf("M_VOLUME_DOWN\n"); 1108 fController->VolumeDown(); 1109 break; 1110 */ 1111 1112 case M_ASPECT_100000_1: 1113 VideoFormatChange(fSourceWidth, fSourceHeight, 1.0, 1.0); 1114 break; 1115 1116 case M_ASPECT_106666_1: 1117 VideoFormatChange(fSourceWidth, fSourceHeight, 1.06666, 1.0); 1118 break; 1119 1120 case M_ASPECT_109091_1: 1121 VideoFormatChange(fSourceWidth, fSourceHeight, 1.09091, 1.0); 1122 break; 1123 1124 case M_ASPECT_141176_1: 1125 VideoFormatChange(fSourceWidth, fSourceHeight, 1.41176, 1.0); 1126 break; 1127 1128 case M_ASPECT_720_576: 1129 VideoFormatChange(720, 576, 1.06666, 1.0); 1130 break; 1131 1132 case M_ASPECT_704_576: 1133 VideoFormatChange(704, 576, 1.09091, 1.0); 1134 break; 1135 1136 case M_ASPECT_544_576: 1137 VideoFormatChange(544, 576, 1.41176, 1.0); 1138 break; 1139 /* 1140 case M_PREFERENCES: 1141 break; 1142 1143 default: 1144 if (msg->what >= M_SELECT_CHANNEL && msg->what <= M_SELECT_CHANNEL_END) { 1145 SelectChannel(msg->what - M_SELECT_CHANNEL); 1146 break; 1147 } 1148 if (msg->what >= M_SELECT_INTERFACE && msg->what <= M_SELECT_INTERFACE_END) { 1149 SelectInterface(msg->what - M_SELECT_INTERFACE - 1); 1150 break; 1151 } 1152 */ 1153 } 1154 } 1155