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