]> git.sesse.net Git - vlc/blob - modules/video_filter/time.c
For consistency, remove references to vlc from libvlc
[vlc] / modules / video_filter / time.c
1 /*****************************************************************************
2  * time.c : time display video plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2003-2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <string.h>
29
30 #include <time.h>
31
32 #include <vlc/vlc.h>
33 #include <vlc/vout.h>
34
35 #include "vlc_filter.h"
36 #include "vlc_block.h"
37 #include "vlc_osd.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 static int TimeCallback( vlc_object_t *p_this, char const *psz_var,
46                             vlc_value_t oldval, vlc_value_t newval,
47                             void *p_data );
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"), 
56                N_("Aqua") };
57
58 /*****************************************************************************
59  * filter_sys_t: time filter descriptor
60  *****************************************************************************/
61 struct filter_sys_t
62 {
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 */
67
68     time_t last_time;
69 };
70
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." )
80
81 #define SIZE_TEXT N_("Font size, pixels")
82 #define SIZE_LONGTEXT N_("Font size, in pixels. Default is -1 (use default " \
83     "font size)." )
84
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" )
90
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).")
96
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") };
101
102 /*****************************************************************************
103  * Module descriptor
104  *****************************************************************************/
105 vlc_module_begin();
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,
121                  VLC_FALSE );
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" );
126 vlc_module_end();
127
128 /*****************************************************************************
129  * CreateFilter: allocates time video filter
130  *****************************************************************************/
131 static int CreateFilter( vlc_object_t *p_this )
132 {
133     filter_t *p_filter = (filter_t *)p_this;
134     filter_sys_t *p_sys;
135
136     /* Allocate structure */
137     p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
138     if( p_sys == NULL )
139     {
140         msg_Err( p_filter, "out of memory" );
141         return VLC_ENOMEM;
142     }
143
144     p_sys->p_style = malloc( sizeof( text_style_t ) );
145     memcpy( p_sys->p_style, &default_text_style, sizeof( text_style_t ) );
146
147     /* Hook used for callback variables */
148     p_sys->i_xoff = var_CreateGetInteger( p_filter->p_libvlc_global , "time-x" );
149     p_sys->i_yoff = var_CreateGetInteger( p_filter->p_libvlc_global , "time-y" );
150     p_sys->psz_format = var_CreateGetString( p_filter->p_libvlc_global, "time-format" );
151     p_sys->i_pos = var_CreateGetInteger( p_filter->p_libvlc_global , "time-position" );
152     
153     p_sys->p_style->i_font_alpha = 255 - var_CreateGetInteger( p_filter->p_libvlc_global , "time-opacity" );
154     p_sys->p_style->i_font_color = var_CreateGetInteger( p_filter->p_libvlc_global , "time-color" );
155     p_sys->p_style->i_font_size = var_CreateGetInteger( p_filter->p_libvlc_global , "time-size" );
156    
157     var_AddCallback( p_filter->p_libvlc_global, "time-x", TimeCallback, p_sys );
158     var_AddCallback( p_filter->p_libvlc_global, "time-y", TimeCallback, p_sys );
159     var_AddCallback( p_filter->p_libvlc_global, "time-format", TimeCallback, p_sys );
160     var_AddCallback( p_filter->p_libvlc_global, "time-position", TimeCallback, p_sys );
161     var_AddCallback( p_filter->p_libvlc_global, "time-color", TimeCallback, p_sys );
162     var_AddCallback( p_filter->p_libvlc_global, "time-opacity", TimeCallback, p_sys );
163     var_AddCallback( p_filter->p_libvlc_global, "time-size", TimeCallback, p_sys );
164
165     /* Misc init */
166     p_filter->pf_sub_filter = Filter;
167     p_sys->last_time = ((time_t)-1);
168
169     return VLC_SUCCESS;
170 }
171 /*****************************************************************************
172  * DestroyFilter: destroy logo video filter
173  *****************************************************************************/
174 static void DestroyFilter( vlc_object_t *p_this )
175 {
176     filter_t *p_filter = (filter_t *)p_this;
177     filter_sys_t *p_sys = p_filter->p_sys;
178
179     if( p_sys->p_style ) free( p_sys->p_style );
180     if( p_sys->psz_format ) free( p_sys->psz_format );
181     free( p_sys );
182
183     /* Delete the time variables */
184     var_Destroy( p_filter->p_libvlc_global , "time-format" );
185     var_Destroy( p_filter->p_libvlc_global , "time-x" );
186     var_Destroy( p_filter->p_libvlc_global , "time-y" );
187     var_Destroy( p_filter->p_libvlc_global , "time-position" );
188     var_Destroy( p_filter->p_libvlc_global , "time-color");
189     var_Destroy( p_filter->p_libvlc_global , "time-opacity");
190     var_Destroy( p_filter->p_libvlc_global , "time-size");
191 }
192
193 static char *FormatTime(char *tformat )
194 {
195   char buffer[255];
196   time_t curtime;
197 #if defined(HAVE_LOCALTIME_R)
198   struct tm loctime;
199 #else
200   struct tm *loctime;
201 #endif
202
203   /* Get the current time.  */
204   curtime = time( NULL );
205
206   /* Convert it to local time representation.  */
207 #if defined(HAVE_LOCALTIME_R)
208   localtime_r( &curtime, &loctime );
209   strftime( buffer, 255, tformat, &loctime );
210 #else
211   loctime = localtime( &curtime );
212   strftime( buffer, 255, tformat, loctime );
213 #endif
214   return strdup( buffer );
215 }
216
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 )
223 {
224     filter_sys_t *p_sys = p_filter->p_sys;
225     subpicture_t *p_spu;
226     video_format_t fmt;
227
228     if( p_sys->last_time == time( NULL ) ) return NULL;
229
230     p_spu = p_filter->pf_sub_buffer_new( p_filter );
231     if( !p_spu ) return NULL;
232
233     memset( &fmt, 0, sizeof(video_format_t) );
234     fmt.i_chroma = VLC_FOURCC('T','E','X','T');
235     fmt.i_aspect = 0;
236     fmt.i_width = fmt.i_height = 0;     
237     fmt.i_x_offset = 0;
238     fmt.i_y_offset = 0;
239     p_spu->p_region = p_spu->pf_create_region( VLC_OBJECT(p_filter), &fmt );
240     if( !p_spu->p_region )
241     {
242         p_filter->pf_sub_buffer_del( p_filter, p_spu );
243         return NULL;
244     }
245
246     p_sys->last_time = time( NULL );
247
248     p_spu->p_region->psz_text = FormatTime( p_sys->psz_format );
249     p_spu->i_start = date;
250     p_spu->i_stop  = 0;
251     p_spu->b_ephemer = VLC_TRUE;
252
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;
257         p_spu->i_x = 0;
258         p_spu->i_y = 0;
259         p_spu->b_absolute = VLC_FALSE;
260     }
261     else
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;
267     }
268     p_spu->p_region->p_style = p_sys->p_style;
269
270     return p_spu;
271 }
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,
277                             void *p_data )
278 {
279     filter_sys_t *p_sys = (filter_sys_t *) p_data;
280
281     if( !strncmp( psz_var, "time-format", 11 ) )
282     {
283         if( p_sys->psz_format ) free( p_sys->psz_format );
284         p_sys->psz_format = strdup( newval.psz_string );
285     }
286     else if ( !strncmp( psz_var, "time-x", 6 ) )
287     {
288         p_sys->i_xoff = newval.i_int;
289     }
290     else if ( !strncmp( psz_var, "time-y", 6 ) )
291     {
292         p_sys->i_yoff = newval.i_int;
293     }
294     else if ( !strncmp( psz_var, "time-color", 8 ) )  /* "time-c" */ 
295     {
296         p_sys->p_style->i_font_color = newval.i_int;
297     }
298     else if ( !strncmp( psz_var, "time-opacity", 8 ) ) /* "time-o" */ 
299     {
300         p_sys->p_style->i_font_alpha = 255 - newval.i_int;
301     }
302     else if ( !strncmp( psz_var, "time-size", 6 ) )
303     {
304         p_sys->p_style->i_font_size = newval.i_int;
305     }
306     else if ( !strncmp( psz_var, "time-position", 8 ) )
307     /* willing to accept a match against time-pos */
308     {
309         p_sys->i_pos = newval.i_int;
310         p_sys->i_xoff = -1;       /* force to relative positioning */
311     }
312     return VLC_SUCCESS;
313 }