2 * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify,
8 * merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
27 #include "Controller.h"
29 #include "DeviceRoster.h"
34 #include <Application.h>
39 #include <Messenger.h>
40 #include <PopUpMenu.h>
46 #undef B_TRANSLATION_CONTEXT
47 #define B_TRANSLATION_CONTEXT "MainWin"
49 B_TRANSLATE_MARK_VOID("TV");
50 B_TRANSLATE_MARK_VOID("unknown");
51 B_TRANSLATE_MARK_VOID("DVB - Digital Video Broadcasting TV");
57 M_SCALE_TO_NATIVE_SIZE
,
61 M_TOGGLE_NO_BORDER_NO_MENU
,
62 M_TOGGLE_ALWAYS_ON_TOP
,
63 M_TOGGLE_KEEP_ASPECT_RATIO
,
76 M_SELECT_INTERFACE
= 0x00000800,
77 M_SELECT_INTERFACE_END
= 0x00000fff,
78 M_SELECT_CHANNEL
= 0x00010000,
79 M_SELECT_CHANNEL_END
= 0x000fffff,
80 // this limits possible channel count to 0xeffff = 983039
83 //#define printf(a...)
86 MainWin::MainWin(BRect frame_rect
)
88 BWindow(frame_rect
, B_TRANSLATE_SYSTEM_NAME(NAME
), B_TITLED_WINDOW
,
89 B_ASYNCHRONOUS_CONTROLS
/* | B_WILL_ACCEPT_FIRST_CLICK */)
90 , fController(new Controller
)
91 , fIsFullscreen(false)
92 , fKeepAspectRatio(true)
100 , fMouseDownTracking(false)
101 , fFrameResizedTriggeredAutomatically(false)
102 , fIgnoreFrameResized(false)
103 , fFrameResizedCalled(true)
105 BRect rect
= Bounds();
108 fBackground
= new BView(rect
, "background", B_FOLLOW_ALL
,
109 B_WILL_DRAW
| B_FULL_UPDATE_ON_RESIZE
);
110 fBackground
->SetViewColor(0,0,0);
111 AddChild(fBackground
);
114 fMenuBar
= new BMenuBar(fBackground
->Bounds(), "menu");
116 fBackground
->AddChild(fMenuBar
);
117 fMenuBar
->ResizeToPreferred();
118 fMenuBarHeight
= (int)fMenuBar
->Frame().Height() + 1;
119 fMenuBar
->SetResizingMode(B_FOLLOW_TOP
| B_FOLLOW_LEFT_RIGHT
);
122 BRect video_rect
= BRect(0, fMenuBarHeight
, rect
.right
, rect
.bottom
);
123 fVideoView
= new VideoView(video_rect
, "video display", B_FOLLOW_ALL
,
124 B_WILL_DRAW
| B_FULL_UPDATE_ON_RESIZE
);
125 fBackground
->AddChild(fVideoView
);
127 fVideoView
->MakeFocus();
129 // SetSizeLimits(fControlViewMinWidth - 1, 32767,
130 // fMenuBarHeight + fControlViewHeight - 1, fMenuBarHeight
131 // + fControlViewHeight - 1);
133 // SetSizeLimits(320 - 1, 32767, 240 + fMenuBarHeight - 1, 32767);
135 SetSizeLimits(0, 32767, fMenuBarHeight
- 1, 32767);
137 fController
->SetVideoView(fVideoView
);
138 fController
->SetVideoNode(fVideoView
->Node());
140 fVideoView
->IsOverlaySupported();
142 SetupInterfaceMenu();
143 SelectInitialInterface();
144 SetInterfaceMenuMarker();
146 SetChannelMenuMarker();
148 VideoFormatChange(fSourceWidth
, fSourceHeight
, fWidthScale
, fHeightScale
);
156 printf("MainWin::~MainWin\n");
157 fController
->DisconnectInterface();
163 MainWin::CreateMenu()
165 fFileMenu
= new BMenu(B_TRANSLATE(NAME
));
166 fChannelMenu
= new BMenu(B_TRANSLATE("Channel"));
167 fInterfaceMenu
= new BMenu(B_TRANSLATE("Interface"));
168 fSettingsMenu
= new BMenu(B_TRANSLATE("Settings"));
169 fDebugMenu
= new BMenu(B_TRANSLATE("Debug"));
171 fMenuBar
->AddItem(fFileMenu
);
172 fMenuBar
->AddItem(fChannelMenu
);
173 fMenuBar
->AddItem(fInterfaceMenu
);
174 fMenuBar
->AddItem(fSettingsMenu
);
175 fMenuBar
->AddItem(fDebugMenu
);
177 fFileMenu
->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
178 new BMessage(M_FILE_QUIT
), 'Q', B_COMMAND_KEY
));
181 fChannelMenu->AddItem(new BMenuItem(B_TRANSLATE("Next channel"),
182 new BMessage(M_CHANNEL_NEXT), '+', B_COMMAND_KEY));
183 fChannelMenu->AddItem(new BMenuItem(B_TRANSLATE("Previous channel"),
184 new BMessage(M_CHANNEL_PREV), '-', B_COMMAND_KEY));
185 fChannelMenu->AddSeparatorItem();
186 fChannelMenu->AddItem(new BMenuItem("RTL", new BMessage(M_DUMMY), '0',
188 fChannelMenu->AddItem(new BMenuItem("Pro7", new BMessage(M_DUMMY), '1',
191 fInterfaceMenu->AddItem(new BMenuItem(B_TRANSLATE("none"),
192 new BMessage(M_DUMMY)));
193 fInterfaceMenu->AddItem(new BMenuItem(B_TRANSLATE("none 1"),
194 new BMessage(M_DUMMY)));
195 fInterfaceMenu->AddItem(new BMenuItem(B_TRANSLATE("none 2"),
196 new BMessage(M_DUMMY)));
199 fSettingsMenu
->AddItem(new BMenuItem(B_TRANSLATE("Scale to native size"),
200 new BMessage(M_SCALE_TO_NATIVE_SIZE
), 'N', B_COMMAND_KEY
));
201 fSettingsMenu
->AddItem(new BMenuItem(B_TRANSLATE("Full screen"),
202 new BMessage(M_TOGGLE_FULLSCREEN
), 'F', B_COMMAND_KEY
));
203 fSettingsMenu
->AddSeparatorItem();
204 fSettingsMenu
->AddItem(new BMenuItem(B_TRANSLATE("No menu"),
205 new BMessage(M_TOGGLE_NO_MENU
), 'M', B_COMMAND_KEY
));
206 fSettingsMenu
->AddItem(new BMenuItem(B_TRANSLATE("No border"),
207 new BMessage(M_TOGGLE_NO_BORDER
), 'B', B_COMMAND_KEY
));
208 fSettingsMenu
->AddItem(new BMenuItem(B_TRANSLATE("Always on top"),
209 new BMessage(M_TOGGLE_ALWAYS_ON_TOP
), 'T', B_COMMAND_KEY
));
210 fSettingsMenu
->AddItem(new BMenuItem(B_TRANSLATE("Keep aspect ratio"),
211 new BMessage(M_TOGGLE_KEEP_ASPECT_RATIO
), 'K', B_COMMAND_KEY
));
212 fSettingsMenu
->AddSeparatorItem();
213 fSettingsMenu
->AddItem(new BMenuItem(B_TRANSLATE("Settings" B_UTF8_ELLIPSIS
)
214 , new BMessage(M_PREFERENCES
), 'P', B_COMMAND_KEY
));
216 const char* pixel_ratio
= B_TRANSLATE("pixel aspect ratio");
217 BString str1
= pixel_ratio
;
218 str1
<< " 1.00000:1";
219 fDebugMenu
->AddItem(new BMenuItem(str1
.String(),
220 new BMessage(M_ASPECT_100000_1
)));
221 BString str2
= pixel_ratio
;
222 str2
<< " 1.06666:1";
223 fDebugMenu
->AddItem(new BMenuItem(str2
.String(),
224 new BMessage(M_ASPECT_106666_1
)));
225 BString str3
= pixel_ratio
;
226 str3
<< " 1.09091:1";
227 fDebugMenu
->AddItem(new BMenuItem(str3
.String(),
228 new BMessage(M_ASPECT_109091_1
)));
229 BString str4
= pixel_ratio
;
230 str4
<< " 1.41176:1";
231 fDebugMenu
->AddItem(new BMenuItem(str4
.String(),
232 new BMessage(M_ASPECT_141176_1
)));
233 fDebugMenu
->AddItem(new BMenuItem(B_TRANSLATE(
234 "force 720 x 576, display aspect 4:3"),
235 new BMessage(M_ASPECT_720_576
)));
236 fDebugMenu
->AddItem(new BMenuItem(B_TRANSLATE(
237 "force 704 x 576, display aspect 4:3"),
238 new BMessage(M_ASPECT_704_576
)));
239 fDebugMenu
->AddItem(new BMenuItem(B_TRANSLATE(
240 "force 544 x 576, display aspect 4:3"),
241 new BMessage(M_ASPECT_544_576
)));
243 fSettingsMenu
->ItemAt(1)->SetMarked(fIsFullscreen
);
244 fSettingsMenu
->ItemAt(3)->SetMarked(fNoMenu
);
245 fSettingsMenu
->ItemAt(4)->SetMarked(fNoBorder
);
246 fSettingsMenu
->ItemAt(5)->SetMarked(fAlwaysOnTop
);
247 fSettingsMenu
->ItemAt(6)->SetMarked(fKeepAspectRatio
);
248 fSettingsMenu
->ItemAt(8)->SetEnabled(false);
249 // XXX disable unused preference menu
254 MainWin::SetupInterfaceMenu()
256 fInterfaceMenu
->RemoveItems(0, fInterfaceMenu
->CountItems(), true);
258 fInterfaceMenu
->AddItem(new BMenuItem(B_TRANSLATE("None"),
259 new BMessage(M_SELECT_INTERFACE
)));
261 int count
= gDeviceRoster
->DeviceCount();
264 fInterfaceMenu
->AddSeparatorItem();
266 for (int i
= 0; i
< count
; i
++) {
267 // 1 gets subtracted in MessageReceived, so -1 is Interface None,
268 // and 0 == Interface 0 in SelectInterface()
269 fInterfaceMenu
->AddItem(new BMenuItem(gDeviceRoster
->DeviceName(i
),
270 new BMessage(M_SELECT_INTERFACE
+ i
+ 1)));
276 MainWin::SetupChannelMenu()
278 fChannelMenu
->RemoveItems(0, fChannelMenu
->CountItems(), true);
280 int interface
= fController
->CurrentInterface();
281 printf("MainWin::SetupChannelMenu: interface %d\n", interface
);
283 int channels
= fController
->ChannelCount();
286 fChannelMenu
->AddItem(new BMenuItem(B_TRANSLATE("None"),
287 new BMessage(M_DUMMY
)));
289 fChannelMenu
->AddItem(new BMenuItem(B_TRANSLATE("Next channel"),
290 new BMessage(M_CHANNEL_NEXT
), '+', B_COMMAND_KEY
));
291 fChannelMenu
->AddItem(new BMenuItem(B_TRANSLATE("Previous channel"),
292 new BMessage(M_CHANNEL_PREV
), '-', B_COMMAND_KEY
));
293 fChannelMenu
->AddSeparatorItem();
296 for (int i
= 0; i
< channels
; i
++) {
298 string
.SetToFormat("%s%d %s", (i
< 9) ? " " : "", i
+ 1,
299 fController
->ChannelName(i
));
300 fChannelMenu
->AddItem(new BMenuItem(string
,
301 new BMessage(M_SELECT_CHANNEL
+ i
)));
307 MainWin::SetInterfaceMenuMarker()
311 int interface
= fController
->CurrentInterface();
312 printf("MainWin::SetInterfaceMenuMarker: interface %d\n", interface
);
315 item
= fInterfaceMenu
->FindMarked();
317 item
->SetMarked(false);
320 int index
= (interface
< 0) ? 0 : interface
+ 2;
321 item
= fInterfaceMenu
->ItemAt(index
);
323 item
->SetMarked(true);
328 MainWin::SetChannelMenuMarker()
332 int channel
= fController
->CurrentChannel();
333 printf("MainWin::SetChannelMenuMarker: channel %d\n", channel
);
336 item
= fChannelMenu
->FindMarked();
338 item
->SetMarked(false);
341 int index
= (channel
< 0) ? 0 : channel
+ 3;
342 item
= fChannelMenu
->ItemAt(index
);
344 item
->SetMarked(true);
349 MainWin::SelectChannel(int i
)
351 printf("MainWin::SelectChannel %d\n", i
);
353 if (B_OK
!= fController
->SelectChannel(i
))
356 SetChannelMenuMarker();
361 MainWin::SelectInterface(int i
)
363 printf("MainWin::SelectInterface %d\n", i
);
364 printf(" CurrentInterface %d\n", fController
->CurrentInterface());
365 printf(" CurrentChannel %d\n", fController
->CurrentChannel());
367 // i = -1 means "None"
370 fController
->DisconnectInterface();
374 if (!fController
->IsInterfaceAvailable(i
)) {
376 s
<< B_TRANSLATE("Error, interface is busy:\n\n");
377 s
<< gDeviceRoster
->DeviceName(i
);
378 BAlert
* alert
= new BAlert("error", s
.String(), B_TRANSLATE("OK"));
379 alert
->SetFlags(alert
->Flags() | B_CLOSE_ON_ESCAPE
);
384 fController
->DisconnectInterface();
385 if (fController
->ConnectInterface(i
) != B_OK
) {
387 s
<< B_TRANSLATE("Error, connecting to interface failed:\n\n");
388 s
<< gDeviceRoster
->DeviceName(i
);
389 BAlert
* alert
= new BAlert("error", s
.String(), B_TRANSLATE("OK"));
390 alert
->SetFlags(alert
->Flags() | B_CLOSE_ON_ESCAPE
);
395 printf("MainWin::SelectInterface done:\n");
396 printf(" CurrentInterface %d\n", fController
->CurrentInterface());
397 printf(" CurrentChannel %d\n", fController
->CurrentChannel());
399 SetInterfaceMenuMarker();
401 SetChannelMenuMarker();
406 MainWin::SelectInitialInterface()
408 printf("MainWin::SelectInitialInterface enter\n");
410 int count
= gDeviceRoster
->DeviceCount();
411 for (int i
= 0; i
< count
; i
++) {
412 if (fController
->IsInterfaceAvailable(i
)
413 && B_OK
== fController
->ConnectInterface(i
)) {
414 printf("MainWin::SelectInitialInterface connected to interface "
420 printf("MainWin::SelectInitialInterface leave\n");
425 MainWin::QuitRequested()
427 be_app
->PostMessage(B_QUIT_REQUESTED
);
433 MainWin::MouseDown(BMessage
*msg
)
436 uint32 buttons
= msg
->FindInt32("buttons");
438 // On Zeta, only "screen_where" is relyable, "where" and "be:view_where"
440 if (B_OK
!= msg
->FindPoint("screen_where", &screen_where
)) {
441 // Workaround for BeOS R5, it has no "screen_where"
442 fVideoView
->GetMouse(&screen_where
, &buttons
, false);
443 fVideoView
->ConvertToScreen(&screen_where
);
446 // msg->PrintToStream();
448 // if (1 == msg->FindInt32("buttons") && msg->FindInt32("clicks") == 1) {
450 if (1 == buttons
&& msg
->FindInt32("clicks") % 2 == 0) {
451 BRect
r(screen_where
.x
- 1, screen_where
.y
- 1, screen_where
.x
+ 1,
453 if (r
.Contains(fMouseDownMousePos
)) {
454 PostMessage(M_TOGGLE_FULLSCREEN
);
459 if (2 == buttons
&& msg
->FindInt32("clicks") % 2 == 0) {
460 BRect
r(screen_where
.x
- 1, screen_where
.y
- 1, screen_where
.x
+ 1,
462 if (r
.Contains(fMouseDownMousePos
)) {
463 PostMessage(M_TOGGLE_NO_BORDER_NO_MENU
);
469 // very broken in Zeta:
470 fMouseDownMousePos = fVideoView->ConvertToScreen(
471 msg->FindPoint("where"));
473 fMouseDownMousePos
= screen_where
;
474 fMouseDownWindowPos
= Frame().LeftTop();
476 if (buttons
== 1 && !fIsFullscreen
) {
477 // start mouse tracking
478 fVideoView
->SetMouseEventMask(B_POINTER_EVENTS
| B_NO_POINTER_HISTORY
479 /* | B_LOCK_WINDOW_FOCUS */);
480 fMouseDownTracking
= true;
483 // pop up a context menu if right mouse button is down for 200 ms
485 if ((buttons
& 2) == 0)
487 bigtime_t start
= system_time();
488 bigtime_t delay
= 200000;
491 fVideoView
->GetMouse(&location
, &buttons
);
492 if ((buttons
& 2) == 0)
495 } while (system_time() - start
< delay
);
498 ShowContextMenu(screen_where
);
503 MainWin::MouseMoved(BMessage
*msg
)
505 // msg->PrintToStream();
508 uint32 buttons
= msg
->FindInt32("buttons");
510 if (1 == buttons
&& fMouseDownTracking
&& !fIsFullscreen
) {
512 // very broken in Zeta:
513 BPoint mousePos = msg->FindPoint("where");
514 printf("view where: %.0f, %.0f => ", mousePos.x, mousePos.y);
515 fVideoView->ConvertToScreen(&mousePos);
517 // On Zeta, only "screen_where" is relyable, "where" and
518 // "be:view_where" seem to be broken
519 if (B_OK
!= msg
->FindPoint("screen_where", &mousePos
)) {
520 // Workaround for BeOS R5, it has no "screen_where"
521 fVideoView
->GetMouse(&mousePos
, &buttons
, false);
522 fVideoView
->ConvertToScreen(&mousePos
);
524 // printf("screen where: %.0f, %.0f => ", mousePos.x, mousePos.y);
525 float delta_x
= mousePos
.x
- fMouseDownMousePos
.x
;
526 float delta_y
= mousePos
.y
- fMouseDownMousePos
.y
;
527 float x
= fMouseDownWindowPos
.x
+ delta_x
;
528 float y
= fMouseDownWindowPos
.y
+ delta_y
;
529 // printf("move window to %.0f, %.0f\n", x, y);
536 MainWin::MouseUp(BMessage
*msg
)
538 // msg->PrintToStream();
539 fMouseDownTracking
= false;
544 MainWin::ShowContextMenu(const BPoint
&screen_point
)
546 printf("Show context menu\n");
547 BPopUpMenu
*menu
= new BPopUpMenu("context menu", false, false);
549 menu
->AddItem(new BMenuItem(B_TRANSLATE("Scale to native size"),
550 new BMessage(M_SCALE_TO_NATIVE_SIZE
), 'N', B_COMMAND_KEY
));
551 menu
->AddItem(item
= new BMenuItem(B_TRANSLATE("Full screen"),
552 new BMessage(M_TOGGLE_FULLSCREEN
), 'F', B_COMMAND_KEY
));
553 item
->SetMarked(fIsFullscreen
);
554 menu
->AddSeparatorItem();
555 menu
->AddItem(item
= new BMenuItem(B_TRANSLATE("No menu"),
556 new BMessage(M_TOGGLE_NO_MENU
), 'M', B_COMMAND_KEY
));
557 item
->SetMarked(fNoMenu
);
558 menu
->AddItem(item
= new BMenuItem(B_TRANSLATE("No border"),
559 new BMessage(M_TOGGLE_NO_BORDER
), 'B', B_COMMAND_KEY
));
560 item
->SetMarked(fNoBorder
);
561 menu
->AddItem(item
= new BMenuItem(B_TRANSLATE("Always on top"),
562 new BMessage(M_TOGGLE_ALWAYS_ON_TOP
), 'T', B_COMMAND_KEY
));
563 item
->SetMarked(fAlwaysOnTop
);
564 menu
->AddItem(item
= new BMenuItem(B_TRANSLATE("Keep aspect ratio"),
565 new BMessage(M_TOGGLE_KEEP_ASPECT_RATIO
), 'K', B_COMMAND_KEY
));
566 item
->SetMarked(fKeepAspectRatio
);
567 menu
->AddSeparatorItem();
568 menu
->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
569 new BMessage(M_FILE_QUIT
), 'Q', B_COMMAND_KEY
));
571 menu
->AddSeparatorItem();
572 const char* pixel_aspect
= "pixel aspect ratio";
573 BString str1
= pixel_aspect
;
574 str1
<< " 1.00000:1";
575 menu
->AddItem(new BMenuItem(str1
.String(),
576 new BMessage(M_ASPECT_100000_1
)));
577 BString str2
= pixel_aspect
;
578 str2
<< " 1.06666:1";
579 menu
->AddItem(new BMenuItem(str2
.String(),
580 new BMessage(M_ASPECT_106666_1
)));
581 BString str3
= pixel_aspect
;
582 str3
<< " 1.09091:1";
583 menu
->AddItem(new BMenuItem(str3
.String(),
584 new BMessage(M_ASPECT_109091_1
)));
585 BString str4
= pixel_aspect
;
586 str4
<< " 1.41176:1";
587 menu
->AddItem(new BMenuItem(str4
.String(),
588 new BMessage(M_ASPECT_141176_1
)));
589 menu
->AddItem(new BMenuItem(B_TRANSLATE(
590 "force 720 x 576, display aspect 4:3"),
591 new BMessage(M_ASPECT_720_576
)));
592 menu
->AddItem(new BMenuItem(B_TRANSLATE(
593 "force 704 x 576, display aspect 4:3"),
594 new BMessage(M_ASPECT_704_576
)));
595 menu
->AddItem(new BMenuItem(B_TRANSLATE(
596 "force 544 x 576, display aspect 4:3"),
597 new BMessage(M_ASPECT_544_576
)));
599 menu
->SetTargetForItems(this);
600 BRect
r(screen_point
.x
- 5, screen_point
.y
- 5, screen_point
.x
+ 5,
602 menu
->Go(screen_point
, true, true, r
, true);
607 MainWin::VideoFormatChange(int width
, int height
, float width_scale
,
610 // called when video format or aspect ratio changes
612 printf("VideoFormatChange enter: width %d, height %d, width_scale %.6f, "
613 "height_scale %.6f\n", width
, height
, width_scale
, height_scale
);
615 if (width_scale
< 1.0 && height_scale
>= 1.0) {
616 width_scale
= 1.0 / width_scale
;
617 height_scale
= 1.0 / height_scale
;
618 printf("inverting! new values: width_scale %.6f, height_scale %.6f\n",
619 width_scale
, height_scale
);
622 fSourceWidth
= width
;
623 fSourceHeight
= height
;
624 fWidthScale
= width_scale
;
625 fHeightScale
= height_scale
;
627 // ResizeWindow(Bounds().Width() + 1, Bounds().Height() + 1, true);
630 AdjustFullscreenRenderer();
632 AdjustWindowedRenderer(false);
635 printf("VideoFormatChange leave\n");
641 MainWin::Zoom(BPoint rec_position
, float rec_width
, float rec_height
)
643 PostMessage(M_TOGGLE_FULLSCREEN
);
648 MainWin::FrameResized(float new_width
, float new_height
)
650 // called when the window got resized
651 fFrameResizedCalled
= true;
653 if (new_width
!= Bounds().Width() || new_height
!= Bounds().Height()) {
654 debugger("size wrong\n");
658 printf("FrameResized enter: new_width %.0f, new_height %.0f, bounds width "
659 "%.0f, bounds height %.0f\n", new_width
, new_height
, Bounds().Width(),
664 printf("FrameResized in fullscreen mode\n");
666 fIgnoreFrameResized
= false;
667 AdjustFullscreenRenderer();
671 if (fFrameResizedTriggeredAutomatically
) {
672 fFrameResizedTriggeredAutomatically
= false;
673 printf("FrameResized triggered automatically\n");
675 fIgnoreFrameResized
= false;
677 AdjustWindowedRenderer(false);
679 printf("FrameResized by user in window mode\n");
681 if (fIgnoreFrameResized
) {
682 fIgnoreFrameResized
= false;
683 printf("FrameResized ignored\n");
687 AdjustWindowedRenderer(true);
692 printf("FrameResized leave\n");
698 MainWin::UpdateWindowTitle()
701 title
.SetToFormat("%s - %d x %d, %.3f:%.3f => %.0f x %.0f",
702 B_TRANSLATE_SYSTEM_NAME(NAME
),
703 fSourceWidth
, fSourceHeight
, fWidthScale
, fHeightScale
,
704 fVideoView
->Bounds().Width() + 1, fVideoView
->Bounds().Height() + 1);
710 MainWin::AdjustFullscreenRenderer()
712 // n.b. we don't have a menu in fullscreen mode!
714 if (fKeepAspectRatio
) {
716 // Keep aspect ratio, place render inside
717 // the background area (may create black bars).
718 float max_width
= fBackground
->Bounds().Width() + 1.0f
;
719 float max_height
= fBackground
->Bounds().Height() + 1.0f
;
720 float scaled_width
= fSourceWidth
* fWidthScale
;
721 float scaled_height
= fSourceHeight
* fHeightScale
;
722 float factor
= min_c(max_width
/ scaled_width
, max_height
724 int render_width
= int(scaled_width
* factor
);
725 int render_height
= int(scaled_height
* factor
);
726 int x_ofs
= (int(max_width
) - render_width
) / 2;
727 int y_ofs
= (int(max_height
) - render_height
) / 2;
729 printf("AdjustFullscreenRenderer: background %.1f x %.1f, src video "
730 "%d x %d, scaled video %.3f x %.3f, factor %.3f, render %d x %d, "
731 "x-ofs %d, y-ofs %d\n", max_width
, max_height
, fSourceWidth
,
732 fSourceHeight
, scaled_width
, scaled_height
, factor
, render_width
,
733 render_height
, x_ofs
, y_ofs
);
735 fVideoView
->MoveTo(x_ofs
, y_ofs
);
736 fVideoView
->ResizeTo(render_width
- 1, render_height
- 1);
740 printf("AdjustFullscreenRenderer: using whole background area\n");
742 // no need to keep aspect ratio, make
743 // render cover the whole background
744 fVideoView
->MoveTo(0, 0);
745 fVideoView
->ResizeTo(fBackground
->Bounds().Width(),
746 fBackground
->Bounds().Height());
753 MainWin::AdjustWindowedRenderer(bool user_resized
)
755 printf("AdjustWindowedRenderer enter - user_resized %d\n", user_resized
);
757 // In windowed mode, the renderer always covers the
758 // whole background, accounting for the menu
759 fVideoView
->MoveTo(0, fNoMenu
? 0 : fMenuBarHeight
);
760 fVideoView
->ResizeTo(fBackground
->Bounds().Width(),
761 fBackground
->Bounds().Height() - (fNoMenu
? 0 : fMenuBarHeight
));
763 if (fKeepAspectRatio
) {
764 // To keep the aspect ratio correct, we
765 // do resize the window as required
767 float max_width
= Bounds().Width() + 1.0f
;
768 float max_height
= Bounds().Height() + 1.0f
- (fNoMenu
? 0
770 float scaled_width
= fSourceWidth
* fWidthScale
;
771 float scaled_height
= fSourceHeight
* fHeightScale
;
773 if (!user_resized
&& (scaled_width
> max_width
774 || scaled_height
> max_height
)) {
775 // A format switch occured, and the window was
776 // smaller then the video source. As it was not
777 // initiated by the user resizing the window, we
778 // enlarge the window to fit the video.
779 fIgnoreFrameResized
= true;
780 ResizeTo(scaled_width
- 1, scaled_height
- 1
781 + (fNoMenu
? 0 : fMenuBarHeight
));
786 float display_aspect_ratio
= scaled_width
/ scaled_height
;
787 int new_width
= int(max_width
);
788 int new_height
= int(max_width
/ display_aspect_ratio
+ 0.5);
790 printf("AdjustWindowedRenderer: old display %d x %d, src video "
791 "%d x %d, scaled video %.3f x %.3f, aspect ratio %.3f, new "
792 "display %d x %d\n", int(max_width
), int(max_height
),
793 fSourceWidth
, fSourceHeight
, scaled_width
, scaled_height
,
794 display_aspect_ratio
, new_width
, new_height
);
796 fIgnoreFrameResized
= true;
797 ResizeTo(new_width
- 1, new_height
- 1 + (fNoMenu
? 0
802 printf("AdjustWindowedRenderer leave\n");
807 MainWin::ToggleNoBorderNoMenu()
809 if (!fNoMenu
&& fNoBorder
) {
810 // if no border, switch of menu, too
811 PostMessage(M_TOGGLE_NO_MENU
);
813 if (fNoMenu
&& !fNoBorder
) {
814 // if no menu, switch of border, too
815 PostMessage(M_TOGGLE_NO_BORDER
);
817 // both are either on or off, toggle both
818 PostMessage(M_TOGGLE_NO_MENU
);
819 PostMessage(M_TOGGLE_NO_BORDER
);
825 MainWin::ToggleFullscreen()
827 printf("ToggleFullscreen enter\n");
829 if (!fFrameResizedCalled
) {
830 printf("ToggleFullscreen - ignoring, as FrameResized wasn't called "
831 "since last switch\n");
834 fFrameResizedCalled
= false;
837 fIsFullscreen
= !fIsFullscreen
;
840 // switch to fullscreen
842 // Sync here is probably not required
845 fSavedFrame
= Frame();
846 printf("saving current frame: %d %d %d %d\n", int(fSavedFrame
.left
),
847 int(fSavedFrame
.top
), int(fSavedFrame
.right
),
848 int(fSavedFrame
.bottom
));
849 BScreen
screen(this);
850 BRect
rect(screen
.Frame());
854 // if we have a menu, remove it now
857 fFrameResizedTriggeredAutomatically
= true;
858 MoveTo(rect
.left
, rect
.top
);
859 ResizeTo(rect
.Width(), rect
.Height());
865 // switch back from full screen mode
868 // if we need a menu, show it now
872 fFrameResizedTriggeredAutomatically
= true;
873 MoveTo(fSavedFrame
.left
, fSavedFrame
.top
);
874 ResizeTo(fSavedFrame
.Width(), fSavedFrame
.Height());
877 // We *must* make sure that the window is at
878 // the correct position before continuing, or
879 // rapid fullscreen switching by holding down
880 // the TAB key will expose strange bugs.
881 // Never remove this Sync!
885 // FrameResized() will do the required adjustments
887 printf("ToggleFullscreen leave\n");
892 MainWin::ToggleNoMenu()
894 printf("ToggleNoMenu enter\n");
899 // fullscreen is always without menu
900 printf("ToggleNoMenu leave, doing nothing, we are fullscreen\n");
904 // fFrameResizedTriggeredAutomatically = true;
905 fIgnoreFrameResized
= true;
909 fVideoView
->MoveTo(0, 0);
910 fVideoView
->ResizeBy(0, fMenuBarHeight
);
911 MoveBy(0, fMenuBarHeight
);
912 ResizeBy(0, - fMenuBarHeight
);
916 fVideoView
->MoveTo(0, fMenuBarHeight
);
917 fVideoView
->ResizeBy(0, -fMenuBarHeight
);
918 MoveBy(0, - fMenuBarHeight
);
919 ResizeBy(0, fMenuBarHeight
);
923 printf("ToggleNoMenu leave\n");
928 MainWin::ToggleNoBorder()
930 printf("ToggleNoBorder enter\n");
931 fNoBorder
= !fNoBorder
;
932 // SetLook(fNoBorder ? B_NO_BORDER_WINDOW_LOOK : B_TITLED_WINDOW_LOOK);
933 SetLook(fNoBorder
? B_BORDERED_WINDOW_LOOK
: B_TITLED_WINDOW_LOOK
);
934 printf("ToggleNoBorder leave\n");
939 MainWin::ToggleAlwaysOnTop()
941 printf("ToggleAlwaysOnTop enter\n");
942 fAlwaysOnTop
= !fAlwaysOnTop
;
943 SetFeel(fAlwaysOnTop
? B_FLOATING_ALL_WINDOW_FEEL
: B_NORMAL_WINDOW_FEEL
);
944 printf("ToggleAlwaysOnTop leave\n");
949 MainWin::ToggleKeepAspectRatio()
951 printf("ToggleKeepAspectRatio enter\n");
952 fKeepAspectRatio
= !fKeepAspectRatio
;
954 fFrameResizedTriggeredAutomatically
= true;
955 FrameResized(Bounds().Width(), Bounds().Height());
956 // if (fIsFullscreen) {
957 // AdjustFullscreenRenderer();
959 // AdjustWindowedRenderer(false);
961 printf("ToggleKeepAspectRatio leave\n");
965 /* Trap keys that are about to be send to background or renderer view.
966 * Return B_OK if it shouldn't be passed to the view
969 MainWin::KeyDown(BMessage
*msg
)
971 // msg->PrintToStream();
973 uint32 key
= msg
->FindInt32("key");
974 uint32 raw_char
= msg
->FindInt32("raw_char");
975 uint32 modifiers
= msg
->FindInt32("modifiers");
977 printf("key 0x%" B_PRIx32
", raw_char 0x%" B_PRIx32
", modifiers 0x%" B_PRIx32
"\n", key
, raw_char
,
982 PostMessage(M_TOGGLE_NO_BORDER_NO_MENU
);
987 PostMessage(M_TOGGLE_FULLSCREEN
);
992 case B_ENTER
: // Enter / Return
993 if (modifiers
& B_COMMAND_KEY
) {
994 PostMessage(M_TOGGLE_FULLSCREEN
);
1000 if ((modifiers
& (B_COMMAND_KEY
| B_CONTROL_KEY
| B_OPTION_KEY
1001 | B_MENU_KEY
)) == 0) {
1002 PostMessage(M_TOGGLE_FULLSCREEN
);
1008 if (modifiers
& B_COMMAND_KEY
) {
1009 PostMessage(M_CHANNEL_NEXT
);
1011 PostMessage(M_VOLUME_UP
);
1016 if (modifiers
& B_COMMAND_KEY
) {
1017 PostMessage(M_CHANNEL_PREV
);
1019 PostMessage(M_VOLUME_DOWN
);
1024 if (modifiers
& B_COMMAND_KEY
) {
1025 PostMessage(M_VOLUME_UP
);
1027 PostMessage(M_CHANNEL_NEXT
);
1032 if (modifiers
& B_COMMAND_KEY
) {
1033 PostMessage(M_VOLUME_DOWN
);
1035 PostMessage(M_CHANNEL_PREV
);
1040 PostMessage(M_CHANNEL_NEXT
);
1044 PostMessage(M_CHANNEL_PREV
);
1049 case 0x3a: // numeric keypad +
1050 if ((modifiers
& B_COMMAND_KEY
) == 0) {
1052 PostMessage(M_VOLUME_UP
);
1059 case 0x25: // numeric keypad -
1060 if ((modifiers
& B_COMMAND_KEY
) == 0) {
1061 PostMessage(M_VOLUME_DOWN
);
1067 case 0x38: // numeric keypad up arrow
1068 PostMessage(M_VOLUME_UP
);
1071 case 0x59: // numeric keypad down arrow
1072 PostMessage(M_VOLUME_DOWN
);
1075 case 0x39: // numeric keypad page up
1076 case 0x4a: // numeric keypad right arrow
1077 PostMessage(M_CHANNEL_NEXT
);
1080 case 0x5a: // numeric keypad page down
1081 case 0x48: // numeric keypad left arrow
1082 PostMessage(M_CHANNEL_PREV
);
1091 MainWin::DispatchMessage(BMessage
*msg
, BHandler
*handler
)
1093 if ((msg
->what
== B_MOUSE_DOWN
) && (handler
== fBackground
1094 || handler
== fVideoView
))
1096 if ((msg
->what
== B_MOUSE_MOVED
) && (handler
== fBackground
1097 || handler
== fVideoView
))
1099 if ((msg
->what
== B_MOUSE_UP
) && (handler
== fBackground
1100 || handler
== fVideoView
))
1103 if ((msg
->what
== B_KEY_DOWN
) && (handler
== fBackground
1104 || handler
== fVideoView
)) {
1106 // special case for PrintScreen key
1107 if (msg
->FindInt32("key") == B_PRINT_KEY
) {
1108 fVideoView
->OverlayScreenshotPrepare();
1109 BWindow::DispatchMessage(msg
, handler
);
1110 fVideoView
->OverlayScreenshotCleanup();
1114 // every other key gets dispatched to our KeyDown first
1115 if (KeyDown(msg
) == B_OK
) {
1116 // it got handled, don't pass it on
1121 BWindow::DispatchMessage(msg
, handler
);
1126 MainWin::MessageReceived(BMessage
*msg
)
1128 switch (msg
->what
) {
1129 case B_ACQUIRE_OVERLAY_LOCK
:
1130 printf("B_ACQUIRE_OVERLAY_LOCK\n");
1131 fVideoView
->OverlayLockAcquire();
1134 case B_RELEASE_OVERLAY_LOCK
:
1135 printf("B_RELEASE_OVERLAY_LOCK\n");
1136 fVideoView
->OverlayLockRelease();
1139 case B_MOUSE_WHEEL_CHANGED
:
1141 printf("B_MOUSE_WHEEL_CHANGED\n");
1142 float dx
= msg
->FindFloat("be:wheel_delta_x");
1143 float dy
= msg
->FindFloat("be:wheel_delta_y");
1144 bool inv
= modifiers() & B_COMMAND_KEY
;
1145 if (dx
> 0.1) PostMessage(inv
? M_VOLUME_DOWN
: M_CHANNEL_PREV
);
1146 if (dx
< -0.1) PostMessage(inv
? M_VOLUME_UP
: M_CHANNEL_NEXT
);
1147 if (dy
> 0.1) PostMessage(inv
? M_CHANNEL_PREV
: M_VOLUME_DOWN
);
1148 if (dy
< -0.1) PostMessage(inv
? M_CHANNEL_NEXT
: M_VOLUME_UP
);
1152 case M_CHANNEL_NEXT
:
1154 printf("M_CHANNEL_NEXT\n");
1155 int chan
= fController
->CurrentChannel();
1158 if (chan
< fController
->ChannelCount())
1159 SelectChannel(chan
);
1164 case M_CHANNEL_PREV
:
1166 printf("M_CHANNEL_PREV\n");
1167 int chan
= fController
->CurrentChannel();
1171 SelectChannel(chan
);
1177 printf("M_VOLUME_UP\n");
1178 fController
->VolumeUp();
1182 printf("M_VOLUME_DOWN\n");
1183 fController
->VolumeDown();
1186 case M_ASPECT_100000_1
:
1187 VideoFormatChange(fSourceWidth
, fSourceHeight
, 1.0, 1.0);
1190 case M_ASPECT_106666_1
:
1191 VideoFormatChange(fSourceWidth
, fSourceHeight
, 1.06666, 1.0);
1194 case M_ASPECT_109091_1
:
1195 VideoFormatChange(fSourceWidth
, fSourceHeight
, 1.09091, 1.0);
1198 case M_ASPECT_141176_1
:
1199 VideoFormatChange(fSourceWidth
, fSourceHeight
, 1.41176, 1.0);
1202 case M_ASPECT_720_576
:
1203 VideoFormatChange(720, 576, 1.06666, 1.0);
1206 case M_ASPECT_704_576
:
1207 VideoFormatChange(704, 576, 1.09091, 1.0);
1210 case M_ASPECT_544_576
:
1211 VideoFormatChange(544, 576, 1.41176, 1.0);
1214 case B_REFS_RECEIVED
:
1215 printf("MainWin::MessageReceived: B_REFS_RECEIVED\n");
1216 // RefsReceived(msg);
1220 printf("MainWin::MessageReceived: B_SIMPLE_DATA\n");
1221 // if (msg->HasRef("refs"))
1222 // RefsReceived(msg);
1226 // be_app->PostMessage(B_QUIT_REQUESTED);
1227 PostMessage(B_QUIT_REQUESTED
);
1230 case M_SCALE_TO_NATIVE_SIZE
:
1231 printf("M_SCALE_TO_NATIVE_SIZE\n");
1232 if (fIsFullscreen
) {
1235 ResizeTo(int(fSourceWidth
* fWidthScale
),
1236 int(fSourceHeight
* fHeightScale
) + (fNoMenu
? 0
1241 case M_TOGGLE_FULLSCREEN
:
1243 fSettingsMenu
->ItemAt(1)->SetMarked(fIsFullscreen
);
1246 case M_TOGGLE_NO_MENU
:
1248 fSettingsMenu
->ItemAt(3)->SetMarked(fNoMenu
);
1251 case M_TOGGLE_NO_BORDER
:
1253 fSettingsMenu
->ItemAt(4)->SetMarked(fNoBorder
);
1256 case M_TOGGLE_ALWAYS_ON_TOP
:
1257 ToggleAlwaysOnTop();
1258 fSettingsMenu
->ItemAt(5)->SetMarked(fAlwaysOnTop
);
1261 case M_TOGGLE_KEEP_ASPECT_RATIO
:
1262 ToggleKeepAspectRatio();
1263 fSettingsMenu
->ItemAt(6)->SetMarked(fKeepAspectRatio
);
1266 case M_TOGGLE_NO_BORDER_NO_MENU
:
1267 ToggleNoBorderNoMenu();
1274 if (msg
->what
>= M_SELECT_CHANNEL
1275 && msg
->what
<= M_SELECT_CHANNEL_END
) {
1276 SelectChannel(msg
->what
- M_SELECT_CHANNEL
);
1279 if (msg
->what
>= M_SELECT_INTERFACE
1280 && msg
->what
<= M_SELECT_INTERFACE_END
) {
1281 SelectInterface(msg
->what
- M_SELECT_INTERFACE
- 1);