~ubuntu-branches/ubuntu/maverick/vlc/maverick

« back to all changes in this revision

Viewing changes to modules/misc/lua/libs/playlist.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-09-17 21:56:14 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20080917215614-tj0vx8xzd57e52t8
Tags: 0.9.2-1ubuntu1
* New Upstream Release, exception granted by
    - dktrkranz, norsetto, Hobbsee (via irc). LP: #270404

Changes done in ubuntu:

* add libxul-dev to build-depends
* make sure that vlc is build against libxul in configure. This doesn't
  change anything in the package, but makes it more robust if building
  in an 'unclean' chroot or when modifying the package.
* debian/control: make Vcs-* fields point to the motumedia branch
* add libx264-dev and libass-dev to build-depends
  LP: #210354, #199870
* actually enable libass support by passing --enable-libass to configure
* enable libdca: add libdca-dev to build depends and --enable-libdca
* install the x264 plugin.

Changes already in the pkg-multimedia branch in debian:

* don't install usr/share/vlc/mozilla in debian/mozilla-plugin-vlc.install  
* new upstream .desktop file now registers flash video mimetype LP: #261567
* add Xb-Npp-Applications to mozilla-plugin-vlc
* remove duplicate entries in debian/vlc-nox.install

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 * playlist.c
 
3
 *****************************************************************************
 
4
 * Copyright (C) 2007-2008 the VideoLAN team
 
5
 * $Id$
 
6
 *
 
7
 * Authors: Antoine Cellerier <dionoea at videolan tod 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 
22
 *****************************************************************************/
 
23
 
 
24
/*****************************************************************************
 
25
 * Preamble
 
26
 *****************************************************************************/
 
27
#ifndef  _GNU_SOURCE
 
28
#   define  _GNU_SOURCE
 
29
#endif
 
30
 
 
31
#ifdef HAVE_CONFIG_H
 
32
# include "config.h"
 
33
#endif
 
34
 
 
35
#include <vlc_common.h>
 
36
 
 
37
#include <vlc_interface.h>
 
38
#include <vlc_playlist.h>
 
39
 
 
40
#include <lua.h>        /* Low level lua C API */
 
41
#include <lauxlib.h>    /* Higher level C API */
 
42
 
 
43
#include "../vlc.h"
 
44
#include "../libs.h"
 
45
#include "playlist.h"
 
46
#include "variables.h"
 
47
 
 
48
/*****************************************************************************
 
49
 * Internal lua<->vlc utils
 
50
 *****************************************************************************/
 
51
playlist_t *vlclua_get_playlist_internal( lua_State *L )
 
52
{
 
53
    vlc_object_t *p_this = vlclua_get_this( L );
 
54
    return pl_Yield( p_this );
 
55
}
 
56
 
 
57
void vlclua_release_playlist_internal( playlist_t *p_playlist )
 
58
{
 
59
    vlc_object_release( p_playlist );
 
60
}
 
61
 
 
62
static int vlclua_playlist_prev( lua_State * L )
 
63
{
 
64
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
65
    playlist_Prev( p_playlist );
 
66
    vlclua_release_playlist_internal( p_playlist );
 
67
    return 0;
 
68
}
 
69
 
 
70
static int vlclua_playlist_next( lua_State * L )
 
71
{
 
72
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
73
    playlist_Next( p_playlist );
 
74
    vlclua_release_playlist_internal( p_playlist );
 
75
    return 0;
 
76
}
 
77
 
 
78
static int vlclua_playlist_skip( lua_State * L )
 
79
{
 
80
    int i_skip = luaL_checkint( L, 1 );
 
81
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
82
    playlist_Skip( p_playlist, i_skip );
 
83
    vlclua_release_playlist_internal( p_playlist );
 
84
    return 0;
 
85
}
 
86
 
 
87
static int vlclua_playlist_play( lua_State * L )
 
