00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <errno.h>
00032 #include <stdlib.h>
00033 #include <stdio.h>
00034 #include <string.h>
00035
00036 #include <Application.h>
00037 #include <BitmapStream.h>
00038 #include <Bitmap.h>
00039 #include <Directory.h>
00040 #include <DirectWindow.h>
00041 #include <File.h>
00042 #include <InterfaceKit.h>
00043 #include <NodeInfo.h>
00044 #include <String.h>
00045 #include <TranslatorRoster.h>
00046 #include <WindowScreen.h>
00047
00048
00049 #include <vlc/vlc.h>
00050 #include <vlc/intf.h>
00051 #include <vlc/vout.h>
00052 #include <vlc_keys.h>
00053
00054 #include "InterfaceWindow.h"
00055 #include "DrawingTidbits.h"
00056 #include "MsgVals.h"
00057
00058 #include "VideoWindow.h"
00059
00060
00061
00062
00063
00064
00065
00066 struct vout_sys_t
00067 {
00068 VideoWindow * p_window;
00069
00070 int32_t i_width;
00071 int32_t i_height;
00072
00073
00074 uint32_t source_chroma;
00075 int i_index;
00076
00077 };
00078
00079 #define MOUSE_IDLE_TIMEOUT 2000000 // two seconds
00080 #define MIN_AUTO_VSYNC_REFRESH 61 // Hz
00081
00082
00083
00084
00085 BWindow*
00086 beos_GetAppWindow(char *name)
00087 {
00088 int32_t index;
00089 BWindow *window;
00090
00091 for (index = 0 ; ; index++)
00092 {
00093 window = be_app->WindowAt(index);
00094 if (window == NULL)
00095 break;
00096 if (window->LockWithTimeout(20000) == B_OK)
00097 {
00098 if (strcmp(window->Name(), name) == 0)
00099 {
00100 window->Unlock();
00101 break;
00102 }
00103 window->Unlock();
00104 }
00105 }
00106 return window;
00107 }
00108
00109 static const int beos_keys[][2] =
00110 {
00111 { B_LEFT_ARROW, KEY_LEFT },
00112 { B_RIGHT_ARROW, KEY_RIGHT },
00113 { B_UP_ARROW, KEY_UP },
00114 { B_DOWN_ARROW, KEY_DOWN },
00115 { B_SPACE, KEY_SPACE },
00116 { B_ENTER, KEY_ENTER },
00117 { B_F1_KEY, KEY_F1 },
00118 { B_F2_KEY, KEY_F2 },
00119 { B_F3_KEY, KEY_F3 },
00120 { B_F4_KEY, KEY_F4 },
00121 { B_F5_KEY, KEY_F5 },
00122 { B_F6_KEY, KEY_F6 },
00123 { B_F7_KEY, KEY_F7 },
00124 { B_F8_KEY, KEY_F8 },
00125 { B_F9_KEY, KEY_F9 },
00126 { B_F10_KEY, KEY_F10 },
00127 { B_F11_KEY, KEY_F11 },
00128 { B_F12_KEY, KEY_F12 },
00129 { B_HOME, KEY_HOME },
00130 { B_END, KEY_END },
00131 { B_ESCAPE, KEY_ESC },
00132 { B_PAGE_UP, KEY_PAGEUP },
00133 { B_PAGE_DOWN, KEY_PAGEDOWN },
00134 { B_TAB, KEY_TAB },
00135 { B_BACKSPACE, KEY_BACKSPACE }
00136 };
00137
00138 static int ConvertKeyFromVLC( int key )
00139 {
00140 for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
00141 {
00142 if( beos_keys[i][1] == key )
00143 {
00144 return beos_keys[i][0];
00145 }
00146 }
00147 return key;
00148 }
00149
00150 static int ConvertKeyToVLC( int key )
00151 {
00152 for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
00153 {
00154 if( beos_keys[i][0] == key )
00155 {
00156 return beos_keys[i][1];
00157 }
00158 }
00159 return key;
00160 }
00161
00162
00163
00164
00165 BWindow*
00166 get_interface_window()
00167 {
00168 return beos_GetAppWindow( "VLC " PACKAGE_VERSION );
00169 }
00170
00171 class BackgroundView : public BView
00172 {
00173 public:
00174 BackgroundView(BRect frame, VLCView* view)
00175 : BView(frame, "background",
00176 B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE),
00177 fVideoView(view)
00178 {
00179 SetViewColor(kBlack);
00180 }
00181 virtual ~BackgroundView() {}
00182
00183 virtual void MouseDown(BPoint where)
00184 {
00185
00186 where = fVideoView->ConvertFromParent(where);
00187
00188 fVideoView->MouseDown(where);
00189 }
00190 virtual void MouseMoved(BPoint where, uint32_t transit,
00191 const BMessage* dragMessage)
00192 {
00193
00194 where = fVideoView->ConvertFromParent(where);
00195
00196 fVideoView->MouseMoved(where, transit, dragMessage);
00197
00198
00199
00200 }
00201
00202 private:
00203 VLCView* fVideoView;
00204 };
00205
00206
00207
00208
00209
00210 VideoSettings::VideoSettings()
00211 : fVideoSize( SIZE_100 ),
00212 fFlags( FLAG_CORRECT_RATIO ),
00213 fSettings( new BMessage( 'sett' ) )
00214 {
00215
00216 status_t ret = load_settings( fSettings, "video_settings", "VideoLAN Client" );
00217 if ( ret == B_OK )
00218 {
00219 uint32_t flags;
00220 if ( fSettings->FindInt32( "flags", (int32*)&flags ) == B_OK )
00221 SetFlags( flags );
00222 uint32_t size;
00223 if ( fSettings->FindInt32( "video size", (int32*)&size ) == B_OK )
00224 SetVideoSize( size );
00225 }
00226 else
00227 {
00228
00229 BScreen screen(B_MAIN_SCREEN_ID);
00230 if (screen.IsValid())
00231 {
00232 display_mode mode;
00233 screen.GetMode(&mode);
00234 float refresh = (mode.timing.pixel_clock * 1000)
00235 / ((mode.timing.h_total)* (mode.timing.v_total));
00236 if (refresh < MIN_AUTO_VSYNC_REFRESH)
00237 AddFlags(FLAG_SYNC_RETRACE);
00238 }
00239 }
00240 }
00241
00242 VideoSettings::VideoSettings( const VideoSettings& clone )
00243 : fVideoSize( clone.VideoSize() ),
00244 fFlags( clone.Flags() ),
00245 fSettings( NULL )
00246 {
00247 }
00248
00249
00250 VideoSettings::~VideoSettings()
00251 {
00252 if ( fSettings )
00253 {
00254
00255
00256 if (fSettings->ReplaceInt32( "video size", VideoSize() ) != B_OK)
00257 fSettings->AddInt32( "video size", VideoSize() );
00258 if (fSettings->ReplaceInt32( "flags", Flags() ) != B_OK)
00259 fSettings->AddInt32( "flags", Flags() );
00260
00261 save_settings( fSettings, "video_settings", "VideoLAN Client" );
00262 delete fSettings;
00263 }
00264 else
00265 {
00266
00267 fDefaultSettings.SetVideoSize( VideoSize() );
00268 fDefaultSettings.SetFlags( Flags() );
00269 }
00270 }
00271
00272
00273
00274
00275 VideoSettings*
00276 VideoSettings::DefaultSettings()
00277 {
00278 return &fDefaultSettings;
00279 }
00280
00281
00282
00283
00284 void
00285 VideoSettings::SetVideoSize( uint32_t mode )
00286 {
00287 fVideoSize = mode;
00288 }
00289
00290
00291 VideoSettings
00292 VideoSettings::fDefaultSettings;
00293
00294
00295
00296
00297
00298 VideoWindow::VideoWindow(int v_width, int v_height, BRect frame,
00299 vout_thread_t *p_videoout)
00300 : BWindow(frame, NULL, B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_MINIMIZABLE),
00301 i_width(frame.IntegerWidth()),
00302 i_height(frame.IntegerHeight()),
00303 winSize(frame),
00304 i_buffer(0),
00305 teardownwindow(false),
00306 fTrueWidth(v_width),
00307 fTrueHeight(v_height),
00308 fCachedFeel(B_NORMAL_WINDOW_FEEL),
00309 fInterfaceShowing(false),
00310 fInitStatus(B_ERROR),
00311 fSettings(new VideoSettings(*VideoSettings::DefaultSettings()))
00312 {
00313 p_vout = p_videoout;
00314
00315
00316 view = new VLCView( Bounds(), p_vout );
00317
00318
00319 BView *mainView = new BackgroundView( Bounds(), view );
00320 AddChild(mainView);
00321 mainView->AddChild(view);
00322
00323
00324 for (int32_t i = 0; i < 3; i++)
00325 bitmap[i] = NULL;
00326 fInitStatus = _AllocateBuffers(v_width, v_height, &mode);
00327
00328
00329 FrameResized(i_width, i_height);
00330
00331 if (fInitStatus >= B_OK && mode == OVERLAY)
00332 {
00333 overlay_restrictions r;
00334
00335 bitmap[0]->GetOverlayRestrictions(&r);
00336 SetSizeLimits((i_width * r.min_width_scale), i_width * r.max_width_scale,
00337 (i_height * r.min_height_scale), i_height * r.max_height_scale);
00338 }
00339
00340
00341 if (config_GetInt(p_vout, "fullscreen"))
00342 fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
00343
00344 _SetToSettings();
00345 }
00346
00347 VideoWindow::~VideoWindow()
00348 {
00349 int32 result;
00350
00351 teardownwindow = true;
00352 wait_for_thread(fDrawThreadID, &result);
00353 _FreeBuffers();
00354 delete fSettings;
00355 }
00356
00357
00358
00359
00360 void
00361 VideoWindow::MessageReceived( BMessage *p_message )
00362 {
00363 switch( p_message->what )
00364 {
00365 case SHOW_INTERFACE:
00366 SetInterfaceShowing( true );
00367 break;
00368 case TOGGLE_FULL_SCREEN:
00369 BWindow::Zoom();
00370 break;
00371 case RESIZE_50:
00372 case RESIZE_100:
00373 case RESIZE_200:
00374 if (IsFullScreen())
00375 BWindow::Zoom();
00376 _SetVideoSize(p_message->what);
00377 break;
00378 case VERT_SYNC:
00379 SetSyncToRetrace(!IsSyncedToRetrace());
00380 break;
00381 case WINDOW_FEEL:
00382 {
00383 window_feel winFeel;
00384 if (p_message->FindInt32("WinFeel", (int32*)&winFeel) == B_OK)
00385 {
00386 SetFeel(winFeel);
00387 fCachedFeel = winFeel;
00388 if (winFeel == B_FLOATING_ALL_WINDOW_FEEL)
00389 fSettings->AddFlags(VideoSettings::FLAG_ON_TOP_ALL);
00390 else
00391 fSettings->ClearFlags(VideoSettings::FLAG_ON_TOP_ALL);
00392 }
00393 }
00394 break;
00395 case ASPECT_CORRECT:
00396 SetCorrectAspectRatio(!CorrectAspectRatio());
00397 break;
00398
00399 case B_KEY_DOWN:
00400 case B_UNMAPPED_KEY_DOWN:
00401 case B_KEY_UP:
00402 case B_UNMAPPED_KEY_UP:
00403 {
00404 key_map * keys;
00405 char * chars;
00406 int32 key, modifiers;
00407
00408 if( p_message->FindInt32( "key", &key ) != B_OK ||
00409 p_message->FindInt32( "modifiers", &modifiers ) != B_OK )
00410 {
00411
00412 break;
00413 }
00414
00415 if( ( p_message->what == B_KEY_UP ||
00416 p_message->what == B_UNMAPPED_KEY_UP ) &&
00417 !( modifiers & B_COMMAND_KEY ) )
00418 {
00419
00420
00421
00422 break;
00423 }
00424
00425
00426
00427
00428 if( ( modifiers & B_COMMAND_KEY ) &&
00429 key >= 18 && key <= 20 )
00430 {
00431 if( key == 18 )
00432 PostMessage( RESIZE_50 );
00433 else if( key == 19 )
00434 PostMessage( RESIZE_100 );
00435 else
00436 PostMessage( RESIZE_200 );
00437
00438 break;
00439 }
00440
00441
00442 get_key_map( &keys, &chars );
00443
00444 if( key >= 128 || chars[keys->normal_map[key]] != 1 )
00445 {
00446
00447 free( keys );
00448 free( chars );
00449 break;
00450 }
00451
00452 vlc_value_t val;
00453 val.i_int = ConvertKeyToVLC( chars[keys->normal_map[key]+1] );
00454
00455 if( modifiers & B_COMMAND_KEY )
00456 {
00457 val.i_int |= KEY_MODIFIER_ALT;
00458 }
00459 if( modifiers & B_SHIFT_KEY )
00460 {
00461 val.i_int |= KEY_MODIFIER_SHIFT;
00462 }
00463 if( modifiers & B_CONTROL_KEY )
00464 {
00465 val.i_int |= KEY_MODIFIER_CTRL;
00466 }
00467 var_Set( p_vout->p_vlc, "key-pressed", val );
00468
00469 free( keys );
00470 free( chars );
00471 break;
00472 }
00473
00474 default:
00475 BWindow::MessageReceived( p_message );
00476 break;
00477 }
00478 }
00479
00480
00481
00482
00483 void
00484 VideoWindow::Zoom(BPoint origin, float width, float height )
00485 {
00486 ToggleFullScreen();
00487 }
00488
00489
00490
00491
00492 void
00493 VideoWindow::FrameMoved(BPoint origin)
00494 {
00495 if (IsFullScreen())
00496 return ;
00497 winSize = Frame();
00498 }
00499
00500
00501
00502
00503 void
00504 VideoWindow::FrameResized( float width, float height )
00505 {
00506 int32_t useWidth = CorrectAspectRatio() ? i_width : fTrueWidth;
00507 int32_t useHeight = CorrectAspectRatio() ? i_height : fTrueHeight;
00508 float out_width, out_height;
00509 float out_left, out_top;
00510 float width_scale = width / useWidth;
00511 float height_scale = height / useHeight;
00512
00513 if (width_scale <= height_scale)
00514 {
00515 out_width = (useWidth * width_scale);
00516 out_height = (useHeight * width_scale);
00517 out_left = 0;
00518 out_top = (height - out_height) / 2;
00519 }
00520 else
00521 {
00522 out_width = (useWidth * height_scale);
00523 out_height = (useHeight * height_scale);
00524 out_top = 0;
00525 out_left = (width - out_width) / 2;
00526 }
00527 view->MoveTo(out_left,out_top);
00528 view->ResizeTo(out_width, out_height);
00529
00530 if (!IsFullScreen())
00531 winSize = Frame();
00532 }
00533
00534
00535
00536
00537 void
00538 VideoWindow::ScreenChanged(BRect frame, color_space format)
00539 {
00540 BScreen screen(this);
00541 display_mode mode;
00542 screen.GetMode(&mode);
00543 float refresh = (mode.timing.pixel_clock * 1000)
00544 / ((mode.timing.h_total) * (mode.timing.v_total));
00545 SetSyncToRetrace(refresh < MIN_AUTO_VSYNC_REFRESH);
00546 }
00547
00548
00549
00550
00551 void
00552 VideoWindow::WindowActivated(bool active)
00553 {
00554 }
00555
00556
00557
00558
00559 void
00560 VideoWindow::drawBuffer(int bufferIndex)
00561 {
00562 i_buffer = bufferIndex;
00563
00564
00565 if (IsSyncedToRetrace())
00566 {
00567 BScreen screen(this);
00568 screen.WaitForRetrace(22000);
00569 }
00570 if (fInitStatus >= B_OK && LockLooper())
00571 {
00572
00573 if (mode == OVERLAY)
00574 {
00575 rgb_color key;
00576 view->SetViewOverlay(bitmap[i_buffer],
00577 bitmap[i_buffer]->Bounds() ,
00578 view->Bounds(),
00579 &key, B_FOLLOW_ALL,
00580 B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL|
00581 B_OVERLAY_TRANSFER_CHANNEL);
00582 view->SetViewColor(key);
00583 }
00584 else
00585 {
00586
00587 view->DrawBitmap(bitmap[i_buffer], view->Bounds() );
00588 }
00589 UnlockLooper();
00590 }
00591 }
00592
00593
00594
00595
00596 void
00597 VideoWindow::ToggleInterfaceShowing()
00598 {
00599 SetInterfaceShowing(!fInterfaceShowing);
00600 }
00601
00602
00603
00604
00605 void
00606 VideoWindow::SetInterfaceShowing(bool showIt)
00607 {
00608 BWindow* window = get_interface_window();
00609 if (window)
00610 {
00611 if (showIt)
00612 {
00613 if (fCachedFeel != B_NORMAL_WINDOW_FEEL)
00614 SetFeel(B_NORMAL_WINDOW_FEEL);
00615 window->Activate(true);
00616 SendBehind(window);
00617 }
00618 else
00619 {
00620 SetFeel(fCachedFeel);
00621 Activate(true);
00622 window->SendBehind(this);
00623 }
00624 fInterfaceShowing = showIt;
00625 }
00626 }
00627
00628
00629
00630
00631 void
00632 VideoWindow::SetCorrectAspectRatio(bool doIt)
00633 {
00634 if (CorrectAspectRatio() != doIt)
00635 {
00636 if (doIt)
00637 fSettings->AddFlags(VideoSettings::FLAG_CORRECT_RATIO);
00638 else
00639 fSettings->ClearFlags(VideoSettings::FLAG_CORRECT_RATIO);
00640 FrameResized(Bounds().Width(), Bounds().Height());
00641 }
00642 }
00643
00644
00645
00646
00647 bool
00648 VideoWindow::CorrectAspectRatio() const
00649 {
00650 return fSettings->HasFlags(VideoSettings::FLAG_CORRECT_RATIO);
00651 }
00652
00653
00654
00655
00656 void
00657 VideoWindow::ToggleFullScreen()
00658 {
00659 SetFullScreen(!IsFullScreen());
00660 }
00661
00662
00663
00664
00665 void
00666 VideoWindow::SetFullScreen(bool doIt)
00667 {
00668 if (doIt)
00669 {
00670 SetLook( B_NO_BORDER_WINDOW_LOOK );
00671 BScreen screen( this );
00672 BRect rect = screen.Frame();
00673 Activate();
00674 MoveTo(0.0, 0.0);
00675 ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
00676 be_app->ObscureCursor();
00677 fInterfaceShowing = false;
00678 fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
00679 }
00680 else
00681 {
00682 SetLook( B_TITLED_WINDOW_LOOK );
00683 MoveTo(winSize.left, winSize.top);
00684 ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
00685 be_app->ShowCursor();
00686 fInterfaceShowing = true;
00687 fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
00688 }
00689 }
00690
00691
00692
00693
00694 bool
00695 VideoWindow::IsFullScreen() const
00696 {
00697 return fSettings->HasFlags(VideoSettings::FLAG_FULL_SCREEN);
00698 }
00699
00700
00701
00702
00703 void
00704 VideoWindow::SetSyncToRetrace(bool doIt)
00705 {
00706 if (doIt)
00707 fSettings->AddFlags(VideoSettings::FLAG_SYNC_RETRACE);
00708 else
00709 fSettings->ClearFlags(VideoSettings::FLAG_SYNC_RETRACE);
00710 }
00711
00712
00713
00714
00715 bool
00716 VideoWindow::IsSyncedToRetrace() const
00717 {
00718 return fSettings->HasFlags(VideoSettings::FLAG_SYNC_RETRACE);
00719 }
00720
00721
00722
00723
00724
00725 status_t
00726 VideoWindow::_AllocateBuffers(int width, int height, int* mode)
00727 {
00728
00729 _FreeBuffers();
00730
00731 *mode = BITMAP;
00732 bitmap_count = 3;
00733
00734 BRect bitmapFrame( 0, 0, width, height );
00735
00736 int noOverlay = !config_GetInt( p_vout, "overlay" );
00737
00738
00739
00740
00741
00742 for( int i = 0; i < COLOR_COUNT; i++ )
00743 {
00744 if( noOverlay )
00745 break;
00746
00747 bitmap[0] = new BBitmap( bitmapFrame,
00748 B_BITMAP_WILL_OVERLAY |
00749 B_BITMAP_RESERVE_OVERLAY_CHANNEL,
00750 colspace[i].colspace );
00751 if( bitmap[0] && bitmap[0]->InitCheck() == B_OK )
00752 {
00753 colspace_index = i;
00754
00755 *mode = OVERLAY;
00756 rgb_color key;
00757 view->SetViewOverlay( bitmap[0], bitmap[0]->Bounds(),
00758 view->Bounds(), &key, B_FOLLOW_ALL,
00759 B_OVERLAY_FILTER_HORIZONTAL |
00760 B_OVERLAY_FILTER_VERTICAL );
00761 view->SetViewColor( key );
00762 SetTitle( "VLC " PACKAGE_VERSION " (Overlay)" );
00763
00764 bitmap[1] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
00765 colspace[colspace_index].colspace);
00766 if( bitmap[1] && bitmap[1]->InitCheck() == B_OK )
00767 {
00768
00769 bitmap[2] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
00770 colspace[colspace_index].colspace);
00771 if( bitmap[2] && bitmap[2]->InitCheck() == B_OK )
00772 {
00773 msg_Dbg( p_vout, "using double-buffered overlay" );
00774 }
00775 else
00776 {
00777 msg_Dbg( p_vout, "using single-buffered overlay" );
00778 bitmap_count = 2;
00779 if( bitmap[2] ) { delete bitmap[2]; bitmap[2] = NULL; }
00780 }
00781 }
00782 else
00783 {
00784 msg_Dbg( p_vout, "using simple overlay" );
00785 bitmap_count = 1;
00786 if( bitmap[1] ) { delete bitmap[1]; bitmap[1] = NULL; }
00787 }
00788 break;
00789 }
00790 else
00791 {
00792 if( bitmap[0] ) { delete bitmap[0]; bitmap[0] = NULL; }
00793 }
00794 }
00795
00796 if (*mode == BITMAP)
00797 {
00798 msg_Warn( p_vout, "no possible overlay" );
00799
00800
00801 colspace_index = DEFAULT_COL;
00802 bitmap[0] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
00803 bitmap[1] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
00804 bitmap[2] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
00805 SetTitle( "VLC " PACKAGE_VERSION " (Bitmap)" );
00806 }
00807
00808 status_t status = B_ERROR;
00809 for (int32_t i = 0; i < bitmap_count; i++)
00810 {
00811 if (bitmap[i])
00812 status = bitmap[i]->InitCheck();
00813 if (status < B_OK)
00814 break;
00815 }
00816 if (status >= B_OK)
00817 {
00818
00819 for (int32_t i = 0; i < bitmap_count; i++)
00820 _BlankBitmap(bitmap[i]);
00821 }
00822 return status;
00823 }
00824
00825
00826
00827
00828 void
00829 VideoWindow::_FreeBuffers()
00830 {
00831 if( bitmap[0] ) { delete bitmap[0]; bitmap[0] = NULL; }
00832 if( bitmap[1] ) { delete bitmap[1]; bitmap[1] = NULL; }
00833 if( bitmap[2] ) { delete bitmap[2]; bitmap[2] = NULL; }
00834 fInitStatus = B_ERROR;
00835 }
00836
00837
00838
00839
00840 void
00841 VideoWindow::_BlankBitmap(BBitmap* bitmap) const
00842 {
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852 switch (bitmap->ColorSpace()) {
00853 case B_YCbCr422: {
00854
00855 int32_t height = bitmap->Bounds().IntegerHeight() + 1;
00856 uint8_t* bits = (uint8_t*)bitmap->Bits();
00857 int32_t bpr = bitmap->BytesPerRow();
00858 for (int32_t y = 0; y < height; y++) {
00859
00860 for (int32_t i = 0; i < bpr; i += 2) {
00861
00862 bits[i] = 16;
00863 bits[i + 1] = 128;
00864 }
00865
00866 bits += bpr;
00867 }
00868 break;
00869 }
00870 case B_YCbCr420: {
00871
00872
00873
00874 int32_t height = bitmap->Bounds().IntegerHeight() + 1;
00875 uint8_t* bits = (uint8_t*)bitmap->Bits();
00876 int32_t bpr = bitmap->BytesPerRow();
00877 for (int32_t y = 0; y < height; y += 1) {
00878
00879 for (int32_t i = 0; i < bpr; i += 3) {
00880
00881 bits[i] = 128;
00882 bits[i + 1] = 16;
00883 bits[i + 2] = 16;
00884 }
00885
00886 bits += bpr;
00887 }
00888 break;
00889 }
00890 case B_YUV422: {
00891
00892
00893 int32_t height = bitmap->Bounds().IntegerHeight() + 1;
00894 uint8_t* bits = (uint8_t*)bitmap->Bits();
00895 int32_t bpr = bitmap->BytesPerRow();
00896 for (int32_t y = 0; y < height; y += 1) {
00897
00898 for (int32_t i = 0; i < bpr; i += 2) {
00899
00900 bits[i] = 128;
00901 bits[i + 1] = 0;
00902 }
00903
00904 bits += bpr;
00905 }
00906 break;
00907 }
00908 default:
00909 memset(bitmap->Bits(), 0, bitmap->BitsLength());
00910 break;
00911 }
00912 }
00913
00914
00915
00916
00917 void
00918 VideoWindow::_SetVideoSize(uint32_t mode)
00919 {
00920
00921 int32_t width = CorrectAspectRatio() ? i_width : fTrueWidth;
00922 int32_t height = CorrectAspectRatio() ? i_height : fTrueHeight;
00923 switch (mode)
00924 {
00925 case RESIZE_50:
00926 width /= 2;
00927 height /= 2;
00928 break;
00929 case RESIZE_200:
00930 width *= 2;
00931 height *= 2;
00932 break;
00933 case RESIZE_100:
00934 default:
00935 break;
00936 }
00937 fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
00938 ResizeTo(width, height);
00939 }
00940
00941
00942
00943
00944 void
00945 VideoWindow::_SetToSettings()
00946 {
00947
00948 uint32_t mode = RESIZE_100;
00949 switch (fSettings->VideoSize())
00950 {
00951 case VideoSettings::SIZE_50:
00952 mode = RESIZE_50;
00953 break;
00954 case VideoSettings::SIZE_200:
00955 mode = RESIZE_200;
00956 break;
00957 case VideoSettings::SIZE_100:
00958 case VideoSettings::SIZE_OTHER:
00959 default:
00960 break;
00961 }
00962 bool fullscreen = IsFullScreen();
00963 _SetVideoSize(mode);
00964
00965
00966 if (fullscreen)
00967 SetFullScreen(true);
00968 if (fSettings->HasFlags(VideoSettings::FLAG_ON_TOP_ALL))
00969 fCachedFeel = B_FLOATING_ALL_WINDOW_FEEL;
00970 else
00971 fCachedFeel = B_NORMAL_WINDOW_FEEL;
00972 SetFeel(fCachedFeel);
00973 }
00974
00975
00976
00977
00978 VLCView::VLCView(BRect bounds, vout_thread_t *p_vout_instance )
00979 : BView(bounds, "video view", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED),
00980 fLastMouseMovedTime(mdate()),
00981 fCursorHidden(false),
00982 fCursorInside(false),
00983 fIgnoreDoubleClick(false)
00984 {
00985 p_vout = p_vout_instance;
00986 SetViewColor(B_TRANSPARENT_32_BIT);
00987 }
00988
00989
00990
00991
00992 VLCView::~VLCView()
00993 {
00994 }
00995
00996
00997
00998
00999 void
01000 VLCView::AttachedToWindow()
01001 {
01002
01003 Window()->SetPulseRate(1000000);
01004 }
01005
01006
01007
01008
01009 void
01010 VLCView::MouseDown(BPoint where)
01011 {
01012 VideoWindow* videoWindow = dynamic_cast<VideoWindow*>(Window());
01013 BMessage* msg = Window()->CurrentMessage();
01014 int32 clicks;
01015 uint32_t buttons;
01016 msg->FindInt32("clicks", &clicks);
01017 msg->FindInt32("buttons", (int32*)&buttons);
01018
01019 if (videoWindow)
01020 {
01021 if (buttons & B_PRIMARY_MOUSE_BUTTON)
01022 {
01023 if (clicks == 2 && !fIgnoreDoubleClick)
01024 Window()->Zoom();
01025
01026
01027 fIgnoreDoubleClick = false;
01028 }
01029 else
01030 {
01031 if (buttons & B_SECONDARY_MOUSE_BUTTON)
01032 {
01033
01034
01035
01036 fIgnoreDoubleClick = true;
01037
01038 BPopUpMenu *menu = new BPopUpMenu("context menu");
01039 menu->SetRadioMode(false);
01040
01041 if( videoWindow->IsFullScreen() )
01042 {
01043 BMenuItem *intfItem =
01044 new BMenuItem( _("Show Interface"), new BMessage(SHOW_INTERFACE) );
01045 menu->AddItem( intfItem );
01046 }
01047
01048 BMenuItem *halfItem = new BMenuItem(_("50%"), new BMessage(RESIZE_50));
01049 menu->AddItem(halfItem);
01050
01051 BMenuItem *origItem = new BMenuItem(_("100%"), new BMessage(RESIZE_100));
01052 menu->AddItem(origItem);
01053
01054 BMenuItem *doubleItem = new BMenuItem(_("200%"), new BMessage(RESIZE_200));
01055 menu->AddItem(doubleItem);
01056
01057 BMenuItem *zoomItem = new BMenuItem(_("Fullscreen"), new BMessage(TOGGLE_FULL_SCREEN));
01058 zoomItem->SetMarked(videoWindow->IsFullScreen());
01059 menu->AddItem(zoomItem);
01060
01061 menu->AddSeparatorItem();
01062
01063
01064 BMenuItem *vsyncItem = new BMenuItem(_("Vertical Sync"), new BMessage(VERT_SYNC));
01065 vsyncItem->SetMarked(videoWindow->IsSyncedToRetrace());
01066 menu->AddItem(vsyncItem);
01067
01068 BMenuItem *aspectItem = new BMenuItem(_("Correct Aspect Ratio"), new BMessage(ASPECT_CORRECT));
01069 aspectItem->SetMarked(videoWindow->CorrectAspectRatio());
01070 menu->AddItem(aspectItem);
01071
01072 menu->AddSeparatorItem();
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093 BMessage *windowFeelMsg = new BMessage( WINDOW_FEEL );
01094 bool onTop = videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL;
01095 window_feel feel = onTop ? B_NORMAL_WINDOW_FEEL : B_FLOATING_ALL_WINDOW_FEEL;
01096 windowFeelMsg->AddInt32( "WinFeel", (int32_t)feel );
01097 BMenuItem *windowFeelItem = new BMenuItem( _("Stay On Top"), windowFeelMsg );
01098 windowFeelItem->SetMarked( onTop );
01099 menu->AddItem( windowFeelItem );
01100
01101 menu->AddSeparatorItem();
01102
01103 BMenuItem* screenShotItem = new BMenuItem( _("Take Screen Shot"),
01104 new BMessage( SCREEN_SHOT ) );
01105 menu->AddItem( screenShotItem );
01106
01107 menu->SetTargetForItems( this );
01108 ConvertToScreen( &where );
01109 BRect mouseRect( where.x - 5, where.y - 5,
01110 where.x + 5, where.y + 5 );
01111 menu->Go( where, true, false, mouseRect, true );
01112 }
01113 }
01114 }
01115 fLastMouseMovedTime = mdate();
01116 fCursorHidden = false;
01117 }
01118
01119
01120
01121
01122 void
01123 VLCView::MouseUp( BPoint where )
01124 {
01125 vlc_value_t val;
01126 val.b_bool = VLC_TRUE;
01127 var_Set( p_vout, "mouse-clicked", val );
01128 }
01129
01130
01131
01132
01133 void
01134 VLCView::MouseMoved(BPoint point, uint32 transit, const BMessage* dragMessage)
01135 {
01136 fLastMouseMovedTime = mdate();
01137 fCursorHidden = false;
01138 fCursorInside = ( transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW );
01139
01140 if( !fCursorInside )
01141 {
01142 return;
01143 }
01144
01145 vlc_value_t val;
01146 unsigned int i_width, i_height, i_x, i_y;
01147 vout_PlacePicture( p_vout, (unsigned int)Bounds().Width(),
01148 (unsigned int)Bounds().Height(),
01149 &i_x, &i_y, &i_width, &i_height );
01150 val.i_int = ( (int)point.x - i_x ) * p_vout->render.i_width / i_width;
01151 var_Set( p_vout, "mouse-x", val );
01152 val.i_int = ( (int)point.y - i_y ) * p_vout->render.i_height / i_height;
01153 var_Set( p_vout, "mouse-y", val );
01154 val.b_bool = VLC_TRUE;
01155 var_Set( p_vout, "mouse-moved", val );
01156 }
01157
01158
01159
01160
01161 void
01162 VLCView::Pulse()
01163 {
01164
01165
01166
01167 VideoWindow *videoWindow = dynamic_cast<VideoWindow*>(Window());
01168 if (!fCursorHidden)
01169 {
01170 if (fCursorInside
01171 && mdate() - fLastMouseMovedTime > MOUSE_IDLE_TIMEOUT)
01172 {
01173 be_app->ObscureCursor();
01174 fCursorHidden = true;
01175
01176
01177 if (videoWindow && videoWindow->IsFullScreen())
01178 videoWindow->SetInterfaceShowing(false);
01179 }
01180 }
01181
01182
01183
01184 if( videoWindow && videoWindow->IsFullScreen() &&
01185 mdate() - fLastMouseMovedTime > 29000000 )
01186 {
01187 BPoint where;
01188 uint32 buttons;
01189 GetMouse(&where, &buttons, false);
01190 ConvertToScreen(&where);
01191 set_mouse_position((int32_t) where.x, (int32_t) where.y);
01192 }
01193 }
01194
01195
01196
01197
01198 void
01199 VLCView::Draw(BRect updateRect)
01200 {
01201 VideoWindow* window = dynamic_cast<VideoWindow*>( Window() );
01202 if ( window && window->mode == BITMAP )
01203 FillRect( updateRect );
01204 }
01205
01206
01207
01208
01209 static int Init ( vout_thread_t * );
01210 static void End ( vout_thread_t * );
01211 static int Manage ( vout_thread_t * );
01212 static void Display ( vout_thread_t *, picture_t * );
01213 static int Control ( vout_thread_t *, int, va_list );
01214
01215 static int BeosOpenDisplay ( vout_thread_t *p_vout );
01216 static void BeosCloseDisplay( vout_thread_t *p_vout );
01217
01218
01219
01220
01221
01222
01223 int E_(OpenVideo) ( vlc_object_t *p_this )
01224 {
01225 vout_thread_t * p_vout = (vout_thread_t *)p_this;
01226
01227
01228 p_vout->p_sys = (vout_sys_t*) malloc( sizeof( vout_sys_t ) );
01229 if( p_vout->p_sys == NULL )
01230 {
01231 msg_Err( p_vout, "out of memory" );
01232 return( 1 );
01233 }
01234 p_vout->p_sys->i_width = p_vout->render.i_width;
01235 p_vout->p_sys->i_height = p_vout->render.i_height;
01236 p_vout->p_sys->source_chroma = p_vout->render.i_chroma;
01237
01238 p_vout->pf_init = Init;
01239 p_vout->pf_end = End;
01240 p_vout->pf_manage = Manage;
01241 p_vout->pf_render = NULL;
01242 p_vout->pf_display = Display;
01243 p_vout->pf_control = Control;
01244
01245 return( 0 );
01246 }
01247
01248
01249
01250
01251 int Init( vout_thread_t *p_vout )
01252 {
01253 int i_index;
01254 picture_t *p_pic;
01255
01256 I_OUTPUTPICTURES = 0;
01257
01258
01259 if( BeosOpenDisplay( p_vout ) )
01260 {
01261 msg_Err(p_vout, "vout error: can't open display");
01262 return 0;
01263 }
01264 p_vout->output.i_width = p_vout->render.i_width;
01265 p_vout->output.i_height = p_vout->render.i_height;
01266
01267
01268 p_vout->output.i_aspect = p_vout->p_sys->i_width
01269 * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
01270 p_vout->output.i_chroma = colspace[p_vout->p_sys->p_window->colspace_index].chroma;
01271 p_vout->p_sys->i_index = 0;
01272
01273 p_vout->b_direct = 1;
01274
01275 p_vout->output.i_rmask = 0x00ff0000;
01276 p_vout->output.i_gmask = 0x0000ff00;
01277 p_vout->output.i_bmask = 0x000000ff;
01278
01279 for( int buffer_index = 0 ;
01280 buffer_index < p_vout->p_sys->p_window->bitmap_count;
01281 buffer_index++ )
01282 {
01283 p_pic = NULL;
01284
01285 for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
01286 {
01287 p_pic = NULL;
01288 if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
01289 {
01290 p_pic = p_vout->p_picture + i_index;
01291 break;
01292 }
01293 }
01294
01295 if( p_pic == NULL )
01296 {
01297 return 0;
01298 }
01299 p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[buffer_index]->Bits();
01300 p_pic->p->i_lines = p_vout->p_sys->i_height;
01301 p_pic->p->i_visible_lines = p_vout->p_sys->i_height;
01302
01303 p_pic->p->i_pixel_pitch = colspace[p_vout->p_sys->p_window->colspace_index].pixel_bytes;
01304 p_pic->i_planes = colspace[p_vout->p_sys->p_window->colspace_index].planes;
01305 p_pic->p->i_pitch = p_vout->p_sys->p_window->bitmap[buffer_index]->BytesPerRow();
01306 p_pic->p->i_visible_pitch = p_pic->p->i_pixel_pitch * ( p_vout->p_sys->p_window->bitmap[buffer_index]->Bounds().IntegerWidth() + 1 );
01307
01308 p_pic->i_status = DESTROYED_PICTURE;
01309 p_pic->i_type = DIRECT_PICTURE;
01310
01311 PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
01312
01313 I_OUTPUTPICTURES++;
01314 }
01315
01316 return( 0 );
01317 }
01318
01319
01320
01321
01322 void End( vout_thread_t *p_vout )
01323 {
01324 BeosCloseDisplay( p_vout );
01325 }
01326
01327
01328
01329
01330 static int Manage( vout_thread_t * p_vout )
01331 {
01332 if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
01333 {
01334 p_vout->p_sys->p_window->PostMessage( TOGGLE_FULL_SCREEN );
01335 p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
01336 }
01337
01338 return 0;
01339 }
01340
01341
01342
01343
01344
01345
01346 void E_(CloseVideo) ( vlc_object_t *p_this )
01347 {
01348 vout_thread_t * p_vout = (vout_thread_t *)p_this;
01349
01350 free( p_vout->p_sys );
01351 }
01352
01353
01354
01355
01356
01357
01358
01359 void Display( vout_thread_t *p_vout, picture_t *p_pic )
01360 {
01361 VideoWindow * p_win = p_vout->p_sys->p_window;
01362
01363
01364 if (!p_win->teardownwindow)
01365 {
01366 p_win->drawBuffer(p_vout->p_sys->i_index);
01367 }
01368
01369 p_vout->p_sys->i_index = ++p_vout->p_sys->i_index %
01370 p_vout->p_sys->p_window->bitmap_count;
01371 p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[p_vout->p_sys->i_index]->Bits();
01372 }
01373
01374 static int Control( vout_thread_t * p_vout, int i_query, va_list args )
01375 {
01376 return vout_vaControlDefault( p_vout, i_query, args );
01377 }
01378
01379
01380
01381
01382
01383
01384 static int BeosOpenDisplay( vout_thread_t *p_vout )
01385 {
01386
01387 p_vout->p_sys->p_window = new VideoWindow( p_vout->p_sys->i_width - 1,
01388 p_vout->p_sys->i_height - 1,
01389 BRect( 20, 50,
01390 20 + p_vout->i_window_width - 1,
01391 50 + p_vout->i_window_height - 1 ),
01392 p_vout );
01393 if( p_vout->p_sys->p_window == NULL )
01394 {
01395 msg_Err( p_vout, "cannot allocate VideoWindow" );
01396 return( 1 );
01397 }
01398 else
01399 {
01400 p_vout->p_sys->p_window->Show();
01401 }
01402
01403 return( 0 );
01404 }
01405
01406
01407
01408
01409
01410
01411
01412 static void BeosCloseDisplay( vout_thread_t *p_vout )
01413 {
01414 VideoWindow * p_win = p_vout->p_sys->p_window;
01415
01416 if( p_win != NULL && !p_win->teardownwindow)
01417 {
01418 p_win->Lock();
01419 p_win->teardownwindow = true;
01420 p_win->Hide();
01421 p_win->Quit();
01422 }
01423 p_win = NULL;
01424 }