vlm.c 77.1 KB
Newer Older
1
/*****************************************************************************
2
 * vlm.c: VLM interface plugin
3
 *****************************************************************************
dionoea's avatar
dionoea committed
4
 * Copyright (C) 2000-2005 the VideoLAN team
5
 * $Id$
6 7 8
 *
 * Authors: Simon Latapie <garf@videolan.org>
 *          Laurent Aimar <fenrir@videolan.org>
gbazin's avatar
gbazin committed
9
 *          Gildas Bazin <gbazin@videolan.org>
10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * 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
dionoea's avatar
dionoea committed
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 25 26 27 28
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
29 30 31
#include <vlc/vlc.h>

#include <stdio.h>
32
#include <stdlib.h>                                      /* malloc(), free() */
33
#include <ctype.h>                                              /* tolower() */
34

35 36
#ifdef ENABLE_VLM

37 38 39
#include <vlc/intf.h>
#include <vlc/input.h>

40 41
#ifdef HAVE_TIME_H
#   include <time.h>                                              /* ctime() */
42
#   include <sys/timeb.h>                                         /* ftime() */
43 44
#endif

45 46 47
#include <vlc_vlm.h>
#include <vlc_vod.h>
#include <charset.h>
48

49 50 51
/*****************************************************************************
 * Local prototypes.
 *****************************************************************************/
52 53 54
static vlm_message_t *vlm_Show( vlm_t *, vlm_media_t *, vlm_schedule_t *, char * );
static vlm_message_t *vlm_Help( vlm_t *, char * );

55
static vlm_media_instance_t *vlm_MediaInstanceSearch( vlm_t *, vlm_media_t *, const char * );
56

gbazin's avatar
gbazin committed
57
static vlm_message_t *vlm_MessageNew( char *, const char *, ... );
58
static vlm_message_t *vlm_MessageAdd( vlm_message_t *, vlm_message_t * );
59

60
static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *, const char * );
61

62 63
static char *Save( vlm_t * );
static int Load( vlm_t *, char * );
64
static int ExecuteCommand( vlm_t *, const char *, vlm_message_t ** );
65
static int Manage( vlc_object_t * );
66

67 68 69 70 71 72
/*****************************************************************************
 * vlm_New:
 *****************************************************************************/
