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>
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 MOUSE_IDLE_TIMEOUT 2000000 // two seconds
81 #define MIN_AUTO_VSYNC_REFRESH 61 // Hz
83 /*****************************************************************************
84 * beos_GetAppWindow : retrieve a BWindow pointer from the window name
85 *****************************************************************************/
87 beos_GetAppWindow(char *name)
92 for (index = 0 ; ; index++)
94 window = be_app->WindowAt(index);
97 if (window->LockWithTimeout(20000) == B_OK)
99 if (strcmp(window->Name(), name) == 0)
110 static const int beos_keys[][2] =
112 { B_LEFT_ARROW, KEY_LEFT },
113 { B_RIGHT_ARROW, KEY_RIGHT },
114 { B_UP_ARROW, KEY_UP },
115 { B_DOWN_ARROW, KEY_DOWN },
116 { B_SPACE, KEY_SPACE },
117 { B_ENTER, KEY_ENTER },
118 { B_F1_KEY, KEY_F1 },
119 { B_F2_KEY, KEY_F2 },
120 { B_F3_KEY, KEY_F3 },
121 { B_F4_KEY, KEY_F4 },
122 { B_F5_KEY, KEY_F5 },
123 { B_F6_KEY, KEY_F6 },
124 { B_F7_KEY, KEY_F7 },
125 { B_F8_KEY, KEY_F8 },
126 { B_F9_KEY, KEY_F9 },
127 { B_F10_KEY, KEY_F10 },
128 { B_F11_KEY, KEY_F11 },
129 { B_F12_KEY, KEY_F12 },
130 { B_HOME, KEY_HOME },
132 { B_ESCAPE, KEY_ESC },
133 { B_PAGE_UP, KEY_PAGEUP },
134 { B_PAGE_DOWN, KEY_PAGEDOWN },
136 { B_BACKSPACE, KEY_BACKSPACE }
139 static int ConvertKeyFromVLC( int key )
141 for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
143 if( beos_keys[i][1] == key )
145 return beos_keys[i][0];
151 static int ConvertKeyToVLC( int key )
153 for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
155 if( beos_keys[i][0] == key )
157 return beos_keys[i][1];
163 /*****************************************************************************
164 * get_interface_window
165 *****************************************************************************/
167 get_interface_window()
169 return beos_GetAppWindow( "VLC " PACKAGE_VERSION );
172 class BackgroundView : public BView
175 BackgroundView(BRect frame, VLCView* view)
176 : BView(frame, "background",
177 B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE),
180 SetViewColor(kBlack);
182 virtual ~BackgroundView() {}
184 virtual void MouseDown(BPoint where)
186 // convert coordinates
187 where = fVideoView->ConvertFromParent(where);
189 fVideoView->MouseDown(where);
191 virtual void MouseMoved(BPoint where, uint32_t transit,
192 const BMessage* dragMessage)
194 // convert coordinates
195 where = fVideoView->ConvertFromParent(where);
197 fVideoView->MouseMoved(where, transit, dragMessage);
198 // notice: It might look like transit should be
199 // B_OUTSIDE_VIEW regardless, but leave it like this,
200 // otherwise, unwanted things will happen!
208 /*****************************************************************************
209 * VideoSettings constructor and destructor
210 *****************************************************************************/
211 VideoSettings::VideoSettings()
212 : fVideoSize( SIZE_100 ),
213 fFlags( FLAG_CORRECT_RATIO ),
214 fSettings( new BMessage( 'sett' ) )
216 // read settings from disk
217 status_t ret = load_settings( fSettings, "video_settings", "VideoLAN Client" );
221 if ( fSettings->FindInt32( "flags", (int32*)&flags ) == B_OK )
224 if ( fSettings->FindInt32( "video size", (int32*)&size ) == B_OK )
225 SetVideoSize( size );
229 // figure out if we should use vertical sync by default
230 BScreen screen(B_MAIN_SCREEN_ID);
231 if (screen.IsValid())
234 screen.GetMode(&mode);
235 float refresh = (mode.timing.pixel_clock * 1000)
236 / ((mode.timing.h_total)* (mode.timing.v_total));
237 if (refresh < MIN_AUTO_VSYNC_REFRESH)
238 AddFlags(FLAG_SYNC_RETRACE);
243 VideoSettings::VideoSettings( const VideoSettings& clone )
244 : fVideoSize( clone.VideoSize() ),
245 fFlags( clone.Flags() ),
251 VideoSettings::~VideoSettings()
255 // we are the default settings
256 // and write our settings to disk
257 if (fSettings->ReplaceInt32( "video size", VideoSize() ) != B_OK)
258 fSettings->AddInt32( "video size", VideoSize() );
259 if (fSettings->ReplaceInt32( "flags", Flags() ) != B_OK)
260 fSettings->AddInt32( "flags", Flags() );
262 save_settings( fSettings, "video_settings", "VideoLAN Client" );
267 // we are just a clone of the default settings
268 fDefaultSettings.SetVideoSize( VideoSize() );
269 fDefaultSettings.SetFlags( Flags() );
273 /*****************************************************************************
274 * VideoSettings::DefaultSettings
275 *****************************************************************************/
277 VideoSettings::DefaultSettings()
279 return &fDefaultSettings;
282 /*****************************************************************************
283 * VideoSettings::SetVideoSize
284 *****************************************************************************/
286 VideoSettings::SetVideoSize( uint32_t mode )
291 // static variable initialization
293 VideoSettings::fDefaultSettings;
296 /*****************************************************************************
297 * VideoWindow constructor and destructor
298 *****************************************************************************/
299 VideoWindow::VideoWindow(int v_width, int v_height, BRect frame,
300 vout_thread_t *p_videoout)
301 : BWindow(frame, NULL, B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_MINIMIZABLE),
302 i_width(frame.IntegerWidth()),
303 i_height(frame.IntegerHeight()),
306 teardownwindow(false),
308 fTrueHeight(v_height),
309 fCachedFeel(B_NORMAL_WINDOW_FEEL),
310 fInterfaceShowing(false),
311 fInitStatus(B_ERROR),
312 fSettings(new VideoSettings(*VideoSettings::DefaultSettings()))
316 // create the view to do the display
317 view = new VLCView( Bounds(), p_vout );
319 // create background view
320 BView *mainView = new BackgroundView( Bounds(), view );
322 mainView->AddChild(view);
324 // allocate bitmap buffers
325 for (int32_t i = 0; i < 3; i++)
327 fInitStatus = _AllocateBuffers(v_width, v_height, &mode);
329 // make sure we layout the view correctly
330 FrameResized(i_width, i_height);
332 if (fInitStatus >= B_OK && mode == OVERLAY)
334 overlay_restrictions r;
336 bitmap[0]->GetOverlayRestrictions(&r);
337 SetSizeLimits((i_width * r.min_width_scale), i_width * r.max_width_scale,
338 (i_height * r.min_height_scale), i_height * r.max_height_scale);
341 // vlc settings override settings from disk
342 if (config_GetInt(p_vout, "fullscreen"))
343 fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
348 VideoWindow::~VideoWindow()
352 teardownwindow = true;
353 wait_for_thread(fDrawThreadID, &result);
358 /*****************************************************************************
359 * VideoWindow::MessageReceived
360 *****************************************************************************/
362 VideoWindow::MessageReceived( BMessage *p_message )
364 switch( p_message->what )
367 SetInterfaceShowing( true );
369 case TOGGLE_FULL_SCREEN:
377 _SetVideoSize(p_message->what);
380 SetSyncToRetrace(!IsSyncedToRetrace());
385 if (p_message->FindInt32("WinFeel", (int32*)&winFeel) == B_OK)
388 fCachedFeel = winFeel;
389 if (winFeel == B_FLOATING_ALL_WINDOW_FEEL)
390 fSettings->AddFlags(VideoSettings::FLAG_ON_TOP_ALL);
392 fSettings->ClearFlags(VideoSettings::FLAG_ON_TOP_ALL);
397 SetCorrectAspectRatio(!CorrectAspectRatio());
401 case B_UNMAPPED_KEY_DOWN:
403 case B_UNMAPPED_KEY_UP:
407 int32 key, modifiers;
409 if( p_message->FindInt32( "key", &key ) != B_OK ||
410 p_message->FindInt32( "modifiers", &modifiers ) != B_OK )
412 /* Shouldn't happen */
416 if( ( p_message->what == B_KEY_UP ||
417 p_message->what == B_UNMAPPED_KEY_UP ) &&
418 !( modifiers & B_COMMAND_KEY ) )
420 /* We only use the KEY_UP messages to detect Alt+X
421 shortcuts (because the KEY_DOWN messages aren't
422 sent when Alt is pressed) */
426 /* Special case for Alt+1, Alt+2 and Alt+3 shortcuts: since
427 the character depends on the keymap, we use the key codes
428 directly (18, 19, 20) */
429 if( ( modifiers & B_COMMAND_KEY ) &&
430 key >= 18 && key <= 20 )
433 PostMessage( RESIZE_50 );
435 PostMessage( RESIZE_100 );
437 PostMessage( RESIZE_200 );
442 /* Get the current keymap */
443 get_key_map( &keys, &chars );
445 if( key >= 128 || chars[keys->normal_map[key]] != 1 )
447 /* Weird key or Unicode character */
454 val.i_int = ConvertKeyToVLC( chars[keys->normal_map[key]+1] );
456 if( modifiers & B_COMMAND_KEY )
458 val.i_int |= KEY_MODIFIER_ALT;
460 if( modifiers & B_SHIFT_KEY )
462 val.i_int |= KEY_MODIFIER_SHIFT;
464 if( modifiers & B_CONTROL_KEY )
466 val.i_int |= KEY_MODIFIER_CTRL;
468 var_Set( p_vout->p_libvlc, "key-pressed", val );
476 BWindow::MessageReceived( p_message );
481 /*****************************************************************************
483 *****************************************************************************/
485 VideoWindow::Zoom(BPoint origin, float width, float height )
490 /*****************************************************************************
491 * VideoWindow::FrameMoved
492 *****************************************************************************/
494 VideoWindow::FrameMoved(BPoint origin)
501 /*****************************************************************************
502 * VideoWindow::FrameResized
503 *****************************************************************************/
505 VideoWindow::FrameResized( float width, float height )
507 int32_t useWidth = CorrectAspectRatio() ? i_width : fTrueWidth;
508 int32_t useHeight = CorrectAspectRatio() ? i_height : fTrueHeight;
509 float out_width, out_height;
510 float out_left, out_top;
511 float width_scale = width / useWidth;
512 float height_scale = height / useHeight;
514 if (width_scale <= height_scale)
516 out_width = (useWidth * width_scale);
517 out_height = (useHeight * width_scale);
519 out_top = (height - out_height) / 2;
521 else /* if the height is proportionally smaller */
523 out_width = (useWidth * height_scale);
524 out_height = (useHeight * height_scale);
526 out_left = (width - out_width) / 2;
528 view->MoveTo(out_left,out_top);
529 view->ResizeTo(out_width, out_height);
535 /*****************************************************************************
536 * VideoWindow::ScreenChanged
537 *****************************************************************************/
539 VideoWindow::ScreenChanged(BRect frame, color_space format)
541 BScreen screen(this);
543 screen.GetMode(&mode);
544 float refresh = (mode.timing.pixel_clock * 1000)
545 / ((mode.timing.h_total) * (mode.timing.v_total));
546 SetSyncToRetrace(refresh < MIN_AUTO_VSYNC_REFRESH);
549 /*****************************************************************************
550 * VideoWindow::Activate
551 *****************************************************************************/
553 VideoWindow::WindowActivated(bool active)
557 /*****************************************************************************
558 * VideoWindow::drawBuffer
559 *****************************************************************************/
561 VideoWindow::drawBuffer(int bufferIndex)
563 i_buffer = bufferIndex;
565 // sync to the screen if required
566 if (IsSyncedToRetrace())
568 BScreen screen(this);
569 screen.WaitForRetrace(22000);
571 if (fInitStatus >= B_OK && LockLooper())
573 // switch the overlay bitmap
577 view->SetViewOverlay(bitmap[i_buffer],
578 bitmap[i_buffer]->Bounds() ,
581 B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL|
582 B_OVERLAY_TRANSFER_CHANNEL);
583 view->SetViewColor(key);
588 view->DrawBitmap(bitmap[i_buffer], view->Bounds() );
594 /*****************************************************************************
595 * VideoWindow::SetInterfaceShowing
596 *****************************************************************************/
598 VideoWindow::ToggleInterfaceShowing()
600 SetInterfaceShowing(!fInterfaceShowing);
603 /*****************************************************************************
604 * VideoWindow::SetInterfaceShowing
605 *****************************************************************************/
607 VideoWindow::SetInterfaceShowing(bool showIt)
609 BWindow* window = get_interface_window();
614 if (fCachedFeel != B_NORMAL_WINDOW_FEEL)
615 SetFeel(B_NORMAL_WINDOW_FEEL);
616 window->Activate(true);
621 SetFeel(fCachedFeel);
623 window->SendBehind(this);
625 fInterfaceShowing = showIt;
629 /*****************************************************************************
630 * VideoWindow::SetCorrectAspectRatio
631 *****************************************************************************/
633 VideoWindow::SetCorrectAspectRatio(bool doIt)
635 if (CorrectAspectRatio() != doIt)
638 fSettings->AddFlags(VideoSettings::FLAG_CORRECT_RATIO);
640 fSettings->ClearFlags(VideoSettings::FLAG_CORRECT_RATIO);
641 FrameResized(Bounds().Width(), Bounds().Height());
645 /*****************************************************************************
646 * VideoWindow::CorrectAspectRatio
647 *****************************************************************************/
649 VideoWindow::CorrectAspectRatio() const
651 return fSettings->HasFlags(VideoSettings::FLAG_CORRECT_RATIO);
654 /*****************************************************************************
655 * VideoWindow::ToggleFullScreen
656 *****************************************************************************/
658 VideoWindow::ToggleFullScreen()
660 SetFullScreen(!IsFullScreen());
663 /*****************************************************************************
664 * VideoWindow::SetFullScreen
665 *****************************************************************************/
667 VideoWindow::SetFullScreen(bool doIt)
671 SetLook( B_NO_BORDER_WINDOW_LOOK );
672 BScreen screen( this );
673 BRect rect = screen.Frame();
676 ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
677 be_app->ObscureCursor();
678 fInterfaceShowing = false;
679 fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
683 SetLook( B_TITLED_WINDOW_LOOK );
684 MoveTo(winSize.left, winSize.top);
685 ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
686 be_app->ShowCursor();
687 fInterfaceShowing = true;
688 fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
692 /*****************************************************************************
693 * VideoWindow::IsFullScreen
694 *****************************************************************************/
696 VideoWindow::IsFullScreen() const
698 return fSettings->HasFlags(VideoSettings::FLAG_FULL_SCREEN);
701 /*****************************************************************************
702 * VideoWindow::SetSyncToRetrace
703 *****************************************************************************/
705 VideoWindow::SetSyncToRetrace(bool doIt)
708 fSettings->AddFlags(VideoSettings::FLAG_SYNC_RETRACE);
710 fSettings->ClearFlags(VideoSettings::FLAG_SYNC_RETRACE);
713 /*****************************************************************************
714 * VideoWindow::IsSyncedToRetrace
715 *****************************************************************************/
717 VideoWindow::IsSyncedToRetrace() const
719 return fSettings->HasFlags(VideoSettings::FLAG_SYNC_RETRACE);
723 /*****************************************************************************
724 * VideoWindow::_AllocateBuffers
725 *****************************************************************************/
727 VideoWindow::_AllocateBuffers(int width, int height, int* mode)
729 // clear any old buffers
735 BRect bitmapFrame( 0, 0, width, height );
736 // read from config, if we are supposed to use overlay at all
737 int noOverlay = !config_GetInt( p_vout, "overlay" );
739 /* Test for overlay capability: for every chroma in colspace,
740 we try to do double-buffered overlay, single-buffered overlay
741 or basic overlay. If nothing worked, we then have to work with
742 a non-overlay BBitmap. */
743 for( int i = 0; i < COLOR_COUNT; i++ )
748 bitmap[0] = new BBitmap( bitmapFrame,
749 B_BITMAP_WILL_OVERLAY |
750 B_BITMAP_RESERVE_OVERLAY_CHANNEL,
751 colspace[i].colspace );
752 if( bitmap[0] && bitmap[0]->InitCheck() == B_OK )
758 view->SetViewOverlay( bitmap[0], bitmap[0]->Bounds(),
759 view->Bounds(), &key, B_FOLLOW_ALL,
760 B_OVERLAY_FILTER_HORIZONTAL |
761 B_OVERLAY_FILTER_VERTICAL );
762 view->SetViewColor( key );
763 SetTitle( "VLC " PACKAGE_VERSION " (Overlay)" );
765 bitmap[1] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
766 colspace[colspace_index].colspace);
767 if( bitmap[1] && bitmap[1]->InitCheck() == B_OK )
770 bitmap[2] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
771 colspace[colspace_index].colspace);
772 if( bitmap[2] && bitmap[2]->InitCheck() == B_OK )
774 msg_Dbg( p_vout, "using double-buffered overlay" );
778 msg_Dbg( p_vout, "using single-buffered overlay" );
780 if( bitmap[2] ) { delete bitmap[2]; bitmap[2] = NULL; }
785 msg_Dbg( p_vout, "using simple overlay" );
787 if( bitmap[1] ) { delete bitmap[1]; bitmap[1] = NULL; }
793 if( bitmap[0] ) { delete bitmap[0]; bitmap[0] = NULL; }
799 msg_Warn( p_vout, "no possible overlay" );
802 colspace_index = DEFAULT_COL; // B_RGB32
803 bitmap[0] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
804 bitmap[1] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
805 bitmap[2] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
806 SetTitle( "VLC " PACKAGE_VERSION " (Bitmap)" );
808 // see if everything went well
809 status_t status = B_ERROR;
810 for (int32_t i = 0; i < bitmap_count; i++)
813 status = bitmap[i]->InitCheck();
819 // clear bitmaps to black
820 for (int32_t i = 0; i < bitmap_count; i++)
821 _BlankBitmap(bitmap[i]);
826 /*****************************************************************************
827 * VideoWindow::_FreeBuffers
828 *****************************************************************************/
830 VideoWindow::_FreeBuffers()
832 if( bitmap[0] ) { delete bitmap[0]; bitmap[0] = NULL; }
833 if( bitmap[1] ) { delete bitmap[1]; bitmap[1] = NULL; }
834 if( bitmap[2] ) { delete bitmap[2]; bitmap[2] = NULL; }
835 fInitStatus = B_ERROR;
838 /*****************************************************************************
839 * VideoWindow::_BlankBitmap
840 *****************************************************************************/
842 VideoWindow::_BlankBitmap(BBitmap* bitmap) const
844 // no error checking (we do that earlier on and since it's a private function...
847 // Loss/Saturation points are Y 16-235 (absoulte); Cb/Cr 16-240 (center 128)
850 // Extrema points are Y 0 - 207 (absolute) U -91 - 91 (offset 128) V -127 - 127 (offset 128)
852 // we only handle weird colorspaces with special care
853 switch (bitmap->ColorSpace()) {
855 // Y0[7:0] Cb0[7:0] Y1[7:0] Cr0[7:0] Y2[7:0] Cb2[7:0] Y3[7:0] Cr2[7:0]
856 int32_t height = bitmap->Bounds().IntegerHeight() + 1;
857 uint8_t* bits = (uint8_t*)bitmap->Bits();
858 int32_t bpr = bitmap->BytesPerRow();
859 for (int32_t y = 0; y < height; y++) {
860 // handle 2 bytes at a time
861 for (int32_t i = 0; i < bpr; i += 2) {
873 // Non-interlaced only, Cb0 Y0 Y1 Cb2 Y2 Y3 on even scan lines ...
874 // Cr0 Y0 Y1 Cr2 Y2 Y3 on odd scan lines
875 int32_t height = bitmap->Bounds().IntegerHeight() + 1;
876 uint8_t* bits = (uint8_t*)bitmap->Bits();
877 int32_t bpr = bitmap->BytesPerRow();
878 for (int32_t y = 0; y < height; y += 1) {
879 // handle 3 bytes at a time
880 for (int32_t i = 0; i < bpr; i += 3) {
893 // U0[7:0] Y0[7:0] V0[7:0] Y1[7:0] U2[7:0] Y2[7:0] V2[7:0] Y3[7:0]
894 int32_t height = bitmap->Bounds().IntegerHeight() + 1;
895 uint8_t* bits = (uint8_t*)bitmap->Bits();
896 int32_t bpr = bitmap->BytesPerRow();
897 for (int32_t y = 0; y < height; y += 1) {
898 // handle 2 bytes at a time
899 for (int32_t i = 0; i < bpr; i += 2) {
910 memset(bitmap->Bits(), 0, bitmap->BitsLength());
915 /*****************************************************************************
916 * VideoWindow::_SetVideoSize
917 *****************************************************************************/
919 VideoWindow::_SetVideoSize(uint32_t mode)
921 // let size depend on aspect correction
922 int32_t width = CorrectAspectRatio() ? i_width : fTrueWidth;
923 int32_t height = CorrectAspectRatio() ? i_height : fTrueHeight;
938 fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
939 ResizeTo(width, height);
942 /*****************************************************************************
943 * VideoWindow::_SetToSettings
944 *****************************************************************************/
946 VideoWindow::_SetToSettings()
949 uint32_t mode = RESIZE_100;
950 switch (fSettings->VideoSize())
952 case VideoSettings::SIZE_50:
955 case VideoSettings::SIZE_200:
958 case VideoSettings::SIZE_100:
959 case VideoSettings::SIZE_OTHER:
963 bool fullscreen = IsFullScreen(); // remember settings
964 _SetVideoSize(mode); // because this will reset settings
965 // the fullscreen status is reflected in the settings,
966 // but not yet in the windows state
969 if (fSettings->HasFlags(VideoSettings::FLAG_ON_TOP_ALL))
970 fCachedFeel = B_FLOATING_ALL_WINDOW_FEEL;
972 fCachedFeel = B_NORMAL_WINDOW_FEEL;
973 SetFeel(fCachedFeel);
976 /*****************************************************************************
978 *****************************************************************************/
979 VLCView::VLCView(BRect bounds, vout_thread_t *p_vout_instance )
980 : BView(bounds, "video view", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED),
981 fLastMouseMovedTime(mdate()),
982 fCursorHidden(false),
983 fCursorInside(false),
984 fIgnoreDoubleClick(false)
986 p_vout = p_vout_instance;
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 )
1127 val.b_bool = VLC_TRUE;
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 );
1155 val.b_bool = VLC_TRUE;
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 > MOUSE_IDLE_TIMEOUT)
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 E_(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->b_direct = 1;
1276 p_vout->output.i_rmask = 0x00ff0000;
1277 p_vout->output.i_gmask = 0x0000ff00;
1278 p_vout->output.i_bmask = 0x000000ff;
1280 for( int buffer_index = 0 ;
1281 buffer_index < p_vout->p_sys->p_window->bitmap_count;
1285 /* Find an empty picture slot */
1286 for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
1289 if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
1291 p_pic = p_vout->p_picture + i_index;
1300 p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[buffer_index]->Bits();
1301 p_pic->p->i_lines = p_vout->p_sys->i_height;
1302 p_pic->p->i_visible_lines = p_vout->p_sys->i_height;
1304 p_pic->p->i_pixel_pitch = colspace[p_vout->p_sys->p_window->colspace_index].pixel_bytes;
1305 p_pic->i_planes = colspace[p_vout->p_sys->p_window->colspace_index].planes;
1306 p_pic->p->i_pitch = p_vout->p_sys->p_window->bitmap[buffer_index]->BytesPerRow();
1307 p_pic->p->i_visible_pitch = p_pic->p->i_pixel_pitch * ( p_vout->p_sys->p_window->bitmap[buffer_index]->Bounds().IntegerWidth() + 1 );
1309 p_pic->i_status = DESTROYED_PICTURE;
1310 p_pic->i_type = DIRECT_PICTURE;
1312 PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
1320 /*****************************************************************************
1321 * End: terminate BeOS video thread output method
1322 *****************************************************************************/
1323 void End( vout_thread_t *p_vout )
1325 BeosCloseDisplay( p_vout );
1328 /*****************************************************************************
1330 *****************************************************************************/
1331 static int Manage( vout_thread_t * p_vout )
1333 if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
1335 p_vout->p_sys->p_window->PostMessage( TOGGLE_FULL_SCREEN );
1336 p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
1342 /*****************************************************************************
1343 * CloseVideo: destroy BeOS video thread output method
1344 *****************************************************************************
1345 * Terminate an output method created by DummyCreateOutputMethod
1346 *****************************************************************************/
1347 void E_(CloseVideo) ( vlc_object_t *p_this )
1349 vout_thread_t * p_vout = (vout_thread_t *)p_this;
1351 free( p_vout->p_sys );
1354 /*****************************************************************************
1355 * Display: displays previously rendered output
1356 *****************************************************************************
1357 * This function send the currently rendered image to BeOS image, waits until
1358 * it is displayed and switch the two rendering buffers, preparing next frame.
1359 *****************************************************************************/
1360 void Display( vout_thread_t *p_vout, picture_t *p_pic )
1362 VideoWindow * p_win = p_vout->p_sys->p_window;
1364 /* draw buffer if required */
1365 if (!p_win->teardownwindow)
1367 p_win->drawBuffer(p_vout->p_sys->i_index);
1370 p_vout->p_sys->i_index = ++p_vout->p_sys->i_index %
1371 p_vout->p_sys->p_window->bitmap_count;
1372 p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[p_vout->p_sys->i_index]->Bits();
1375 static int Control( vout_thread_t * p_vout, int i_query, va_list args )
1377 return vout_vaControlDefault( p_vout, i_query, args );
1380 /* following functions are local */
1382 /*****************************************************************************
1383 * BeosOpenDisplay: open and initialize BeOS device
1384 *****************************************************************************/
1385 static int BeosOpenDisplay( vout_thread_t *p_vout )
1388 p_vout->p_sys->p_window = new VideoWindow( p_vout->p_sys->i_width - 1,
1389 p_vout->p_sys->i_height - 1,
1391 20 + p_vout->i_window_width - 1,
1392 50 + p_vout->i_window_height - 1 ),
1394 if( p_vout->p_sys->p_window == NULL )
1396 msg_Err( p_vout, "cannot allocate VideoWindow" );
1401 p_vout->p_sys->p_window->Show();
1407 /*****************************************************************************
1408 * BeosDisplay: close and reset BeOS device
1409 *****************************************************************************
1410 * Returns all resources allocated by BeosOpenDisplay and restore the original
1411 * state of the device.
1412 *****************************************************************************/
1413 static void BeosCloseDisplay( vout_thread_t *p_vout )
1415 VideoWindow * p_win = p_vout->p_sys->p_window;
1416 /* Destroy the video window */
1417 if( p_win != NULL && !p_win->teardownwindow)
1420 p_win->teardownwindow = true;