hal.c 9.17 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*****************************************************************************
 * hal.c :  HAL probing module
 *****************************************************************************
 * Copyright (C) 2004 the VideoLAN team
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include <vlc/vlc.h>
zorglub's avatar
zorglub committed
25
#include <vlc_interface.h>
26
27
28
29
30
31
32
#include <vlc_devices.h>

#include <hal/libhal.h>

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
33
struct probe_sys_t
34
{
35
    DBusConnection *p_connection;
36
37
38
39
40
41
42
43
    LibHalContext *p_ctx;
    int            i_devices;
    device_t     **pp_devices;
};

static int  Open ( vlc_object_t * );
static void Close( vlc_object_t * );

44
45
46
47
static void Update ( device_probe_t *p_probe );
static void UpdateMedia( device_probe_t *p_probe, device_t *p_dev );
static void AddDevice( device_probe_t * p_probe, device_t *p_dev );
static device_t * ParseDisc( device_probe_t *p_probe,  char *psz_device );
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
vlc_module_begin();
    set_description( _("HAL devices detection") );
    set_capability( "devices probe", 0 );
    set_callbacks( Open, Close );
vlc_module_end();


/*****************************************************************************
 * Open: initialize and create stuff
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
64
    device_probe_t *p_probe = (device_probe_t *)p_this;
65
66
    DBusError           dbus_error;
    DBusConnection      *p_connection;
67
    probe_sys_t          *p_sys;
68

69
70
71
    p_probe->p_sys = p_sys = (probe_sys_t*)malloc( sizeof( probe_sys_t ) );
    p_probe->p_sys->i_devices = 0;
    p_probe->p_sys->pp_devices = NULL;
72

73
    p_probe->pf_run = Update;
74
75
76

    dbus_error_init( &dbus_error );

zorglub's avatar
zorglub committed
77
78
    p_sys->p_ctx = libhal_ctx_new();
    if( !p_sys->p_ctx )
79
    {
80
81
        msg_Err( p_probe, "unable to create HAL context") ;
        free( p_probe->p_sys );
82
83
84
85
86
        return VLC_EGENERIC;
    }
    p_connection = dbus_bus_get( DBUS_BUS_SYSTEM, &dbus_error );
    if( dbus_error_is_set( &dbus_error ) )
    {
87
        msg_Err( p_probe, "unable to connect to DBUS: %s", dbus_error.message );
88
        dbus_error_free( &dbus_error );
89
        free( p_probe->p_sys );
90
91
        return VLC_EGENERIC;
    }
92
    p_sys->p_connection = p_connection;
93
94
    libhal_ctx_set_dbus_connection( p_probe->p_sys->p_ctx, p_connection );
    if( !libhal_ctx_init( p_probe->p_sys->p_ctx, &dbus_error ) )
95
    {
96
        msg_Err( p_probe, "hal not available : %s", dbus_error.message );
97
        dbus_connection_unref( p_connection );
98
99
100
101
102
103
104
105
106
107
108
109
        dbus_error_free( &dbus_error );
        free( p_sys );
        return VLC_EGENERIC;
    }
    return VLC_SUCCESS;
}

/*****************************************************************************
 * Close:
 *****************************************************************************/
static void Close( vlc_object_t *p_this )
{
110
111
    device_probe_t *p_probe = (device_probe_t *) p_this;
    probe_sys_t *p_sys = p_probe->p_sys;
112
    dbus_connection_unref( p_sys->p_connection );
113
114
    free( p_sys );
}
115
#if 0
116
static int GetAllDevices( device_probe_t *p_probe, device_t ***ppp_devices )
117
{
dionoea's avatar
dionoea committed
118
    /// \todo : fill the dst array
119
    return p_probe->p_sys->i_devices;
120
}
121
#endif
122
static void Update( device_probe_t * p_probe )
123
{
124
    probe_sys_t *p_sys = p_probe->p_sys;
125
126
127
128
129
    int i, i_devices, j;
    char **devices;
    vlc_bool_t b_exists;

    for ( j = 0 ; j < p_sys->i_devices; j++ )
zorglub's avatar
zorglub committed
130
        p_sys->pp_devices[j]->b_seen = VLC_FALSE;
131

zorglub's avatar
zorglub committed
132
133
    /* CD/DVD */
    if( ( devices = libhal_find_device_by_capability( p_sys->p_ctx,
dionoea's avatar
dionoea committed
134
135
                              "storage.cdrom",
                              &i_devices, NULL ) ) )
136
137
138
    {
        for( i = 0; i < i_devices; i++ )
        {
139
            device_t *p_dev = ParseDisc( p_probe, devices[ i ] );
140
141
142
143
144
145
146
147
148
            b_exists = VLC_FALSE;

            for ( j = 0 ; j < p_sys->i_devices; j++ )
            {
                if( !strcmp( p_sys->pp_devices[j]->psz_uri,
                             p_dev->psz_uri ) )
                {
                    b_exists = VLC_TRUE;
                    p_dev->b_seen = VLC_TRUE;
149
                    UpdateMedia( p_probe, p_dev );
150
151
152
                    break;
                }
                if( !b_exists )
153
                    AddDevice( p_probe, p_dev );
154
155
156
157
158
159
160
            }
        }
    }
    /// \todo Remove unseen devices
}


