voutgl.m
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:11k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * vout.m: MacOS X video output module
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2003 VideoLAN
  5.  * $Id: vout.m 8351 2004-08-02 13:06:38Z hartman $
  6.  *
  7.  * Authors: Colin Delacroix <colin@zoy.org>
  8.  *          Florian G. Pflug <fgp@phlo.org>
  9.  *          Jon Lech Johansen <jon-vl@nanocrew.net>
  10.  *          Derk-Jan Hartman <hartman at videolan dot org>
  11.  *          Eric Petit <titer@m0k.org>
  12.  *
  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.
  17.  * 
  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.
  22.  *
  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.  *****************************************************************************/
  27. /*****************************************************************************
  28.  * Preamble
  29.  *****************************************************************************/
  30. #include <errno.h>                                                 /* ENOMEM */
  31. #include <stdlib.h>                                                /* free() */
  32. #include <string.h>                                            /* strerror() */
  33. #include <vlc_keys.h>
  34. #include "intf.h"
  35. #include "vout.h"
  36. #include <OpenGL/OpenGL.h>
  37. #include <OpenGL/gl.h>
  38. /*****************************************************************************
  39.  * VLCView interface
  40.  *****************************************************************************/
  41. @interface VLCGLView : NSOpenGLView
  42. {
  43.     vout_thread_t * p_vout;
  44. }
  45. - (id)initWithFrame: (NSRect) frame vout: (vout_thread_t*) p_vout;
  46. @end
  47. struct vout_sys_t
  48. {
  49.     NSAutoreleasePool *o_pool;
  50.     VLCWindow * o_window;
  51.     VLCGLView * o_glview;
  52.     vlc_bool_t  b_saved_frame;
  53.     NSRect      s_frame;
  54. };
  55. /*****************************************************************************
  56.  * Local prototypes
  57.  *****************************************************************************/
  58. static int  Init   ( vout_thread_t * p_vout );
  59. static void End    ( vout_thread_t * p_vout );
  60. static int  Manage ( vout_thread_t * p_vout );
  61. static int  Control( vout_thread_t *, int, va_list );
  62. static void Swap   ( vout_thread_t * p_vout );
  63. int E_(OpenVideoGL)  ( vlc_object_t * p_this )
  64. {
  65.     vout_thread_t * p_vout = (vout_thread_t *) p_this;
  66.     int i_timeout;
  67.     vlc_value_t val;
  68. /* OpenGL interface disabled until
  69.  * - the video on top var is properly working
  70.  * - the escape key is working in fullscreen
  71.  * - the green line is gone
  72.  * - other problems?????
  73.  */
  74. return( 1 );
  75.     if( !CGDisplayUsesOpenGLAcceleration( kCGDirectMainDisplay ) )
  76.     {
  77.         msg_Warn( p_vout, "no hardware acceleration" );
  78.         return( 1 );
  79.     }
  80.     msg_Dbg( p_vout, "display is Quartz Extreme accelerated" );
  81.     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
  82.     if( p_vout->p_sys == NULL )
  83.     {
  84.         msg_Err( p_vout, "out of memory" );
  85.         return( 1 );
  86.     }
  87.     memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
  88.     /* Wait for a MacOS X interface to appear. Timeout is 2 seconds. */
  89.     for( i_timeout = 20 ; i_timeout-- ; )
  90.     {
  91.         if( NSApp == NULL )     
  92.         {
  93.             msleep( INTF_IDLE_SLEEP );
  94.         }
  95.     }
  96.     if( NSApp == NULL )
  97.     {
  98.         /* No MacOS X intf, unable to communicate with MT */
  99.         msg_Err( p_vout, "no MacOS X interface present" );
  100.         return VLC_EGENERIC;
  101.     }
  102.     p_vout->pf_init   = Init;
  103.     p_vout->pf_end    = End;
  104.     p_vout->pf_manage = Manage;
  105.     p_vout->pf_control= Control;
  106.     p_vout->pf_swap   = Swap;
  107.     p_vout->p_sys->o_pool = [[NSAutoreleasePool alloc] init];
  108.     var_Create( p_vout, "macosx-vdev", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  109.     var_Create( p_vout, "macosx-fill", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  110.     var_Create( p_vout, "macosx-stretch", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  111.     var_Create( p_vout, "macosx-opaqueness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
  112.     /* Setup the menuitem for the multiple displays. Read the vlc preference (macosx-vdev) for the primary display */
  113.     NSArray * o_screens = [NSScreen screens];
  114.     if( [o_screens count] > 0 && var_Type( p_vout, "video-device" ) == 0 )
  115.     {
  116.         int i = 1;
  117.         vlc_value_t val2, text;
  118.         NSScreen * o_screen;
  119.         var_Get( p_vout, "macosx-vdev", &val );
  120.         var_Create( p_vout, "video-device", VLC_VAR_INTEGER |
  121.                                             VLC_VAR_HASCHOICE ); 
  122.         text.psz_string = _("Video device");
  123.         var_Change( p_vout, "video-device", VLC_VAR_SETTEXT, &text, NULL );
  124.         
  125.         NSEnumerator * o_enumerator = [o_screens objectEnumerator];
  126.         while( (o_screen = [o_enumerator nextObject]) != NULL )
  127.         {
  128.             char psz_temp[255];
  129.             NSRect s_rect = [o_screen frame];
  130.             snprintf( psz_temp, sizeof(psz_temp)/sizeof(psz_temp[0])-1, 
  131.                       "%s %d (%dx%d)", _("Screen"), i,
  132.                       (int)s_rect.size.width, (int)s_rect.size.height ); 
  133.             text.psz_string = psz_temp;
  134.             val2.i_int = i;
  135.             var_Change( p_vout, "video-device",
  136.                         VLC_VAR_ADDCHOICE, &val2, &text );
  137.             if( ( i - 1 ) == val.i_int )
  138.             {
  139.                 var_Set( p_vout, "video-device", val2 );
  140.             }
  141.             i++;
  142.         }
  143.         var_AddCallback( p_vout, "video-device", vout_VarCallback,
  144.                          NULL );
  145.         val2.b_bool = VLC_TRUE;
  146.         var_Set( p_vout, "intf-change", val2 );
  147.     }
  148.     /* Spawn window */
  149.     p_vout->p_sys->o_window = [[VLCWindow alloc] initWithVout: p_vout
  150.                                                  frame: nil];
  151.     
  152.     /* Add OpenGL view */
  153. #define o_glview p_vout->p_sys->o_glview
  154.     o_glview = [[VLCGLView alloc] initWithFrame:
  155.                 [p_vout->p_sys->o_window frame] vout: p_vout];
  156.     [p_vout->p_sys->o_window setContentView: o_glview];
  157.     [o_glview autorelease];
  158. #undef o_glview
  159.     return VLC_SUCCESS;
  160. }
  161. int E_(CloseVideoGL) ( vlc_object_t * p_this )
  162. {
  163.     vout_thread_t * p_vout = (vout_thread_t *) p_this;
  164.     NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; 
  165.     [p_vout->p_sys->o_window close];
  166.     [o_pool release];
  167.     return VLC_SUCCESS;
  168. }
  169. static int Init( vout_thread_t * p_vout )
  170. {
  171.     [[p_vout->p_sys->o_glview openGLContext] makeCurrentContext];
  172.     return VLC_SUCCESS;
  173. }
  174. static void End( vout_thread_t * p_vout )
  175. {
  176.     [[p_vout->p_sys->o_glview openGLContext] makeCurrentContext];
  177. }
  178. static int Manage( vout_thread_t * p_vout )
  179. {
  180.     if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
  181.     {
  182.         NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
  183.         
  184.         if( !p_vout->b_fullscreen )
  185.         {
  186.             /* Save window size and position */
  187.             p_vout->p_sys->s_frame.size =
  188.                 [[p_vout->p_sys->o_window contentView] frame].size;
  189.             p_vout->p_sys->s_frame.origin =
  190.                 [p_vout->p_sys->o_window frame].origin;
  191.             p_vout->p_sys->b_saved_frame = VLC_TRUE;
  192.         }
  193.         [p_vout->p_sys->o_window close];
  194.         p_vout->b_fullscreen = !p_vout->b_fullscreen;
  195.         if( p_vout->p_sys->b_saved_frame )
  196.         {
  197.             p_vout->p_sys->o_window = [[VLCWindow alloc]
  198.                 initWithVout: p_vout frame: &p_vout->p_sys->s_frame];
  199.         }
  200.         else
  201.         {
  202.             p_vout->p_sys->o_window = [[VLCWindow alloc]
  203.                 initWithVout: p_vout frame: nil];
  204.         }
  205. #define o_glview p_vout->p_sys->o_glview
  206.         o_glview = [[VLCGLView alloc] initWithFrame: [p_vout->p_sys->o_window frame] vout: p_vout];
  207.         [p_vout->p_sys->o_window setContentView: o_glview];
  208.         [o_glview autorelease];
  209.         [[o_glview openGLContext] makeCurrentContext];
  210. #undef o_glview
  211.         [o_pool release];
  212.         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
  213.     }
  214.     [p_vout->p_sys->o_window manage];
  215.     return VLC_SUCCESS;
  216. }
  217. /*****************************************************************************
  218.  * Control: control facility for the vout
  219.  *****************************************************************************/
  220. static int Control( vout_thread_t *p_vout, int i_query, va_list args )
  221. {
  222.     vlc_bool_t b_arg;
  223.     switch( i_query )
  224.     {
  225.         case VOUT_SET_STAY_ON_TOP:
  226.             b_arg = va_arg( args, vlc_bool_t );
  227.             [p_vout->p_sys->o_window setOnTop: b_arg];
  228.             return VLC_SUCCESS;
  229.         case VOUT_CLOSE:
  230.         case VOUT_REPARENT:
  231.         default:
  232.             return vout_vaControlDefault( p_vout, i_query, args );
  233.     }
  234. }
  235. static void Swap( vout_thread_t * p_vout )
  236. {
  237.     [[p_vout->p_sys->o_glview openGLContext] makeCurrentContext];
  238.     if( [p_vout->p_sys->o_glview lockFocusIfCanDraw] )
  239.     {
  240.         glFlush();
  241.         [p_vout->p_sys->o_glview unlockFocus];
  242.     }
  243. }
  244. /*****************************************************************************
  245.  * VLCGLView implementation
  246.  *****************************************************************************/
  247. @implementation VLCGLView
  248. - (id) initWithFrame: (NSRect) frame vout: (vout_thread_t*) _p_vout
  249. {
  250.     p_vout = _p_vout;
  251.     
  252.     NSOpenGLPixelFormatAttribute attribs[] =
  253.     {
  254.         NSOpenGLPFAAccelerated,
  255.         NSOpenGLPFANoRecovery,
  256.         NSOpenGLPFAColorSize, 24,
  257.         NSOpenGLPFAAlphaSize, 8,
  258.         NSOpenGLPFADepthSize, 24,
  259.         NSOpenGLPFAWindow,
  260.         0
  261.     };
  262.     NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc]
  263.         initWithAttributes: attribs];
  264.     if( !fmt )
  265.     {
  266.         msg_Warn( p_vout, "Cannot create NSOpenGLPixelFormat" );
  267.         return nil;
  268.     }
  269.     self = [super initWithFrame:frame pixelFormat: fmt];
  270.     [fmt release];
  271.     [[self openGLContext] makeCurrentContext];
  272.     [[self openGLContext] update];
  273.     /* Swap buffers only during the vertical retrace of the monitor.
  274.        http://developer.apple.com/documentation/GraphicsImaging/
  275.        Conceptual/OpenGL/chap5/chapter_5_section_44.html */
  276.     long params[] = { 1 };
  277.     CGLSetParameter( CGLGetCurrentContext(), kCGLCPSwapInterval,
  278.                      params );
  279.     return self;
  280. }
  281. - (void)reshape
  282. {
  283.     int x, y;
  284.     NSRect bounds = [self bounds];
  285.     [[self openGLContext] makeCurrentContext];
  286.     if( bounds.size.height * p_vout->render.i_aspect <
  287.             bounds.size.width * VOUT_ASPECT_FACTOR )
  288.     {
  289.         x = bounds.size.height * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
  290.         y = bounds.size.height;
  291.     }
  292.     else
  293.     {
  294.         x = bounds.size.width;
  295.         y = bounds.size.width * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect;
  296.     }
  297.     glViewport( ( bounds.size.width - x ) / 2,
  298.                 ( bounds.size.height - y ) / 2, x, y );
  299.     glClear( GL_COLOR_BUFFER_BIT );
  300. }
  301. - (void) drawRect: (NSRect) rect
  302. {
  303.     [[self openGLContext] makeCurrentContext];
  304.     glFlush();
  305. }
  306. @end