88
{
 
89
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
90
    vlc_object_lock( p_playlist );
 
91
    playlist_Play( p_playlist );
 
92
    vlc_object_unlock( p_playlist );
 
93
    vlclua_release_playlist_internal( p_playlist );
 
94
    return 0;
 
95
}
 
96
 
 
97
static int vlclua_playlist_pause( lua_State * L )
 
98
{
 
99
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
100
    playlist_Pause( p_playlist );
 
101
    vlclua_release_playlist_internal( p_playlist );
 
102
    return 0;
 
103
}
 
104
 
 
105
static int vlclua_playlist_stop( lua_State * L )
 
106
{
 
107
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
108
    playlist_Stop( p_playlist );
 
109
    vlclua_release_playlist_internal( p_playlist );
 
110
    return 0;
 
111
}
 
112
 
 
113
static int vlclua_playlist_clear( lua_State * L )
 
114
{
 
115
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
116
    playlist_Stop( p_playlist ); /* Isn't this already implied by Clear? */
 
117
    playlist_Clear( p_playlist, pl_Unlocked );
 
118
    vlclua_release_playlist_internal( p_playlist );
 
119
    return 0;
 
120
}
 
121
 
 
122
static int vlclua_playlist_repeat( lua_State * L )
 
123
{
 
124
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
125
    int i_ret = vlclua_var_toggle_or_set( L, p_playlist, "repeat" );
 
126
    vlclua_release_playlist_internal( p_playlist );
 
127
    return i_ret;
 
128
}
 
129
 
 
130
static int vlclua_playlist_loop( lua_State * L )
 
131
{
 
132
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
133
    int i_ret = vlclua_var_toggle_or_set( L, p_playlist, "loop" );
 
134
    vlclua_release_playlist_internal( p_playlist );
 
135
    return i_ret;
 
136
}
 
137
 
 
138
static int vlclua_playlist_random( lua_State * L )
 
139
{
 
140
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
141
    int i_ret = vlclua_var_toggle_or_set( L, p_playlist, "random" );
 
142
    vlclua_release_playlist_internal( p_playlist );
 
143
    return i_ret;
 
144
}
 
145
 
 
146
static int vlclua_playlist_goto( lua_State * L )
 
147
{
 
148
    int i_id = luaL_checkint( L, 1 );
 
149
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
150
    vlc_object_lock( p_playlist );
 
151
    int i_ret = playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
 
152
                                  true, NULL,
 
153
                                  playlist_ItemGetById( p_playlist, i_id,
 
154
                                                        true ) );
 
155
    vlc_object_unlock( p_playlist );
 
156
    vlclua_release_playlist_internal( p_playlist );
 
157
    return vlclua_push_ret( L, i_ret );
 
158
}
 
159
 
 
160
static int vlclua_playlist_add( lua_State *L )
 
161
{
 
162
    int i_count;
 
163
    vlc_object_t *p_this = vlclua_get_this( L );
 
164
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
165
    i_count = vlclua_playlist_add_internal( p_this, L, p_playlist,
 
166
                                            NULL, true );
 
167
    vlclua_release_playlist_internal( p_playlist );
 
168
    lua_pushinteger( L, i_count );
 
169
    return 1;
 
170
}
 
171
 
 
172
static int vlclua_playlist_enqueue( lua_State *L )
 
173
{
 
174
    int i_count;
 
175
    vlc_object_t *p_this = vlclua_get_this( L );
 
176
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
177
    i_count = vlclua_playlist_add_internal( p_this, L, p_playlist,
 
178
                                            NULL, false );
 
179
    vlclua_release_playlist_internal( p_playlist );
 
180
    lua_pushinteger( L, i_count );
 
181
    return 1;
 
182
}
 
183
 
 
184
static void push_playlist_item( lua_State *L, playlist_item_t *p_item );
 
185
static void push_playlist_item( lua_State *L, playlist_item_t *p_item )
 
