]> git.sesse.net Git - vlc/blob - modules/video_filter/dynamicoverlay/dynamicoverlay_commands.c
Fix non utf-8 encoding.
[vlc] / modules / video_filter / dynamicoverlay / dynamicoverlay_commands.c
1 /*****************************************************************************
2  * dynamicoverlay_commands.c : dynamic overlay plugin commands
3  *****************************************************************************
4  * Copyright (C) 2008 the VideoLAN team
5  * $Id$
6  *
7  * Author: Soren Bog <avacore@videolan.org>
8  *         Jean-Paul Saman <jpsaman@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <vlc_common.h>
30 #include <vlc_arrays.h>
31 #include <vlc_vout.h>
32 #include <vlc_filter.h>
33 #include <vlc_osd.h>
34
35 #include <string.h>
36 #include <ctype.h>
37
38 #if defined(HAVE_SYS_SHM_H)
39 #include <sys/shm.h>
40 #endif
41
42 #include "dynamicoverlay.h"
43
44
45 /*****************************************************************************
46  * overlay_t: Overlay descriptor
47  *****************************************************************************/
48
49 overlay_t *OverlayCreate( void )
50 {
51     overlay_t *p_ovl = malloc( sizeof( overlay_t ) );
52     if( p_ovl == NULL )
53        return NULL;
54     memset( p_ovl, 0, sizeof( overlay_t ) );
55
56     p_ovl->i_x = p_ovl->i_y = 0;
57     p_ovl->i_alpha = 0xFF;
58     p_ovl->b_active = false;
59     vout_InitFormat( &p_ovl->format, VLC_FOURCC( '\0','\0','\0','\0') , 0, 0,
60                      VOUT_ASPECT_FACTOR );
61     memcpy( &p_ovl->fontstyle, &default_text_style, sizeof(struct text_style_t) );
62     p_ovl->data.p_text = NULL;
63
64     return p_ovl;
65 }
66
67 int OverlayDestroy( overlay_t *p_ovl )
68 {
69     if( p_ovl->data.p_text != NULL )
70         free( p_ovl->data.p_text );
71
72     return VLC_SUCCESS;
73 }
74
75 /*****************************************************************************
76  * Command parsers
77  *****************************************************************************/
78 static int skip_space( char **psz_command )
79 {
80     char *psz_temp = *psz_command;
81
82     while( isspace( *psz_temp ) )
83     {
84         ++psz_temp;
85     }
86     if( psz_temp == *psz_command )
87     {
88         return VLC_EGENERIC;
89     }
90     *psz_command = psz_temp;
91     return VLC_SUCCESS;
92 }
93
94 static int parse_digit( char **psz_command, int32_t *value )
95 {
96     char *psz_temp;
97     *value = strtol( *psz_command, &psz_temp, 10 );
98     if( psz_temp == *psz_command )
99     {
100         return VLC_EGENERIC;
101     }
102     *psz_command = psz_temp;
103     return VLC_SUCCESS;
104 }
105
106 static int parse_char( char **psz_command, char **psz_end,
107                        int count, char *psz_value )
108 {
109     if( *psz_end - *psz_command < count )
110     {
111         return VLC_EGENERIC;
112     }
113     memcpy( psz_value, *psz_command, count );
114     *psz_command += count;
115     return VLC_SUCCESS;
116 }
117
118 static int parser_DataSharedMem( char *psz_command,
119                                  char *psz_end,
120                                  commandparams_t *p_params )
121 {
122     /* Parse: 0 128 128 RGBA 9404459 */
123     skip_space( &psz_command );
124     if( isdigit( *psz_command ) )
125     {
126         if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
127             return VLC_EGENERIC;
128     }
129     skip_space( &psz_command );
130     if( isdigit( *psz_command ) )
131     {
132         if( parse_digit( &psz_command, &p_params->i_width ) == VLC_EGENERIC )
133             return VLC_EGENERIC;
134     }
135     skip_space( &psz_command );
136     if( isdigit( *psz_command ) )
137     {
138         if( parse_digit( &psz_command, &p_params->i_height ) == VLC_EGENERIC )
139             return VLC_EGENERIC;
140     }
141     skip_space( &psz_command );
142     if( isascii( *psz_command ) )
143     {
144         if( parse_char( &psz_command, &psz_end, 4, (char*)&p_params->fourcc )
145             == VLC_EGENERIC )
146             return VLC_EGENERIC;
147     }
148     skip_space( &psz_command );
149     if( isdigit( *psz_command ) )
150     {
151         if( parse_digit( &psz_command, &p_params->i_shmid ) == VLC_EGENERIC )
152             return VLC_EGENERIC;
153     }
154     return VLC_SUCCESS;
155 }
156
157 static int parser_Id( char *psz_command, char *psz_end,
158                       commandparams_t *p_params )
159 {
160     VLC_UNUSED(psz_end);
161     skip_space( &psz_command );
162     if( isdigit( *psz_command ) )
163     {
164         if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
165             return VLC_EGENERIC;
166     }
167     return VLC_SUCCESS;
168 }
169
170 static int parser_None( char *psz_command, char *psz_end,
171                         commandparams_t *p_params )
172 {
173     VLC_UNUSED(psz_command);
174     VLC_UNUSED(psz_end);
175     VLC_UNUSED(p_params);
176     return VLC_SUCCESS;
177 }
178
179 static int parser_SetAlpha( char *psz_command, char *psz_end,
180                             commandparams_t *p_params )
181 {
182     VLC_UNUSED(psz_end);
183     skip_space( &psz_command );
184     if( isdigit( *psz_command ) )
185     {
186         if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC  )
187             return VLC_EGENERIC;
188     }
189     skip_space( &psz_command );
190     if( isdigit( *psz_command ) )
191     {
192         if( parse_digit( &psz_command, &p_params->i_alpha ) == VLC_EGENERIC )
193             return VLC_EGENERIC;
194     }
195     return VLC_SUCCESS;
196 }
197
198 static int parser_SetPosition( char *psz_command, char *psz_end,
199                                commandparams_t *p_params )
200 {
201     VLC_UNUSED(psz_end);
202     skip_space( &psz_command );
203     if( isdigit( *psz_command ) )
204     {
205         if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
206             return VLC_EGENERIC;
207     }
208     skip_space( &psz_command );
209     if( isdigit( *psz_command ) )
210     {
211         if( parse_digit( &psz_command, &p_params->i_x ) == VLC_EGENERIC )
212             return VLC_EGENERIC;
213     }
214     skip_space( &psz_command );
215     if( isdigit( *psz_command ) )
216     {
217         if( parse_digit( &psz_command, &p_params->i_y ) == VLC_EGENERIC )
218             return VLC_EGENERIC;
219     }
220     return VLC_SUCCESS;
221 }
222
223 static int parser_SetTextAlpha( char *psz_command, char *psz_end,
224                                 commandparams_t *p_params )
225 {
226     VLC_UNUSED(psz_end);
227     skip_space( &psz_command );
228     if( isdigit( *psz_command ) )
229     {
230         if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
231             return VLC_EGENERIC;
232     }
233     skip_space( &psz_command );
234     if( isdigit( *psz_command ) )
235     {
236         if( parse_digit( &psz_command, &p_params->fontstyle.i_font_alpha ) == VLC_EGENERIC )
237             return VLC_EGENERIC;
238     }
239     return VLC_SUCCESS;
240 }
241
242 static int parser_SetTextColor( char *psz_command, char *psz_end,
243                                 commandparams_t *p_params )
244 {
245     int r, g, b;
246     VLC_UNUSED(psz_end);
247     skip_space( &psz_command );
248     if( isdigit( *psz_command ) )
249     {
250         if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
251             return VLC_EGENERIC;
252     }
253     skip_space( &psz_command );
254     if( isdigit( *psz_command ) )
255     {
256         if( parse_digit( &psz_command, &r ) == VLC_EGENERIC )
257             return VLC_EGENERIC;
258     }
259     skip_space( &psz_command );
260     if( isdigit( *psz_command ) )
261     {
262         if( parse_digit( &psz_command, &g ) == VLC_EGENERIC )
263             return VLC_EGENERIC;
264     }
265     skip_space( &psz_command );
266     if( isdigit( *psz_command ) )
267     {
268         if( parse_digit( &psz_command, &b ) == VLC_EGENERIC )
269             return VLC_EGENERIC;
270     }
271     p_params->fontstyle.i_font_color = (r<<24) | (g<<16) | (b<<8);
272     return VLC_SUCCESS;
273 }
274
275 static int parser_SetTextSize( char *psz_command, char *psz_end,
276                                commandparams_t *p_params )
277 {
278     VLC_UNUSED(psz_end);
279     skip_space( &psz_command );
280     if( isdigit( *psz_command ) )
281     {
282         if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
283             return VLC_EGENERIC;
284     }
285     skip_space( &psz_command );
286     if( isdigit( *psz_command ) )
287     {
288         if( parse_digit( &psz_command, &p_params->fontstyle.i_font_size ) == VLC_EGENERIC )
289             return VLC_EGENERIC;
290     }
291     return VLC_SUCCESS;
292 }
293
294 static int parser_SetVisibility( char *psz_command, char *psz_end,
295                                  commandparams_t *p_params )
296 {
297     VLC_UNUSED(psz_end);
298     skip_space( &psz_command );
299     if( isdigit( *psz_command ) )
300     {
301         if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
302             return VLC_EGENERIC;
303     }
304     skip_space( &psz_command );
305     if( isdigit( *psz_command ) )
306     {
307         int32_t i_vis = 0;
308         if( parse_digit( &psz_command, &i_vis ) == VLC_EGENERIC )
309             return VLC_EGENERIC;
310         p_params->b_visible = (i_vis == 1) ? true : false;
311     }
312     return VLC_SUCCESS;
313 }
314
315 /*****************************************************************************
316  * Command unparser functions
317  *****************************************************************************/
318
319 static int unparse_default( const commandparams_t *p_results,
320                             buffer_t *p_output )
321 {
322     VLC_UNUSED(p_results);
323     VLC_UNUSED(p_output);
324     return VLC_SUCCESS;
325 }
326
327 static int unparse_GenImage( const commandparams_t *p_results,
328                              buffer_t *p_output )
329 {
330     int ret = BufferPrintf( p_output, " %d", p_results->i_id );
331     if( ret != VLC_SUCCESS )
332         return ret;
333
334     return VLC_SUCCESS;
335 }
336
337 static int unparse_GetAlpha( const commandparams_t *p_results,
338                              buffer_t *p_output )
339 {
340     int ret = BufferPrintf( p_output, " %d", p_results->i_alpha );
341     if( ret != VLC_SUCCESS )
342         return ret;
343
344     return VLC_SUCCESS;
345 }
346
347 static int unparse_GetPosition( const commandparams_t *p_results,
348                                 buffer_t *p_output )
349 {
350     int ret = BufferPrintf( p_output, " %d", p_results->i_x );
351     if( ret != VLC_SUCCESS )
352         return ret;
353
354     ret = BufferPrintf( p_output, " %d", p_results->i_y );
355     if( ret != VLC_SUCCESS )
356         return ret;
357
358     return VLC_SUCCESS;
359 }
360
361 static int unparse_GetTextAlpha( const commandparams_t *p_results,
362                                  buffer_t *p_output )
363 {
364     int ret = BufferPrintf( p_output, " %d", p_results->fontstyle.i_font_alpha );
365     if( ret != VLC_SUCCESS )
366         return ret;
367
368     return VLC_SUCCESS;
369 }
370
371 static int unparse_GetTextColor( const commandparams_t *p_results,
372                                  buffer_t *p_output )
373 {
374     int ret = BufferPrintf( p_output, " %d", (p_results->fontstyle.i_font_color & 0xff0000)>>24 );
375     if( ret != VLC_SUCCESS )
376         return ret;
377
378     ret = BufferPrintf( p_output, " %d", (p_results->fontstyle.i_font_color & 0x00ff00)>>16 );
379     if( ret != VLC_SUCCESS )
380         return ret;
381
382     ret = BufferPrintf( p_output, " %d", (p_results->fontstyle.i_font_color & 0x0000ff)>>8 );
383     if( ret != VLC_SUCCESS )
384         return ret;
385
386     return VLC_SUCCESS;
387 }
388
389 static int unparse_GetTextSize( const commandparams_t *p_results,
390                                 buffer_t *p_output )
391 {
392     int ret = BufferPrintf( p_output, " %d", p_results->fontstyle.i_font_size );
393     if( ret != VLC_SUCCESS )
394         return ret;
395
396     return VLC_SUCCESS;
397 }
398
399 static int unparse_GetVisibility( const commandparams_t *p_results,
400                              buffer_t *p_output )
401 {
402     int ret = BufferPrintf( p_output, " %d", (p_results->b_visible ? 1 : 0) );
403     if( ret != VLC_SUCCESS ) {
404         return ret;
405     }
406     return VLC_SUCCESS;
407 }
408
409 /*****************************************************************************
410  * Command functions
411  *****************************************************************************/
412 static int exec_DataSharedMem( filter_t *p_filter,
413                                const commandparams_t *p_params,
414                                commandparams_t *p_results )
415 {
416 #if defined(HAVE_SYS_SHM_H)
417     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
418     struct shmid_ds shminfo;
419     overlay_t *p_ovl;
420     size_t i_size;
421
422     VLC_UNUSED(p_results);
423
424     p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
425     if( p_ovl == NULL )
426     {
427         msg_Err( p_filter, "Invalid overlay: %d", p_params->i_id );
428         return VLC_EGENERIC;
429     }
430
431     if( shmctl( p_params->i_shmid, IPC_STAT, &shminfo ) == -1 )
432     {
433         msg_Err( p_filter, "Unable to access shared memory" );
434         return VLC_EGENERIC;
435     }
436     i_size = shminfo.shm_segsz;
437
438     if( p_params->fourcc == VLC_FOURCC('T','E','X','T') )
439     {
440         char *p_data;
441
442         if( (p_params->i_height != 1) || (p_params->i_width < 1) )
443         {
444             msg_Err( p_filter,
445                      "Invalid width and/or height. when specifing text height "
446                      "must be 1 and width the number of bytes in the string, "
447                      "including the null terminator" );
448             return VLC_EGENERIC;
449         }
450
451         if( (size_t)p_params->i_width > i_size )
452         {
453             msg_Err( p_filter,
454                      "Insufficient data in shared memory. need %d, got %zu",
455                      p_params->i_width, i_size );
456             return VLC_EGENERIC;
457         }
458
459         p_ovl->data.p_text = malloc( p_params->i_width );
460         if( p_ovl->data.p_text == NULL )
461         {
462             msg_Err( p_filter, "Unable to allocate string storage" );
463             return VLC_ENOMEM;
464         }
465
466         vout_InitFormat( &p_ovl->format, VLC_FOURCC('T','E','X','T'),
467                          0, 0, 0 );
468
469         p_data = shmat( p_params->i_shmid, NULL, SHM_RDONLY );
470         if( p_data == NULL )
471         {
472             msg_Err( p_filter, "Unable to attach to shared memory" );
473             free( p_ovl->data.p_text );
474             p_ovl->data.p_text = NULL;
475             return VLC_ENOMEM;
476         }
477         memcpy( p_ovl->data.p_text, p_data, p_params->i_width );
478
479         shmdt( p_data );
480     }
481     else
482     {
483         uint8_t *p_data, *p_in;
484         size_t i_neededsize = 0;
485
486         p_ovl->data.p_pic = malloc( sizeof( picture_t ) );
487         if( p_ovl->data.p_pic == NULL )
488             return VLC_ENOMEM;
489
490         vout_InitFormat( &p_ovl->format, p_params->fourcc,
491                          p_params->i_width, p_params->i_height,
492                          VOUT_ASPECT_FACTOR );
493         if( vout_AllocatePicture( p_filter, p_ovl->data.p_pic,
494                                   p_ovl->format.i_chroma, p_params->i_width,
495                                   p_params->i_height, p_ovl->format.i_aspect ) )
496         {
497             msg_Err( p_filter, "Unable to allocate picture" );
498             free( p_ovl->data.p_pic );
499             p_ovl->data.p_pic = NULL;
500             return VLC_ENOMEM;
501         }
502
503         for( size_t i_plane = 0; i_plane < (size_t)p_ovl->data.p_pic->i_planes;
504              ++i_plane )
505         {
506             i_neededsize += p_ovl->data.p_pic->p[i_plane].i_visible_lines *
507                             p_ovl->data.p_pic->p[i_plane].i_visible_pitch;
508         }
509
510         if( i_neededsize > i_size )
511         {
512             msg_Err( p_filter,
513                      "Insufficient data in shared memory. need %zu, got %zu",
514                      i_neededsize, i_size );
515             p_ovl->data.p_pic->pf_release( p_ovl->data.p_pic );
516             free( p_ovl->data.p_pic );
517             p_ovl->data.p_pic = NULL;
518             return VLC_EGENERIC;
519         }
520
521         p_data = shmat( p_params->i_shmid, NULL, SHM_RDONLY );
522         if( p_data == NULL )
523         {
524             msg_Err( p_filter, "Unable to attach to shared memory" );
525             p_ovl->data.p_pic->pf_release( p_ovl->data.p_pic );
526             free( p_ovl->data.p_pic );
527             p_ovl->data.p_pic = NULL;
528             return VLC_ENOMEM;
529         }
530
531         p_in = p_data;
532         for( size_t i_plane = 0; i_plane < (size_t)p_ovl->data.p_pic->i_planes;
533              ++i_plane )
534         {
535             uint8_t *p_out = p_ovl->data.p_pic->p[i_plane].p_pixels;
536             for( size_t i_line = 0;
537                  i_line < (size_t)p_ovl->data.p_pic->p[i_plane].i_visible_lines;
538                  ++i_line )
539             {
540                 vlc_memcpy( p_out, p_in,
541                             p_ovl->data.p_pic->p[i_plane].i_visible_pitch );
542                 p_out += p_ovl->data.p_pic->p[i_plane].i_pitch;
543                 p_in += p_ovl->data.p_pic->p[i_plane].i_visible_pitch;
544             }
545         }
546         shmdt( p_data );
547     }
548     p_sys->b_updated = p_ovl->b_active;
549
550     return VLC_SUCCESS;
551 #else
552     VLC_UNUSED(p_params);
553     VLC_UNUSED(p_results);
554
555     msg_Err( p_filter, "system doesn't support shared memory" );
556     return VLC_EGENERIC;
557 #endif
558 }
559
560 static int exec_DeleteImage( filter_t *p_filter,
561                              const commandparams_t *p_params,
562                              commandparams_t *p_results )
563 {
564     VLC_UNUSED(p_results);
565     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
566     p_sys->b_updated = true;
567
568     return ListRemove( &p_sys->overlays, p_params->i_id );
569 }
570
571 static int exec_EndAtomic( filter_t *p_filter,
572                            const commandparams_t *p_params,
573                            commandparams_t *p_results )
574 {
575     VLC_UNUSED(p_params);
576     VLC_UNUSED(p_results);
577     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
578     QueueTransfer( &p_sys->pending, &p_sys->atomic );
579     p_sys->b_atomic = false;
580     return VLC_SUCCESS;
581 }
582
583 static int exec_GenImage( filter_t *p_filter,
584                           const commandparams_t *p_params,
585                           commandparams_t *p_results )
586 {
587     VLC_UNUSED(p_params);
588     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
589
590     overlay_t *p_ovl = OverlayCreate();
591     if( p_ovl == NULL )
592         return VLC_ENOMEM;
593
594     ssize_t i_idx = ListAdd( &p_sys->overlays, p_ovl );
595     if( i_idx < 0 )
596         return i_idx;
597
598     p_results->i_id = i_idx;
599     return VLC_SUCCESS;
600 }
601
602 static int exec_GetAlpha( filter_t *p_filter,
603                           const commandparams_t *p_params,
604                           commandparams_t *p_results )
605 {
606     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
607     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
608     if( p_ovl == NULL )
609         return VLC_EGENERIC;
610
611     p_results->i_alpha = p_ovl->i_alpha;
612     return VLC_SUCCESS;
613 }
614
615 static int exec_GetPosition( filter_t *p_filter,
616                              const commandparams_t *p_params,
617                              commandparams_t *p_results )
618 {
619     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
620     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
621     if( p_ovl == NULL )
622         return VLC_EGENERIC;
623
624     p_results->i_x = p_ovl->i_x;
625     p_results->i_y = p_ovl->i_y;
626     return VLC_SUCCESS;
627 }
628
629 static int exec_GetTextAlpha( filter_t *p_filter,
630                               const commandparams_t *p_params,
631                               commandparams_t *p_results )
632 {
633     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
634     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
635     if( p_ovl == NULL )
636         return VLC_EGENERIC;
637
638     p_results->fontstyle.i_font_alpha = p_ovl->fontstyle.i_font_alpha;
639     return VLC_SUCCESS;
640 }
641
642 static int exec_GetTextColor( filter_t *p_filter,
643                               const commandparams_t *p_params,
644                               commandparams_t *p_results )
645 {
646     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
647     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
648     if( p_ovl == NULL )
649         return VLC_EGENERIC;
650
651     p_results->fontstyle.i_font_color = p_ovl->fontstyle.i_font_color;
652     return VLC_SUCCESS;
653 }
654
655 static int exec_GetTextSize( filter_t *p_filter,
656                              const commandparams_t *p_params,
657                              commandparams_t *p_results )
658 {
659     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
660     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
661     if( p_ovl == NULL )
662         return VLC_EGENERIC;
663
664     p_results->fontstyle.i_font_size = p_ovl->fontstyle.i_font_size;
665     return VLC_SUCCESS;
666 }
667
668 static int exec_GetVisibility( filter_t *p_filter,
669                                const commandparams_t *p_params,
670                                commandparams_t *p_results )
671 {
672     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
673
674     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
675     if( p_ovl == NULL )
676         return VLC_EGENERIC;
677
678     p_results->b_visible = ( p_ovl->b_active == true ) ? 1 : 0;
679     return VLC_SUCCESS;
680 }
681
682 static int exec_SetAlpha( filter_t *p_filter,
683                           const commandparams_t *p_params,
684                           commandparams_t *p_results )
685 {
686     VLC_UNUSED(p_results);
687     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
688
689     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
690     if( p_ovl == NULL )
691         return VLC_EGENERIC;
692
693     p_ovl->i_alpha = p_params->i_alpha;
694     p_sys->b_updated = p_ovl->b_active;
695     return VLC_SUCCESS;
696 }
697
698 static int exec_SetPosition( filter_t *p_filter,
699                              const commandparams_t *p_params,
700                              commandparams_t *p_results )
701 {
702     VLC_UNUSED(p_results);
703     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
704
705     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
706     if( p_ovl == NULL )
707         return VLC_EGENERIC;
708
709     p_ovl->i_x = p_params->i_x;
710     p_ovl->i_y = p_params->i_y;
711
712     p_sys->b_updated = p_ovl->b_active;
713     return VLC_SUCCESS;
714 }
715
716 static int exec_SetTextAlpha( filter_t *p_filter,
717                               const commandparams_t *p_params,
718                               commandparams_t *p_results )
719 {
720     VLC_UNUSED(p_results);
721     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
722
723     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
724     if( p_ovl == NULL )
725         return VLC_EGENERIC;
726
727     p_ovl->fontstyle.i_font_alpha = p_params->fontstyle.i_font_alpha;
728     p_sys->b_updated = p_ovl->b_active;
729     return VLC_SUCCESS;
730 }
731
732 static int exec_SetTextColor( filter_t *p_filter,
733                               const commandparams_t *p_params,
734                               commandparams_t *p_results )
735 {
736     VLC_UNUSED(p_results);
737     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
738
739     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
740     if( p_ovl == NULL )
741         return VLC_EGENERIC;
742
743     p_ovl->fontstyle.i_font_color = p_params->fontstyle.i_font_color;
744     p_sys->b_updated = p_ovl->b_active;
745     return VLC_SUCCESS;
746 }
747
748 static int exec_SetTextSize( filter_t *p_filter,
749                               const commandparams_t *p_params,
750                               commandparams_t *p_results )
751 {
752     VLC_UNUSED(p_results);
753     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
754
755     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
756     if( p_ovl == NULL )
757         return VLC_EGENERIC;
758
759     p_ovl->fontstyle.i_font_size = p_params->fontstyle.i_font_size;
760     p_sys->b_updated = p_ovl->b_active;
761     return VLC_SUCCESS;
762 }
763
764 static int exec_SetVisibility( filter_t *p_filter,
765                                const commandparams_t *p_params,
766                                commandparams_t *p_results )
767 {
768     VLC_UNUSED(p_results);
769     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
770
771     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
772     if( p_ovl == NULL )
773         return VLC_EGENERIC;
774
775     p_ovl->b_active = p_params->b_visible;// ? false : true;
776     p_sys->b_updated = true;
777     return VLC_SUCCESS;
778 }
779
780 static int exec_StartAtomic( filter_t *p_filter,
781                              const commandparams_t *p_params,
782                              commandparams_t *p_results )
783 {
784     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
785     VLC_UNUSED(p_params);
786     VLC_UNUSED(p_results);
787
788     p_sys->b_atomic = true;
789     return VLC_SUCCESS;
790 }
791
792 /*****************************************************************************
793  * Command functions
794  *****************************************************************************/
795 static commanddesc_t p_commands[] =
796 {
797     {   .psz_command = "DataSharedMem",
798         .b_atomic = true,
799         .pf_parser = parser_DataSharedMem,
800         .pf_execute = exec_DataSharedMem,
801         .pf_unparse = unparse_default,
802     },
803     {   .psz_command = "DeleteImage",
804         .b_atomic = true,
805         .pf_parser = parser_Id,
806         .pf_execute = exec_DeleteImage,
807         .pf_unparse = unparse_default,
808     },
809     {   .psz_command = "EndAtomic",
810         .b_atomic = false,
811         .pf_parser = parser_None,
812         .pf_execute = exec_EndAtomic,
813         .pf_unparse = unparse_default,
814     },
815     {   .psz_command = "GenImage",
816         .b_atomic = false,
817         .pf_parser = parser_None,
818         .pf_execute = exec_GenImage,
819         .pf_unparse = unparse_GenImage,
820     },
821     {   .psz_command = "GetAlpha",
822         .b_atomic = false,
823         .pf_parser = parser_Id,
824         .pf_execute = exec_GetAlpha,
825         .pf_unparse = unparse_GetAlpha,
826     },
827     {   .psz_command = "GetPosition",
828         .b_atomic = false,
829         .pf_parser = parser_Id,
830         .pf_execute = exec_GetPosition,
831         .pf_unparse = unparse_GetPosition,
832     },
833     {   .psz_command = "GetTextAlpha",
834         .b_atomic = false,
835         .pf_parser = parser_Id,
836         .pf_execute = exec_GetTextAlpha,
837         .pf_unparse = unparse_GetTextAlpha,
838     },
839     {   .psz_command = "GetTextColor",
840         .b_atomic = false,
841         .pf_parser = parser_Id,
842         .pf_execute = exec_GetTextColor,
843         .pf_unparse = unparse_GetTextColor,
844     },
845     {   .psz_command = "GetTextSize",
846         .b_atomic = true,
847         .pf_parser = parser_Id,
848         .pf_execute = exec_GetTextSize,
849         .pf_unparse = unparse_GetTextSize,
850     },
851     {   .psz_command = "GetVisibility",
852         .b_atomic = false,
853         .pf_parser = parser_Id,
854         .pf_execute = exec_GetVisibility,
855         .pf_unparse = unparse_GetVisibility,
856     },
857     {   .psz_command = "SetAlpha",
858         .b_atomic = true,
859         .pf_parser = parser_SetAlpha,
860         .pf_execute = exec_SetAlpha,
861         .pf_unparse = unparse_default,
862     },
863     {   .psz_command = "SetPosition",
864         .b_atomic = true,
865         .pf_parser = parser_SetPosition,
866         .pf_execute = exec_SetPosition,
867         .pf_unparse = unparse_default,
868     },
869     {   .psz_command = "SetTextAlpha",
870         .b_atomic = true,
871         .pf_parser = parser_SetTextAlpha,
872         .pf_execute = exec_SetTextAlpha,
873         .pf_unparse = unparse_default,
874     },
875     {   .psz_command = "SetTextColor",
876         .b_atomic = true,
877         .pf_parser = parser_SetTextColor,
878         .pf_execute = exec_SetTextColor,
879         .pf_unparse = unparse_default,
880     },
881     {   .psz_command = "SetTextSize",
882         .b_atomic = true,
883         .pf_parser = parser_SetTextSize,
884         .pf_execute = exec_SetTextSize,
885         .pf_unparse = unparse_default,
886     },
887     {   .psz_command = "SetVisibility",
888         .b_atomic = true,
889         .pf_parser = parser_SetVisibility,
890         .pf_execute = exec_SetVisibility,
891         .pf_unparse = unparse_default,
892     },
893     {   .psz_command = "StartAtomic",
894         .b_atomic = true,
895         .pf_parser = parser_None,
896         .pf_execute = exec_StartAtomic,
897         .pf_unparse = unparse_default,
898     }
899 };
900
901 void RegisterCommand( filter_t *p_filter )
902 {
903     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
904     size_t i_index = 0;
905
906     p_sys->i_commands = ARRAY_SIZE(p_commands);
907     p_sys->pp_commands = (commanddesc_t **) calloc( p_sys->i_commands, sizeof(commanddesc_t*) );
908     if( !p_sys->pp_commands ) return;
909     for( i_index = 0; i_index < p_sys->i_commands; i_index ++ )
910     {
911         p_sys->pp_commands[i_index] = (commanddesc_t *) malloc( sizeof(commanddesc_t) );
912         if( !p_sys->pp_commands[i_index] ) return;
913         p_sys->pp_commands[i_index]->psz_command = strdup( p_commands[i_index].psz_command );
914         p_sys->pp_commands[i_index]->b_atomic = p_commands[i_index].b_atomic;
915         p_sys->pp_commands[i_index]->pf_parser = p_commands[i_index].pf_parser;
916         p_sys->pp_commands[i_index]->pf_execute = p_commands[i_index].pf_execute;
917         p_sys->pp_commands[i_index]->pf_unparse = p_commands[i_index].pf_unparse;
918     }
919
920     msg_Dbg( p_filter, "%zu commands are available", p_sys->i_commands );
921     for( size_t i_index = 0; i_index < p_sys->i_commands; i_index++ )
922         msg_Dbg( p_filter, "    %s", p_sys->pp_commands[i_index]->psz_command );
923 }
924
925 void UnregisterCommand( filter_t *p_filter )
926 {
927     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
928     size_t i_index = 0;
929
930     for( i_index = 0; i_index < p_sys->i_commands; i_index++ )
931     {
932         free( p_sys->pp_commands[i_index]->psz_command );
933         free( p_sys->pp_commands[i_index] );
934     }
935     free( p_sys->pp_commands );
936     p_sys->pp_commands = NULL;
937     p_sys->i_commands = 0;
938 }