]> git.sesse.net Git - vlc/blob - modules/video_filter/marq.c
Revert [23438] because --enable-fast-install does the same.
[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
30 #include <vlc/vlc.h>
31 #include <vlc_vout.h>
32
33 #include "vlc_filter.h"
34 #include "vlc_block.h"
35 #include "vlc_osd.h"
36
37 #include "vlc_strings.h"
38
39 /*****************************************************************************
40  * Local prototypes
41  *****************************************************************************/
42 static int  CreateFilter ( vlc_object_t * );
43 static void DestroyFilter( vlc_object_t * );
44 static subpicture_t *Filter( filter_t *, mtime_t );
45
46
47 static int MarqueeCallback( vlc_object_t *p_this, char const *psz_var,
48                             vlc_value_t oldval, vlc_value_t newval,
49                             void *p_data );
50 static int pi_color_values[] = { 0xf0000000, 0x00000000, 0x00808080, 0x00C0C0C0,
51                0x00FFFFFF, 0x00800000, 0x00FF0000, 0x00FF00FF, 0x00FFFF00,
52                0x00808000, 0x00008000, 0x00008080, 0x0000FF00, 0x00800080,
53                0x00000080, 0x000000FF, 0x0000FFFF};
54 static const char *ppsz_color_descriptions[] = { N_("Default"), N_("Black"),
55                N_("Gray"), N_("Silver"), N_("White"), N_("Maroon"), N_("Red"),
56                N_("Fuchsia"), N_("Yellow"), N_("Olive"), N_("Green"),
57                N_("Teal"), N_("Lime"), N_("Purple"), N_("Navy"), N_("Blue"),
58                N_("Aqua") };
59
60 /*****************************************************************************
61  * filter_sys_t: marquee filter descriptor
62  *****************************************************************************/
63 struct filter_sys_t
64 {
65     int i_xoff, i_yoff;  /* offsets for the display string in the video window */
66     int i_pos; /* permit relative positioning (top, bottom, left, right, center) */
67     int i_timeout;
68
69     char *psz_marquee;    /* marquee string */
70
71     text_style_t *p_style; /* font control */
72
73     time_t last_time;
74
75     vlc_bool_t b_need_update;
76 };
77
78 #define MSG_TEXT N_("Text")
79 #define MSG_LONGTEXT N_( \
80     "Marquee text to display. " \
81     "(Available format strings: " \
82     "Time related: %Y = year, %m = month, %d = day, %H = hour, " \
83     "%M = minute, %S = second, ... " \
84     "Meta data related: $a = artist, $b = album, $c = copyright, " \
85     "$d = description, $e = encoded by, $g = genre, " \
86     "$l = language, $n = track num, $p = now playing, " \
87     "$r = rating, $s = subtitles language, $t = title, "\
88     "$u = url, $A = date, " \
89     "$B = audio bitrate (in kb/s), $C = chapter," \
90     "$D = duration, $F = full name with path, $I = title, "\
91     "$L = time left, " \
92     "$N = name, $O = audio language, $P = position (in %), $R = rate, " \
93     "$S = audio sample rate (in kHz), " \
94     "$T = time, $U = publisher, $V = volume, $_ = new line) ")
95 #define POSX_TEXT N_("X offset")
96 #define POSX_LONGTEXT N_("X offset, from the left screen edge." )
97 #define POSY_TEXT N_("Y offset")
98 #define POSY_LONGTEXT N_("Y offset, down from the top." )
99 #define TIMEOUT_TEXT N_("Timeout")
100 #define TIMEOUT_LONGTEXT N_("Number of milliseconds the marquee must remain " \
101                             "displayed. Default value is " \
102                             "0 (remains forever).")
103 #define OPACITY_TEXT N_("Opacity")
104 #define OPACITY_LONGTEXT N_("Opacity (inverse of transparency) of " \
105     "overlayed text. 0 = transparent, 255 = totally opaque. " )
106 #define SIZE_TEXT N_("Font size, pixels")
107 #define SIZE_LONGTEXT N_("Font size, in pixels. Default is -1 (use default " \
108     "font size)." )
109
110 #define COLOR_TEXT N_("Color")
111 #define COLOR_LONGTEXT N_("Color of the text that will be rendered on "\
112     "the video. This must be an hexadecimal (like HTML colors). The first two "\
113     "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
114     " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
115
116 #define POS_TEXT N_("Marquee position")
117 #define POS_LONGTEXT N_( \
118   "You can enforce the marquee position on the video " \
119   "(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \
120   "also use combinations of these values, eg 6 = top-right).")
121
122 static int pi_pos_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };
123 static const char *ppsz_pos_descriptions[] =
124      { N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
125      N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };
126
127 #define CFG_PREFIX "marq-"
128
129 /*****************************************************************************
130  * Module descriptor
131  *****************************************************************************/
132 vlc_module_begin();
133     set_capability( "sub filter", 0 );
134     set_shortname( _("Marquee" ));
135     set_callbacks( CreateFilter, DestroyFilter );
136     set_category( CAT_VIDEO );
137     set_subcategory( SUBCAT_VIDEO_SUBPIC );
138     add_string( CFG_PREFIX "marquee", "VLC", NULL, MSG_TEXT, MSG_LONGTEXT,
139                 VLC_FALSE );
140
141     set_section( N_("Position"), NULL );
142     add_integer( CFG_PREFIX "x", -1, NULL, POSX_TEXT, POSX_LONGTEXT, VLC_TRUE );
143     add_integer( CFG_PREFIX "y", 0, NULL, POSY_TEXT, POSY_LONGTEXT, VLC_TRUE );
144     add_integer( CFG_PREFIX "position", 5, NULL, POS_TEXT, POS_LONGTEXT, VLC_FALSE );
145         change_integer_list( pi_pos_values, ppsz_pos_descriptions, 0 );
146
147     set_section( N_("Font"), NULL );
148     /* 5 sets the default to top [1] left [4] */
149     add_integer_with_range( CFG_PREFIX "opacity", 255, 0, 255, NULL,
150         OPACITY_TEXT, OPACITY_LONGTEXT, VLC_FALSE );
151     add_integer( CFG_PREFIX "color", 0xFFFFFF, NULL, COLOR_TEXT, COLOR_LONGTEXT,
152                  VLC_FALSE );
153         change_integer_list( pi_color_values, ppsz_color_descriptions, 0 );
154     add_integer( CFG_PREFIX "size", -1, NULL, SIZE_TEXT, SIZE_LONGTEXT,
155                  VLC_FALSE );
156
157     set_section( N_("Misc"), NULL );
158     add_integer( CFG_PREFIX "timeout", 0, NULL, TIMEOUT_TEXT, TIMEOUT_LONGTEXT,
159                  VLC_FALSE );
160
161     set_description( _("Marquee display") );
162     add_shortcut( "marq" );
163     add_shortcut( "time" );
164 vlc_module_end();
165
166 static const char *ppsz_filter_options[] = {
167     "marquee", "x", "y", "position", "color", "size", "timeout", NULL
168 };
169
170 /*****************************************************************************
171  * CreateFilter: allocates marquee video filter
172  *****************************************************************************/
173 static int CreateFilter( vlc_object_t *p_this )
174 {
175     filter_t *p_filter = (filter_t *)p_this;
176     filter_sys_t *p_sys;
177
178     /* Allocate structure */
179     p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
180     if( p_sys == NULL )
181     {
182         msg_Err( p_filter, "out of memory" );
183         return VLC_ENOMEM;
184     }
185
186     p_sys->p_style = malloc( sizeof( text_style_t ) );
187     memcpy( p_sys->p_style, &default_text_style, sizeof( text_style_t ) );
188
189     config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
190                        p_filter->p_cfg );
191
192 #define CREATE_VAR( stor, type, var ) \
193     p_sys->stor = var_CreateGet##type##Command( p_filter, var ); \
194     var_AddCallback( p_filter, var, MarqueeCallback, p_sys );
195
196     CREATE_VAR( i_xoff, Integer, "marq-x" );
197     CREATE_VAR( i_yoff, Integer, "marq-y" );
198     CREATE_VAR( i_timeout,Integer, "marq-timeout" );
199     CREATE_VAR( i_pos, Integer, "marq-position" );
200     CREATE_VAR( psz_marquee, String, "marq-marquee" );
201     CREATE_VAR( p_style->i_font_alpha, Integer, "marq-opacity" );
202     CREATE_VAR( p_style->i_font_color, Integer, "marq-color" );
203     CREATE_VAR( p_style->i_font_size, Integer, "marq-size" );
204
205     p_sys->p_style->i_font_alpha = 255 - p_sys->p_style->i_font_alpha ;
206
207     /* Misc init */
208     p_filter->pf_sub_filter = Filter;
209     p_sys->last_time = ((time_t)-1);
210     p_sys->b_need_update = VLC_TRUE;
211
212     return VLC_SUCCESS;
213 }
214 /*****************************************************************************
215  * DestroyFilter: destroy marquee video filter
216  *****************************************************************************/
217 static void DestroyFilter( vlc_object_t *p_this )
218 {
219     filter_t *p_filter = (filter_t *)p_this;
220     filter_sys_t *p_sys = p_filter->p_sys;
221
222     if( p_sys->p_style ) free( p_sys->p_style );
223     if( p_sys->psz_marquee ) free( p_sys->psz_marquee );
224
225     /* Delete the marquee variables */
226 #define DEL_VAR(var) \
227     var_DelCallback( p_filter, var, MarqueeCallback, p_sys ); \
228     var_Destroy( p_filter, var );
229     DEL_VAR( "marq-x" );
230     DEL_VAR( "marq-y" );
231     DEL_VAR( "marq-marquee" );
232     DEL_VAR( "marq-timeout" );
233     DEL_VAR( "marq-position" );
234     DEL_VAR( "marq-color" );
235     DEL_VAR( "marq-opacity" );
236     DEL_VAR( "marq-size" );
237
238     free( p_sys );
239 }
240
241 /****************************************************************************
242  * Filter: the whole thing
243  ****************************************************************************
244  * This function outputs subpictures at regular time intervals.
245  ****************************************************************************/
246 static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
247 {
248     filter_sys_t *p_sys = p_filter->p_sys;
249     subpicture_t *p_spu;
250     video_format_t fmt;
251     time_t t;
252
253     if( p_sys->last_time == time( NULL ) )
254     {
255         return NULL;
256     }
257
258     if( p_sys->b_need_update == VLC_FALSE )
259     {
260         return NULL;
261     }
262
263     p_spu = p_filter->pf_sub_buffer_new( p_filter );
264     if( !p_spu ) return NULL;
265
266     memset( &fmt, 0, sizeof(video_format_t) );
267     fmt.i_chroma = VLC_FOURCC('T','E','X','T');
268     fmt.i_aspect = 0;
269     fmt.i_width = fmt.i_height = 0;
270     fmt.i_x_offset = 0;
271     fmt.i_y_offset = 0;
272     p_spu->p_region = p_spu->pf_create_region( VLC_OBJECT(p_filter), &fmt );
273     if( !p_spu->p_region )
274     {
275         p_filter->pf_sub_buffer_del( p_filter, p_spu );
276         return NULL;
277     }
278
279     t = p_sys->last_time = time( NULL );
280
281     if( strchr( p_sys->psz_marquee, '%' ) || strchr( p_sys->psz_marquee, '$' ) )
282     {
283         p_sys->b_need_update = VLC_TRUE;
284     }
285     else
286     {
287         p_sys->b_need_update = VLC_FALSE;
288     }
289     p_spu->p_region->psz_text = str_format( p_filter, p_sys->psz_marquee );
290     p_spu->i_start = date;
291     p_spu->i_stop  = p_sys->i_timeout == 0 ? 0 : date + p_sys->i_timeout * 1000;
292     p_spu->b_ephemer = VLC_TRUE;
293
294     /*  where to locate the string: */
295     if( p_sys->i_xoff < 0 || p_sys->i_yoff < 0 )
296     {   /* set to one of the 9 relative locations */
297         p_spu->p_region->i_align = p_sys->i_pos;
298         p_spu->i_x = 0;
299         p_spu->i_y = 0;
300         p_spu->b_absolute = VLC_FALSE;
301     }
302     else
303     {   /*  set to an absolute xy, referenced to upper left corner */
304         p_spu->p_region->i_align = OSD_ALIGN_LEFT | OSD_ALIGN_TOP;
305         p_spu->i_x = p_sys->i_xoff;
306         p_spu->i_y = p_sys->i_yoff;
307         p_spu->b_absolute = VLC_TRUE;
308     }
309     p_spu->p_region->p_style = p_sys->p_style;
310
311     return p_spu;
312 }
313
314 /**********************************************************************
315  * Callback to update params on the fly
316  **********************************************************************/
317 static int MarqueeCallback( vlc_object_t *p_this, char const *psz_var,
318                             vlc_value_t oldval, vlc_value_t newval,
319                             void *p_data )
320 {
321     filter_sys_t *p_sys = (filter_sys_t *) p_data;
322
323     if( !strncmp( psz_var, "marq-marquee", 7 ) )
324     {
325         if( p_sys->psz_marquee ) free( p_sys->psz_marquee );
326         p_sys->psz_marquee = strdup( newval.psz_string );
327     }
328     else if ( !strncmp( psz_var, "marq-x", 6 ) )
329     {
330         p_sys->i_xoff = newval.i_int;
331     }
332     else if ( !strncmp( psz_var, "marq-y", 6 ) )
333     {
334         p_sys->i_yoff = newval.i_int;
335     }
336     else if ( !strncmp( psz_var, "marq-color", 8 ) )  /* "marq-col" */
337     {
338         p_sys->p_style->i_font_color = newval.i_int;
339     }
340     else if ( !strncmp( psz_var, "marq-opacity", 8 ) ) /* "marq-opa" */
341     {
342         p_sys->p_style->i_font_alpha = 255 - newval.i_int;
343     }
344     else if ( !strncmp( psz_var, "marq-size", 6 ) )
345     {
346         p_sys->p_style->i_font_size = newval.i_int;
347     }
348     else if ( !strncmp( psz_var, "marq-timeout", 12 ) )
349     {
350         p_sys->i_timeout = newval.i_int;
351     }
352     else if ( !strncmp( psz_var, "marq-position", 8 ) )
353     /* willing to accept a match against marq-pos */
354     {
355         p_sys->i_pos = newval.i_int;
356         p_sys->i_xoff = -1;       /* force to relative positioning */
357     }
358     p_sys->b_need_update = VLC_TRUE;
359     return VLC_SUCCESS;
360 }