engine.c 23.6 KB
Newer Older
1
2
3
4
/*****************************************************************************
 * engine.c : Run the playlist and handle its control
 *****************************************************************************
 * Copyright (C) 1999-2004 the VideoLAN team
dionoea's avatar
2nd try    
dionoea committed
5
 * $Id$
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * Authors: Samuel Hocevar <sam@zoy.org>
 *          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.
 *****************************************************************************/
24

25
26
27
28
29
30
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/sout.h>
#include <vlc/input.h>
#include "vlc_playlist.h"
#include "vlc_interaction.h"
31
#include "playlist_internal.h"
32
33
34
35
36
37

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
static void VariablesInit( playlist_t *p_playlist );

zorglub's avatar
zorglub committed
38
39
40
41
static int RandomCallback( vlc_object_t *p_this, char const *psz_cmd,
                           vlc_value_t oldval, vlc_value_t newval, void *a )
{
    ((playlist_t*)p_this)->b_reset_currently_playing = VLC_TRUE;
42
    playlist_Signal( ((playlist_t*)p_this) );
zorglub's avatar
zorglub committed
43
44
45
    return VLC_SUCCESS;
}

46
47
48
49
50
51
52
53
54
55
/**
 * Create playlist
 *
 * Create a playlist structure.
 * \param p_parent the vlc object that is to be the parent of this playlist
 * \return a pointer to the created playlist, or NULL on error
 */
playlist_t * playlist_Create( vlc_object_t *p_parent )
{
    playlist_t *p_playlist;
56
    int i_tree;
57
58
59
60
61
62
63
64

    /* Allocate structure */
    p_playlist = vlc_object_create( p_parent, VLC_OBJECT_PLAYLIST );
    if( !p_playlist )
    {
        msg_Err( p_parent, "out of memory" );
        return NULL;
    }
65
    p_parent->p_libvlc->p_playlist = p_playlist;
66
67
68
69
70
71
72
73
74

    VariablesInit( p_playlist );

    /* Initialise data structures */
    vlc_mutex_init( p_playlist, &p_playlist->gc_lock );
    p_playlist->i_last_playlist_id = 0;
    p_playlist->i_last_input_id = 0;
    p_playlist->p_input = NULL;

75
76
    p_playlist->gc_date = 0;
    p_playlist->b_cant_sleep = VLC_FALSE;
77

zorglub's avatar
zorglub committed
78
79
80
81
    ARRAY_INIT( p_playlist->items );
    ARRAY_INIT( p_playlist->all_items );
    ARRAY_INIT( p_playlist->input_items );
    ARRAY_INIT( p_playlist->current );
82

zorglub's avatar
zorglub committed
83
84
    p_playlist->i_current_index = 0;
    p_playlist->b_reset_currently_playing = VLC_TRUE;
85
    p_playlist->last_rebuild_date = 0;
zorglub's avatar
zorglub committed
86

87
88
89
90
    i_tree = var_CreateGetBool( p_playlist, "playlist-tree" );
    p_playlist->b_always_tree = (i_tree == 1);
    p_playlist->b_never_tree = (i_tree == 2);

91
92
    p_playlist->b_doing_ml = VLC_FALSE;

93
94
95
96
97
98
99
100
    p_playlist->p_root_category = playlist_NodeCreate( p_playlist, NULL, NULL);
    p_playlist->p_root_onelevel = playlist_NodeCreate( p_playlist, NULL, NULL);

    /* Create playlist and media library */
    p_playlist->p_local_category = playlist_NodeCreate( p_playlist,
                                 _( "Playlist" ),p_playlist->p_root_category );
    p_playlist->p_local_onelevel =  playlist_NodeCreate( p_playlist,
                                _( "Playlist" ), p_playlist->p_root_onelevel );
101
102
103
    p_playlist->p_local_category->i_flags |= PLAYLIST_RO_FLAG;
    p_playlist->p_local_onelevel->i_flags |= PLAYLIST_RO_FLAG;

104
    /* Link the nodes together. Todo: actually create them from the same input*/
105
106
    p_playlist->p_local_onelevel->p_input->i_id =
        p_playlist->p_local_category->p_input->i_id;
107
108
109
110
111
112
113
114
115
116
117

    if( config_GetInt( p_playlist, "media-library") )
    {
        p_playlist->p_ml_category =   playlist_NodeCreate( p_playlist,
                           _( "Media Library" ), p_playlist->p_root_category );
        p_playlist->p_ml_onelevel =  playlist_NodeCreate( p_playlist,
                           _( "Media Library" ), p_playlist->p_root_onelevel );
        p_playlist->p_ml_category->i_flags |= PLAYLIST_RO_FLAG;
        p_playlist->p_ml_onelevel->i_flags |= PLAYLIST_RO_FLAG;
        p_playlist->p_ml_onelevel->p_input->i_id =
             p_playlist->p_ml_category->p_input->i_id;
118

119
120
121
122
123
    }
    else
    {
        p_playlist->p_ml_category = p_playlist->p_ml_onelevel = NULL;
    }
124
125
126

    /* Initial status */
    p_playlist->status.p_item = NULL;
127
    p_playlist->status.p_node = p_playlist->p_local_onelevel;
128
129
130
131
132
133
134
    p_playlist->request.b_request = VLC_FALSE;
    p_playlist->status.i_status = PLAYLIST_STOPPED;

    p_playlist->i_sort = SORT_ID;
    p_playlist->i_order = ORDER_NORMAL;

    vlc_object_attach( p_playlist, p_parent );
135
136

    playlist_MLLoad( p_playlist );
137
138
139
140
141
142
143
144
145
146
    return p_playlist;
}

