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