1 /*****************************************************************************
2 * time.c : time display video plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2003-2005 the VideoLAN team
7 * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <stdlib.h> /* malloc(), free() */
35 #include "vlc_filter.h"
36 #include "vlc_block.h"
39 /*****************************************************************************
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 static int TimeCallback( vlc_object_t *p_this, char const *psz_var,
46 vlc_value_t oldval, vlc_value_t newval,
48 static int pi_color_values[] = { 0xf0000000, 0x00000000, 0x00808080, 0x00C0C0C0,
49 0x00FFFFFF, 0x00800000, 0x00FF0000, 0x00FF00FF, 0x00FFFF00,
50 0x00808000, 0x00008000, 0x00008080, 0x0000FF00, 0x00800080,
51 0x00000080, 0x000000FF, 0x0000FFFF};
52 static char *ppsz_color_descriptions[] = { N_("Default"), N_("Black"),
53 N_("Gray"), N_("Silver"), N_("White"), N_("Maroon"), N_("Red"),
54 N_("Fuchsia"), N_("Yellow"), N_("Olive"), N_("Green"),
55 N_("Teal"), N_("Lime"), N_("Purple"), N_("Navy"), N_("Blue"),
58 /*****************************************************************************
59 * filter_sys_t: time filter descriptor
60 *****************************************************************************/
63 int i_xoff, i_yoff; /* offsets for the display string in the video window */
64 char *psz_format; /* time format string */
65 int i_pos; /* permit relative positioning (top, bottom, left, right, center) */
66 text_style_t *p_style; /* font control */
71 #define MSG_TEXT N_("Time format string (%Y%m%d %H%M%S)")
72 #define MSG_LONGTEXT N_("Time format string (%Y = year, %m = month, %d = day, %H = hour, %M = minute, %S = second).")
73 #define POSX_TEXT N_("X offset")
74 #define POSX_LONGTEXT N_("X offset, from the left screen edge" )
75 #define POSY_TEXT N_("Y offset")
76 #define POSY_LONGTEXT N_("Y offset, down from the top" )
77 #define OPACITY_TEXT N_("Opacity")
78 #define OPACITY_LONGTEXT N_("Opacity (inverse of transparency) of " \
79 "overlay text. 0 = transparent, 255 = totally opaque." )
81 #define SIZE_TEXT N_("Font size, pixels")
82 #define SIZE_LONGTEXT N_("Font size, in pixels. Default is -1 (use default " \
85 #define COLOR_TEXT N_("Color")
86 #define COLOR_LONGTEXT N_("Color of the text that will be rendered on "\
87 "the video. This must be an hexadecimal (like HTML colors). The first two "\
88 "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
89 " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
91 #define POS_TEXT N_("Text position")
92 #define POS_LONGTEXT N_( \
93 "You can enforce the text position on the video " \
94 "(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \
95 "also use combinations of these values, e.g. 6 = top-right).")
97 static int pi_pos_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };
98 static char *ppsz_pos_descriptions[] =
99 { N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
100 N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };
102 /*****************************************************************************
104 *****************************************************************************/
106 set_capability( "sub filter", 0 );
107 set_shortname( N_("Time overlay"));
108 set_category( CAT_VIDEO );
109 set_subcategory( SUBCAT_VIDEO_SUBPIC );
110 set_callbacks( CreateFilter, DestroyFilter );
111 add_string( "time-format", "%Y-%m-%d %H:%M:%S", NULL, MSG_TEXT,
112 MSG_LONGTEXT, VLC_TRUE );
113 add_integer( "time-x", -1, NULL, POSX_TEXT, POSX_LONGTEXT, VLC_TRUE );
114 add_integer( "time-y", 0, NULL, POSY_TEXT, POSY_LONGTEXT, VLC_TRUE );
115 add_integer( "time-position", 9, NULL, POS_TEXT, POS_LONGTEXT, VLC_FALSE );
116 /* 9 sets the default to bottom-left, minimizing jitter */
117 change_integer_list( pi_pos_values, ppsz_pos_descriptions, 0 );
118 add_integer_with_range( "time-opacity", 255, 0, 255, NULL,
119 OPACITY_TEXT, OPACITY_LONGTEXT, VLC_FALSE );
120 add_integer( "time-color", 0xFFFFFF, NULL, COLOR_TEXT, COLOR_LONGTEXT,
122 change_integer_list( pi_color_values, ppsz_color_descriptions, 0 );
123 add_integer( "time-size", -1, NULL, SIZE_TEXT, SIZE_LONGTEXT, VLC_FALSE );
124 set_description( _("Time display sub filter") );
125 add_shortcut( "time" );
128 /*****************************************************************************
129 * CreateFilter: allocates time video filter
130 *****************************************************************************/
131 static int CreateFilter( vlc_object_t *p_this )
133 filter_t *p_filter = (filter_t *)p_this;
136 /* Allocate structure */
137 p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
140 msg_Err( p_filter, "out of memory" );
144 p_sys->p_style = malloc( sizeof( text_style_t ) );
145 memcpy( p_sys->p_style, &default_text_style, sizeof( text_style_t ) );
147 /* Hook used for callback variables */
148 p_sys->i_xoff = var_CreateGetInteger( p_filter->p_libvlc , "time-x" );
149 p_sys->i_yoff = var_CreateGetInteger( p_filter->p_libvlc , "time-y" );
150 p_sys->psz_format = var_CreateGetString( p_filter->p_libvlc, "time-format" );
151 p_sys->i_pos = var_CreateGetInteger( p_filter->p_libvlc , "time-position" );
153 p_sys->p_style->i_font_alpha = 255 - var_CreateGetInteger( p_filter->p_libvlc , "time-opacity" );
154 p_sys->p_style->i_font_color = var_CreateGetInteger( p_filter->p_libvlc , "time-color" );
155 p_sys->p_style->i_font_size = var_CreateGetInteger( p_filter->p_libvlc , "time-size" );
157 var_AddCallback( p_filter->p_libvlc, "time-x", TimeCallback, p_sys );
158 var_AddCallback( p_filter->p_libvlc, "time-y", TimeCallback, p_sys );
159 var_AddCallback( p_filter->p_libvlc, "time-format", TimeCallback, p_sys );
160 var_AddCallback( p_filter->p_libvlc, "time-position", TimeCallback, p_sys );
161 var_AddCallback( p_filter->p_libvlc, "time-color", TimeCallback, p_sys );
162 var_AddCallback( p_filter->p_libvlc, "time-opacity", TimeCallback, p_sys );
163 var_AddCallback( p_filter->p_libvlc, "time-size", TimeCallback, p_sys );
166 p_filter->pf_sub_filter = Filter;
167 p_sys->last_time = ((time_t)-1);
171 /*****************************************************************************
172 * DestroyFilter: destroy logo video filter
173 *****************************************************************************/
174 static void DestroyFilter( vlc_object_t *p_this )
176 filter_t *p_filter = (filter_t *)p_this;
177 filter_sys_t *p_sys = p_filter->p_sys;
179 if( p_sys->p_style ) free( p_sys->p_style );
180 if( p_sys->psz_format ) free( p_sys->psz_format );
183 /* Delete the time variables */
184 var_Destroy( p_filter->p_libvlc , "time-format" );
185 var_Destroy( p_filter->p_libvlc , "time-x" );
186 var_Destroy( p_filter->p_libvlc , "time-y" );
187 var_Destroy( p_filter->p_libvlc , "time-position" );
188 var_Destroy( p_filter->p_libvlc , "time-color");
189 var_Destroy( p_filter->p_libvlc , "time-opacity");
190 var_Destroy( p_filter->p_libvlc , "time-size");
193 static char *FormatTime(char *tformat )
197 #if defined(HAVE_LOCALTIME_R)
203 /* Get the current time. */
204 curtime = time( NULL );
206 /* Convert it to local time representation. */
207 #if defined(HAVE_LOCALTIME_R)
208 localtime_r( &curtime, &loctime );
209 strftime( buffer, 255, tformat, &loctime );
211 loctime = localtime( &curtime );
212 strftime( buffer, 255, tformat, loctime );
214 return strdup( buffer );
217 /****************************************************************************
218 * Filter: the whole thing
219 ****************************************************************************
220 * This function outputs subpictures at regular time intervals.
221 ****************************************************************************/
222 static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
224 filter_sys_t *p_sys = p_filter->p_sys;
228 if( p_sys->last_time == time( NULL ) ) return NULL;
230 p_spu = p_filter->pf_sub_buffer_new( p_filter );
231 if( !p_spu ) return NULL;
233 memset( &fmt, 0, sizeof(video_format_t) );
234 fmt.i_chroma = VLC_FOURCC('T','E','X','T');
236 fmt.i_width = fmt.i_height = 0;
239 p_spu->p_region = p_spu->pf_create_region( VLC_OBJECT(p_filter), &fmt );
240 if( !p_spu->p_region )
242 p_filter->pf_sub_buffer_del( p_filter, p_spu );
246 p_sys->last_time = time( NULL );
248 p_spu->p_region->psz_text = FormatTime( p_sys->psz_format );
249 p_spu->i_start = date;
251 p_spu->b_ephemer = VLC_TRUE;
253 /* where to locate the string: */
254 if( p_sys->i_xoff < 0 || p_sys->i_yoff < 0 )
255 { /* set to one of the 9 relative locations */
256 p_spu->i_flags = p_sys->i_pos;
259 p_spu->b_absolute = VLC_FALSE;
262 { /* set to an absolute xy, referenced to upper left corner */
263 p_spu->i_flags = OSD_ALIGN_LEFT | OSD_ALIGN_TOP;
264 p_spu->i_x = p_sys->i_xoff;
265 p_spu->i_y = p_sys->i_yoff;
266 p_spu->b_absolute = VLC_TRUE;
268 p_spu->p_region->p_style = p_sys->p_style;
272 /**********************************************************************
273 * Callback to update params on the fly
274 **********************************************************************/
275 static int TimeCallback( vlc_object_t *p_this, char const *psz_var,
276 vlc_value_t oldval, vlc_value_t newval,
279 filter_sys_t *p_sys = (filter_sys_t *) p_data;
281 if( !strncmp( psz_var, "time-format", 11 ) )
283 if( p_sys->psz_format ) free( p_sys->psz_format );
284 p_sys->psz_format = strdup( newval.psz_string );
286 else if ( !strncmp( psz_var, "time-x", 6 ) )
288 p_sys->i_xoff = newval.i_int;
290 else if ( !strncmp( psz_var, "time-y", 6 ) )
292 p_sys->i_yoff = newval.i_int;
294 else if ( !strncmp( psz_var, "time-color", 8 ) ) /* "time-c" */
296 p_sys->p_style->i_font_color = newval.i_int;
298 else if ( !strncmp( psz_var, "time-opacity", 8 ) ) /* "time-o" */
300 p_sys->p_style->i_font_alpha = 255 - newval.i_int;
302 else if ( !strncmp( psz_var, "time-size", 6 ) )
304 p_sys->p_style->i_font_size = newval.i_int;
306 else if ( !strncmp( psz_var, "time-position", 8 ) )
307 /* willing to accept a match against time-pos */
309 p_sys->i_pos = newval.i_int;
310 p_sys->i_xoff = -1; /* force to relative positioning */