void playlist_Destroy( playlist_t *p_playlist )
{
    while( p_playlist->i_sds )
    {
        playlist_ServicesDiscoveryRemove( p_playlist,
                                          p_playlist->pp_sds[0]->psz_module );
    }
147
148
149

    playlist_MLDump( p_playlist );

150
    vlc_thread_join( p_playlist->p_preparse );
151
    vlc_thread_join( p_playlist->p_fetcher );
152
153
154
    vlc_thread_join( p_playlist );

    vlc_object_detach( p_playlist->p_preparse );
155
    vlc_object_detach( p_playlist->p_fetcher );
156
157
158
159
160
161
162

    var_Destroy( p_playlist, "intf-change" );
    var_Destroy( p_playlist, "item-change" );
    var_Destroy( p_playlist, "playlist-current" );
    var_Destroy( p_playlist, "intf-popmenu" );
    var_Destroy( p_playlist, "intf-show" );
    var_Destroy( p_playlist, "play-and-stop" );
163
    var_Destroy( p_playlist, "play-and-exit" );
164
165
166
167
168
    var_Destroy( p_playlist, "random" );
    var_Destroy( p_playlist, "repeat" );
    var_Destroy( p_playlist, "loop" );
    var_Destroy( p_playlist, "activity" );

169
    PL_LOCK;
zorglub's avatar
zorglub committed
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
    /* Go through all items, and simply free everything without caring
     * about the tree structure. Do not decref, it will be done by doing
     * the same thing on the input items array */
    FOREACH_ARRAY( playlist_item_t *p_del, p_playlist->all_items )
        free( p_del->pp_children );
        free( p_del );
    FOREACH_END();
    ARRAY_RESET( p_playlist->all_items );

    FOREACH_ARRAY( input_item_t *p_del, p_playlist->input_items )
        input_ItemClean( p_del );
        free( p_del );
    FOREACH_END();
    ARRAY_RESET( p_playlist->input_items );

    ARRAY_RESET( p_playlist->items );
    ARRAY_RESET( p_playlist->current );

188
    PL_UNLOCK;
189
190
191
192
193
194

    if( p_playlist->p_stats )
        free( p_playlist->p_stats );

    vlc_mutex_destroy( &p_playlist->gc_lock );
    vlc_object_destroy( p_playlist->p_preparse );
195
    vlc_object_destroy( p_playlist->p_fetcher );
196
    vlc_object_detach( p_playlist );
197
198
199
    vlc_object_destroy( p_playlist );

}
200

