hal.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:11k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * hal.c :  HAL interface module
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 the VideoLAN team
  5.  * Copyright © 2006-2007 Rafaël Carré
  6.  * $Id: a8241bd85a5941ac9e23680e3673e42733b819f5 $
  7.  *
  8.  * Authors: Clément Stenac <zorglub@videolan.org>
  9.  *          Rafaël Carré <funman at videolanorg>
  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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  24.  *****************************************************************************/
  25. #ifdef HAVE_CONFIG_H
  26. # include "config.h"
  27. #endif
  28. #include <vlc_common.h>
  29. #include <vlc_plugin.h>
  30. #include <vlc_playlist.h>
  31. #include <vlc_services_discovery.h>
  32. #include <vlc_network.h>
  33. #include <errno.h>                                                 /* ENOMEM */
  34. #ifdef HAVE_UNISTD_H
  35. #    include <unistd.h>
  36. #endif
  37. #ifdef HAVE_SYS_TIME_H
  38. #    include <sys/time.h>
  39. #endif
  40. #include <hal/libhal.h>
  41. #define MAX_LINE_LENGTH 256
  42. /*****************************************************************************
  43.  * Local prototypes
  44.  *****************************************************************************/
  45. /* store relation between item id and udi for ejection */
  46. struct udi_input_id_t
  47. {
  48.     char            *psz_udi;
  49.     input_item_t    *p_item;
  50. };
  51. struct services_discovery_sys_t
  52. {
  53.     vlc_thread_t            thread;
  54.     LibHalContext           *p_ctx;
  55.     DBusConnection          *p_connection;
  56.     int                     i_devices_number;
  57.     struct udi_input_id_t   **pp_devices;
  58. };
  59. static void *Run ( void * );
  60. static int  Open ( vlc_object_t * );
  61. static void Close( vlc_object_t * );
  62. /* HAL callbacks */
  63. void DeviceAdded( LibHalContext *p_ctx, const char *psz_udi );
  64. void DeviceRemoved( LibHalContext *p_ctx, const char *psz_udi );
  65. /* to retrieve p_sd in HAL callbacks */
  66. services_discovery_t        *p_sd_global;
  67. /*****************************************************************************
  68.  * Module descriptor
  69.  *****************************************************************************/
  70. vlc_module_begin ()
  71.     set_description( N_("HAL devices detection") )
  72.     set_category( CAT_PLAYLIST )
  73.     set_subcategory( SUBCAT_PLAYLIST_SD )
  74.     set_capability( "services_discovery", 0 )
  75.     set_callbacks( Open, Close )
  76. vlc_module_end ()
  77. /*****************************************************************************
  78.  * Open: initialize and create stuff
  79.  *****************************************************************************/
  80. static int Open( vlc_object_t *p_this )
  81. {
  82.     services_discovery_t *p_sd = ( services_discovery_t* )p_this;
  83.     services_discovery_sys_t *p_sys  = malloc(
  84.                                     sizeof( services_discovery_sys_t ) );
  85.     if( !p_sys )
  86.         return VLC_ENOMEM;
  87.     DBusError           dbus_error;
  88.     DBusConnection      *p_connection = NULL;
  89.     p_sd_global = p_sd;
  90.     p_sys->i_devices_number = 0;
  91.     p_sys->pp_devices = NULL;
  92.     p_sd->p_sys  = p_sys;
  93.     dbus_error_init( &dbus_error );
  94.     p_sys->p_ctx = libhal_ctx_new();
  95.     if( !p_sys->p_ctx )
  96.     {
  97.         msg_Err( p_sd, "unable to create HAL context") ;
  98.         free( p_sys );
  99.         return VLC_EGENERIC;
  100.     }
  101.     p_connection = dbus_bus_get( DBUS_BUS_SYSTEM, &dbus_error );
  102.     if( dbus_error_is_set( &dbus_error ) )
  103.     {
  104.         msg_Err( p_sd, "unable to connect to DBUS: %s", dbus_error.message );
  105.         goto error;
  106.     }
  107.     libhal_ctx_set_dbus_connection( p_sys->p_ctx, p_connection );
  108.     p_sys->p_connection = p_connection;
  109.     if( !libhal_ctx_init( p_sys->p_ctx, &dbus_error ) )
  110.     {
  111.         msg_Err( p_sd, "hal not available : %s", dbus_error.message );
  112.         goto error;
  113.     }
  114.     if( !libhal_ctx_set_device_added( p_sys->p_ctx, DeviceAdded ) ||
  115.             !libhal_ctx_set_device_removed( p_sys->p_ctx, DeviceRemoved ) )
  116.     {
  117.         msg_Err( p_sd, "unable to add callback" );
  118.         goto error;
  119.     }
  120.     if( vlc_clone( &p_sys->thread, Run, p_this, VLC_THREAD_PRIORITY_LOW ) )
  121.         goto error;
  122.     return VLC_SUCCESS;
  123. error:
  124.     if( p_connection )
  125.         dbus_connection_unref( p_connection );
  126.     dbus_error_free( &dbus_error );
  127.     libhal_ctx_free( p_sys->p_ctx );
  128.     free( p_sys );
  129.     return VLC_EGENERIC;
  130. }
  131. /*****************************************************************************
  132.  * Close:
  133.  *****************************************************************************/
  134. static void Close( vlc_object_t *p_this )
  135. {
  136.     services_discovery_t *p_sd = ( services_discovery_t* )p_this;
  137.     services_discovery_sys_t *p_sys  = p_sd->p_sys;
  138.     /*vlc_cancel( p_sys->thread );*/
  139.     vlc_object_kill( p_sd );
  140.     vlc_join( p_sys->thread, NULL );
  141.     dbus_connection_unref( p_sys->p_connection );
  142.     struct udi_input_id_t *p_udi_entry;
  143.     while( p_sys->i_devices_number > 0 )
  144.     {
  145.         p_udi_entry = p_sys->pp_devices[0];
  146.         free( p_udi_entry->psz_udi );
  147.         TAB_REMOVE( p_sys->i_devices_number, p_sys->pp_devices,
  148.                 p_sys->pp_devices[0] );
  149.         free( p_udi_entry );
  150.     }
  151.     p_sys->pp_devices = NULL;
  152.     libhal_ctx_free( p_sys->p_ctx );
  153.     free( p_sys );
  154. }
  155. static void AddItem( services_discovery_t *p_sd, input_item_t * p_input,
  156.                     const char* psz_device )
  157. {
  158.     services_discovery_sys_t *p_sys  = p_sd->p_sys;
  159.     services_discovery_AddItem( p_sd, p_input, NULL /* no category */ );
  160.     struct udi_input_id_t *p_udi_entry;
  161.     p_udi_entry = malloc( sizeof( struct udi_input_id_t ) );
  162.     if( !p_udi_entry )
  163.         return;
  164.     p_udi_entry->psz_udi = strdup( psz_device );
  165.     if( !p_udi_entry->psz_udi )
  166.     {
  167.         free( p_udi_entry );
  168.         return;
  169.     }
  170.     vlc_gc_incref( p_input );
  171.     p_udi_entry->p_item = p_input;
  172.     TAB_APPEND( p_sys->i_devices_number, p_sys->pp_devices, p_udi_entry );
  173. }
  174. static void AddDvd( services_discovery_t *p_sd, const char *psz_device )
  175. {
  176.     char *psz_name;
  177.     char *psz_uri;
  178.     char *psz_blockdevice;
  179.     input_item_t        *p_input;
  180.     psz_name = libhal_device_get_property_string( p_sd->p_sys->p_ctx,
  181.                                         psz_device, "volume.label", NULL );
  182.     psz_blockdevice = libhal_device_get_property_string( p_sd->p_sys->p_ctx,
  183.                                         psz_device, "block.device", NULL );
  184.     if( asprintf( &psz_uri, "dvd://%s", psz_blockdevice ) == -1 )
  185.         return;
  186.     /* Create the playlist item here */
  187.     p_input = input_item_New( p_sd, psz_uri, psz_name );
  188.     free( psz_uri );
  189.     if( !p_input )
  190.     {
  191.         return;
  192.     }
  193.     AddItem( p_sd, p_input, psz_device );
  194.     vlc_gc_decref( p_input );
  195. }
  196. static void DelItem( services_discovery_t *p_sd, const char* psz_udi )
  197. {
  198.     services_discovery_sys_t    *p_sys  = p_sd->p_sys;
  199.     int i;
  200.     for( i = 0; i < p_sys->i_devices_number; i++ )
  201.     { /*  looks for a matching udi */
  202.         if( strcmp( psz_udi, p_sys->pp_devices[i]->psz_udi ) == 0 )
  203.         { /* delete the corresponding item */    
  204.             services_discovery_RemoveItem( p_sd, p_sys->pp_devices[i]->p_item );
  205.             vlc_gc_decref( p_sys->pp_devices[i]->p_item );
  206.             free( p_sys->pp_devices[i]->psz_udi );
  207.             TAB_REMOVE( p_sys->i_devices_number, p_sys->pp_devices,
  208.                     p_sys->pp_devices[i] );
  209.         }
  210.     }
  211. }
  212. static void AddCdda( services_discovery_t *p_sd, const char *psz_device )
  213. {
  214.     char *psz_uri;
  215.     char *psz_blockdevice;
  216.     input_item_t     *p_input;
  217.     psz_blockdevice = libhal_device_get_property_string( p_sd->p_sys->p_ctx,
  218.                                             psz_device, "block.device", NULL );
  219.     if( asprintf( &psz_uri, "cdda://%s", psz_blockdevice ) == -1 )
  220.         return;
  221.     /* Create the item here */
  222.     p_input = input_item_New( p_sd, psz_uri, "Audio CD" );
  223.     free( psz_uri );
  224.     if( !p_input )
  225.         return;
  226.     AddItem( p_sd, p_input, psz_device );
  227.     vlc_gc_decref( p_input );
  228. }
  229. static void ParseDevice( services_discovery_t *p_sd, const char *psz_device )
  230. {
  231.     char *psz_disc_type;
  232.     services_discovery_sys_t    *p_sys  = p_sd->p_sys;
  233.     if( !libhal_device_property_exists( p_sys->p_ctx, psz_device,
  234.                                        "volume.disc.type", NULL ) )
  235.         return;
  236.     psz_disc_type = libhal_device_get_property_string( p_sys->p_ctx,
  237.                                                     psz_device,
  238.                                                     "volume.disc.type",
  239.                                                     NULL );
  240.     if( !strncmp( psz_disc_type, "dvd_r", 5 ) )
  241.     {
  242.         if (libhal_device_get_property_bool( p_sys->p_ctx, psz_device,
  243.                                      "volume.disc.is_videodvd", NULL ) )
  244.         AddDvd( p_sd, psz_device );
  245.     }
  246.     else if( !strncmp( psz_disc_type, "cd_r", 4 ) )
  247.     {
  248.         if( libhal_device_get_property_bool( p_sys->p_ctx, psz_device,
  249.                                      "volume.disc.has_audio" , NULL ) )
  250.             AddCdda( p_sd, psz_device );
  251.     }
  252. }
  253. /*****************************************************************************
  254.  * Run: main HAL thread
  255.  *****************************************************************************/
  256. static void *Run( void *data )
  257. {
  258.     services_discovery_t     *p_sd  = data;
  259.     services_discovery_sys_t *p_sys = p_sd->p_sys;
  260.     char **devices;
  261.     int i, i_devices;
  262.     int canc = vlc_savecancel();
  263.     /* parse existing devices first */
  264.     if( ( devices = libhal_get_all_devices( p_sys->p_ctx, &i_devices, NULL ) ) )
  265.     {
  266.         for( i = 0; i < i_devices; i++ )
  267.         {
  268.             ParseDevice( p_sd, devices[ i ] );
  269.             libhal_free_string( devices[ i ] );
  270.         }
  271.         free( devices );
  272.     }
  273.     /* FIXME: Totally lame. There are DBus watch functions to do this properly.
  274.      * -- Courmisch, 28/08/2008 */
  275.     while( vlc_object_alive (p_sd) )
  276.     {
  277.         /* look for events on the bus, blocking 1 second */
  278.         dbus_connection_read_write_dispatch( p_sys->p_connection, 1000 );
  279.         /* HAL 0.5.8.1 can use libhal_ctx_get_dbus_connection(p_sys->p_ctx) */
  280.     }
  281.     vlc_restorecancel (canc);
  282.     return NULL;
  283. }
  284. void DeviceAdded( LibHalContext *p_ctx, const char *psz_udi )
  285. {
  286.     VLC_UNUSED(p_ctx);
  287.     ParseDevice( p_sd_global, psz_udi );
  288. }
  289. void DeviceRemoved( LibHalContext *p_ctx, const char *psz_udi )
  290. {
  291.     VLC_UNUSED(p_ctx);
  292.     DelItem( p_sd_global, psz_udi );
  293. }