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