201
/* Destroy remaining objects */
202
static void ObjectGarbageCollector( playlist_t *p_playlist )
203
204
205
{
    vlc_object_t *p_obj;

206
207
208
209
210
211
212
    if( mdate() - p_playlist->gc_date < 1000000 )
    {
        p_playlist->b_cant_sleep = VLC_TRUE;
        return;
    }
    else if( p_playlist->gc_date == 0 )
        return;
213

214
215
216
    vlc_mutex_lock( &p_playlist->gc_lock );
    while( ( p_obj = vlc_object_find( p_playlist, VLC_OBJECT_VOUT,
                                                  FIND_CHILD ) ) )
217
    {
218
219
220
221
222
223
224
225
226
        if( p_obj->p_parent != (vlc_object_t*)p_playlist )
        {
            vlc_object_release( p_obj );
            break;
        }
        msg_Dbg( p_playlist, "garbage collector destroying 1 vout" );
        vlc_object_detach( p_obj );
        vlc_object_release( p_obj );
        vout_Destroy( (vout_thread_t *)p_obj );
227
    }
228
229
    while( ( p_obj = vlc_object_find( p_playlist, VLC_OBJECT_SOUT,
                                                  FIND_CHILD ) ) )
230
    {
231
        if( p_obj->p_parent != (vlc_object_t*)p_playlist )
232
        {
233
234
            vlc_object_release( p_obj );
            break;
235
        }
236
237
        vlc_object_release( p_obj );
        sout_DeleteInstance( (sout_instance_t*)p_obj );
238
    }
239
240
    p_playlist->b_cant_sleep = VLC_FALSE;
    vlc_mutex_unlock( &p_playlist->gc_lock );
241
242
243
244
245
246
}

