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 <Application.h>
32 #include <BitmapStream.h>
34 #include <Directory.h>
35 #include <DirectWindow.h>
37 #include <InterfaceKit.h>
40 #include <TranslatorRoster.h>
41 #include <WindowScreen.h>
48 #include <vlc_common.h>
49 #include <vlc_interface.h>
53 #include "InterfaceWindow.h" // for load/save_settings()
54 #include "DrawingTidbits.h"
57 #include "VideoWindow.h"
59 /*****************************************************************************
60 * vout_sys_t: BeOS video output method descriptor
61 *****************************************************************************
62 * This structure is part of the video output thread descriptor.
63 * It describes the BeOS specific properties of an output thread.
64 *****************************************************************************/
67 VideoWindow * p_window;
72 // uint8_t *pp_buffer[3];
73 uint32_t source_chroma;
78 #define MIN_AUTO_VSYNC_REFRESH 61 // Hz
80 /*****************************************************************************
81 * beos_GetAppWindow : retrieve a BWindow pointer from the window name
82 *****************************************************************************/
84 beos_GetAppWindow(char *name)
89 for (index = 0 ; ; index++)
91 window = be_app->WindowAt(index);
94 if (window->LockWithTimeout(20000) == B_OK)
96 if (strcmp(window->Name(), name) == 0)
107 static const int beos_keys[][2] =
109 { B_LEFT_ARROW, KEY_LEFT },
110 { B_RIGHT_ARROW, KEY_RIGHT },
111 { B_UP_ARROW, KEY_UP },
112 { B_DOWN_ARROW, KEY_DOWN },
114 { B_ENTER, KEY_ENTER },
115 { B_F1_KEY, KEY_F1 },
116 { B_F2_KEY, KEY_F2 },
117 { B_F3_KEY, KEY_F3 },
118 { B_F4_KEY, KEY_F4 },
119 { B_F5_KEY, KEY_F5 },
120 { B_F6_KEY, KEY_F6 },
121 { B_F7_KEY, KEY_F7 },
122 { B_F8_KEY, KEY_F8 },
123 { B_F9_KEY, KEY_F9 },
124 { B_F10_KEY, KEY_F10 },
125 { B_F11_KEY, KEY_F11 },
126 { B_F12_KEY, KEY_F12 },
127 { B_HOME, KEY_HOME },
129 { B_ESCAPE, KEY_ESC },
130 { B_PAGE_UP, KEY_PAGEUP },
131 { B_PAGE_DOWN, KEY_PAGEDOWN },
133 { B_BACKSPACE, KEY_BACKSPACE }
136 static int ConvertKeyFromVLC( int key )
138 for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
140 if( beos_keys[i][1] == key )
142 return beos_keys[i][0];
148 static int ConvertKeyToVLC( int key )
150 for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
152 if( beos_keys[i][0] == key )
154 return beos_keys[i][1];
160 /*****************************************************************************
161 * get_interface_window
162 *****************************************************************************/
164 get_interface_window()
166 return beos_GetAppWindow( "VLC " PACKAGE_VERSION );
169 class BackgroundView : public BView
172 BackgroundView(BRect frame, VLCView* view)
173 : BView(frame, "background",
174 B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE),
177 SetViewColor(kBlack);
179 virtual ~BackgroundView() {}
181 virtual void MouseDown(BPoint where)
183 // convert coordinates
184 where = fVideoView->ConvertFromParent(where);
186 fVideoView->MouseDown(where);
188 virtual void MouseMoved(BPoint where, uint32_t transit,
189 const BMessage* dragMessage)
191 // convert coordinates
192 where = fVideoView->ConvertFromParent(where);
194 fVideoView->MouseMoved(where, transit, dragMessage);
195 // notice: It might look like transit should be
196 // B_OUTSIDE_VIEW regardless, but leave it like this,
197 // otherwise, unwanted things will happen!
205 /*****************************************************************************
206 * VideoSettings constructor and destructor
207 *****************************************************************************/
208 VideoSettings::VideoSettings()
209 : fVideoSize( SIZE_100 ),
210 fFlags( FLAG_CORRECT_RATIO ),
211 fSettings( new BMessage( 'sett' ) )
213 // read settings from disk
214 status_t ret = load_settings( fSettings, "video_settings", "VideoLAN Client" );
218 if ( fSettings->FindInt32( "flags", (int32*)&flags ) == B_OK )
221 if ( fSettings->FindInt32( "video size", (int32*)&size ) == B_OK )
222 SetVideoSize( size );
226 // figure out if we should use vertical sync by default
227 BScreen screen(B_MAIN_SCREEN_ID);
228 if (screen.IsValid())
231 screen.GetMode(&mode);
232 float refresh = (mode.timing.pixel_clock * 1000)
233 / ((mode.timing.h_total)* (mode.timing.v_total));
234 if (refresh < MIN_AUTO_VSYNC_REFRESH)
235 AddFlags(FLAG_SYNC_RETRACE);
240 VideoSettings::VideoSettings( const VideoSettings& clone )
241 : fVideoSize( clone.VideoSize() ),
242 fFlags( clone.Flags() ),
248 VideoSettings::~VideoSettings()
252 // we are the default settings
253 // and write our settings to disk
254 if (fSettings->ReplaceInt32( "video size", VideoSize() ) != B_OK)
255 fSettings->AddInt32( "video size", VideoSize() );
256 if (fSettings->ReplaceInt32( "flags", Flags() ) != B_OK)
257 fSettings->AddInt32( "flags", Flags() );
259 save_settings( fSettings, "video_settings", "VideoLAN Client" );
264 // we are just a clone of the default settings
265 fDefaultSettings.SetVideoSize( VideoSize() );
266 fDefaultSettings.SetFlags( Flags() );
270 /*****************************************************************************
271 * VideoSettings::DefaultSettings
272 *****************************************************************************/
274 VideoSettings::DefaultSettings()
276 return &fDefaultSettings;
279 /*****************************************************************************
280 * VideoSettings::SetVideoSize
281 *****************************************************************************/
283 VideoSettings::SetVideoSize( uint32_t mode )
288 // static variable initialization
290 VideoSettings::fDefaultSettings;
293 /*****************************************************************************
294 * VideoWindow constructor and destructor
295 *****************************************************************************/
296 VideoWindow::VideoWindow(int v_width, int v_height, BRect frame,
297 vout_thread_t *p_videoout)
298 : BWindow(frame, NULL, B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_MINIMIZABLE),
299 i_width(frame.IntegerWidth()),
300 i_height(frame.IntegerHeight()),
303 teardownwindow(false),
305 fTrueHeight(v_height),
306 fCachedFeel(B_NORMAL_WINDOW_FEEL),
307 fInterfaceShowing(false),
308 fInitStatus(B_ERROR),
309 fSettings(new VideoSettings(*VideoSettings::DefaultSettings()))
313 // create the view to do the display
314 view = new VLCView( Bounds(), p_vout );
316 // create background view
317 BView *mainView = new BackgroundView( Bounds(), view );
319 mainView->AddChild(view);
321 // allocate bitmap buffers
322 for (int32_t i = 0; i < 3; i++)
324 fInitStatus = _AllocateBuffers(v_width, v_height, &mode);
326 // make sure we layout the view correctly
327 FrameResized(i_width, i_height);
329 if (fInitStatus >= B_OK && mode == OVERLAY)
331 overlay_restrictions r;
333 bitmap[0]->GetOverlayRestrictions(&r);
334 SetSizeLimits((i_width * r.min_width_scale), i_width * r.max_width_scale,
335 (i_height * r.min_height_scale), i_height * r.max_height_scale);
338 // vlc settings override settings from disk
339 if (config_GetInt(p_vout, "fullscreen"))
340 fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
345 VideoWindow::~VideoWindow()
349 teardownwindow = true;
350 wait_for_thread(fDrawThreadID, &result);
355 /*****************************************************************************
356 * VideoWindow::MessageReceived
357 *****************************************************************************/
359 VideoWindow::MessageReceived( BMessage *p_message )
361 switch( p_message->what )
364 SetInterfaceShowing( true );
366 case TOGGLE_FULL_SCREEN:
374 _SetVideoSize(p_message->what);
377 SetSyncToRetrace(!IsSyncedToRetrace());
382 if (p_message->FindInt32("WinFeel", (int32*)&winFeel) == B_OK)
385 fCachedFeel = winFeel;
386 if (winFeel == B_FLOATING_ALL_WINDOW_FEEL)
387 fSettings->AddFlags(VideoSettings::FLAG_ON_TOP_ALL);
389 fSettings->ClearFlags(VideoSettings::FLAG_ON_TOP_ALL);
394 SetCorrectAspectRatio(!CorrectAspectRatio());
398 case B_UNMAPPED_KEY_DOWN:
400 case B_UNMAPPED_KEY_UP:
404 int32 key, modifiers;
406 if( p_message->FindInt32( "key", &key ) != B_OK ||
407 p_message->FindInt32( "modifiers", &modifiers ) != B_OK )
409 /* Shouldn't happen */
413 if( ( p_message->what == B_KEY_UP ||
414 p_message->what == B_UNMAPPED_KEY_UP ) &&
415 !( modifiers & B_COMMAND_KEY ) )
417 /* We only use the KEY_UP messages to detect Alt+X
418 shortcuts (because the KEY_DOWN messages aren't
419 sent when Alt is pressed) */
423 /* Special case for Alt+1, Alt+2 and Alt+3 shortcuts: since
424 the character depends on the keymap, we use the key codes
425 directly (18, 19, 20) */
426 if( ( modifiers & B_COMMAND_KEY ) &&
427 key >= 18 && key <= 20 )
430 PostMessage( RESIZE_50 );
432 PostMessage( RESIZE_100 );
434 PostMessage( RESIZE_200 );
439 /* Get the current keymap */
440 get_key_map( &keys, &chars );
442 if( key >= 128 || chars[keys->normal_map[key]] != 1 )
444 /* Weird key or Unicode character */
451 val.i_int = ConvertKeyToVLC( chars[keys->normal_map[key]+1] );
453 if( modifiers & B_COMMAND_KEY )
455 val.i_int |= KEY_MODIFIER_ALT;
457 if( modifiers & B_SHIFT_KEY )
459 val.i_int |= KEY_MODIFIER_SHIFT;
461 if( modifiers & B_CONTROL_KEY )
463 val.i_int |= KEY_MODIFIER_CTRL;
465 var_Set( p_vout->p_libvlc, "key-pressed", val );
473 BWindow::MessageReceived( p_message );
478 /*****************************************************************************
480 *****************************************************************************/
482 VideoWindow::Zoom(BPoint origin, float width, float height )
487 /*****************************************************************************
488 * VideoWindow::FrameMoved
489 *****************************************************************************/
491 VideoWindow::FrameMoved(BPoint origin)
498 /*****************************************************************************
499 * VideoWindow::FrameResized
500 *****************************************************************************/
502 VideoWindow::FrameResized( float width, float height )
504 int32_t useWidth = CorrectAspectRatio() ? i_width : fTrueWidth;
505 int32_t useHeight = CorrectAspectRatio() ? i_height : fTrueHeight;
506 float out_width, out_height;
507 float out_left, out_top;
508 float width_scale = width / useWidth;
509 float height_scale = height / useHeight;
511 if (width_scale <= height_scale)
513 out_width = (useWidth * width_scale);
514 out_height = (useHeight * width_scale);
516 out_top = (height - out_height) / 2;
518 else /* if the height is proportionally smaller */
520 out_width = (useWidth * height_scale);
521 out_height = (useHeight * height_scale);
523 out_left = (width - out_width) / 2;
525 view->MoveTo(out_left,out_top);
526 view->ResizeTo(out_width, out_height);
532 /*****************************************************************************
533 * VideoWindow::ScreenChanged
534 *****************************************************************************/
536 VideoWindow::ScreenChanged(BRect frame, color_space format)
538 BScreen screen(this);
540 screen.GetMode(&mode);
541 float refresh = (mode.timing.pixel_clock * 1000)
542 / ((mode.timing.h_total) * (mode.timing.v_total));
543 SetSyncToRetrace(refresh < MIN_AUTO_VSYNC_REFRESH);
546 /*****************************************************************************
547 * VideoWindow::Activate
548 *****************************************************************************/
550 VideoWindow::WindowActivated(bool active)
554 /*****************************************************************************
555 * VideoWindow::drawBuffer
556 *****************************************************************************/
558 VideoWindow::drawBuffer(int bufferIndex)
560 i_buffer = bufferIndex;
562 // sync to the screen if required
563 if (IsSyncedToRetrace())
565 BScreen screen(this);
566 screen.WaitForRetrace(22000);
568 if (fInitStatus >= B_OK && LockLooper())
570 // switch the overlay bitmap
574 view->SetViewOverlay(bitmap[i_buffer],
575 bitmap[i_buffer]->Bounds() ,
578 B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL|
579 B_OVERLAY_TRANSFER_CHANNEL);
580 view->SetViewColor(key);
585 view->DrawBitmap(bitmap[i_buffer], view->Bounds() );
591 /*****************************************************************************
592 * VideoWindow::SetInterfaceShowing
593 *****************************************************************************/
595 VideoWindow::ToggleInterfaceShowing()
597 SetInterfaceShowing(!fInterfaceShowing);
600 /*****************************************************************************
601 * VideoWindow::SetInterfaceShowing
602 *****************************************************************************/
604 VideoWindow::SetInterfaceShowing(bool showIt)
606 BWindow* window = get_interface_window();
611 if (fCachedFeel != B_NORMAL_WINDOW_FEEL)
612 SetFeel(B_NORMAL_WINDOW_FEEL);
613 window->Activate(true);
618 SetFeel(fCachedFeel);
620 window->SendBehind(this);
622 fInterfaceShowing = showIt;
626 /*****************************************************************************
627 * VideoWindow::SetCorrectAspectRatio
628 *****************************************************************************/
630 VideoWindow::SetCorrectAspectRatio(bool doIt)
632 if (CorrectAspectRatio() != doIt)
635 fSettings->AddFlags(VideoSettings::FLAG_CORRECT_RATIO);
637 fSettings->ClearFlags(VideoSettings::FLAG_CORRECT_RATIO);
638 FrameResized(Bounds().Width(), Bounds().Height());
642 /*****************************************************************************
643 * VideoWindow::CorrectAspectRatio
644 *****************************************************************************/
646 VideoWindow::CorrectAspectRatio() const
648 return fSettings->HasFlags(VideoSettings::FLAG_CORRECT_RATIO);
651 /*****************************************************************************
652 * VideoWindow::ToggleFullScreen
653 *****************************************************************************/
655 VideoWindow::ToggleFullScreen()
657 SetFullScreen(!IsFullScreen());
660 /*****************************************************************************
661 * VideoWindow::SetFullScreen
662 *****************************************************************************/
664 VideoWindow::SetFullScreen(bool doIt)
668 SetLook( B_NO_BORDER_WINDOW_LOOK );
669 BScreen screen( this );
670 BRect rect = screen.Frame();
673 ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
674 be_app->ObscureCursor();
675 fInterfaceShowing = false;
676 fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
680 SetLook( B_TITLED_WINDOW_LOOK );
681 MoveTo(winSize.left, winSize.top);
682 ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
683 be_app->ShowCursor();
684 fInterfaceShowing = true;
685 fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
689 /*****************************************************************************
690 * VideoWindow::IsFullScreen
691 *****************************************************************************/
693 VideoWindow::IsFullScreen() const
695 return fSettings->HasFlags(VideoSettings::FLAG_FULL_SCREEN);
698 /*****************************************************************************
699 * VideoWindow::SetSyncToRetrace
700 *****************************************************************************/
702 VideoWindow::SetSyncToRetrace(bool doIt)
705 fSettings->AddFlags(VideoSettings::FLAG_SYNC_RETRACE);
707 fSettings->ClearFlags(VideoSettings::FLAG_SYNC_RETRACE);
710 /*****************************************************************************
711 * VideoWindow::IsSyncedToRetrace
712 *****************************************************************************/
714 VideoWindow::IsSyncedToRetrace() const
716 return fSettings->HasFlags(VideoSettings::FLAG_SYNC_RETRACE);
720 /*****************************************************************************
721 * VideoWindow::_AllocateBuffers
722 *****************************************************************************/
724 VideoWindow::_AllocateBuffers(int width, int height, int* mode)
726 // clear any old buffers
732 BRect bitmapFrame( 0, 0, width, height );
733 // read from config, if we are supposed to use overlay at all
734 int noOverlay = !config_GetInt( p_vout, "overlay" );
736 /* Test for overlay capability: for every chroma in colspace,
737 we try to do double-buffered overlay, single-buffered overlay
738 or basic overlay. If nothing worked, we then have to work with
739 a non-overlay BBitmap. */
740 for( int i = 0; i < COLOR_COUNT; i++ )
745 bitmap[0] = new BBitmap( bitmapFrame,
746 B_BITMAP_WILL_OVERLAY |
747 B_BITMAP_RESERVE_OVERLAY_CHANNEL,
748 colspace[i].colspace );
749 if( bitmap[0] && bitmap[0]->InitCheck() == B_OK )
755 view->SetViewOverlay( bitmap[0], bitmap[0]->Bounds(),
756 view->Bounds(), &key, B_FOLLOW_ALL,
757 B_OVERLAY_FILTER_HORIZONTAL |
758 B_OVERLAY_FILTER_VERTICAL );
759 view->SetViewColor( key );
760 SetTitle( "VLC " PACKAGE_VERSION " (Overlay)" );
762 bitmap[1] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
763 colspace[colspace_index].colspace);
764 if( bitmap[1] && bitmap[1]->InitCheck() == B_OK )
767 bitmap[2] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
768 colspace[colspace_index].colspace);
769 if( bitmap[2] && bitmap[2]->InitCheck() == B_OK )
771 msg_Dbg( p_vout, "using double-buffered overlay" );
775 msg_Dbg( p_vout, "using single-buffered overlay" );
777 delete bitmap[2]; bitmap[2] = NULL;
782 msg_Dbg( p_vout, "using simple overlay" );
784 delete bitmap[1]; bitmap[1] = NULL;
790 delete bitmap[0]; bitmap[0] = NULL;
796 msg_Warn( p_vout, "no possible overlay" );
799 colspace_index = DEFAULT_COL; // B_RGB32
800 bitmap[0] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
801 bitmap[1] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
802 bitmap[2] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
803 SetTitle( "VLC " PACKAGE_VERSION " (Bitmap)" );
805 // see if everything went well
806 status_t status = B_ERROR;
807 for (int32_t i = 0; i < bitmap_count; i++)
810 status = bitmap[i]->InitCheck();
816 // clear bitmaps to black
817 for (int32_t i = 0; i < bitmap_count; i++)
818 _BlankBitmap(bitmap[i]);
823 /*****************************************************************************
824 * VideoWindow::_FreeBuffers
825 *****************************************************************************/
827 VideoWindow::_FreeBuffers()
829 delete bitmap[0]; bitmap[0] = NULL;
830 delete bitmap[1]; bitmap[1] = NULL;
831 delete bitmap[2]; bitmap[2] = NULL;
832 fInitStatus = B_ERROR;
835 /*****************************************************************************
836 * VideoWindow::_BlankBitmap
837 *****************************************************************************/
839 VideoWindow::_BlankBitmap(BBitmap* bitmap) const
841 // no error checking (we do that earlier on and since it's a private function...
844 // Loss/Saturation points are Y 16-235 (absoulte); Cb/Cr 16-240 (center 128)
847 // Extrema points are Y 0 - 207 (absolute) U -91 - 91 (offset 128) V -127 - 127 (offset 128)
849 // we only handle weird colorspaces with special care
850 switch (bitmap->ColorSpace()) {
852 // Y0[7:0] Cb0[7:0] Y1[7:0] Cr0[7:0] Y2[7:0] Cb2[7:0] Y3[7:0] Cr2[7:0]
853 int32_t height = bitmap->Bounds().IntegerHeight() + 1;
854 uint8_t* bits = (uint8_t*)bitmap->Bits();
855 int32_t bpr = bitmap->BytesPerRow();
856 for (int32_t y = 0; y < height; y++) {
857 // handle 2 bytes at a time
858 for (int32_t i = 0; i < bpr; i += 2) {
870 // Non-interlaced only, Cb0 Y0 Y1 Cb2 Y2 Y3 on even scan lines ...
871 // Cr0 Y0 Y1 Cr2 Y2 Y3 on odd scan lines
872 int32_t height = bitmap->Bounds().IntegerHeight() + 1;
873 uint8_t* bits = (uint8_t*)bitmap->Bits();
874 int32_t bpr = bitmap->BytesPerRow();
875 for (int32_t y = 0; y < height; y += 1) {
876 // handle 3 bytes at a time
877 for (int32_t i = 0; i < bpr; i += 3) {
890 // U0[7:0] Y0[7:0] V0[7:0] Y1[7:0] U2[7:0] Y2[7:0] V2[7:0] Y3[7:0]
891 int32_t height = bitmap->Bounds().IntegerHeight() + 1;
892 uint8_t* bits = (uint8_t*)bitmap->Bits();
893 int32_t bpr = bitmap->BytesPerRow();
894 for (int32_t y = 0; y < height; y += 1) {
895 // handle 2 bytes at a time
896 for (int32_t i = 0; i < bpr; i += 2) {
907 memset(bitmap->Bits(), 0, bitmap->BitsLength());
912 /*****************************************************************************
913 * VideoWindow::_SetVideoSize
914 *****************************************************************************/
916 VideoWindow::_SetVideoSize(uint32_t mode)
918 // let size depend on aspect correction
919 int32_t width = CorrectAspectRatio() ? i_width : fTrueWidth;
920 int32_t height = CorrectAspectRatio() ? i_height : fTrueHeight;
935 fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
936 ResizeTo(width, height);
939 /*****************************************************************************
940 * VideoWindow::_SetToSettings
941 *****************************************************************************/
943 VideoWindow::_SetToSettings()
946 uint32_t mode = RESIZE_100;
947 switch (fSettings->VideoSize())
949 case VideoSettings::SIZE_50:
952 case VideoSettings::SIZE_200:
955 case VideoSettings::SIZE_100:
956 case VideoSettings::SIZE_OTHER:
960 bool fullscreen = IsFullScreen(); // remember settings
961 _SetVideoSize(mode); // because this will reset settings
962 // the fullscreen status is reflected in the settings,
963 // but not yet in the windows state
966 if (fSettings->HasFlags(VideoSettings::FLAG_ON_TOP_ALL))
967 fCachedFeel = B_FLOATING_ALL_WINDOW_FEEL;
969 fCachedFeel = B_NORMAL_WINDOW_FEEL;
970 SetFeel(fCachedFeel);
973 /*****************************************************************************
975 *****************************************************************************/
976 VLCView::VLCView(BRect bounds, vout_thread_t *p_vout_instance )
977 : BView(bounds, "video view", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED),
978 fLastMouseMovedTime(mdate()),
979 fCursorHidden(false),
980 fCursorInside(false),
981 fIgnoreDoubleClick(false)
983 p_vout = p_vout_instance;
984 fMouseHideTimeout = var_GetInteger(p_vout, "mouse-hide-timeout") * 1000;
985 SetViewColor(B_TRANSPARENT_32_BIT);
988 /*****************************************************************************
990 *****************************************************************************/
995 /*****************************************************************************
996 * VLCVIew::AttachedToWindow
997 *****************************************************************************/
999 VLCView::AttachedToWindow()
1001 // periodically check if we want to hide the pointer
1002 Window()->SetPulseRate(1000000);
1005 /*****************************************************************************
1006 * VLCVIew::MouseDown
1007 *****************************************************************************/
1009 VLCView::MouseDown(BPoint where)
1011 VideoWindow* videoWindow = dynamic_cast<VideoWindow*>(Window());
1012 BMessage* msg = Window()->CurrentMessage();
1015 msg->FindInt32("clicks", &clicks);
1016 msg->FindInt32("buttons", (int32*)&buttons);
1020 if (buttons & B_PRIMARY_MOUSE_BUTTON)
1022 if (clicks == 2 && !fIgnoreDoubleClick)
1025 videoWindow->ToggleInterfaceShowing(); */
1026 fIgnoreDoubleClick = false;
1030 if (buttons & B_SECONDARY_MOUSE_BUTTON)
1032 // clicks will be 2 next time (if interval short enough)
1033 // even if the first click and the second
1034 // have not been made with the same mouse button
1035 fIgnoreDoubleClick = true;
1036 // launch popup menu
1037 BPopUpMenu *menu = new BPopUpMenu("context menu");
1038 menu->SetRadioMode(false);
1039 // In full screen, add an item to show/hide the interface
1040 if( videoWindow->IsFullScreen() )
1042 BMenuItem *intfItem =
1043 new BMenuItem( _("Show Interface"), new BMessage(SHOW_INTERFACE) );
1044 menu->AddItem( intfItem );
1047 BMenuItem *halfItem = new BMenuItem(_("50%"), new BMessage(RESIZE_50));
1048 menu->AddItem(halfItem);
1050 BMenuItem *origItem = new BMenuItem(_("100%"), new BMessage(RESIZE_100));
1051 menu->AddItem(origItem);
1053 BMenuItem *doubleItem = new BMenuItem(_("200%"), new BMessage(RESIZE_200));
1054 menu->AddItem(doubleItem);
1055 // Toggle FullScreen
1056 BMenuItem *zoomItem = new BMenuItem(_("Fullscreen"), new BMessage(TOGGLE_FULL_SCREEN));
1057 zoomItem->SetMarked(videoWindow->IsFullScreen());
1058 menu->AddItem(zoomItem);
1060 menu->AddSeparatorItem();
1063 BMenuItem *vsyncItem = new BMenuItem(_("Vertical Sync"), new BMessage(VERT_SYNC));
1064 vsyncItem->SetMarked(videoWindow->IsSyncedToRetrace());
1065 menu->AddItem(vsyncItem);
1066 // Correct Aspect Ratio
1067 BMenuItem *aspectItem = new BMenuItem(_("Correct Aspect Ratio"), new BMessage(ASPECT_CORRECT));
1068 aspectItem->SetMarked(videoWindow->CorrectAspectRatio());
1069 menu->AddItem(aspectItem);
1071 menu->AddSeparatorItem();
1073 // Window Feel Items
1074 /* BMessage *winNormFeel = new BMessage(WINDOW_FEEL);
1075 winNormFeel->AddInt32("WinFeel", (int32_t)B_NORMAL_WINDOW_FEEL);
1076 BMenuItem *normWindItem = new BMenuItem("Normal Window", winNormFeel);
1077 normWindItem->SetMarked(videoWindow->Feel() == B_NORMAL_WINDOW_FEEL);
1078 menu->AddItem(normWindItem);
1080 BMessage *winFloatFeel = new BMessage(WINDOW_FEEL);
1081 winFloatFeel->AddInt32("WinFeel", (int32_t)B_FLOATING_APP_WINDOW_FEEL);
1082 BMenuItem *onTopWindItem = new BMenuItem("App Top", winFloatFeel);
1083 onTopWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_APP_WINDOW_FEEL);
1084 menu->AddItem(onTopWindItem);
1086 BMessage *winAllFeel = new BMessage(WINDOW_FEEL);
1087 winAllFeel->AddInt32("WinFeel", (int32_t)B_FLOATING_ALL_WINDOW_FEEL);
1088 BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel);
1089 allSpacesWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL);
1090 menu->AddItem(allSpacesWindItem);*/
1092 BMessage *windowFeelMsg = new BMessage( WINDOW_FEEL );
1093 bool onTop = videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL;
1094 window_feel feel = onTop ? B_NORMAL_WINDOW_FEEL : B_FLOATING_ALL_WINDOW_FEEL;
1095 windowFeelMsg->AddInt32( "WinFeel", (int32_t)feel );
1096 BMenuItem *windowFeelItem = new BMenuItem( _("Stay On Top"), windowFeelMsg );
1097 windowFeelItem->SetMarked( onTop );
1098 menu->AddItem( windowFeelItem );
1100 menu->AddSeparatorItem();
1102 BMenuItem* screenShotItem = new BMenuItem( _("Take Screen Shot"),
1103 new BMessage( SCREEN_SHOT ) );
1104 menu->AddItem( screenShotItem );
1106 menu->SetTargetForItems( this );
1107 ConvertToScreen( &where );
1108 BRect mouseRect( where.x - 5, where.y - 5,
1109 where.x + 5, where.y + 5 );
1110 menu->Go( where, true, false, mouseRect, true );
1114 fLastMouseMovedTime = mdate();
1115 fCursorHidden = false;
1118 /*****************************************************************************
1120 *****************************************************************************/
1122 VLCView::MouseUp( BPoint where )
1124 var_SetBool( p_vout, "mouse-clicked", true );
1127 /*****************************************************************************
1128 * VLCVIew::MouseMoved
1129 *****************************************************************************/
1131 VLCView::MouseMoved(BPoint point, uint32 transit, const BMessage* dragMessage)
1133 fLastMouseMovedTime = mdate();
1134 fCursorHidden = false;
1135 fCursorInside = ( transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW );
1137 if( !fCursorInside )
1143 unsigned int i_width, i_height, i_x, i_y;
1144 vout_PlacePicture( p_vout, (unsigned int)Bounds().Width(),
1145 (unsigned int)Bounds().Height(),
1146 &i_x, &i_y, &i_width, &i_height );
1147 val.i_int = ( (int)point.x - i_x ) * p_vout->render.i_width / i_width;
1148 var_Set( p_vout, "mouse-x", val );
1149 val.i_int = ( (int)point.y - i_y ) * p_vout->render.i_height / i_height;
1150 var_Set( p_vout, "mouse-y", val );
1152 var_Set( p_vout, "mouse-moved", val );
1155 /*****************************************************************************
1157 *****************************************************************************/
1161 // We are getting the pulse messages no matter if the mouse is over
1162 // this view. If we are in full screen mode, we want to hide the cursor
1163 // even if it is not.
1164 VideoWindow *videoWindow = dynamic_cast<VideoWindow*>(Window());
1168 && mdate() - fLastMouseMovedTime > fMouseHideTimeout)
1170 be_app->ObscureCursor();
1171 fCursorHidden = true;
1173 // hide the interface window as well if full screen
1174 if (videoWindow && videoWindow->IsFullScreen())
1175 videoWindow->SetInterfaceShowing(false);
1179 // Workaround to disable the screensaver in full screen:
1180 // we simulate an activity every 29 seconds
1181 if( videoWindow && videoWindow->IsFullScreen() &&
1182 mdate() - fLastMouseMovedTime > 29000000 )
1186 GetMouse(&where, &buttons, false);
1187 ConvertToScreen(&where);
1188 set_mouse_position((int32_t) where.x, (int32_t) where.y);
1192 /*****************************************************************************
1194 *****************************************************************************/
1196 VLCView::Draw(BRect updateRect)
1198 VideoWindow* window = dynamic_cast<VideoWindow*>( Window() );
1199 if ( window && window->mode == BITMAP )
1200 FillRect( updateRect );
1203 /*****************************************************************************
1205 *****************************************************************************/
1206 static int Init ( vout_thread_t * );
1207 static void End ( vout_thread_t * );
1208 static int Manage ( vout_thread_t * );
1209 static void Display ( vout_thread_t *, picture_t * );
1210 static int Control ( vout_thread_t *, int, va_list );
1212 static int BeosOpenDisplay ( vout_thread_t *p_vout );
1213 static void BeosCloseDisplay( vout_thread_t *p_vout );
1215 /*****************************************************************************
1216 * OpenVideo: allocates BeOS video thread output method
1217 *****************************************************************************
1218 * This function allocates and initializes a BeOS vout method.
1219 *****************************************************************************/
1220 int OpenVideo ( vlc_object_t *p_this )
1222 vout_thread_t * p_vout = (vout_thread_t *)p_this;
1224 /* Allocate structure */
1225 p_vout->p_sys = (vout_sys_t*) malloc( sizeof( vout_sys_t ) );
1226 if( p_vout->p_sys == NULL )
1228 p_vout->p_sys->i_width = p_vout->render.i_width;
1229 p_vout->p_sys->i_height = p_vout->render.i_height;
1230 p_vout->p_sys->source_chroma = p_vout->render.i_chroma;
1232 p_vout->pf_init = Init;
1233 p_vout->pf_end = End;
1234 p_vout->pf_manage = Manage;
1235 p_vout->pf_render = NULL;
1236 p_vout->pf_display = Display;
1237 p_vout->pf_control = Control;
1242 /*****************************************************************************
1243 * Init: initialize BeOS video thread output method
1244 *****************************************************************************/
1245 int Init( vout_thread_t *p_vout )
1250 I_OUTPUTPICTURES = 0;
1252 /* Open and initialize device */
1253 if( BeosOpenDisplay( p_vout ) )
1255 msg_Err(p_vout, "vout error: can't open display");
1258 p_vout->output.i_width = p_vout->render.i_width;
1259 p_vout->output.i_height = p_vout->render.i_height;
1261 /* Assume we have square pixels */
1262 p_vout->output.i_aspect = p_vout->p_sys->i_width
1263 * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
1264 p_vout->output.i_chroma = colspace[p_vout->p_sys->p_window->colspace_index].chroma;
1265 p_vout->p_sys->i_index = 0;
1267 p_vout->output.i_rmask = 0x00ff0000;
1268 p_vout->output.i_gmask = 0x0000ff00;
1269 p_vout->output.i_bmask = 0x000000ff;
1271 for( int buffer_index = 0 ;
1272 buffer_index < p_vout->p_sys->p_window->bitmap_count;
1276 /* Find an empty picture slot */
1277 for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
1280 if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
1282 p_pic = p_vout->p_picture + i_index;
1291 p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[buffer_index]->Bits();
1292 p_pic->p->i_lines = p_vout->p_sys->i_height;
1293 p_pic->p->i_visible_lines = p_vout->p_sys->i_height;
1295 p_pic->p->i_pixel_pitch = colspace[p_vout->p_sys->p_window->colspace_index].pixel_bytes;
1296 p_pic->i_planes = colspace[p_vout->p_sys->p_window->colspace_index].planes;
1297 p_pic->p->i_pitch = p_vout->p_sys->p_window->bitmap[buffer_index]->BytesPerRow();
1298 p_pic->p->i_visible_pitch = p_pic->p->i_pixel_pitch * ( p_vout->p_sys->p_window->bitmap[buffer_index]->Bounds().IntegerWidth() + 1 );
1300 p_pic->i_status = DESTROYED_PICTURE;
1301 p_pic->i_type = DIRECT_PICTURE;
1303 PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
1311 /*****************************************************************************
1312 * End: terminate BeOS video thread output method
1313 *****************************************************************************/
1314 void End( vout_thread_t *p_vout )
1316 BeosCloseDisplay( p_vout );
1319 /*****************************************************************************
1321 *****************************************************************************/
1322 static int Manage( vout_thread_t * p_vout )
1324 if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
1326 p_vout->p_sys->p_window->PostMessage( TOGGLE_FULL_SCREEN );
1327 p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
1333 /*****************************************************************************
1334 * CloseVideo: destroy BeOS video thread output method
1335 *****************************************************************************
1336 * Terminate an output method created by DummyCreateOutputMethod
1337 *****************************************************************************/
1338 void CloseVideo ( vlc_object_t *p_this )
1340 vout_thread_t * p_vout = (vout_thread_t *)p_this;
1342 free( p_vout->p_sys );
1345 /*****************************************************************************
1346 * Display: displays previously rendered output
1347 *****************************************************************************
1348 * This function send the currently rendered image to BeOS image, waits until
1349 * it is displayed and switch the two rendering buffers, preparing next frame.
1350 *****************************************************************************/
1351 void Display( vout_thread_t *p_vout, picture_t *p_pic )
1353 VideoWindow * p_win = p_vout->p_sys->p_window;
1355 /* draw buffer if required */
1356 if (!p_win->teardownwindow)
1358 p_win->drawBuffer(p_vout->p_sys->i_index);
1361 p_vout->p_sys->i_index = ++p_vout->p_sys->i_index %
1362 p_vout->p_sys->p_window->bitmap_count;
1363 p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[p_vout->p_sys->i_index]->Bits();
1366 static int Control( vout_thread_t * p_vout, int i_query, va_list args )
1368 return VLC_EGENERIC;
1371 /* following functions are local */
1373 /*****************************************************************************
1374 * BeosOpenDisplay: open and initialize BeOS device
1375 *****************************************************************************/
1376 static int BeosOpenDisplay( vout_thread_t *p_vout )
1379 p_vout->p_sys->p_window = new VideoWindow( p_vout->p_sys->i_width - 1,
1380 p_vout->p_sys->i_height - 1,
1382 20 + p_vout->i_window_width - 1,
1383 50 + p_vout->i_window_height - 1 ),
1385 if( p_vout->p_sys->p_window == NULL )
1387 msg_Err( p_vout, "cannot allocate VideoWindow" );
1392 p_vout->p_sys->p_window->Show();
1398 /*****************************************************************************
1399 * BeosDisplay: close and reset BeOS device
1400 *****************************************************************************
1401 * Returns all resources allocated by BeosOpenDisplay and restore the original
1402 * state of the device.
1403 *****************************************************************************/
1404 static void BeosCloseDisplay( vout_thread_t *p_vout )
1406 VideoWindow * p_win = p_vout->p_sys->p_window;
1407 /* Destroy the video window */
1408 if( p_win != NULL && !p_win->teardownwindow)
1411 p_win->teardownwindow = true;