~ubuntu-branches/debian/wheezy/vlc/wheezy

« back to all changes in this revision

Viewing changes to modules/access/slp.c

Tags: upstream-0.7.2.final
Import upstream version 0.7.2.final

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 * slp.c: SLP access plugin
 
3
 *****************************************************************************
 
4
 * Copyright (C) 2002-2004 VideoLAN
 
5
 * $Id: slp.c 7209 2004-03-31 20:52:31Z gbazin $
 
6
 *
 
7
 * Authors: Lo�c Minier <lool@videolan.org>
 
8
 *
 
9
 * This program is free software; you can redistribute it and/or modify
 
10
 * it under the terms of the GNU General Public License as published by
 
11
 * the Free Software Foundation; either version 2 of the License, or
 
12
 * (at your option) any later version.
 
13
 *
 
14
 * This program is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 * GNU General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU General Public License
 
20
 * along with this program; if not, write to the Free Software
 
21
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 
22
 *****************************************************************************/
 
23
 
 
24
/*****************************************************************************
 
25
 * Preamble
 
26
 *****************************************************************************/
 
27
#include <stdlib.h>                                                /* malloc */
 
28
 
 
29
#include <vlc/vlc.h>
 
30
#include <vlc/input.h>
 
31
 
 
32
#include <vlc_playlist.h>
 
33
 
 
34
#include <slp.h>
 
35
 
 
36
/*****************************************************************************
 
37
 * Local prototypes
 
38
 *****************************************************************************/
 
39
static int  Open  ( vlc_object_t * );
 
40
static void Close ( vlc_object_t * );
 
41
static ssize_t Read( input_thread_t *, byte_t *, size_t );
 
42
 
 
43
static int  Init  ( vlc_object_t * );
 
44
static void End   ( vlc_object_t * );
 
45
static int  Demux ( input_thread_t * );
 
46
 
 
47
int i_group;
 
48
 
 
49
/*****************************************************************************
 
50
 * Module descriptor
 
51
 *****************************************************************************/
 
52
 
 
53
#if 0
 
54
#define SRVTYPE_TEXT /*N_*/("SLP service type")
 
55
#define SRVTYPE_LONGTEXT /*N_*/( \
 
56
    "The service type string for SLP queries, including the authority " \
 
57
    "string (if any) for the request. May not be empty." )
 
58
#endif
 
59
 
 
60
#define ATTRIDS_TEXT N_("SLP attribute identifiers")
 
61
#define ATTRIDS_LONGTEXT N_( \
 
62
    "This string is a comma separated list of attribute identifiers to " \
 
63
    "search for a playlist title or empty to use all attributes." )
 
64
 
 
65
#define SCOPELIST_TEXT N_("SLP scopes list")
 
66
#define SCOPELIST_LONGTEXT N_( \
 
67
    "This string is a comma separated list of scope names or empty if you " \
 
68
    "want to use the default scopes. It is used in all SLP queries." )
 
69
 
 
70
#define NAMINGAUTHORITY_TEXT N_("SLP naming authority")
 
71
#define NAMINGAUTHORITY_LONGTEXT N_( \
 
72
    "This string is a list of naming authorities to search. " \
 
73
    "Use \"*\" for all and the empty string for the default of IANA." )
 
74
 
 
75
#define FILTER_TEXT N_("SLP LDAP filter")
 
76
#define FILTER_LONGTEXT N_( \
 
77
    "This is a query formulated of attribute pattern matching expressions " \
 
78
    "in the form of an LDAPv3 search filter or empty for all answers." )
 
79
 
 
80
#define LANG_TEXT N_("Language requested in SLP requests")
 
81
#define LANG_LONGTEXT N_( \
 
82
    "RFC 1766 Language tag for the natural language locale of requests, " \
 
83
    "leave empty to use the default locale. It is used in all SLP queries." )
 
84
 
 
85
vlc_module_begin();
 
86
    set_description( _("SLP input") );
 
87
 
 
88
    add_string( "slp-attrids", "", NULL, ATTRIDS_TEXT, ATTRIDS_LONGTEXT,
 
89
                VLC_TRUE );
 
90
    add_string( "slp-scopelist", "", NULL, SCOPELIST_TEXT,
 
91
                SCOPELIST_LONGTEXT, VLC_TRUE );
 
92
    add_string( "slp-namingauthority", "*", NULL, NAMINGAUTHORITY_TEXT,
 
93
                NAMINGAUTHORITY_LONGTEXT, VLC_TRUE );
 
94
    add_string( "slp-filter", "", NULL, FILTER_TEXT, FILTER_LONGTEXT,
 
95
                VLC_TRUE );
 
96
    add_string( "slp-lang", "", NULL, LANG_TEXT, LANG_LONGTEXT, VLC_TRUE );
 
