📄 voutgl.m
字号:
#undef o_glview}- (id) initWithVout: (vout_thread_t *) vout{ /* Must be called from main thread: * "The NSView class is generally thread-safe, with a few exceptions. You * should create, destroy, resize, move, and perform other operations on NSView * objects only from the main thread of an application. Drawing from secondary * threads is thread-safe as long as you bracket drawing calls with calls to * lockFocusIfCanDraw and unlockFocus." Cocoa Thread Safety */ p_vout = vout; NSOpenGLPixelFormatAttribute attribs[] = { NSOpenGLPFADoubleBuffer, NSOpenGLPFAAccelerated, NSOpenGLPFANoRecovery, NSOpenGLPFAColorSize, 24, NSOpenGLPFAAlphaSize, 8, NSOpenGLPFADepthSize, 24, NSOpenGLPFAWindow, 0 }; NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs]; if( !fmt ) { msg_Warn( p_vout, "could not create OpenGL video output" ); return nil; } self = [super initWithFrame: NSMakeRect(0,0,10,10) pixelFormat: fmt]; [fmt release]; [[self openGLContext] makeCurrentContext]; [[self openGLContext] update]; /* Swap buffers only during the vertical retrace of the monitor. http://developer.apple.com/documentation/GraphicsImaging/ Conceptual/OpenGL/chap5/chapter_5_section_44.html */ GLint params[] = { 1 }; CGLSetParameter( CGLGetCurrentContext(), kCGLCPSwapInterval, params ); return self;}- (BOOL)mouseDownCanMoveWindow{ return YES;}- (void) reshape{ int x, y; vlc_value_t val; Lock( p_vout ); NSRect bounds = [self bounds]; var_Get( p_vout, "macosx-stretch", &val ); if( val.b_bool ) { x = bounds.size.width; y = bounds.size.height; } else if( bounds.size.height * p_vout->fmt_in.i_visible_width * p_vout->fmt_in.i_sar_num < bounds.size.width * p_vout->fmt_in.i_visible_height * p_vout->fmt_in.i_sar_den ) { x = ( bounds.size.height * p_vout->fmt_in.i_visible_width * p_vout->fmt_in.i_sar_num ) / ( p_vout->fmt_in.i_visible_height * p_vout->fmt_in.i_sar_den); y = bounds.size.height; } else { x = bounds.size.width; y = ( bounds.size.width * p_vout->fmt_in.i_visible_height * p_vout->fmt_in.i_sar_den) / ( p_vout->fmt_in.i_visible_width * p_vout->fmt_in.i_sar_num ); } glViewport( ( bounds.size.width - x ) / 2, ( bounds.size.height - y ) / 2, x, y ); [super reshape]; if( p_vout->p_sys->b_got_frame ) { /* Ask the opengl module to redraw */ vout_thread_t * p_parent; p_parent = (vout_thread_t *) p_vout->p_parent; Unlock( p_vout ); if( p_parent && p_parent->pf_display ) { p_parent->pf_display( p_parent, NULL ); } } else { glClear( GL_COLOR_BUFFER_BIT ); Unlock( p_vout ); }}- (void) update{ Lock( p_vout ); [super update]; Unlock( p_vout );}- (void) drawRect: (NSRect) rect{ Lock( p_vout ); [[p_vout->p_sys->o_glview openGLContext] flushBuffer]; [super drawRect:rect]; Unlock( p_vout );}@end/***************************************************************************** * embedded AGL context implementation *****************************************************************************/static void aglSetViewport( vout_thread_t *p_vout, Rect viewBounds, Rect clipBounds );static void aglReshape( vout_thread_t * p_vout );static OSStatus WindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);static int aglInit( vout_thread_t * p_vout ){ vlc_value_t val; Rect viewBounds; Rect clipBounds; var_Get( p_vout->p_libvlc, "drawable", &val ); p_vout->p_sys->agl_drawable = (AGLDrawable)val.i_int; aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys->agl_drawable); var_Get( p_vout->p_libvlc, "drawable-view-top", &val ); viewBounds.top = val.i_int; var_Get( p_vout->p_libvlc, "drawable-view-left", &val ); viewBounds.left = val.i_int; var_Get( p_vout->p_libvlc, "drawable-view-bottom", &val ); viewBounds.bottom = val.i_int; var_Get( p_vout->p_libvlc, "drawable-view-right", &val ); viewBounds.right = val.i_int; var_Get( p_vout->p_libvlc, "drawable-clip-top", &val ); clipBounds.top = val.i_int; var_Get( p_vout->p_libvlc, "drawable-clip-left", &val ); clipBounds.left = val.i_int; var_Get( p_vout->p_libvlc, "drawable-clip-bottom", &val ); clipBounds.bottom = val.i_int; var_Get( p_vout->p_libvlc, "drawable-clip-right", &val ); clipBounds.right = val.i_int; p_vout->p_sys->b_clipped_out = (clipBounds.top == clipBounds.bottom) || (clipBounds.left == clipBounds.right); if( ! p_vout->p_sys->b_clipped_out ) { aglLock(p_vout); aglSetViewport(p_vout, viewBounds, clipBounds); aglReshape(p_vout); aglUnlock(p_vout); } p_vout->p_sys->clipBounds = clipBounds; p_vout->p_sys->viewBounds = viewBounds; return VLC_SUCCESS;}static void aglEnd( vout_thread_t * p_vout ){ aglSetCurrentContext(NULL); if( p_vout->p_sys->theWindow ) DisposeWindow( p_vout->p_sys->theWindow );}static void aglReshape( vout_thread_t * p_vout ){ unsigned int x, y; unsigned int i_height = p_vout->p_sys->i_height; unsigned int i_width = p_vout->p_sys->i_width; vout_PlacePicture(p_vout, i_width, i_height, &x, &y, &i_width, &i_height); glViewport( p_vout->p_sys->i_offx + x, p_vout->p_sys->i_offy + y, i_width, i_height ); if( p_vout->p_sys->b_got_frame ) { /* Ask the opengl module to redraw */ vout_thread_t * p_parent; p_parent = (vout_thread_t *) p_vout->p_parent; if( p_parent && p_parent->pf_display ) { p_parent->pf_display( p_parent, NULL ); } } else { glClear( GL_COLOR_BUFFER_BIT ); }}/* private event class */enum{ kEventClassVLCPlugin = 'vlcp',};/* private event kinds */enum{ kEventVLCPluginShowFullscreen = 32768, kEventVLCPluginHideFullscreen,};static void sendEventToMainThread(EventTargetRef target, UInt32 class, UInt32 kind){ EventRef myEvent; if( noErr == CreateEvent(NULL, class, kind, 0, kEventAttributeNone, &myEvent) ) { if( noErr == SetEventParameter(myEvent, kEventParamPostTarget, typeEventTargetRef, sizeof(EventTargetRef), &target) ) { PostEventToQueue(GetMainEventQueue(), myEvent, kEventPriorityStandard); } ReleaseEvent(myEvent); }}static int aglManage( vout_thread_t * p_vout ){ if( p_vout->i_changes & VOUT_ASPECT_CHANGE ) { aglLock( p_vout ); aglReshape(p_vout); aglUnlock( p_vout ); p_vout->i_changes &= ~VOUT_ASPECT_CHANGE; } if( p_vout->i_changes & VOUT_CROP_CHANGE ) { aglLock( p_vout ); aglReshape(p_vout); aglUnlock( p_vout ); p_vout->i_changes &= ~VOUT_CROP_CHANGE; } if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE ) { aglSetDrawable(p_vout->p_sys->agl_ctx, NULL); aglLock( p_vout ); if( p_vout->b_fullscreen ) { /* Close the fullscreen window and resume normal drawing */ vlc_value_t val; Rect viewBounds; Rect clipBounds; var_Get( p_vout->p_libvlc, "drawable", &val ); p_vout->p_sys->agl_drawable = (AGLDrawable)val.i_int; aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys->agl_drawable); var_Get( p_vout->p_libvlc, "drawable-view-top", &val ); viewBounds.top = val.i_int; var_Get( p_vout->p_libvlc, "drawable-view-left", &val ); viewBounds.left = val.i_int; var_Get( p_vout->p_libvlc, "drawable-view-bottom", &val ); viewBounds.bottom = val.i_int; var_Get( p_vout->p_libvlc, "drawable-view-right", &val ); viewBounds.right = val.i_int; var_Get( p_vout->p_libvlc, "drawable-clip-top", &val ); clipBounds.top = val.i_int; var_Get( p_vout->p_libvlc, "drawable-clip-left", &val ); clipBounds.left = val.i_int; var_Get( p_vout->p_libvlc, "drawable-clip-bottom", &val ); clipBounds.bottom = val.i_int; var_Get( p_vout->p_libvlc, "drawable-clip-right", &val ); clipBounds.right = val.i_int; aglSetCurrentContext(p_vout->p_sys->agl_ctx); aglSetViewport(p_vout, viewBounds, clipBounds); /* Most Carbon APIs are not thread-safe, therefore delagate some GUI visibilty update to the main thread */ sendEventToMainThread(GetWindowEventTarget(p_vout->p_sys->theWindow), kEventClassVLCPlugin, kEventVLCPluginHideFullscreen); } else { Rect deviceRect; GDHandle deviceHdl = GetMainDevice(); deviceRect = (*deviceHdl)->gdRect; if( !p_vout->p_sys->theWindow ) { /* Create a window */ WindowAttributes windowAttrs; windowAttrs = kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute | kWindowLiveResizeAttribute | kWindowNoShadowAttribute; windowAttrs &= (~kWindowResizableAttribute); CreateNewWindow(kDocumentWindowClass, windowAttrs, &deviceRect, &p_vout->p_sys->theWindow); if( !p_vout->p_sys->winGroup ) { CreateWindowGroup(0, &p_vout->p_sys->winGroup); SetWindowGroup(p_vout->p_sys->theWindow, p_vout->p_sys->winGroup); SetWindowGroupParent( p_vout->p_sys->winGroup, GetWindowGroupOfClass(kDocumentWindowClass) ) ; } // Window title CFStringRef titleKey = CFSTR("Fullscreen VLC media plugin"); CFStringRef windowTitle = CFCopyLocalizedString(titleKey, NULL); SetWindowTitleWithCFString(p_vout->p_sys->theWindow, windowTitle); CFRelease(titleKey); CFRelease(windowTitle); //Install event handler static const EventTypeSpec win_events[] = { { kEventClassMouse, kEventMouseDown }, { kEventClassMouse, kEventMouseMoved }, { kEventClassMouse, kEventMouseUp }, { kEventClassWindow, kEventWindowClosed }, { kEventClassWindow, kEventWindowBoundsChanged }, { kEventClassCommand, kEventCommandProcess }, { kEventClassVLCPlugin, kEventVLCPluginShowFullscreen }, { kEventClassVLCPlugin, kEventVLCPluginHideFullscreen }, }; InstallWindowEventHandler (p_vout->p_sys->theWindow, NewEventHandlerUPP (WindowEventHandler), GetEventTypeCount(win_events), win_events, p_vout, NULL); } else { /* just in case device resolution changed */ SetWindowBounds(p_vout->p_sys->theWindow, kWindowContentRgn, &deviceRect); } glClear( GL_COLOR_BUFFER_BIT ); p_vout->p_sys->agl_drawable = (AGLDrawable)GetWindowPort(p_vout->p_sys->theWindow); aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys->agl_drawable); aglSetCurrentContext(p_vout->p_sys->agl_ctx); aglSetViewport(p_vout, deviceRect, deviceRect); //aglSetFullScreen(p_vout->p_sys->agl_ctx, device_width, device_height, 0, 0); /* Most Carbon APIs are not thread-safe, therefore delagate some GUI visibilty update to the main thread */ sendEventToMainThread(GetWindowEventTarget(p_vout->p_sys->theWindow), kEventClassVLCPlugin, kEventVLCPluginShowFullscreen); } aglReshape(p_vout); aglUnlock( p_vout ); p_vout->b_fullscreen = !p_vout->b_fullscreen; p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE; } return VLC_SUCCESS;}static int aglControl( vout_thread_t *p_vout, int i_query, va_list args ){ switch( i_query ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -