new rpn function : volume_set
[vlc.git] / modules / control / http / rpn.c
1 /*****************************************************************************
2  * rpn.c : RPN evaluator for the HTTP Interface
3  *****************************************************************************
4  * Copyright (C) 2001-2005 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., 59 Temple Place - Suite 330, Boston, MA  02111, 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_config_set" ) )
754         {
755             char *psz_variable = E_(SSPop)( st );
756             int i_type = config_GetType( p_intf, psz_variable );
757
758             switch( i_type & VLC_VAR_TYPE )
759             {
760             case VLC_VAR_BOOL:
761             case VLC_VAR_INTEGER:
762                 config_PutInt( p_intf, psz_variable, E_(SSPopN)( st, vars ) );
763                 break;
764             case VLC_VAR_STRING:
765             case VLC_VAR_MODULE:
766             case VLC_VAR_FILE:
767             case VLC_VAR_DIRECTORY:
768             {
769                 char *psz_string = E_(SSPop)( st );
770                 config_PutPsz( p_intf, psz_variable, psz_string );
771                 free( psz_string );
772                 break;
773             }
774             case VLC_VAR_FLOAT:
775             {
776                 char *psz_string = E_(SSPop)( st );
777                 config_PutFloat( p_intf, psz_variable, atof(psz_string) );
778                 free( psz_string );
779                 break;
780             }
781             default:
782                 msg_Warn( p_intf, "vlc_config_set called on unknown var (%s)",
783                           psz_variable );
784             }
785             free( psz_variable );
786         }
787         else if( !strcmp( s, "vlc_config_get" ) )
788         {
789             char *psz_variable = E_(SSPop)( st );
790             int i_type = config_GetType( p_intf, psz_variable );
791
792             switch( i_type & VLC_VAR_TYPE )
793             {
794             case VLC_VAR_BOOL:
795             case VLC_VAR_INTEGER:
796                 E_(SSPushN)( st, config_GetInt( p_intf, psz_variable ) );
797                 break;
798             case VLC_VAR_STRING:
799             case VLC_VAR_MODULE:
800             case VLC_VAR_FILE:
801             case VLC_VAR_DIRECTORY:
802             {
803                 char *psz_string = config_GetPsz( p_intf, psz_variable );
804                 E_(SSPush)( st, psz_string );
805                 free( psz_string );
806                 break;
807             }
808             case VLC_VAR_FLOAT:
809             {
810                 char psz_string[20];
811                 snprintf( psz_string, sizeof(psz_string), "%f",
812                           config_GetFloat( p_intf, psz_variable ) );
813                 E_(SSPush)( st, psz_string );
814                 break;
815             }
816             default:
817                 msg_Warn( p_intf, "vlc_config_get called on unknown var (%s)",
818                           psz_variable );
819             }
820             free( psz_variable );
821         }
822         else if( !strcmp( s, "vlc_config_save" ) )
823         {
824             char *psz_module = E_(SSPop)( st );
825             int i_result;
826
827             if( !*psz_module )
828             {
829                 free( psz_module );
830                 psz_module = NULL;
831             }
832             i_result = config_SaveConfigFile( p_intf, psz_module );
833
834             if( psz_module != NULL )
835                 free( psz_module );
836             E_(SSPushN)( st, i_result );
837         }
838         else if( !strcmp( s, "vlc_config_reset" ) )
839         {
840             config_ResetAll( p_intf );
841         }
842         /* 6. playlist functions */
843         else if( !strcmp( s, "playlist_add" ) )
844         {
845             char *psz_name = E_(SSPop)( st );
846             char *mrl = E_(SSPop)( st );
847             char *tmp;
848             playlist_item_t *p_item;
849             int i_id;
850
851             tmp = E_(ToUTF8)( p_intf, psz_name );
852             free( psz_name );
853             psz_name = tmp;
854             tmp = E_(ToUTF8)( p_intf, mrl );
855             free( mrl );
856             mrl = tmp;
857
858             if( !*psz_name )
859             {
860                 p_item = E_(MRLParse)( p_intf, mrl, mrl );
861             }
862             else
863             {
864                 p_item = E_(MRLParse)( p_intf, mrl, psz_name );
865             }
866
867             if( p_item == NULL || p_item->input.psz_uri == NULL ||
868                  !*p_item->input.psz_uri )
869             {
870                 i_id = VLC_EGENERIC;
871                 msg_Dbg( p_intf, "invalid requested mrl: %s", mrl );
872             }
873             else
874             {
875                 i_id = playlist_AddItem( p_sys->p_playlist, p_item,
876                                          PLAYLIST_APPEND, PLAYLIST_END );
877                 msg_Dbg( p_intf, "requested mrl add: %s", mrl );
878             }
879             E_(SSPushN)( st, i_id );
880
881             free( mrl );
882             free( psz_name );
883         }
884         else if( !strcmp( s, "playlist_empty" ) )
885         {
886             playlist_LockClear( p_sys->p_playlist );
887             msg_Dbg( p_intf, "requested playlist empty" );
888         }
889         else if( !strcmp( s, "playlist_delete" ) )
890         {
891             int i_id = E_(SSPopN)( st, vars );
892             playlist_LockDelete( p_sys->p_playlist, i_id );
893             msg_Dbg( p_intf, "requested playlist delete: %d", i_id );
894         }
895         else if( !strcmp( s, "playlist_move" ) )
896         {
897             int i_newpos = E_(SSPopN)( st, vars );
898             int i_pos = E_(SSPopN)( st, vars );
899             if ( i_pos < i_newpos )
900             {
901                 playlist_Move( p_sys->p_playlist, i_pos, i_newpos + 1 );
902             }
903             else
904             {
905                 playlist_Move( p_sys->p_playlist, i_pos, i_newpos );
906             }
907             msg_Dbg( p_intf, "requested to move playlist item %d to %d",
908                      i_pos, i_newpos);
909         }
910         else if( !strcmp( s, "volume_set" ) )
911         {
912             char *psz_vol = E_(SSPop)( st );
913             int i_value;
914             audio_volume_t i_volume;
915             aout_VolumeGet( p_intf, &i_volume );
916             if( psz_vol[0] == '+' )
917             {
918                 i_value = atoi( psz_vol );
919                 if( (i_volume + i_value) > AOUT_VOLUME_MAX )
920                     aout_VolumeSet( p_intf, AOUT_VOLUME_MAX );
921                 else
922                     aout_VolumeSet( p_intf, i_volume + i_value );
923             }
924             else if( psz_vol[0] == '-' )
925             {
926                 i_value = atoi( psz_vol );
927                 if( (i_volume + i_value) < AOUT_VOLUME_MIN )
928                     aout_VolumeSet( p_intf, AOUT_VOLUME_MIN );
929                 else
930                     aout_VolumeSet( p_intf, i_volume + i_value );
931             }
932             else if( strstr( psz_vol, "%") != NULL )
933             {
934                 i_value = atoi( psz_vol );
935                 if( i_value < 0 ) i_value = 0;
936                 if( i_value > 400 ) i_value = 400;
937                 aout_VolumeSet( p_intf, (i_value * (AOUT_VOLUME_MAX - AOUT_VOLUME_MIN))/400+AOUT_VOLUME_MIN);
938             }
939             else
940             {
941                 i_value = atoi( psz_vol );
942                 if( i_value > AOUT_VOLUME_MAX ) i_value = AOUT_VOLUME_MAX;
943                 if( i_value < AOUT_VOLUME_MIN ) i_value = AOUT_VOLUME_MIN;
944                 aout_VolumeSet( p_intf, i_value );
945             }
946             aout_VolumeGet( p_intf, &i_volume );
947         }
948         else
949         {
950             E_(SSPush)( st, s );
951         }
952     }
953 }