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