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>
47 #include <vlc_interface.h>
51 #include "InterfaceWindow.h" // for load/save_settings()
52 #include "DrawingTidbits.h"
55 #include "VideoWindow.h"
57 /*****************************************************************************
58 * vout_sys_t: BeOS video output method descriptor
59 *****************************************************************************
60 * This structure is part of the video output thread descriptor.
61 * It describes the BeOS specific properties of an output thread.
62 *****************************************************************************/
65 VideoWindow * p_window;
70 // uint8_t *pp_buffer[3];
71 uint32_t source_chroma;
76 #define MOUSE_IDLE_TIMEOUT 2000000 // two seconds
77 #define MIN_AUTO_VSYNC_REFRESH 61 // Hz
79 /*****************************************************************************
80 * beos_GetAppWindow : retrieve a BWindow pointer from the window name
81 *****************************************************************************/
83 beos_GetAppWindow(char *name)
88 for (index = 0 ; ; index++)
90 window = be_app->WindowAt(index);
93 if (window->LockWithTimeout(20000) == B_OK)
95 if (strcmp(window->Name(), name) == 0)
106 static const int beos_keys[][2] =
108 { B_LEFT_ARROW, KEY_LEFT },
109 { B_RIGHT_ARROW, KEY_RIGHT },
110 { B_UP_ARROW, KEY_UP },
111 { B_DOWN_ARROW, KEY_DOWN },
112 { B_SPACE, KEY_SPACE },
113 { B_ENTER, KEY_ENTER },
114 { B_F1_KEY, KEY_F1 },
115 { B_F2_KEY, KEY_F2 },
116 { B_F3_KEY, KEY_F3 },
117 { B_F4_KEY, KEY_F4 },
118 { B_F5_KEY, KEY_F5 },
119 { B_F6_KEY, KEY_F6 },
120 { B_F7_KEY, KEY_F7 },
121 { B_F8_KEY, KEY_F8 },
122 { B_F9_KEY, KEY_F9 },
123 { B_F10_KEY, KEY_F10 },
124 { B_F11_KEY, KEY_F11 },
125 { B_F12_KEY, KEY_F12 },
126 { B_HOME, KEY_HOME },
128 { B_ESCAPE, KEY_ESC },
129 { B_PAGE_UP, KEY_PAGEUP },
130 { B_PAGE_DOWN, KEY_PAGEDOWN },
132 { B_BACKSPACE, KEY_BACKSPACE }
135 static int ConvertKeyFromVLC( int key )
137 for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
139 if( beos_keys[i][1] == key )
141 return beos_keys[i][0];
147 static int ConvertKeyToVLC( int key )
149 for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
151 if( beos_keys[i][0] == key )
153 return beos_keys[i][1];
159 /*****************************************************************************
160 * get_interface_window
161 *****************************************************************************/
163 get_interface_window()
165 return beos_GetAppWindow( "VLC " PACKAGE_VERSION );
168 class BackgroundView : public BView
171 BackgroundView(BRect frame, VLCView* view)
172 : BView(frame, "background",
173 B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE),
176 SetViewColor(kBlack);
178 virtual ~BackgroundView() {}
180 virtual void MouseDown(BPoint where)
182 // convert coordinates
183 where = fVideoView->ConvertFromParent(where);
185 fVideoView->MouseDown(where);
187 virtual void MouseMoved(BPoint where, uint32_t transit,
188 const BMessage* dragMessage)
190 // convert coordinates
191 where = fVideoView->ConvertFromParent(where);
193 fVideoView->MouseMoved(where, transit, dragMessage);
194 // notice: It might look like transit should be
195 // B_OUTSIDE_VIEW regardless, but leave it like this,
196 // otherwise, unwanted things will happen!
204 /*****************************************************************************
205 * VideoSettings constructor and destructor
206 *****************************************************************************/
207 VideoSettings::VideoSettings()
208 : fVideoSize( SIZE_100 ),
209 fFlags( FLAG_CORRECT_RATIO ),
210 fSettings( new BMessage( 'sett' ) )
212 // read settings from disk
213 status_t ret = load_settings( fSettings, "video_settings", "VideoLAN Client" );
217 if ( fSettings->FindInt32( "flags", (int32*)&flags ) == B_OK )
220 if ( fSettings->FindInt32( "video size", (int32*)&size ) == B_OK )
221 SetVideoSize( size );
225 // figure out if we should use vertical sync by default
226 BScreen screen(B_MAIN_SCREEN_ID);
227 if (screen.IsValid())
230 screen.GetMode(&mode);
231 float refresh = (mode.timing.pixel_clock * 1000)
232 / ((mode.timing.h_total)* (mode.timing.v_total));
233 if (refresh < MIN_AUTO_VSYNC_REFRESH)
234 AddFlags(FLAG_SYNC_RETRACE);
239 VideoSettings::VideoSettings( const VideoSettings& clone )
240 : fVideoSize( clone.VideoSize() ),
241 fFlags( clone.Flags() ),
247 VideoSettings::~VideoSettings()
251 // we are the default settings
252 // and write our settings to disk
253 if (fSettings->ReplaceInt32( "video size", VideoSize() ) != B_OK)
254 fSettings->AddInt32( "video size", VideoSize() );
255 if (fSettings->ReplaceInt32( "flags", Flags() ) != B_OK)
256 fSettings->AddInt32( "flags", Flags() );
258 save_settings( fSettings, "video_settings", "VideoLAN Client" );
263 // we are just a clone of the default settings
264 fDefaultSettings.SetVideoSize( VideoSize() );
265 fDefaultSettings.SetFlags( Flags() );
269 /*****************************************************************************
270 * VideoSettings::DefaultSettings
271 *****************************************************************************/
273 VideoSettings::DefaultSettings()
275 return &fDefaultSettings;
278 /*****************************************************************************
279 * VideoSettings::SetVideoSize
280 *****************************************************************************/
282 VideoSettings::SetVideoSize( uint32_t mode )
287 // static variable initialization
289 VideoSettings::fDefaultSettings;
292 /*****************************************************************************
293 * VideoWindow constructor and destructor
294 *****************************************************************************/
295 VideoWindow::VideoWindow(int v_width, int v_height, BRect frame,
296 vout_thread_t *p_videoout)
297 : BWindow(frame, NULL, B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_MINIMIZABLE),
298 i_width(frame.IntegerWidth()),
299 i_height(frame.IntegerHeight()),
302 teardownwindow(false),
304 fTrueHeight(v_height),
305 fCachedFeel(B_NORMAL_WINDOW_FEEL),
306 fInterfaceShowing(false),
307 fInitStatus(B_ERROR),
308 fSettings(new VideoSettings(*VideoSettings::DefaultSettings()))
312 // create the view to do the display
313 view = new VLCView( Bounds(), p_vout );
315 // create background view
316 BView *mainView = new BackgroundView( Bounds(), view );
318 mainView->AddChild(view);
320 // allocate bitmap buffers
321 for (int32_t i = 0; i < 3; i++)
323 fInitStatus = _AllocateBuffers(v_width, v_height, &mode);
325 // make sure we layout the view correctly
326 FrameResized(i_width, i_height);
328 if (fInitStatus >= B_OK && mode == OVERLAY)
330 overlay_restrictions r;
332 bitmap[0]->GetOverlayRestrictions(&r);
333 SetSizeLimits((i_width * r.min_width_scale), i_width * r.max_width_scale,
334 (i_height * r.min_height_scale), i_height * r.max_height_scale);
337 // vlc settings override settings from disk
338 if (config_GetInt(p_vout, "fullscreen"))
339 fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
344 VideoWindow::~VideoWindow()
348 teardownwindow = true;
349 wait_for_thread(fDrawThreadID, &result);
354 /*****************************************************************************
355 * VideoWindow::MessageReceived
356 *****************************************************************************/
358 VideoWindow::MessageReceived( BMessage *p_message )
360 switch( p_message->what )
363 SetInterfaceShowing( true );
365 case TOGGLE_FULL_SCREEN:
373 _SetVideoSize(p_message->what);
376 SetSyncToRetrace(!IsSyncedToRetrace());
381 if (p_message->FindInt32("WinFeel", (int32*)&winFeel) == B_OK)
384 fCachedFeel = winFeel;
385 if (winFeel == B_FLOATING_ALL_WINDOW_FEEL)
386 fSettings->AddFlags(VideoSettings::FLAG_ON_TOP_ALL);
388 fSettings->ClearFlags(VideoSettings::FLAG_ON_TOP_ALL);
393 SetCorrectAspectRatio(!CorrectAspectRatio());
397 case B_UNMAPPED_KEY_DOWN:
399 case B_UNMAPPED_KEY_UP:
403 int32 key, modifiers;
405 if( p_message->FindInt32( "key", &key ) != B_OK ||
406 p_message->FindInt32( "modifiers", &modifiers ) != B_OK )
408 /* Shouldn't happen */
412 if( ( p_message->what == B_KEY_UP ||
413 p_message->what == B_UNMAPPED_KEY_UP ) &&
414 !( modifiers & B_COMMAND_KEY ) )
416 /* We only use the KEY_UP messages to detect Alt+X
417 shortcuts (because the KEY_DOWN messages aren't
418 sent when Alt is pressed) */
422 /* Special case for Alt+1, Alt+2 and Alt+3 shortcuts: since
423 the character depends on the keymap, we use the key codes
424 directly (18, 19, 20) */
425 if( ( modifiers & B_COMMAND_KEY ) &&
426 key >= 18 && key <= 20 )
429 PostMessage( RESIZE_50 );
431 PostMessage( RESIZE_100 );
433 PostMessage( RESIZE_200 );
438 /* Get the current keymap */
439 get_key_map( &keys, &chars );
441 if( key >= 128 || chars[keys->normal_map[key]] != 1 )
443 /* Weird key or Unicode character */
450 val.i_int = ConvertKeyToVLC( chars[keys->normal_map[key]+1] );
452 if( modifiers & B_COMMAND_KEY )
454 val.i_int |= KEY_MODIFIER_ALT;
456 if( modifiers & B_SHIFT_KEY )
458 val.i_int |= KEY_MODIFIER_SHIFT;
460 if( modifiers & B_CONTROL_KEY )
462 val.i_int |= KEY_MODIFIER_CTRL;
464 var_Set( p_vout->p_libvlc, "key-pressed", val );
472 BWindow::MessageReceived( p_message );
477 /*****************************************************************************
479 *****************************************************************************/
481 VideoWindow::Zoom(BPoint origin, float width, float height )
486 /*****************************************************************************
487 * VideoWindow::FrameMoved
488 *****************************************************************************/
490 VideoWindow::FrameMoved(BPoint origin)
497 /*****************************************************************************
498 * VideoWindow::FrameResized
499 *****************************************************************************/
501 VideoWindow::FrameResized( float width, float height )
503 int32_t useWidth = CorrectAspectRatio() ? i_width : fTrueWidth;
504 int32_t useHeight = CorrectAspectRatio() ? i_height : fTrueHeight;
505 float out_width, out_height;
506 float out_left, out_top;
507 float width_scale = width / useWidth;
508 float height_scale = height / useHeight;
510 if (width_scale <= height_scale)
512 out_width = (useWidth * width_scale);
513 out_height = (useHeight * width_scale);
515 out_top = (height - out_height) / 2;
517 else /* if the height is proportionally smaller */
519 out_width = (useWidth * height_scale);
520 out_height = (useHeight * height_scale);
522 out_left = (width - out_width) / 2;
524 view->MoveTo(out_left,out_top);
525 view->ResizeTo(out_width, out_height);
531 /*****************************************************************************
532 * VideoWindow::ScreenChanged
533 *****************************************************************************/
535 VideoWindow::ScreenChanged(BRect frame, color_space format)
537 BScreen screen(this);
539 screen.GetMode(&mode);
540 float refresh = (mode.timing.pixel_clock * 1000)
541 / ((mode.timing.h_total) * (mode.timing.v_total));
542 SetSyncToRetrace(refresh < MIN_AUTO_VSYNC_REFRESH);
545 /*****************************************************************************
546 * VideoWindow::Activate
547 *****************************************************************************/
549 VideoWindow::WindowActivated(bool active)
553 /*****************************************************************************
554 * VideoWindow::drawBuffer
555 *****************************************************************************/
557 VideoWindow::drawBuffer(int bufferIndex)
559 i_buffer = bufferIndex;
561 // sync to the screen if required
562 if (IsSyncedToRetrace())
564 BScreen screen(this);
565 screen.WaitForRetrace(22000);
567 if (fInitStatus >= B_OK && LockLooper())
569 // switch the overlay bitmap
573 view->SetViewOverlay(bitmap[i_buffer],
574 bitmap[i_buffer]->Bounds() ,
577 B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL|
578 B_OVERLAY_TRANSFER_CHANNEL);
579 view->SetViewColor(key);
584 view->DrawBitmap(bitmap[i_buffer], view->Bounds() );
590 /*****************************************************************************
591 * VideoWindow::SetInterfaceShowing
592 *****************************************************************************/
594 VideoWindow::ToggleInterfaceShowing()
596 SetInterfaceShowing(!fInterfaceShowing);
599 /*****************************************************************************
600 * VideoWindow::SetInterfaceShowing
601 *****************************************************************************/
603 VideoWindow::SetInterfaceShowing(bool showIt)
605 BWindow* window = get_interface_window();
610 if (fCachedFeel != B_NORMAL_WINDOW_FEEL)
611 SetFeel(B_NORMAL_WINDOW_FEEL);
612 window->Activate(true);
617 SetFeel(fCachedFeel);
619 window->SendBehind(this);
621 fInterfaceShowing = showIt;
625 /*****************************************************************************
626 * VideoWindow::SetCorrectAspectRatio
627 *****************************************************************************/
629 VideoWindow::SetCorrectAspectRatio(bool doIt)
631 if (CorrectAspectRatio() != doIt)
634 fSettings->AddFlags(VideoSettings::FLAG_CORRECT_RATIO);
636 fSettings->ClearFlags(VideoSettings::FLAG_CORRECT_RATIO);
637 FrameResized(Bounds().Width(), Bounds().Height());
641 /*****************************************************************************
642 * VideoWindow::CorrectAspectRatio
643 *****************************************************************************/
645 VideoWindow::CorrectAspectRatio() const
647 return fSettings->HasFlags(VideoSettings::FLAG_CORRECT_RATIO);
650 /*****************************************************************************
651 * VideoWindow::ToggleFullScreen
652 *****************************************************************************/
654 VideoWindow::ToggleFullScreen()
656 SetFullScreen(!IsFullScreen());
659 /*****************************************************************************
660 * VideoWindow::SetFullScreen
661 *****************************************************************************/
663 VideoWindow::SetFullScreen(bool doIt)
667 SetLook( B_NO_BORDER_WINDOW_LOOK );
668 BScreen screen( this );
669 BRect rect = screen.Frame();
672 ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
673 be_app->ObscureCursor();
674 fInterfaceShowing = false;
675 fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
679 SetLook( B_TITLED_WINDOW_LOOK );
680 MoveTo(winSize.left, winSize.top);
681 ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
682 be_app->ShowCursor();
683 fInterfaceShowing = true;
684 fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
688 /*****************************************************************************
689 * VideoWindow::IsFullScreen
690 *****************************************************************************/
692 VideoWindow::IsFullScreen() const
694 return fSettings->HasFlags(VideoSettings::FLAG_FULL_SCREEN);
697 /*****************************************************************************
698 * VideoWindow::SetSyncToRetrace
699 *****************************************************************************/
701 VideoWindow::SetSyncToRetrace(bool doIt)
704 fSettings->AddFlags(VideoSettings::FLAG_SYNC_RETRACE);
706 fSettings->ClearFlags(VideoSettings::FLAG_SYNC_RETRACE);
709 /*****************************************************************************
710 * VideoWindow::IsSyncedToRetrace
711 *****************************************************************************/
713 VideoWindow::IsSyncedToRetrace() const
715 return fSettings->HasFlags(VideoSettings::FLAG_SYNC_RETRACE);
719 /*****************************************************************************
720 * VideoWindow::_AllocateBuffers
721 *****************************************************************************/
723 VideoWindow::_AllocateBuffers(int width, int height, int* mode)
725 // clear any old buffers
731 BRect bitmapFrame( 0, 0, width, height );
732 // read from config, if we are supposed to use overlay at all
733 int noOverlay = !config_GetInt( p_vout, "overlay" );
735 /* Test for overlay capability: for every chroma in colspace,
736 we try to do double-buffered overlay, single-buffered overlay
737 or basic overlay. If nothing worked, we then have to work with
738 a non-overlay BBitmap. */
739 for( int i = 0; i < COLOR_COUNT; i++ )
744 bitmap[0] = new BBitmap( bitmapFrame,
745 B_BITMAP_WILL_OVERLAY |
746 B_BITMAP_RESERVE_OVERLAY_CHANNEL,
747 colspace[i].colspace );
748 if( bitmap[0] && bitmap[0]->InitCheck() == B_OK )
754 view->SetViewOverlay( bitmap[0], bitmap[0]->Bounds(),
755 view->Bounds(), &key, B_FOLLOW_ALL,
756 B_OVERLAY_FILTER_HORIZONTAL |
757 B_OVERLAY_FILTER_VERTICAL );
758 view->SetViewColor( key );
759 SetTitle( "VLC " PACKAGE_VERSION " (Overlay)" );
761 bitmap[1] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
762 colspace[colspace_index].colspace);
763 if( bitmap[1] && bitmap[1]->InitCheck() == B_OK )
766 bitmap[2] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
767 colspace[colspace_index].colspace);
768 if( bitmap[2] && bitmap[2]->InitCheck() == B_OK )
770 msg_Dbg( p_vout, "using double-buffered overlay" );
774 msg_Dbg( p_vout, "using single-buffered overlay" );
776 if( bitmap[2] ) { delete bitmap[2]; bitmap[2] = NULL; }
781 msg_Dbg( p_vout, "using simple overlay" );
783 if( bitmap[1] ) { delete bitmap[1]; bitmap[1] = NULL; }
789 if( bitmap[0] ) { delete bitmap[0]; bitmap[0] = NULL; }
795 msg_Warn( p_vout, "no possible overlay" );
798 colspace_index = DEFAULT_COL; // B_RGB32
799 bitmap[0] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
800 bitmap[1] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
801 bitmap[2] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
802 SetTitle( "VLC " PACKAGE_VERSION " (Bitmap)" );
804 // see if everything went well
805 status_t status = B_ERROR;
806 for (int32_t i = 0; i < bitmap_count; i++)
809 status = bitmap[i]->InitCheck();
815 // clear bitmaps to black
816 for (int32_t i = 0; i < bitmap_count; i++)
817 _BlankBitmap(bitmap[i]);
822 /*****************************************************************************
823 * VideoWindow::_FreeBuffers
824 *****************************************************************************/
826 VideoWindow::_FreeBuffers()
828 if( bitmap[0] ) { delete bitmap[0]; bitmap[0] = NULL; }
829 if( bitmap[1] ) { delete bitmap[1]; bitmap[1] = NULL; }
830 if( bitmap[2] ) { delete bitmap[2]; bitmap[2] = NULL; }
831 fInitStatus = B_ERROR;
834 /*****************************************************************************
835 * VideoWindow::_BlankBitmap
836 *****************************************************************************/
838 VideoWindow::_BlankBitmap(BBitmap* bitmap) const
840 // no error checking (we do that earlier on and since it's a private function...
843 // Loss/Saturation points are Y 16-235 (absoulte); Cb/Cr 16-240 (center 128)
846 // Extrema points are Y 0 - 207 (absolute) U -91 - 91 (offset 128) V -127 - 127 (offset 128)
848 // we only handle weird colorspaces with special care
849 switch (bitmap->ColorSpace()) {
851 // Y0[7:0] Cb0[7:0] Y1[7:0] Cr0[7:0] Y2[7:0] Cb2[7:0] Y3[7:0] Cr2[7:0]
852 int32_t height = bitmap->Bounds().IntegerHeight() + 1;
853 uint8_t* bits = (uint8_t*)bitmap->Bits();
854 int32_t bpr = bitmap->BytesPerRow();
855 for (int32_t y = 0; y < height; y++) {
856 // handle 2 bytes at a time
857 for (int32_t i = 0; i < bpr; i += 2) {
869 // Non-interlaced only, Cb0 Y0 Y1 Cb2 Y2 Y3 on even scan lines ...
870 // Cr0 Y0 Y1 Cr2 Y2 Y3 on odd scan lines
871 int32_t height = bitmap->Bounds().IntegerHeight() + 1;
872 uint8_t* bits = (uint8_t*)bitmap->Bits();
873 int32_t bpr = bitmap->BytesPerRow();
874 for (int32_t y = 0; y < height; y += 1) {
875 // handle 3 bytes at a time
876 for (int32_t i = 0; i < bpr; i += 3) {
889 // U0[7:0] Y0[7:0] V0[7:0] Y1[7:0] U2[7:0] Y2[7:0] V2[7:0] Y3[7:0]
890 int32_t height = bitmap->Bounds().IntegerHeight() + 1;
891 uint8_t* bits = (uint8_t*)bitmap->Bits();
892 int32_t bpr = bitmap->BytesPerRow();
893 for (int32_t y = 0; y < height; y += 1) {
894 // handle 2 bytes at a time
895 for (int32_t i = 0; i < bpr; i += 2) {
906 memset(bitmap->Bits(), 0, bitmap->BitsLength());
911 /*****************************************************************************
912 * VideoWindow::_SetVideoSize
913 *****************************************************************************/
915 VideoWindow::_SetVideoSize(uint32_t mode)
917 // let size depend on aspect correction
918 int32_t width = CorrectAspectRatio() ? i_width : fTrueWidth;
919 int32_t height = CorrectAspectRatio() ? i_height : fTrueHeight;
934 fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
935 ResizeTo(width, height);
938 /*****************************************************************************
939 * VideoWindow::_SetToSettings
940 *****************************************************************************/
942 VideoWindow::_SetToSettings()
945 uint32_t mode = RESIZE_100;
946 switch (fSettings->VideoSize())
948 case VideoSettings::SIZE_50:
951 case VideoSettings::SIZE_200:
954 case VideoSettings::SIZE_100:
955 case VideoSettings::SIZE_OTHER:
959 bool fullscreen = IsFullScreen(); // remember settings
960 _SetVideoSize(mode); // because this will reset settings
961 // the fullscreen status is reflected in the settings,
962 // but not yet in the windows state
965 if (fSettings->HasFlags(VideoSettings::FLAG_ON_TOP_ALL))
966 fCachedFeel = B_FLOATING_ALL_WINDOW_FEEL;
968 fCachedFeel = B_NORMAL_WINDOW_FEEL;
969 SetFeel(fCachedFeel);
972 /*****************************************************************************
974 *****************************************************************************/
975 VLCView::VLCView(BRect bounds, vout_thread_t *p_vout_instance )
976 : BView(bounds, "video view", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED),
977 fLastMouseMovedTime(mdate()),
978 fCursorHidden(false),
979 fCursorInside(false),
980 fIgnoreDoubleClick(false)
982 p_vout = p_vout_instance;
983 SetViewColor(B_TRANSPARENT_32_BIT);
986 /*****************************************************************************
988 *****************************************************************************/
993 /*****************************************************************************
994 * VLCVIew::AttachedToWindow
995 *****************************************************************************/
997 VLCView::AttachedToWindow()
999 // periodically check if we want to hide the pointer
1000 Window()->SetPulseRate(1000000);
1003 /*****************************************************************************
1004 * VLCVIew::MouseDown
1005 *****************************************************************************/
1007 VLCView::MouseDown(BPoint where)
1009 VideoWindow* videoWindow = dynamic_cast<VideoWindow*>(Window());
1010 BMessage* msg = Window()->CurrentMessage();
1013 msg->FindInt32("clicks", &clicks);
1014 msg->FindInt32("buttons", (int32*)&buttons);
1018 if (buttons & B_PRIMARY_MOUSE_BUTTON)
1020 if (clicks == 2 && !fIgnoreDoubleClick)
1023 videoWindow->ToggleInterfaceShowing(); */
1024 fIgnoreDoubleClick = false;
1028 if (buttons & B_SECONDARY_MOUSE_BUTTON)
1030 // clicks will be 2 next time (if interval short enough)
1031 // even if the first click and the second
1032 // have not been made with the same mouse button
1033 fIgnoreDoubleClick = true;
1034 // launch popup menu
1035 BPopUpMenu *menu = new BPopUpMenu("context menu");
1036 menu->SetRadioMode(false);
1037 // In full screen, add an item to show/hide the interface
1038 if( videoWindow->IsFullScreen() )
1040 BMenuItem *intfItem =
1041 new BMenuItem( _("Show Interface"), new BMessage(SHOW_INTERFACE) );
1042 menu->AddItem( intfItem );
1045 BMenuItem *halfItem = new BMenuItem(_("50%"), new BMessage(RESIZE_50));
1046 menu->AddItem(halfItem);
1048 BMenuItem *origItem = new BMenuItem(_("100%"), new BMessage(RESIZE_100));
1049 menu->AddItem(origItem);
1051 BMenuItem *doubleItem = new BMenuItem(_("200%"), new BMessage(RESIZE_200));
1052 menu->AddItem(doubleItem);
1053 // Toggle FullScreen
1054 BMenuItem *zoomItem = new BMenuItem(_("Fullscreen"), new BMessage(TOGGLE_FULL_SCREEN));
1055 zoomItem->SetMarked(videoWindow->IsFullScreen());
1056 menu->AddItem(zoomItem);
1058 menu->AddSeparatorItem();
1061 BMenuItem *vsyncItem = new BMenuItem(_("Vertical Sync"), new BMessage(VERT_SYNC));
1062 vsyncItem->SetMarked(videoWindow->IsSyncedToRetrace());
1063 menu->AddItem(vsyncItem);
1064 // Correct Aspect Ratio
1065 BMenuItem *aspectItem = new BMenuItem(_("Correct Aspect Ratio"), new BMessage(ASPECT_CORRECT));
1066 aspectItem->SetMarked(videoWindow->CorrectAspectRatio());
1067 menu->AddItem(aspectItem);
1069 menu->AddSeparatorItem();
1071 // Window Feel Items
1072 /* BMessage *winNormFeel = new BMessage(WINDOW_FEEL);
1073 winNormFeel->AddInt32("WinFeel", (int32_t)B_NORMAL_WINDOW_FEEL);
1074 BMenuItem *normWindItem = new BMenuItem("Normal Window", winNormFeel);
1075 normWindItem->SetMarked(videoWindow->Feel() == B_NORMAL_WINDOW_FEEL);
1076 menu->AddItem(normWindItem);
1078 BMessage *winFloatFeel = new BMessage(WINDOW_FEEL);
1079 winFloatFeel->AddInt32("WinFeel", (int32_t)B_FLOATING_APP_WINDOW_FEEL);
1080 BMenuItem *onTopWindItem = new BMenuItem("App Top", winFloatFeel);
1081 onTopWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_APP_WINDOW_FEEL);
1082 menu->AddItem(onTopWindItem);
1084 BMessage *winAllFeel = new BMessage(WINDOW_FEEL);
1085 winAllFeel->AddInt32("WinFeel", (int32_t)B_FLOATING_ALL_WINDOW_FEEL);
1086 BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel);
1087 allSpacesWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL);
1088 menu->AddItem(allSpacesWindItem);*/
1090 BMessage *windowFeelMsg = new BMessage( WINDOW_FEEL );
1091 bool onTop = videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL;
1092 window_feel feel = onTop ? B_NORMAL_WINDOW_FEEL : B_FLOATING_ALL_WINDOW_FEEL;
1093 windowFeelMsg->AddInt32( "WinFeel", (int32_t)feel );
1094 BMenuItem *windowFeelItem = new BMenuItem( _("Stay On Top"), windowFeelMsg );
1095 windowFeelItem->SetMarked( onTop );
1096 menu->AddItem( windowFeelItem );
1098 menu->AddSeparatorItem();
1100 BMenuItem* screenShotItem = new BMenuItem( _("Take Screen Shot"),
1101 new BMessage( SCREEN_SHOT ) );
1102 menu->AddItem( screenShotItem );
1104 menu->SetTargetForItems( this );
1105 ConvertToScreen( &where );
1106 BRect mouseRect( where.x - 5, where.y - 5,
1107 where.x + 5, where.y + 5 );
1108 menu->Go( where, true, false, mouseRect, true );
1112 fLastMouseMovedTime = mdate();
1113 fCursorHidden = false;
1116 /*****************************************************************************
1118 *****************************************************************************/
1120 VLCView::MouseUp( BPoint where )
1123 val.b_bool = VLC_TRUE;
1124 var_Set( p_vout, "mouse-clicked", val );
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 );
1151 val.b_bool = VLC_TRUE;
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 > MOUSE_IDLE_TIMEOUT)
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 E_(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 msg_Err( p_vout, "out of memory" );
1231 p_vout->p_sys->i_width = p_vout->render.i_width;
1232 p_vout->p_sys->i_height = p_vout->render.i_height;
1233 p_vout->p_sys->source_chroma = p_vout->render.i_chroma;
1235 p_vout->pf_init = Init;
1236 p_vout->pf_end = End;
1237 p_vout->pf_manage = Manage;
1238 p_vout->pf_render = NULL;
1239 p_vout->pf_display = Display;
1240 p_vout->pf_control = Control;
1245 /*****************************************************************************
1246 * Init: initialize BeOS video thread output method
1247 *****************************************************************************/
1248 int Init( vout_thread_t *p_vout )
1253 I_OUTPUTPICTURES = 0;
1255 /* Open and initialize device */
1256 if( BeosOpenDisplay( p_vout ) )
1258 msg_Err(p_vout, "vout error: can't open display");
1261 p_vout->output.i_width = p_vout->render.i_width;
1262 p_vout->output.i_height = p_vout->render.i_height;
1264 /* Assume we have square pixels */
1265 p_vout->output.i_aspect = p_vout->p_sys->i_width
1266 * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
1267 p_vout->output.i_chroma = colspace[p_vout->p_sys->p_window->colspace_index].chroma;
1268 p_vout->p_sys->i_index = 0;
1270 p_vout->b_direct = 1;
1272 p_vout->output.i_rmask = 0x00ff0000;
1273 p_vout->output.i_gmask = 0x0000ff00;
1274 p_vout->output.i_bmask = 0x000000ff;
1276 for( int buffer_index = 0 ;
1277 buffer_index < p_vout->p_sys->p_window->bitmap_count;
1281 /* Find an empty picture slot */
1282 for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
1285 if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
1287 p_pic = p_vout->p_picture + i_index;
1296 p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[buffer_index]->Bits();
1297 p_pic->p->i_lines = p_vout->p_sys->i_height;
1298 p_pic->p->i_visible_lines = p_vout->p_sys->i_height;
1300 p_pic->p->i_pixel_pitch = colspace[p_vout->p_sys->p_window->colspace_index].pixel_bytes;
1301 p_pic->i_planes = colspace[p_vout->p_sys->p_window->colspace_index].planes;
1302 p_pic->p->i_pitch = p_vout->p_sys->p_window->bitmap[buffer_index]->BytesPerRow();
1303 p_pic->p->i_visible_pitch = p_pic->p->i_pixel_pitch * ( p_vout->p_sys->p_window->bitmap[buffer_index]->Bounds().IntegerWidth() + 1 );
1305 p_pic->i_status = DESTROYED_PICTURE;
1306 p_pic->i_type = DIRECT_PICTURE;
1308 PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
1316 /*****************************************************************************
1317 * End: terminate BeOS video thread output method
1318 *****************************************************************************/
1319 void End( vout_thread_t *p_vout )
1321 BeosCloseDisplay( p_vout );
1324 /*****************************************************************************
1326 *****************************************************************************/
1327 static int Manage( vout_thread_t * p_vout )
1329 if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
1331 p_vout->p_sys->p_window->PostMessage( TOGGLE_FULL_SCREEN );
1332 p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
1338 /*****************************************************************************
1339 * CloseVideo: destroy BeOS video thread output method
1340 *****************************************************************************
1341 * Terminate an output method created by DummyCreateOutputMethod
1342 *****************************************************************************/
1343 void E_(CloseVideo) ( vlc_object_t *p_this )
1345 vout_thread_t * p_vout = (vout_thread_t *)p_this;
1347 free( p_vout->p_sys );
1350 /*****************************************************************************
1351 * Display: displays previously rendered output
1352 *****************************************************************************
1353 * This function send the currently rendered image to BeOS image, waits until
1354 * it is displayed and switch the two rendering buffers, preparing next frame.
1355 *****************************************************************************/
1356 void Display( vout_thread_t *p_vout, picture_t *p_pic )
1358 VideoWindow * p_win = p_vout->p_sys->p_window;
1360 /* draw buffer if required */
1361 if (!p_win->teardownwindow)
1363 p_win->drawBuffer(p_vout->p_sys->i_index);
1366 p_vout->p_sys->i_index = ++p_vout->p_sys->i_index %
1367 p_vout->p_sys->p_window->bitmap_count;
1368 p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[p_vout->p_sys->i_index]->Bits();
1371 static int Control( vout_thread_t * p_vout, int i_query, va_list args )
1373 return vout_vaControlDefault( p_vout, i_query, args );
1376 /* following functions are local */
1378 /*****************************************************************************
1379 * BeosOpenDisplay: open and initialize BeOS device
1380 *****************************************************************************/
1381 static int BeosOpenDisplay( vout_thread_t *p_vout )
1384 p_vout->p_sys->p_window = new VideoWindow( p_vout->p_sys->i_width - 1,
1385 p_vout->p_sys->i_height - 1,
1387 20 + p_vout->i_window_width - 1,
1388 50 + p_vout->i_window_height - 1 ),
1390 if( p_vout->p_sys->p_window == NULL )
1392 msg_Err( p_vout, "cannot allocate VideoWindow" );
1397 p_vout->p_sys->p_window->Show();
1403 /*****************************************************************************
1404 * BeosDisplay: close and reset BeOS device
1405 *****************************************************************************
1406 * Returns all resources allocated by BeosOpenDisplay and restore the original
1407 * state of the device.
1408 *****************************************************************************/
1409 static void BeosCloseDisplay( vout_thread_t *p_vout )
1411 VideoWindow * p_win = p_vout->p_sys->p_window;
1412 /* Destroy the video window */
1413 if( p_win != NULL && !p_win->teardownwindow)
1416 p_win->teardownwindow = true;