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