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