/** Main loop for the playlist */
void playlist_MainLoop( playlist_t *p_playlist )
{
    playlist_item_t *p_item = NULL;
247
    vlc_bool_t b_playexit = var_GetBool( p_playlist, "play-and-exit" );
248
    PL_LOCK;
249

250
251
    if( p_playlist->b_reset_currently_playing &&
        mdate() - p_playlist->last_rebuild_date > 30000 ) // 30 ms
252
    {
253
254
255
        ResetCurrentlyPlaying( p_playlist, var_GetBool( p_playlist, "random"),
                             p_playlist->status.p_item );
        p_playlist->last_rebuild_date = mdate();
256
    }
257

258
check_input:
259
260
261
    /* If there is an input, check that it doesn't need to die. */
    if( p_playlist->p_input )
    {
262
263
264
265
266
267
        if( p_playlist->request.b_request && !p_playlist->p_input->b_die )
        {
            PL_DEBUG( "incoming request - stopping current input" );
            input_StopThread( p_playlist->p_input );
        }

268
269
270
271
272
        /* This input is dead. Remove it ! */
        if( p_playlist->p_input->b_dead )
        {
            int i_activity;
            input_thread_t *p_input;
zorglub's avatar
zorglub committed
273
            PL_DEBUG( "dead input" );
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291

            p_input = p_playlist->p_input;
            p_playlist->p_input = NULL;

            /* Release the playlist lock, because we may get stuck
             * in input_DestroyThread() for some time. */
            PL_UNLOCK

            /* Destroy input */
            input_DestroyThread( p_input );

            /* Unlink current input
             * (_after_ input_DestroyThread for vout garbage collector) */
            vlc_object_detach( p_input );

            /* Destroy object */
            vlc_object_destroy( p_input );

292
293
294
295
            PL_LOCK;

            p_playlist->gc_date = mdate();
            p_playlist->b_cant_sleep = VLC_TRUE;
296
297
298
299

            if( p_playlist->status.p_item->i_flags
                & PLAYLIST_REMOVE_FLAG )
            {
zorglub's avatar
zorglub committed
300
301
                 PL_DEBUG( "%s was marked for deletion, deleting",
                                 PLI_NAME( p_playlist->status.p_item  ) );
302
                 playlist_ItemDelete( p_playlist->status.p_item );
303
304
                 if( p_playlist->request.p_item == p_playlist->status.p_item )
                     p_playlist->request.p_item = NULL;
305
306
307
308
309
310
                 p_playlist->status.p_item = NULL;
            }

            i_activity= var_GetInteger( p_playlist, "activity") ;
            var_SetInteger( p_playlist, "activity", i_activity -
                            DEFAULT_INPUT_ACTIVITY );
311
            goto check_input;
312
313
314
315
        }
        /* This input is dying, let it do */
        else if( p_playlist->p_input->b_die )
        {
zorglub's avatar
zorglub committed
316
            PL_DEBUG( "dying input" );
317
318
            msleep( 25000 ); // 25 ms
            goto check_input;
319
320
321
322
323
        }
        /* This input has finished, ask it to die ! */
        else if( p_playlist->p_input->b_error
                  || p_playlist->p_input->b_eof )
        {
zorglub's avatar
zorglub committed
324
            PL_DEBUG( "finished input" );
325
            input_StopThread( p_playlist->p_input );
326
327
            /* No need to wait here, we'll wait in the p_input->b_die case */
            goto check_input;
328
329
330
        }
        else if( p_playlist->p_input->i_state != INIT_S )
        {
zorglub's avatar
zorglub committed
331
            PL_UNLOCK;
332
333
            ObjectGarbageCollector( p_playlist );
            PL_LOCK;
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
        }
    }
    else
    {
        /* No input. Several cases
         *  - No request, running status -> start new item
         *  - No request, stopped status -> collect garbage
         *  - Request, running requested -> start new item
         *  - Request, stopped requested -> collect garbage
         */
         if( (!p_playlist->request.b_request &&
              p_playlist->status.i_status != PLAYLIST_STOPPED) ||
              ( p_playlist->request.b_request &&
                p_playlist->request.i_status != PLAYLIST_STOPPED ) )
         {
zorglub's avatar
zorglub committed
349
             msg_Dbg( p_playlist, "starting new item" );
350
351
352
353
354
             p_item = playlist_NextItem( p_playlist );

             if( p_item == NULL )
             {
                msg_Dbg( p_playlist, "nothing to play" );
355
356
357
                if( b_playexit == VLC_TRUE )
                {
                    msg_Info( p_playlist, "end of playlist, exiting" );
358
                    p_playlist->p_libvlc->b_die = VLC_TRUE;
359
                }
360
361
362
363
364
365
366
367
                p_playlist->status.i_status = PLAYLIST_STOPPED;
                PL_UNLOCK
                return;
             }
             playlist_PlayItem( p_playlist, p_item );
         }
         else
         {
368
369
370
371
372
373
374
375
            p_playlist->status.i_status = PLAYLIST_STOPPED;
            if( p_playlist->status.p_item &&
                p_playlist->status.p_item->i_flags & PLAYLIST_REMOVE_FLAG )
            {
                PL_DEBUG( "deleting item marked for deletion" );
                playlist_ItemDelete( p_playlist->status.p_item );
                p_playlist->status.p_item = NULL;
            }
376

377
378
379
380
381
            /* Collect garbage */
            PL_UNLOCK;
            ObjectGarbageCollector( p_playlist );
            PL_LOCK;
        }
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
    }
    PL_UNLOCK
}

