00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdlib.h>
00028 #include <string.h>
00029
00030 #include <vlc/vlc.h>
00031 #include <vlc/vout.h>
00032
00033 #include "vlc_filter.h"
00034 #include "vlc_block.h"
00035 #include "vlc_osd.h"
00036
00037
00038
00039
00040 static int CreateFilter ( vlc_object_t * );
00041 static void DestroyFilter( vlc_object_t * );
00042 static subpicture_t *Filter( filter_t *, mtime_t );
00043
00044
00045 static int MarqueeCallback( vlc_object_t *p_this, char const *psz_var,
00046 vlc_value_t oldval, vlc_value_t newval,
00047 void *p_data );
00048 static int pi_color_values[] = { 0xf0000000, 0x00000000, 0x00808080, 0x00C0C0C0,
00049 0x00FFFFFF, 0x00800000, 0x00FF0000, 0x00FF00FF, 0x00FFFF00,
00050 0x00808000, 0x00008000, 0x00008080, 0x0000FF00, 0x00800080,
00051 0x00000080, 0x000000FF, 0x0000FFFF};
00052 static char *ppsz_color_descriptions[] = { N_("Default"), N_("Black"),
00053 N_("Gray"), N_("Silver"), N_("White"), N_("Maroon"), N_("Red"),
00054 N_("Fuchsia"), N_("Yellow"), N_("Olive"), N_("Green"),
00055 N_("Teal"), N_("Lime"), N_("Purple"), N_("Navy"), N_("Blue"),
00056 N_("Aqua") };
00057
00058
00059
00060
00061 struct filter_sys_t
00062 {
00063 int i_xoff, i_yoff;
00064 int i_pos;
00065 int i_timeout;
00066
00067 char *psz_marquee;
00068
00069 int i_font_color, i_font_opacity, i_font_size;
00070
00071 time_t last_time;
00072
00073 vlc_bool_t b_need_update;
00074 };
00075
00076 #define MSG_TEXT N_("Marquee text")
00077 #define MSG_LONGTEXT N_("Marquee text to display")
00078 #define POSX_TEXT N_("X offset, from left")
00079 #define POSX_LONGTEXT N_("X offset, from the left screen edge" )
00080 #define POSY_TEXT N_("Y offset, from the top")
00081 #define POSY_LONGTEXT N_("Y offset, down from the top" )
00082 #define TIMEOUT_TEXT N_("Marquee timeout")
00083 #define TIMEOUT_LONGTEXT N_("Defines the time the marquee must remain " \
00084 "displayed, in milliseconds. Default value is " \
00085 "0 (remain forever).")
00086 #define OPACITY_TEXT N_("Opacity")
00087 #define OPACITY_LONGTEXT N_("The opacity (inverse of transparency) of " \
00088 "overlay text. 0 = transparent, 255 = totally opaque. " )
00089 #define SIZE_TEXT N_("Font size, pixels")
00090 #define SIZE_LONGTEXT N_("Specify the font size, in pixels, " \
00091 "with -1 = use freetype-fontsize" )
00092
00093 #define COLOR_TEXT N_("Text Default Color")
00094 #define COLOR_LONGTEXT N_("The color of overlay text. 1 byte for each color, hexadecimal. " \
00095 "#000000 = all colors off, " \
00096 "0xFF0000 = just Red, 0xFFFFFF = all color on [White]" )
00097
00098 #define POS_TEXT N_("Marquee position")
00099 #define POS_LONGTEXT N_( \
00100 "You can enforce the marquee position on the video " \
00101 "(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \
00102 "also use combinations of these values by adding them).")
00103
00104 static int pi_pos_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };
00105 static char *ppsz_pos_descriptions[] =
00106 { N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
00107 N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };
00108
00109
00110
00111
00112 vlc_module_begin();
00113 set_capability( "sub filter", 0 );
00114 set_shortname( N_("Marquee" ));
00115 set_callbacks( CreateFilter, DestroyFilter );
00116 set_category( CAT_VIDEO );
00117 set_subcategory( SUBCAT_VIDEO_SUBPIC );
00118 add_string( "marq-marquee", "VLC", NULL, MSG_TEXT, MSG_LONGTEXT,
00119 VLC_FALSE );
00120
00121 set_section( N_("Position"), NULL );
00122 add_integer( "marq-x", -1, NULL, POSX_TEXT, POSX_LONGTEXT, VLC_TRUE );
00123 add_integer( "marq-y", 0, NULL, POSY_TEXT, POSY_LONGTEXT, VLC_TRUE );
00124 add_integer( "marq-position", 5, NULL, POS_TEXT, POS_LONGTEXT, VLC_FALSE );
00125
00126 set_section( N_("Font"), NULL );
00127
00128 change_integer_list( pi_pos_values, ppsz_pos_descriptions, 0 );
00129 add_integer_with_range( "marq-opacity", 255, 0, 255, NULL,
00130 OPACITY_TEXT, OPACITY_LONGTEXT, VLC_FALSE );
00131 add_integer( "marq-color", 0xFFFFFF, NULL, COLOR_TEXT, COLOR_LONGTEXT,
00132 VLC_FALSE );
00133 change_integer_list( pi_color_values, ppsz_color_descriptions, 0 );
00134 add_integer( "marq-size", -1, NULL, SIZE_TEXT, SIZE_LONGTEXT, VLC_FALSE );
00135
00136 set_section( N_("Misc"), NULL );
00137 add_integer( "marq-timeout", 0, NULL, TIMEOUT_TEXT, TIMEOUT_LONGTEXT,
00138 VLC_FALSE );
00139
00140 set_description( _("Marquee display sub filter") );
00141 add_shortcut( "marq" );
00142 vlc_module_end();
00143
00144
00145
00146
00147 static int CreateFilter( vlc_object_t *p_this )
00148 {
00149 filter_t *p_filter = (filter_t *)p_this;
00150 filter_sys_t *p_sys;
00151 vlc_object_t *p_input;
00152
00153
00154 p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
00155 if( p_sys == NULL )
00156 {
00157 msg_Err( p_filter, "out of memory" );
00158 return VLC_ENOMEM;
00159 }
00160
00161
00162 p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_ANYWHERE );
00163 if( !p_input )
00164 {
00165 return VLC_ENOOBJ;
00166 }
00167
00168 p_sys->i_xoff = var_CreateGetInteger( p_input->p_libvlc , "marq-x" );
00169 p_sys->i_yoff = var_CreateGetInteger( p_input->p_libvlc , "marq-y" );
00170 p_sys->i_timeout = var_CreateGetInteger( p_input->p_libvlc , "marq-timeout" );
00171 p_sys->i_pos = var_CreateGetInteger( p_input->p_libvlc , "marq-position" );
00172 p_sys->psz_marquee = var_CreateGetString( p_input->p_libvlc, "marq-marquee" );
00173 var_Create( p_input->p_libvlc, "marq-opacity", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
00174 p_sys->i_font_opacity = var_CreateGetInteger( p_input->p_libvlc , "marq-opacity" );
00175 p_sys->i_font_color = var_CreateGetInteger( p_input->p_libvlc , "marq-color" );
00176 p_sys->i_font_size = var_CreateGetInteger( p_input->p_libvlc , "marq-size" );
00177
00178 var_AddCallback( p_input->p_libvlc, "marq-x", MarqueeCallback, p_sys );
00179 var_AddCallback( p_input->p_libvlc, "marq-y", MarqueeCallback, p_sys );
00180 var_AddCallback( p_input->p_libvlc, "marq-marquee", MarqueeCallback, p_sys );
00181 var_AddCallback( p_input->p_libvlc, "marq-timeout", MarqueeCallback, p_sys );
00182 var_AddCallback( p_input->p_libvlc, "marq-position", MarqueeCallback, p_sys );
00183 var_AddCallback( p_input->p_libvlc, "marq-color", MarqueeCallback, p_sys );
00184 var_AddCallback( p_input->p_libvlc, "marq-opacity", MarqueeCallback, p_sys );
00185 var_AddCallback( p_input->p_libvlc, "marq-size", MarqueeCallback, p_sys );
00186
00187 vlc_object_release( p_input );
00188
00189
00190
00191 p_filter->pf_sub_filter = Filter;
00192 p_sys->last_time = ((time_t)-1);
00193 p_sys->b_need_update = VLC_TRUE;
00194
00195 return VLC_SUCCESS;
00196 }
00197
00198
00199
00200 static void DestroyFilter( vlc_object_t *p_this )
00201 {
00202 filter_t *p_filter = (filter_t *)p_this;
00203 filter_sys_t *p_sys = p_filter->p_sys;
00204 vlc_object_t *p_input;
00205
00206 if( p_sys->psz_marquee ) free( p_sys->psz_marquee );
00207 free( p_sys );
00208
00209
00210 p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_ANYWHERE );
00211 if( !p_input )
00212 {
00213 return;
00214 }
00215 var_DelCallback( p_input->p_libvlc, "marq-x", MarqueeCallback, p_sys );
00216 var_DelCallback( p_input->p_libvlc, "marq-y", MarqueeCallback, p_sys );
00217 var_DelCallback( p_input->p_libvlc, "marq-marquee", MarqueeCallback, p_sys );
00218 var_DelCallback( p_input->p_libvlc, "marq-timeout", MarqueeCallback, p_sys );
00219 var_DelCallback( p_input->p_libvlc, "marq-position", MarqueeCallback, p_sys );
00220 var_DelCallback( p_input->p_libvlc, "marq-color", MarqueeCallback, p_sys );
00221 var_DelCallback( p_input->p_libvlc, "marq-opacity", MarqueeCallback, p_sys );
00222 var_DelCallback( p_input->p_libvlc, "marq-size", MarqueeCallback, p_sys );
00223
00224 var_Destroy( p_input->p_libvlc , "marq-marquee" );
00225 var_Destroy( p_input->p_libvlc , "marq-x" );
00226 var_Destroy( p_input->p_libvlc , "marq-y" );
00227 var_Destroy( p_input->p_libvlc , "marq-timeout" );
00228 var_Destroy( p_input->p_libvlc , "marq-position" );
00229 var_Destroy( p_input->p_libvlc , "marq-color");
00230 var_Destroy( p_input->p_libvlc , "marq-opacity");
00231 var_Destroy( p_input->p_libvlc , "marq-size");
00232
00233 vlc_object_release( p_input );
00234 }
00235
00236
00237
00238
00239
00240
00241 static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
00242 {
00243 filter_sys_t *p_sys = p_filter->p_sys;
00244 subpicture_t *p_spu;
00245 video_format_t fmt;
00246 time_t t;
00247
00248 if( p_sys->last_time == time( NULL ) )
00249 {
00250 return NULL;
00251 }
00252
00253 if( p_sys->b_need_update == VLC_FALSE )
00254 {
00255 return NULL;
00256 }
00257
00258 p_spu = p_filter->pf_sub_buffer_new( p_filter );
00259 if( !p_spu ) return NULL;
00260
00261 memset( &fmt, 0, sizeof(video_format_t) );
00262 fmt.i_chroma = VLC_FOURCC('T','E','X','T');
00263 fmt.i_aspect = 0;
00264 fmt.i_width = fmt.i_height = 0;
00265 fmt.i_x_offset = 0;
00266 fmt.i_y_offset = 0;
00267 p_spu->p_region = p_spu->pf_create_region( VLC_OBJECT(p_filter), &fmt );
00268 if( !p_spu->p_region )
00269 {
00270 p_filter->pf_sub_buffer_del( p_filter, p_spu );
00271 return NULL;
00272 }
00273
00274 t = p_sys->last_time = time( NULL );
00275
00276 p_spu->p_region->psz_text = strdup(p_sys->psz_marquee);
00277 p_spu->i_start = date;
00278 p_spu->i_stop = p_sys->i_timeout == 0 ? 0 : date + p_sys->i_timeout * 1000;
00279 p_spu->b_ephemer = VLC_TRUE;
00280
00281
00282 if( p_sys->i_xoff < 0 || p_sys->i_yoff < 0 )
00283 {
00284 p_spu->i_flags = p_sys->i_pos;
00285 p_spu->i_x = 0;
00286 p_spu->i_y = 0;
00287 p_spu->b_absolute = VLC_FALSE;
00288 }
00289 else
00290 {
00291 p_spu->i_flags = OSD_ALIGN_LEFT | OSD_ALIGN_TOP;
00292 p_spu->i_x = p_sys->i_xoff;
00293 p_spu->i_y = p_sys->i_yoff;
00294 p_spu->b_absolute = VLC_TRUE;
00295 }
00296 p_spu->p_region->i_text_color = p_sys->i_font_color;
00297 p_spu->p_region->i_text_alpha = 255 - p_sys->i_font_opacity;
00298 p_spu->p_region->i_text_size = p_sys->i_font_size;
00299
00300
00301 p_sys->b_need_update = VLC_FALSE;
00302 return p_spu;
00303 }
00304
00305
00306
00307
00308 static int MarqueeCallback( vlc_object_t *p_this, char const *psz_var,
00309 vlc_value_t oldval, vlc_value_t newval,
00310 void *p_data )
00311 {
00312 filter_sys_t *p_sys = (filter_sys_t *) p_data;
00313
00314 if( !strncmp( psz_var, "marq-marquee", 7 ) )
00315 {
00316 if( p_sys->psz_marquee ) free( p_sys->psz_marquee );
00317 p_sys->psz_marquee = strdup( newval.psz_string );
00318 }
00319 else if ( !strncmp( psz_var, "marq-x", 6 ) )
00320 {
00321 p_sys->i_xoff = newval.i_int;
00322 }
00323 else if ( !strncmp( psz_var, "marq-y", 6 ) )
00324 {
00325 p_sys->i_yoff = newval.i_int;
00326 }
00327 else if ( !strncmp( psz_var, "marq-color", 8 ) )
00328 {
00329 p_sys->i_font_color = newval.i_int;
00330 }
00331 else if ( !strncmp( psz_var, "marq-opacity", 8 ) )
00332 {
00333 p_sys->i_font_opacity = newval.i_int;
00334 }
00335 else if ( !strncmp( psz_var, "marq-size", 6 ) )
00336 {
00337 p_sys->i_font_size = newval.i_int;
00338 }
00339 else if ( !strncmp( psz_var, "marq-timeout", 12 ) )
00340 {
00341 p_sys->i_timeout = newval.i_int;
00342 }
00343 else if ( !strncmp( psz_var, "marq-position", 8 ) )
00344
00345 {
00346 p_sys->i_pos = newval.i_int;
00347 p_sys->i_xoff = -1;
00348 }
00349 p_sys->b_need_update = VLC_TRUE;
00350 return VLC_SUCCESS;
00351 }