1 /*****************************************************************************
2 * vout_beos.cpp: beos video output display method
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 the VideoLAN team
7 * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
8 * Samuel Hocevar <sam@zoy.org>
9 * Tony Castley <tcastley@mail.powerup.com.au>
10 * Richard Shepherd <richard@rshepherd.demon.co.uk>
11 * Stephan Aßmus <stippi@yellowbites.com>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26 *****************************************************************************/
28 /*****************************************************************************
30 *****************************************************************************/
31 #include <errno.h> /* ENOMEM */
33 #include <Application.h>
34 #include <BitmapStream.h>
36 #include <Directory.h>
37 #include <DirectWindow.h>
39 #include <InterfaceKit.h>
42 #include <TranslatorRoster.h>
43 #include <WindowScreen.h>
50 #include <vlc_common.h>
51 #include <vlc_interface.h>
55 #include "InterfaceWindow.h" // for load/save_settings()
56 #include "DrawingTidbits.h"
59 #include "VideoWindow.h"
61 /*****************************************************************************
62 * vout_sys_t: BeOS video output method descriptor
63 *****************************************************************************
64 * This structure is part of the video output thread descriptor.
65 * It describes the BeOS specific properties of an output thread.
66 *****************************************************************************/
69 VideoWindow * p_window;
74 // uint8_t *pp_buffer[3];
75 uint32_t source_chroma;
80 #define MIN_AUTO_VSYNC_REFRESH 61 // Hz
82 /*****************************************************************************
83 * beos_GetAppWindow : retrieve a BWindow pointer from the window name
84 *****************************************************************************/
86 beos_GetAppWindow(char *name)
91 for (index = 0 ; ; index++)
93 window = be_app->WindowAt(index);
96 if (window->LockWithTimeout(20000) == B_OK)
98 if (strcmp(window->Name(), name) == 0)
109 static const int beos_keys[][2] =
111 { B_LEFT_ARROW, KEY_LEFT },
112 { B_RIGHT_ARROW, KEY_RIGHT },
113 { B_UP_ARROW, KEY_UP },
114 { B_DOWN_ARROW, KEY_DOWN },
115 { B_SPACE, KEY_SPACE },
116 { B_ENTER, KEY_ENTER },
117 { B_F1_KEY, KEY_F1 },
118 { B_F2_KEY, KEY_F2 },
119 { B_F3_KEY, KEY_F3 },
120 { B_F4_KEY, KEY_F4 },
121 { B_F5_KEY, KEY_F5 },
122 { B_F6_KEY, KEY_F6 },
123 { B_F7_KEY, KEY_F7 },
124 { B_F8_KEY, KEY_F8 },
125 { B_F9_KEY, KEY_F9 },
126 { B_F10_KEY, KEY_F10 },
127 { B_F11_KEY, KEY_F11 },
128 { B_F12_KEY, KEY_F12 },
129 { B_HOME, KEY_HOME },
131 { B_ESCAPE, KEY_ESC },
132 { B_PAGE_UP, KEY_PAGEUP },
133 { B_PAGE_DOWN, KEY_PAGEDOWN },
135 { B_BACKSPACE, KEY_BACKSPACE }
138 static int ConvertKeyFromVLC( int key )
140 for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
142 if( beos_keys[i][1] == key )
144 return beos_keys[i][0];
150 static int ConvertKeyToVLC( int key )
152 for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
154 if( beos_keys[i][0] == key )
156 return beos_keys[i][1];
162 /*****************************************************************************
163 * get_interface_window
164 *****************************************************************************/
166 get_interface_window()
168 return beos_GetAppWindow( "VLC " PACKAGE_VERSION );
171 class BackgroundView : public BView
174 BackgroundView(BRect frame, VLCView* view)
175 : BView(frame, "background",
176 B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE),
179 SetViewColor(kBlack);
181 virtual ~BackgroundView() {}
183 virtual void MouseDown(BPoint where)
185 // convert coordinates
186 where = fVideoView->ConvertFromParent(where);
188 fVideoView->MouseDown(where);
190 virtual void MouseMoved(BPoint where, uint32_t transit,
191 const BMessage* dragMessage)
193 // convert coordinates
194 where = fVideoView->ConvertFromParent(where);
196 fVideoView->MouseMoved(where, transit, dragMessage);
197 // notice: It might look like transit should be
198 // B_OUTSIDE_VIEW regardless, but leave it like this,
199 // otherwise, unwanted things will happen!
207 /*****************************************************************************
208 * VideoSettings constructor and destructor
209 *****************************************************************************/
210 VideoSettings::VideoSettings()
211 : fVideoSize( SIZE_100 ),
212 fFlags( FLAG_CORRECT_RATIO ),
213 fSettings( new BMessage( 'sett' ) )
215 // read settings from disk
216 status_t ret = load_settings( fSettings, "video_settings", "VideoLAN Client" );
220 if ( fSettings->FindInt32( "flags", (int32*)&flags ) == B_OK )
223 if ( fSettings->FindInt32( "video size", (int32*)&size ) == B_OK )
224 SetVideoSize( size );
228 // figure out if we should use vertical sync by default
229 BScreen screen(B_MAIN_SCREEN_ID);
230 if (screen.IsValid())
233 screen.GetMode(&mode);
234 float refresh = (mode.timing.pixel_clock * 1000)
235 / ((mode.timing.h_total)* (mode.timing.v_total));
236 if (refresh < MIN_AUTO_VSYNC_REFRESH)
237 AddFlags(FLAG_SYNC_RETRACE);
242 VideoSettings::VideoSettings( const VideoSettings& clone )
243 : fVideoSize( clone.VideoSize() ),
244 fFlags( clone.Flags() ),
250 VideoSettings::~VideoSettings()
254 // we are the default settings
255 // and write our settings to disk
256 if (fSettings->ReplaceInt32( "video size", VideoSize() ) != B_OK)
257 fSettings->AddInt32( "video size", VideoSize() );
258 if (fSettings->ReplaceInt32( "flags", Flags() ) != B_OK)
259 fSettings->AddInt32( "flags", Flags() );
261 save_settings( fSettings, "video_settings", "VideoLAN Client" );
266 // we are just a clone of the default settings
267 fDefaultSettings.SetVideoSize( VideoSize() );
268 fDefaultSettings.SetFlags( Flags() );
272 /*****************************************************************************
273 * VideoSettings::DefaultSettings
274 *****************************************************************************/
276 VideoSettings::DefaultSettings()
278 return &fDefaultSettings;
281 /*****************************************************************************
282 * VideoSettings::SetVideoSize
283 *****************************************************************************/
285 VideoSettings::SetVideoSize( uint32_t mode )
290 // static variable initialization
292 VideoSettings::fDefaultSettings;
295 /*****************************************************************************
296 * VideoWindow constructor and destructor
297 *****************************************************************************/
298 VideoWindow::VideoWindow(int v_width, int v_height, BRect frame,
299 vout_thread_t *p_videoout)
300 : BWindow(frame, NULL, B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_MINIMIZABLE),
301 i_width(frame.IntegerWidth()),
302 i_height(frame.IntegerHeight()),
305 teardownwindow(false),
307 fTrueHeight(v_height),
308 fCachedFeel(B_NORMAL_WINDOW_FEEL),
309 fInterfaceShowing(false),
310 fInitStatus(B_ERROR),
311 fSettings(new VideoSettings(*VideoSettings::DefaultSettings()))
315 // create the view to do the display
316 view = new VLCView( Bounds(), p_vout );
318 // create background view
319 BView *mainView = new BackgroundView( Bounds(), view );
321 mainView->AddChild(view);
323 // allocate bitmap buffers
324 for (int32_t i = 0; i < 3; i++)
326 fInitStatus = _AllocateBuffers(v_width, v_height, &mode);
328 // make sure we layout the view correctly
329 FrameResized(i_width, i_height);
331 if (fInitStatus >= B_OK && mode == OVERLAY)
333 overlay_restrictions r;
335 bitmap[0]->GetOverlayRestrictions(&r);
336 SetSizeLimits((i_width * r.min_width_scale), i_width * r.max_width_scale,
337 (i_height * r.min_height_scale), i_height * r.max_height_scale);
340 // vlc settings override settings from disk
341 if (config_GetInt(p_vout, "fullscreen"))
342 fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
347 VideoWindow::~VideoWindow()
351 teardownwindow = true;
352 wait_for_thread(fDrawThreadID, &result);
357 /*****************************************************************************
358 * VideoWindow::MessageReceived
359 *****************************************************************************/
361 VideoWindow::MessageReceived( BMessage *p_message )
363 switch( p_message->what )
366 SetInterfaceShowing( true );
368 case TOGGLE_FULL_SCREEN:
376 _SetVideoSize(p_message->what);
379 SetSyncToRetrace(!IsSyncedToRetrace());
384 if (p_message->FindInt32("WinFeel", (int32*)&winFeel) == B_OK)
387 fCachedFeel = winFeel;
388 if (winFeel == B_FLOATING_ALL_WINDOW_FEEL)
389 fSettings->AddFlags(VideoSettings::FLAG_ON_TOP_ALL);
391 fSettings->ClearFlags(VideoSettings::FLAG_ON_TOP_ALL);
396 SetCorrectAspectRatio(!CorrectAspectRatio());
400 case B_UNMAPPED_KEY_DOWN:
402 case B_UNMAPPED_KEY_UP:
406 int32 key, modifiers;
408 if( p_message->FindInt32( "key", &key ) != B_OK ||
409 p_message->FindInt32( "modifiers", &modifiers ) != B_OK )
411 /* Shouldn't happen */
415 if( ( p_message->what == B_KEY_UP ||
416 p_message->what == B_UNMAPPED_KEY_UP ) &&
417 !( modifiers & B_COMMAND_KEY ) )
419 /* We only use the KEY_UP messages to detect Alt+X
420 shortcuts (because the KEY_DOWN messages aren't
421 sent when Alt is pressed) */
425 /* Special case for Alt+1, Alt+2 and Alt+3 shortcuts: since
426 the character depends on the keymap, we use the key codes
427 directly (18, 19, 20) */
428 if( ( modifiers & B_COMMAND_KEY ) &&
429 key >= 18 && key <= 20 )
432 PostMessage( RESIZE_50 );
434 PostMessage( RESIZE_100 );
436 PostMessage( RESIZE_200 );
441 /* Get the current keymap */
442 get_key_map( &keys, &chars );
444 if( key >= 128 || chars[keys->normal_map[key]] != 1 )
446 /* Weird key or Unicode character */
453 val.i_int = ConvertKeyToVLC( chars[keys->normal_map[key]+1] );
455 if( modifiers & B_COMMAND_KEY )
457 val.i_int |= KEY_MODIFIER_ALT;
459 if( modifiers & B_SHIFT_KEY )
461 val.i_int |= KEY_MODIFIER_SHIFT;
463 if( modifiers & B_CONTROL_KEY )
465 val.i_int |= KEY_MODIFIER_CTRL;
467 var_Set( p_vout->p_libvlc, "key-pressed", val );
475 BWindow::MessageReceived( p_message );
480 /*****************************************************************************
482 *****************************************************************************/
484 VideoWindow::Zoom(BPoint origin, float width, float height )
489 /*****************************************************************************
490 * VideoWindow::FrameMoved
491 *****************************************************************************/
493 VideoWindow::FrameMoved(BPoint origin)
500 /*****************************************************************************
501 * VideoWindow::FrameResized
502 *****************************************************************************/
504 VideoWindow::FrameResized( float width, float height )
506 int32_t useWidth = CorrectAspectRatio() ? i_width : fTrueWidth;
507 int32_t useHeight = CorrectAspectRatio() ? i_height : fTrueHeight;
508 float out_width, out_height;
509 float out_left, out_top;
510 float width_scale = width / useWidth;
511 float height_scale = height / useHeight;
513 if (width_scale <= height_scale)
515 out_width = (useWidth * width_scale);
516 out_height = (useHeight * width_scale);
518 out_top = (height - out_height) / 2;
520 else /* if the height is proportionally smaller */
522 out_width = (useWidth * height_scale);
523 out_height = (useHeight * height_scale);
525 out_left = (width - out_width) / 2;
527 view->MoveTo(out_left,out_top);
528 view->ResizeTo(out_width, out_height);
534 /*****************************************************************************
535 * VideoWindow::ScreenChanged
536 *****************************************************************************/
538 VideoWindow::ScreenChanged(BRect frame, color_space format)
540 BScreen screen(this);
542 screen.GetMode(&mode);
543 float refresh = (mode.timing.pixel_clock * 1000)
544 / ((mode.timing.h_total) * (mode.timing.v_total));
545 SetSyncToRetrace(refresh < MIN_AUTO_VSYNC_REFRESH);
548 /*****************************************************************************
549 * VideoWindow::Activate
550 *****************************************************************************/
552 VideoWindow::WindowActivated(bool active)
556 /*****************************************************************************
557 * VideoWindow::drawBuffer
558 *****************************************************************************/
560 VideoWindow::drawBuffer(int bufferIndex)
562 i_buffer = bufferIndex;
564 // sync to the screen if required
565 if (IsSyncedToRetrace())
567 BScreen screen(this);
568 screen.WaitForRetrace(22000);
570 if (fInitStatus >= B_OK && LockLooper())
572 // switch the overlay bitmap
576 view->SetViewOverlay(bitmap[i_buffer],
577 bitmap[i_buffer]->Bounds() ,
580 B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL|
581 B_OVERLAY_TRANSFER_CHANNEL);
582 view->SetViewColor(key);
587 view->DrawBitmap(bitmap[i_buffer], view->Bounds() );
593 /*****************************************************************************
594 * VideoWindow::SetInterfaceShowing
595 *****************************************************************************/
597 VideoWindow::ToggleInterfaceShowing()
599 SetInterfaceShowing(!fInterfaceShowing);
602 /*****************************************************************************
603 * VideoWindow::SetInterfaceShowing
604 *****************************************************************************/
606 VideoWindow::SetInterfaceShowing(bool showIt)
608 BWindow* window = get_interface_window();
613 if (fCachedFeel != B_NORMAL_WINDOW_FEEL)
614 SetFeel(B_NORMAL_WINDOW_FEEL);
615 window->Activate(true);
620 SetFeel(fCachedFeel);
622 window->SendBehind(this);
624 fInterfaceShowing = showIt;
628 /*****************************************************************************
629 * VideoWindow::SetCorrectAspectRatio
630 *****************************************************************************/
632 VideoWindow::SetCorrectAspectRatio(bool doIt)
634 if (CorrectAspectRatio() != doIt)
637 fSettings->AddFlags(VideoSettings::FLAG_CORRECT_RATIO);
639 fSettings->ClearFlags(VideoSettings::FLAG_CORRECT_RATIO);
640 FrameResized(Bounds().Width(), Bounds().Height());
644 /*****************************************************************************
645 * VideoWindow::CorrectAspectRatio
646 *****************************************************************************/
648 VideoWindow::CorrectAspectRatio() const
650 return fSettings->HasFlags(VideoSettings::FLAG_CORRECT_RATIO);
653 /*****************************************************************************
654 * VideoWindow::ToggleFullScreen
655 *****************************************************************************/
657 VideoWindow::ToggleFullScreen()
659 SetFullScreen(!IsFullScreen());
662 /*****************************************************************************
663 * VideoWindow::SetFullScreen
664 *****************************************************************************/
666 VideoWindow::SetFullScreen(bool doIt)
670 SetLook( B_NO_BORDER_WINDOW_LOOK );
671 BScreen screen( this );
672 BRect rect = screen.Frame();
675 ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
676 be_app->ObscureCursor();
677 fInterfaceShowing = false;
678 fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
682 SetLook( B_TITLED_WINDOW_LOOK );
683 MoveTo(winSize.left, winSize.top);
684 ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
685 be_app->ShowCursor();
686 fInterfaceShowing = true;
687 fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
691 /*****************************************************************************
692 * VideoWindow::IsFullScreen
693 *****************************************************************************/
695 VideoWindow::IsFullScreen() const
697 return fSettings->HasFlags(VideoSettings::FLAG_FULL_SCREEN);
700 /*****************************************************************************
701 * VideoWindow::SetSyncToRetrace
702 *****************************************************************************/
704 VideoWindow::SetSyncToRetrace(bool doIt)
707 fSettings->AddFlags(VideoSettings::FLAG_SYNC_RETRACE);
709 fSettings->ClearFlags(VideoSettings::FLAG_SYNC_RETRACE);
712 /*****************************************************************************
713 * VideoWindow::IsSyncedToRetrace
714 *****************************************************************************/
716 VideoWindow::IsSyncedToRetrace() const
718 return fSettings->HasFlags(VideoSettings::FLAG_SYNC_RETRACE);
722 /*****************************************************************************
723 * VideoWindow::_AllocateBuffers
724 *****************************************************************************/
726 VideoWindow::_AllocateBuffers(int width, int height, int* mode)
728 // clear any old buffers
734 BRect bitmapFrame( 0, 0, width, height );
735 // read from config, if we are supposed to use overlay at all
736 int noOverlay = !config_GetInt( p_vout, "overlay" );
738 /* Test for overlay capability: for every chroma in colspace,
739 we try to do double-buffered overlay, single-buffered overlay
740 or basic overlay. If nothing worked, we then have to work with
741 a non-overlay BBitmap. */
742 for( int i = 0; i < COLOR_COUNT; i++ )
747 bitmap[0] = new BBitmap( bitmapFrame,
748 B_BITMAP_WILL_OVERLAY |
749 B_BITMAP_RESERVE_OVERLAY_CHANNEL,
750 colspace[i].colspace );
751 if( bitmap[0] && bitmap[0]->InitCheck() == B_OK )
757 view->SetViewOverlay( bitmap[0], bitmap[0]->Bounds(),
758 view->Bounds(), &key, B_FOLLOW_ALL,
759 B_OVERLAY_FILTER_HORIZONTAL |
760 B_OVERLAY_FILTER_VERTICAL );
761 view->SetViewColor( key );
762 SetTitle( "VLC " PACKAGE_VERSION " (Overlay)" );
764 bitmap[1] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
765 colspace[colspace_index].colspace);
766 if( bitmap[1] && bitmap[1]->InitCheck() == B_OK )
769 bitmap[2] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
770 colspace[colspace_index].colspace);
771 if( bitmap[2] && bitmap[2]->InitCheck() == B_OK )
773 msg_Dbg( p_vout, "using double-buffered overlay" );
777 msg_Dbg( p_vout, "using single-buffered overlay" );
779 delete bitmap[2]; bitmap[2] = NULL;
784 msg_Dbg( p_vout, "using simple overlay" );
786 delete bitmap[1]; bitmap[1] = NULL;
792 delete bitmap[0]; bitmap[0] = NULL;
798 msg_Warn( p_vout, "no possible overlay" );
801 colspace_index = DEFAULT_COL; // B_RGB32
802 bitmap[0] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
803 bitmap[1] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
804 bitmap[2] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
805 SetTitle( "VLC " PACKAGE_VERSION " (Bitmap)" );
807 // see if everything went well
808 status_t status = B_ERROR;
809 for (int32_t i = 0; i < bitmap_count; i++)
812 status = bitmap[i]->InitCheck();
818 // clear bitmaps to black
819 for (int32_t i = 0; i < bitmap_count; i++)
820 _BlankBitmap(bitmap[i]);
825 /*****************************************************************************
826 * VideoWindow::_FreeBuffers
827 *****************************************************************************/
829 VideoWindow::_FreeBuffers()
831 delete bitmap[0]; bitmap[0] = NULL;
832 delete bitmap[1]; bitmap[1] = NULL;
833 delete bitmap[2]; bitmap[2] = NULL;
834 fInitStatus = B_ERROR;
837 /*****************************************************************************
838 * VideoWindow::_BlankBitmap
839 *****************************************************************************/
841 VideoWindow::_BlankBitmap(BBitmap* bitmap) const
843 // no error checking (we do that earlier on and since it's a private function...
846 // Loss/Saturation points are Y 16-235 (absoulte); Cb/Cr 16-240 (center 128)
849 // Extrema points are Y 0 - 207 (absolute) U -91 - 91 (offset 128) V -127 - 127 (offset 128)
851 // we only handle weird colorspaces with special care
852 switch (bitmap->ColorSpace()) {
854 // Y0[7:0] Cb0[7:0] Y1[7:0] Cr0[7:0] Y2[7:0] Cb2[7:0] Y3[7:0] Cr2[7:0]
855 int32_t height = bitmap->Bounds().IntegerHeight() + 1;
856 uint8_t* bits = (uint8_t*)bitmap->Bits();
857 int32_t bpr = bitmap->BytesPerRow();
858 for (int32_t y = 0; y < height; y++) {
859 // handle 2 bytes at a time
860 for (int32_t i = 0; i < bpr; i += 2) {
872 // Non-interlaced only, Cb0 Y0 Y1 Cb2 Y2 Y3 on even scan lines ...
873 // Cr0 Y0 Y1 Cr2 Y2 Y3 on odd scan lines
874 int32_t height = bitmap->Bounds().IntegerHeight() + 1;
875 uint8_t* bits = (uint8_t*)bitmap->Bits();
876 int32_t bpr = bitmap->BytesPerRow();
877 for (int32_t y = 0; y < height; y += 1) {
878 // handle 3 bytes at a time
879 for (int32_t i = 0; i < bpr; i += 3) {
892 // U0[7:0] Y0[7:0] V0[7:0] Y1[7:0] U2[7:0] Y2[7:0] V2[7:0] Y3[7:0]
893 int32_t height = bitmap->Bounds().IntegerHeight() + 1;
894 uint8_t* bits = (uint8_t*)bitmap->Bits();
895 int32_t bpr = bitmap->BytesPerRow();
896 for (int32_t y = 0; y < height; y += 1) {
897 // handle 2 bytes at a time
898 for (int32_t i = 0; i < bpr; i += 2) {
909 memset(bitmap->Bits(), 0, bitmap->BitsLength());
914 /*****************************************************************************
915 * VideoWindow::_SetVideoSize
916 *****************************************************************************/
918 VideoWindow::_SetVideoSize(uint32_t mode)
920 // let size depend on aspect correction
921 int32_t width = CorrectAspectRatio() ? i_width : fTrueWidth;
922 int32_t height = CorrectAspectRatio() ? i_height : fTrueHeight;
937 fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
938 ResizeTo(width, height);
941 /*****************************************************************************
942 * VideoWindow::_SetToSettings
943 *****************************************************************************/
945 VideoWindow::_SetToSettings()
948 uint32_t mode = RESIZE_100;
949 switch (fSettings->VideoSize())
951 case VideoSettings::SIZE_50:
954 case VideoSettings::SIZE_200:
957 case VideoSettings::SIZE_100:
958 case VideoSettings::SIZE_OTHER:
962 bool fullscreen = IsFullScreen(); // remember settings
963 _SetVideoSize(mode); // because this will reset settings
964 // the fullscreen status is reflected in the settings,
965 // but not yet in the windows state
968 if (fSettings->HasFlags(VideoSettings::FLAG_ON_TOP_ALL))
969 fCachedFeel = B_FLOATING_ALL_WINDOW_FEEL;
971 fCachedFeel = B_NORMAL_WINDOW_FEEL;
972 SetFeel(fCachedFeel);
975 /*****************************************************************************
977 *****************************************************************************/
978 VLCView::VLCView(BRect bounds, vout_thread_t *p_vout_instance )
979 : BView(bounds, "video view", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED),
980 fLastMouseMovedTime(mdate()),
981 fCursorHidden(false),
982 fCursorInside(false),
983 fIgnoreDoubleClick(false)
985 p_vout = p_vout_instance;
986 fMouseHideTimeout = var_GetInteger(p_vout, "mouse-hide-timeout") * 1000;
987 SetViewColor(B_TRANSPARENT_32_BIT);
990 /*****************************************************************************
992 *****************************************************************************/
997 /*****************************************************************************
998 * VLCVIew::AttachedToWindow
999 *****************************************************************************/
1001 VLCView::AttachedToWindow()
1003 // periodically check if we want to hide the pointer
1004 Window()->SetPulseRate(1000000);
1007 /*****************************************************************************
1008 * VLCVIew::MouseDown
1009 *****************************************************************************/
1011 VLCView::MouseDown(BPoint where)
1013 VideoWindow* videoWindow = dynamic_cast<VideoWindow*>(Window());
1014 BMessage* msg = Window()->CurrentMessage();
1017 msg->FindInt32("clicks", &clicks);
1018 msg->FindInt32("buttons", (int32*)&buttons);
1022 if (buttons & B_PRIMARY_MOUSE_BUTTON)
1024 if (clicks == 2 && !fIgnoreDoubleClick)
1027 videoWindow->ToggleInterfaceShowing(); */
1028 fIgnoreDoubleClick = false;
1032 if (buttons & B_SECONDARY_MOUSE_BUTTON)
1034 // clicks will be 2 next time (if interval short enough)
1035 // even if the first click and the second
1036 // have not been made with the same mouse button
1037 fIgnoreDoubleClick = true;
1038 // launch popup menu
1039 BPopUpMenu *menu = new BPopUpMenu("context menu");
1040 menu->SetRadioMode(false);
1041 // In full screen, add an item to show/hide the interface
1042 if( videoWindow->IsFullScreen() )
1044 BMenuItem *intfItem =
1045 new BMenuItem( _("Show Interface"), new BMessage(SHOW_INTERFACE) );
1046 menu->AddItem( intfItem );
1049 BMenuItem *halfItem = new BMenuItem(_("50%"), new BMessage(RESIZE_50));
1050 menu->AddItem(halfItem);
1052 BMenuItem *origItem = new BMenuItem(_("100%"), new BMessage(RESIZE_100));
1053 menu->AddItem(origItem);
1055 BMenuItem *doubleItem = new BMenuItem(_("200%"), new BMessage(RESIZE_200));
1056 menu->AddItem(doubleItem);
1057 // Toggle FullScreen
1058 BMenuItem *zoomItem = new BMenuItem(_("Fullscreen"), new BMessage(TOGGLE_FULL_SCREEN));
1059 zoomItem->SetMarked(videoWindow->IsFullScreen());
1060 menu->AddItem(zoomItem);
1062 menu->AddSeparatorItem();
1065 BMenuItem *vsyncItem = new BMenuItem(_("Vertical Sync"), new BMessage(VERT_SYNC));
1066 vsyncItem->SetMarked(videoWindow->IsSyncedToRetrace());
1067 menu->AddItem(vsyncItem);
1068 // Correct Aspect Ratio
1069 BMenuItem *aspectItem = new BMenuItem(_("Correct Aspect Ratio"), new BMessage(ASPECT_CORRECT));
1070 aspectItem->SetMarked(videoWindow->CorrectAspectRatio());
1071 menu->AddItem(aspectItem);
1073 menu->AddSeparatorItem();
1075 // Window Feel Items
1076 /* BMessage *winNormFeel = new BMessage(WINDOW_FEEL);
1077 winNormFeel->AddInt32("WinFeel", (int32_t)B_NORMAL_WINDOW_FEEL);
1078 BMenuItem *normWindItem = new BMenuItem("Normal Window", winNormFeel);
1079 normWindItem->SetMarked(videoWindow->Feel() == B_NORMAL_WINDOW_FEEL);
1080 menu->AddItem(normWindItem);
1082 BMessage *winFloatFeel = new BMessage(WINDOW_FEEL);
1083 winFloatFeel->AddInt32("WinFeel", (int32_t)B_FLOATING_APP_WINDOW_FEEL);
1084 BMenuItem *onTopWindItem = new BMenuItem("App Top", winFloatFeel);
1085 onTopWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_APP_WINDOW_FEEL);
1086 menu->AddItem(onTopWindItem);
1088 BMessage *winAllFeel = new BMessage(WINDOW_FEEL);
1089 winAllFeel->AddInt32("WinFeel", (int32_t)B_FLOATING_ALL_WINDOW_FEEL);
1090 BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel);
1091 allSpacesWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL);
1092 menu->AddItem(allSpacesWindItem);*/
1094 BMessage *windowFeelMsg = new BMessage( WINDOW_FEEL );
1095 bool onTop = videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL;
1096 window_feel feel = onTop ? B_NORMAL_WINDOW_FEEL : B_FLOATING_ALL_WINDOW_FEEL;
1097 windowFeelMsg->AddInt32( "WinFeel", (int32_t)feel );
1098 BMenuItem *windowFeelItem = new BMenuItem( _("Stay On Top"), windowFeelMsg );
1099 windowFeelItem->SetMarked( onTop );
1100 menu->AddItem( windowFeelItem );
1102 menu->AddSeparatorItem();
1104 BMenuItem* screenShotItem = new BMenuItem( _("Take Screen Shot"),
1105 new BMessage( SCREEN_SHOT ) );
1106 menu->AddItem( screenShotItem );
1108 menu->SetTargetForItems( this );
1109 ConvertToScreen( &where );
1110 BRect mouseRect( where.x - 5, where.y - 5,
1111 where.x + 5, where.y + 5 );
1112 menu->Go( where, true, false, mouseRect, true );
1116 fLastMouseMovedTime = mdate();
1117 fCursorHidden = false;
1120 /*****************************************************************************
1122 *****************************************************************************/
1124 VLCView::MouseUp( BPoint where )
1128 var_Set( p_vout, "mouse-clicked", val );
1131 /*****************************************************************************
1132 * VLCVIew::MouseMoved
1133 *****************************************************************************/
1135 VLCView::MouseMoved(BPoint point, uint32 transit, const BMessage* dragMessage)
1137 fLastMouseMovedTime = mdate();
1138 fCursorHidden = false;
1139 fCursorInside = ( transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW );
1141 if( !fCursorInside )
1147 unsigned int i_width, i_height, i_x, i_y;
1148 vout_PlacePicture( p_vout, (unsigned int)Bounds().Width(),
1149 (unsigned int)Bounds().Height(),
1150 &i_x, &i_y, &i_width, &i_height );
1151 val.i_int = ( (int)point.x - i_x ) * p_vout->render.i_width / i_width;
1152 var_Set( p_vout, "mouse-x", val );
1153 val.i_int = ( (int)point.y - i_y ) * p_vout->render.i_height / i_height;
1154 var_Set( p_vout, "mouse-y", val );
1156 var_Set( p_vout, "mouse-moved", val );
1159 /*****************************************************************************
1161 *****************************************************************************/
1165 // We are getting the pulse messages no matter if the mouse is over
1166 // this view. If we are in full screen mode, we want to hide the cursor
1167 // even if it is not.
1168 VideoWindow *videoWindow = dynamic_cast<VideoWindow*>(Window());
1172 && mdate() - fLastMouseMovedTime > fMouseHideTimeout)
1174 be_app->ObscureCursor();
1175 fCursorHidden = true;
1177 // hide the interface window as well if full screen
1178 if (videoWindow && videoWindow->IsFullScreen())
1179 videoWindow->SetInterfaceShowing(false);
1183 // Workaround to disable the screensaver in full screen:
1184 // we simulate an activity every 29 seconds
1185 if( videoWindow && videoWindow->IsFullScreen() &&
1186 mdate() - fLastMouseMovedTime > 29000000 )
1190 GetMouse(&where, &buttons, false);
1191 ConvertToScreen(&where);
1192 set_mouse_position((int32_t) where.x, (int32_t) where.y);
1196 /*****************************************************************************
1198 *****************************************************************************/
1200 VLCView::Draw(BRect updateRect)
1202 VideoWindow* window = dynamic_cast<VideoWindow*>( Window() );
1203 if ( window && window->mode == BITMAP )
1204 FillRect( updateRect );
1207 /*****************************************************************************
1209 *****************************************************************************/
1210 static int Init ( vout_thread_t * );
1211 static void End ( vout_thread_t * );
1212 static int Manage ( vout_thread_t * );
1213 static void Display ( vout_thread_t *, picture_t * );
1214 static int Control ( vout_thread_t *, int, va_list );
1216 static int BeosOpenDisplay ( vout_thread_t *p_vout );
1217 static void BeosCloseDisplay( vout_thread_t *p_vout );
1219 /*****************************************************************************
1220 * OpenVideo: allocates BeOS video thread output method
1221 *****************************************************************************
1222 * This function allocates and initializes a BeOS vout method.
1223 *****************************************************************************/
1224 int OpenVideo ( vlc_object_t *p_this )
1226 vout_thread_t * p_vout = (vout_thread_t *)p_this;
1228 /* Allocate structure */
1229 p_vout->p_sys = (vout_sys_t*) malloc( sizeof( vout_sys_t ) );
1230 if( p_vout->p_sys == NULL )
1232 msg_Err( p_vout, "out of memory" );
1235 p_vout->p_sys->i_width = p_vout->render.i_width;
1236 p_vout->p_sys->i_height = p_vout->render.i_height;
1237 p_vout->p_sys->source_chroma = p_vout->render.i_chroma;
1239 p_vout->pf_init = Init;
1240 p_vout->pf_end = End;
1241 p_vout->pf_manage = Manage;
1242 p_vout->pf_render = NULL;
1243 p_vout->pf_display = Display;
1244 p_vout->pf_control = Control;
1249 /*****************************************************************************
1250 * Init: initialize BeOS video thread output method
1251 *****************************************************************************/
1252 int Init( vout_thread_t *p_vout )
1257 I_OUTPUTPICTURES = 0;
1259 /* Open and initialize device */
1260 if( BeosOpenDisplay( p_vout ) )
1262 msg_Err(p_vout, "vout error: can't open display");
1265 p_vout->output.i_width = p_vout->render.i_width;
1266 p_vout->output.i_height = p_vout->render.i_height;
1268 /* Assume we have square pixels */
1269 p_vout->output.i_aspect = p_vout->p_sys->i_width
1270 * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
1271 p_vout->output.i_chroma = colspace[p_vout->p_sys->p_window->colspace_index].chroma;
1272 p_vout->p_sys->i_index = 0;
1274 p_vout->output.i_rmask = 0x00ff0000;
1275 p_vout->output.i_gmask = 0x0000ff00;
1276 p_vout->output.i_bmask = 0x000000ff;
1278 for( int buffer_index = 0 ;
1279 buffer_index < p_vout->p_sys->p_window->bitmap_count;
1283 /* Find an empty picture slot */
1284 for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
1287 if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
1289 p_pic = p_vout->p_picture + i_index;
1298 p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[buffer_index]->Bits();
1299 p_pic->p->i_lines = p_vout->p_sys->i_height;
1300 p_pic->p->i_visible_lines = p_vout->p_sys->i_height;
1302 p_pic->p->i_pixel_pitch = colspace[p_vout->p_sys->p_window->colspace_index].pixel_bytes;
1303 p_pic->i_planes = colspace[p_vout->p_sys->p_window->colspace_index].planes;
1304 p_pic->p->i_pitch = p_vout->p_sys->p_window->bitmap[buffer_index]->BytesPerRow();
1305 p_pic->p->i_visible_pitch = p_pic->p->i_pixel_pitch * ( p_vout->p_sys->p_window->bitmap[buffer_index]->Bounds().IntegerWidth() + 1 );
1307 p_pic->i_status = DESTROYED_PICTURE;
1308 p_pic->i_type = DIRECT_PICTURE;
1310 PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
1318 /*****************************************************************************
1319 * End: terminate BeOS video thread output method
1320 *****************************************************************************/
1321 void End( vout_thread_t *p_vout )
1323 BeosCloseDisplay( p_vout );
1326 /*****************************************************************************
1328 *****************************************************************************/
1329 static int Manage( vout_thread_t * p_vout )
1331 if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
1333 p_vout->p_sys->p_window->PostMessage( TOGGLE_FULL_SCREEN );
1334 p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
1340 /*****************************************************************************
1341 * CloseVideo: destroy BeOS video thread output method
1342 *****************************************************************************
1343 * Terminate an output method created by DummyCreateOutputMethod
1344 *****************************************************************************/
1345 void CloseVideo ( vlc_object_t *p_this )
1347 vout_thread_t * p_vout = (vout_thread_t *)p_this;
1349 free( p_vout->p_sys );
1352 /*****************************************************************************
1353 * Display: displays previously rendered output
1354 *****************************************************************************
1355 * This function send the currently rendered image to BeOS image, waits until
1356 * it is displayed and switch the two rendering buffers, preparing next frame.
1357 *****************************************************************************/
1358 void Display( vout_thread_t *p_vout, picture_t *p_pic )
1360 VideoWindow * p_win = p_vout->p_sys->p_window;
1362 /* draw buffer if required */
1363 if (!p_win->teardownwindow)
1365 p_win->drawBuffer(p_vout->p_sys->i_index);
1368 p_vout->p_sys->i_index = ++p_vout->p_sys->i_index %
1369 p_vout->p_sys->p_window->bitmap_count;
1370 p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[p_vout->p_sys->i_index]->Bits();
1373 static int Control( vout_thread_t * p_vout, int i_query, va_list args )
1375 return vout_vaControlDefault( p_vout, i_query, args );
1378 /* following functions are local */
1380 /*****************************************************************************
1381 * BeosOpenDisplay: open and initialize BeOS device
1382 *****************************************************************************/
1383 static int BeosOpenDisplay( vout_thread_t *p_vout )
1386 p_vout->p_sys->p_window = new VideoWindow( p_vout->p_sys->i_width - 1,
1387 p_vout->p_sys->i_height - 1,
1389 20 + p_vout->i_window_width - 1,
1390 50 + p_vout->i_window_height - 1 ),
1392 if( p_vout->p_sys->p_window == NULL )
1394 msg_Err( p_vout, "cannot allocate VideoWindow" );
1399 p_vout->p_sys->p_window->Show();
1405 /*****************************************************************************
1406 * BeosDisplay: close and reset BeOS device
1407 *****************************************************************************
1408 * Returns all resources allocated by BeosOpenDisplay and restore the original
1409 * state of the device.
1410 *****************************************************************************/
1411 static void BeosCloseDisplay( vout_thread_t *p_vout )
1413 VideoWindow * p_win = p_vout->p_sys->p_window;
1414 /* Destroy the video window */
1415 if( p_win != NULL && !p_win->teardownwindow)
1418 p_win->teardownwindow = true;