/** Playlist dying last loop */
void playlist_LastLoop( playlist_t *p_playlist )
{
    vlc_object_t *p_obj;

    /* If there is an input, kill it */
    while( 1 )
    {
        PL_LOCK

        if( p_playlist->p_input == NULL )
        {
            PL_UNLOCK
            break;
        }

        if( p_playlist->p_input->b_dead )
        {
            input_thread_t *p_input;

            /* Unlink current input */
            p_input = p_playlist->p_input;
            p_playlist->p_input = NULL;
            PL_UNLOCK

            /* Destroy input */
            input_DestroyThread( p_input );
            /* Unlink current input (_after_ input_DestroyThread for vout
             * garbage collector)*/
            vlc_object_detach( p_input );

            /* Destroy object */
            vlc_object_destroy( p_input );
            continue;
        }
        else if( p_playlist->p_input->b_die )
        {
            /* This input is dying, leave it alone */
            ;
        }
        else if( p_playlist->p_input->b_error || p_playlist->p_input->b_eof )
        {
            input_StopThread( p_playlist->p_input );
            PL_UNLOCK
            continue;
        }
        else
        {
            p_playlist->p_input->b_eof = 1;
        }

        PL_UNLOCK

        msleep( INTF_IDLE_SLEEP );
    }

    /* close all remaining sout */
    while( ( p_obj = vlc_object_find( p_playlist,
                                      VLC_OBJECT_SOUT, FIND_CHILD ) ) )
    {
        vlc_object_release( p_obj );
        sout_DeleteInstance( (sout_instance_t*)p_obj );
    }

    /* close all remaining vout */
    while( ( p_obj = vlc_object_find( p_playlist,
                                      VLC_OBJECT_VOUT, FIND_CHILD ) ) )
    {
        vlc_object_detach( p_obj );
        vlc_object_release( p_obj );
        vout_Destroy( (vout_thread_t *)p_obj );
    }
}

/** Main loop for preparser queue */
void playlist_PreparseLoop( playlist_preparse_t *p_obj )
{
    playlist_t *p_playlist = (playlist_t *)p_obj->p_parent;
464
    input_item_t *p_current;
465
    int i_activity;
zorglub's avatar
zorglub committed
466
    uint32_t i_m, i_o;
467

468
    while( !p_playlist->b_die )
469
    {
470
471
472
473
474
475
476
477
478
479
480
481
        vlc_mutex_lock( &p_obj->object_lock );
        while( p_obj->i_waiting == 0 )
        {
            vlc_cond_wait( &p_obj->object_wait, &p_obj->object_lock );
            if( p_playlist->b_die )
            {
                vlc_mutex_unlock( &p_obj->object_lock );
                return;
            }
        }

        p_current = p_obj->pp_waiting[0];
482
483
        REMOVE_ELEM( p_obj->pp_waiting, p_obj->i_waiting, 0 );
        vlc_mutex_unlock( &p_obj->object_lock );
484

zorglub's avatar
zorglub committed
485
        PL_LOCK;
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
        if( p_current )
        {
            vlc_bool_t b_preparsed = VLC_FALSE;
            if( strncmp( p_current->psz_uri, "http:", 5 ) &&
                strncmp( p_current->psz_uri, "rtsp:", 5 ) &&
                strncmp( p_current->psz_uri, "udp:", 4 ) &&
                strncmp( p_current->psz_uri, "mms:", 4 ) &&
                strncmp( p_current->psz_uri, "cdda:", 4 ) &&
                strncmp( p_current->psz_uri, "dvd:", 4 ) &&
                strncmp( p_current->psz_uri, "v4l:", 4 ) &&
                strncmp( p_current->psz_uri, "dshow:", 6 ) )
            {
                b_preparsed = VLC_TRUE;
                stats_TimerStart( p_playlist, "Preparse run",
                                  STATS_TIMER_PREPARSE );
zorglub's avatar
zorglub committed
501
                PL_UNLOCK;
502
                input_Preparse( p_playlist, p_current );
zorglub's avatar
zorglub committed
503
                PL_LOCK;
504
505
                stats_TimerStop( p_playlist, STATS_TIMER_PREPARSE );
            }
zorglub's avatar
zorglub committed
506
            PL_UNLOCK;
507
508
            if( b_preparsed )
            {
zorglub's avatar
zorglub committed
509
510
                p_current->p_meta->i_status |= ITEM_PREPARSED;
                var_SetInteger( p_playlist, "item-change", p_current->i_id );
511
            }
512
            PL_LOCK;
513

zorglub's avatar
zorglub committed
514
            /* If we haven't retrieved enough meta, add to secondary queue
515
516
517
             * which will run the "meta fetchers".
             * This only checks for meta, not for art
             * \todo don't do this for things we won't get meta for, like vids
518
             */
519
            if( !input_MetaSatisfied( p_playlist, p_current, &i_m, &i_o ) )
zorglub's avatar
zorglub committed
520
521
            {
                preparse_item_t p;
522
                PL_DEBUG("need to fetch meta for %s", p_current->psz_name );
dionoea's avatar
dionoea committed
523
524
                p.p_item = p_current;
                p.b_fetch_art = VLC_FALSE;
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
                vlc_mutex_lock( &p_playlist->p_fetcher->object_lock );
                INSERT_ELEM( p_playlist->p_fetcher->p_waiting,
                             p_playlist->p_fetcher->i_waiting,
                             p_playlist->p_fetcher->i_waiting,
                             p );
                vlc_mutex_unlock( &p_playlist->p_fetcher->object_lock );
                vlc_cond_signal( &p_playlist->p_fetcher->object_wait );
            }
            /* We already have all needed meta, but we need art right now */
            else if( p_playlist->p_fetcher->i_art_policy == ALBUM_ART_ALL &&
                     EMPTY_STR( p_current->p_meta->psz_arturl ) )
            {
                preparse_item_t p;
                PL_DEBUG("meta ok for %s, need to fetch art",
                                                         p_current->psz_name );
                p.p_item = p_current;
                p.b_fetch_art = VLC_TRUE;
                vlc_mutex_lock( &p_playlist->p_fetcher->object_lock );
                INSERT_ELEM( p_playlist->p_fetcher->p_waiting,
                             p_playlist->p_fetcher->i_waiting,
                             p_playlist->p_fetcher->i_waiting,
dionoea's avatar
dionoea committed
546
                             p );
547
548
                vlc_mutex_unlock( &p_playlist->p_fetcher->object_lock );
                vlc_cond_signal( &p_playlist->p_fetcher->object_wait );
zorglub's avatar
zorglub committed
549
            }
550
            else
551
552
553
            {
                PL_DEBUG( "no fetch required for %s (art currently %s)",
                          p_current->psz_name, p_current->p_meta->psz_arturl );
zorglub's avatar
zorglub committed
554
                vlc_gc_decref( p_current );
555
            }
556
            PL_UNLOCK;
557
558
        }
        else
559
560
            PL_UNLOCK;

561
        vlc_mutex_lock( &p_obj->object_lock );
562
        i_activity = var_GetInteger( p_playlist, "activity" );
563
        if( i_activity < 0 ) i_activity = 0;
zorglub's avatar
zorglub committed
564
        vlc_mutex_unlock( &p_obj->object_lock );
565
        /* Sleep at least 1ms */
566
567
568
569
        msleep( (i_activity+1) * 1000 );
    }
}

