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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * interface.c: interface access for other threads
  3.  * This library provides basic functions for threads to interact with user
  4.  * interface, such as command line.
  5.  *****************************************************************************
  6.  * Copyright (C) 1998-2004 VideoLAN
  7.  * $Id: interface.c 8481 2004-08-21 11:47:04Z ipkiss $
  8.  *
  9.  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  24.  *****************************************************************************/
  25. /**
  26.  *   file
  27.  *   This file contains functions related to interface management
  28.  */
  29. /*****************************************************************************
  30.  * Preamble
  31.  *****************************************************************************/
  32. #include <stdlib.h>                                      /* free(), strtol() */
  33. #include <stdio.h>                                                   /* FILE */
  34. #include <string.h>                                            /* strerror() */
  35. #include <vlc/vlc.h>
  36. #include <vlc/input.h>
  37. #include "audio_output.h"
  38. #include "vlc_interface.h"
  39. #include "vlc_video.h"
  40. #include "video_output.h"
  41. #ifdef SYS_DARWIN
  42. #    include "Cocoa/Cocoa.h"
  43. #endif /* SYS_DARWIN */
  44. /*****************************************************************************
  45.  * Local prototypes
  46.  *****************************************************************************/
  47. static void Manager( intf_thread_t *p_intf );
  48. static void RunInterface( intf_thread_t *p_intf );
  49. static int SwitchIntfCallback( vlc_object_t *, char const *,
  50.                                vlc_value_t , vlc_value_t , void * );
  51. static int AddIntfCallback( vlc_object_t *, char const *,
  52.                             vlc_value_t , vlc_value_t , void * );
  53. #ifdef SYS_DARWIN
  54. /*****************************************************************************
  55.  * VLCApplication interface
  56.  *****************************************************************************/
  57. @interface VLCApplication : NSApplication
  58. {
  59. }
  60. @end
  61. #endif
  62. /*****************************************************************************
  63.  * intf_Create: prepare interface before main loop
  64.  *****************************************************************************
  65.  * This function opens output devices and creates specific interfaces. It sends
  66.  * its own error messages.
  67.  *****************************************************************************/
  68. /**
  69.  * Create the interface, and prepare it for main loop.
  70.  *
  71.  * param p_this the calling vlc_object_t
  72.  * param psz_module a prefered interface module
  73.  * return a pointer to the created interface thread, NULL on error
  74.  */
  75. intf_thread_t* __intf_Create( vlc_object_t *p_this, const char *psz_module )
  76. {
  77.     intf_thread_t * p_intf;
  78.     /* Allocate structure */
  79.     p_intf = vlc_object_create( p_this, VLC_OBJECT_INTF );
  80.     if( !p_intf )
  81.     {
  82.         msg_Err( p_this, "out of memory" );
  83.         return NULL;
  84.     }
  85.     p_intf->pf_request_window = NULL;
  86.     p_intf->pf_release_window = NULL;
  87.     p_intf->pf_control_window = NULL;
  88.     p_intf->b_play = VLC_FALSE;
  89.     /* Choose the best module */
  90.     p_intf->p_module = module_Need( p_intf, "interface", psz_module, 0 );
  91.     if( p_intf->p_module == NULL )
  92.     {
  93.         msg_Err( p_intf, "no suitable intf module" );
  94.         vlc_object_destroy( p_intf );
  95.         return NULL;
  96.     }
  97.     /* Initialize structure */
  98.     p_intf->b_menu        = VLC_FALSE;
  99.     p_intf->b_menu_change = VLC_FALSE;
  100.     /* Initialize mutexes */
  101.     vlc_mutex_init( p_intf, &p_intf->change_lock );
  102.     msg_Dbg( p_intf, "interface initialized" );
  103.     /* Attach interface to its parent object */
  104.     vlc_object_attach( p_intf, p_this );
  105.     return p_intf;
  106. }
  107. /*****************************************************************************
  108.  * intf_RunThread: launch the interface thread
  109.  *****************************************************************************
  110.  * This function either creates a new thread and runs the interface in it,
  111.  * or runs the interface in the current thread, depending on b_block.
  112.  *****************************************************************************/
  113. /**
  114.  * Run the interface thread.
  115.  *
  116.  * If b_block is not set, runs the interface in the thread, else,
  117.  * creates a new thread and runs the interface.
  118.  * param p_intf the interface thread
  119.  * return VLC_SUCCESS on success, an error number else
  120.  */
  121. int intf_RunThread( intf_thread_t *p_intf )
  122. {
  123. #ifdef SYS_DARWIN
  124.     NSAutoreleasePool * o_pool;
  125.     if( p_intf->b_block )
  126.     {
  127.         /* This is the primary intf */
  128.         /* Run a manager thread, launch the interface, kill the manager */
  129.         if( vlc_thread_create( p_intf, "manager", Manager,
  130.                                VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
  131.         {
  132.             msg_Err( p_intf, "cannot spawn manager thread" );
  133.             return VLC_EGENERIC;
  134.         }
  135.     }
  136.     if( p_intf->b_block && strncmp( p_intf->p_module->psz_shortname, "clivlc", 6) )
  137.     {
  138.         o_pool = [[NSAutoreleasePool alloc] init];
  139. [VLCApplication sharedApplication];
  140.     }
  141.     if( p_intf->b_block && ( !strncmp( p_intf->p_module->psz_shortname, "macosx" , 6 ) ||
  142.                              !strncmp( p_intf->p_vlc->psz_object_name, "clivlc", 6 ) ) )
  143.     {
  144.         /* VLC in normal primary interface mode */
  145.         RunInterface( p_intf );
  146.         p_intf->b_die = VLC_TRUE;
  147.     }
  148.     else
  149.     {
  150.         /* Run the interface in a separate thread */
  151.         if( vlc_thread_create( p_intf, "interface", RunInterface,
  152.                                VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
  153.         {
  154.             msg_Err( p_intf, "cannot spawn interface thread" );
  155.             return VLC_EGENERIC;
  156.         }
  157.         if( p_intf->b_block )
  158.         {
  159.             /* VLC in primary interface mode with a working macosx vout */
  160.             [NSApp run];
  161.             p_intf->b_die = VLC_TRUE;
  162.         }
  163.     }
  164. #else
  165.     if( p_intf->b_block )
  166.     {
  167.         /* Run a manager thread, launch the interface, kill the manager */
  168.         if( vlc_thread_create( p_intf, "manager", Manager,
  169.                                VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
  170.         {
  171.             msg_Err( p_intf, "cannot spawn manager thread" );
  172.             return VLC_EGENERIC;
  173.         }
  174.         RunInterface( p_intf );
  175.         p_intf->b_die = VLC_TRUE;
  176.         /* Do not join the thread... intf_StopThread will do it for us */
  177.     }
  178.     else
  179.     {
  180.         /* Run the interface in a separate thread */
  181.         if( vlc_thread_create( p_intf, "interface", RunInterface,
  182.                                VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
  183.         {
  184.             msg_Err( p_intf, "cannot spawn interface thread" );
  185.             return VLC_EGENERIC;
  186.         }
  187.     }
  188. #endif
  189.     return VLC_SUCCESS;
  190. }
  191. /**
  192.  * Stops the interface thread
  193.  *
  194.  * This function asks the interface thread to stop
  195.  * param p_intf the interface thread
  196.  * return nothing
  197.  */
  198. void intf_StopThread( intf_thread_t *p_intf )
  199. {
  200.     /* Tell the interface to die */
  201.     if( !p_intf->b_block )
  202.     {
  203.         p_intf->b_die = VLC_TRUE;
  204.     }
  205.     /* Wait for the thread to exit */
  206.     vlc_thread_join( p_intf );
  207. }
  208. /**
  209.  * brief Destroy the interface after the main loop endeed.
  210.  *
  211.  * Destroys interfaces and closes output devices
  212.  * param p_intf the interface thread
  213.  * return nothing
  214.  */
  215. void intf_Destroy( intf_thread_t *p_intf )
  216. {
  217.     /* Unlock module if present (a switch may have failed) */
  218.     if( p_intf->p_module )
  219.     {
  220.         module_Unneed( p_intf, p_intf->p_module );
  221.     }
  222.     vlc_mutex_destroy( &p_intf->change_lock );
  223.     /* Free structure */
  224.     vlc_object_destroy( p_intf );
  225. }
  226. /* Following functions are local */
  227. /*****************************************************************************
  228.  * Manager: helper thread for blocking interfaces
  229.  *****************************************************************************
  230.  * If the interface is launched in the main thread, it will not listen to
  231.  * p_vlc->b_die events because it is only supposed to listen to p_intf->b_die.
  232.  * This thread takes care of the matter.
  233.  *****************************************************************************/
  234. /**
  235.  * brief Helper thread for blocking interfaces.
  236.  * ingroup vlc_interface
  237.  *
  238.  * This is a local function
  239.  * If the interface is launched in the main thread, it will not listen to
  240.  * p_vlc->b_die events because it is only supposed to listen to p_intf->b_die.
  241.  * This thread takes care of the matter.
  242.  * see intf_RunThread
  243.  * param p_intf an interface thread
  244.  * return nothing
  245.  */
  246. static void Manager( intf_thread_t *p_intf )
  247. {
  248.     while( !p_intf->b_die )
  249.     {
  250.         msleep( INTF_IDLE_SLEEP );
  251.         if( p_intf->p_vlc->b_die )
  252.         {
  253.             p_intf->b_die = VLC_TRUE;
  254. #ifdef SYS_DARWIN
  255.     if( strncmp( p_intf->p_vlc->psz_object_name, "clivlc", 6 ) )
  256.     {
  257.         [NSApp stop: NULL];
  258.     }
  259. #endif
  260.             return;
  261.         }
  262.     }
  263. }
  264. /*****************************************************************************
  265.  * RunInterface: setups necessary data and give control to the interface
  266.  *****************************************************************************/
  267. static void RunInterface( intf_thread_t *p_intf )
  268. {
  269.     static char *ppsz_interfaces[] =
  270.     {
  271.         "skins2", "Skins 2",
  272.         "wxwindows", "wxWindows",
  273.         NULL, NULL
  274.     };
  275.     char **ppsz_parser;
  276.     vlc_list_t *p_list;
  277.     int i;
  278.     vlc_value_t val, text;
  279.     char *psz_intf;
  280.     /* Variable used for interface switching */
  281.     p_intf->psz_switch_intf = NULL;
  282.     var_Create( p_intf, "intf-switch", VLC_VAR_STRING |
  283.                 VLC_VAR_HASCHOICE | VLC_VAR_ISCOMMAND );
  284.     text.psz_string = _("Switch interface");
  285.     var_Change( p_intf, "intf-switch", VLC_VAR_SETTEXT, &text, NULL );
  286.     /* Only fill the list with available modules */
  287.     p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
  288.     for( ppsz_parser = ppsz_interfaces; *ppsz_parser; ppsz_parser += 2 )
  289.     {
  290.         for( i = 0; i < p_list->i_count; i++ )
  291.         {
  292.             module_t *p_module = (module_t *)p_list->p_values[i].p_object;
  293.             if( !strcmp( p_module->psz_object_name, ppsz_parser[0] ) )
  294.             {
  295.                 val.psz_string = ppsz_parser[0];
  296.                 text.psz_string = ppsz_parser[1];
  297.                 var_Change( p_intf, "intf-switch", VLC_VAR_ADDCHOICE,
  298.                             &val, &text );
  299.                 break;
  300.             }
  301.         }
  302.     }
  303.     vlc_list_release( p_list );
  304.     var_AddCallback( p_intf, "intf-switch", SwitchIntfCallback, NULL );
  305.     /* Variable used for interface spawning */
  306.     var_Create( p_intf, "intf-add", VLC_VAR_STRING |
  307.                 VLC_VAR_HASCHOICE | VLC_VAR_ISCOMMAND );
  308.     text.psz_string = _("Add Interface");
  309.     var_Change( p_intf, "intf-add", VLC_VAR_SETTEXT, &text, NULL );
  310.     val.psz_string = "rc"; text.psz_string = "Console";
  311.     var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
  312.     val.psz_string = "telnet"; text.psz_string = "Telnet Interface";
  313.     var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
  314.     val.psz_string = "http"; text.psz_string = "Web Interface";
  315.     var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
  316.     val.psz_string = "logger"; text.psz_string = "Debug logging";
  317.     var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
  318.     val.psz_string = "sap"; text.psz_string = "SAP Playlist";
  319.     var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
  320.     val.psz_string = "gestures"; text.psz_string = "Mouse Gestures";
  321.     var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
  322.     var_AddCallback( p_intf, "intf-add", AddIntfCallback, NULL );
  323.     do
  324.     {
  325.         /* Give control to the interface */
  326.         p_intf->pf_run( p_intf );
  327.         /* Reset play on start status */
  328.         p_intf->b_play = VLC_FALSE;
  329.         if( !p_intf->psz_switch_intf )
  330.         {
  331.             break;
  332.         }
  333.         /* Make sure the old interface is completely uninitialized */
  334.         module_Unneed( p_intf, p_intf->p_module );
  335.         /* Provide ability to switch the main interface on the fly */
  336.         psz_intf = p_intf->psz_switch_intf;
  337.         p_intf->psz_switch_intf = NULL;
  338.         vlc_mutex_lock( &p_intf->object_lock );
  339.         p_intf->b_die = VLC_FALSE;
  340.         p_intf->b_dead = VLC_FALSE;
  341.         vlc_mutex_unlock( &p_intf->object_lock );
  342.         p_intf->p_module = module_Need( p_intf, "interface", psz_intf, 0 );
  343.         free( psz_intf );
  344.     }
  345.     while( p_intf->p_module );
  346. }
  347. static int SwitchIntfCallback( vlc_object_t *p_this, char const *psz_cmd,
  348.                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
  349. {
  350.     intf_thread_t *p_intf = (intf_thread_t *)p_this;
  351.     p_intf->psz_switch_intf =
  352.         malloc( strlen(newval.psz_string) + sizeof(",none") );
  353.     sprintf( p_intf->psz_switch_intf, "%s,none", newval.psz_string );
  354.     p_intf->b_die = VLC_TRUE;
  355.     return VLC_SUCCESS;
  356. }
  357. static int AddIntfCallback( vlc_object_t *p_this, char const *psz_cmd,
  358.                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
  359. {
  360.     intf_thread_t *p_intf;
  361.     char *psz_intf = malloc( strlen(newval.psz_string) + sizeof(",none") );
  362.     /* Try to create the interface */
  363.     sprintf( psz_intf, "%s,none", newval.psz_string );
  364.     p_intf = intf_Create( p_this->p_vlc, psz_intf );
  365.     free( psz_intf );
  366.     if( p_intf == NULL )
  367.     {
  368.         msg_Err( p_this, "interface "%s" initialization failed",
  369.                  newval.psz_string );
  370.         return VLC_EGENERIC;
  371.     }
  372.     /* Try to run the interface */
  373.     p_intf->b_block = VLC_FALSE;
  374.     if( intf_RunThread( p_intf ) != VLC_SUCCESS )
  375.     {
  376.         vlc_object_detach( p_intf );
  377.         intf_Destroy( p_intf );
  378.         return VLC_EGENERIC;
  379.     }
  380.     return VLC_SUCCESS;
  381. }
  382. #ifdef SYS_DARWIN
  383. /*****************************************************************************
  384.  * VLCApplication implementation 
  385.  *****************************************************************************/
  386. @implementation VLCApplication 
  387. - (void)stop: (id)sender
  388. {
  389.     NSEvent *o_event;
  390.     NSAutoreleasePool *o_pool;
  391.     [super stop:sender];
  392.     o_pool = [[NSAutoreleasePool alloc] init];
  393.     /* send a dummy event to break out of the event loop */
  394.     o_event = [NSEvent mouseEventWithType: NSLeftMouseDown
  395.                 location: NSMakePoint( 1, 1 ) modifierFlags: 0
  396.                 timestamp: 1 windowNumber: [[NSApp mainWindow] windowNumber]
  397.                 context: [NSGraphicsContext currentContext] eventNumber: 1
  398.                 clickCount: 1 pressure: 0.0];
  399.     [NSApp postEvent: o_event atStart: YES];
  400.     [o_pool release];
  401. }
  402. - (void)terminate: (id)sender
  403. {
  404.     if( [NSApp isRunning] )
  405.         [NSApp stop:sender];
  406.     [super terminate: sender];
  407. }
  408. @end
  409. #endif