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 #include "Controller.h" 23 #include "config.h" 24 #include "DeviceRoster.h" 25 26 #include <View.h> 27 #include <Screen.h> 28 #include <Menu.h> 29 #include <MenuBar.h> 30 #include <MenuItem.h> 31 #include <Application.h> 32 #include <Alert.h> 33 #include <stdio.h> 34 #include <string.h> 35 #include <Messenger.h> 36 #include <PopUpMenu.h> 37 #include <String.h> 38 39 enum 40 { 41 M_DUMMY = 0x100, 42 M_CHECK_TB, 43 M_FILE_ABOUT, 44 M_FILE_QUIT, 45 M_SCALE_TO_NATIVE_SIZE, 46 M_TOGGLE_FULLSCREEN, 47 M_TOGGLE_NO_BORDER, 48 M_TOGGLE_NO_MENU, 49 M_TOGGLE_NO_BORDER_NO_MENU, 50 M_TOGGLE_ALWAYS_ON_TOP, 51 M_TOGGLE_KEEP_ASPECT_RATIO, 52 M_PREFERENCES, 53 M_CHANNEL_NEXT, 54 M_CHANNEL_PREV, 55 M_VOLUME_UP, 56 M_VOLUME_DOWN, 57 M_ASPECT_100000_1, 58 M_ASPECT_106666_1, 59 M_ASPECT_109091_1, 60 M_ASPECT_141176_1, 61 M_ASPECT_720_576, 62 M_ASPECT_704_576, 63 M_ASPECT_544_576, 64 M_SELECT_INTERFACE = 0x00000800, 65 M_SELECT_INTERFACE_END = 0x00000fff, 66 M_SELECT_CHANNEL = 0x00010000, 67 M_SELECT_CHANNEL_END = 0x000fffff, // this limits possible channel count to 0xeffff = 983039 68 }; 69 70 //#define printf(a...) 71 72 73 MainWin::MainWin(BRect frame_rect) 74 : BWindow(frame_rect, NAME, B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS /* | B_WILL_ACCEPT_FIRST_CLICK */) 75 , fController(new Controller) 76 , fIsFullscreen(false) 77 , fKeepAspectRatio(true) 78 , fAlwaysOnTop(false) 79 , fNoMenu(false) 80 , fNoBorder(false) 81 , fSourceWidth(720) 82 , fSourceHeight(576) 83 , fWidthScale(1.0) 84 , fHeightScale(1.0) 85 , fMouseDownTracking(false) 86 , fFrameResizedTriggeredAutomatically(false) 87 , fIgnoreFrameResized(false) 88 , fFrameResizedCalled(true) 89 { 90 BRect rect = Bounds(); 91 92 // background 93 fBackground = new BView(rect, "background", B_FOLLOW_ALL, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE); 94 fBackground->SetViewColor(0,0,0); 95 AddChild(fBackground); 96 97 // menu 98 fMenuBar = new BMenuBar(fBackground->Bounds(), "menu"); 99 CreateMenu(); 100 fBackground->AddChild(fMenuBar); 101 fMenuBar->ResizeToPreferred(); 102 fMenuBarHeight = (int)fMenuBar->Frame().Height() + 1; 103 fMenuBar->SetResizingMode(B_FOLLOW_TOP | B_FOLLOW_LEFT_RIGHT); 104 105 // video view 106 BRect video_rect = BRect(0, fMenuBarHeight, rect.right, rect.bottom); 107 fVideoView = new VideoView(video_rect, "video display", B_FOLLOW_ALL, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE); 108 fBackground->AddChild(fVideoView); 109 110 fVideoView->MakeFocus(); 111 112 // SetSizeLimits(fControlViewMinWidth - 1, 32767, 113 // fMenuBarHeight + fControlViewHeight - 1, fMenuBarHeight + fControlViewHeight - 1); 114 115 // SetSizeLimits(320 - 1, 32767, 240 + fMenuBarHeight - 1, 32767); 116 117 SetSizeLimits(0, 32767, fMenuBarHeight - 1, 32767); 118 119 fController->SetVideoView(fVideoView); 120 fController->SetVideoNode(fVideoView->Node()); 121 122 fVideoView->IsOverlaySupported(); 123 124 SetupInterfaceMenu(); 125 SelectInitialInterface(); 126 SetInterfaceMenuMarker(); 127 SetupChannelMenu(); 128 SetChannelMenuMarker(); 129 130 VideoFormatChange(fSourceWidth, fSourceHeight, fWidthScale, fHeightScale); 131 } 132 133 134 MainWin::~MainWin() 135 { 136 printf("MainWin::~MainWin\n"); 137 fController->DisconnectInterface(); 138 delete fController; 139 } 140 141 142 void 143 MainWin::CreateMenu() 144 { 145 fFileMenu = new BMenu(NAME); 146 fChannelMenu = new BMenu("Channel"); 147 fInterfaceMenu = new BMenu("Interface"); 148 fSettingsMenu = new BMenu("Settings"); 149 fDebugMenu = new BMenu("Debug"); 150 151 fMenuBar->AddItem(fFileMenu); 152 fMenuBar->AddItem(fChannelMenu); 153 fMenuBar->AddItem(fInterfaceMenu); 154 fMenuBar->AddItem(fSettingsMenu); 155 fMenuBar->AddItem(fDebugMenu); 156 157 fFileMenu->AddItem(new BMenuItem("About", new BMessage(M_FILE_ABOUT), 'A', B_COMMAND_KEY)); 158 fFileMenu->AddSeparatorItem(); 159 fFileMenu->AddItem(new BMenuItem("Quit", new BMessage(M_FILE_QUIT), 'Q', B_COMMAND_KEY)); 160 161 162 fSettingsMenu->AddItem(new BMenuItem("Scale to native size", new BMessage(M_SCALE_TO_NATIVE_SIZE), 'N', B_COMMAND_KEY)); 163 fSettingsMenu->AddItem(new BMenuItem("Full Screen", new BMessage(M_TOGGLE_FULLSCREEN), 'F', B_COMMAND_KEY)); 164 fSettingsMenu->AddSeparatorItem(); 165 fSettingsMenu->AddItem(new BMenuItem("No Menu", new BMessage(M_TOGGLE_NO_MENU), 'M', B_COMMAND_KEY)); 166 fSettingsMenu->AddItem(new BMenuItem("No Border", new BMessage(M_TOGGLE_NO_BORDER), 'B', B_COMMAND_KEY)); 167 fSettingsMenu->AddItem(new BMenuItem("Always on Top", new BMessage(M_TOGGLE_ALWAYS_ON_TOP), 'T', B_COMMAND_KEY)); 168 fSettingsMenu->AddItem(new BMenuItem("Keep Aspect Ratio", new BMessage(M_TOGGLE_KEEP_ASPECT_RATIO), 'K', B_COMMAND_KEY)); 169 fSettingsMenu->AddSeparatorItem(); 170 fSettingsMenu->AddItem(new BMenuItem("Preferences"B_UTF8_ELLIPSIS, new BMessage(M_PREFERENCES), 'P', B_COMMAND_KEY)); 171 172 fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.00000:1", new BMessage(M_ASPECT_100000_1))); 173 fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.06666:1", new BMessage(M_ASPECT_106666_1))); 174 fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.09091:1", new BMessage(M_ASPECT_109091_1))); 175 fDebugMenu->AddItem(new BMenuItem("pixel aspect ratio 1.41176:1", new BMessage(M_ASPECT_141176_1))); 176 fDebugMenu->AddItem(new BMenuItem("force 720 x 576, display aspect 4:3", new BMessage(M_ASPECT_720_576))); 177 fDebugMenu->AddItem(new BMenuItem("force 704 x 576, display aspect 4:3", new BMessage(M_ASPECT_704_576))); 178 fDebugMenu->AddItem(new BMenuItem("force 544 x 576, display aspect 4:3", new BMessage(M_ASPECT_544_576))); 179 180 fSettingsMenu->ItemAt(1)->SetMarked(fIsFullscreen); 181 fSettingsMenu->ItemAt(3)->SetMarked(fNoMenu); 182 fSettingsMenu->ItemAt(4)->SetMarked(fNoBorder); 183 fSettingsMenu->ItemAt(5)->SetMarked(fAlwaysOnTop); 184 fSettingsMenu->ItemAt(6)->SetMarked(fKeepAspectRatio); 185 fSettingsMenu->ItemAt(8)->SetEnabled(false); // XXX disable unused preference menu 186 } 187 188 189 190 bool 191 MainWin::QuitRequested() 192 { 193 be_app->PostMessage(B_QUIT_REQUESTED); 194 return true; 195 } 196 197 198 void 199 MainWin::MouseDown(BMessage *msg) 200 { 201 BPoint screen_where; 202 uint32 buttons = msg->FindInt32("buttons"); 203 204 // On Zeta, only "screen_where" is relyable, "where" and "be:view_where" seem to be broken 205 if (B_OK != msg->FindPoint("screen_where", &screen_where)) { 206 // Workaround for BeOS R5, it has no "screen_where" 207 fVideoView->GetMouse(&screen_where, &buttons, false); 208 fVideoView->ConvertToScreen(&screen_where); 209 } 210 211 // msg->PrintToStream(); 212 213 // if (1 == msg->FindInt32("buttons") && msg->FindInt32("clicks") == 1) { 214 215 if (1 == buttons && msg->FindInt32("clicks") % 2 == 0) { 216 BRect r(screen_where.x - 1, screen_where.y - 1, screen_where.x + 1, screen_where.y + 1); 217 if (r.Contains(fMouseDownMousePos)) { 218 PostMessage(M_TOGGLE_FULLSCREEN); 219 return; 220 } 221 } 222 223 if (2 == buttons && msg->FindInt32("clicks") % 2 == 0) { 224 BRect r(screen_where.x - 1, screen_where.y - 1, screen_where.x + 1, screen_where.y + 1); 225 if (r.Contains(fMouseDownMousePos)) { 226 PostMessage(M_TOGGLE_NO_BORDER_NO_MENU); 227 return; 228 } 229 } 230 231 /* 232 // very broken in Zeta: 233 fMouseDownMousePos = fVideoView->ConvertToScreen(msg->FindPoint("where")); 234 */ 235 fMouseDownMousePos = screen_where; 236 fMouseDownWindowPos = Frame().LeftTop(); 237 238 if (buttons == 1 && !fIsFullscreen) { 239 // start mouse tracking 240 fVideoView->SetMouseEventMask(B_POINTER_EVENTS | B_NO_POINTER_HISTORY /* | B_LOCK_WINDOW_FOCUS */); 241 fMouseDownTracking = true; 242 } 243 244 // pop up a context menu if right mouse button is down for 200 ms 245 246 if ((buttons & 2) == 0) 247 return; 248 bigtime_t start = system_time(); 249 bigtime_t delay = 200000; 250 BPoint location; 251 do { 252 fVideoView->GetMouse(&location, &buttons); 253 if ((buttons & 2) == 0) 254 break; 255 snooze(1000); 256 } while (system_time() - start < delay); 257 258 if (buttons & 2) 259 ShowContextMenu(screen_where); 260 } 261 262 263 void 264 MainWin::MouseMoved(BMessage *msg) 265 { 266 // msg->PrintToStream(); 267 268 BPoint mousePos; 269 uint32 buttons = msg->FindInt32("buttons"); 270 271 if (1 == buttons && fMouseDownTracking && !fIsFullscreen) { 272 /* 273 // very broken in Zeta: 274 BPoint mousePos = msg->FindPoint("where"); 275 printf("view where: %.0f, %.0f => ", mousePos.x, mousePos.y); 276 fVideoView->ConvertToScreen(&mousePos); 277 */ 278 // On Zeta, only "screen_where" is relyable, "where" and "be:view_where" seem to be broken 279 if (B_OK != msg->FindPoint("screen_where", &mousePos)) { 280 // Workaround for BeOS R5, it has no "screen_where" 281 fVideoView->GetMouse(&mousePos, &buttons, false); 282 fVideoView->ConvertToScreen(&mousePos); 283 } 284 // printf("screen where: %.0f, %.0f => ", mousePos.x, mousePos.y); 285 float delta_x = mousePos.x - fMouseDownMousePos.x; 286 float delta_y = mousePos.y - fMouseDownMousePos.y; 287 float x = fMouseDownWindowPos.x + delta_x; 288 float y = fMouseDownWindowPos.y + delta_y; 289 // printf("move window to %.0f, %.0f\n", x, y); 290 MoveTo(x, y); 291 } 292 } 293 294 295 void 296 MainWin::MouseUp(BMessage *msg) 297 { 298 // msg->PrintToStream(); 299 fMouseDownTracking = false; 300 } 301 302 303 void 304 MainWin::ShowContextMenu(const BPoint &screen_point) 305 { 306 printf("Show context menu\n"); 307 BPopUpMenu *menu = new BPopUpMenu("context menu", false, false); 308 BMenuItem *item; 309 menu->AddItem(new BMenuItem("Scale to native size", new BMessage(M_SCALE_TO_NATIVE_SIZE), 'N', B_COMMAND_KEY)); 310 menu->AddItem(item = new BMenuItem("Full Screen", new BMessage(M_TOGGLE_FULLSCREEN), 'F', B_COMMAND_KEY)); 311 item->SetMarked(fIsFullscreen); 312 menu->AddSeparatorItem(); 313 menu->AddItem(item = new BMenuItem("No Menu", new BMessage(M_TOGGLE_NO_MENU), 'M', B_COMMAND_KEY)); 314 item->SetMarked(fNoMenu); 315 menu->AddItem(item = new BMenuItem("No Border", new BMessage(M_TOGGLE_NO_BORDER), 'B', B_COMMAND_KEY)); 316 item->SetMarked(fNoBorder); 317 menu->AddItem(item = new BMenuItem("Always on Top", new BMessage(M_TOGGLE_ALWAYS_ON_TOP), 'T', B_COMMAND_KEY)); 318 item->SetMarked(fAlwaysOnTop); 319 menu->AddItem(item = new BMenuItem("Keep Aspect Ratio", new BMessage(M_TOGGLE_KEEP_ASPECT_RATIO), 'K', B_COMMAND_KEY)); 320 item->SetMarked(fKeepAspectRatio); 321 menu->AddSeparatorItem(); 322 menu->AddItem(new BMenuItem("About", new BMessage(M_FILE_ABOUT), 'A', B_COMMAND_KEY)); 323 menu->AddSeparatorItem(); 324 menu->AddItem(new BMenuItem("Quit", new BMessage(M_FILE_QUIT), 'Q', B_COMMAND_KEY)); 325 326 menu->AddSeparatorItem(); 327 menu->AddItem(new BMenuItem("pixel aspect ratio 1.00000:1", new BMessage(M_ASPECT_100000_1))); 328 menu->AddItem(new BMenuItem("pixel aspect ratio 1.06666:1", new BMessage(M_ASPECT_106666_1))); 329 menu->AddItem(new BMenuItem("pixel aspect ratio 1.09091:1", new BMessage(M_ASPECT_109091_1))); 330 menu->AddItem(new BMenuItem("pixel aspect ratio 1.41176:1", new BMessage(M_ASPECT_141176_1))); 331 menu->AddItem(new BMenuItem("force 720 x 576, display aspect 4:3", new BMessage(M_ASPECT_720_576))); 332 menu->AddItem(new BMenuItem("force 704 x 576, display aspect 4:3", new BMessage(M_ASPECT_704_576))); 333 menu->AddItem(new BMenuItem("force 544 x 576, display aspect 4:3", new BMessage(M_ASPECT_544_576))); 334 335 menu->SetTargetForItems(this); 336 BRect r(screen_point.x - 5, screen_point.y - 5, screen_point.x + 5, screen_point.y + 5); 337 menu->Go(screen_point, true, true, r, true); 338 } 339 340 341 void 342 MainWin::VideoFormatChange(int width, int height, float width_scale, float height_scale) 343 { 344 // called when video format or aspect ratio changes 345 346 printf("VideoFormatChange enter: width %d, height %d, width_scale %.6f, height_scale %.6f\n", width, height, width_scale, height_scale); 347 348 if (width_scale < 1.0 && height_scale >= 1.0) { 349 width_scale = 1.0 / width_scale; 350 height_scale = 1.0 / height_scale; 351 printf("inverting! new values: width_scale %.6f, height_scale %.6f\n", width_scale, height_scale); 352 } 353 354 fSourceWidth = width; 355 fSourceHeight = height; 356 fWidthScale = width_scale; 357 fHeightScale = height_scale; 358 359 // ResizeWindow(Bounds().Width() + 1, Bounds().Height() + 1, true); 360 361 if (fIsFullscreen) { 362 AdjustFullscreenRenderer(); 363 } else { 364 AdjustWindowedRenderer(false); 365 } 366 367 printf("VideoFormatChange leave\n"); 368 369 } 370 371 372 void 373 MainWin::Zoom(BPoint rec_position, float rec_width, float rec_height) 374 { 375 PostMessage(M_TOGGLE_FULLSCREEN); 376 } 377 378 379 void 380 MainWin::FrameResized(float new_width, float new_height) 381 { 382 // called when the window got resized 383 fFrameResizedCalled = true; 384 385 if (new_width != Bounds().Width() || new_height != Bounds().Height()) { 386 debugger("size wrong\n"); 387 } 388 389 390 printf("FrameResized enter: new_width %.0f, new_height %.0f, bounds width %.0f, bounds height %.0f\n", new_width, new_height, Bounds().Width(), Bounds().Height()); 391 392 if (fIsFullscreen) { 393 394 printf("FrameResized in fullscreen mode\n"); 395 396 fIgnoreFrameResized = false; 397 AdjustFullscreenRenderer(); 398 399 } else { 400 401 if (fFrameResizedTriggeredAutomatically) { 402 fFrameResizedTriggeredAutomatically = false; 403 printf("FrameResized triggered automatically\n"); 404 405 fIgnoreFrameResized = false; 406 407 AdjustWindowedRenderer(false); 408 } else { 409 printf("FrameResized by user in window mode\n"); 410 411 if (fIgnoreFrameResized) { 412 fIgnoreFrameResized = false; 413 printf("FrameResized ignored\n"); 414 return; 415 } 416 417 AdjustWindowedRenderer(true); 418 } 419 420 } 421 422 printf("FrameResized leave\n"); 423 } 424 425 426 427 void 428 MainWin::UpdateWindowTitle() 429 { 430 char buf[100]; 431 sprintf(buf, "%s - %d x %d, %.3f:%.3f => %.0f x %.0f", NAME, fSourceWidth, fSourceHeight, fWidthScale, fHeightScale, fVideoView->Bounds().Width() + 1, fVideoView->Bounds().Height() + 1); 432 SetTitle(buf); 433 } 434 435 436 void 437 MainWin::AdjustFullscreenRenderer() 438 { 439 // n.b. we don't have a menu in fullscreen mode! 440 441 if (fKeepAspectRatio) { 442 443 // Keep aspect ratio, place render inside 444 // the background area (may create black bars). 445 float max_width = fBackground->Bounds().Width() + 1.0f; 446 float max_height = fBackground->Bounds().Height() + 1.0f; 447 float scaled_width = fSourceWidth * fWidthScale; 448 float scaled_height = fSourceHeight * fHeightScale; 449 float factor = min_c(max_width / scaled_width, max_height / scaled_height); 450 int render_width = int(scaled_width * factor); 451 int render_height = int(scaled_height * factor); 452 int x_ofs = (int(max_width) - render_width) / 2; 453 int y_ofs = (int(max_height) - render_height) / 2; 454 455 printf("AdjustFullscreenRenderer: background %.1f x %.1f, src video %d x %d, " 456 "scaled video %.3f x %.3f, factor %.3f, render %d x %d, x-ofs %d, y-ofs %d\n", 457 max_width, max_height, fSourceWidth, fSourceHeight, scaled_width, scaled_height, 458 factor, render_width, render_height, x_ofs, y_ofs); 459 460 fVideoView->MoveTo(x_ofs, y_ofs); 461 fVideoView->ResizeTo(render_width - 1, render_height - 1); 462 463 } else { 464 465 printf("AdjustFullscreenRenderer: using whole background area\n"); 466 467 // no need to keep aspect ratio, make 468 // render cover the whole background 469 fVideoView->MoveTo(0, 0); 470 fVideoView->ResizeTo(fBackground->Bounds().Width(), fBackground->Bounds().Height()); 471 472 } 473 } 474 475 476 void 477 MainWin::AdjustWindowedRenderer(bool user_resized) 478 { 479 printf("AdjustWindowedRenderer enter - user_resized %d\n", user_resized); 480 481 // In windowed mode, the renderer always covers the 482 // whole background, accounting for the menu 483 fVideoView->MoveTo(0, fNoMenu ? 0 : fMenuBarHeight); 484 fVideoView->ResizeTo(fBackground->Bounds().Width(), fBackground->Bounds().Height() - (fNoMenu ? 0 : fMenuBarHeight)); 485 486 if (fKeepAspectRatio) { 487 // To keep the aspect ratio correct, we 488 // do resize the window as required 489 490 float max_width = Bounds().Width() + 1.0f; 491 float max_height = Bounds().Height() + 1.0f - (fNoMenu ? 0 : fMenuBarHeight); 492 float scaled_width = fSourceWidth * fWidthScale; 493 float scaled_height = fSourceHeight * fHeightScale; 494 495 if (!user_resized && (scaled_width > max_width || scaled_height > max_height)) { 496 // A format switch occured, and the window was 497 // smaller then the video source. As it was not 498 // initiated by the user resizing the window, we 499 // enlarge the window to fit the video. 500 fIgnoreFrameResized = true; 501 ResizeTo(scaled_width - 1, scaled_height - 1 + (fNoMenu ? 0 : fMenuBarHeight)); 502 // Sync(); 503 return; 504 } 505 506 float display_aspect_ratio = scaled_width / scaled_height; 507 int new_width = int(max_width); 508 int new_height = int(max_width / display_aspect_ratio + 0.5); 509 510 printf("AdjustWindowedRenderer: old display %d x %d, src video %d x %d, " 511 "scaled video %.3f x %.3f, aspect ratio %.3f, new display %d x %d\n", 512 int(max_width), int(max_height), fSourceWidth, fSourceHeight, scaled_width, scaled_height, 513 display_aspect_ratio, new_width, new_height); 514 515 fIgnoreFrameResized = true; 516 ResizeTo(new_width - 1, new_height - 1 + (fNoMenu ? 0 : fMenuBarHeight)); 517 // Sync(); 518 } 519 520 printf("AdjustWindowedRenderer leave\n"); 521 } 522 523 524 void 525 MainWin::ToggleNoBorderNoMenu() 526 { 527 if (!fNoMenu && fNoBorder) { 528 // if no border, switch of menu, too 529 PostMessage(M_TOGGLE_NO_MENU); 530 } else 531 if (fNoMenu && !fNoBorder) { 532 // if no menu, switch of border, too 533 PostMessage(M_TOGGLE_NO_BORDER); 534 } else { 535 // both are either on or off, toggle both 536 PostMessage(M_TOGGLE_NO_MENU); 537 PostMessage(M_TOGGLE_NO_BORDER); 538 } 539 } 540 541 542 void 543 MainWin::ToggleFullscreen() 544 { 545 printf("ToggleFullscreen enter\n"); 546 547 if (!fFrameResizedCalled) { 548 printf("ToggleFullscreen - ignoring, as FrameResized wasn't called since last switch\n"); 549 return; 550 } 551 fFrameResizedCalled = false; 552 553 554 fIsFullscreen = !fIsFullscreen; 555 556 if (fIsFullscreen) { 557 // switch to fullscreen 558 559 fSavedFrame = Frame(); 560 printf("saving current frame: %d %d %d %d\n", int(fSavedFrame.left), int(fSavedFrame.top), int(fSavedFrame.right), int(fSavedFrame.bottom)); 561 BScreen screen(this); 562 BRect rect(screen.Frame()); 563 564 Hide(); 565 if (!fNoMenu) { 566 // if we have a menu, remove it now 567 fMenuBar->Hide(); 568 } 569 fFrameResizedTriggeredAutomatically = true; 570 MoveTo(rect.left, rect.top); 571 ResizeTo(rect.Width(), rect.Height()); 572 Show(); 573 574 } else { 575 // switch back from full screen mode 576 577 Hide(); 578 // if we need a menu, show it now 579 if (!fNoMenu) { 580 fMenuBar->Show(); 581 } 582 fFrameResizedTriggeredAutomatically = true; 583 MoveTo(fSavedFrame.left, fSavedFrame.top); 584 ResizeTo(fSavedFrame.Width(), fSavedFrame.Height()); 585 Show(); 586 587 } 588 589 // FrameResized() will do the required adjustments 590 591 printf("ToggleFullscreen leave\n"); 592 } 593 594 595 void 596 MainWin::ToggleNoMenu() 597 { 598 printf("ToggleNoMenu enter\n"); 599 600 fNoMenu = !fNoMenu; 601 602 if (fIsFullscreen) { 603 // fullscreen is always without menu 604 printf("ToggleNoMenu leave, doing nothing, we are fullscreen\n"); 605 return; 606 } 607 608 // fFrameResizedTriggeredAutomatically = true; 609 fIgnoreFrameResized = true; 610 611 if (fNoMenu) { 612 fMenuBar->Hide(); 613 fVideoView->MoveTo(0, 0); 614 fVideoView->ResizeBy(0, fMenuBarHeight); 615 MoveBy(0, fMenuBarHeight); 616 ResizeBy(0, - fMenuBarHeight); 617 // Sync(); 618 } else { 619 fMenuBar->Show(); 620 fVideoView->MoveTo(0, fMenuBarHeight); 621 fVideoView->ResizeBy(0, -fMenuBarHeight); 622 MoveBy(0, - fMenuBarHeight); 623 ResizeBy(0, fMenuBarHeight); 624 // Sync(); 625 } 626 627 printf("ToggleNoMenu leave\n"); 628 } 629 630 631 void 632 MainWin::ToggleNoBorder() 633 { 634 printf("ToggleNoBorder enter\n"); 635 fNoBorder = !fNoBorder; 636 // SetLook(fNoBorder ? B_NO_BORDER_WINDOW_LOOK : B_TITLED_WINDOW_LOOK); 637 SetLook(fNoBorder ? B_BORDERED_WINDOW_LOOK : B_TITLED_WINDOW_LOOK); 638 printf("ToggleNoBorder leave\n"); 639 } 640 641 642 void 643 MainWin::ToggleAlwaysOnTop() 644 { 645 printf("ToggleAlwaysOnTop enter\n"); 646 fAlwaysOnTop = !fAlwaysOnTop; 647 SetFeel(fAlwaysOnTop ? B_FLOATING_ALL_WINDOW_FEEL : B_NORMAL_WINDOW_FEEL); 648 printf("ToggleAlwaysOnTop leave\n"); 649 } 650 651 652 void 653 MainWin::ToggleKeepAspectRatio() 654 { 655 printf("ToggleKeepAspectRatio enter\n"); 656 fKeepAspectRatio = !fKeepAspectRatio; 657 658 fFrameResizedTriggeredAutomatically = true; 659 FrameResized(Bounds().Width(), Bounds().Height()); 660 // if (fIsFullscreen) { 661 // AdjustFullscreenRenderer(); 662 // } else { 663 // AdjustWindowedRenderer(false); 664 // } 665 printf("ToggleKeepAspectRatio leave\n"); 666 } 667 668 669 /* Trap keys that are about to be send to background or renderer view. 670 * Return B_OK if it shouldn't be passed to the view 671 */ 672 status_t 673 MainWin::KeyDown(BMessage *msg) 674 { 675 // msg->PrintToStream(); 676 677 uint32 key = msg->FindInt32("key"); 678 uint32 raw_char = msg->FindInt32("raw_char"); 679 uint32 modifiers = msg->FindInt32("modifiers"); 680 681 printf("key 0x%lx, raw_char 0x%lx, modifiers 0x%lx\n", key, raw_char, modifiers); 682 683 switch (raw_char) { 684 case B_SPACE: 685 PostMessage(M_TOGGLE_NO_BORDER_NO_MENU); 686 return B_OK; 687 688 case B_ESCAPE: 689 if (fIsFullscreen) { 690 PostMessage(M_TOGGLE_FULLSCREEN); 691 return B_OK; 692 } else 693 break; 694 695 case B_ENTER: // Enter / Return 696 if (modifiers & B_COMMAND_KEY) { 697 PostMessage(M_TOGGLE_FULLSCREEN); 698 return B_OK; 699 } else 700 break; 701 702 case B_TAB: 703 if ((modifiers & (B_COMMAND_KEY | B_CONTROL_KEY | B_OPTION_KEY | B_MENU_KEY)) == 0) { 704 PostMessage(M_TOGGLE_FULLSCREEN); 705 return B_OK; 706 } else 707 break; 708 709 case B_UP_ARROW: 710 if (modifiers & B_COMMAND_KEY) { 711 PostMessage(M_CHANNEL_NEXT); 712 } else { 713 PostMessage(M_VOLUME_UP); 714 } 715 return B_OK; 716 717 case B_DOWN_ARROW: 718 if (modifiers & B_COMMAND_KEY) { 719 PostMessage(M_CHANNEL_PREV); 720 } else { 721 PostMessage(M_VOLUME_DOWN); 722 } 723 return B_OK; 724 725 case B_RIGHT_ARROW: 726 if (modifiers & B_COMMAND_KEY) { 727 PostMessage(M_VOLUME_UP); 728 } else { 729 PostMessage(M_CHANNEL_NEXT); 730 } 731 return B_OK; 732 733 case B_LEFT_ARROW: 734 if (modifiers & B_COMMAND_KEY) { 735 PostMessage(M_VOLUME_DOWN); 736 } else { 737 PostMessage(M_CHANNEL_PREV); 738 } 739 return B_OK; 740 741 case B_PAGE_UP: 742 PostMessage(M_CHANNEL_NEXT); 743 return B_OK; 744 745 case B_PAGE_DOWN: 746 PostMessage(M_CHANNEL_PREV); 747 return B_OK; 748 } 749 750 switch (key) { 751 case 0x3a: // numeric keypad + 752 if ((modifiers & B_COMMAND_KEY) == 0) { 753 printf("if\n"); 754 PostMessage(M_VOLUME_UP); 755 return B_OK; 756 } else { 757 printf("else\n"); 758 break; 759 } 760 761 case 0x25: // numeric keypad - 762 if ((modifiers & B_COMMAND_KEY) == 0) { 763 PostMessage(M_VOLUME_DOWN); 764 return B_OK; 765 } else { 766 break; 767 } 768 769 case 0x38: // numeric keypad up arrow 770 PostMessage(M_VOLUME_UP); 771 return B_OK; 772 773 case 0x59: // numeric keypad down arrow 774 PostMessage(M_VOLUME_DOWN); 775 return B_OK; 776 777 case 0x39: // numeric keypad page up 778 case 0x4a: // numeric keypad right arrow 779 PostMessage(M_CHANNEL_NEXT); 780 return B_OK; 781 782 case 0x5a: // numeric keypad page down 783 case 0x48: // numeric keypad left arrow 784 PostMessage(M_CHANNEL_PREV); 785 return B_OK; 786 } 787 788 return B_ERROR; 789 } 790 791 792 void 793 MainWin::DispatchMessage(BMessage *msg, BHandler *handler) 794 { 795 if ((msg->what == B_MOUSE_DOWN) && (handler == fBackground || handler == fVideoView)) 796 MouseDown(msg); 797 if ((msg->what == B_MOUSE_MOVED) && (handler == fBackground || handler == fVideoView)) 798 MouseMoved(msg); 799 if ((msg->what == B_MOUSE_UP) && (handler == fBackground || handler == fVideoView)) 800 MouseUp(msg); 801 802 if ((msg->what == B_KEY_DOWN) && (handler == fBackground || handler == fVideoView)) { 803 804 // special case for PrintScreen key 805 if (msg->FindInt32("key") == B_PRINT_KEY) { 806 fVideoView->OverlayScreenshotPrepare(); 807 BWindow::DispatchMessage(msg, handler); 808 fVideoView->OverlayScreenshotCleanup(); 809 return; 810 } 811 812 // every other key gets dispatched to our KeyDown first 813 if (KeyDown(msg) == B_OK) { 814 // it got handled, don't pass it on 815 return; 816 } 817 } 818 819 BWindow::DispatchMessage(msg, handler); 820 } 821 822 823 void 824 MainWin::MessageReceived(BMessage *msg) 825 { 826 switch (msg->what) { 827 case B_ACQUIRE_OVERLAY_LOCK: 828 printf("B_ACQUIRE_OVERLAY_LOCK\n"); 829 fVideoView->OverlayLockAcquire(); 830 break; 831 832 case B_RELEASE_OVERLAY_LOCK: 833 printf("B_RELEASE_OVERLAY_LOCK\n"); 834 fVideoView->OverlayLockRelease(); 835 break; 836 837 case B_MOUSE_WHEEL_CHANGED: 838 { 839 printf("B_MOUSE_WHEEL_CHANGED\n"); 840 float dx = msg->FindFloat("be:wheel_delta_x"); 841 float dy = msg->FindFloat("be:wheel_delta_y"); 842 bool inv = modifiers() & B_COMMAND_KEY; 843 if (dx > 0.1) PostMessage(inv ? M_VOLUME_DOWN : M_CHANNEL_PREV); 844 if (dx < -0.1) PostMessage(inv ? M_VOLUME_UP : M_CHANNEL_NEXT); 845 if (dy > 0.1) PostMessage(inv ? M_CHANNEL_PREV : M_VOLUME_DOWN); 846 if (dy < -0.1) PostMessage(inv ? M_CHANNEL_NEXT : M_VOLUME_UP); 847 break; 848 } 849 850 case M_CHANNEL_NEXT: 851 { 852 printf("M_CHANNEL_NEXT\n"); 853 int chan = fController->CurrentChannel(); 854 if (chan != -1) { 855 chan++; 856 if (chan < fController->ChannelCount()) 857 SelectChannel(chan); 858 } 859 break; 860 } 861 862 case M_CHANNEL_PREV: 863 { 864 printf("M_CHANNEL_PREV\n"); 865 int chan = fController->CurrentChannel(); 866 if (chan != -1) { 867 chan--; 868 if (chan >= 0) 869 SelectChannel(chan); 870 } 871 break; 872 } 873 874 case M_VOLUME_UP: 875 printf("M_VOLUME_UP\n"); 876 fController->VolumeUp(); 877 break; 878 879 case M_VOLUME_DOWN: 880 printf("M_VOLUME_DOWN\n"); 881 fController->VolumeDown(); 882 break; 883 884 case M_ASPECT_100000_1: 885 VideoFormatChange(fSourceWidth, fSourceHeight, 1.0, 1.0); 886 break; 887 888 case M_ASPECT_106666_1: 889 VideoFormatChange(fSourceWidth, fSourceHeight, 1.06666, 1.0); 890 break; 891 892 case M_ASPECT_109091_1: 893 VideoFormatChange(fSourceWidth, fSourceHeight, 1.09091, 1.0); 894 break; 895 896 case M_ASPECT_141176_1: 897 VideoFormatChange(fSourceWidth, fSourceHeight, 1.41176, 1.0); 898 break; 899 900 case M_ASPECT_720_576: 901 VideoFormatChange(720, 576, 1.06666, 1.0); 902 break; 903 904 case M_ASPECT_704_576: 905 VideoFormatChange(704, 576, 1.09091, 1.0); 906 break; 907 908 case M_ASPECT_544_576: 909 VideoFormatChange(544, 576, 1.41176, 1.0); 910 break; 911 912 case B_REFS_RECEIVED: 913 printf("MainWin::MessageReceived: B_REFS_RECEIVED\n"); 914 // RefsReceived(msg); 915 break; 916 917 case B_SIMPLE_DATA: 918 printf("MainWin::MessageReceived: B_SIMPLE_DATA\n"); 919 // if (msg->HasRef("refs")) 920 // RefsReceived(msg); 921 break; 922 923 case M_FILE_ABOUT: 924 BAlert *alert; 925 alert = new BAlert("about", NAME"\n\n" 926 INFO1 927 "\n\nCopyright "COPYRIGHT"\n\nVersion "VERSION"\n\nRevision "REVISION"\n\nBuild "BUILD, "Thanks"); 928 if (fAlwaysOnTop) { 929 ToggleAlwaysOnTop(); 930 alert->Go(); 931 ToggleAlwaysOnTop(); 932 } else { 933 alert->Go(); 934 } 935 break; 936 937 case M_FILE_QUIT: 938 // be_app->PostMessage(B_QUIT_REQUESTED); 939 PostMessage(B_QUIT_REQUESTED); 940 break; 941 942 case M_SCALE_TO_NATIVE_SIZE: 943 printf("M_SCALE_TO_NATIVE_SIZE\n"); 944 if (fIsFullscreen) { 945 ToggleFullscreen(); 946 } 947 ResizeTo(int(fSourceWidth * fWidthScale), 948 int(fSourceHeight * fHeightScale) + (fNoMenu ? 0 : fMenuBarHeight)); 949 // Sync(); 950 break; 951 952 case M_TOGGLE_FULLSCREEN: 953 ToggleFullscreen(); 954 fSettingsMenu->ItemAt(1)->SetMarked(fIsFullscreen); 955 break; 956 957 case M_TOGGLE_NO_MENU: 958 ToggleNoMenu(); 959 fSettingsMenu->ItemAt(3)->SetMarked(fNoMenu); 960 break; 961 962 case M_TOGGLE_NO_BORDER: 963 ToggleNoBorder(); 964 fSettingsMenu->ItemAt(4)->SetMarked(fNoBorder); 965 break; 966 967 case M_TOGGLE_ALWAYS_ON_TOP: 968 ToggleAlwaysOnTop(); 969 fSettingsMenu->ItemAt(5)->SetMarked(fAlwaysOnTop); 970 break; 971 972 case M_TOGGLE_KEEP_ASPECT_RATIO: 973 ToggleKeepAspectRatio(); 974 fSettingsMenu->ItemAt(6)->SetMarked(fKeepAspectRatio); 975 break; 976 977 case M_TOGGLE_NO_BORDER_NO_MENU: 978 ToggleNoBorderNoMenu(); 979 break; 980 981 case M_PREFERENCES: 982 break; 983 984 default: 985 if (msg->what >= M_SELECT_CHANNEL && msg->what <= M_SELECT_CHANNEL_END) { 986 SelectChannel(msg->what - M_SELECT_CHANNEL); 987 break; 988 } 989 if (msg->what >= M_SELECT_INTERFACE && msg->what <= M_SELECT_INTERFACE_END) { 990 SelectInterface(msg->what - M_SELECT_INTERFACE - 1); 991 break; 992 } 993 } 994 } 995