]> git.sesse.net Git - vlc/blob - modules/video_filter/marq.c
Use gettext_noop() consistently
[vlc] / modules / video_filter / marq.c
1 /*****************************************************************************
2  * marq.c : marquee display video plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2003-2008 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
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <vlc/vlc.h>
35 #include <vlc_plugin.h>
36 #include <vlc_vout.h>
37
38 #include "vlc_filter.h"
39 #include "vlc_block.h"
40 #include "vlc_osd.h"
41
42 #include "vlc_strings.h"
43
44 /*****************************************************************************
45  * Local prototypes
46  *****************************************************************************/
47 static int  CreateFilter ( vlc_object_t * );
48 static void DestroyFilter( vlc_object_t * );
49 static subpicture_t *Filter( filter_t *, mtime_t );
50
51
52 static int MarqueeCallback( vlc_object_t *p_this, char const *psz_var,
53                             vlc_value_t oldval, vlc_value_t newval,
54                             void *p_data );
55 static int pi_color_values[] = { 0xf0000000, 0x00000000, 0x00808080, 0x00C0C0C0,
56                0x00FFFFFF, 0x00800000, 0x00FF0000, 0x00FF00FF, 0x00FFFF00,
57                0x00808000, 0x00008000, 0x00008080, 0x0000FF00, 0x00800080,
58                0x00000080, 0x000000FF, 0x0000FFFF};
59 static const char *ppsz_color_descriptions[] = { N_("Default"), N_("Black"),
60                N_("Gray"), N_("Silver"), N_("White"), N_("Maroon"), N_("Red"),
61                N_("Fuchsia"), N_("Yellow"), N_("Olive"), N_("Green"),
62                N_("Teal"), N_("Lime"), N_("Purple"), N_("Navy"), N_("Blue"),
63                N_("Aqua") };
64
65 /*****************************************************************************
66  * filter_sys_t: marquee filter descriptor
67  *****************************************************************************/
68 struct filter_sys_t
69 {
70     int i_xoff, i_yoff;  /* offsets for the display string in the video window */
71     int i_pos; /* permit relative positioning (top, bottom, left, right, center) */
72     int i_timeout;
73
74     char *psz_marquee;    /* marquee string */
75
76     text_style_t *p_style; /* font control */
77
78     mtime_t last_time;
79     mtime_t i_refresh;
80
81     bool 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 REFRESH_TEXT N_("Refresh period in ms")
110 #define REFRESH_LONGTEXT N_("Number of milliseconds between string updates. " \
111                             "This is mainly usefull when using meta data " \
112                             "or time format string sequences.")
113 #define OPACITY_TEXT N_("Opacity")
114 #define OPACITY_LONGTEXT N_("Opacity (inverse of transparency) of " \
115     "overlayed text. 0 = transparent, 255 = totally opaque. " )
116 #define SIZE_TEXT N_("Font size, pixels")
117 #define SIZE_LONGTEXT N_("Font size, in pixels. Default is -1 (use default " \
118     "font size)." )
119
120 #define COLOR_TEXT N_("Color")
121 #define COLOR_LONGTEXT N_("Color of the text that will be rendered on "\
122     "the video. This must be an hexadecimal (like HTML colors). The first two "\
123     "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
124     " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
125
126 #define POS_TEXT N_("Marquee position")
127 #define POS_LONGTEXT N_( \
128   "You can enforce the marquee position on the video " \
129   "(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \
130   "also use combinations of these values, eg 6 = top-right).")
131
132 static int pi_pos_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };
133 static const char *ppsz_pos_descriptions[] =
134      { N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
135      N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };
136
137 #define CFG_PREFIX "marq-"
138
139 /*****************************************************************************
140  * Module descriptor
141  *****************************************************************************/
142 vlc_module_begin();
143     set_capability( "sub filter", 0 );
144     set_shortname( N_("Marquee" ));
145     set_callbacks( CreateFilter, DestroyFilter );
146     set_category( CAT_VIDEO );
147     set_subcategory( SUBCAT_VIDEO_SUBPIC );
148     add_string( CFG_PREFIX "marquee", "VLC", NULL, MSG_TEXT, MSG_LONGTEXT,
149                 false );
150
151     set_section( N_("Position"), NULL );
152     add_integer( CFG_PREFIX "x", 0, NULL, POSX_TEXT, POSX_LONGTEXT, true );
153     add_integer( CFG_PREFIX "y", 0, NULL, POSY_TEXT, POSY_LONGTEXT, true );
154     add_integer( CFG_PREFIX "position", -1, NULL, POS_TEXT, POS_LONGTEXT, false );
155         change_integer_list( pi_pos_values, ppsz_pos_descriptions, 0 );
156
157     set_section( N_("Font"), NULL );
158     /* 5 sets the default to top [1] left [4] */
159     add_integer_with_range( CFG_PREFIX "opacity", 255, 0, 255, NULL,
160         OPACITY_TEXT, OPACITY_LONGTEXT, false );
161     add_integer( CFG_PREFIX "color", 0xFFFFFF, NULL, COLOR_TEXT, COLOR_LONGTEXT,
162                  false );
163         change_integer_list( pi_color_values, ppsz_color_descriptions, 0 );
164     add_integer( CFG_PREFIX "size", -1, NULL, SIZE_TEXT, SIZE_LONGTEXT,
165                  false );
166
167     set_section( N_("Misc"), NULL );
168     add_integer( CFG_PREFIX "timeout", 0, NULL, TIMEOUT_TEXT, TIMEOUT_LONGTEXT,
169                  false );
170     add_integer( CFG_PREFIX "refresh", 1000, NULL, REFRESH_TEXT,
171                  REFRESH_LONGTEXT, false );
172
173     set_description( N_("Marquee display") );
174     add_shortcut( "time" );
175     add_obsolete_string( "time-format" );
176     add_obsolete_string( "time-x" );
177     add_obsolete_string( "time-y" );
178     add_obsolete_string( "time-position" );
179     add_obsolete_string( "time-opacity" );
180     add_obsolete_string( "time-color" );
181     add_obsolete_string( "time-size" );
182 vlc_module_end();
183
184 static const char *ppsz_filter_options[] = {
185     "marquee", "x", "y", "position", "color", "size", "timeout", "refresh",
186     NULL
187 };
188
189 /*****************************************************************************
190  * CreateFilter: allocates marquee video filter
191  *****************************************************************************/
192 static int CreateFilter( vlc_object_t *p_this )
193 {
194     filter_t *p_filter = (filter_t *)p_this;
195     filter_sys_t *p_sys;
196
197     /* Allocate structure */
198     p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
199     if( p_sys == NULL )
200     {
201         msg_Err( p_filter, "out of memory" );
202         return VLC_ENOMEM;
203     }
204
205     p_sys->p_style = malloc( sizeof( text_style_t ) );
206     memcpy( p_sys->p_style, &default_text_style, sizeof( text_style_t ) );
207
208     config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
209                        p_filter->p_cfg );
210
211 #define CREATE_VAR( stor, type, var ) \
212     p_sys->stor = var_CreateGet##type##Command( p_filter, var ); \
213     var_AddCallback( p_filter, var, MarqueeCallback, p_sys );
214
215     CREATE_VAR( i_xoff, Integer, "marq-x" );
216     CREATE_VAR( i_yoff, Integer, "marq-y" );
217     CREATE_VAR( i_timeout,Integer, "marq-timeout" );
218     CREATE_VAR( i_refresh,Integer, "marq-refresh" );
219     CREATE_VAR( i_pos, Integer, "marq-position" );
220     CREATE_VAR( psz_marquee, String, "marq-marquee" );
221     CREATE_VAR( p_style->i_font_alpha, Integer, "marq-opacity" );
222     CREATE_VAR( p_style->i_font_color, Integer, "marq-color" );
223     CREATE_VAR( p_style->i_font_size, Integer, "marq-size" );
224
225     p_sys->p_style->i_font_alpha = 255 - p_sys->p_style->i_font_alpha ;
226
227     /* Misc init */
228     p_filter->pf_sub_filter = Filter;
229     p_sys->last_time = 0;
230     p_sys->b_need_update = true;
231
232     return VLC_SUCCESS;
233 }
234 /*****************************************************************************
235  * DestroyFilter: destroy marquee video filter
236  *****************************************************************************/
237 static void DestroyFilter( vlc_object_t *p_this )
238 {
239     filter_t *p_filter = (filter_t *)p_this;
240     filter_sys_t *p_sys = p_filter->p_sys;
241
242     free( p_sys->p_style );
243     free( p_sys->psz_marquee );
244
245     /* Delete the marquee variables */
246 #define DEL_VAR(var) \
247     var_DelCallback( p_filter, var, MarqueeCallback, p_sys ); \
248     var_Destroy( p_filter, var );
249     DEL_VAR( "marq-x" );
250     DEL_VAR( "marq-y" );
251     DEL_VAR( "marq-marquee" );
252     DEL_VAR( "marq-timeout" );
253     DEL_VAR( "marq-position" );
254     DEL_VAR( "marq-color" );
255     DEL_VAR( "marq-opacity" );
256     DEL_VAR( "marq-size" );
257
258     free( p_sys );
259 }
260
261 /****************************************************************************
262  * Filter: the whole thing
263  ****************************************************************************
264  * This function outputs subpictures at regular time intervals.
265  ****************************************************************************/
266 static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
267 {
268     filter_sys_t *p_sys = p_filter->p_sys;
269     subpicture_t *p_spu;
270     video_format_t fmt;
271
272     if( p_sys->last_time + p_sys->i_refresh*1000 > date )
273     {
274         return NULL;
275     }
276
277     if( p_sys->b_need_update == false )
278     {
279         return NULL;
280     }
281
282     p_spu = p_filter->pf_sub_buffer_new( p_filter );
283     if( !p_spu ) return NULL;
284
285     memset( &fmt, 0, sizeof(video_format_t) );
286     fmt.i_chroma = VLC_FOURCC('T','E','X','T');
287     fmt.i_aspect = 0;
288     fmt.i_width = fmt.i_height = 0;
289     fmt.i_x_offset = 0;
290     fmt.i_y_offset = 0;
291     p_spu->p_region = p_spu->pf_create_region( VLC_OBJECT(p_filter), &fmt );
292     if( !p_spu->p_region )
293     {
294         p_filter->pf_sub_buffer_del( p_filter, p_spu );
295         return NULL;
296     }
297
298     p_sys->last_time = date;
299
300     if( strchr( p_sys->psz_marquee, '%' ) || strchr( p_sys->psz_marquee, '$' ) )
301     {
302         p_sys->b_need_update = true;
303     }
304     else
305     {
306         p_sys->b_need_update = false;
307     }
308     p_spu->p_region->psz_text = str_format( p_filter, p_sys->psz_marquee );
309     p_spu->i_start = date;
310     p_spu->i_stop  = p_sys->i_timeout == 0 ? 0 : date + p_sys->i_timeout * 1000;
311     p_spu->b_ephemer = true;
312
313     /*  where to locate the string: */
314     if( p_sys->i_pos < 0 )
315     {   /*  set to an absolute xy */
316         p_spu->p_region->i_align = OSD_ALIGN_LEFT | OSD_ALIGN_TOP;
317         p_spu->b_absolute = true;
318     }
319     else
320     {   /* set to one of the 9 relative locations */
321         p_spu->p_region->i_align = p_sys->i_pos;
322         p_spu->b_absolute = false;
323     }
324
325     p_spu->i_x = p_sys->i_xoff;
326     p_spu->i_y = p_sys->i_yoff;
327
328     p_spu->p_region->p_style = p_sys->p_style;
329
330     return p_spu;
331 }
332
333 /**********************************************************************
334  * Callback to update params on the fly
335  **********************************************************************/
336 static int MarqueeCallback( vlc_object_t *p_this, char const *psz_var,
337                             vlc_value_t oldval, vlc_value_t newval,
338                             void *p_data )
339 {
340     VLC_UNUSED(p_this); VLC_UNUSED(oldval);
341     filter_sys_t *p_sys = (filter_sys_t *) p_data;
342
343     if( !strncmp( psz_var, "marq-marquee", 7 ) )
344     {
345         free( p_sys->psz_marquee );
346         p_sys->psz_marquee = strdup( newval.psz_string );
347     }
348     else if ( !strncmp( psz_var, "marq-x", 6 ) )
349     {
350         p_sys->i_xoff = newval.i_int;
351     }
352     else if ( !strncmp( psz_var, "marq-y", 6 ) )
353     {
354         p_sys->i_yoff = newval.i_int;
355     }
356     else if ( !strncmp( psz_var, "marq-color", 8 ) )  /* "marq-col" */
357     {
358         p_sys->p_style->i_font_color = newval.i_int;
359     }
360     else if ( !strncmp( psz_var, "marq-opacity", 8 ) ) /* "marq-opa" */
361     {
362         p_sys->p_style->i_font_alpha = 255 - newval.i_int;
363     }
364     else if ( !strncmp( psz_var, "marq-size", 6 ) )
365     {
366         p_sys->p_style->i_font_size = newval.i_int;
367     }
368     else if ( !strncmp( psz_var, "marq-timeout", 12 ) )
369     {
370         p_sys->i_timeout = newval.i_int;
371     }
372     else if ( !strncmp( psz_var, "marq-refresh", 12 ) )
373     {
374         p_sys->i_refresh = newval.i_int;
375     }
376     else if ( !strncmp( psz_var, "marq-position", 8 ) )
377     /* willing to accept a match against marq-pos */
378     {
379         p_sys->i_pos = newval.i_int;
380         p_sys->i_xoff = -1;       /* force to relative positioning */
381     }
382     p_sys->b_need_update = true;
383     return VLC_SUCCESS;
384 }