97
 
 
98
    set_capability( "access", 0 );
 
99
    set_callbacks( Open, Close );
 
100
 
 
101
    add_submodule();
 
102
        add_shortcut( "demux_slp" );
 
103
        set_capability( "demux", 0 );
 
104
        set_callbacks( Init, End );
 
105
vlc_module_end();
 
106
 
 
107
/*****************************************************************************
 
108
 * AttrCallback: updates the description of a playlist item
 
109
 *****************************************************************************/
 
110
static SLPBoolean AttrCallback( SLPHandle slph_slp,
 
111
                           const char * psz_attrlist,
 
112
                           SLPError slpe_errcode,
 
113
                           void * p_cookie )
 
114
{
 
115
    playlist_item_t * p_playlist_item = (playlist_item_t *)p_cookie;
 
116
 
 
117
    /* our callback was only called to tell us there's nothing more to read */
 
118
    if( slpe_errcode == SLP_LAST_CALL )
 
119
    {
 
120
        return SLP_TRUE;
 
121
    }
 
122
 
 
123
    /* or there was a problem with getting the data we requested */
 
124
    if( (slpe_errcode != SLP_OK) )
 
125
    {
 
126
#if 0
 
127
        msg_Err( (vlc_object_t*)NULL,
 
128
                 "AttrCallback got an error %i with attribute %s",
 
129
                 slpe_errcode,
 
130
                 psz_attrlist );
 
131
#endif
 
132
        return SLP_TRUE;
 
133
    }
 
134
 
 
135
    if( p_playlist_item->input.psz_name )
 
136
        free( p_playlist_item->input.psz_name );
 
137
 
 
138
    p_playlist_item->input.psz_name = strdup(psz_attrlist); /* NULL is checked */
 
139
    return SLP_TRUE;
 
140
}
 
141
 
 
142
/*****************************************************************************
 
143
 * SrvUrlCallback: adds an entry to the playlist
 
144
 *****************************************************************************/
 
145
static SLPBoolean SrvUrlCallback( SLPHandle slph_slp,
 
146
                           const char * psz_srvurl,
 
147
                           uint16_t i_lifetime,
 
148
                           SLPError slpe_errcode,
 
149
                           void * p_cookie )
 
150
{
 
151
    input_thread_t *p_input = (input_thread_t  *)p_cookie;
 
152
    playlist_t * p_playlist;
 
153
    char psz_item[42] = ""; //"udp:@";
 
154
    char * psz_s;                           /* to hold the uri of the stream */
 
155
    SLPHandle slph_slp3;
 
156
    SLPError slpe_result;
 
157
    playlist_item_t * p_playlist_item;
 
158
 
 
159
    /* our callback was only called to tell us there's nothing more to read */
 
160
    if( slpe_errcode == SLP_LAST_CALL )
 
161
    {
 
162
        return SLP_TRUE;
 
163
    }
 
164
 
 
165
    msg_Dbg( p_input,"URL: %s", psz_srvurl );
 
166
 
 
167
    /* or there was a problem with getting the data we requested */
 
168
    if( (slpe_errcode != SLP_OK) )
 
169
    {
 
170
        msg_Err( p_input, "SrvUrlCallback got an error %i with URL %s",
 
171
                 slpe_errcode, psz_srvurl );
 
172
        return SLP_TRUE;
 
173
    }
 
174
 
 
175
    /* search the returned address after a double-slash */
 
176
    psz_s = strstr( psz_srvurl, "//" );
 
177
    if( psz_s == NULL )
 
178
    {
 
179
        msg_Err( p_input,
 
180
                 "SrvUrlCallback got a strange string of your libslp" );
 
181
        return SLP_TRUE;
 
182
    }
 
183
    /* skip the slashes */
 
184
    psz_s = &psz_s[2];
 
185
    /* add udp:@ in front of the address */
 
186
    psz_s = strncat( psz_item,
 
187
                     psz_s,
 
188
                     sizeof(psz_item) - strlen(psz_item) - 1 );
 
189
 
 
190
    /* create a playlist  item */
 
191
    p_playlist_item = playlist_ItemNew( p_input, psz_s, NULL );
 
192
    if( p_playlist_item == NULL )
 
193
    {
 
194
        msg_Err( p_input, "out of memory" );
 
195
        return SLP_TRUE;
 
196
    }
 
197
 
 
198
    p_playlist_item->i_group = i_group;
 
199
    p_playlist_item->b_enabled = VLC_TRUE;
 
200
 
 
201
    /* search the description of the stream */
 
202
    if( SLPOpen( config_GetPsz( p_input, "slp-lang" ),
 
203
                 SLP_FALSE,                              /* synchronous ops */
 
204
                 &slph_slp3 ) == SLP_OK )
 
205
    {
 
206
        /* search all attributes */
 
207
        slpe_result = SLPFindAttrs( slph_slp3,
 
208
                                    psz_srvurl,
 
209
                                    config_GetPsz( p_input, "slp-scopelist" ),
 
210
                                    config_GetPsz( p_input, "slp-attrids" ),
 
211
                                    AttrCallback,
 
212
                                    p_playlist_item
 
213
                                  );
 
214
 
 
215
        /* we're done, clean up */
 
216
        SLPClose( slph_slp3 );
 
217
    }
 
218
 
 
219
    /* search the main playlist object */
 
220
    p_playlist = vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
 
221
                                  FIND_ANYWHERE );
 
