Changeset 16093d941c54bf45a447e1157c96eb0c61813687

Show
Ignore:
Timestamp:
15/11/06 22:44:18 (2 years ago)
Author:
Rafaël Carré <funman@videolan.org>
git-committer:
Rafaël Carré <funman@videolan.org> 1163627058 +0000
git-parent:

[772fa346a8229fcb4ed6aa7124783032964294bb]

git-author:
Rafaël Carré <funman@videolan.org> 1163627058 +0000
Message:

Manages hot ejection of devices
Uses hal callbacks instead of pure D-Bus monitoring
Uses HAL >= 0.5.0 only if D-Bus >= 0.9.2 is present
(refs #99)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • modules/services_discovery/hal.c

    r1d330ec r16093d9  
    33 ***************************************************************************** 
    44 * Copyright (C) 2004 the VideoLAN team 
     5 * Copyright (C) 2006 Rafaël Carré 
    56 * $Id$ 
    67 * 
    78 * Authors: Clément Stenac <zorglub@videolan.org> 
     9 *          Rafaël Carré <funman at videolanorg> 
    810 * 
    911 * This program is free software; you can redistribute it and/or modify 
     
    4547 * Local prototypes 
    4648 *****************************************************************************/ 
     49#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
     50/* store relation between item id and udi for ejection */ 
     51struct udi_input_id_t 
     52{ 
     53    char    *psz_udi; 
     54    int     i_id; 
     55}; 
     56#endif 
     57 
    4758struct services_discovery_sys_t 
    4859{ 
     
    5061    playlist_item_t *p_node_cat; 
    5162    playlist_item_t *p_node_one; 
     63#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
     64    int                     i_devices_number; 
     65    struct udi_input_id_t   **pp_devices; 
     66#endif 
    5267}; 
    53 static void AddItem( services_discovery_t *p_sd, input_item_t * p_input ); 
    5468static void Run    ( services_discovery_t *p_intf ); 
    5569 
    5670static int  Open ( vlc_object_t * ); 
    5771static void Close( vlc_object_t * ); 
     72 
     73#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
     74/* HAL callbacks */ 
     75void DeviceAdded( LibHalContext *p_ctx, const char *psz_udi ); 
     76void DeviceRemoved( LibHalContext *p_ctx, const char *psz_udi ); 
     77/* to retrieve p_sd in HAL callbacks */ 
     78services_discovery_t        *p_sd_global; 
     79#endif 
    5880 
    5981/***************************************************************************** 
     
    85107    DBusError           dbus_error; 
    86108    DBusConnection      *p_connection; 
     109 
     110    p_sd_global = p_sd; 
     111    p_sys->i_devices_number = 0; 
     112    p_sys->pp_devices = NULL; 
    87113#endif 
    88114 
     
    123149        return VLC_EGENERIC; 
    124150    } 
     151 
     152#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
     153        if( !libhal_ctx_set_device_added( p_sys->p_ctx, DeviceAdded ) || 
     154                !libhal_ctx_set_device_removed( p_sys->p_ctx, DeviceRemoved ) ) 
     155        { 
     156            msg_Err( p_sd, "unable to add callback" ); 
     157            dbus_error_free( &dbus_error ); 
     158            free( p_sys ); 
     159            return VLC_EGENERIC; 
     160        } 
     161#endif 
    125162 
    126163    /* Create our playlist node */ 
     
    157194    } 
    158195    free( p_sys ); 
    159 
    160  
    161 static void AddDvd( services_discovery_t *p_sd, char *psz_device ) 
    162 
    163     char *psz_name; 
    164     char *psz_uri; 
    165     char *psz_blockdevice; 
    166     input_item_t        *p_input; 
    167 #ifdef HAVE_HAL_1 
    168     psz_name = libhal_device_get_property_string( p_sd->p_sys->p_ctx, 
    169                                         psz_device, "volume.label", NULL ); 
    170     psz_blockdevice = libhal_device_get_property_string( p_sd->p_sys->p_ctx, 
    171                                         psz_device, "block.device", NULL ); 
    172 #else 
    173     psz_name = hal_device_get_property_string( p_sd->p_sys->p_ctx, 
    174                                                psz_device, "volume.label" ); 
    175     psz_blockdevice = hal_device_get_property_string( p_sd->p_sys->p_ctx, 
    176                                                  psz_device, "block.device" ); 
    177 #endif 
    178     asprintf( &psz_uri, "dvd://%s", psz_blockdevice ); 
    179     /* Create the playlist item here */ 
    180     p_input = input_ItemNew( p_sd, psz_uri, psz_name ); 
    181     free( psz_uri ); 
    182 #ifdef HAVE_HAL_1 
    183     libhal_free_string( psz_device ); 
    184 #else 
    185     hal_free_string( psz_device ); 
    186 #endif 
    187     if( !p_input ) 
    188     { 
    189         return; 
    190     } 
    191     AddItem( p_sd, p_input ); 
    192 
    193  
    194 static void AddItem( services_discovery_t *p_sd, input_item_t * p_input ) 
     196#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
     197    while( p_sys->i_devices_number > 0 ); 
     198    { 
     199        struct udi_input_id_t *p_udi_entry = p_sys->pp_devices[0]; 
     200        if( p_udi_entry->psz_udi ) free( p_udi_entry->psz_udi ); 
     201        TAB_REMOVE( p_sys->i_devices_number, p_sys->pp_devices, 0 ); 
     202        if( p_udi_entry ) free( p_udi_entry ); 
     203    } 
     204    p_sys->pp_devices = NULL; 
     205#endif 
     206
     207 
     208static void AddItem( services_discovery_t *p_sd, input_item_t * p_input 
     209#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
     210                ,char* psz_device 
     211#endif 
     212                    ) 
    195213{ 
    196214    playlist_item_t *p_item; 
     215    services_discovery_sys_t *p_sys  = p_sd->p_sys; 
    197216    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_sd, 
    198217                                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); 
     
    210229 
    211230    vlc_object_release( p_playlist ); 
    212 
     231 
     232#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
     233    struct udi_input_id_t *p_udi_entry; 
     234    p_udi_entry = malloc( sizeof( struct udi_input_id_t ) ); 
     235    if( !p_udi_entry ) 
     236    { 
     237        return; 
     238    } 
     239    p_udi_entry->i_id = p_item->i_id; 
     240    p_udi_entry->psz_udi = strdup( psz_device ); 
     241    TAB_APPEND( p_sys->i_devices_number, p_sys->pp_devices, p_udi_entry ); 
     242#endif 
     243
     244 
     245static void AddDvd( services_discovery_t *p_sd, char *psz_device ) 
     246
     247    char *psz_name; 
     248    char *psz_uri; 
     249    char *psz_blockdevice; 
     250    input_item_t        *p_input; 
     251#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
     252    psz_name = libhal_device_get_property_string( p_sd->p_sys->p_ctx, 
     253                                        psz_device, "volume.label", NULL ); 
     254    psz_blockdevice = libhal_device_get_property_string( p_sd->p_sys->p_ctx, 
     255                                        psz_device, "block.device", NULL ); 
     256#else 
     257    psz_name = hal_device_get_property_string( p_sd->p_sys->p_ctx, 
     258                                               psz_device, "volume.label" ); 
     259    psz_blockdevice = hal_device_get_property_string( p_sd->p_sys->p_ctx, 
     260                                                 psz_device, "block.device" ); 
     261#endif 
     262    asprintf( &psz_uri, "dvd://%s", psz_blockdevice ); 
     263    /* Create the playlist item here */ 
     264    p_input = input_ItemNew( p_sd, psz_uri, psz_name ); 
     265    free( psz_uri ); 
     266    if( !p_input ) 
     267    { 
     268        return; 
     269    } 
     270#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
     271    AddItem( p_sd, p_input, psz_device ); 
     272#else 
     273    AddItem( p_sd, p_input ); 
     274#endif 
     275
     276 
     277#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
     278static void DelItem( services_discovery_t *p_sd, char* psz_udi ) 
     279
     280    services_discovery_sys_t    *p_sys  = p_sd->p_sys; 
     281    int                         i; 
     282 
     283    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_sd, 
     284                                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); 
     285    if( !p_playlist ) 
     286    { 
     287        msg_Err( p_sd, "playlist not found" ); 
     288        return; 
     289    } 
     290 
     291    for( i = 0; i < p_sys->i_devices_number; i++ ) 
     292    { 
     293        if( strcmp( psz_udi, p_sys->pp_devices[i]->psz_udi ) == 0 ) 
     294        { 
     295            playlist_DeleteFromItemId( p_playlist, p_sys->pp_devices[i]->i_id ); 
     296        } 
     297    } 
     298 
     299    vlc_object_release( p_playlist ); 
     300
     301#endif 
    213302 
    214303static void AddCdda( services_discovery_t *p_sd, char *psz_device ) 
    215304{ 
    216     char *psz_name = "Audio CD"; 
    217305    char *psz_uri; 
    218306    char *psz_blockdevice; 
    219307    input_item_t     *p_input; 
    220 #ifdef HAVE_HAL_1 
     308#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
    221309    psz_blockdevice = libhal_device_get_property_string( p_sd->p_sys->p_ctx, 
    222310                                            psz_device, "block.device", NULL ); 
     
    227315    asprintf( &psz_uri, "cdda://%s", psz_blockdevice ); 
    228316    /* Create the playlist item here */ 
    229     p_input = input_ItemNew( p_sd, psz_uri, psz_name ); 
     317    p_input = input_ItemNew( p_sd, psz_uri, "Audio CD" ); 
    230318    free( psz_uri ); 
    231 #ifdef HAVE_HAL_1 
    232     libhal_free_string( psz_device ); 
    233 #else 
    234     hal_free_string( psz_device ); 
    235 #endif 
    236319    if( !p_input ) 
    237320        return; 
     321#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
     322    AddItem( p_sd, p_input, psz_device ); 
     323#else 
    238324    AddItem( p_sd, p_input ); 
     325#endif 
    239326} 
    240327 
     
    243330    char *psz_disc_type; 
    244331    services_discovery_sys_t    *p_sys  = p_sd->p_sys; 
    245 #ifdef HAVE_HAL_1 
     332#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
    246333    if( libhal_device_property_exists( p_sys->p_ctx, psz_device, 
    247334                                       "volume.disc.type", NULL ) ) 
     
    261348        if( !strcmp( psz_disc_type, "dvd_rom" ) ) 
    262349        { 
    263 #ifdef HAVE_HAL_1 
     350#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
    264351            /* hal 0.2.9.7 (HAVE_HAL) has not is_videodvd 
    265352             * but hal 0.5.0 (HAVE_HAL_1) has */ 
     
    271358        else if( !strcmp( psz_disc_type, "cd_rom" ) ) 
    272359        { 
    273 #ifdef HAVE_HAL_1 
     360#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
    274361            if( libhal_device_get_property_bool( p_sys->p_ctx, psz_device, 
    275362                                         "volume.disc.has_audio" , NULL ) ) 
     
    282369            } 
    283370        } 
    284 #ifdef HAVE_HAL_1 
    285         libhal_free_string( psz_disc_type ); 
    286 #else 
    287         hal_free_string( psz_disc_type ); 
    288 #endif 
    289371    } 
    290372} 
     
    300382 
    301383    /* parse existing devices first */ 
    302 #ifdef HAVE_HAL_1 
     384#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
    303385    if( ( devices = libhal_get_all_devices( p_sys->p_ctx, &i_devices, NULL ) ) ) 
    304386#else 
     
    309391        { 
    310392            ParseDevice( p_sd, devices[ i ] ); 
     393#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
     394            libhal_free_string( devices[ i ] ); 
     395#else 
     396            hal_free_string( devices[ i ] ); 
     397#endif 
     398 
    311399        } 
    312400    } 
    313 #ifdef HAVE_DBUS_2 
    314     /* We'll use D-Bus to listen for devices evenements */ 
    315     /* TODO: Manage hot removal of devices */ 
    316     DBusMessage*        dbus_message; 
    317     DBusMessageIter     dbus_args; 
    318     const char**        psz_dbus_value; 
    319     char*               psz_dbus_device; 
    320     DBusError           dbus_error; 
    321     DBusConnection*     p_connection; 
    322  
    323     dbus_error_init( &dbus_error ); 
    324  
    325     /* connect to the system bus */ 
    326     p_connection = dbus_bus_get( DBUS_BUS_SYSTEM, &dbus_error ); 
    327     if ( dbus_error_is_set( &dbus_error ) ) 
    328     { 
    329         msg_Err( p_sd, "D-Bus Connection Error (%s)\n", dbus_error.message); 
    330         dbus_error_free( &dbus_error ); 
    331         return; 
    332     } 
    333  
    334     /* check for hal signals */ 
    335     dbus_bus_add_match( p_connection, 
    336         "type='signal',interface='org.freedesktop.Hal.Manager'", &dbus_error ); 
    337     dbus_connection_flush( p_connection ); 
    338  
    339     /* an error ? oooh too bad :) */ 
    340     if ( dbus_error_is_set( &dbus_error ) ) 
    341     {  
    342         msg_Err( p_sd, "D-Bus signal match Error (%s)\n", dbus_error.message); 
    343         return; 
    344     } 
    345  
     401#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
    346402    while( !p_sd->b_die ) 
    347403    { 
    348         /* read next available message */ 
    349         dbus_connection_read_write( p_connection, 0 ); 
    350         dbus_message = dbus_connection_pop_message( p_connection ); 
    351  
    352         if( dbus_message == NULL ) 
    353         { 
    354             /* we've worked really hard, now it's time to sleep */ 
    355             msleep( 100000 ); 
    356             continue; 
    357         } 
    358         /* check if the message is a signal from the correct interface */ 
    359         if( dbus_message_is_signal( dbus_message, "org.freedesktop.Hal.Manager", 
    360                     "DeviceAdded" ) ) 
    361         { 
    362             /* read the parameter (it must be an udi string) */ 
    363             if( dbus_message_iter_init( dbus_message, &dbus_args ) && 
    364                 ( dbus_message_iter_get_arg_type( &dbus_args ) == 
    365                         DBUS_TYPE_STRING ) 
    366                 ) 
    367             { 
    368                 dbus_message_iter_get_basic( &dbus_args, &psz_dbus_value ); 
    369                 /* psz_bus_value musn't be freed, but AddCdda will do it 
    370                  * so we allocate some memory, and copy it into psz_dbus_device 
    371                  */ 
    372                 psz_dbus_device = strdup( psz_dbus_value ); 
    373                 ParseDevice( p_sd, psz_dbus_device ); 
    374             } 
    375         } 
    376         dbus_message_unref( dbus_message ); 
    377     } 
    378 #endif 
    379 
     404    /* look for events on the bus, blocking 1 second */ 
     405    dbus_connection_read_write_dispatch( 
     406            libhal_ctx_get_dbus_connection(p_sys->p_ctx), 1000 ); 
     407    } 
     408#endif 
     409 
     410
     411 
     412#if defined( HAVE_HAL_1 ) && defined( HAVE_DBUS_2 ) 
     413void DeviceAdded( LibHalContext *p_ctx, const char *psz_udi ) 
     414
     415        ParseDevice( p_sd_global, (char*) psz_udi ); 
     416
     417void DeviceRemoved( LibHalContext *p_ctx, const char *psz_udi ) 
     418
     419        DelItem( p_sd_global, (char*) psz_udi ); 
     420
     421#endif 
     422