]> git.sesse.net Git - vlc/blob - modules/video_filter/dynamicoverlay/dynamicoverlay_commands.c
macosx: fixed menubar appearance in fullscreen mode by partially reverting [46c93c9cc...
[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 = 0, g = 0, b = 0;
246     VLC_UNUSED(psz_end);
247
248     skip_space( &psz_command );
249     if( isdigit( *psz_command ) )
250     {
251         if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
252             return VLC_EGENERIC;
253     }
254     skip_space( &psz_command );
255     if( isdigit( *psz_command ) )
256     {
257         if( parse_digit( &psz_command, &r ) == VLC_EGENERIC )
258             return VLC_EGENERIC;
259     }
260     skip_space( &psz_command );
261     if( isdigit( *psz_command ) )
262     {
263         if( parse_digit( &psz_command, &g ) == VLC_EGENERIC )
264             return VLC_EGENERIC;
265     }
266     skip_space( &psz_command );
267     if( isdigit( *psz_command ) )
268     {
269         if( parse_digit( &psz_command, &b ) == VLC_EGENERIC )
270             return VLC_EGENERIC;
271     }
272     p_params->fontstyle.i_font_color = (r<<16) | (g<<8) | (b<<0);
273     return VLC_SUCCESS;
274 }
275
276 static int parser_SetTextSize( char *psz_command, char *psz_end,
277                                commandparams_t *p_params )
278 {
279     VLC_UNUSED(psz_end);
280     skip_space( &psz_command );
281     if( isdigit( *psz_command ) )
282     {
283         if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
284             return VLC_EGENERIC;
285     }
286     skip_space( &psz_command );
287     if( isdigit( *psz_command ) )
288     {
289         if( parse_digit( &psz_command, &p_params->fontstyle.i_font_size ) == VLC_EGENERIC )
290             return VLC_EGENERIC;
291     }
292     return VLC_SUCCESS;
293 }
294
295 static int parser_SetVisibility( char *psz_command, char *psz_end,
296                                  commandparams_t *p_params )
297 {
298     VLC_UNUSED(psz_end);
299     skip_space( &psz_command );
300     if( isdigit( *psz_command ) )
301     {
302         if( parse_digit( &psz_command, &p_params->i_id ) == VLC_EGENERIC )
303             return VLC_EGENERIC;
304     }
305     skip_space( &psz_command );
306     if( isdigit( *psz_command ) )
307     {
308         int32_t i_vis = 0;
309         if( parse_digit( &psz_command, &i_vis ) == VLC_EGENERIC )
310             return VLC_EGENERIC;
311         p_params->b_visible = (i_vis == 1) ? true : false;
312     }
313     return VLC_SUCCESS;
314 }
315
316 /*****************************************************************************
317  * Command unparser functions
318  *****************************************************************************/
319
320 static int unparse_default( const commandparams_t *p_results,
321                             buffer_t *p_output )
322 {
323     VLC_UNUSED(p_results);
324     VLC_UNUSED(p_output);
325     return VLC_SUCCESS;
326 }
327
328 static int unparse_GenImage( const commandparams_t *p_results,
329                              buffer_t *p_output )
330 {
331     int ret = BufferPrintf( p_output, " %d", p_results->i_id );
332     if( ret != VLC_SUCCESS )
333         return ret;
334
335     return VLC_SUCCESS;
336 }
337
338 static int unparse_GetAlpha( const commandparams_t *p_results,
339                              buffer_t *p_output )
340 {
341     int ret = BufferPrintf( p_output, " %d", p_results->i_alpha );
342     if( ret != VLC_SUCCESS )
343         return ret;
344
345     return VLC_SUCCESS;
346 }
347
348 static int unparse_GetPosition( const commandparams_t *p_results,
349                                 buffer_t *p_output )
350 {
351     int ret = BufferPrintf( p_output, " %d", p_results->i_x );
352     if( ret != VLC_SUCCESS )
353         return ret;
354
355     ret = BufferPrintf( p_output, " %d", p_results->i_y );
356     if( ret != VLC_SUCCESS )
357         return ret;
358
359     return VLC_SUCCESS;
360 }
361
362 static int unparse_GetTextAlpha( const commandparams_t *p_results,
363                                  buffer_t *p_output )
364 {
365     int ret = BufferPrintf( p_output, " %d", p_results->fontstyle.i_font_alpha );
366     if( ret != VLC_SUCCESS )
367         return ret;
368
369     return VLC_SUCCESS;
370 }
371
372 static int unparse_GetTextColor( const commandparams_t *p_results,
373                                  buffer_t *p_output )
374 {
375     int ret = BufferPrintf( p_output, " %d", (p_results->fontstyle.i_font_color & 0xff0000)>>16 );
376     if( ret != VLC_SUCCESS )
377         return ret;
378
379     ret = BufferPrintf( p_output, " %d", (p_results->fontstyle.i_font_color & 0x00ff00)>>8 );
380     if( ret != VLC_SUCCESS )
381         return ret;
382
383     ret = BufferPrintf( p_output, " %d", (p_results->fontstyle.i_font_color & 0x0000ff) );
384     if( ret != VLC_SUCCESS )
385         return ret;
386
387     return VLC_SUCCESS;
388 }
389
390 static int unparse_GetTextSize( const commandparams_t *p_results,
391                                 buffer_t *p_output )
392 {
393     int ret = BufferPrintf( p_output, " %d", p_results->fontstyle.i_font_size );
394     if( ret != VLC_SUCCESS )
395         return ret;
396
397     return VLC_SUCCESS;
398 }
399
400 static int unparse_GetVisibility( const commandparams_t *p_results,
401                              buffer_t *p_output )
402 {
403     int ret = BufferPrintf( p_output, " %d", (p_results->b_visible ? 1 : 0) );
404     if( ret != VLC_SUCCESS ) {
405         return ret;
406     }
407     return VLC_SUCCESS;
408 }
409
410 /*****************************************************************************
411  * Command functions
412  *****************************************************************************/
413 static int exec_DataSharedMem( filter_t *p_filter,
414                                const commandparams_t *p_params,
415                                commandparams_t *p_results )
416 {
417 #if defined(HAVE_SYS_SHM_H)
418     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
419     struct shmid_ds shminfo;
420     overlay_t *p_ovl;
421     size_t i_size;
422
423     VLC_UNUSED(p_results);
424
425     p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
426     if( p_ovl == NULL )
427     {
428         msg_Err( p_filter, "Invalid overlay: %d", p_params->i_id );
429         return VLC_EGENERIC;
430     }
431
432     if( shmctl( p_params->i_shmid, IPC_STAT, &shminfo ) == -1 )
433     {
434         msg_Err( p_filter, "Unable to access shared memory" );
435         return VLC_EGENERIC;
436     }
437     i_size = shminfo.shm_segsz;
438
439     if( p_params->fourcc == VLC_FOURCC('T','E','X','T') )
440     {
441         char *p_data;
442
443         if( (p_params->i_height != 1) || (p_params->i_width < 1) )
444         {
445             msg_Err( p_filter,
446                      "Invalid width and/or height. when specifing text height "
447                      "must be 1 and width the number of bytes in the string, "
448                      "including the null terminator" );
449             return VLC_EGENERIC;
450         }
451
452         if( (size_t)p_params->i_width > i_size )
453         {
454             msg_Err( p_filter,
455                      "Insufficient data in shared memory. need %d, got %zu",
456                      p_params->i_width, i_size );
457             return VLC_EGENERIC;
458         }
459
460         p_ovl->data.p_text = malloc( p_params->i_width );
461         if( p_ovl->data.p_text == NULL )
462         {
463             msg_Err( p_filter, "Unable to allocate string storage" );
464             return VLC_ENOMEM;
465         }
466
467         vout_InitFormat( &p_ovl->format, VLC_FOURCC('T','E','X','T'),
468                          0, 0, 0 );
469
470         p_data = shmat( p_params->i_shmid, NULL, SHM_RDONLY );
471         if( p_data == NULL )
472         {
473             msg_Err( p_filter, "Unable to attach to shared memory" );
474             free( p_ovl->data.p_text );
475             p_ovl->data.p_text = NULL;
476             return VLC_ENOMEM;
477         }
478         memcpy( p_ovl->data.p_text, p_data, p_params->i_width );
479
480         shmdt( p_data );
481     }
482     else
483     {
484         uint8_t *p_data, *p_in;
485         size_t i_neededsize = 0;
486
487         p_ovl->data.p_pic = malloc( sizeof( picture_t ) );
488         if( p_ovl->data.p_pic == NULL )
489             return VLC_ENOMEM;
490
491         vout_InitFormat( &p_ovl->format, p_params->fourcc,
492                          p_params->i_width, p_params->i_height,
493                          VOUT_ASPECT_FACTOR );
494         if( vout_AllocatePicture( p_filter, p_ovl->data.p_pic,
495                                   p_ovl->format.i_chroma, p_params->i_width,
496                                   p_params->i_height, p_ovl->format.i_aspect ) )
497         {
498             msg_Err( p_filter, "Unable to allocate picture" );
499             free( p_ovl->data.p_pic );
500             p_ovl->data.p_pic = NULL;
501             return VLC_ENOMEM;
502         }
503
504         for( size_t i_plane = 0; i_plane < (size_t)p_ovl->data.p_pic->i_planes;
505              ++i_plane )
506         {
507             i_neededsize += p_ovl->data.p_pic->p[i_plane].i_visible_lines *
508                             p_ovl->data.p_pic->p[i_plane].i_visible_pitch;
509         }
510
511         if( i_neededsize > i_size )
512         {
513             msg_Err( p_filter,
514                      "Insufficient data in shared memory. need %zu, got %zu",
515                      i_neededsize, i_size );
516             picture_Release( p_ovl->data.p_pic );
517             free( p_ovl->data.p_pic );
518             p_ovl->data.p_pic = NULL;
519             return VLC_EGENERIC;
520         }
521
522         p_data = shmat( p_params->i_shmid, NULL, SHM_RDONLY );
523         if( p_data == NULL )
524         {
525             msg_Err( p_filter, "Unable to attach to shared memory" );
526             picture_Release( p_ovl->data.p_pic );
527             free( p_ovl->data.p_pic );
528             p_ovl->data.p_pic = NULL;
529             return VLC_ENOMEM;
530         }
531
532         p_in = p_data;
533         for( size_t i_plane = 0; i_plane < (size_t)p_ovl->data.p_pic->i_planes;
534              ++i_plane )
535         {
536             uint8_t *p_out = p_ovl->data.p_pic->p[i_plane].p_pixels;
537             for( size_t i_line = 0;
538                  i_line < (size_t)p_ovl->data.p_pic->p[i_plane].i_visible_lines;
539                  ++i_line )
540             {
541                 vlc_memcpy( p_out, p_in,
542                             p_ovl->data.p_pic->p[i_plane].i_visible_pitch );
543                 p_out += p_ovl->data.p_pic->p[i_plane].i_pitch;
544                 p_in += p_ovl->data.p_pic->p[i_plane].i_visible_pitch;
545             }
546         }
547         shmdt( p_data );
548     }
549     p_sys->b_updated = p_ovl->b_active;
550
551     return VLC_SUCCESS;
552 #else
553     VLC_UNUSED(p_params);
554     VLC_UNUSED(p_results);
555
556     msg_Err( p_filter, "system doesn't support shared memory" );
557     return VLC_EGENERIC;
558 #endif
559 }
560
561 static int exec_DeleteImage( filter_t *p_filter,
562                              const commandparams_t *p_params,
563                              commandparams_t *p_results )
564 {
565     VLC_UNUSED(p_results);
566     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
567     p_sys->b_updated = true;
568
569     return ListRemove( &p_sys->overlays, p_params->i_id );
570 }
571
572 static int exec_EndAtomic( filter_t *p_filter,
573                            const commandparams_t *p_params,
574                            commandparams_t *p_results )
575 {
576     VLC_UNUSED(p_params);
577     VLC_UNUSED(p_results);
578     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
579     QueueTransfer( &p_sys->pending, &p_sys->atomic );
580     p_sys->b_atomic = false;
581     return VLC_SUCCESS;
582 }
583
584 static int exec_GenImage( filter_t *p_filter,
585                           const commandparams_t *p_params,
586                           commandparams_t *p_results )
587 {
588     VLC_UNUSED(p_params);
589     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
590
591     overlay_t *p_ovl = OverlayCreate();
592     if( p_ovl == NULL )
593         return VLC_ENOMEM;
594
595     ssize_t i_idx = ListAdd( &p_sys->overlays, p_ovl );
596     if( i_idx < 0 )
597         return i_idx;
598
599     p_results->i_id = i_idx;
600     return VLC_SUCCESS;
601 }
602
603 static int exec_GetAlpha( filter_t *p_filter,
604                           const commandparams_t *p_params,
605                           commandparams_t *p_results )
606 {
607     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
608     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
609     if( p_ovl == NULL )
610         return VLC_EGENERIC;
611
612     p_results->i_alpha = p_ovl->i_alpha;
613     return VLC_SUCCESS;
614 }
615
616 static int exec_GetPosition( filter_t *p_filter,
617                              const commandparams_t *p_params,
618                              commandparams_t *p_results )
619 {
620     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
621     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
622     if( p_ovl == NULL )
623         return VLC_EGENERIC;
624
625     p_results->i_x = p_ovl->i_x;
626     p_results->i_y = p_ovl->i_y;
627     return VLC_SUCCESS;
628 }
629
630 static int exec_GetTextAlpha( filter_t *p_filter,
631                               const commandparams_t *p_params,
632                               commandparams_t *p_results )
633 {
634     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
635     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
636     if( p_ovl == NULL )
637         return VLC_EGENERIC;
638
639     p_results->fontstyle.i_font_alpha = p_ovl->fontstyle.i_font_alpha;
640     return VLC_SUCCESS;
641 }
642
643 static int exec_GetTextColor( filter_t *p_filter,
644                               const commandparams_t *p_params,
645                               commandparams_t *p_results )
646 {
647     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
648     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
649     if( p_ovl == NULL )
650         return VLC_EGENERIC;
651
652     p_results->fontstyle.i_font_color = p_ovl->fontstyle.i_font_color;
653     return VLC_SUCCESS;
654 }
655
656 static int exec_GetTextSize( filter_t *p_filter,
657                              const commandparams_t *p_params,
658                              commandparams_t *p_results )
659 {
660     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
661     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
662     if( p_ovl == NULL )
663         return VLC_EGENERIC;
664
665     p_results->fontstyle.i_font_size = p_ovl->fontstyle.i_font_size;
666     return VLC_SUCCESS;
667 }
668
669 static int exec_GetVisibility( filter_t *p_filter,
670                                const commandparams_t *p_params,
671                                commandparams_t *p_results )
672 {
673     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
674
675     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
676     if( p_ovl == NULL )
677         return VLC_EGENERIC;
678
679     p_results->b_visible = ( p_ovl->b_active == true ) ? 1 : 0;
680     return VLC_SUCCESS;
681 }
682
683 static int exec_SetAlpha( filter_t *p_filter,
684                           const commandparams_t *p_params,
685                           commandparams_t *p_results )
686 {
687     VLC_UNUSED(p_results);
688     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
689
690     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
691     if( p_ovl == NULL )
692         return VLC_EGENERIC;
693
694     p_ovl->i_alpha = p_params->i_alpha;
695     p_sys->b_updated = p_ovl->b_active;
696     return VLC_SUCCESS;
697 }
698
699 static int exec_SetPosition( filter_t *p_filter,
700                              const commandparams_t *p_params,
701                              commandparams_t *p_results )
702 {
703     VLC_UNUSED(p_results);
704     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
705
706     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
707     if( p_ovl == NULL )
708         return VLC_EGENERIC;
709
710     p_ovl->i_x = p_params->i_x;
711     p_ovl->i_y = p_params->i_y;
712
713     p_sys->b_updated = p_ovl->b_active;
714     return VLC_SUCCESS;
715 }
716
717 static int exec_SetTextAlpha( filter_t *p_filter,
718                               const commandparams_t *p_params,
719                               commandparams_t *p_results )
720 {
721     VLC_UNUSED(p_results);
722     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
723
724     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
725     if( p_ovl == NULL )
726         return VLC_EGENERIC;
727
728     p_ovl->fontstyle.i_font_alpha = p_params->fontstyle.i_font_alpha;
729     p_sys->b_updated = p_ovl->b_active;
730     return VLC_SUCCESS;
731 }
732
733 static int exec_SetTextColor( filter_t *p_filter,
734                               const commandparams_t *p_params,
735                               commandparams_t *p_results )
736 {
737     VLC_UNUSED(p_results);
738     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
739
740     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
741     if( p_ovl == NULL )
742         return VLC_EGENERIC;
743
744     p_ovl->fontstyle.i_font_color = p_params->fontstyle.i_font_color;
745     p_sys->b_updated = p_ovl->b_active;
746     return VLC_SUCCESS;
747 }
748
749 static int exec_SetTextSize( filter_t *p_filter,
750                               const commandparams_t *p_params,
751                               commandparams_t *p_results )
752 {
753     VLC_UNUSED(p_results);
754     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
755
756     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
757     if( p_ovl == NULL )
758         return VLC_EGENERIC;
759
760     p_ovl->fontstyle.i_font_size = p_params->fontstyle.i_font_size;
761     p_sys->b_updated = p_ovl->b_active;
762     return VLC_SUCCESS;
763 }
764
765 static int exec_SetVisibility( filter_t *p_filter,
766                                const commandparams_t *p_params,
767                                commandparams_t *p_results )
768 {
769     VLC_UNUSED(p_results);
770     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
771
772     overlay_t *p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
773     if( p_ovl == NULL )
774         return VLC_EGENERIC;
775
776     p_ovl->b_active = p_params->b_visible;// ? false : true;
777     p_sys->b_updated = true;
778     return VLC_SUCCESS;
779 }
780
781 static int exec_StartAtomic( filter_t *p_filter,
782                              const commandparams_t *p_params,
783                              commandparams_t *p_results )
784 {
785     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
786     VLC_UNUSED(p_params);
787     VLC_UNUSED(p_results);
788
789     p_sys->b_atomic = true;
790     return VLC_SUCCESS;
791 }
792
793 /*****************************************************************************
794  * Command functions
795  *****************************************************************************/
796 static const commanddesc_t p_commands[] =
797 {
798     {   .psz_command = "DataSharedMem",
799         .b_atomic = true,
800         .pf_parser = parser_DataSharedMem,
801         .pf_execute = exec_DataSharedMem,
802         .pf_unparse = unparse_default,
803     },
804     {   .psz_command = "DeleteImage",
805         .b_atomic = true,
806         .pf_parser = parser_Id,
807         .pf_execute = exec_DeleteImage,
808         .pf_unparse = unparse_default,
809     },
810     {   .psz_command = "EndAtomic",
811         .b_atomic = false,
812         .pf_parser = parser_None,
813         .pf_execute = exec_EndAtomic,
814         .pf_unparse = unparse_default,
815     },
816     {   .psz_command = "GenImage",
817         .b_atomic = false,
818         .pf_parser = parser_None,
819         .pf_execute = exec_GenImage,
820         .pf_unparse = unparse_GenImage,
821     },
822     {   .psz_command = "GetAlpha",
823         .b_atomic = false,
824         .pf_parser = parser_Id,
825         .pf_execute = exec_GetAlpha,
826         .pf_unparse = unparse_GetAlpha,
827     },
828     {   .psz_command = "GetPosition",
829         .b_atomic = false,
830         .pf_parser = parser_Id,
831         .pf_execute = exec_GetPosition,
832         .pf_unparse = unparse_GetPosition,
833     },
834     {   .psz_command = "GetTextAlpha",
835         .b_atomic = false,
836         .pf_parser = parser_Id,
837         .pf_execute = exec_GetTextAlpha,
838         .pf_unparse = unparse_GetTextAlpha,
839     },
840     {   .psz_command = "GetTextColor",
841         .b_atomic = false,
842         .pf_parser = parser_Id,
843         .pf_execute = exec_GetTextColor,
844         .pf_unparse = unparse_GetTextColor,
845     },
846     {   .psz_command = "GetTextSize",
847         .b_atomic = true,
848         .pf_parser = parser_Id,
849         .pf_execute = exec_GetTextSize,
850         .pf_unparse = unparse_GetTextSize,
851     },
852     {   .psz_command = "GetVisibility",
853         .b_atomic = false,
854         .pf_parser = parser_Id,
855         .pf_execute = exec_GetVisibility,
856         .pf_unparse = unparse_GetVisibility,
857     },
858     {   .psz_command = "SetAlpha",
859         .b_atomic = true,
860         .pf_parser = parser_SetAlpha,
861         .pf_execute = exec_SetAlpha,
862         .pf_unparse = unparse_default,
863     },
864     {   .psz_command = "SetPosition",
865         .b_atomic = true,
866         .pf_parser = parser_SetPosition,
867         .pf_execute = exec_SetPosition,
868         .pf_unparse = unparse_default,
869     },
870     {   .psz_command = "SetTextAlpha",
871         .b_atomic = true,
872         .pf_parser = parser_SetTextAlpha,
873         .pf_execute = exec_SetTextAlpha,
874         .pf_unparse = unparse_default,
875     },
876     {   .psz_command = "SetTextColor",
877         .b_atomic = true,
878         .pf_parser = parser_SetTextColor,
879         .pf_execute = exec_SetTextColor,
880         .pf_unparse = unparse_default,
881     },
882     {   .psz_command = "SetTextSize",
883         .b_atomic = true,
884         .pf_parser = parser_SetTextSize,
885         .pf_execute = exec_SetTextSize,
886         .pf_unparse = unparse_default,
887     },
888     {   .psz_command = "SetVisibility",
889         .b_atomic = true,
890         .pf_parser = parser_SetVisibility,
891         .pf_execute = exec_SetVisibility,
892         .pf_unparse = unparse_default,
893     },
894     {   .psz_command = "StartAtomic",
895         .b_atomic = true,
896         .pf_parser = parser_None,
897         .pf_execute = exec_StartAtomic,
898         .pf_unparse = unparse_default,
899     }
900 };
901
902 void RegisterCommand( filter_t *p_filter )
903 {
904     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
905     size_t i_index = 0;
906
907     p_sys->i_commands = ARRAY_SIZE(p_commands);
908     p_sys->pp_commands = (commanddesc_t **) calloc( p_sys->i_commands, sizeof(commanddesc_t*) );
909     if( !p_sys->pp_commands ) return;
910     for( i_index = 0; i_index < p_sys->i_commands; i_index ++ )
911     {
912         p_sys->pp_commands[i_index] = (commanddesc_t *) malloc( sizeof(commanddesc_t) );
913         if( !p_sys->pp_commands[i_index] ) return;
914         p_sys->pp_commands[i_index]->psz_command = strdup( p_commands[i_index].psz_command );
915         p_sys->pp_commands[i_index]->b_atomic = p_commands[i_index].b_atomic;
916         p_sys->pp_commands[i_index]->pf_parser = p_commands[i_index].pf_parser;
917         p_sys->pp_commands[i_index]->pf_execute = p_commands[i_index].pf_execute;
918         p_sys->pp_commands[i_index]->pf_unparse = p_commands[i_index].pf_unparse;
919     }
920
921     msg_Dbg( p_filter, "%zu commands are available", p_sys->i_commands );
922     for( size_t i_index = 0; i_index < p_sys->i_commands; i_index++ )
923         msg_Dbg( p_filter, "    %s", p_sys->pp_commands[i_index]->psz_command );
924 }
925
926 void UnregisterCommand( filter_t *p_filter )
927 {
928     filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
929     size_t i_index = 0;
930
931     for( i_index = 0; i_index < p_sys->i_commands; i_index++ )
932     {
933         free( p_sys->pp_commands[i_index]->psz_command );
934         free( p_sys->pp_commands[i_index] );
935     }
936     free( p_sys->pp_commands );
937     p_sys->pp_commands = NULL;
938     p_sys->i_commands = 0;
939 }