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