1 /*****************************************************************************
2 * vout_beos.cpp: beos video output display method
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: VideoOutput.cpp,v 1.11 2003/02/01 12:01:11 stippi Exp $
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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
26 *****************************************************************************/
28 /*****************************************************************************
30 *****************************************************************************/
31 #include <errno.h> /* ENOMEM */
32 #include <stdlib.h> /* free() */
34 #include <string.h> /* strerror() */
36 #include <Application.h>
37 #include <BitmapStream.h>
39 #include <DirectWindow.h>
41 #include <InterfaceKit.h>
44 #include <TranslatorRoster.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;
76 #define MOUSE_IDLE_TIMEOUT 2000000 // two seconds
77 #define MIN_AUTO_VSYNC_REFRESH 61 // Hz
78 #define DEFAULT_SCREEN_SHOT_FORMAT 'PNG '
79 #define DEFAULT_SCREEN_SHOT_PATH "/boot/home/vlc screenshot"
81 /*****************************************************************************
82 * beos_GetAppWindow : retrieve a BWindow pointer from the window name
83 *****************************************************************************/
85 beos_GetAppWindow(char *name)
90 for (index = 0 ; ; index++)
92 window = be_app->WindowAt(index);
95 if (window->LockWithTimeout(20000) == B_OK)
97 if (strcmp(window->Name(), name) == 0)
108 /*****************************************************************************
109 * get_interface_window
110 *****************************************************************************/
112 get_interface_window()
114 return beos_GetAppWindow(VOUT_TITLE);
117 class BackgroundView : public BView
120 BackgroundView(BRect frame, VLCView* view)
121 : BView(frame, "background",
122 B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE),
125 SetViewColor(kBlack);
127 virtual ~BackgroundView() {}
129 virtual void MouseDown(BPoint where)
131 // convert coordinates
132 where = fVideoView->ConvertFromParent(where);
134 fVideoView->MouseDown(where);
136 virtual void MouseMoved(BPoint where, uint32 transit,
137 const BMessage* dragMessage)
139 // convert coordinates
140 where = fVideoView->ConvertFromParent(where);
142 fVideoView->MouseMoved(where, transit, dragMessage);
143 // notice: It might look like transit should be
144 // B_OUTSIDE_VIEW regardless, but leave it like this,
145 // otherwise, unwanted things will happen!
153 /*****************************************************************************
154 * VideoSettings constructor and destructor
155 *****************************************************************************/
156 VideoSettings::VideoSettings()
157 : fVideoSize( SIZE_100 ),
158 fFlags( FLAG_CORRECT_RATIO ),
159 fSettings( new BMessage( 'sett' ) )
161 // read settings from disk
162 status_t ret = load_settings( fSettings, "video_settings", "VideoLAN Client" );
166 if ( fSettings->FindInt32( "flags", (int32*)&flags ) == B_OK )
169 if ( fSettings->FindInt32( "video size", (int32*)&size ) == B_OK )
170 SetVideoSize( size );
174 fprintf( stderr, "error loading video settings: %s\n", strerror( ret ) );
176 // figure out if we should use vertical sync by default
177 BScreen screen(B_MAIN_SCREEN_ID);
178 if (screen.IsValid())
181 screen.GetMode(&mode);
182 float refresh = (mode.timing.pixel_clock * 1000)
183 / ((mode.timing.h_total)* (mode.timing.v_total));
184 if (refresh < MIN_AUTO_VSYNC_REFRESH)
185 AddFlags(FLAG_SYNC_RETRACE);
190 VideoSettings::VideoSettings( const VideoSettings& clone )
191 : fVideoSize( clone.VideoSize() ),
192 fFlags( clone.Flags() ),
198 VideoSettings::~VideoSettings()
202 // we are the default settings
203 // and write our settings to disk
204 if (fSettings->ReplaceInt32( "video size", VideoSize() ) != B_OK)
205 fSettings->AddInt32( "video size", VideoSize() );
206 if (fSettings->ReplaceInt32( "flags", Flags() ) != B_OK)
207 fSettings->AddInt32( "flags", Flags() );
209 status_t ret = save_settings( fSettings, "video_settings", "VideoLAN Client" );
211 fprintf( stderr, "error saving video settings: %s\n", strerror( ret ) );
216 // we are just a clone of the default settings
217 fDefaultSettings.SetVideoSize( VideoSize() );
218 fDefaultSettings.SetFlags( Flags() );
222 /*****************************************************************************
223 * VideoSettings::DefaultSettings
224 *****************************************************************************/
226 VideoSettings::DefaultSettings()
228 return &fDefaultSettings;
231 /*****************************************************************************
232 * VideoSettings::SetVideoSize
233 *****************************************************************************/
235 VideoSettings::SetVideoSize( uint32 mode )
240 // static variable initialization
242 VideoSettings::fDefaultSettings;
245 /*****************************************************************************
246 * VideoWindow constructor and destructor
247 *****************************************************************************/
248 VideoWindow::VideoWindow(int v_width, int v_height, BRect frame,
249 vout_thread_t *p_videoout)
250 : BWindow(frame, NULL, B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_MINIMIZABLE),
251 i_width(frame.IntegerWidth()),
252 i_height(frame.IntegerHeight()),
255 teardownwindow(false),
257 fTrueHeight(v_height),
258 fCachedFeel(B_NORMAL_WINDOW_FEEL),
259 fInterfaceShowing(false),
260 fInitStatus(B_ERROR),
261 fSettings(new VideoSettings(*VideoSettings::DefaultSettings()))
265 // create the view to do the display
266 view = new VLCView( Bounds(), p_vout );
268 // create background view
269 BView *mainView = new BackgroundView( Bounds(), view );
271 mainView->AddChild(view);
273 // allocate bitmap buffers
274 for (int32 i = 0; i < 3; i++)
276 fInitStatus = _AllocateBuffers(v_width, v_height, &mode);
278 // make sure we layout the view correctly
279 FrameResized(i_width, i_height);
281 if (fInitStatus >= B_OK && mode == OVERLAY)
283 overlay_restrictions r;
285 bitmap[1]->GetOverlayRestrictions(&r);
286 SetSizeLimits((i_width * r.min_width_scale), i_width * r.max_width_scale,
287 (i_height * r.min_height_scale), i_height * r.max_height_scale);
290 // vlc settings override settings from disk
291 if (config_GetInt(p_vout, "fullscreen"))
292 fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
297 VideoWindow::~VideoWindow()
301 teardownwindow = true;
302 wait_for_thread(fDrawThreadID, &result);
307 /*****************************************************************************
308 * VideoWindow::MessageReceived
309 *****************************************************************************/
311 VideoWindow::MessageReceived( BMessage *p_message )
313 switch( p_message->what )
315 case TOGGLE_FULL_SCREEN:
323 _SetVideoSize(p_message->what);
326 SetSyncToRetrace(!IsSyncedToRetrace());
331 if (p_message->FindInt32("WinFeel", (int32*)&winFeel) == B_OK)
334 fCachedFeel = winFeel;
335 if (winFeel == B_FLOATING_ALL_WINDOW_FEEL)
336 fSettings->AddFlags(VideoSettings::FLAG_ON_TOP_ALL);
338 fSettings->ClearFlags(VideoSettings::FLAG_ON_TOP_ALL);
343 SetCorrectAspectRatio(!CorrectAspectRatio());
346 // save a screen shot
347 if ( BBitmap* current = bitmap[i_buffer] )
349 // the following line might be tempting, but does not work for some overlay bitmaps!!!
350 // BBitmap* temp = new BBitmap( current );
351 // so we clone the bitmap ourselves
352 // however, we need to take care of potentially different padding!
353 // memcpy() is slow when reading from grafix memory, but what the heck...
354 BBitmap* temp = new BBitmap( current->Bounds(), current->ColorSpace() );
355 if ( temp && temp->IsValid() )
357 int32 height = (int32)current->Bounds().Height();
358 uint8* dst = (uint8*)temp->Bits();
359 uint8* src = (uint8*)current->Bits();
360 int32 dstBpr = temp->BytesPerRow();
361 int32 srcBpr = current->BytesPerRow();
362 int32 validBytes = dstBpr > srcBpr ? srcBpr : dstBpr;
363 for ( int32 y = 0; y < height; y++ )
365 memcpy( dst, src, validBytes );
369 _SaveScreenShot( temp,
370 strdup( DEFAULT_SCREEN_SHOT_PATH ),
371 DEFAULT_SCREEN_SHOT_FORMAT );
380 BWindow::MessageReceived( p_message );
385 /*****************************************************************************
387 *****************************************************************************/
389 VideoWindow::Zoom(BPoint origin, float width, float height )
394 /*****************************************************************************
395 * VideoWindow::FrameMoved
396 *****************************************************************************/
398 VideoWindow::FrameMoved(BPoint origin)
405 /*****************************************************************************
406 * VideoWindow::FrameResized
407 *****************************************************************************/
409 VideoWindow::FrameResized( float width, float height )
411 int32 useWidth = CorrectAspectRatio() ? i_width : fTrueWidth;
412 int32 useHeight = CorrectAspectRatio() ? i_height : fTrueHeight;
413 float out_width, out_height;
414 float out_left, out_top;
415 float width_scale = width / useWidth;
416 float height_scale = height / useHeight;
418 if (width_scale <= height_scale)
420 out_width = (useWidth * width_scale);
421 out_height = (useHeight * width_scale);
423 out_top = (height - out_height) / 2;
425 else /* if the height is proportionally smaller */
427 out_width = (useWidth * height_scale);
428 out_height = (useHeight * height_scale);
430 out_left = (width - out_width) / 2;
432 view->MoveTo(out_left,out_top);
433 view->ResizeTo(out_width, out_height);
439 /*****************************************************************************
440 * VideoWindow::ScreenChanged
441 *****************************************************************************/
443 VideoWindow::ScreenChanged(BRect frame, color_space format)
445 BScreen screen(this);
447 screen.GetMode(&mode);
448 float refresh = (mode.timing.pixel_clock * 1000)
449 / ((mode.timing.h_total) * (mode.timing.v_total));
450 SetSyncToRetrace(refresh < MIN_AUTO_VSYNC_REFRESH);
453 /*****************************************************************************
454 * VideoWindow::Activate
455 *****************************************************************************/
457 VideoWindow::WindowActivated(bool active)
461 /*****************************************************************************
462 * VideoWindow::drawBuffer
463 *****************************************************************************/
465 VideoWindow::drawBuffer(int bufferIndex)
467 i_buffer = bufferIndex;
469 // sync to the screen if required
470 if (IsSyncedToRetrace())
472 BScreen screen(this);
473 screen.WaitForRetrace(22000);
475 if (fInitStatus >= B_OK && LockLooper())
477 // switch the overlay bitmap
481 view->SetViewOverlay(bitmap[i_buffer],
482 bitmap[i_buffer]->Bounds() ,
485 B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL|
486 B_OVERLAY_TRANSFER_CHANNEL);
487 view->SetViewColor(key);
492 view->DrawBitmap(bitmap[i_buffer], view->Bounds() );
498 /*****************************************************************************
499 * VideoWindow::SetInterfaceShowing
500 *****************************************************************************/
502 VideoWindow::ToggleInterfaceShowing()
504 SetInterfaceShowing(!fInterfaceShowing);
507 /*****************************************************************************
508 * VideoWindow::SetInterfaceShowing
509 *****************************************************************************/
511 VideoWindow::SetInterfaceShowing(bool showIt)
513 BWindow* window = get_interface_window();
518 if (fCachedFeel != B_NORMAL_WINDOW_FEEL)
519 SetFeel(B_NORMAL_WINDOW_FEEL);
520 window->Activate(true);
525 SetFeel(fCachedFeel);
527 window->SendBehind(this);
529 fInterfaceShowing = showIt;
533 /*****************************************************************************
534 * VideoWindow::SetCorrectAspectRatio
535 *****************************************************************************/
537 VideoWindow::SetCorrectAspectRatio(bool doIt)
539 if (CorrectAspectRatio() != doIt)
542 fSettings->AddFlags(VideoSettings::FLAG_CORRECT_RATIO);
544 fSettings->ClearFlags(VideoSettings::FLAG_CORRECT_RATIO);
545 FrameResized(Bounds().Width(), Bounds().Height());
549 /*****************************************************************************
550 * VideoWindow::CorrectAspectRatio
551 *****************************************************************************/
553 VideoWindow::CorrectAspectRatio() const
555 return fSettings->HasFlags(VideoSettings::FLAG_CORRECT_RATIO);
558 /*****************************************************************************
559 * VideoWindow::ToggleFullScreen
560 *****************************************************************************/
562 VideoWindow::ToggleFullScreen()
564 SetFullScreen(!IsFullScreen());
567 /*****************************************************************************
568 * VideoWindow::SetFullScreen
569 *****************************************************************************/
571 VideoWindow::SetFullScreen(bool doIt)
575 BScreen screen(this);
576 BRect rect = screen.Frame();
579 ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
580 be_app->ObscureCursor();
581 fInterfaceShowing = false;
582 fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
586 MoveTo(winSize.left, winSize.top);
587 ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
588 be_app->ShowCursor();
589 fInterfaceShowing = true;
590 fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
594 /*****************************************************************************
595 * VideoWindow::IsFullScreen
596 *****************************************************************************/
598 VideoWindow::IsFullScreen() const
600 return fSettings->HasFlags(VideoSettings::FLAG_FULL_SCREEN);
603 /*****************************************************************************
604 * VideoWindow::SetSyncToRetrace
605 *****************************************************************************/
607 VideoWindow::SetSyncToRetrace(bool doIt)
610 fSettings->AddFlags(VideoSettings::FLAG_SYNC_RETRACE);
612 fSettings->ClearFlags(VideoSettings::FLAG_SYNC_RETRACE);
615 /*****************************************************************************
616 * VideoWindow::IsSyncedToRetrace
617 *****************************************************************************/
619 VideoWindow::IsSyncedToRetrace() const
621 return fSettings->HasFlags(VideoSettings::FLAG_SYNC_RETRACE);
625 /*****************************************************************************
626 * VideoWindow::_AllocateBuffers
627 *****************************************************************************/
629 VideoWindow::_AllocateBuffers(int width, int height, int* mode)
631 // clear any old buffers
636 BRect bitmapFrame( 0, 0, width, height );
637 // read from config, if we are supposed to use overlay at all
638 int noOverlay = !config_GetInt( p_vout, "overlay" );
639 // test for overlay capability
640 for (int i = 0; i < COLOR_COUNT; i++)
642 if (noOverlay) break;
643 bitmap[0] = new BBitmap ( bitmapFrame,
644 B_BITMAP_WILL_OVERLAY |
645 B_BITMAP_RESERVE_OVERLAY_CHANNEL,
646 colspace[i].colspace);
648 if(bitmap[0] && bitmap[0]->InitCheck() == B_OK)
652 bitmap[1] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
653 colspace[colspace_index].colspace);
654 bitmap[2] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
655 colspace[colspace_index].colspace);
656 if ( (bitmap[2] && bitmap[2]->InitCheck() == B_OK) )
660 view->SetViewOverlay(bitmap[0],
661 bitmap[0]->Bounds() ,
664 B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL);
665 view->SetViewColor(key);
666 SetTitle(VOUT_TITLE " (Overlay)");
672 *mode = BITMAP; // might want to try again with normal bitmaps
682 colspace_index = DEFAULT_COL; // B_RGB32
683 SetTitle( VOUT_TITLE " (Bitmap)" );
684 bitmap[0] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
685 bitmap[1] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
686 bitmap[2] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
688 // see if everything went well
689 status_t status = B_ERROR;
690 for (int32 i = 0; i < 3; i++)
693 status = bitmap[i]->InitCheck();
699 // clear bitmaps to black
700 for (int32 i = 0; i < 3; i++)
701 _BlankBitmap(bitmap[i]);
706 /*****************************************************************************
707 * VideoWindow::_FreeBuffers
708 *****************************************************************************/
710 VideoWindow::_FreeBuffers()
718 fInitStatus = B_ERROR;
721 /*****************************************************************************
722 * VideoWindow::_BlankBitmap
723 *****************************************************************************/
725 VideoWindow::_BlankBitmap(BBitmap* bitmap) const
727 // no error checking (we do that earlier on and since it's a private function...
730 // Loss/Saturation points are Y 16-235 (absoulte); Cb/Cr 16-240 (center 128)
733 // Extrema points are Y 0 - 207 (absolute) U -91 - 91 (offset 128) V -127 - 127 (offset 128)
735 // we only handle weird colorspaces with special care
736 switch (bitmap->ColorSpace()) {
738 // Y0[7:0] Cb0[7:0] Y1[7:0] Cr0[7:0] Y2[7:0] Cb2[7:0] Y3[7:0] Cr2[7:0]
739 int32 height = bitmap->Bounds().IntegerHeight() + 1;
740 uint8* bits = (uint8*)bitmap->Bits();
741 int32 bpr = bitmap->BytesPerRow();
742 for (int32 y = 0; y < height; y++) {
743 // handle 2 bytes at a time
744 for (int32 i = 0; i < bpr; i += 2) {
756 // Non-interlaced only, Cb0 Y0 Y1 Cb2 Y2 Y3 on even scan lines ...
757 // Cr0 Y0 Y1 Cr2 Y2 Y3 on odd scan lines
758 int32 height = bitmap->Bounds().IntegerHeight() + 1;
759 uint8* bits = (uint8*)bitmap->Bits();
760 int32 bpr = bitmap->BytesPerRow();
761 for (int32 y = 0; y < height; y += 1) {
762 // handle 3 bytes at a time
763 for (int32 i = 0; i < bpr; i += 3) {
776 // U0[7:0] Y0[7:0] V0[7:0] Y1[7:0] U2[7:0] Y2[7:0] V2[7:0] Y3[7:0]
777 int32 height = bitmap->Bounds().IntegerHeight() + 1;
778 uint8* bits = (uint8*)bitmap->Bits();
779 int32 bpr = bitmap->BytesPerRow();
780 for (int32 y = 0; y < height; y += 1) {
781 // handle 2 bytes at a time
782 for (int32 i = 0; i < bpr; i += 2) {
793 memset(bitmap->Bits(), 0, bitmap->BitsLength());
798 /*****************************************************************************
799 * VideoWindow::_SetVideoSize
800 *****************************************************************************/
802 VideoWindow::_SetVideoSize(uint32 mode)
804 // let size depend on aspect correction
805 int32 width = CorrectAspectRatio() ? i_width : fTrueWidth;
806 int32 height = CorrectAspectRatio() ? i_height : fTrueHeight;
821 fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
822 ResizeTo(width, height);
825 /*****************************************************************************
826 * VideoWindow::_SetToSettings
827 *****************************************************************************/
829 VideoWindow::_SetToSettings()
832 uint32 mode = RESIZE_100;
833 switch (fSettings->VideoSize())
835 case VideoSettings::SIZE_50:
838 case VideoSettings::SIZE_200:
841 case VideoSettings::SIZE_100:
842 case VideoSettings::SIZE_OTHER:
846 bool fullscreen = IsFullScreen(); // remember settings
847 _SetVideoSize(mode); // because this will reset settings
848 // the fullscreen status is reflected in the settings,
849 // but not yet in the windows state
852 if (fSettings->HasFlags(VideoSettings::FLAG_ON_TOP_ALL))
853 fCachedFeel = B_FLOATING_ALL_WINDOW_FEEL;
855 fCachedFeel = B_NORMAL_WINDOW_FEEL;
856 SetFeel(fCachedFeel);
859 /*****************************************************************************
860 * VideoWindow::_SaveScreenShot
861 *****************************************************************************/
863 VideoWindow::_SaveScreenShot( BBitmap* bitmap, char* path,
864 uint32 translatorID ) const
866 // make the info object from the parameters
867 screen_shot_info* info = new screen_shot_info;
868 info->bitmap = bitmap;
870 info->translatorID = translatorID;
871 info->width = CorrectAspectRatio() ? i_width : fTrueWidth;
872 info->height = CorrectAspectRatio() ? i_height : fTrueHeight;
873 // spawn a new thread to take care of the actual saving to disk
874 thread_id thread = spawn_thread( _save_screen_shot,
876 B_LOW_PRIORITY, (void*)info );
877 // start thread or do the job ourself if something went wrong
878 if ( thread < B_OK || resume_thread( thread ) < B_OK )
879 _save_screen_shot( (void*)info );
882 /*****************************************************************************
883 * VideoWindow::_save_screen_shot
884 *****************************************************************************/
886 VideoWindow::_save_screen_shot( void* cookie )
888 screen_shot_info* info = (screen_shot_info*)cookie;
889 if ( info && info->bitmap && info->bitmap->IsValid() && info->path )
891 // try to be as quick as possible creating the file (the user might have
892 // taken the next screen shot already!)
893 // make sure we have a unique name for the screen shot
894 BString path( info->path );
895 BEntry entry( path.String() );
896 int32 appendedNumber = 0;
897 if ( entry.Exists() && !entry.IsSymLink() )
899 // we would clobber an existing entry
900 bool foundUniqueName = false;
902 while ( !foundUniqueName ) {
903 BString newName( info->path );
904 newName << " " << appendedNumber;
905 BEntry possiblyClobberedEntry( newName.String() );
906 if ( possiblyClobberedEntry.Exists()
907 && !possiblyClobberedEntry.IsSymLink() )
910 foundUniqueName = true;
913 if ( appendedNumber > 0 )
914 path << " " << appendedNumber;
915 // there is still a slight chance to clobber an existing
916 // file (if it was created in the "meantime"), but we take it...
917 BFile outFile( path.String(),
918 B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE );
920 // make colorspace converted copy of bitmap
921 BBitmap* converted = new BBitmap( BRect( 0.0, 0.0, info->width, info->height ),
923 // if ( converted->IsValid() )
924 // memset( converted->Bits(), 0, converted->BitsLength() );
925 status_t status = convert_bitmap( info->bitmap, converted );
926 if ( status == B_OK )
928 BTranslatorRoster* roster = BTranslatorRoster::Default();
929 uint32 imageFormat = 0;
930 translator_id translator = 0;
933 // find suitable translator
934 translator_id* ids = NULL;
937 status = roster->GetAllTranslators( &ids, &count );
938 if ( status >= B_OK )
940 for ( int tix = 0; tix < count; tix++ )
942 const translation_format *formats = NULL;
943 int32 num_formats = 0;
945 status = roster->GetInputFormats( ids[tix],
946 &formats, &num_formats );
949 for ( int iix = 0; iix < num_formats; iix++ )
951 if ( formats[iix].type == B_TRANSLATOR_BITMAP )
960 status = roster->GetOutputFormats( ids[tix],
961 &formats, &num_formats);
962 if ( status >= B_OK )
964 for ( int32 oix = 0; oix < num_formats; oix++ )
966 if ( formats[oix].type != B_TRANSLATOR_BITMAP )
968 if ( formats[oix].type == info->translatorID )
971 imageFormat = formats[oix].type;
972 translator = ids[tix];
983 // make bitmap stream
984 BBitmapStream outStream( converted );
986 status = outFile.InitCheck();
987 if (status == B_OK) {
988 status = roster->Translate( &outStream, NULL, NULL,
989 &outFile, imageFormat );
990 if ( status == B_OK )
992 BNodeInfo nodeInfo( &outFile );
993 if ( nodeInfo.InitCheck() == B_OK )
995 translation_format* formats;
997 status = roster->GetOutputFormats( translator,
998 (const translation_format **) &formats,
1000 if ( status >= B_OK )
1002 const char * mime = NULL;
1003 for ( int ix = 0; ix < count; ix++ ) {
1004 if ( formats[ix].type == imageFormat ) {
1005 mime = formats[ix].MIME;
1010 nodeInfo.SetType( mime );
1015 outStream.DetachBitmap( &converted );
1023 delete info->bitmap;
1024 delete[] info->path;
1031 /*****************************************************************************
1033 *****************************************************************************/
1034 VLCView::VLCView(BRect bounds, vout_thread_t *p_vout_instance )
1035 : BView(bounds, "video view", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED),
1036 fLastMouseMovedTime(system_time()),
1037 fCursorHidden(false),
1038 fCursorInside(false),
1039 fIgnoreDoubleClick(false)
1041 p_vout = p_vout_instance;
1042 SetViewColor(B_TRANSPARENT_32_BIT);
1045 /*****************************************************************************
1047 *****************************************************************************/
1052 /*****************************************************************************
1053 * VLCVIew::AttachedToWindow
1054 *****************************************************************************/
1056 VLCView::AttachedToWindow()
1058 // in order to get keyboard events
1060 // periodically check if we want to hide the pointer
1061 Window()->SetPulseRate(1000000);
1064 /*****************************************************************************
1065 * VLCVIew::MouseDown
1066 *****************************************************************************/
1068 VLCView::MouseDown(BPoint where)
1070 VideoWindow* videoWindow = dynamic_cast<VideoWindow*>(Window());
1071 BMessage* msg = Window()->CurrentMessage();
1074 msg->FindInt32("clicks", &clicks);
1075 msg->FindInt32("buttons", (int32*)&buttons);
1079 if (buttons & B_PRIMARY_MOUSE_BUTTON)
1081 if (clicks == 2 && !fIgnoreDoubleClick)
1084 videoWindow->ToggleInterfaceShowing();
1085 fIgnoreDoubleClick = false;
1089 if (buttons & B_SECONDARY_MOUSE_BUTTON)
1091 // clicks will be 2 next time (if interval short enough)
1092 // even if the first click and the second
1093 // have not been made with the same mouse button
1094 fIgnoreDoubleClick = true;
1095 // launch popup menu
1096 BPopUpMenu *menu = new BPopUpMenu("context menu");
1097 menu->SetRadioMode(false);
1099 BMenuItem *halfItem = new BMenuItem("50%", new BMessage(RESIZE_50));
1100 menu->AddItem(halfItem);
1102 BMenuItem *origItem = new BMenuItem("100%", new BMessage(RESIZE_100));
1103 menu->AddItem(origItem);
1105 BMenuItem *doubleItem = new BMenuItem("200%", new BMessage(RESIZE_200));
1106 menu->AddItem(doubleItem);
1107 // Toggle FullScreen
1108 BMenuItem *zoomItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULL_SCREEN));
1109 zoomItem->SetMarked(videoWindow->IsFullScreen());
1110 menu->AddItem(zoomItem);
1112 menu->AddSeparatorItem();
1115 BMenuItem *vsyncItem = new BMenuItem("Vertical Sync", new BMessage(VERT_SYNC));
1116 vsyncItem->SetMarked(videoWindow->IsSyncedToRetrace());
1117 menu->AddItem(vsyncItem);
1118 // Correct Aspect Ratio
1119 BMenuItem *aspectItem = new BMenuItem("Correct Aspect Ratio", new BMessage(ASPECT_CORRECT));
1120 aspectItem->SetMarked(videoWindow->CorrectAspectRatio());
1121 menu->AddItem(aspectItem);
1123 menu->AddSeparatorItem();
1125 // Windwo Feel Items
1126 /* BMessage *winNormFeel = new BMessage(WINDOW_FEEL);
1127 winNormFeel->AddInt32("WinFeel", (int32)B_NORMAL_WINDOW_FEEL);
1128 BMenuItem *normWindItem = new BMenuItem("Normal Window", winNormFeel);
1129 normWindItem->SetMarked(videoWindow->Feel() == B_NORMAL_WINDOW_FEEL);
1130 menu->AddItem(normWindItem);
1132 BMessage *winFloatFeel = new BMessage(WINDOW_FEEL);
1133 winFloatFeel->AddInt32("WinFeel", (int32)B_FLOATING_APP_WINDOW_FEEL);
1134 BMenuItem *onTopWindItem = new BMenuItem("App Top", winFloatFeel);
1135 onTopWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_APP_WINDOW_FEEL);
1136 menu->AddItem(onTopWindItem);
1138 BMessage *winAllFeel = new BMessage(WINDOW_FEEL);
1139 winAllFeel->AddInt32("WinFeel", (int32)B_FLOATING_ALL_WINDOW_FEEL);
1140 BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel);
1141 allSpacesWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL);
1142 menu->AddItem(allSpacesWindItem);*/
1144 BMessage *windowFeelMsg = new BMessage( WINDOW_FEEL );
1145 bool onTop = videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL;
1146 window_feel feel = onTop ? B_NORMAL_WINDOW_FEEL : B_FLOATING_ALL_WINDOW_FEEL;
1147 windowFeelMsg->AddInt32( "WinFeel", (int32)feel );
1148 BMenuItem *windowFeelItem = new BMenuItem( "Stay On Top", windowFeelMsg );
1149 windowFeelItem->SetMarked( onTop );
1150 menu->AddItem( windowFeelItem );
1152 menu->AddSeparatorItem();
1154 BMenuItem* screenShotItem = new BMenuItem( "Take Screen Shot",
1155 new BMessage( SCREEN_SHOT ) );
1156 menu->AddItem( screenShotItem );
1158 menu->SetTargetForItems( this );
1159 ConvertToScreen( &where );
1160 menu->Go( where, true, false, true );
1164 fLastMouseMovedTime = system_time();
1165 fCursorHidden = false;
1168 /*****************************************************************************
1170 *****************************************************************************/
1172 VLCView::MouseUp( BPoint where )
1175 val.b_bool = VLC_TRUE;
1176 var_Set( p_vout, "mouse-clicked", val );
1179 /*****************************************************************************
1180 * VLCVIew::MouseMoved
1181 *****************************************************************************/
1183 VLCView::MouseMoved(BPoint point, uint32 transit, const BMessage* dragMessage)
1185 fLastMouseMovedTime = system_time();
1186 fCursorHidden = false;
1187 fCursorInside = (transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW);
1188 /* DVD navigation */
1189 unsigned int i_width, i_height, i_x, i_y;
1190 vout_PlacePicture( p_vout, (unsigned int)Bounds().Width(),
1191 (unsigned int)Bounds().Height(),
1192 &i_x, &i_y, &i_width, &i_height );
1194 val.i_int = ( (int)point.x - i_x ) * p_vout->render.i_width / i_width;
1195 var_Set( p_vout, "mouse-x", val );
1196 val.i_int = ( (int)point.y - i_y ) * p_vout->render.i_height / i_height;
1197 var_Set( p_vout, "mouse-y", val );
1198 val.b_bool = VLC_TRUE;
1199 var_Set( p_vout, "mouse-moved", val );
1202 /*****************************************************************************
1204 *****************************************************************************/
1208 // We are getting the pulse messages no matter if the mouse is over
1209 // this view. If we are in full screen mode, we want to hide the cursor
1210 // even if it is not.
1214 && system_time() - fLastMouseMovedTime > MOUSE_IDLE_TIMEOUT)
1216 be_app->ObscureCursor();
1217 fCursorHidden = true;
1218 VideoWindow *videoWindow = dynamic_cast<VideoWindow*>(Window());
1219 // hide the interface window as well if full screen
1220 if (videoWindow && videoWindow->IsFullScreen())
1221 videoWindow->SetInterfaceShowing(false);
1226 /*****************************************************************************
1228 *****************************************************************************/
1230 VLCView::KeyDown(const char *bytes, int32 numBytes)
1232 VideoWindow *videoWindow = dynamic_cast<VideoWindow*>(Window());
1233 BWindow* interfaceWindow = get_interface_window();
1234 if (videoWindow && numBytes > 0) {
1235 uint32 mods = modifiers();
1238 // toggle window and full screen mode
1239 // not passing on the tab key to the default KeyDown()
1240 // implementation also avoids loosing the keyboard focus
1241 videoWindow->PostMessage(TOGGLE_FULL_SCREEN);
1244 // go back to window mode
1245 if (videoWindow->IsFullScreen())
1246 videoWindow->PostMessage(TOGGLE_FULL_SCREEN);
1250 if (interfaceWindow)
1251 interfaceWindow->PostMessage(PAUSE_PLAYBACK);
1254 if (interfaceWindow)
1256 if (mods & B_SHIFT_KEY)
1258 interfaceWindow->PostMessage(NEXT_TITLE);
1261 interfaceWindow->PostMessage(NEXT_CHAPTER);
1265 if (interfaceWindow)
1267 if (mods & B_SHIFT_KEY)
1269 interfaceWindow->PostMessage(PREV_TITLE);
1272 interfaceWindow->PostMessage(PREV_CHAPTER);
1276 // previous file in playlist
1277 interfaceWindow->PostMessage(PREV_FILE);
1280 // next file in playlist
1281 interfaceWindow->PostMessage(NEXT_FILE);
1286 videoWindow->PostMessage( SCREEN_SHOT );
1289 BView::KeyDown(bytes, numBytes);
1295 /*****************************************************************************
1297 *****************************************************************************/
1299 VLCView::Draw(BRect updateRect)
1301 VideoWindow* window = dynamic_cast<VideoWindow*>( Window() );
1302 if ( window && window->mode == BITMAP )
1303 FillRect( updateRect );
1306 /*****************************************************************************
1308 *****************************************************************************/
1309 static int Init ( vout_thread_t * );
1310 static void End ( vout_thread_t * );
1311 // static int Manage ( vout_thread_t * );
1312 static void Display ( vout_thread_t *, picture_t * );
1314 static int BeosOpenDisplay ( vout_thread_t *p_vout );
1315 static void BeosCloseDisplay( vout_thread_t *p_vout );
1317 /*****************************************************************************
1318 * OpenVideo: allocates BeOS video thread output method
1319 *****************************************************************************
1320 * This function allocates and initializes a BeOS vout method.
1321 *****************************************************************************/
1322 int E_(OpenVideo) ( vlc_object_t *p_this )
1324 vout_thread_t * p_vout = (vout_thread_t *)p_this;
1326 /* Allocate structure */
1327 p_vout->p_sys = (vout_sys_t*) malloc( sizeof( vout_sys_t ) );
1328 if( p_vout->p_sys == NULL )
1330 msg_Err( p_vout, "out of memory" );
1333 p_vout->p_sys->i_width = p_vout->render.i_width;
1334 p_vout->p_sys->i_height = p_vout->render.i_height;
1335 p_vout->p_sys->source_chroma = p_vout->render.i_chroma;
1337 p_vout->pf_init = Init;
1338 p_vout->pf_end = End;
1339 p_vout->pf_manage = NULL;
1340 p_vout->pf_render = NULL;
1341 p_vout->pf_display = Display;
1346 /*****************************************************************************
1347 * Init: initialize BeOS video thread output method
1348 *****************************************************************************/
1349 int Init( vout_thread_t *p_vout )
1354 I_OUTPUTPICTURES = 0;
1356 /* Open and initialize device */
1357 if( BeosOpenDisplay( p_vout ) )
1359 msg_Err(p_vout, "vout error: can't open display");
1362 p_vout->output.i_width = p_vout->render.i_width;
1363 p_vout->output.i_height = p_vout->render.i_height;
1365 /* Assume we have square pixels */
1366 p_vout->output.i_aspect = p_vout->p_sys->i_width
1367 * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
1368 p_vout->output.i_chroma = colspace[p_vout->p_sys->p_window->colspace_index].chroma;
1369 p_vout->p_sys->i_index = 0;
1371 p_vout->b_direct = 1;
1373 p_vout->output.i_rmask = 0x00ff0000;
1374 p_vout->output.i_gmask = 0x0000ff00;
1375 p_vout->output.i_bmask = 0x000000ff;
1377 for (int buffer_index = 0 ; buffer_index < 3; buffer_index++)
1380 /* Find an empty picture slot */
1381 for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
1384 if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
1386 p_pic = p_vout->p_picture + i_index;
1395 p_pic->p->p_pixels = (u8*)p_vout->p_sys->p_window->bitmap[buffer_index]->Bits();
1396 p_pic->p->i_lines = p_vout->p_sys->i_height;
1398 p_pic->p->i_pixel_pitch = colspace[p_vout->p_sys->p_window->colspace_index].pixel_bytes;
1399 p_pic->i_planes = colspace[p_vout->p_sys->p_window->colspace_index].planes;
1400 p_pic->p->i_pitch = p_vout->p_sys->p_window->bitmap[buffer_index]->BytesPerRow();
1401 p_pic->p->i_visible_pitch = p_pic->p->i_pixel_pitch * ( p_vout->p_sys->p_window->bitmap[buffer_index]->Bounds().IntegerWidth() + 1 );
1403 p_pic->i_status = DESTROYED_PICTURE;
1404 p_pic->i_type = DIRECT_PICTURE;
1406 PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
1414 /*****************************************************************************
1415 * End: terminate BeOS video thread output method
1416 *****************************************************************************/
1417 void End( vout_thread_t *p_vout )
1419 BeosCloseDisplay( p_vout );
1422 /*****************************************************************************
1423 * CloseVideo: destroy BeOS video thread output method
1424 *****************************************************************************
1425 * Terminate an output method created by DummyCreateOutputMethod
1426 *****************************************************************************/
1427 void E_(CloseVideo) ( vlc_object_t *p_this )
1429 vout_thread_t * p_vout = (vout_thread_t *)p_this;
1431 free( p_vout->p_sys );
1434 /*****************************************************************************
1435 * Display: displays previously rendered output
1436 *****************************************************************************
1437 * This function send the currently rendered image to BeOS image, waits until
1438 * it is displayed and switch the two rendering buffers, preparing next frame.
1439 *****************************************************************************/
1440 void Display( vout_thread_t *p_vout, picture_t *p_pic )
1442 VideoWindow * p_win = p_vout->p_sys->p_window;
1444 /* draw buffer if required */
1445 if (!p_win->teardownwindow)
1447 p_win->drawBuffer(p_vout->p_sys->i_index);
1450 p_vout->p_sys->i_index = ++p_vout->p_sys->i_index % 3;
1451 p_pic->p->p_pixels = (u8*)p_vout->p_sys->p_window->bitmap[p_vout->p_sys->i_index]->Bits();
1454 /* following functions are local */
1456 /*****************************************************************************
1457 * BeosOpenDisplay: open and initialize BeOS device
1458 *****************************************************************************/
1459 static int BeosOpenDisplay( vout_thread_t *p_vout )
1462 p_vout->p_sys->p_window = new VideoWindow( p_vout->p_sys->i_width - 1,
1463 p_vout->p_sys->i_height - 1,
1465 20 + p_vout->i_window_width - 1,
1466 50 + p_vout->i_window_height - 1 ),
1468 if( p_vout->p_sys->p_window == NULL )
1470 msg_Err( p_vout, "cannot allocate VideoWindow" );
1475 p_vout->p_sys->p_window->Show();
1481 /*****************************************************************************
1482 * BeosDisplay: close and reset BeOS device
1483 *****************************************************************************
1484 * Returns all resources allocated by BeosOpenDisplay and restore the original
1485 * state of the device.
1486 *****************************************************************************/
1487 static void BeosCloseDisplay( vout_thread_t *p_vout )
1489 VideoWindow * p_win = p_vout->p_sys->p_window;
1490 /* Destroy the video window */
1491 if( p_win != NULL && !p_win->teardownwindow)
1494 p_win->teardownwindow = true;