222
    if( p_playlist == NULL )
 
223
    {
 
224
        msg_Warn( p_input, "could not find playlist, not adding entries" );
 
225
        return SLP_TRUE;
 
226
    }
 
227
 
 
228
    playlist_AddItem( p_playlist, p_playlist_item,
 
229
                      PLAYLIST_APPEND, PLAYLIST_END );
 
230
    vlc_object_release( p_playlist );
 
231
 
 
232
    msg_Info( p_input, "added � %s � (lifetime %i) to playlist",
 
233
              psz_srvurl, i_lifetime );
 
234
 
 
235
    return SLP_TRUE;
 
236
}
 
237
 
 
238
/*****************************************************************************
 
239
 * SrvTypeCallback: searchs all servers of a certain type
 
240
 *****************************************************************************/
 
241
static SLPBoolean SrvTypeCallback( SLPHandle slph_slp,
 
242
                           const char * psz_srvurl,
 
243
                           SLPError slpe_errcode,
 
244
                           void * p_cookie )
 
245
{
 
246
    input_thread_t * p_input = (input_thread_t  *)p_cookie;
 
247
    SLPError slpe_result;
 
248
    SLPHandle slph_slp2;
 
249
    char *psz_eos;
 
250
    char *psz_service;
 
251
 
 
252
    msg_Dbg( p_input, "services: %s", psz_srvurl );
 
253
    /* our callback was only called to tell us there's nothing more to read */
 
254
    if( slpe_errcode == SLP_LAST_CALL )
 
255
    {
 
256
        return SLP_TRUE;
 
257
    }
 
258
 
 
259
    msg_Dbg( p_input, "services: %s", psz_srvurl );
 
260
 
 
261
    /* or there was a problem with getting the data we requested */
 
262
    if( slpe_errcode != SLP_OK )
 
263
    {
 
264
        msg_Err( p_input, "SrvTypeCallback got an error %i with URL %s",
 
265
                 slpe_errcode, psz_srvurl );
 
266
        return SLP_TRUE;
 
267
    }
 
268
 
 
269
    /* get a new handle to the library */
 
270
    if( SLPOpen( config_GetPsz( p_input, "slp-lang" ),
 
271
                 SLP_FALSE,                              /* synchronous ops */
 
272
                 &slph_slp2 ) == SLP_OK )
 
273
    {
 
274
        /* search for services */
 
275
        while(1)
 
276
        {
 
277
            if( *psz_srvurl == '\0')  break;
 
278
 
 
279
            if( !strncasecmp( psz_srvurl, "service:", 8 ) )
 
280
            {
 
281
                while(1)
 
282
                {
 
283
                    psz_eos = strchr( psz_srvurl, ',');
 
284
                    if(!psz_eos) break;
 
285
                    if(!strncasecmp(psz_eos+1,"service:",8)) break;
 
286
                }
 
287
 
 
288
                if(psz_eos)
 
289
                    *psz_eos = '\0';
 
290
 
 
291
                psz_service = strdup( psz_srvurl);
 
292
 
 
293
                msg_Dbg( p_input, "getting details for %s", psz_service );
 
294
 
 
295
                slpe_result = SLPFindSrvs( slph_slp2,
 
296
                                   psz_service,
 
297
                                   config_GetPsz( p_input, "slp-scopelist" ),
 
298
                                   config_GetPsz( p_input, "slp-filter" ),
 
299
                                   SrvUrlCallback,
 
300
                                   p_input );
 
301
 
 
302
                if(psz_eos)
 
303
                    psz_srvurl = psz_eos;
 
304
 
 
305
#if 0
 
306
                SLPClose( slph_slp2 );
 
307
#endif
 
308
                if( slpe_result != SLP_OK )
 
309
                {
 
310
                   msg_Err( p_input,
 
311
                           "SLPFindSrvs error %i finding servers of type %s",
 
312
                           slpe_result, psz_service );
 
313
                }
 
314
            }
 
315
            psz_srvurl++;
 
316
        }
 
317
    }
 
318
                SLPClose( slph_slp2 );
 
319
 
 
320
    return SLP_TRUE;
 
321
}
 