161
static void AddDevice( device_probe_t * p_probe, device_t *p_dev )
162
{
163
164
165
    INSERT_ELEM( p_probe->p_sys->pp_devices,
                 p_probe->p_sys->i_devices,
                 p_probe->p_sys->i_devices,
166
167
168
169
                 p_dev );
    /// \todo : emit variable
}

170
static device_t * ParseDisc( device_probe_t *p_probe,  char *psz_device )
zorglub's avatar
zorglub committed
171
{
172
    probe_sys_t *p_sys = p_probe->p_sys;
zorglub's avatar
zorglub committed
173
174
175
    device_t *p_dev;
    char *block_dev;
    dbus_bool_t b_dvd;
dionoea's avatar
dionoea committed
176

zorglub's avatar
zorglub committed
177
    if( !libhal_device_property_exists( p_sys->p_ctx, psz_device,
dionoea's avatar
dionoea committed
178
                                        "storage.cdrom.dvd", NULL ) )
zorglub's avatar
zorglub committed
179
180
181
182
183
        return NULL;

    p_dev = (device_t *)malloc( sizeof( device_t ) );
    p_dev->i_media_type = p_dev->i_capabilities = 0;
    p_dev->psz_name = p_dev->psz_uri = NULL;
184

zorglub's avatar
zorglub committed
185
186
187
188
189
190
191
    block_dev =  libhal_device_get_property_string( p_sys->p_ctx, psz_device,
                                                   "block.device" , NULL );
    if( block_dev )
    {
        p_dev->psz_uri = strdup( block_dev );
        libhal_free_string( block_dev );
    }
192

zorglub's avatar
zorglub committed
193
194
195
196
197
198
    b_dvd = libhal_device_get_property_bool( p_sys->p_ctx, psz_device,
                                            "storage.cdrom.dvd", NULL  );
    if( b_dvd )
        p_dev->i_capabilities = DEVICE_CAN_DVD | DEVICE_CAN_CD;
    else
        p_dev->i_capabilities = DEVICE_CAN_CD;
199

200
    UpdateMedia( p_probe, p_dev );
zorglub's avatar
zorglub committed
201
202
203
    return p_dev;
}

204
static void UpdateMedia( device_probe_t *p_probe, device_t *p_dev )
205
{
206
    probe_sys_t *p_sys = p_probe->p_sys;
zorglub's avatar
zorglub committed
207
208
209
210
211
212
213
214
    char **matching_media;
    int i_matching, i;
    vlc_bool_t b_changed = VLC_FALSE;;
    int i_old_type = p_dev->i_media_type;
    p_dev->i_media_type = 0;

    /* Find the media in the drive */
    matching_media = libhal_manager_find_device_string_match( p_sys->p_ctx,
dionoea's avatar
dionoea committed
215
216
                                            "block.device", p_dev->psz_uri,
                                            &i_matching, NULL );
zorglub's avatar
zorglub committed
217
    for( i = 0; i < i_matching; i++ )
218
    {
dionoea's avatar
dionoea committed
219
        if( libhal_device_property_exists( p_sys->p_ctx, matching_media[i],
zorglub's avatar
zorglub committed
220
                                           "volume.disc.type", NULL ) )
dionoea's avatar
dionoea committed
221
222
223
224
225
        {
            char *psz_media_name = libhal_device_get_property_string(
                                            p_sys->p_ctx,
                                            matching_media[i],
                                            "volume.label", NULL );
zorglub's avatar
zorglub committed
226
            if( psz_media_name )
227
            {
zorglub's avatar
zorglub committed
228
229
230
231
232
233
234
235
236
                if( p_dev->psz_name && strcmp( p_dev->psz_name, psz_media_name))
                {
                    free( p_dev->psz_name );
                    p_dev->psz_name = NULL;
                    b_changed = VLC_TRUE;
                }
                if( !p_dev->psz_name )
                    p_dev->psz_name = strdup( psz_media_name );
                libhal_free_string( psz_media_name );
237
            }
zorglub's avatar
zorglub committed
238
239
240
241

            if( libhal_device_get_property_bool( p_sys->p_ctx,
                                             matching_media[i],
                                             "volume.disc.is_videodvd", NULL) )
dionoea's avatar
dionoea committed
242
                p_dev->i_media_type = MEDIA_TYPE_DVD;
zorglub's avatar
zorglub committed
243
244
245
246
247
248
249
250
251
252
253
254
255
            else if( libhal_device_get_property_bool( p_sys->p_ctx,
                                             matching_media[i],
                                             "volume.disc.is_vcd", NULL) ||
                     libhal_device_get_property_bool( p_sys->p_ctx,
                                             matching_media[i],
                                             "volume.disc.is_svcd", NULL) )
               p_dev->i_media_type = MEDIA_TYPE_VCD;
            else if( libhal_device_get_property_bool( p_sys->p_ctx,
                                             matching_media[i],
                                             "volume.disc.has_audio", NULL) )
               p_dev->i_media_type = MEDIA_TYPE_CDDA;

            break;
256
257
        }
    }
zorglub's avatar
zorglub committed
258
259
260
261
    if( b_changed || p_dev->i_media_type != i_old_type )
    {
        /// \todo emit changed signal
    }
262
}