]> git.sesse.net Git - vlc/blob - modules/video_filter/marq.c
forward port [17012] and make update-po
[vlc] / modules / video_filter / marq.c
1 /*****************************************************************************
2  * marq.c : marquee display video plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2003-2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Mark Moriarty
8  *          Sigmund Augdal Helberg <dnumgis@videolan.org>
9  *          Antoine Cellerier <dionoea . videolan \ org>
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 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <stdlib.h>                                      /* malloc(), free() */
30 #include <string.h>
31
32 #include <time.h>
33
34 #include <vlc/vlc.h>
35 #include <vlc/vout.h>
36
37 #include "vlc_filter.h"
38 #include "vlc_block.h"
39 #include "vlc_osd.h"
40 #include "vlc_playlist.h"
41 #include "vlc_meta.h"
42 #include "vlc_input.h"
43 #include <vlc/aout.h>
44
45 /*****************************************************************************
46  * Local prototypes
47  *****************************************************************************/
48 static int  CreateFilter ( vlc_object_t * );
49 static void DestroyFilter( vlc_object_t * );
50 static subpicture_t *Filter( filter_t *, mtime_t );
51
52
53 static int MarqueeCallback( vlc_object_t *p_this, char const *psz_var,
54                             vlc_value_t oldval, vlc_value_t newval,
55                             void *p_data );
56 static int pi_color_values[] = { 0xf0000000, 0x00000000, 0x00808080, 0x00C0C0C0,
57                0x00FFFFFF, 0x00800000, 0x00FF0000, 0x00FF00FF, 0x00FFFF00,
58                0x00808000, 0x00008000, 0x00008080, 0x0000FF00, 0x00800080,
59                0x00000080, 0x000000FF, 0x0000FFFF};
60 static char *ppsz_color_descriptions[] = { N_("Default"), N_("Black"),
61                N_("Gray"), N_("Silver"), N_("White"), N_("Maroon"), N_("Red"),
62                N_("Fuchsia"), N_("Yellow"), N_("Olive"), N_("Green"),
63                N_("Teal"), N_("Lime"), N_("Purple"), N_("Navy"), N_("Blue"),
64                N_("Aqua") };
65
66 /*****************************************************************************
67  * filter_sys_t: marquee filter descriptor
68  *****************************************************************************/
69 struct filter_sys_t
70 {
71     int i_xoff, i_yoff;  /* offsets for the display string in the video window */
72     int i_pos; /* permit relative positioning (top, bottom, left, right, center) */
73     int i_timeout;
74
75     char *psz_marquee;    /* marquee string */
76
77     text_style_t *p_style; /* font control */
78
79     time_t last_time;
80
81     vlc_bool_t b_need_update;
82 };
83
84 #define MSG_TEXT N_("Text")
85 #define MSG_LONGTEXT N_( \
86     "Marquee text to display. " \
87     "(Available format strings: " \
88     "Time related: %Y = year, %m = month, %d = day, %H = hour, " \
89     "%M = minute, %S = second, ... " \
90     "Meta data related: $a = artist, $b = album, $c = copyright, " \
91     "$d = description, $e = encoded by, $g = genre, " \
92     "$l = language, $n = track num, $p = now playing, " \
93     "$r = rating, $s = subtitles language, $t = title, "\
94     "$u = url, $A = date, " \
95     "$B = audio bitrate (in kb/s), $C = chapter," \
96     "$D = duration, $F = full name with path, $I = title, "\
97     "$L = time left, " \
98     "$N = name, $O = audio language, $P = position (in %), $R = rate, " \
99     "$S = audio sample rate (in kHz), " \
100     "$T = time, $U = publisher, $V = volume, $_ = new line) ")
101 #define POSX_TEXT N_("X offset")
102 #define POSX_LONGTEXT N_("X offset, from the left screen edge." )
103 #define POSY_TEXT N_("Y offset")
104 #define POSY_LONGTEXT N_("Y offset, down from the top." )
105 #define TIMEOUT_TEXT N_("Timeout")
106 #define TIMEOUT_LONGTEXT N_("Number of milliseconds the marquee must remain " \
107                             "displayed. Default value is " \
108                             "0 (remains forever).")
109 #define OPACITY_TEXT N_("Opacity")
110 #define OPACITY_LONGTEXT N_("Opacity (inverse of transparency) of " \
111     "overlayed text. 0 = transparent, 255 = totally opaque. " )
112 #define SIZE_TEXT N_("Font size, pixels")
113 #define SIZE_LONGTEXT N_("Font size, in pixels. Default is -1 (use default " \
114     "font size)." )
115
116 #define COLOR_TEXT N_("Color")
117 #define COLOR_LONGTEXT N_("Color of the text that will be rendered on "\
118     "the video. This must be an hexadecimal (like HTML colors). The first two "\
119     "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
120     " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
121
122 #define POS_TEXT N_("Marquee position")
123 #define POS_LONGTEXT N_( \
124   "You can enforce the marquee position on the video " \
125   "(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \
126   "also use combinations of these values, eg 6 = top-right).")
127
128 static int pi_pos_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };
129 static char *ppsz_pos_descriptions[] =
130      { N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
131      N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };
132
133 #define CFG_PREFIX "marq-"
134
135 /*****************************************************************************
136  * Module descriptor
137  *****************************************************************************/
138 vlc_module_begin();
139     set_capability( "sub filter", 0 );
140     set_shortname( _("Marquee" ));
141     set_callbacks( CreateFilter, DestroyFilter );
142     set_category( CAT_VIDEO );
143     set_subcategory( SUBCAT_VIDEO_SUBPIC );
144     add_string( CFG_PREFIX "marquee", "VLC", NULL, MSG_TEXT, MSG_LONGTEXT,
145                 VLC_FALSE );
146
147     set_section( N_("Position"), NULL );
148     add_integer( CFG_PREFIX "x", -1, NULL, POSX_TEXT, POSX_LONGTEXT, VLC_TRUE );
149     add_integer( CFG_PREFIX "y", 0, NULL, POSY_TEXT, POSY_LONGTEXT, VLC_TRUE );
150     add_integer( CFG_PREFIX "position", 5, NULL, POS_TEXT, POS_LONGTEXT, VLC_FALSE );
151
152     set_section( N_("Font"), NULL );
153     /* 5 sets the default to top [1] left [4] */
154     change_integer_list( pi_pos_values, ppsz_pos_descriptions, 0 );
155     add_integer_with_range( CFG_PREFIX "opacity", 255, 0, 255, NULL,
156         OPACITY_TEXT, OPACITY_LONGTEXT, VLC_FALSE );
157     add_integer( CFG_PREFIX "color", 0xFFFFFF, NULL, COLOR_TEXT, COLOR_LONGTEXT,
158                  VLC_FALSE );
159         change_integer_list( pi_color_values, ppsz_color_descriptions, 0 );
160     add_integer( CFG_PREFIX "size", -1, NULL, SIZE_TEXT, SIZE_LONGTEXT,
161                  VLC_FALSE );
162
163     set_section( N_("Misc"), NULL );
164     add_integer( CFG_PREFIX "timeout", 0, NULL, TIMEOUT_TEXT, TIMEOUT_LONGTEXT,
165                  VLC_FALSE );
166
167     set_description( _("Marquee display") );
168     add_shortcut( "marq" );
169     add_shortcut( "time" );
170 vlc_module_end();
171
172 static const char *ppsz_filter_options[] = {
173     "marquee", "x", "y", "position", "color", "size", "timeout", NULL
174 };
175
176 /*****************************************************************************
177  * CreateFilter: allocates marquee video filter
178  *****************************************************************************/
179 static int CreateFilter( vlc_object_t *p_this )
180 {
181     filter_t *p_filter = (filter_t *)p_this;
182     filter_sys_t *p_sys;
183
184     /* Allocate structure */
185     p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
186     if( p_sys == NULL )
187     {
188         msg_Err( p_filter, "out of memory" );
189         return VLC_ENOMEM;
190     }
191
192     p_sys->p_style = malloc( sizeof( text_style_t ) );
193     memcpy( p_sys->p_style, &default_text_style, sizeof( text_style_t ) );
194
195     config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
196                        p_filter->p_cfg );
197
198 #define CREATE_VAR( stor, type, var ) \
199     p_sys->stor = var_CreateGet##type( p_filter, var ); \
200     var_AddCallback( p_filter, var, MarqueeCallback, p_sys );
201
202     CREATE_VAR( i_xoff, Integer, "marq-x" );
203     CREATE_VAR( i_yoff, Integer, "marq-y" );
204     CREATE_VAR( i_timeout,Integer, "marq-timeout" );
205     CREATE_VAR( i_pos, Integer, "marq-position" );
206     CREATE_VAR( psz_marquee, String, "marq-marquee" );
207     CREATE_VAR( p_style->i_font_alpha, Integer, "marq-opacity" );
208     CREATE_VAR( p_style->i_font_color, Integer, "marq-color" );
209     CREATE_VAR( p_style->i_font_size, Integer, "marq-size" );
210
211     p_sys->p_style->i_font_alpha = 255 - p_sys->p_style->i_font_alpha ;
212
213     /* Misc init */
214     p_filter->pf_sub_filter = Filter;
215     p_sys->last_time = ((time_t)-1);
216     p_sys->b_need_update = VLC_TRUE;
217
218     return VLC_SUCCESS;
219 }
220 /*****************************************************************************
221  * DestroyFilter: destroy marquee video filter
222  *****************************************************************************/
223 static void DestroyFilter( vlc_object_t *p_this )
224 {
225     filter_t *p_filter = (filter_t *)p_this;
226     filter_sys_t *p_sys = p_filter->p_sys;
227
228     if( p_sys->p_style ) free( p_sys->p_style );
229     if( p_sys->psz_marquee ) free( p_sys->psz_marquee );
230     free( p_sys );
231
232     /* Delete the marquee variables */
233 #define DEL_VAR(var) \
234     var_DelCallback( p_filter, var, MarqueeCallback, p_sys ); \
235     var_Destroy( p_filter, var );
236     DEL_VAR( "marq-x" );
237     DEL_VAR( "marq-y" );
238     DEL_VAR( "marq-marquee" );
239     DEL_VAR( "marq-timeout" );
240     DEL_VAR( "marq-position" );
241     DEL_VAR( "marq-color" );
242     DEL_VAR( "marq-opacity" );
243     DEL_VAR( "marq-size" );
244 }
245 /****************************************************************************
246  * String formating functions
247  ****************************************************************************/
248
249 static char *FormatTime(char *tformat )
250 {
251     char buffer[255];
252     time_t curtime;
253 #if defined(HAVE_LOCALTIME_R)
254     struct tm loctime;
255 #else
256     struct tm *loctime;
257 #endif
258
259     /* Get the current time.  */
260     curtime = time( NULL );
261
262     /* Convert it to local time representation.  */
263 #if defined(HAVE_LOCALTIME_R)
264     localtime_r( &curtime, &loctime );
265     strftime( buffer, 255, tformat, &loctime );
266 #else
267     loctime = localtime( &curtime );
268     strftime( buffer, 255, tformat, loctime );
269 #endif
270     return strdup( buffer );
271 }
272
273 #define INSERT_STRING( check, string )                              \
274                     if( check && string )                           \
275                     {                                               \
276                         int len = strlen( string );                 \
277                         dst = realloc( dst,                         \
278                                        i_size = i_size + len + 1 ); \
279                         strncpy( d, string, len+1 );                \
280                         d += len;                                   \
281                     }                                               \
282                     else                                            \
283                     {                                               \
284                         *d = '-';                                   \
285                         d++;                                        \
286                     }
287 char *FormatMeta( vlc_object_t *p_object, char *string )
288 {
289     char *s = string;
290     char *dst = malloc( 1000 );
291     char *d = dst;
292     int b_is_format = 0;
293     char buf[10];
294     int i_size = strlen( string );
295
296     playlist_t *p_playlist = pl_Yield( p_object );
297     input_thread_t *p_input = p_playlist->p_input;
298     input_item_t *p_item = NULL;
299     pl_Release( p_object );
300     if( p_input )
301     {
302         vlc_object_yield( p_input );
303         p_item = p_input->input.p_item;
304         if( p_item )
305             vlc_mutex_lock( &p_item->lock );
306     }
307
308     sprintf( dst, string );
309
310     while( *s )
311     {
312         if( b_is_format )
313         {
314             switch( *s )
315             {
316                 case 'a':
317                     INSERT_STRING( p_item && p_item->p_meta,
318                                    p_item->p_meta->psz_artist );
319                     break;
320                 case 'b':
321                     INSERT_STRING( p_item && p_item->p_meta,
322                                    p_item->p_meta->psz_album );
323                     break;
324                 case 'c':
325                     INSERT_STRING( p_item && p_item->p_meta,
326                                    p_item->p_meta->psz_copyright );
327                     break;
328                 case 'd':
329                     INSERT_STRING( p_item && p_item->p_meta,
330                                    p_item->p_meta->psz_description );
331                     break;
332                 case 'e':
333                     INSERT_STRING( p_item && p_item->p_meta,
334                                    p_item->p_meta->psz_encodedby );
335                     break;
336                 case 'g':
337                     INSERT_STRING( p_item && p_item->p_meta,
338                                    p_item->p_meta->psz_genre );
339                     break;
340                 case 'l':
341                     INSERT_STRING( p_item && p_item->p_meta,
342                                    p_item->p_meta->psz_language );
343                     break;
344                 case 'n':
345                     INSERT_STRING( p_item && p_item->p_meta,
346                                    p_item->p_meta->psz_tracknum );
347                     break;
348                 case 'p':
349                     INSERT_STRING( p_item && p_item->p_meta,
350                                    p_item->p_meta->psz_nowplaying );
351                     break;
352                 case 'r':
353                     INSERT_STRING( p_item && p_item->p_meta,
354                                    p_item->p_meta->psz_rating );
355                     break;
356                 case 's':
357                 {
358                     char *lang;
359                     if( p_input )
360                     {
361                         lang = var_GetString( p_input, "sub-language" );
362                     }
363                     else
364                     {
365                         lang = strdup( "-" );
366                     }
367                     INSERT_STRING( 1, lang );
368                     free( lang );
369                     break;
370                 }
371                 case 't':
372                     INSERT_STRING( p_item && p_item->p_meta,
373                                    p_item->p_meta->psz_title );
374                     break;
375                 case 'u':
376                     INSERT_STRING( p_item && p_item->p_meta,
377                                    p_item->p_meta->psz_url );
378                     break;
379                 case 'A':
380                     INSERT_STRING( p_item && p_item->p_meta,
381                                    p_item->p_meta->psz_date );
382                     break;
383                 case 'B':
384                     if( p_input )
385                     {
386                         snprintf( buf, 10, "%d",
387                                   var_GetInteger( p_input, "bit-rate" )/1000 );
388                     }
389                     else
390                     {
391                         sprintf( buf, "-" );
392                     }
393                     INSERT_STRING( 1, buf );
394                     break;
395                 case 'C':
396                     if( p_input )
397                     {
398                         snprintf( buf, 10, "%d",
399                                   var_GetInteger( p_input, "chapter" ) );
400                     }
401                     else
402                     {
403                         sprintf( buf, "-" );
404                     }
405                     INSERT_STRING( 1, buf );
406                     break;
407                 case 'D':
408                     if( p_item )
409                     {
410                         sprintf( buf, "%02d:%02d:%02d",
411                                  (int)(p_item->i_duration/(3600000000)),
412                                  (int)((p_item->i_duration/(60000000))%60),
413                                  (int)((p_item->i_duration/1000000)%60) );
414                     }
415                     else
416                     {
417                         sprintf( buf, "--:--:--" );
418                     }
419                     INSERT_STRING( 1, buf );
420                     break;
421                 case 'F':
422                     INSERT_STRING( p_item, p_item->psz_uri );
423                     break;
424                 case 'I':
425                     if( p_input )
426                     {
427                         snprintf( buf, 10, "%d",
428                                   var_GetInteger( p_input, "title" ) );
429                     }
430                     else
431                     {
432                         sprintf( buf, "-" );
433                     }
434                     INSERT_STRING( 1, buf );
435                     break;
436                 case 'L':
437                     if( p_item && p_input )
438                     {
439                         sprintf( buf, "%02d:%02d:%02d",
440                      (int)((p_item->i_duration-p_input->i_time)/(3600000000)),
441                      (int)(((p_item->i_duration-p_input->i_time)/(60000000))%60),
442                      (int)(((p_item->i_duration-p_input->i_time)/1000000)%60) );
443                     }
444                     else
445                     {
446                         sprintf( buf, "--:--:--" );
447                     }
448                     INSERT_STRING( 1, buf );
449                     break;
450                 case 'N':
451                     INSERT_STRING( p_item, p_item->psz_name );
452                     break;
453                 case 'O':
454                 {
455                     char *lang;
456                     if( p_input )
457                     {
458                         lang = var_GetString( p_input, "audio-language" );
459                     }
460                     else
461                     {
462                         lang = strdup( "-" );
463                     }
464                     INSERT_STRING( 1, lang );
465                     free( lang );
466                     break;
467                 }
468                 case 'P':
469                     if( p_input )
470                     {
471                         snprintf( buf, 10, "%2.1lf",
472                                   var_GetFloat( p_input, "position" ) * 100. );
473                     }
474                     else
475                     {
476                         sprintf( buf, "--.-%%" );
477                     }
478                     INSERT_STRING( 1, buf );
479                     break;
480                 case 'R':
481                     if( p_input )
482                     {
483                         int r = var_GetInteger( p_input, "rate" );
484                         snprintf( buf, 10, "%d.%d", r/1000, r%1000 );
485                     }
486                     else
487                     {
488                         sprintf( buf, "-" );
489                     }
490                     INSERT_STRING( 1, buf );
491                     break;
492                 case 'S':
493                     if( p_input )
494                     {
495                         int r = var_GetInteger( p_input, "sample-rate" );
496                         snprintf( buf, 10, "%d.%d", r/1000, (r/100)%10 );
497                     }
498                     else
499                     {
500                         sprintf( buf, "-" );
501                     }
502                     INSERT_STRING( 1, buf );
503                     break;
504                 case 'T':
505                     if( p_input )
506                     {
507                         sprintf( buf, "%02d:%02d:%02d",
508                                  (int)(p_input->i_time/(3600000000)),
509                                  (int)((p_input->i_time/(60000000))%60),
510                                  (int)((p_input->i_time/1000000)%60) );
511                     }
512                     else
513                     {
514                         sprintf( buf, "--:--:--" );
515                     }
516                     INSERT_STRING( 1, buf );
517                     break;
518                 case 'U':
519                     INSERT_STRING( p_item && p_item->p_meta,
520                                    p_item->p_meta->psz_publisher );
521                     break;
522                 case 'V':
523                 {
524                     audio_volume_t volume;
525                     aout_VolumeGet( p_object, &volume );
526                     snprintf( buf, 10, "%d", volume );
527                     INSERT_STRING( 1, buf );
528                     break;
529                 }
530                 case '_':
531                     *d = '\n';
532                     d++;
533                     break;
534
535                 default:
536                     *d = *s;
537                     d++;
538                     break;
539             }
540             b_is_format = 0;
541         }
542         else if( *s == '$' )
543         {
544             b_is_format = 1;
545         }
546         else
547         {
548             *d = *s;
549             d++;
550         }
551         s++;
552     }
553     *d = '\0';
554
555     if( p_input )
556     {
557         vlc_object_release( p_input );
558         if( p_item )
559             vlc_mutex_unlock( &p_item->lock );
560     }
561
562     return dst;
563 }
564
565 /****************************************************************************
566  * Filter: the whole thing
567  ****************************************************************************
568  * This function outputs subpictures at regular time intervals.
569  ****************************************************************************/
570 static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
571 {
572     filter_sys_t *p_sys = p_filter->p_sys;
573     subpicture_t *p_spu;
574     video_format_t fmt;
575     time_t t;
576     char *buf;
577
578     if( p_sys->last_time == time( NULL ) )
579     {
580         return NULL;
581     }
582
583     if( p_sys->b_need_update == VLC_FALSE )
584     {
585         return NULL;
586     }
587
588     p_spu = p_filter->pf_sub_buffer_new( p_filter );
589     if( !p_spu ) return NULL;
590
591     memset( &fmt, 0, sizeof(video_format_t) );
592     fmt.i_chroma = VLC_FOURCC('T','E','X','T');
593     fmt.i_aspect = 0;
594     fmt.i_width = fmt.i_height = 0;
595     fmt.i_x_offset = 0;
596     fmt.i_y_offset = 0;
597     p_spu->p_region = p_spu->pf_create_region( VLC_OBJECT(p_filter), &fmt );
598     if( !p_spu->p_region )
599     {
600         p_filter->pf_sub_buffer_del( p_filter, p_spu );
601         return NULL;
602     }
603
604     t = p_sys->last_time = time( NULL );
605
606     if( strchr( p_sys->psz_marquee, '%' ) || strchr( p_sys->psz_marquee, '$' ) )
607     {
608         p_sys->b_need_update = VLC_TRUE;
609     }
610     else
611     {
612         p_sys->b_need_update = VLC_FALSE;
613     }
614     buf = FormatTime( p_sys->psz_marquee );
615     p_spu->p_region->psz_text = FormatMeta( VLC_OBJECT( p_filter ), buf );
616     free( buf );
617     p_spu->i_start = date;
618     p_spu->i_stop  = p_sys->i_timeout == 0 ? 0 : date + p_sys->i_timeout * 1000;
619     p_spu->b_ephemer = VLC_TRUE;
620
621     /*  where to locate the string: */
622     if( p_sys->i_xoff < 0 || p_sys->i_yoff < 0 )
623     {   /* set to one of the 9 relative locations */
624         p_spu->i_flags = p_sys->i_pos;
625         p_spu->i_x = 0;
626         p_spu->i_y = 0;
627         p_spu->b_absolute = VLC_FALSE;
628     }
629     else
630     {   /*  set to an absolute xy, referenced to upper left corner */
631         p_spu->i_flags = OSD_ALIGN_LEFT | OSD_ALIGN_TOP;
632         p_spu->i_x = p_sys->i_xoff;
633         p_spu->i_y = p_sys->i_yoff;
634         p_spu->b_absolute = VLC_TRUE;
635     }
636     p_spu->p_region->p_style = p_sys->p_style;
637
638     return p_spu;
639 }
640
641 /**********************************************************************
642  * Callback to update params on the fly
643  **********************************************************************/
644 static int MarqueeCallback( vlc_object_t *p_this, char const *psz_var,
645                             vlc_value_t oldval, vlc_value_t newval,
646                             void *p_data )
647 {
648     filter_sys_t *p_sys = (filter_sys_t *) p_data;
649
650     if( !strncmp( psz_var, "marq-marquee", 7 ) )
651     {
652         if( p_sys->psz_marquee ) free( p_sys->psz_marquee );
653         p_sys->psz_marquee = strdup( newval.psz_string );
654     }
655     else if ( !strncmp( psz_var, "marq-x", 6 ) )
656     {
657         p_sys->i_xoff = newval.i_int;
658     }
659     else if ( !strncmp( psz_var, "marq-y", 6 ) )
660     {
661         p_sys->i_yoff = newval.i_int;
662     }
663     else if ( !strncmp( psz_var, "marq-color", 8 ) )  /* "marq-col" */
664     {
665         p_sys->p_style->i_font_color = newval.i_int;
666     }
667     else if ( !strncmp( psz_var, "marq-opacity", 8 ) ) /* "marq-opa" */
668     {
669         p_sys->p_style->i_font_alpha = 255 - newval.i_int;
670     }
671     else if ( !strncmp( psz_var, "marq-size", 6 ) )
672     {
673         p_sys->p_style->i_font_size = newval.i_int;
674     }
675     else if ( !strncmp( psz_var, "marq-timeout", 12 ) )
676     {
677         p_sys->i_timeout = newval.i_int;
678     }
679     else if ( !strncmp( psz_var, "marq-position", 8 ) )
680     /* willing to accept a match against marq-pos */
681     {
682         p_sys->i_pos = newval.i_int;
683         p_sys->i_xoff = -1;       /* force to relative positioning */
684     }
685     p_sys->b_need_update = VLC_TRUE;
686     return VLC_SUCCESS;
687 }