322
 
 
323
/*****************************************************************************
 
324
 * Open: initialize library for the access module
 
325
 *****************************************************************************/
 
326
static int Open( vlc_object_t * p_this )
 
327
{
 
328
    input_thread_t *   p_input = (input_thread_t *)p_this;
 
329
    SLPError           slpe_result;
 
330
    SLPHandle          slph_slp;
 
331
    playlist_t *       p_playlist;
 
332
    playlist_group_t * p_group;
 
333
 
 
334
    /* remove the "slp:" entry of the playlist */
 
335
    p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
 
336
                                                 FIND_ANYWHERE );
 
337
    if( !p_playlist )
 
338
    {
 
339
        msg_Warn( p_input, "hey I can't find the main playlist, I need it" );
 
340
        return VLC_FALSE;
 
341
    }
 
342
 
 
343
    p_group = playlist_CreateGroup( p_playlist , "SLP" );
 
344
    i_group = p_group->i_id;
 
345
    p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = VLC_TRUE;
 
346
    vlc_object_release( (vlc_object_t *)p_playlist );
 
347
 
 
348
    /* get a new handle to the library */
 
349
    if( SLPOpen( config_GetPsz( p_input, "slp-lang" ),
 
350
                 SLP_FALSE,                              /* synchronous ops */
 
351
                 &slph_slp ) == SLP_OK )
 
352
    {
 
353
        /* search all service types */
 
354
        slpe_result =
 
355
            SLPFindSrvTypes( slph_slp,
 
356
                             config_GetPsz( p_input, "slp-namingauthority" ),
 
357
                             config_GetPsz( p_input, "slp-scopelist" ),
 
358
                             SrvTypeCallback,
 
359
                             p_input );
 
360
        /* we're done, clean up */
 
361
        SLPClose( slph_slp );
 
362
    }
 
363
 
 
364
    if( !p_input->psz_demux || !*p_input->psz_demux )
 
365
    {
 
366
        p_input->psz_demux = "demux_slp";
 
367
    }
 
368
 
 
369
    p_input->pf_read = Read;
 
370
    p_input->pf_set_program = NULL;
 
371
    p_input->pf_set_area = NULL;
 
372
    p_input->pf_seek = NULL;
 
373
 
 
374
    vlc_mutex_lock( &p_input->stream.stream_lock );
 
375
    p_input->stream.b_pace_control = VLC_FALSE;
 
376
    p_input->stream.b_seekable = VLC_FALSE;
 
377
    p_input->stream.p_selected_area->i_tell = 0;
 
378
    p_input->stream.p_selected_area->i_size = 0;
 
379
    p_input->stream.i_method = INPUT_METHOD_SLP;
 
380
    vlc_mutex_unlock( &p_input->stream.stream_lock );
 
381
    p_input->i_mtu = 0;
 
382
 
 
383
    return VLC_SUCCESS;
 
384
}
 
385
 
 
386
/*****************************************************************************
 
387
 * Close: close access
 
388
 *****************************************************************************/
 
389
static void Close( vlc_object_t * p_this )
 
390
{
 
391
    return;
 
392
}
 
393
 
 
394
/*****************************************************************************
 
395
 * Read: should fill but zeroes the buffer
 
396
 *****************************************************************************/
 
397
static ssize_t Read  ( input_thread_t *p_input, byte_t *p_buffer, size_t s )
 
398
{
 
399
    memset( p_buffer, 0, s );
 
400
    return s;
 
401
}
 
402
 
 
403
/*****************************************************************************
 
404
 * Init: initialize demux
 
405
 *****************************************************************************/
 
406
static int Init ( vlc_object_t *p_this )
 
407
{
 
408
    input_thread_t *p_input = (input_thread_t *)p_this;
 
409
 
 
410
    if( p_input->stream.i_method != INPUT_METHOD_SLP )
 
411
    {
 
412
        return VLC_FALSE;
 
413
    }
 
414
 
 
415
    p_input->pf_demux  = Demux;
 
416
    p_input->pf_demux_control = demux_vaControlDefault;
 
417
    p_input->pf_rewind = NULL;
 
418
 
 
419
    return VLC_SUCCESS;
 
420
}
 
421
 
 
422
/*****************************************************************************
 
423
 * Demux: should demux but does nothing
 
424
 *****************************************************************************/
 
425
static int Demux ( input_thread_t * p_input )
 
426
{
 
427
    return 0;
 
428
}
 
429
 
 
430
/*****************************************************************************
 
431
 * End: end demux
 
432
 *****************************************************************************/
 
433
static void End ( vlc_object_t *p_this )
 
434
{
 
435
    return;
 
436
}