vlm_t *__vlm_New ( vlc_object_t *p_this )
{
    vlc_value_t lockval;
zorglub's avatar
zorglub committed
73
    vlm_t *p_vlm = NULL;
74
    char *psz_vlmconf;
75 76

    /* to be sure to avoid multiple creation */
77 78
    var_Create( p_this->p_libvlc_global, "vlm_mutex", VLC_VAR_MUTEX );
    var_Get( p_this->p_libvlc_global, "vlm_mutex", &lockval );
79 80
    vlc_mutex_lock( lockval.p_address );

zorglub's avatar
zorglub committed
81
    if( !(p_vlm = vlc_object_find( p_this, VLC_OBJECT_VLM, FIND_ANYWHERE )) )
82
    {
zorglub's avatar
zorglub committed
83
        msg_Info( p_this, "creating VLM" );
zorglub's avatar
zorglub committed
84
        if( ( p_vlm = vlc_object_create( p_this, VLC_OBJECT_VLM ) ) == NULL )
85 86 87 88 89
        {
            vlc_mutex_unlock( lockval.p_address );
            return NULL;
        }

90
        vlc_mutex_init( p_this->p_libvlc, &p_vlm->lock );
zorglub's avatar
zorglub committed
91 92 93 94 95
        p_vlm->i_media      = 0;
        p_vlm->media        = NULL;
        p_vlm->i_vod        = 0;
        p_vlm->i_schedule   = 0;
        p_vlm->schedule     = NULL;
96

zorglub's avatar
zorglub committed
97
        vlc_object_yield( p_vlm );
98
        vlc_object_attach( p_vlm, p_this->p_libvlc );
99 100 101
    }
    vlc_mutex_unlock( lockval.p_address );

zorglub's avatar
zorglub committed
102
    if( vlc_thread_create( p_vlm, "vlm thread",
103 104
                           Manage, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
    {
zorglub's avatar
zorglub committed
105 106
        vlc_mutex_destroy( &p_vlm->lock );
        vlc_object_destroy( p_vlm );
107 108
        return NULL;
    }
109

110 111
    /* Try loading the vlm conf file given by --vlm-conf */
    psz_vlmconf = config_GetPsz( p_vlm, "vlm-conf" );
dionoea's avatar
dionoea committed
112 113 114 115 116 117

    if( psz_vlmconf && *psz_vlmconf )
    {
        vlm_message_t *p_message = NULL;
        char *psz_buffer = NULL;

zorglub's avatar
zorglub committed
118
        msg_Dbg( p_this, "loading VLM configuration" );
dionoea's avatar
dionoea committed
119 120 121 122 123
        asprintf(&psz_buffer, "load %s", psz_vlmconf );
        if( psz_buffer )
        {
            msg_Dbg( p_this, psz_buffer);
            if( vlm_ExecuteCommand( p_vlm, psz_buffer, &p_message ) ){
zorglub's avatar
zorglub committed
124
                msg_Warn( p_this, "error while loading the configuration file" );
dionoea's avatar
dionoea committed
125
            }
126
            vlm_MessageDelete(p_message);
dionoea's avatar
dionoea committed
127 128 129 130 131 132
            free(psz_buffer);
        }
   }
   free(psz_vlmconf);

   return p_vlm;
133 134 135 136 137
}

/*****************************************************************************
 * vlm_Delete:
 *****************************************************************************/
zorglub's avatar
zorglub committed
138
void vlm_Delete( vlm_t *p_vlm )
139 140 141
{
    vlc_value_t lockval;

142
    var_Get( p_vlm->p_libvlc_global, "vlm_mutex", &lockval );
143 144
    vlc_mutex_lock( lockval.p_address );

zorglub's avatar
zorglub committed
145
    vlc_object_release( p_vlm );
146

zorglub's avatar
zorglub committed
147
    if( p_vlm->i_refcount > 0 )
148 149 150 151 152
    {
        vlc_mutex_unlock( lockval.p_address );
        return;
    }

zorglub's avatar
zorglub committed
153 154
    p_vlm->b_die = VLC_TRUE;
    vlc_thread_join( p_vlm );
155

zorglub's avatar
zorglub committed
156
    vlc_mutex_destroy( &p_vlm->lock );
157

zorglub's avatar
zorglub committed
158
    while( p_vlm->i_media ) vlm_MediaDelete( p_vlm, p_vlm->media[0], NULL );
zorglub's avatar
zorglub committed
159
    FREENULL( p_vlm->media );
160

zorglub's avatar
zorglub committed
161 162
    while( p_vlm->i_schedule ) vlm_ScheduleDelete( p_vlm,
                                                   p_vlm->schedule[0], NULL );
zorglub's avatar
zorglub committed
163
    FREENULL( p_vlm->schedule );
164

zorglub's avatar
zorglub committed
165 166
    vlc_object_detach( p_vlm );
    vlc_object_destroy( p_vlm );
167 168 169 170 171 172
    vlc_mutex_unlock( lockval.p_address );
}

/*****************************************************************************
 * vlm_ExecuteCommand:
 *****************************************************************************/
173
int vlm_ExecuteCommand( vlm_t *p_vlm, const char *psz_command,
zorglub's avatar
zorglub committed
174
                        vlm_message_t **pp_message)
175
{
zorglub's avatar
zorglub committed
176
    int i_result;
177

zorglub's avatar
zorglub committed
178 179 180
    vlc_mutex_lock( &p_vlm->lock );
    i_result = ExecuteCommand( p_vlm, psz_command, pp_message );
    vlc_mutex_unlock( &p_vlm->lock );
181

zorglub's avatar
zorglub committed
182
    return i_result;
183 184
}

185 186 187
/*****************************************************************************
 * vlm_Save:
 *****************************************************************************/
188
int vlm_Save( vlm_t *p_vlm, const char *psz_file )
189 190 191 192 193 194
{
    FILE *file;
    char *psz_save;

    if( !p_vlm || !psz_file ) return 1;

195
    file = utf8_fopen( psz_file, "wt" );
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
    if( file == NULL ) return 1;

    psz_save = Save( p_vlm );
    if( psz_save == NULL )
    {
        fclose( file );
        return 1;
    }
    fwrite( psz_save, strlen( psz_save ), 1, file );
    fclose( file );
    free( psz_save );

    return 0;
}

/*****************************************************************************
 * vlm_Load:
 *****************************************************************************/
214
int vlm_Load( vlm_t *p_vlm, const char *psz_file )
215
{
216
    stream_t *p_stream;
217 218 219 220 221
    int64_t i_size;
    char *psz_buffer;

    if( !p_vlm || !psz_file ) return 1;

222 223
    p_stream = stream_UrlNew( p_vlm, psz_file );
    if( p_stream == NULL ) return 1;
224

225
    if( stream_Seek( p_stream, 0 ) != 0 )
226
    {
227
        stream_Delete( p_stream );
228 229
        return 2;
    }
230

231 232
    i_size = stream_Size( p_stream );

233 234 235
    psz_buffer = malloc( i_size + 1 );
    if( !psz_buffer )
    {
236
        stream_Delete( p_stream );
237 238
        return 2;
    }
239 240

    stream_Read( p_stream, psz_buffer, i_size );
241
    psz_buffer[ i_size ] = '\0';
242 243 244

    stream_Delete( p_stream );

245 246 247 248 249 250
    if( Load( p_vlm, psz_buffer ) )
    {
        free( psz_buffer );
        return 3;
    }

251
    free( psz_buffer );
252 253 254 255

    return 0;
}

256
/*****************************************************************************
gbazin's avatar
gbazin committed
257
 * FindEndCommand
258
 *****************************************************************************/
259
static const char *FindEndCommand( const char *psz_sent )
260
{
dionoea's avatar
dionoea committed
261 262
    vlc_bool_t b_escape = VLC_FALSE;

gbazin's avatar
gbazin committed
263
    switch( *psz_sent )
264
    {
gbazin's avatar
gbazin committed
265 266
    case '\"':
        psz_sent++;
267 268
        while( ( *psz_sent != '\"' || b_escape == VLC_TRUE )
               && ( *psz_sent != '\0' ) )
gbazin's avatar
gbazin committed
269
        {
dionoea's avatar
dionoea committed
270
            if( *psz_sent == '\'' && b_escape == VLC_FALSE )
271
            {
gbazin's avatar
gbazin committed
272 273
                psz_sent = FindEndCommand( psz_sent );
                if( psz_sent == NULL ) return NULL;
274
            }
dionoea's avatar
dionoea committed
275 276 277 278
            else if( *psz_sent++ == '\\' && b_escape == VLC_FALSE )
                b_escape = VLC_TRUE;
            else
                b_escape = VLC_FALSE;
279
        }
gbazin's avatar
gbazin committed
280 281

        if( *psz_sent == '\"' )
282
        {
gbazin's avatar
gbazin committed
283 284 285
            psz_sent++;
            return psz_sent;
        }
286

gbazin's avatar
gbazin committed
287 288
        /* *psz_sent == '\0' -> number of " is incorrect */
        else return NULL;
289

gbazin's avatar
gbazin committed
290
        break;
291

gbazin's avatar
gbazin committed
292 293
    case '\'':
        psz_sent++;
294 295
        while( ( *psz_sent != '\'' || b_escape == VLC_TRUE )
                 && ( *psz_sent != '\0' ) )
296
        {
dionoea's avatar
dionoea committed
297
            if( *psz_sent == '\"' && b_escape == VLC_FALSE )
298
            {
gbazin's avatar
gbazin committed
299 300
                psz_sent = FindEndCommand( psz_sent );
                if( psz_sent == NULL ) return NULL;
301
            }
dionoea's avatar
dionoea committed
302 303 304 305
            else if( *psz_sent++ == '\\' && b_escape == VLC_FALSE )
                b_escape = VLC_TRUE;
            else
                b_escape = VLC_FALSE;
306 307
        }

gbazin's avatar
gbazin committed
308
        if( *psz_sent == '\'' )
309
        {
gbazin's avatar
gbazin committed
310 311 312
            psz_sent++;
            return psz_sent;
        }
313

gbazin's avatar
gbazin committed
314 315 316 317 318 319 320 321
        /* *psz_sent == '\0' -> number of " is incorrect */
        else return NULL;

        break;

    default: /* now we can look for spaces */
        while( ( *psz_sent != ' ' ) && ( *psz_sent != '\0' ) )
        {
dionoea's avatar
dionoea committed
322 323
            if( ( ( *psz_sent == '\'' ) || ( *psz_sent == '\"' ) )
                && b_escape == VLC_FALSE )
324
            {
gbazin's avatar
gbazin committed
325
                psz_sent = FindEndCommand( psz_sent );
326
                if( psz_sent == NULL ) return NULL;
327
            }
dionoea's avatar
dionoea committed
328 329 330 331 332
            else if( *psz_sent++ == '\\' && b_escape == VLC_FALSE )
                b_escape = VLC_TRUE;
            else
                b_escape = VLC_FALSE;

333
        }
gbazin's avatar
gbazin committed
334 335

        return psz_sent;
336 337 338
    }
}

gbazin's avatar
gbazin committed
339 340 341 342 343
/*****************************************************************************
 * ExecuteCommand: The main state machine
 *****************************************************************************
 * Execute a command which ends with '\0' (string)
 *****************************************************************************/
344
static int ExecuteCommand( vlm_t *p_vlm, const char *psz_command,
zorglub's avatar
zorglub committed
345
                           vlm_message_t **pp_message )
346 347
{
    int i_command = 0;
zorglub's avatar
zorglub committed
348
    char **ppsz_command = NULL;
349
    const char *psz_cmd = psz_command;
zorglub's avatar
zorglub committed
350
    vlm_message_t *p_message = NULL;
gbazin's avatar
gbazin committed
351
    int i, j;
352 353

    /* First, parse the line and cut it */
zorglub's avatar
zorglub committed
354
    while( *psz_cmd != '\0' )
355 356
    {

zorglub's avatar
zorglub committed
357
        if( *psz_cmd == ' ' || *psz_cmd == '\t' )
358
        {
zorglub's avatar
zorglub committed
359
            psz_cmd++;
360 361 362
        }
        else
        {
363
            const char *psz_temp;
dionoea's avatar
dionoea committed
364 365 366
            const char *psz_buf;
            char *psz_dst;
            vlc_bool_t b_escape = VLC_FALSE;
367 368
            int   i_temp;

369
            /* support for comments */
zorglub's avatar
zorglub committed
370
            if( i_command == 0 && *psz_cmd == '#')
371
            {
zorglub's avatar
zorglub committed
372
                p_message = vlm_MessageNew( "", NULL );
373 374 375
                goto success;
            }

zorglub's avatar
zorglub committed
376
            psz_temp = FindEndCommand( psz_cmd );
377

378 379 380 381 382
            if( psz_temp == NULL )
            {
                p_message = vlm_MessageNew( "Incomplete command", psz_cmd );
                goto error;
            }
383

zorglub's avatar
zorglub committed
384
            i_temp = psz_temp - psz_cmd;
385

zorglub's avatar
zorglub committed
386 387 388
            ppsz_command = realloc( ppsz_command, (i_command + 1) *
                                    sizeof(char*) );
            ppsz_command[ i_command ] = malloc( (i_temp + 1) * sizeof(char) );
dionoea's avatar
dionoea committed
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405

            /* unescape ", ' and \ ... and everything else */
            psz_buf = psz_cmd;
            psz_dst = ppsz_command[ i_command ];
            while( i_temp-- )
            {
                if( *psz_buf == '\\' && b_escape == VLC_FALSE )
                    b_escape = VLC_TRUE;
                else
                {
                    b_escape = VLC_FALSE;
                    *psz_dst = *psz_buf;
                    psz_dst++;
                }
                psz_buf++;
            }
            *psz_dst = '\0';
406 407

            i_command++;
408

zorglub's avatar
zorglub committed
409
            psz_cmd = psz_temp;
410 411 412
        }
    }

gbazin's avatar
gbazin committed
413 414 415
    /*
     * And then Interpret it
     */
416 417 418

    if( i_command == 0 )
    {
zorglub's avatar
zorglub committed
419
        p_message = vlm_MessageNew( "", NULL );
gbazin's avatar
gbazin committed
420
        goto success;
421 422
    }

423
    if( !strcmp(ppsz_command[0], "new") )
424
    {
gbazin's avatar
gbazin committed
425
        int i_type;
426

gbazin's avatar
gbazin committed
427 428
        /* Check the number of arguments */
        if( i_command < 3 ) goto syntax_error;
429

gbazin's avatar
gbazin committed
430
        /* Get type */
431
        if( !strcmp(ppsz_command[2], "vod") )
gbazin's avatar
gbazin committed
432 433 434
        {
            i_type = VOD_TYPE;
        }
435
        else if( !strcmp(ppsz_command[2], "broadcast") )
gbazin's avatar
gbazin committed
436 437 438
        {
            i_type = BROADCAST_TYPE;
        }
439
        else if( !strcmp(ppsz_command[2], "schedule") )
gbazin's avatar
gbazin committed
440 441 442 443 444
        {
            i_type = SCHEDULE_TYPE;
        }
        else
        {
445 446 447
            p_message =
                vlm_MessageNew( "new", "%s: Choose between vod, "
                                "broadcast or schedule", ppsz_command[1] );
gbazin's avatar
gbazin committed
448 449
            goto error;
        }
450

gbazin's avatar
gbazin committed
451
        /* Check for forbidden media names */
452 453 454
        if( !strcmp(ppsz_command[1], "all") ||
            !strcmp(ppsz_command[1], "media") ||
            !strcmp(ppsz_command[1], "schedule") )
gbazin's avatar
gbazin committed
455
        {
zorglub's avatar
zorglub committed
456
            p_message = vlm_MessageNew( "new", "\"all\", \"media\" and "
457
                                        "\"schedule\" are reserved names" );
gbazin's avatar
gbazin committed
458 459
            goto error;
        }
460

gbazin's avatar
gbazin committed
461
        /* Check the name is not already in use */
zorglub's avatar
zorglub committed
462 463
        if( vlm_ScheduleSearch( p_vlm, ppsz_command[1] ) ||
            vlm_MediaSearch( p_vlm, ppsz_command[1] ) )
gbazin's avatar
gbazin committed
464
        {
zorglub's avatar
zorglub committed
465 466
            p_message = vlm_MessageNew( "new", "%s: Name already in use",
                                        ppsz_command[1] );
gbazin's avatar
gbazin committed
467 468
            goto error;
        }
469

gbazin's avatar
gbazin committed
470 471 472
        /* Schedule */
        if( i_type == SCHEDULE_TYPE )
        {
zorglub's avatar
zorglub committed
473 474 475
            vlm_schedule_t *p_schedule;
            p_schedule = vlm_ScheduleNew( p_vlm, ppsz_command[1] );
            if( !p_schedule )
476
            {
zorglub's avatar
zorglub committed
477
                p_message = vlm_MessageNew( "new", "could not create schedule" );
gbazin's avatar
gbazin committed
478
                goto error;
479
            }
gbazin's avatar
gbazin committed
480
        }
481

gbazin's avatar
gbazin committed
482 483 484
        /* Media */
        else
        {
zorglub's avatar
zorglub committed
485 486 487
            vlm_media_t *p_media;
            p_media = vlm_MediaNew( p_vlm, ppsz_command[1], i_type );
            if( !p_media )
488
            {
zorglub's avatar
zorglub committed
489
                p_message = vlm_MessageNew( "new", "could not create media" );
gbazin's avatar
gbazin committed
490
                goto error;
491 492
            }
        }
gbazin's avatar
gbazin committed
493 494

        if( i_command <= 3 )
495
        {
zorglub's avatar
zorglub committed
496
            p_message = vlm_MessageNew( "new", NULL );
gbazin's avatar
gbazin committed
497
            goto success;
498
        }
gbazin's avatar
gbazin committed
499 500 501 502

        /* Properties will be dealt with later on */
    }

503
    else if( !strcmp(ppsz_command[0], "setup") )
gbazin's avatar
gbazin committed
504 505 506 507
    {
        if( i_command < 2 ) goto syntax_error;

        /* Properties will be dealt with later on */
508
    }
zorglub's avatar
zorglub committed
509

510
    else if( !strcmp(ppsz_command[0], "del") )
511
    {
zorglub's avatar
zorglub committed
512 513
        vlm_media_t *p_media;
        vlm_schedule_t *p_schedule;
514

gbazin's avatar
gbazin committed
515
        if( i_command < 2 ) goto syntax_error;
516

zorglub's avatar
zorglub committed
517 518
        p_media = vlm_MediaSearch( p_vlm, ppsz_command[1] );
        p_schedule = vlm_ScheduleSearch( p_vlm, ppsz_command[1] );
519

zorglub's avatar
zorglub committed
520
        if( p_schedule != NULL )
gbazin's avatar
gbazin committed
521
        {
zorglub's avatar
zorglub committed
522
            vlm_ScheduleDelete( p_vlm, p_schedule, NULL );
gbazin's avatar
gbazin committed
523
        }
zorglub's avatar
zorglub committed
524
        else if( p_media != NULL )
gbazin's avatar
gbazin committed
525
        {
zorglub's avatar
zorglub committed
526
            vlm_MediaDelete( p_vlm, p_media, NULL );
gbazin's avatar
gbazin committed
527
        }
528
        else if( !strcmp(ppsz_command[1], "media") )
gbazin's avatar
gbazin committed
529
        {
zorglub's avatar
zorglub committed
530 531
            while( p_vlm->i_media ) vlm_MediaDelete( p_vlm, p_vlm->media[0],
                                                     NULL );
gbazin's avatar
gbazin committed
532
        }
533
        else if( !strcmp(ppsz_command[1], "schedule") )
gbazin's avatar
gbazin committed
534
        {
zorglub's avatar
zorglub committed
535 536
            while( p_vlm->i_schedule )
                vlm_ScheduleDelete( p_vlm, p_vlm->schedule[0], NULL );
gbazin's avatar
gbazin committed
537
        }
538
        else if( !strcmp(ppsz_command[1], "all") )
gbazin's avatar
gbazin committed
539
        {
zorglub's avatar
zorglub committed
540 541
            while( p_vlm->i_media ) vlm_MediaDelete( p_vlm, p_vlm->media[0],
                                                     NULL );
gbazin's avatar
gbazin committed
542

zorglub's avatar
zorglub committed
543 544
            while( p_vlm->i_schedule )
                vlm_ScheduleDelete( p_vlm, p_vlm->schedule[0], NULL );
545 546 547
        }
        else
        {
zorglub's avatar
zorglub committed
548 549
            p_message = vlm_MessageNew( "del", "%s: media unknown",
                                      ppsz_command[1] );
gbazin's avatar
gbazin committed
550
            goto error;
551
        }
gbazin's avatar
gbazin committed
552

zorglub's avatar
zorglub committed
553
        p_message = vlm_MessageNew( "del", NULL );
gbazin's avatar
gbazin committed
554
        goto success;
555
    }
gbazin's avatar
gbazin committed
556

557
    else if( !strcmp(ppsz_command[0], "show") )
558
    {
zorglub's avatar
zorglub committed
559 560
        vlm_media_t *p_media;
        vlm_schedule_t *p_schedule;
gbazin's avatar
gbazin committed
561

562 563
        if( i_command == 1 )
        {
zorglub's avatar
zorglub committed
564
            p_message = vlm_Show( p_vlm, NULL, NULL, NULL );
gbazin's avatar
gbazin committed
565
            goto success;
566
        }
gbazin's avatar
gbazin committed
567
        else if( i_command > 2 ) goto syntax_error;
568

zorglub's avatar
zorglub committed
569 570
        p_media = vlm_MediaSearch( p_vlm, ppsz_command[1] );
        p_schedule = vlm_ScheduleSearch( p_vlm, ppsz_command[1] );
571

zorglub's avatar
zorglub committed
572
        if( p_schedule != NULL )
573
        {
zorglub's avatar
zorglub committed
574
            p_message = vlm_Show( p_vlm, NULL, p_schedule, NULL );
575
        }
zorglub's avatar
zorglub committed
576
        else if( p_media != NULL )
577
        {
zorglub's avatar
zorglub committed
578
            p_message = vlm_Show( p_vlm, p_media, NULL, NULL );
579 580 581
        }
        else
        {
zorglub's avatar
zorglub committed
582
            p_message = vlm_Show( p_vlm, NULL, NULL, ppsz_command[1] );
583
        }
gbazin's avatar
gbazin committed
584 585

        goto success;
586 587
    }

588
    else if( !strcmp(ppsz_command[0], "help") )
gbazin's avatar
gbazin committed
589 590
    {
        if( i_command != 1 ) goto syntax_error;
591

zorglub's avatar
zorglub committed
592
        p_message = vlm_Help( p_vlm, NULL );
gbazin's avatar
gbazin committed
593 594
        goto success;
    }
595

596
    else if( !strcmp(ppsz_command[0], "control") )
gbazin's avatar
gbazin committed
597
    {
zorglub's avatar
zorglub committed
598
        vlm_media_t *p_media;
599

gbazin's avatar
gbazin committed
600
        if( i_command < 3 ) goto syntax_error;
601

zorglub's avatar
zorglub committed
602
        if( !(p_media = vlm_MediaSearch( p_vlm, ppsz_command[1] ) ) )
603
        {
zorglub's avatar
zorglub committed
604 605
            p_message = vlm_MessageNew( "control", "%s: media unknown",
                                      ppsz_command[1] );
gbazin's avatar
gbazin committed
606
            goto error;
607
        }
gbazin's avatar
gbazin committed
608
        else
609
        {
gbazin's avatar
gbazin committed
610 611
            char *psz_command, *psz_arg = 0, *psz_instance = 0;
            int i_index = 2;
612

613 614 615 616
            if( strcmp( ppsz_command[2], "play" ) &&
                strcmp( ppsz_command[2], "stop" ) &&
                strcmp( ppsz_command[2], "pause" ) &&
                strcmp( ppsz_command[2], "seek" ) )
617
            {
gbazin's avatar
gbazin committed
618
                i_index++;
zorglub's avatar
zorglub committed
619
                psz_instance = ppsz_command[2];
gbazin's avatar
gbazin committed
620 621

                if( i_command < 4 ) goto syntax_error;
622 623
            }

zorglub's avatar
zorglub committed
624
            psz_command = ppsz_command[i_index];
625

zorglub's avatar
zorglub committed
626
            if( i_command >= i_index + 2 ) psz_arg = ppsz_command[i_index + 1];
gbazin's avatar
gbazin committed
627

zorglub's avatar
zorglub committed
628 629 630
            vlm_MediaControl( p_vlm, p_media, psz_instance, psz_command,
                             psz_arg );
            p_message = vlm_MessageNew( "control", NULL );
gbazin's avatar
gbazin committed
631
            goto success;
632 633
        }
    }
gbazin's avatar
gbazin committed
634

635
    else if( !strcmp(ppsz_command[0], "save") )
636
    {
gbazin's avatar
gbazin committed
637
        if( i_command != 2 ) goto syntax_error;
638

639
        if( vlm_Save( p_vlm, ppsz_command[1] ) )
gbazin's avatar
gbazin committed
640
        {
zorglub's avatar
zorglub committed
641
            p_message = vlm_MessageNew( "save", "Unable to save to file" );
gbazin's avatar
gbazin committed
642
            goto error;
643 644 645
        }
        else
        {
zorglub's avatar
zorglub committed
646
            p_message = vlm_MessageNew( "save", NULL );
gbazin's avatar
gbazin committed
647
            goto success;
648 649
        }
    }
gbazin's avatar
gbazin committed
650

651 652 653 654 655 656 657 658 659 660 661 662
    else if( !strcmp(ppsz_command[0], "export" ) )
    {
        char *psz_buf;

        if( i_command != 1 ) goto syntax_error;

        p_message = vlm_MessageNew( "export", psz_buf = Save( p_vlm ) );
        free( psz_buf );

        goto success;
    }

663
    else if( !strcmp(ppsz_command[0], "load") )
664
    {
gbazin's avatar
gbazin committed
665
        if( i_command != 2 ) goto syntax_error;
666

667
        switch( vlm_Load( p_vlm, ppsz_command[1] ) )
gbazin's avatar
gbazin committed
668
        {
669 670 671 672
            case 0:
                p_message = vlm_MessageNew( "load", NULL );
                goto success;
            case 2:
673
                p_message = vlm_MessageNew( "load", "Read file error" );
gbazin's avatar
gbazin committed
674
                goto error;
675 676
            case 3:
                p_message =
677
                    vlm_MessageNew( "load", "Error while loading file" );
678 679 680 681 682
                goto error;
            default:
                p_message =
                    vlm_MessageNew( "load", "Unable to load from file" );
                goto error;
gbazin's avatar
gbazin committed
683 684 685 686 687
        }
    }

    else
    {
zorglub's avatar
zorglub committed
688
        p_message = vlm_MessageNew( ppsz_command[0], "Unknown command" );
gbazin's avatar
gbazin committed
689 690 691 692
        goto error;
    }

    /* Common code between "new" and "setup" */
693 694
    if( !strcmp(ppsz_command[0], "new") ||
        !strcmp(ppsz_command[0], "setup") )
gbazin's avatar
gbazin committed
695
    {
696
        int i_command_start = strcmp(ppsz_command[0], "new") ? 2 : 3;
zorglub's avatar
zorglub committed
697 698
        vlm_media_t *p_media;
        vlm_schedule_t *p_schedule;
gbazin's avatar
gbazin committed
699 700 701

        if( i_command < i_command_start ) goto syntax_error;

zorglub's avatar
zorglub committed
702 703
        p_media = vlm_MediaSearch( p_vlm, ppsz_command[1] );
        p_schedule = vlm_ScheduleSearch( p_vlm, ppsz_command[1] );
gbazin's avatar
gbazin committed
704

zorglub's avatar
zorglub committed
705
        if( !p_media && !p_schedule )
gbazin's avatar
gbazin committed
706
        {
zorglub's avatar
zorglub committed
707 708
            p_message = vlm_MessageNew( ppsz_command[0], "%s unknown",
                                        ppsz_command[1] );
gbazin's avatar
gbazin committed
709 710 711
            goto error;
        }

zorglub's avatar
zorglub committed
712
        if( p_schedule != NULL )
gbazin's avatar
gbazin committed
713 714 715
        {
            for( i = i_command_start ; i < i_command ; i++ )
            {
716 717
                if( !strcmp( ppsz_command[i], "enabled" ) ||
                    !strcmp( ppsz_command[i], "disabled" ) )
gbazin's avatar
gbazin committed
718
                {
zorglub's avatar
zorglub committed
719
                    vlm_ScheduleSetup( p_schedule, ppsz_command[i], NULL );
gbazin's avatar
gbazin committed
720
                }
721

zorglub's avatar
zorglub committed
722
                /* Beware: everything behind append is considered as
gbazin's avatar
gbazin committed
723
                 * command line */
724
                else if( !strcmp( ppsz_command[i], "append" ) )
725
                {
gbazin's avatar
gbazin committed
726 727 728
                    if( ++i >= i_command ) break;

                    for( j = i + 1; j < i_command; j++ )
729
                    {
zorglub's avatar
zorglub committed
730 731 732 733 734
                        ppsz_command[i] =
                            realloc( ppsz_command[i], strlen(ppsz_command[i]) +
                                     strlen(ppsz_command[j]) + 1 + 1 );
                        strcat( ppsz_command[i], " " );
                        strcat( ppsz_command[i], ppsz_command[j] );
735
                    }
gbazin's avatar
gbazin committed
736

zorglub's avatar
zorglub committed
737 738
                    vlm_ScheduleSetup( p_schedule, ppsz_command[i - 1],
                                       ppsz_command[i] );
gbazin's avatar
gbazin committed
739
                    break;
740 741 742
                }
                else
                {
743
                    if( i + 1 >= i_command && !strcmp(ppsz_command[0], "new") )
gbazin's avatar
gbazin committed
744
                    {
zorglub's avatar
zorglub committed
745
                        vlm_ScheduleDelete( p_vlm, p_schedule, NULL );
746 747 748
                        p_message =
                            vlm_MessageNew( ppsz_command[0],
                                            "Wrong properties syntax" );