570
/** Main loop for secondary preparser queue */
571
void playlist_FetcherLoop( playlist_fetcher_t *p_obj )
572
573
{
    playlist_t *p_playlist = (playlist_t *)p_obj->p_parent;
574
575
576
    vlc_bool_t b_fetch_art;
    input_item_t *p_item;
    int i_activity;
577

578
    while( !p_playlist->b_die )
579
    {
580
581
582
583
584
585
586
587
588
589
590
591
592
        vlc_mutex_lock( &p_obj->object_lock );
        while( p_obj->i_waiting == 0 )
        {
            vlc_cond_wait( &p_obj->object_wait, &p_obj->object_lock );
            if( p_playlist->b_die )
            {
                vlc_mutex_unlock( &p_obj->object_lock );
                return;
            }
        }

        b_fetch_art = p_obj->p_waiting->b_fetch_art;
        p_item = p_obj->p_waiting->p_item;
dionoea's avatar
dionoea committed
593
        REMOVE_ELEM( p_obj->p_waiting, p_obj->i_waiting, 0 );
594
        vlc_mutex_unlock( &p_obj->object_lock );
dionoea's avatar
dionoea committed
595
        if( p_item )
596
        {
zorglub's avatar
zorglub committed
597
598
599
600
            if( !b_fetch_art )
            {
                input_MetaFetch( p_playlist, p_item );
                p_item->p_meta->i_status |= ITEM_META_FETCHED;
601
602
                var_SetInteger( p_playlist, "item-change", p_item->i_id );
                /*  Fetch right now */
603
                if( p_playlist->p_fetcher->i_art_policy == ALBUM_ART_ALL )
604
605
606
607
608
                {
                    vlc_mutex_lock( &p_obj->object_lock );
                    preparse_item_t p;
                    p.p_item = p_item;
                    p.b_fetch_art = VLC_TRUE;
609
610
                    INSERT_ELEM( p_playlist->p_fetcher->p_waiting,
                                 p_playlist->p_fetcher->i_waiting,
611
                                 0, p );
612
                    PL_DEBUG("meta fetched for %s, get art", p_item->psz_name);
613
                    vlc_mutex_unlock( &p_obj->object_lock );
614
                    continue;
615
616
617
                }
                else
                    vlc_gc_decref( p_item );
zorglub's avatar
zorglub committed
618
619
            }
            else
dionoea's avatar
dionoea committed
620
            {
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
                int i_ret = input_ArtFind( p_playlist, p_item );
                if( i_ret == 1 )
                {
                    PL_DEBUG("downloading art for %s", p_item->psz_name );
                    if( !input_DownloadAndCacheArt( p_playlist, p_item ) )
                        p_item->p_meta->i_status |= ITEM_ART_NOTFOUND;
                    else
                        p_item->p_meta->i_status |= ITEM_ART_FETCHED;
                }
                else if( i_ret == 0 ) /* Was in cache */
                {
                    PL_DEBUG("found art for %s in cache", p_item->psz_name );
                    p_item->p_meta->i_status |= ITEM_ART_FETCHED;
                }
                else
                {
                    PL_DEBUG("art not found for %s", p_item->psz_name );
                    p_item->p_meta->i_status |= ITEM_ART_NOTFOUND;
                }
640
641
                vlc_gc_decref( p_item );
           }
642
        }
643
644
645
646
647
648
        vlc_mutex_lock( &p_obj->object_lock );
        i_activity = var_GetInteger( p_playlist, "activity" );
        if( i_activity < 0 ) i_activity = 0;
        vlc_mutex_unlock( &p_obj->object_lock );
        /* Sleep at least 1ms */
        msleep( (i_activity+1) * 1000 );
649
650
651
    }
}

