]> git.sesse.net Git - vlc/blob - modules/video_filter/marq.c
b4e1dd4993d8d2bd391a20605a2e3db79d55f33a
[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
231     /* Delete the marquee variables */
232 #define DEL_VAR(var) \
233     var_DelCallback( p_filter, var, MarqueeCallback, p_sys ); \
234     var_Destroy( p_filter, var );
235     DEL_VAR( "marq-x" );
236     DEL_VAR( "marq-y" );
237     DEL_VAR( "marq-marquee" );
238     DEL_VAR( "marq-timeout" );
239     DEL_VAR( "marq-position" );
240     DEL_VAR( "marq-color" );
241     DEL_VAR( "marq-opacity" );
242     DEL_VAR( "marq-size" );
243
244     free( p_sys );
245 }
246 /****************************************************************************
247  * String formating functions
248  ****************************************************************************/
249
250 static char *FormatTime(char *tformat )
251 {
252     char buffer[255];
253     time_t curtime;
254 #if defined(HAVE_LOCALTIME_R)
255     struct tm loctime;
256 #else
257     struct tm *loctime;
258 #endif
259
260     /* Get the current time.  */
261     curtime = time( NULL );
262
263     /* Convert it to local time representation.  */
264 #if defined(HAVE_LOCALTIME_R)
265     localtime_r( &curtime, &loctime );
266     strftime( buffer, 255, tformat, &loctime );
267 #else
268     loctime = localtime( &curtime );
269     strftime( buffer, 255, tformat, loctime );
270 #endif
271     return strdup( buffer );
272 }
273
274 #define INSERT_STRING( check, string )                              \
275                     if( check && string )                           \
276                     {                                               \
277                         int len = strlen( string );                 \
278                         dst = realloc( dst,                         \
279                                        i_size = i_size + len + 1 ); \
280                         strncpy( d, string, len+1 );                \
281                         d += len;                                   \
282                     }                                               \
283                     else                                            \
284                     {                                               \
285                         *d = '-';                                   \
286                         d++;                                        \
287                     }
288 char *FormatMeta( vlc_object_t *p_object, char *string )
289 {
290     char *s = string;
291     char *dst = malloc( 1000 );
292     char *d = dst;
293     int b_is_format = 0;
294     char buf[10];
295     int i_size = strlen( string );
296
297     playlist_t *p_playlist = pl_Yield( p_object );
298     input_thread_t *p_input = p_playlist->p_input;
299     input_item_t *p_item = NULL;
300     pl_Release( p_object );
301     if( p_input )
302     {
303         vlc_object_yield( p_input );
304         p_item = p_input->input.p_item;
305         if( p_item )
306             vlc_mutex_lock( &p_item->lock );
307     }
308
309     sprintf( dst, string );
310
311     while( *s )
312     {
313         if( b_is_format )
314         {
315             switch( *s )
316             {
317                 case 'a':
318                     INSERT_STRING( p_item && p_item->p_meta,
319                                    p_item->p_meta->psz_artist );
320                     break;
321                 case 'b':
322                     INSERT_STRING( p_item && p_item->p_meta,
323                                    p_item->p_meta->psz_album );
324                     break;
325                 case 'c':
326                     INSERT_STRING( p_item && p_item->p_meta,
327                                    p_item->p_meta->psz_copyright );
328                     break;
329                 case 'd':
330                     INSERT_STRING( p_item && p_item->p_meta,
331                                    p_item->p_meta->psz_description );
332                     break;
333                 case 'e':
334                     INSERT_STRING( p_item && p_item->p_meta,
335                                    p_item->p_meta->psz_encodedby );
336                     break;
337                 case 'g':
338                     INSERT_STRING( p_item && p_item->p_meta,
339                                    p_item->p_meta->psz_genre );
340                     break;
341                 case 'l':
342                     INSERT_STRING( p_item && p_item->p_meta,
343                                    p_item->p_meta->psz_language );
344                     break;
345                 case 'n':
346                     INSERT_STRING( p_item && p_item->p_meta,
347                                    p_item->p_meta->psz_tracknum );
348                     break;
349                 case 'p':
350                     INSERT_STRING( p_item && p_item->p_meta,
351                                    p_item->p_meta->psz_nowplaying );
352                     break;
353                 case 'r':
354                     INSERT_STRING( p_item && p_item->p_meta,
355                                    p_item->p_meta->psz_rating );
356                     break;
357                 case 's':
358                 {
359                     char *lang;
360                     if( p_input )
361                     {
362                         lang = var_GetString( p_input, "sub-language" );
363                     }
364                     else
365                     {
366                         lang = strdup( "-" );
367                     }
368                     INSERT_STRING( 1, lang );
369                     free( lang );
370                     break;
371                 }
372                 case 't':
373                     INSERT_STRING( p_item && p_item->p_meta,
374                                    p_item->p_meta->psz_title );
375                     break;
376                 case 'u':
377                     INSERT_STRING( p_item && p_item->p_meta,
378                                    p_item->p_meta->psz_url );
379                     break;
380                 case 'A':
381                     INSERT_STRING( p_item && p_item->p_meta,
382                                    p_item->p_meta->psz_date );
383                     break;
384                 case 'B':
385                     if( p_input )
386                     {
387                         snprintf( buf, 10, "%d",
388                                   var_GetInteger( p_input, "bit-rate" )/1000 );
389                     }
390                     else
391                     {
392                         sprintf( buf, "-" );
393                     }
394                     INSERT_STRING( 1, buf );
395                     break;
396                 case 'C':
397                     if( p_input )
398                     {
399                         snprintf( buf, 10, "%d",
400                                   var_GetInteger( p_input, "chapter" ) );
401                     }
402                     else
403                     {
404                         sprintf( buf, "-" );
405                     }
406                     INSERT_STRING( 1, buf );
407                     break;
408                 case 'D':
409                     if( p_item )
410                     {
411                         sprintf( buf, "%02d:%02d:%02d",
412                                  (int)(p_item->i_duration/(3600000000)),
413                                  (int)((p_item->i_duration/(60000000))%60),
414                                  (int)((p_item->i_duration/1000000)%60) );
415                     }
416                     else
417                     {
418                         sprintf( buf, "--:--:--" );
419                     }
420                     INSERT_STRING( 1, buf );
421                     break;
422                 case 'F':
423                     INSERT_STRING( p_item, p_item->psz_uri );
424                     break;
425                 case 'I':
426                     if( p_input )
427                     {
428                         snprintf( buf, 10, "%d",
429                                   var_GetInteger( p_input, "title" ) );
430                     }
431                     else
432                     {
433                         sprintf( buf, "-" );
434                     }
435                     INSERT_STRING( 1, buf );
436                     break;
437                 case 'L':
438                     if( p_item && p_input )
439                     {
440                         sprintf( buf, "%02d:%02d:%02d",
441                      (int)((p_item->i_duration-p_input->i_time)/(3600000000)),
442                      (int)(((p_item->i_duration-p_input->i_time)/(60000000))%60),
443                      (int)(((p_item->i_duration-p_input->i_time)/1000000)%60) );
444                     }
445                     else
446                     {
447                         sprintf( buf, "--:--:--" );
448                     }
449                     INSERT_STRING( 1, buf );
450                     break;
451                 case 'N':
452                     INSERT_STRING( p_item, p_item->psz_name );
453                     break;
454                 case 'O':
455                 {
456                     char *lang;
457                     if( p_input )
458                     {
459                         lang = var_GetString( p_input, "audio-language" );
460                     }
461                     else
462                     {
463                         lang = strdup( "-" );
464                     }
465                     INSERT_STRING( 1, lang );
466                     free( lang );
467                     break;
468                 }
469                 case 'P':
470                     if( p_input )
471                     {
472                         snprintf( buf, 10, "%2.1lf",
473                                   var_GetFloat( p_input, "position" ) * 100. );
474                     }
475                     else
476                     {
477                         sprintf( buf, "--.-%%" );
478                     }
479                     INSERT_STRING( 1, buf );
480                     break;
481                 case 'R':
482                     if( p_input )
483                     {
484                         int r = var_GetInteger( p_input, "rate" );
485                         snprintf( buf, 10, "%d.%d", r/1000, r%1000 );
486                     }
487                     else
488                     {
489                         sprintf( buf, "-" );
490                     }
491                     INSERT_STRING( 1, buf );
492                     break;
493                 case 'S':
494                     if( p_input )
495                     {
496                         int r = var_GetInteger( p_input, "sample-rate" );
497                         snprintf( buf, 10, "%d.%d", r/1000, (r/100)%10 );
498                     }
499                     else
500                     {
501                         sprintf( buf, "-" );
502                     }
503                     INSERT_STRING( 1, buf );
504                     break;
505                 case 'T':
506                     if( p_input )
507                     {
508                         sprintf( buf, "%02d:%02d:%02d",
509                                  (int)(p_input->i_time/(3600000000)),
510                                  (int)((p_input->i_time/(60000000))%60),
511                                  (int)((p_input->i_time/1000000)%60) );
512                     }
513                     else
514                     {
515                         sprintf( buf, "--:--:--" );
516                     }
517                     INSERT_STRING( 1, buf );
518                     break;
519                 case 'U':
520                     INSERT_STRING( p_item && p_item->p_meta,
521                                    p_item->p_meta->psz_publisher );
522                     break;
523                 case 'V':
524                 {
525                     audio_volume_t volume;
526                     aout_VolumeGet( p_object, &volume );
527                     snprintf( buf, 10, "%d", volume );
528                     INSERT_STRING( 1, buf );
529                     break;
530                 }
531                 case '_':
532                     *d = '\n';
533                     d++;
534                     break;
535
536                 default:
537                     *d = *s;
538                     d++;
539                     break;
540             }
541             b_is_format = 0;
542         }
543         else if( *s == '$' )
544         {
545             b_is_format = 1;
546         }
547         else
548         {
549             *d = *s;
550             d++;
551         }
552         s++;
553     }
554     *d = '\0';
555
556     if( p_input )
557     {
558         vlc_object_release( p_input );
559         if( p_item )
560             vlc_mutex_unlock( &p_item->lock );
561     }
562
563     return dst;
564 }
565
566 /****************************************************************************
567  * Filter: the whole thing
568  ****************************************************************************
569  * This function outputs subpictures at regular time intervals.
570  ****************************************************************************/
571 static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
572 {
573     filter_sys_t *p_sys = p_filter->p_sys;
574     subpicture_t *p_spu;
575     video_format_t fmt;
576     time_t t;
577     char *buf;
578
579     if( p_sys->last_time == time( NULL ) )
580     {
581         return NULL;
582     }
583
584     if( p_sys->b_need_update == VLC_FALSE )
585     {
586         return NULL;
587     }
588
589     p_spu = p_filter->pf_sub_buffer_new( p_filter );
590     if( !p_spu ) return NULL;
591
592     memset( &fmt, 0, sizeof(video_format_t) );
593     fmt.i_chroma = VLC_FOURCC('T','E','X','T');
594     fmt.i_aspect = 0;
595     fmt.i_width = fmt.i_height = 0;
596     fmt.i_x_offset = 0;
597     fmt.i_y_offset = 0;
598     p_spu->p_region = p_spu->pf_create_region( VLC_OBJECT(p_filter), &fmt );
599     if( !p_spu->p_region )
600     {
601         p_filter->pf_sub_buffer_del( p_filter, p_spu );
602         return NULL;
603     }
604
605     t = p_sys->last_time = time( NULL );
606
607     if( strchr( p_sys->psz_marquee, '%' ) || strchr( p_sys->psz_marquee, '$' ) )
608     {
609         p_sys->b_need_update = VLC_TRUE;
610     }
611     else
612     {
613         p_sys->b_need_update = VLC_FALSE;
614     }
615     buf = FormatTime( p_sys->psz_marquee );
616     p_spu->p_region->psz_text = FormatMeta( VLC_OBJECT( p_filter ), buf );
617     free( buf );
618     p_spu->i_start = date;
619     p_spu->i_stop  = p_sys->i_timeout == 0 ? 0 : date + p_sys->i_timeout * 1000;
620     p_spu->b_ephemer = VLC_TRUE;
621
622     /*  where to locate the string: */
623     if( p_sys->i_xoff < 0 || p_sys->i_yoff < 0 )
624     {   /* set to one of the 9 relative locations */
625         p_spu->i_flags = p_sys->i_pos;
626         p_spu->i_x = 0;
627         p_spu->i_y = 0;
628         p_spu->b_absolute = VLC_FALSE;
629     }
630     else
631     {   /*  set to an absolute xy, referenced to upper left corner */
632         p_spu->i_flags = OSD_ALIGN_LEFT | OSD_ALIGN_TOP;
633         p_spu->i_x = p_sys->i_xoff;
634         p_spu->i_y = p_sys->i_yoff;
635         p_spu->b_absolute = VLC_TRUE;
636     }
637     p_spu->p_region->p_style = p_sys->p_style;
638
639     return p_spu;
640 }
641
642 /**********************************************************************
643  * Callback to update params on the fly
644  **********************************************************************/
645 static int MarqueeCallback( vlc_object_t *p_this, char const *psz_var,
646                             vlc_value_t oldval, vlc_value_t newval,
647                             void *p_data )
648 {
649     filter_sys_t *p_sys = (filter_sys_t *) p_data;
650
651     if( !strncmp( psz_var, "marq-marquee", 7 ) )
652     {
653         if( p_sys->psz_marquee ) free( p_sys->psz_marquee );
654         p_sys->psz_marquee = strdup( newval.psz_string );
655     }
656     else if ( !strncmp( psz_var, "marq-x", 6 ) )
657     {
658         p_sys->i_xoff = newval.i_int;
659     }
660     else if ( !strncmp( psz_var, "marq-y", 6 ) )
661     {
662         p_sys->i_yoff = newval.i_int;
663     }
664     else if ( !strncmp( psz_var, "marq-color", 8 ) )  /* "marq-col" */
665     {
666         p_sys->p_style->i_font_color = newval.i_int;
667     }
668     else if ( !strncmp( psz_var, "marq-opacity", 8 ) ) /* "marq-opa" */
669     {
670         p_sys->p_style->i_font_alpha = 255 - newval.i_int;
671     }
672     else if ( !strncmp( psz_var, "marq-size", 6 ) )
673     {
674         p_sys->p_style->i_font_size = newval.i_int;
675     }
676     else if ( !strncmp( psz_var, "marq-timeout", 12 ) )
677     {
678         p_sys->i_timeout = newval.i_int;
679     }
680     else if ( !strncmp( psz_var, "marq-position", 8 ) )
681     /* willing to accept a match against marq-pos */
682     {
683         p_sys->i_pos = newval.i_int;
684         p_sys->i_xoff = -1;       /* force to relative positioning */
685     }
686     p_sys->b_need_update = VLC_TRUE;
687     return VLC_SUCCESS;
688 }