186
{
 
187
    input_item_t *p_input = p_item->p_input;
 
188
    int i_flags = 0;
 
189
    i_flags = p_item->i_flags;
 
190
    lua_newtable( L );
 
191
    lua_pushinteger( L, p_item->i_id );
 
192
    lua_setfield( L, -2, "id" );
 
193
    lua_newtable( L );
 
194
#define CHECK_AND_SET_FLAG( name, label ) \
 
195
    if( i_flags & PLAYLIST_ ## name ## _FLAG ) \
 
196
    { \
 
197
        lua_pushboolean( L, 1 ); \
 
198
        lua_setfield( L, -2, #label ); \
 
199
    }
 
200
    CHECK_AND_SET_FLAG( SAVE, save )
 
201
    CHECK_AND_SET_FLAG( SKIP, skip )
 
202
    CHECK_AND_SET_FLAG( DBL, disabled )
 
203
    CHECK_AND_SET_FLAG( RO, ro )
 
204
    CHECK_AND_SET_FLAG( REMOVE, remove )
 
205
    CHECK_AND_SET_FLAG( EXPANDED, expanded )
 
206
#undef CHECK_AND_SET_FLAG
 
207
    lua_setfield( L, -2, "flags" );
 
208
    if( p_input )
 
209
    {
 
210
        lua_pushstring( L, p_input->psz_name );
 
211
        lua_setfield( L, -2, "name" );
 
212
        lua_pushstring( L, p_input->psz_uri );
 
213
        lua_setfield( L, -2, "path" );
 
214
        if( p_input->i_duration < 0 )
 
215
            lua_pushnumber( L, -1 );
 
216
        else
 
217
            lua_pushnumber( L, ((double)p_input->i_duration)*1e-6 );
 
218
        lua_setfield( L, -2, "duration" );
 
219
        lua_pushinteger( L, p_input->i_nb_played );
 
220
        lua_setfield( L, -2, "nb_played" );
 
221
        /* TODO: add (optional) info categories, meta, options, es */
 
222
    }
 
223
    if( p_item->i_children >= 0 )
 
224
    {
 
225
        int i;
 
226
        lua_createtable( L, p_item->i_children, 0 );
 
227
        for( i = 0; i < p_item->i_children; i++ )
 
228
        {
 
229
            push_playlist_item( L, p_item->pp_children[i] );
 
230
            lua_rawseti( L, -2, i+1 );
 
231
        }
 
232
        lua_setfield( L, -2, "children" );
 
233
    }
 
234
}
 
235
 
 
236
static int vlclua_playlist_get( lua_State *L )
 
237
{
 
238
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
239
    vlc_object_lock( p_playlist );
 
240
    int b_category = luaL_optboolean( L, 2, 1 ); /* Default to tree playlist (discared when 1st argument is a playlist_item's id) */
 
241
    playlist_item_t *p_item = NULL;
 
242
 
 
243
    if( lua_isnumber( L, 1 ) )
 
244
    {
 
245
        int i_id = lua_tointeger( L, 1 );
 
246
        p_item = playlist_ItemGetById( p_playlist, i_id, true );
 
247
        if( !p_item )
 
248
        {
 
249
            vlc_object_unlock( p_playlist );
 
250
            vlclua_release_playlist_internal( p_playlist );
 
251
            return 0; /* Should we return an error instead? */
 
252
        }
 
253
    }
 
254
    else if( lua_isstring( L, 1 ) )
 
255
    {
 
256
        const char *psz_what = lua_tostring( L, 1 );
 
257
        if( !strcasecmp( psz_what, "normal" )
 
258
         || !strcasecmp( psz_what, "playlist" ) )
 
259
            p_item = b_category ? p_playlist->p_local_category
 
260
                                : p_playlist->p_local_onelevel;
 
261
        else if( !strcasecmp( psz_what, "ml" )
 
262
              || !strcasecmp( psz_what, "media library" ) )
 
263
            p_item = b_category ? p_playlist->p_ml_category
 
264
                                : p_playlist->p_ml_onelevel;
 
265
        else if( !strcasecmp( psz_what, "root" ) )
 
266
            p_item = b_category ? p_playlist->p_root_category
 
267
                                : p_playlist->p_root_onelevel;
 
268
        else
 
269
        {
 
270
            int i;
 
271
            for( i = 0; i < p_playlist->i_sds; i++ )
 
272
            {
 
273
                if( !strcasecmp( psz_what,
 
274
                                 p_playlist->pp_sds[i]->p_sd->psz_module ) )
 
275
                {
 
276
                    p_item = b_category ? p_playlist->pp_sds[i]->p_cat
 
277
                                        : p_playlist->pp_sds[i]->p_one;
 
278
                    break;
 
279
                }
 
280
            }
 
281
            if( !p_item )
 
282
            {
 
283
                vlc_object_unlock( p_playlist );
 
284
                vlclua_release_playlist_internal( p_playlist );
 
285
                return 0; /* Should we return an error instead? */
 
286
            }
 
287
        }
 
288
    }
 
289
    else
 
290
    {
 
291
        p_item = b_category ? p_playlist->p_root_category
 
292
                            : p_playlist->p_root_onelevel;
 
293
    }
 
294
    push_playlist_item( L, p_item );
 
295
    vlc_object_unlock( p_playlist );
 
296
    vlclua_release_playlist_internal( p_playlist );
 
297
    return 1;
 
298
}
 
299
 
 
300
static int vlclua_playlist_search( lua_State *L )
 
301
{
 
302
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
303
    const char *psz_string = luaL_optstring( L, 1, "" );
 
304
    int b_category = luaL_optboolean( L, 2, 1 ); /* default to category */
 
305
    playlist_item_t *p_item = b_category ? p_playlist->p_root_category
 
306
                                         : p_playlist->p_root_onelevel;
 
307
    vlc_object_lock( p_playlist );
 
308
    playlist_LiveSearchUpdate( p_playlist, p_item, psz_string );
 
309
    vlc_object_unlock( p_playlist );
 
310
    push_playlist_item( L, p_item );
 
311
    vlclua_release_playlist_internal( p_playlist );
 
312
    return 1;
 
313
}
 
314
 
 
315
static int vlclua_playlist_current( lua_State *L )
 
316
{
 
317
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
318
    lua_pushinteger( L, var_GetInteger( p_playlist, "playlist-current" ) );
 
319
    vlclua_release_playlist_internal( p_playlist );
 
320
    return 1;
 
321
}
 
322
 
 
323
static int vlc_sort_key_from_string( const char *psz_name )
 
324
{
 
325
    static const struct
 
326
    {
 
327
        const char *psz_name;
 
328
        int i_key;
 
329
    } pp_keys[] =
 
330
        { { "id", SORT_ID },
 
331
          { "title", SORT_TITLE },
 
332
          { "title nodes first", SORT_TITLE_NODES_FIRST },
 
333
          { "artist", SORT_ARTIST },
 
334
          { "genre", SORT_GENRE },
 
335
          { "random", SORT_RANDOM },
 
336
          { "duration", SORT_DURATION },
 
337
          { "title numeric", SORT_TITLE_NUMERIC },
 
338
          { "album", SORT_ALBUM },
 
339
          { NULL, -1 } };
 
340
    int i;
 
341
    for( i = 0; pp_keys[i].psz_name; i++ )
 
342
    {
 
343
        if( !strcmp( psz_name, pp_keys[i].psz_name ) )
 
344
            return pp_keys[i].i_key;
 
345
    }
 
346
    return -1;
 
347
}
 
348
 
 
349
static int vlclua_playlist_sort( lua_State *L )
 
350
{
 
351
    /* allow setting the different sort keys */
 
352
    int i_mode = vlc_sort_key_from_string( luaL_checkstring( L, 1 ) );
 
353
    if( i_mode == -1 )
 
354
        return luaL_error( L, "Invalid search key." );
 
355
    int i_type = luaL_optboolean( L, 2, 0 ) ? ORDER_REVERSE : ORDER_NORMAL;
 
356
    int b_category = luaL_optboolean( L, 3, 1 ); /* default to category */
 
357
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
358
    vlc_object_lock( p_playlist );
 
359
    playlist_item_t *p_root = b_category ? p_playlist->p_local_category
 
360
                                         : p_playlist->p_local_onelevel;
 
361
    int i_ret = playlist_RecursiveNodeSort( p_playlist, p_root, i_mode,
 
362
                                            i_type );
 
363
    vlc_object_unlock( p_playlist );
 
364
    vlclua_release_playlist_internal( p_playlist );
 
365
    return vlclua_push_ret( L, i_ret );
 
366
}
 
367
 
 
368
/* FIXME: split this in 3 different functions? */
 
369
static int vlclua_playlist_status( lua_State *L )
 
370
{
 
371
    playlist_t *p_playlist = vlclua_get_playlist_internal( L );
 
372
    /*
 
373
    int i_count = 0;
 
374
    lua_settop( L, 0 );*/
 
375
    if( p_playlist->p_input )
 
376
    {
 
377
        /*char *psz_uri =
 
378
            input_item_GetURI( input_GetItem( p_playlist->p_input ) );
 
379
        lua_pushstring( L, psz_uri );
 
380
        free( psz_uri );
 
381
        lua_pushnumber( L, config_GetInt( p_intf, "volume" ) );*/
 
382
        vlc_object_lock( p_playlist );
 
383
        switch( p_playlist->status.i_status )
 
384
        {
 
385
            case PLAYLIST_STOPPED:
 
386
                lua_pushstring( L, "stopped" );
 
387
                break;
 
388
            case PLAYLIST_RUNNING:
 
389
                lua_pushstring( L, "playing" );
 
390
                break;
 
391
            case PLAYLIST_PAUSED:
 
392
                lua_pushstring( L, "paused" );
 
393
                break;
 
394
            default:
 
395
                lua_pushstring( L, "unknown" );
 
396
                break;
 
397
        }
 
398
        vlc_object_unlock( p_playlist );
 
399
        /*i_count += 3;*/
 
400
    }
 
401
    else
 
402
    {
 
403
        lua_pushstring( L, "stopped" );
 
404
    }
 
405
    vlclua_release_playlist_internal( p_playlist );
 
406
    return 1;
 
407
}
 
408
 
 
409
/*****************************************************************************
 
410
 *
 
411
 *****************************************************************************/
 
412
static const luaL_Reg vlclua_playlist_reg[] = {
 
413
    { "prev", vlclua_playlist_prev },
 
414
    { "next", vlclua_playlist_next },
 
415
    { "skip", vlclua_playlist_skip },
 
416
    { "play", vlclua_playlist_play },
 
417
    { "pause", vlclua_playlist_pause },
 
418
    { "stop", vlclua_playlist_stop },
 
419
    { "clear", vlclua_playlist_clear },
 
420
    { "repeat", vlclua_playlist_repeat },
 
421
    { "loop", vlclua_playlist_loop },
 
422
    { "random", vlclua_playlist_random },
 
423
    { "goto", vlclua_playlist_goto },
 
424
    { "add", vlclua_playlist_add },
 
425
    { "enqueue", vlclua_playlist_enqueue },
 
426
    { "get", vlclua_playlist_get },
 
427
    { "search", vlclua_playlist_search },
 
428
    { "current", vlclua_playlist_current },
 
429
    { "sort", vlclua_playlist_sort },
 
430
    { "status", vlclua_playlist_status },
 
431
    { NULL, NULL }
 
432
};
 
433
 
 
434
void luaopen_playlist( lua_State *L )
 
435
{
 
436
    lua_newtable( L );
 
437
    luaL_register( L, NULL, vlclua_playlist_reg );
 
438
    lua_setfield( L, -2, "playlist" );
 
439
}