652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
static void VariablesInit( playlist_t *p_playlist )
{
    vlc_value_t val;
    /* These variables control updates */
    var_Create( p_playlist, "intf-change", VLC_VAR_BOOL );
    val.b_bool = VLC_TRUE;
    var_Set( p_playlist, "intf-change", val );

    var_Create( p_playlist, "item-change", VLC_VAR_INTEGER );
    val.i_int = -1;
    var_Set( p_playlist, "item-change", val );

    var_Create( p_playlist, "item-deleted", VLC_VAR_INTEGER );
    val.i_int = -1;
    var_Set( p_playlist, "item-deleted", val );

    var_Create( p_playlist, "item-append", VLC_VAR_ADDRESS );

    var_Create( p_playlist, "playlist-current", VLC_VAR_INTEGER );
    val.i_int = -1;
    var_Set( p_playlist, "playlist-current", val );

    var_Create( p_playlist, "intf-popupmenu", VLC_VAR_BOOL );

    var_Create( p_playlist, "intf-show", VLC_VAR_BOOL );
    val.b_bool = VLC_TRUE;
    var_Set( p_playlist, "intf-show", val );

    var_Create( p_playlist, "activity", VLC_VAR_INTEGER );
    var_SetInteger( p_playlist, "activity", 0 );

    /* Variables to control playback */
    var_CreateGetBool( p_playlist, "play-and-stop" );
685
    var_CreateGetBool( p_playlist, "play-and-exit" );
686
687
688
    var_CreateGetBool( p_playlist, "random" );
    var_CreateGetBool( p_playlist, "repeat" );
    var_CreateGetBool( p_playlist, "loop" );
zorglub's avatar
zorglub committed
689
690

    var_AddCallback( p_playlist, "random", RandomCallback, NULL );
691
}