]> git.sesse.net Git - vlc/blob - modules/control/http/rpn.c
rpn.c : vlm_cmd now adds a "vlm_value" variable
[vlc] / modules / control / http / rpn.c
1 /*****************************************************************************
2  * rpn.c : RPN evaluator for the HTTP Interface
3  *****************************************************************************
4  * Copyright (C) 2001-2006 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  *          Laurent Aimar <fenrir@via.ecp.fr>
9  *          Christophe Massiot <massiot@via.ecp.fr>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 #include "http.h"
27
28 static vlc_object_t *GetVLCObject( intf_thread_t *p_intf,
29                                    const char *psz_object,
30                                    vlc_bool_t *pb_need_release )
31 {
32     intf_sys_t    *p_sys = p_intf->p_sys;
33     int i_object_type = 0;
34     vlc_object_t *p_object = NULL;
35     *pb_need_release = VLC_FALSE;
36
37     if( !strcmp( psz_object, "VLC_OBJECT_ROOT" ) )
38         i_object_type = VLC_OBJECT_ROOT;
39     else if( !strcmp( psz_object, "VLC_OBJECT_VLC" ) )
40         p_object = VLC_OBJECT(p_intf->p_vlc);
41     else if( !strcmp( psz_object, "VLC_OBJECT_INTF" ) )
42         p_object = VLC_OBJECT(p_intf);
43     else if( !strcmp( psz_object, "VLC_OBJECT_PLAYLIST" ) )
44         p_object = VLC_OBJECT(p_sys->p_playlist);
45     else if( !strcmp( psz_object, "VLC_OBJECT_INPUT" ) )
46         p_object = VLC_OBJECT(p_sys->p_input);
47     else if( !strcmp( psz_object, "VLC_OBJECT_VOUT" ) )
48         i_object_type = VLC_OBJECT_VOUT;
49     else if( !strcmp( psz_object, "VLC_OBJECT_AOUT" ) )
50         i_object_type = VLC_OBJECT_AOUT;
51     else if( !strcmp( psz_object, "VLC_OBJECT_SOUT" ) )
52         i_object_type = VLC_OBJECT_SOUT;
53     else
54         msg_Warn( p_intf, "unknown object type (%s)", psz_object );
55
56     if( p_object == NULL && i_object_type )
57     {
58         *pb_need_release = VLC_TRUE;
59         p_object = vlc_object_find( p_intf, i_object_type, FIND_ANYWHERE );
60     }
61
62     return p_object;
63 }
64
65 void E_(SSInit)( rpn_stack_t *st )
66 {
67     st->i_stack = 0;
68 }
69
70 void E_(SSClean)( rpn_stack_t *st )
71 {
72     while( st->i_stack > 0 )
73     {
74         free( st->stack[--st->i_stack] );
75     }
76 }
77
78 void E_(SSPush)( rpn_stack_t *st, const char *s )
79 {
80     if( st->i_stack < STACK_MAX )
81     {
82         st->stack[st->i_stack++] = strdup( s );
83     }
84 }
85
86 char *E_(SSPop)( rpn_stack_t *st )
87 {
88     if( st->i_stack <= 0 )
89     {
90         return strdup( "" );
91     }
92     else
93     {
94         return st->stack[--st->i_stack];
95     }
96 }
97
98 int E_(SSPopN)( rpn_stack_t *st, mvar_t  *vars )
99 {
100     char *name;
101     char *value;
102
103     char *end;
104     int  i;
105
106     name = E_(SSPop)( st );
107     i = strtol( name, &end, 0 );
108     if( end == name )
109     {
110         value = E_(mvar_GetValue)( vars, name );
111         i = atoi( value );
112     }
113     free( name );
114
115     return( i );
116 }
117
118 void E_(SSPushN)( rpn_stack_t *st, int i )
119 {
120     char v[512];
121
122     sprintf( v, "%d", i );
123     E_(SSPush)( st, v );
124 }
125
126 void E_(EvaluateRPN)( intf_thread_t *p_intf, mvar_t  *vars,
127                       rpn_stack_t *st, char *exp )
128 {
129     intf_sys_t    *p_sys = p_intf->p_sys;
130
131     while( exp != NULL && *exp != '\0' )
132     {
133         char *p, *s;
134
135         /* skip space */
136         while( *exp == ' ' )
137         {
138             exp++;
139         }
140
141         if( *exp == '\'' )
142         {
143             /* extract string */
144             p = E_(FirstWord)( exp, exp );
145             E_(SSPush)( st, exp );
146             exp = p;
147             continue;
148         }
149
150         /* extract token */
151         p = E_(FirstWord)( exp, exp );
152         s = exp;
153         if( p == NULL )
154         {
155             exp += strlen( exp );
156         }
157         else
158         {
159             exp = p;
160         }
161
162         if( *s == '\0' )
163         {
164             break;
165         }
166
167         /* 1. Integer function */
168         if( !strcmp( s, "!" ) )
169         {
170             E_(SSPushN)( st, ~E_(SSPopN)( st, vars ) );
171         }
172         else if( !strcmp( s, "^" ) )
173         {
174             E_(SSPushN)( st, E_(SSPopN)( st, vars ) ^ E_(SSPopN)( st, vars ) );
175         }
176         else if( !strcmp( s, "&" ) )
177         {
178             E_(SSPushN)( st, E_(SSPopN)( st, vars ) & E_(SSPopN)( st, vars ) );
179         }
180         else if( !strcmp( s, "|" ) )
181         {
182             E_(SSPushN)( st, E_(SSPopN)( st, vars ) | E_(SSPopN)( st, vars ) );
183         }
184         else if( !strcmp( s, "+" ) )
185         {
186             E_(SSPushN)( st, E_(SSPopN)( st, vars ) + E_(SSPopN)( st, vars ) );
187         }
188         else if( !strcmp( s, "-" ) )
189         {
190             int j = E_(SSPopN)( st, vars );
191             int i = E_(SSPopN)( st, vars );
192             E_(SSPushN)( st, i - j );
193         }
194         else if( !strcmp( s, "*" ) )
195         {
196             E_(SSPushN)( st, E_(SSPopN)( st, vars ) * E_(SSPopN)( st, vars ) );
197         }
198         else if( !strcmp( s, "/" ) )
199         {
200             int i, j;
201
202             j = E_(SSPopN)( st, vars );
203             i = E_(SSPopN)( st, vars );
204
205             E_(SSPushN)( st, j != 0 ? i / j : 0 );
206         }
207         else if( !strcmp( s, "%" ) )
208         {
209             int i, j;
210
211             j = E_(SSPopN)( st, vars );
212             i = E_(SSPopN)( st, vars );
213
214             E_(SSPushN)( st, j != 0 ? i % j : 0 );
215         }
216         /* 2. integer tests */
217         else if( !strcmp( s, "=" ) )
218         {
219             E_(SSPushN)( st, E_(SSPopN)( st, vars ) == E_(SSPopN)( st, vars ) ? -1 : 0 );
220         }
221         else if( !strcmp( s, "!=" ) )
222         {
223             E_(SSPushN)( st, E_(SSPopN)( st, vars ) != E_(SSPopN)( st, vars ) ? -1 : 0 );
224         }
225         else if( !strcmp( s, "<" ) )
226         {
227             int j = E_(SSPopN)( st, vars );
228             int i = E_(SSPopN)( st, vars );
229
230             E_(SSPushN)( st, i < j ? -1 : 0 );
231         }
232         else if( !strcmp( s, ">" ) )
233         {
234             int j = E_(SSPopN)( st, vars );
235             int i = E_(SSPopN)( st, vars );
236
237             E_(SSPushN)( st, i > j ? -1 : 0 );
238         }
239         else if( !strcmp( s, "<=" ) )
240         {
241             int j = E_(SSPopN)( st, vars );
242             int i = E_(SSPopN)( st, vars );
243
244             E_(SSPushN)( st, i <= j ? -1 : 0 );
245         }
246         else if( !strcmp( s, ">=" ) )
247         {
248             int j = E_(SSPopN)( st, vars );
249             int i = E_(SSPopN)( st, vars );
250
251             E_(SSPushN)( st, i >= j ? -1 : 0 );
252         }
253         /* 3. string functions */
254         else if( !strcmp( s, "strcat" ) )
255         {
256             char *s2 = E_(SSPop)( st );
257             char *s1 = E_(SSPop)( st );
258             char *str = malloc( strlen( s1 ) + strlen( s2 ) + 1 );
259
260             strcpy( str, s1 );
261             strcat( str, s2 );
262
263             E_(SSPush)( st, str );
264             free( s1 );
265             free( s2 );
266             free( str );
267         }
268         else if( !strcmp( s, "strcmp" ) )
269         {
270             char *s2 = E_(SSPop)( st );
271             char *s1 = E_(SSPop)( st );
272
273             E_(SSPushN)( st, strcmp( s1, s2 ) );
274             free( s1 );
275             free( s2 );
276         }
277         else if( !strcmp( s, "strncmp" ) )
278         {
279             int n = E_(SSPopN)( st, vars );
280             char *s2 = E_(SSPop)( st );
281             char *s1 = E_(SSPop)( st );
282
283             E_(SSPushN)( st, strncmp( s1, s2 , n ) );
284             free( s1 );
285             free( s2 );
286         }
287         else if( !strcmp( s, "strsub" ) )
288         {
289             int n = E_(SSPopN)( st, vars );
290             int m = E_(SSPopN)( st, vars );
291             int i_len;
292             char *s = E_(SSPop)( st );
293             char *str;
294
295             if( n >= m )
296             {
297                 i_len = n - m + 1;
298             }
299             else
300             {
301                 i_len = 0;
302             }
303
304             str = malloc( i_len + 1 );
305
306             memcpy( str, s + m - 1, i_len );
307             str[ i_len ] = '\0';
308
309             E_(SSPush)( st, str );
310             free( s );
311             free( str );
312         }
313         else if( !strcmp( s, "strlen" ) )
314         {
315             char *str = E_(SSPop)( st );
316
317             E_(SSPushN)( st, strlen( str ) );
318             free( str );
319         }
320         else if( !strcmp( s, "str_replace" ) )
321         {
322             char *psz_to = E_(SSPop)( st );
323             char *psz_from = E_(SSPop)( st );
324             char *psz_in = E_(SSPop)( st );
325             char *psz_in_current = psz_in;
326             char *psz_out = malloc( strlen(psz_in) * strlen(psz_to) + 1 );
327             char *psz_out_current = psz_out;
328
329             while( (p = strstr( psz_in_current, psz_from )) != NULL )
330             {
331                 memcpy( psz_out_current, psz_in_current, p - psz_in_current );
332                 psz_out_current += p - psz_in_current;
333                 strcpy( psz_out_current, psz_to );
334                 psz_out_current += strlen(psz_to);
335                 psz_in_current = p + strlen(psz_from);
336             }
337             strcpy( psz_out_current, psz_in_current );
338             psz_out_current += strlen(psz_in_current);
339             *psz_out_current = '\0';
340
341             E_(SSPush)( st, psz_out );
342             free( psz_to );
343             free( psz_from );
344             free( psz_in );
345             free( psz_out );
346         }
347         else if( !strcmp( s, "url_extract" ) )
348         {
349             char *url = E_(mvar_GetValue)( vars, "url_value" );
350             char *name = E_(SSPop)( st );
351             char value[512];
352             char *tmp;
353
354             E_(ExtractURIValue)( url, name, value, 512 );
355             E_(DecodeEncodedURI)( value );
356             tmp = E_(FromUTF8)( p_intf, value );
357             E_(SSPush)( st, tmp );
358             free( tmp );
359             free( name );
360         }
361         else if( !strcmp( s, "url_encode" ) )
362         {
363             char *url = E_(SSPop)( st );
364             char *value;
365
366             value = E_(ToUTF8)( p_intf, url );
367             free( url );
368             url = value;
369             value = vlc_UrlEncode( url );
370             free( url );
371             E_(SSPush)( st, value );
372             free( value );
373         }
374         else if( !strcmp( s, "addslashes" ) )
375         {
376             char *psz_src = E_(SSPop)( st );
377             char *psz_dest;
378             char *str = psz_src;
379
380             p = psz_dest = malloc( strlen( str ) * 2 + 1 );
381
382             while( *str != '\0' )
383             {
384                 if( *str == '"' || *str == '\'' || *str == '\\' )
385                 {
386                     *p++ = '\\';
387                 }
388                 *p++ = *str;
389                 str++;
390             }
391             *p = '\0';
392
393             E_(SSPush)( st, psz_dest );
394             free( psz_src );
395             free( psz_dest );
396         }
397         else if( !strcmp( s, "stripslashes" ) )
398         {
399             char *psz_src = E_(SSPop)( st );
400             char *psz_dest;
401
402             p = psz_dest = strdup( psz_src );
403
404             while( *psz_src )
405             {
406                 if( *psz_src == '\\' && *(psz_src + 1) )
407                 {
408                     psz_src++;
409                 }
410                 *p++ = *psz_src++;
411             }
412             *p = '\0';
413
414             E_(SSPush)( st, psz_dest );
415             free( psz_src );
416             free( psz_dest );
417         }
418         else if( !strcmp( s, "htmlspecialchars" ) )
419         {
420             char *psz_src = E_(SSPop)( st );
421             char *psz_dest;
422             char *str = psz_src;
423
424             p = psz_dest = malloc( strlen( str ) * 6 + 1 );
425
426             while( *str != '\0' )
427             {
428                 if( *str == '&' )
429                 {
430                     strcpy( p, "&amp;" );
431                     p += 5;
432                 }
433                 else if( *str == '\"' )
434                 {
435                     strcpy( p, "&quot;" );
436                     p += 6;
437                 }
438                 else if( *str == '\'' )
439                 {
440                     strcpy( p, "&#039;" );
441                     p += 6;
442                 }
443                 else if( *str == '<' )
444                 {
445                     strcpy( p, "&lt;" );
446                     p += 4;
447                 }
448                 else if( *str == '>' )
449                 {
450                     strcpy( p, "&gt;" );
451                     p += 4;
452                 }
453                 else
454                 {
455                     *p++ = *str;
456                 }
457                 str++;
458             }
459             *p = '\0';
460
461             E_(SSPush)( st, psz_dest );
462             free( psz_src );
463             free( psz_dest );
464         }
465         else if( !strcmp( s, "realpath" ) )
466         {
467             char *psz_src = E_(SSPop)( st );
468             char *psz_dir = E_(RealPath)( p_intf, psz_src );
469
470             E_(SSPush)( st, psz_dir );
471             free( psz_src );
472             free( psz_dir );
473         }
474         /* 4. stack functions */
475         else if( !strcmp( s, "dup" ) )
476         {
477             char *str = E_(SSPop)( st );
478             E_(SSPush)( st, str );
479             E_(SSPush)( st, str );
480             free( str );
481         }
482         else if( !strcmp( s, "drop" ) )
483         {
484             char *str = E_(SSPop)( st );
485             free( str );
486         }
487         else if( !strcmp( s, "swap" ) )
488         {
489             char *s1 = E_(SSPop)( st );
490             char *s2 = E_(SSPop)( st );
491
492             E_(SSPush)( st, s1 );
493             E_(SSPush)( st, s2 );
494             free( s1 );
495             free( s2 );
496         }
497         else if( !strcmp( s, "flush" ) )
498         {
499             E_(SSClean)( st );
500             E_(SSInit)( st );
501         }
502         else if( !strcmp( s, "store" ) )
503         {
504             char *value = E_(SSPop)( st );
505             char *name  = E_(SSPop)( st );
506
507             E_(mvar_PushNewVar)( vars, name, value );
508             free( name );
509             free( value );
510         }
511         else if( !strcmp( s, "value" ) )
512         {
513             char *name  = E_(SSPop)( st );
514             char *value = E_(mvar_GetValue)( vars, name );
515
516             E_(SSPush)( st, value );
517
518             free( name );
519         }
520         /* 5. player control */
521         else if( !strcmp( s, "vlc_play" ) )
522         {
523             int i_id = E_(SSPopN)( st, vars );
524             int i_ret;
525
526             i_ret = playlist_Control( p_sys->p_playlist, PLAYLIST_ITEMPLAY,
527                                       playlist_ItemGetById( p_sys->p_playlist,
528                                       i_id ) );
529             msg_Dbg( p_intf, "requested playlist item: %i", i_id );
530             E_(SSPushN)( st, i_ret );
531         }
532         else if( !strcmp( s, "vlc_stop" ) )
533         {
534             playlist_Control( p_sys->p_playlist, PLAYLIST_STOP );
535             msg_Dbg( p_intf, "requested playlist stop" );
536         }
537         else if( !strcmp( s, "vlc_pause" ) )
538         {
539             playlist_Control( p_sys->p_playlist, PLAYLIST_PAUSE );
540             msg_Dbg( p_intf, "requested playlist pause" );
541         }
542         else if( !strcmp( s, "vlc_next" ) )
543         {
544             playlist_Control( p_sys->p_playlist, PLAYLIST_SKIP, 1 );
545             msg_Dbg( p_intf, "requested playlist next" );
546         }
547         else if( !strcmp( s, "vlc_previous" ) )
548         {
549             playlist_Control( p_sys->p_playlist, PLAYLIST_SKIP, -1 );
550             msg_Dbg( p_intf, "requested playlist previous" );
551         }
552         else if( !strcmp( s, "vlc_seek" ) )
553         {
554             char *psz_value = E_(SSPop)( st );
555             E_(HandleSeek)( p_intf, psz_value );
556             msg_Dbg( p_intf, "requested playlist seek: %s", psz_value );
557             free( psz_value );
558         }
559         else if( !strcmp( s, "vlc_var_type" )
560                   || !strcmp( s, "vlc_config_type" ) )
561         {
562             vlc_object_t *p_object;
563             const char *psz_type = NULL;
564             int i_type = 0;
565
566             if( !strcmp( s, "vlc_var_type" ) )
567             {
568                 char *psz_object = E_(SSPop)( st );
569                 char *psz_variable = E_(SSPop)( st );
570                 vlc_bool_t b_need_release;
571
572                 p_object = GetVLCObject( p_intf, psz_object, &b_need_release );
573
574                 if( p_object != NULL )
575                     i_type = var_Type( p_object, psz_variable );
576                 free( psz_variable );
577                 free( psz_object );
578                 if( b_need_release && p_object != NULL )
579                     vlc_object_release( p_object );
580             }
581             else
582             {
583                 char *psz_variable = E_(SSPop)( st );
584                 p_object = VLC_OBJECT(p_intf);
585                 i_type = config_GetType( p_object, psz_variable );
586                 free( psz_variable );
587             }
588
589             if( p_object != NULL )
590             {
591                 switch( i_type & VLC_VAR_TYPE )
592                 {
593                 case VLC_VAR_BOOL:
594                     psz_type = "VLC_VAR_BOOL";
595                     break;
596                 case VLC_VAR_INTEGER:
597                     psz_type = "VLC_VAR_INTEGER";
598                     break;
599                 case VLC_VAR_HOTKEY:
600                     psz_type = "VLC_VAR_HOTKEY";
601                     break;
602                 case VLC_VAR_STRING:
603                     psz_type = "VLC_VAR_STRING";
604                     break;
605                 case VLC_VAR_MODULE:
606                     psz_type = "VLC_VAR_MODULE";
607                     break;
608                 case VLC_VAR_FILE:
609                     psz_type = "VLC_VAR_FILE";
610                     break;
611                 case VLC_VAR_DIRECTORY:
612                     psz_type = "VLC_VAR_DIRECTORY";
613                     break;
614                 case VLC_VAR_VARIABLE:
615                     psz_type = "VLC_VAR_VARIABLE";
616                     break;
617                 case VLC_VAR_FLOAT:
618                     psz_type = "VLC_VAR_FLOAT";
619                     break;
620                 default:
621                     psz_type = "UNDEFINED";
622                 }
623             }
624             else
625                 psz_type = "INVALID";
626
627             E_(SSPush)( st, psz_type );
628         }
629         else if( !strcmp( s, "vlc_var_set" ) )
630         {
631             char *psz_object = E_(SSPop)( st );
632             char *psz_variable = E_(SSPop)( st );
633             vlc_bool_t b_need_release;
634
635             vlc_object_t *p_object = GetVLCObject( p_intf, psz_object,
636                                                    &b_need_release );
637
638             if( p_object != NULL )
639             {
640                 vlc_bool_t b_error = VLC_FALSE;
641                 char *psz_value = NULL;
642                 vlc_value_t val;
643                 int i_type;
644
645                 i_type = var_Type( p_object, psz_variable );
646
647                 switch( i_type & VLC_VAR_TYPE )
648                 {
649                 case VLC_VAR_BOOL:
650                     val.b_bool = E_(SSPopN)( st, vars );
651                     msg_Dbg( p_intf, "requested %s var change: %s->%d",
652                              psz_object, psz_variable, val.b_bool );
653                     break;
654                 case VLC_VAR_INTEGER:
655                 case VLC_VAR_HOTKEY:
656                     val.i_int = E_(SSPopN)( st, vars );
657                     msg_Dbg( p_intf, "requested %s var change: %s->%d",
658                              psz_object, psz_variable, val.i_int );
659                     break;
660                 case VLC_VAR_STRING:
661                 case VLC_VAR_MODULE:
662                 case VLC_VAR_FILE:
663                 case VLC_VAR_DIRECTORY:
664                 case VLC_VAR_VARIABLE:
665                     val.psz_string = psz_value = E_(SSPop)( st );
666                     msg_Dbg( p_intf, "requested %s var change: %s->%s",
667                              psz_object, psz_variable, psz_value );
668                     break;
669                 case VLC_VAR_FLOAT:
670                     psz_value = E_(SSPop)( st );
671                     val.f_float = atof( psz_value );
672                     msg_Dbg( p_intf, "requested %s var change: %s->%f",
673                              psz_object, psz_variable, val.f_float );
674                     break;
675                 default:
676                     E_(SSPopN)( st, vars );
677                     msg_Warn( p_intf, "invalid %s variable type %d (%s)",
678                               psz_object, i_type & VLC_VAR_TYPE, psz_variable );
679                     b_error = VLC_TRUE;
680                 }
681
682                 if( !b_error )
683                     var_Set( p_object, psz_variable, val );
684                 if( psz_value != NULL )
685                     free( psz_value );
686             }
687             else
688                 msg_Warn( p_intf, "vlc_var_set called without an object" );
689             free( psz_variable );
690             free( psz_object );
691
692             if( b_need_release && p_object != NULL )
693                 vlc_object_release( p_object );
694         }
695         else if( !strcmp( s, "vlc_var_get" ) )
696         {
697             char *psz_object = E_(SSPop)( st );
698             char *psz_variable = E_(SSPop)( st );
699             vlc_bool_t b_need_release;
700
701             vlc_object_t *p_object = GetVLCObject( p_intf, psz_object,
702                                                    &b_need_release );
703
704             if( p_object != NULL )
705             {
706                 vlc_value_t val;
707                 int i_type;
708
709                 i_type = var_Type( p_object, psz_variable );
710                 var_Get( p_object, psz_variable, &val );
711
712                 switch( i_type & VLC_VAR_TYPE )
713                 {
714                 case VLC_VAR_BOOL:
715                     E_(SSPushN)( st, val.b_bool );
716                     break;
717                 case VLC_VAR_INTEGER:
718                 case VLC_VAR_HOTKEY:
719                     E_(SSPushN)( st, val.i_int );
720                     break;
721                 case VLC_VAR_STRING:
722                 case VLC_VAR_MODULE:
723                 case VLC_VAR_FILE:
724                 case VLC_VAR_DIRECTORY:
725                 case VLC_VAR_VARIABLE:
726                     E_(SSPush)( st, val.psz_string );
727                     free( val.psz_string );
728                     break;
729                 case VLC_VAR_FLOAT:
730                 {
731                     char psz_value[20];
732                     snprintf( psz_value, sizeof(psz_value), "%f", val.f_float );
733                     E_(SSPush)( st, psz_value );
734                     break;
735                 }
736                 default:
737                     msg_Warn( p_intf, "invalid %s variable type %d (%s)",
738                               psz_object, i_type & VLC_VAR_TYPE, psz_variable );
739                     E_(SSPush)( st, "" );
740                 }
741             }
742             else
743             {
744                 msg_Warn( p_intf, "vlc_var_get called without an object" );
745                 E_(SSPush)( st, "" );
746             }
747             free( psz_variable );
748             free( psz_object );
749
750             if( b_need_release && p_object != NULL )
751                 vlc_object_release( p_object );
752         }
753         else if( !strcmp( s, "vlc_object_exists" ) )
754         {
755             char *psz_object = E_(SSPop)( st );
756             vlc_bool_t b_need_release;
757
758             vlc_object_t *p_object = GetVLCObject( p_intf, psz_object,
759                                                    &b_need_release );
760             if( b_need_release && p_object != NULL )
761                 vlc_object_release( p_object );
762
763             if( p_object != NULL )
764                 E_(SSPush)( st, "1" );
765             else
766                 E_(SSPush)( st, "0" );
767         }
768         else if( !strcmp( s, "vlc_config_set" ) )
769         {
770             char *psz_variable = E_(SSPop)( st );
771             int i_type = config_GetType( p_intf, psz_variable );
772
773             switch( i_type & VLC_VAR_TYPE )
774             {
775             case VLC_VAR_BOOL:
776             case VLC_VAR_INTEGER:
777                 config_PutInt( p_intf, psz_variable, E_(SSPopN)( st, vars ) );
778                 break;
779             case VLC_VAR_STRING:
780             case VLC_VAR_MODULE:
781             case VLC_VAR_FILE:
782             case VLC_VAR_DIRECTORY:
783             {
784                 char *psz_string = E_(SSPop)( st );
785                 config_PutPsz( p_intf, psz_variable, psz_string );
786                 free( psz_string );
787                 break;
788             }
789             case VLC_VAR_FLOAT:
790             {
791                 char *psz_string = E_(SSPop)( st );
792                 config_PutFloat( p_intf, psz_variable, atof(psz_string) );
793                 free( psz_string );
794                 break;
795             }
796             default:
797                 msg_Warn( p_intf, "vlc_config_set called on unknown var (%s)",
798                           psz_variable );
799             }
800             free( psz_variable );
801         }
802         else if( !strcmp( s, "vlc_config_get" ) )
803         {
804             char *psz_variable = E_(SSPop)( st );
805             int i_type = config_GetType( p_intf, psz_variable );
806
807             switch( i_type & VLC_VAR_TYPE )
808             {
809             case VLC_VAR_BOOL:
810             case VLC_VAR_INTEGER:
811                 E_(SSPushN)( st, config_GetInt( p_intf, psz_variable ) );
812                 break;
813             case VLC_VAR_STRING:
814             case VLC_VAR_MODULE:
815             case VLC_VAR_FILE:
816             case VLC_VAR_DIRECTORY:
817             {
818                 char *psz_string = config_GetPsz( p_intf, psz_variable );
819                 E_(SSPush)( st, psz_string );
820                 free( psz_string );
821                 break;
822             }
823             case VLC_VAR_FLOAT:
824             {
825                 char psz_string[20];
826                 snprintf( psz_string, sizeof(psz_string), "%f",
827                           config_GetFloat( p_intf, psz_variable ) );
828                 E_(SSPush)( st, psz_string );
829                 break;
830             }
831             default:
832                 msg_Warn( p_intf, "vlc_config_get called on unknown var (%s)",
833                           psz_variable );
834             }
835             free( psz_variable );
836         }
837         else if( !strcmp( s, "vlc_config_save" ) )
838         {
839             char *psz_module = E_(SSPop)( st );
840             int i_result;
841
842             if( !*psz_module )
843             {
844                 free( psz_module );
845                 psz_module = NULL;
846             }
847             i_result = config_SaveConfigFile( p_intf, psz_module );
848
849             if( psz_module != NULL )
850                 free( psz_module );
851             E_(SSPushN)( st, i_result );
852         }
853         else if( !strcmp( s, "vlc_config_reset" ) )
854         {
855             config_ResetAll( p_intf );
856         }
857         /* 6. playlist functions */
858         else if( !strcmp( s, "playlist_add" ) )
859         {
860             char *psz_name = E_(SSPop)( st );
861             char *mrl = E_(SSPop)( st );
862             char *tmp;
863             playlist_item_t *p_item;
864             int i_id;
865
866             tmp = E_(ToUTF8)( p_intf, psz_name );
867             free( psz_name );
868             psz_name = tmp;
869             tmp = E_(ToUTF8)( p_intf, mrl );
870             free( mrl );
871             mrl = tmp;
872
873             if( !*psz_name )
874             {
875                 p_item = E_(MRLParse)( p_intf, mrl, mrl );
876             }
877             else
878             {
879                 p_item = E_(MRLParse)( p_intf, mrl, psz_name );
880             }
881
882             if( p_item == NULL || p_item->input.psz_uri == NULL ||
883                  !*p_item->input.psz_uri )
884             {
885                 i_id = VLC_EGENERIC;
886                 msg_Dbg( p_intf, "invalid requested mrl: %s", mrl );
887             }
888             else
889             {
890                 i_id = playlist_AddItem( p_sys->p_playlist, p_item,
891                                          PLAYLIST_APPEND, PLAYLIST_END );
892                 msg_Dbg( p_intf, "requested mrl add: %s", mrl );
893             }
894             E_(SSPushN)( st, i_id );
895
896             free( mrl );
897             free( psz_name );
898         }
899         else if( !strcmp( s, "playlist_empty" ) )
900         {
901             playlist_LockClear( p_sys->p_playlist );
902             msg_Dbg( p_intf, "requested playlist empty" );
903         }
904         else if( !strcmp( s, "playlist_delete" ) )
905         {
906             int i_id = E_(SSPopN)( st, vars );
907             playlist_LockDelete( p_sys->p_playlist, i_id );
908             msg_Dbg( p_intf, "requested playlist delete: %d", i_id );
909         }
910         else if( !strcmp( s, "playlist_move" ) )
911         {
912             int i_newpos = E_(SSPopN)( st, vars );
913             int i_pos = E_(SSPopN)( st, vars );
914             if ( i_pos < i_newpos )
915             {
916                 playlist_Move( p_sys->p_playlist, i_pos, i_newpos + 1 );
917             }
918             else
919             {
920                 playlist_Move( p_sys->p_playlist, i_pos, i_newpos );
921             }
922             msg_Dbg( p_intf, "requested to move playlist item %d to %d",
923                      i_pos, i_newpos);
924         }
925         else if( !strcmp( s, "vlc_volume_set" ) )
926         {
927             char *psz_vol = E_(SSPop)( st );
928             int i_value;
929             audio_volume_t i_volume;
930             aout_VolumeGet( p_intf, &i_volume );
931             if( psz_vol[0] == '+' )
932             {
933                 i_value = atoi( psz_vol );
934                 if( (i_volume + i_value) > AOUT_VOLUME_MAX )
935                     aout_VolumeSet( p_intf, AOUT_VOLUME_MAX );
936                 else
937                     aout_VolumeSet( p_intf, i_volume + i_value );
938             }
939             else if( psz_vol[0] == '-' )
940             {
941                 i_value = atoi( psz_vol );
942                 if( (i_volume + i_value) < AOUT_VOLUME_MIN )
943                     aout_VolumeSet( p_intf, AOUT_VOLUME_MIN );
944                 else
945                     aout_VolumeSet( p_intf, i_volume + i_value );
946             }
947             else if( strstr( psz_vol, "%") != NULL )
948             {
949                 i_value = atoi( psz_vol );
950                 if( i_value < 0 ) i_value = 0;
951                 if( i_value > 400 ) i_value = 400;
952                 aout_VolumeSet( p_intf, (i_value * (AOUT_VOLUME_MAX - AOUT_VOLUME_MIN))/400+AOUT_VOLUME_MIN);
953             }
954             else
955             {
956                 i_value = atoi( psz_vol );
957                 if( i_value > AOUT_VOLUME_MAX ) i_value = AOUT_VOLUME_MAX;
958                 if( i_value < AOUT_VOLUME_MIN ) i_value = AOUT_VOLUME_MIN;
959                 aout_VolumeSet( p_intf, i_value );
960             }
961             aout_VolumeGet( p_intf, &i_volume );
962         }
963         else if( !strcmp( s, "vlm_command" ) || !strcmp( s, "vlm_cmd" ) )
964         {
965             char *psz_elt;
966             char *psz_cmd = strdup( "" );
967             char *psz_error;
968             vlm_message_t *vlm_answer;
969
970             /* make sure that we have a vlm object */
971             if( p_intf->p_sys->p_vlm == NULL )
972                 p_intf->p_sys->p_vlm = vlm_New( p_intf );
973
974
975             /* vlm command uses the ';' delimiter
976              * (else we can't know when to stop) */
977             while( strcmp( psz_elt = E_(SSPop)( st ), "" )
978                    && strcmp( psz_elt, ";" ) )
979             {
980                 char *psz_buf =
981                     (char *)malloc( strlen( psz_cmd ) + strlen( psz_elt ) + 2 );
982                 sprintf( psz_buf, "%s %s", psz_cmd, psz_elt );
983                 free( psz_cmd );
984                 free( psz_elt );
985                 psz_cmd = psz_buf;
986             }
987
988             msg_Dbg( p_intf, "executing vlm command: %s", psz_cmd );
989             vlm_ExecuteCommand( p_intf->p_sys->p_vlm, psz_cmd, &vlm_answer );
990
991             if( vlm_answer->psz_value == NULL )
992             {
993                 psz_error = strdup( "" );
994             }
995             else
996             {
997                 psz_error = malloc( strlen(vlm_answer->psz_name) +
998                                     strlen(vlm_answer->psz_value) +
999                                     strlen( " : ") + 1 );
1000                 sprintf( psz_error , "%s : %s" , vlm_answer->psz_name,
1001                                                  vlm_answer->psz_value );
1002             }
1003
1004             E_(mvar_AppendNewVar)( vars, "vlm_error", psz_error );
1005             /* this is kind of a duplicate but we need to have the message
1006              * without the command name for the "export" command */
1007             E_(mvar_AppendNewVar)( vars, "vlm_value", vlm_answer->psz_value );
1008             vlm_MessageDelete( vlm_answer );
1009
1010             free( psz_cmd );
1011             free( psz_error );
1012         }
1013         else
1014         {
1015             E_(SSPush)( st, s );
1016         }
1017     }
1018 }