MacOS X: fix preferences for ModulesConfig
[vlc.git] / modules / gui / fbosd.c
blobce9c36909067c6a2fb0aa305ba9d6b84de7f225d
1 /*****************************************************************************
2 * fbosd.c : framebuffer osd plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2007-2008, the VideoLAN team
5 * $Id$
7 * Authors: Jean-Paul Saman
8 * Copied from modules/video_output/fb.c by Samuel Hocevar <sam@zoy.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
26 * Preamble
27 *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_fs.h>
35 #include <vlc_modules.h>
37 #include <stdlib.h> /* free() */
38 #include <string.h> /* strerror() */
39 #include <fcntl.h> /* open() */
40 #include <unistd.h> /* close() */
42 #include <sys/ioctl.h>
43 #include <sys/mman.h> /* mmap() */
45 #include <linux/fb.h>
47 #include <vlc_image.h>
48 #include <vlc_interface.h>
49 #include <vlc_input.h>
50 #include <vlc_vout.h>
51 #include <vlc_filter.h>
52 #include <vlc_osd.h>
53 #include <vlc_strings.h>
55 #undef FBOSD_BLENDING
56 #undef FBOSD_DEBUG
58 /*****************************************************************************
59 * Local prototypes
60 *****************************************************************************/
61 static int Create ( vlc_object_t * );
62 static void Destroy ( vlc_object_t * );
63 static void Run ( intf_thread_t * );
65 static int Init ( intf_thread_t * );
66 static void End ( intf_thread_t * );
68 static int OpenDisplay ( intf_thread_t * );
69 static void CloseDisplay ( intf_thread_t * );
71 /* Load modules needed for rendering and blending */
72 #if defined(FBOSD_BLENDING)
73 static int OpenBlending ( intf_thread_t * );
74 static void CloseBlending ( intf_thread_t * );
75 #endif
76 static int OpenTextRenderer ( intf_thread_t * );
77 static void CloseTextRenderer( intf_thread_t * );
79 /* Manipulate the overlay buffer */
80 static int OverlayCallback( vlc_object_t *, char const *,
81 vlc_value_t, vlc_value_t, void * );
83 static picture_t *AllocatePicture( video_format_t * );
84 static void DeAllocatePicture( picture_t *, video_format_t * );
85 static void SetOverlayTransparency( intf_thread_t *,
86 bool );
87 static picture_t *LoadImage( intf_thread_t *, video_format_t *,
88 char * );
90 #if defined(FBOSD_BLENDING)
91 static int BlendPicture( intf_thread_t *, video_format_t *,
92 video_format_t *, picture_t *, picture_t * );
93 #else
94 static picture_t *ConvertImage( intf_thread_t *, picture_t *,
95 video_format_t *, video_format_t * );
96 #endif
97 static int RenderPicture( intf_thread_t *, int, int,
98 picture_t *, picture_t * );
99 static picture_t *RenderText( intf_thread_t *, const char *,
100 text_style_t *, video_format_t * );
102 #define DEVICE_TEXT N_("Framebuffer device")
103 #define DEVICE_LONGTEXT N_( \
104 "Framebuffer device to use for rendering (usually /dev/fb0).")
106 #define ASPECT_RATIO_TEXT N_("Video aspect ratio")
107 #define ASPECT_RATIO_LONGTEXT N_( \
108 "Aspect ratio of the video image (4:3, 16:9). Default is square pixels." )
110 #define FBOSD_IMAGE_TEXT N_("Image file")
111 #define FBOSD_IMAGE_LONGTEXT N_( \
112 "Filename of image file to use on the overlay framebuffer." )
114 #define ALPHA_TEXT N_("Transparency of the image")
115 #define ALPHA_LONGTEXT N_( "Transparency value of the new image " \
116 "used in blending. By default it set to fully opaque (255). " \
117 "(from 0 for full transparency to 255 for full opacity)" )
119 #define FBOSD_TEXT N_("Text")
120 #define FBOSD_LONGTEXT N_( "Text to display on the overlay framebuffer." )
122 #define POSX_TEXT N_("X coordinate")
123 #define POSX_LONGTEXT N_("X coordinate of the rendered image")
125 #define POSY_TEXT N_("Y coordinate")
126 #define POSY_LONGTEXT N_("Y coordinate of the rendered image")
128 #define POS_TEXT N_("Position")
129 #define POS_LONGTEXT N_( \
130 "You can enforce the picture position on the overlay " \
131 "(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \
132 "also use combinations of these values, e.g. 6=top-right).")
134 #define OPACITY_TEXT N_("Opacity")
135 #define OPACITY_LONGTEXT N_("Opacity (inverse of transparency) of " \
136 "overlayed text. 0 = transparent, 255 = totally opaque. " )
138 #define SIZE_TEXT N_("Font size, pixels")
139 #define SIZE_LONGTEXT N_("Font size, in pixels. Default is -1 (use default " \
140 "font size)." )
142 #define COLOR_TEXT N_("Color")
143 #define COLOR_LONGTEXT N_("Color of the text that will be rendered on "\
144 "the video. This must be an hexadecimal (like HTML colors). The first two "\
145 "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
146 " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
148 #define CLEAR_TEXT N_( "Clear overlay framebuffer" )
149 #define CLEAR_LONGTEXT N_( "The displayed overlay images is cleared by " \
150 "making the overlay completely transparent. All previously rendered " \
151 "images and text will be cleared from the cache." )
153 #define RENDER_TEXT N_( "Render text or image" )
154 #define RENDER_LONGTEXT N_( "Render the image or text in current overlay " \
155 "buffer." )
157 #define DISPLAY_TEXT N_( "Display on overlay framebuffer" )
158 #define DISPLAY_LONGTEXT N_( "All rendered images and text will be " \
159 "displayed on the overlay framebuffer." )
161 static const int pi_pos_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };
162 static const char *const ppsz_pos_descriptions[] =
163 { N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
164 N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };
166 static const int pi_color_values[] = {
167 0xf0000000, 0x00000000, 0x00808080, 0x00C0C0C0,
168 0x00FFFFFF, 0x00800000, 0x00FF0000, 0x00FF00FF, 0x00FFFF00,
169 0x00808000, 0x00008000, 0x00008080, 0x0000FF00, 0x00800080,
170 0x00000080, 0x000000FF, 0x0000FFFF};
171 static const char *const ppsz_color_descriptions[] = {
172 N_("Default"), N_("Black"),
173 N_("Gray"), N_("Silver"), N_("White"), N_("Maroon"), N_("Red"),
174 N_("Fuchsia"), N_("Yellow"), N_("Olive"), N_("Green"),
175 N_("Teal"), N_("Lime"), N_("Purple"), N_("Navy"), N_("Blue"),
176 N_("Aqua") };
178 vlc_module_begin ()
179 set_shortname( "fbosd" )
180 set_category( CAT_INTERFACE )
181 set_subcategory( SUBCAT_INTERFACE_MAIN )
183 add_loadfile( "fbosd-dev", "/dev/fb0", DEVICE_TEXT, DEVICE_LONGTEXT,
184 false )
185 add_string( "fbosd-aspect-ratio", "", ASPECT_RATIO_TEXT,
186 ASPECT_RATIO_LONGTEXT, true )
188 add_string( "fbosd-image", NULL, FBOSD_IMAGE_TEXT,
189 FBOSD_IMAGE_LONGTEXT, true )
190 add_string( "fbosd-text", NULL, FBOSD_TEXT,
191 FBOSD_LONGTEXT, true )
193 add_integer_with_range( "fbosd-alpha", 255, 0, 255, ALPHA_TEXT,
194 ALPHA_LONGTEXT, true )
196 set_section( N_("Position"), NULL )
197 add_integer( "fbosd-x", 0, POSX_TEXT,
198 POSX_LONGTEXT, false )
199 add_integer( "fbosd-y", 0, POSY_TEXT,
200 POSY_LONGTEXT, false )
201 add_integer( "fbosd-position", 8, POS_TEXT, POS_LONGTEXT, true )
202 change_integer_list( pi_pos_values, ppsz_pos_descriptions );
204 set_section( N_("Font"), NULL )
205 add_integer_with_range( "fbosd-font-opacity", 255, 0, 255,
206 OPACITY_TEXT, OPACITY_LONGTEXT, false )
207 add_integer( "fbosd-font-color", 0x00FFFFFF, COLOR_TEXT, COLOR_LONGTEXT,
208 false )
209 change_integer_list( pi_color_values, ppsz_color_descriptions );
210 add_integer( "fbosd-font-size", -1, SIZE_TEXT, SIZE_LONGTEXT,
211 false )
213 set_section( N_("Commands"), NULL )
214 add_bool( "fbosd-clear", false, CLEAR_TEXT, CLEAR_LONGTEXT, true )
215 add_bool( "fbosd-render", false, RENDER_TEXT, RENDER_LONGTEXT, true )
216 add_bool( "fbosd-display", false, DISPLAY_TEXT, DISPLAY_LONGTEXT, true )
218 set_description( N_("GNU/Linux osd/overlay framebuffer interface") )
219 set_capability( "interface", 10 )
220 set_callbacks( Create, Destroy )
221 vlc_module_end ()
223 /*****************************************************************************
224 * fbosd_render_t: render descriptor
225 *****************************************************************************/
226 struct fbosd_render_t
228 #define FBOSD_RENDER_IMAGE 0
229 #define FBOSD_RENDER_TEXT 1
230 int i_type;
232 #define FBOSD_STATE_FREE 0
233 #define FBOSD_STATE_RESERVED 1
234 #define FBOSD_STATE_RENDER 2
235 int i_state;
237 /* Font style */
238 text_style_t* p_text_style; /* font control */
239 char *psz_string;
241 /* Position */
242 bool b_absolute;
243 int i_x;
244 int i_y;
245 int i_pos;
246 int i_alpha; /* transparency for images */
248 #define FBOSD_RENDER_MAX 10
250 /*****************************************************************************
251 * intf_sys_t: interface framebuffer method descriptor
252 *****************************************************************************/
253 struct intf_sys_t
255 /* Framebuffer information */
256 int i_fd; /* device handle */
257 struct fb_var_screeninfo var_info; /* current mode information */
258 bool b_pan; /* does device supports panning ? */
259 struct fb_cmap fb_cmap; /* original colormap */
260 uint16_t *p_palette; /* original palette */
262 /* Overlay framebuffer format */
263 video_format_t fmt_out;
264 picture_t *p_overlay;
265 size_t i_page_size; /* page size */
266 int i_width;
267 int i_height;
268 int i_aspect;
269 int i_bytes_per_pixel;
271 /* Image and Picture rendering */
272 image_handler_t *p_image;
273 #if defined(FBOSD_BLENDING)
274 filter_t *p_blend; /* alpha blending module */
275 #endif
276 filter_t *p_text; /* text renderer module */
278 /* Render */
279 struct fbosd_render_t render[FBOSD_RENDER_MAX];
281 /* Font style */
282 text_style_t *p_style; /* font control */
284 /* Position */
285 bool b_absolute;
286 int i_x;
287 int i_y;
288 int i_pos;
290 int i_alpha; /* transparency for images */
292 /* commands control */
293 bool b_need_update; /* update display with \overlay buffer */
294 bool b_clear; /* clear overlay buffer make it tranparent */
295 bool b_render; /* render an image or text in overlay buffer */
298 /*****************************************************************************
299 * Create: allocates FB interface thread output method
300 *****************************************************************************/
301 static int Create( vlc_object_t *p_this )
303 intf_thread_t *p_intf = (intf_thread_t *)p_this;
304 intf_sys_t *p_sys;
305 char *psz_aspect;
306 char *psz_tmp;
307 int i;
309 /* Allocate instance and initialize some members */
310 p_intf->p_sys = p_sys = calloc( 1, sizeof( intf_sys_t ) );
311 if( !p_intf->p_sys )
312 return VLC_ENOMEM;
314 p_sys->p_style = text_style_New();
315 if( !p_sys->p_style )
317 free( p_intf->p_sys );
318 return VLC_ENOMEM;
321 p_intf->pf_run = Run;
323 p_sys->p_image = image_HandlerCreate( p_this );
324 if( !p_sys->p_image )
326 text_style_Delete( p_sys->p_style );
327 free( p_sys );
328 return VLC_ENOMEM;
331 p_sys->i_alpha = var_CreateGetIntegerCommand( p_intf, "fbosd-alpha" );
332 var_AddCallback( p_intf, "fbosd-alpha", OverlayCallback, NULL );
334 /* Use PAL by default */
335 p_sys->i_width = p_sys->fmt_out.i_width = 704;
336 p_sys->i_height = p_sys->fmt_out.i_height = 576;
338 p_sys->i_aspect = -1;
339 psz_aspect =
340 var_CreateGetNonEmptyString( p_intf, "fbosd-aspect-ratio" );
341 if( psz_aspect )
343 char *psz_parser = strchr( psz_aspect, ':' );
345 if( psz_parser )
347 *psz_parser++ = '\0';
348 p_sys->i_aspect = ( atoi( psz_aspect )
349 * VOUT_ASPECT_FACTOR ) / atoi( psz_parser );
350 p_sys->fmt_out.i_sar_num = p_sys->i_aspect * p_sys->i_height;
351 p_sys->fmt_out.i_sar_den = VOUT_ASPECT_FACTOR * p_sys->i_width;
353 msg_Dbg( p_intf, "using aspect ratio %d:%d",
354 atoi( psz_aspect ), atoi( psz_parser ) );
356 free( psz_aspect );
359 psz_tmp = var_CreateGetNonEmptyStringCommand( p_intf, "fbosd-image" );
360 var_AddCallback( p_intf, "fbosd-image", OverlayCallback, NULL );
361 if( psz_tmp && *psz_tmp )
363 p_sys->render[0].i_type = FBOSD_RENDER_IMAGE;
364 p_sys->render[0].i_state = FBOSD_STATE_RENDER;
365 p_sys->render[0].psz_string = strdup( psz_tmp );
367 free( psz_tmp );
369 psz_tmp = var_CreateGetNonEmptyStringCommand( p_intf, "fbosd-text" );
370 var_AddCallback( p_intf, "fbosd-text", OverlayCallback, NULL );
371 if( psz_tmp && *psz_tmp )
373 p_sys->render[1].i_type = FBOSD_RENDER_TEXT;
374 p_sys->render[1].i_state = FBOSD_STATE_RENDER;
375 p_sys->render[1].psz_string = strdup( psz_tmp );
377 free( psz_tmp );
379 p_sys->i_pos = var_CreateGetIntegerCommand( p_intf, "fbosd-position" );
380 p_sys->i_x = var_CreateGetIntegerCommand( p_intf, "fbosd-x" );
381 p_sys->i_y = var_CreateGetIntegerCommand( p_intf, "fbosd-y" );
383 var_AddCallback( p_intf, "fbosd-position", OverlayCallback, NULL );
384 var_AddCallback( p_intf, "fbosd-x", OverlayCallback, NULL );
385 var_AddCallback( p_intf, "fbosd-y", OverlayCallback, NULL );
387 p_sys->p_style->i_font_size =
388 var_CreateGetIntegerCommand( p_intf, "fbosd-font-size" );
389 p_sys->p_style->i_font_color =
390 var_CreateGetIntegerCommand( p_intf, "fbosd-font-color" );
391 p_sys->p_style->i_font_alpha = 255 -
392 var_CreateGetIntegerCommand( p_intf, "fbosd-font-opacity" );
394 var_AddCallback( p_intf, "fbosd-font-color", OverlayCallback, NULL );
395 var_AddCallback( p_intf, "fbosd-font-size", OverlayCallback, NULL );
396 var_AddCallback( p_intf, "fbosd-font-opacity", OverlayCallback, NULL );
398 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
399 p_sys->render[i].p_text_style = text_style_New();
401 p_sys->b_clear = var_CreateGetBoolCommand( p_intf, "fbosd-clear" );
402 p_sys->b_render = var_CreateGetBoolCommand( p_intf, "fbosd-render" );
403 p_sys->b_need_update = var_CreateGetBoolCommand( p_intf, "fbosd-display" );
405 var_AddCallback( p_intf, "fbosd-clear", OverlayCallback, NULL );
406 var_AddCallback( p_intf, "fbosd-render", OverlayCallback, NULL );
407 var_AddCallback( p_intf, "fbosd-display", OverlayCallback, NULL );
409 /* Check if picture position was overridden */
410 p_sys->b_absolute = true;
411 if( ( p_sys->i_x >= 0 ) && ( p_sys->i_y >= 0 ) )
413 p_sys->b_absolute = false;
414 p_sys->i_y = (p_sys->i_y < p_sys->i_height) ?
415 p_sys->i_y : p_sys->i_height;
416 p_sys->i_x = (p_sys->i_x < p_sys->i_width) ?
417 p_sys->i_x : p_sys->i_width;
420 p_sys->render[0].i_x = p_sys->render[1].i_x = p_sys->i_x;
421 p_sys->render[0].i_y = p_sys->render[1].i_y = p_sys->i_y;
422 p_sys->render[0].i_pos = p_sys->render[1].i_pos = p_sys->i_pos;
423 p_sys->render[0].i_alpha = p_sys->render[1].i_alpha = p_sys->i_alpha;
425 /* Initialize framebuffer */
426 if( OpenDisplay( p_intf ) )
428 Destroy( VLC_OBJECT(p_intf) );
429 return VLC_EGENERIC;
432 Init( p_intf );
434 #if defined(FBOSD_BLENDING)
435 /* Load the blending module */
436 if( OpenBlending( p_intf ) )
438 msg_Err( p_intf, "Unable to load image blending module" );
439 Destroy( VLC_OBJECT(p_intf) );
440 return VLC_EGENERIC;
442 #endif
444 /* Load text renderer module */
445 if( OpenTextRenderer( p_intf ) )
447 msg_Err( p_intf, "Unable to load text rendering module" );
448 Destroy( VLC_OBJECT(p_intf) );
449 return VLC_EGENERIC;
452 p_sys->b_render = true;
453 p_sys->b_need_update = true;
455 return VLC_SUCCESS;
458 /*****************************************************************************
459 * Destroy: destroy FB interface thread output method
460 *****************************************************************************
461 * Terminate an output method created by Create
462 *****************************************************************************/
463 static void Destroy( vlc_object_t *p_this )
465 intf_thread_t *p_intf = (intf_thread_t *)p_this;
466 intf_sys_t *p_sys = p_intf->p_sys;
467 int i;
470 p_sys->b_need_update = false;
471 p_sys->b_render = false;
472 p_sys->b_clear = false;
474 var_DelCallback( p_intf, "fbosd-alpha", OverlayCallback, NULL );
475 var_Destroy( p_intf, "fbosd-alpha" );
477 var_DelCallback( p_intf, "fbosd-x", OverlayCallback, NULL );
478 var_DelCallback( p_intf, "fbosd-y", OverlayCallback, NULL );
479 var_DelCallback( p_intf, "fbosd-position", OverlayCallback, NULL );
480 var_DelCallback( p_intf, "fbosd-image", OverlayCallback, NULL );
481 var_DelCallback( p_intf, "fbosd-text", OverlayCallback, NULL );
482 var_DelCallback( p_intf, "fbosd-font-size", OverlayCallback, NULL );
483 var_DelCallback( p_intf, "fbosd-font-color", OverlayCallback, NULL );
484 var_DelCallback( p_intf, "fbosd-font-opacity", OverlayCallback, NULL );
485 var_DelCallback( p_intf, "fbosd-clear", OverlayCallback, NULL );
486 var_DelCallback( p_intf, "fbosd-render", OverlayCallback, NULL );
487 var_DelCallback( p_intf, "fbosd-display", OverlayCallback, NULL );
489 var_Destroy( p_intf, "fbosd-x" );
490 var_Destroy( p_intf, "fbosd-y" );
491 var_Destroy( p_intf, "fbosd-position" );
492 var_Destroy( p_intf, "fbosd-image" );
493 var_Destroy( p_intf, "fbosd-text" );
494 var_Destroy( p_intf, "fbosd-font-size" );
495 var_Destroy( p_intf, "fbosd-font-color" );
496 var_Destroy( p_intf, "fbosd-font-opacity" );
497 var_Destroy( p_intf, "fbosd-clear" );
498 var_Destroy( p_intf, "fbosd-render" );
499 var_Destroy( p_intf, "fbosd-display" );
501 var_Destroy( p_intf, "fbosd-aspect-ratio" );
503 CloseDisplay( p_intf );
505 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
507 free( p_sys->render[i].psz_string );
508 p_sys->render[i].i_state = FBOSD_STATE_FREE;
509 text_style_Delete( p_sys->render[i].p_text_style );
512 #if defined(FBOSD_BLENDING)
513 if( p_sys->p_blend ) CloseBlending( p_intf );
514 #endif
515 if( p_sys->p_text ) CloseTextRenderer( p_intf );
517 if( p_sys->p_image )
518 image_HandlerDelete( p_sys->p_image );
519 if( p_sys->p_overlay )
520 picture_Release( p_sys->p_overlay );
522 text_style_Delete( p_sys->p_style );
523 free( p_sys );
526 #if defined(FBOSD_BLENDING)
527 static int OpenBlending( intf_thread_t *p_intf )
529 if( p_intf->p_sys->p_blend ) return VLC_EGENERIC;
531 p_intf->p_sys->p_blend =
532 vlc_object_create( p_intf, sizeof(filter_t) );
533 p_intf->p_sys->p_blend->fmt_out.video.i_x_offset =
534 p_intf->p_sys->p_blend->fmt_out.video.i_y_offset = 0;
535 p_intf->p_sys->p_blend->fmt_out.video.i_sar_num =
536 p_intf->p_sys->fmt_out.i_sar_num;
537 p_intf->p_sys->p_blend->fmt_out.video.i_sar_den =
538 p_intf->p_sys->fmt_out.i_sar_den;
539 p_intf->p_sys->p_blend->fmt_out.video.i_chroma =
540 p_intf->p_sys->fmt_out.i_chroma;
541 if( var_InheritBool( p_intf, "freetype-yuvp" ) )
542 p_intf->p_sys->p_blend->fmt_in.video.i_chroma =
543 VLC_CODEC_YUVP;
544 else
545 p_intf->p_sys->p_blend->fmt_in.video.i_chroma =
546 VLC_CODEC_YUVA;
548 p_intf->p_sys->p_blend->p_module =
549 module_need( p_intf->p_sys->p_blend, "video blending", NULL, false );
551 if( !p_intf->p_sys->p_blend->p_module )
552 return VLC_EGENERIC;
554 return VLC_SUCCESS;
557 static void CloseBlending( intf_thread_t *p_intf )
559 if( p_intf->p_sys->p_blend )
561 if( p_intf->p_sys->p_blend->p_module )
562 module_unneed( p_intf->p_sys->p_blend,
563 p_intf->p_sys->p_blend->p_module );
565 vlc_object_release( p_intf->p_sys->p_blend );
568 #endif
570 static int OpenTextRenderer( intf_thread_t *p_intf )
572 char *psz_modulename = NULL;
574 if( p_intf->p_sys->p_text ) return VLC_EGENERIC;
576 p_intf->p_sys->p_text =
577 vlc_object_create( p_intf, sizeof(filter_t) );
579 p_intf->p_sys->p_text->fmt_out.video.i_width =
580 p_intf->p_sys->p_text->fmt_out.video.i_visible_width =
581 p_intf->p_sys->i_width;
582 p_intf->p_sys->p_text->fmt_out.video.i_height =
583 p_intf->p_sys->p_text->fmt_out.video.i_visible_height =
584 p_intf->p_sys->i_height;
586 psz_modulename = var_CreateGetString( p_intf, "text-renderer" );
587 if( psz_modulename && *psz_modulename )
589 p_intf->p_sys->p_text->p_module =
590 module_need( p_intf->p_sys->p_text, "text renderer",
591 psz_modulename, true );
593 if( !p_intf->p_sys->p_text->p_module )
595 p_intf->p_sys->p_text->p_module =
596 module_need( p_intf->p_sys->p_text, "text renderer", NULL, false );
598 free( psz_modulename );
600 if( !p_intf->p_sys->p_text->p_module )
601 return VLC_EGENERIC;
603 return VLC_SUCCESS;
606 static void CloseTextRenderer( intf_thread_t *p_intf )
608 if( p_intf->p_sys->p_text )
610 if( p_intf->p_sys->p_text->p_module )
611 module_unneed( p_intf->p_sys->p_text,
612 p_intf->p_sys->p_text->p_module );
614 vlc_object_release( p_intf->p_sys->p_text );
618 /*****************************************************************************
619 * AllocatePicture:
620 * allocate a picture buffer for use with the overlay fb.
621 *****************************************************************************/
622 static picture_t *AllocatePicture( video_format_t *p_fmt )
624 picture_t *p_picture = picture_NewFromFormat( p_fmt );
625 if( !p_picture )
626 return NULL;
628 if( !p_fmt->p_palette &&
629 ( p_fmt->i_chroma == VLC_CODEC_YUVP ) )
631 p_fmt->p_palette = malloc( sizeof(video_palette_t) );
632 if( !p_fmt->p_palette )
634 picture_Release( p_picture );
635 return NULL;
638 else
640 p_fmt->p_palette = NULL;
643 return p_picture;
646 /*****************************************************************************
647 * DeAllocatePicture:
648 * Deallocate a picture buffer and free all associated memory.
649 *****************************************************************************/
650 static void DeAllocatePicture( picture_t *p_pic, video_format_t *p_fmt )
652 if( p_fmt )
654 free( p_fmt->p_palette );
655 p_fmt->p_palette = NULL;
658 if( p_pic )
659 picture_Release( p_pic );
662 /*****************************************************************************
663 * SetOverlayTransparency: Set the transparency for this overlay fb,
664 * - true is make transparent
665 * - false is make non tranparent
666 *****************************************************************************/
667 static void SetOverlayTransparency( intf_thread_t *p_intf,
668 bool b_transparent )
670 intf_sys_t *p_sys = p_intf->p_sys;
671 size_t i_size = p_sys->fmt_out.i_width * p_sys->fmt_out.i_height
672 * p_sys->i_bytes_per_pixel;
673 size_t i_page_size = (p_sys->i_page_size > i_size) ?
674 i_size : p_sys->i_page_size;
676 if( p_sys->p_overlay )
678 msg_Dbg( p_intf, "Make overlay %s",
679 b_transparent ? "transparent" : "opaque" );
680 if( b_transparent )
681 memset( p_sys->p_overlay->p[0].p_pixels, 0xFF, i_page_size );
682 else
683 memset( p_sys->p_overlay->p[0].p_pixels, 0x00, i_page_size );
687 #if defined(FBOSD_BLENDING)
688 /*****************************************************************************
689 * BlendPicture: Blend two pictures together..
690 *****************************************************************************/
691 static int BlendPicture( intf_thread_t *p_intf, video_format_t *p_fmt_src,
692 video_format_t *p_fmt_dst, picture_t *p_pic_src,
693 picture_t *p_pic_dst )
695 intf_sys_t *p_sys = p_intf->p_sys;
696 if( p_sys->p_blend && p_sys->p_blend->p_module )
698 int i_x_offset = p_sys->i_x;
699 int i_y_offset = p_sys->i_y;
701 memcpy( &p_sys->p_blend->fmt_in.video, p_fmt_src, sizeof( video_format_t ) );
703 /* Update the output picture size */
704 p_sys->p_blend->fmt_out.video.i_width =
705 p_sys->p_blend->fmt_out.video.i_visible_width =
706 p_fmt_dst->i_width;
707 p_sys->p_blend->fmt_out.video.i_height =
708 p_sys->p_blend->fmt_out.video.i_visible_height =
709 p_fmt_dst->i_height;
711 i_x_offset = __MAX( i_x_offset, 0 );
712 i_y_offset = __MAX( i_y_offset, 0 );
714 p_sys->p_blend->pf_video_blend( p_sys->p_blend, p_pic_dst,
715 p_pic_src, p_pic_dst, i_x_offset, i_y_offset,
716 p_sys->i_alpha );
718 return VLC_SUCCESS;
720 return VLC_EGENERIC;
723 static int InvertAlpha( intf_thread_t *p_intf, picture_t **p_pic, video_format_t fmt )
725 uint8_t *p_begin = NULL, *p_end = NULL;
726 uint8_t i_skip = 0;
728 if( *p_pic && ((*p_pic)->i_planes != 1) )
730 msg_Err( p_intf,
731 "cannot invert alpha channel too many planes %d (only 1 supported)",
732 (*p_pic)->i_planes );
733 return VLC_EGENERIC;
736 switch( fmt.i_chroma )
738 case VLC_CODEC_RGB24:
739 p_begin = (uint8_t *)(*p_pic)->p[Y_PLANE].p_pixels;
740 p_end = (uint8_t *)(*p_pic)->p[Y_PLANE].p_pixels +
741 ( fmt.i_height * (*p_pic)->p[Y_PLANE].i_pitch );
742 i_skip = 3;
743 break;
744 case VLC_CODEC_RGB32:
745 p_begin = (uint8_t *)(*p_pic)->p[Y_PLANE].p_pixels;
746 p_end = (uint8_t *)(*p_pic)->p[Y_PLANE].p_pixels +
747 ( fmt.i_height * (*p_pic)->p[Y_PLANE].i_pitch );
748 i_skip = 4;
749 break;
750 default:
751 msg_Err( p_intf, "cannot invert alpha channel chroma not supported %4.4s",
752 (char *)&fmt.i_chroma );
753 return VLC_EGENERIC;
756 for( ; p_begin < p_end; p_begin += i_skip )
758 uint8_t i_opacity = 0;
760 if( *p_begin != 0xFF )
761 i_opacity = 255 - *p_begin;
762 *p_begin = i_opacity;
764 /* end of kludge */
765 return VLC_SUCCESS;
767 #endif
769 /*****************************************************************************
770 * RenderPicture: Render the picture into the p_dest buffer.
771 * We don't take transparent pixels into account, so we don't have to blend
772 * the two images together.
773 *****************************************************************************/
774 static int RenderPicture( intf_thread_t *p_intf, int i_x_offset, int i_y_offset,
775 picture_t *p_src, picture_t *p_dest )
777 int i;
778 VLC_UNUSED( p_intf );
780 if( !p_dest && !p_src ) return VLC_EGENERIC;
782 for( i = 0; i < p_src->i_planes ; i++ )
784 if( p_src->p[i].i_pitch == p_dest->p[i].i_pitch )
786 /* There are margins, but with the same width : perfect ! */
787 vlc_memcpy( p_dest->p[i].p_pixels, p_src->p[i].p_pixels,
788 p_src->p[i].i_pitch * p_src->p[i].i_visible_lines );
790 else
792 /* We need to proceed line by line */
793 uint8_t *p_in = p_src->p[i].p_pixels;
794 uint8_t *p_out = p_dest->p[i].p_pixels;
796 int i_x = i_x_offset * p_src->p[i].i_pixel_pitch;
797 int i_x_clip, i_y_clip;
799 /* Check boundaries, clip the image if necessary */
800 i_x_clip = ( i_x + p_src->p[i].i_visible_pitch ) - p_dest->p[i].i_visible_pitch;
801 i_x_clip = ( i_x_clip > 0 ) ? i_x_clip : 0;
803 i_y_clip = ( i_y_offset + p_src->p[i].i_visible_lines ) - p_dest->p[i].i_visible_lines;
804 i_y_clip = ( i_y_clip > 0 ) ? i_y_clip : 0;
805 #if defined(FBOSD_DEBUG)
806 msg_Dbg( p_intf, "i_pitch (%d,%d), (%d,%d)/(%d,%d)",
807 p_dest->p[i].i_visible_pitch, p_src->p[i].i_visible_pitch,
808 i_x_offset, i_y_offset, i_x, i_x_clip );
809 #endif
810 if( ( i_y_offset <= p_dest->p[i].i_visible_lines ) &&
811 ( i_x <= p_dest->p[i].i_visible_pitch ) )
813 int i_line;
815 p_out += ( i_y_offset * p_dest->p[i].i_pitch );
816 for( i_line = 0; i_line < ( p_src->p[i].i_visible_lines - i_y_clip ); i_line++ )
818 vlc_memcpy( p_out + i_x, p_in,
819 p_src->p[i].i_visible_pitch - i_x_clip );
820 p_in += p_src->p[i].i_pitch;
821 p_out += p_dest->p[i].i_pitch;
826 return VLC_SUCCESS;
829 /*****************************************************************************
830 * RenderText - Render text to the desired picture format
831 *****************************************************************************/
832 static picture_t *RenderText( intf_thread_t *p_intf, const char *psz_string,
833 text_style_t *p_style, video_format_t *p_fmt )
835 intf_sys_t *p_sys = p_intf->p_sys;
836 subpicture_region_t *p_region;
837 picture_t *p_dest = NULL;
839 if( !psz_string ) return p_dest;
841 if( p_sys->p_text && p_sys->p_text->p_module )
843 video_format_t fmt;
845 memset( &fmt, 0, sizeof(fmt) );
846 fmt.i_chroma = VLC_CODEC_TEXT;
847 fmt.i_width = fmt.i_visible_width = 0;
848 fmt.i_height = fmt.i_visible_height = 0;
849 fmt.i_x_offset = 0;
850 fmt.i_y_offset = 0;
852 p_region = subpicture_region_New( &fmt );
853 if( !p_region )
854 return p_dest;
856 p_region->psz_text = strdup( psz_string );
857 if( !p_region->psz_text )
859 subpicture_region_Delete( p_region );
860 return NULL;
862 p_region->p_style = text_style_Duplicate( p_style );
863 p_region->i_align = SUBPICTURE_ALIGN_LEFT | SUBPICTURE_ALIGN_TOP;
865 if( p_sys->p_text->pf_render_text )
867 video_format_t fmt_out;
869 memset( &fmt_out, 0, sizeof(video_format_t) );
871 p_sys->p_text->pf_render_text( p_sys->p_text,
872 p_region, p_region, NULL );
874 #if defined(FBOSD_BLENDING)
875 fmt_out = p_region->fmt;
876 fmt_out.i_bits_per_pixel = 32;
877 vlc_memcpy( p_fmt, &fmt_out, sizeof(video_format_t) );
879 /* FIXME not needed to copy the picture anymore no ? */
880 p_dest = AllocatePicture( VLC_OBJECT(p_intf), &fmt_out );
881 if( !p_dest )
883 subpicture_region_Delete( p_region );
884 return NULL;
886 picture_Copy( p_dest, p_region->p_picture );
887 #else
888 fmt_out.i_chroma = p_fmt->i_chroma;
889 p_dest = ConvertImage( p_intf, p_region->p_picture,
890 &p_region->fmt, &fmt_out );
891 #endif
892 subpicture_region_Delete( p_region );
893 return p_dest;
895 subpicture_region_Delete( p_region );
897 return p_dest;
900 /*****************************************************************************
901 * LoadImage: Load an image from file into a picture buffer.
902 *****************************************************************************/
903 static picture_t *LoadImage( intf_thread_t *p_intf, video_format_t *p_fmt,
904 char *psz_file )
906 picture_t *p_pic = NULL;
908 if( psz_file && p_intf->p_sys->p_image )
910 video_format_t fmt_in, fmt_out;
912 memset( &fmt_in, 0, sizeof(fmt_in) );
913 memset( &fmt_out, 0, sizeof(fmt_out) );
915 fmt_out.i_chroma = p_fmt->i_chroma;
916 p_pic = image_ReadUrl( p_intf->p_sys->p_image, psz_file,
917 &fmt_in, &fmt_out );
919 msg_Dbg( p_intf, "image size %dx%d chroma %4.4s",
920 fmt_out.i_width, fmt_out.i_height,
921 (char *)&p_fmt->i_chroma );
923 return p_pic;
926 #if ! defined(FBOSD_BLENDING)
927 /*****************************************************************************
928 * Convertmage: Convert image to another fourcc
929 *****************************************************************************/
930 static picture_t *ConvertImage( intf_thread_t *p_intf, picture_t *p_pic,
931 video_format_t *p_fmt_in, video_format_t *p_fmt_out )
933 intf_sys_t *p_sys = p_intf->p_sys;
934 picture_t *p_old = NULL;
936 if( p_sys->p_image )
938 p_old = image_Convert( p_sys->p_image, p_pic, p_fmt_in, p_fmt_out );
940 msg_Dbg( p_intf, "converted image size %dx%d chroma %4.4s",
941 p_fmt_out->i_width, p_fmt_out->i_height,
942 (char *)&p_fmt_out->i_chroma );
944 return p_old;
946 #endif
948 /*****************************************************************************
949 * Init: initialize framebuffer video thread output method
950 *****************************************************************************/
951 static int Init( intf_thread_t *p_intf )
953 intf_sys_t *p_sys = p_intf->p_sys;
955 /* Initialize the output structure: RGB with square pixels, whatever
956 * the input format is, since it's the only format we know */
957 switch( p_sys->var_info.bits_per_pixel )
959 case 8: /* FIXME: set the palette */
960 p_sys->fmt_out.i_chroma = VLC_CODEC_RGB8; break;
961 case 15:
962 p_sys->fmt_out.i_chroma = VLC_CODEC_RGB15; break;
963 case 16:
964 p_sys->fmt_out.i_chroma = VLC_CODEC_RGB16; break;
965 case 24:
966 p_sys->fmt_out.i_chroma = VLC_CODEC_RGB24; break;
967 case 32:
968 p_sys->fmt_out.i_chroma = VLC_CODEC_RGB32; break;
969 default:
970 msg_Err( p_intf, "unknown screen depth %i",
971 p_sys->var_info.bits_per_pixel );
972 return VLC_EGENERIC;
975 p_sys->fmt_out.i_bits_per_pixel = p_sys->var_info.bits_per_pixel;
976 p_sys->fmt_out.i_width = p_sys->i_width;
977 p_sys->fmt_out.i_height = p_sys->i_height;
979 /* Assume we have square pixels */
980 if( p_sys->i_aspect < 0 )
982 p_sys->fmt_out.i_sar_num = 1;
983 p_sys->fmt_out.i_sar_den = 1;
985 else
987 p_sys->fmt_out.i_sar_num = p_sys->i_aspect * p_sys->i_height;
988 p_sys->fmt_out.i_sar_den = VOUT_ASPECT_FACTOR * p_sys->i_width;
991 /* Allocate overlay buffer */
992 p_sys->p_overlay = AllocatePicture( &p_sys->fmt_out );
993 if( !p_sys->p_overlay ) return VLC_EGENERIC;
995 SetOverlayTransparency( p_intf, true );
997 /* We know the chroma, allocate a buffer which will be used
998 * to write to the overlay framebuffer */
999 p_sys->p_overlay->p->i_pixel_pitch = p_sys->i_bytes_per_pixel;
1000 p_sys->p_overlay->p->i_lines = p_sys->var_info.yres;
1001 p_sys->p_overlay->p->i_visible_lines = p_sys->var_info.yres;
1003 if( p_sys->var_info.xres_virtual )
1005 p_sys->p_overlay->p->i_pitch = p_sys->var_info.xres_virtual
1006 * p_sys->i_bytes_per_pixel;
1008 else
1010 p_sys->p_overlay->p->i_pitch = p_sys->var_info.xres
1011 * p_sys->i_bytes_per_pixel;
1014 p_sys->p_overlay->p->i_visible_pitch = p_sys->var_info.xres
1015 * p_sys->i_bytes_per_pixel;
1017 p_sys->p_overlay->i_planes = 1;
1019 return VLC_SUCCESS;
1022 /*****************************************************************************
1023 * End: terminate framebuffer interface
1024 *****************************************************************************/
1025 static void End( intf_thread_t *p_intf )
1027 intf_sys_t *p_sys = p_intf->p_sys;
1029 /* CleanUp */
1030 SetOverlayTransparency( p_intf, false );
1031 if( p_sys->p_overlay )
1033 int ret;
1034 ret = write( p_sys->i_fd, p_sys->p_overlay->p[0].p_pixels,
1035 p_sys->i_page_size );
1036 if( ret < 0 )
1037 msg_Err( p_intf, "unable to clear overlay" );
1040 DeAllocatePicture( p_intf->p_sys->p_overlay,
1041 &p_intf->p_sys->fmt_out );
1042 p_intf->p_sys->p_overlay = NULL;
1045 /*****************************************************************************
1046 * OpenDisplay: initialize framebuffer
1047 *****************************************************************************/
1048 static int OpenDisplay( intf_thread_t *p_intf )
1050 intf_sys_t *p_sys = p_intf->p_sys;
1051 char *psz_device; /* framebuffer device path */
1052 struct fb_fix_screeninfo fix_info; /* framebuffer fix information */
1054 /* Open framebuffer device */
1055 if( !(psz_device = var_InheritString( p_intf, "fbosd-dev" )) )
1057 msg_Err( p_intf, "don't know which fb osd/overlay device to open" );
1058 return VLC_EGENERIC;
1061 p_sys->i_fd = vlc_open( psz_device, O_RDWR );
1062 if( p_sys->i_fd == -1 )
1064 msg_Err( p_intf, "cannot open %s (%m)", psz_device );
1065 free( psz_device );
1066 return VLC_EGENERIC;
1068 free( psz_device );
1070 /* Get framebuffer device information */
1071 if( ioctl( p_sys->i_fd, FBIOGET_VSCREENINFO, &p_sys->var_info ) )
1073 msg_Err( p_intf, "cannot get fb info (%m)" );
1074 close( p_sys->i_fd );
1075 return VLC_EGENERIC;
1078 /* Get some info on the framebuffer itself */
1079 if( ioctl( p_sys->i_fd, FBIOGET_FSCREENINFO, &fix_info ) == 0 )
1081 p_sys->i_width = p_sys->fmt_out.i_width = p_sys->var_info.xres;
1082 p_sys->i_height = p_sys->fmt_out.i_height = p_sys->var_info.yres;
1085 /* FIXME: if the image is full-size, it gets cropped on the left
1086 * because of the xres / xres_virtual slight difference */
1087 msg_Dbg( p_intf, "%ix%i (virtual %ix%i)",
1088 p_sys->var_info.xres, p_sys->var_info.yres,
1089 p_sys->var_info.xres_virtual,
1090 p_sys->var_info.yres_virtual );
1092 p_sys->fmt_out.i_width = p_sys->i_width;
1093 p_sys->fmt_out.i_height = p_sys->i_height;
1095 p_sys->p_palette = NULL;
1096 p_sys->b_pan = ( fix_info.ypanstep || fix_info.ywrapstep );
1098 switch( p_sys->var_info.bits_per_pixel )
1100 case 8:
1101 p_sys->p_palette = malloc( 8 * 256 * sizeof( uint16_t ) );
1102 if( !p_sys->p_palette )
1104 close( p_sys->i_fd );
1105 return VLC_ENOMEM;
1107 p_sys->fb_cmap.start = 0;
1108 p_sys->fb_cmap.len = 256;
1109 p_sys->fb_cmap.red = p_sys->p_palette;
1110 p_sys->fb_cmap.green = p_sys->p_palette + 256 * sizeof( uint16_t );
1111 p_sys->fb_cmap.blue = p_sys->p_palette + 2 * 256 * sizeof( uint16_t );
1112 p_sys->fb_cmap.transp = p_sys->p_palette + 3 * 256 * sizeof( uint16_t );
1114 /* Save the colormap */
1115 ioctl( p_sys->i_fd, FBIOGETCMAP, &p_sys->fb_cmap );
1117 p_sys->i_bytes_per_pixel = 1;
1118 break;
1120 case 15:
1121 case 16:
1122 p_sys->i_bytes_per_pixel = 2;
1123 break;
1125 case 24:
1126 p_sys->i_bytes_per_pixel = 3;
1127 break;
1129 case 32:
1130 p_sys->i_bytes_per_pixel = 4;
1131 break;
1133 default:
1134 msg_Err( p_intf, "screen depth %d is not supported",
1135 p_sys->var_info.bits_per_pixel );
1137 close( p_sys->i_fd );
1138 return VLC_EGENERIC;
1141 p_sys->i_page_size = p_sys->i_width * p_sys->i_height
1142 * p_sys->i_bytes_per_pixel;
1144 msg_Dbg( p_intf, "framebuffer type=%d, visual=%d, ypanstep=%d, "
1145 "ywrap=%d, accel=%d", fix_info.type, fix_info.visual,
1146 fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel );
1147 return VLC_SUCCESS;
1150 /*****************************************************************************
1151 * CloseDisplay: terminate FB interface thread
1152 *****************************************************************************/
1153 static void CloseDisplay( intf_thread_t *p_intf )
1155 intf_sys_t *p_sys = p_intf->p_sys;
1157 /* Restore palette */
1158 if( p_sys->var_info.bits_per_pixel == 8 )
1160 ioctl( p_sys->i_fd, FBIOPUTCMAP, &p_sys->fb_cmap );
1161 free( p_sys->p_palette );
1162 p_sys->p_palette = NULL;
1165 /* Close fb */
1166 close( p_sys->i_fd );
1169 static void Render( intf_thread_t *p_intf, struct fbosd_render_t *render )
1171 intf_sys_t *p_sys = p_intf->p_sys;
1173 if( render->i_state != FBOSD_STATE_RENDER ) return;
1174 if( !render->psz_string ) return;
1176 if( render->i_type == FBOSD_RENDER_IMAGE )
1178 picture_t *p_pic;
1179 p_pic = LoadImage( p_intf, &p_sys->fmt_out, render->psz_string );
1180 if( p_pic )
1182 RenderPicture( p_intf, render->i_x, render->i_y,
1183 p_pic, p_sys->p_overlay );
1184 picture_Release( p_pic );
1187 else if( render->i_type == FBOSD_RENDER_TEXT )
1189 picture_t *p_text;
1190 #if defined(FBOSD_BLENDING)
1191 video_format_t fmt_in;
1192 memset( &fmt_in, 0, sizeof(video_format_t) );
1193 p_text = RenderText( p_intf, render->psz_string, render->p_text_style,
1194 &fmt_in );
1195 if( p_text )
1197 BlendPicture( p_intf, &fmt_in, &p_sys->fmt_out,
1198 p_text, p_sys->p_overlay );
1199 msg_Dbg( p_intf, "releasing picture" );
1200 DeAllocatePicture( p_text, &fmt_in );
1202 #else
1203 p_text = RenderText( p_intf, render->psz_string, render->p_text_style,
1204 &p_sys->fmt_out );
1205 if( p_text )
1207 RenderPicture( p_intf, render->i_x, render->i_y,
1208 p_text, p_sys->p_overlay );
1209 picture_Release( p_text );
1211 #endif
1215 static void RenderClear( intf_thread_t *p_intf, struct fbosd_render_t *render )
1217 intf_sys_t *p_sys = p_intf->p_sys;
1219 text_style_Delete( render->p_text_style );
1220 render->p_text_style = text_style_New();
1221 free( render->psz_string );
1222 render->psz_string = NULL;
1224 render->i_x = p_sys->i_x;
1225 render->i_y = p_sys->i_y;
1226 render->i_pos = p_sys->i_pos;
1227 render->i_alpha = p_sys->i_alpha;
1228 render->b_absolute = p_sys->b_absolute;
1229 render->i_state = FBOSD_STATE_FREE;
1232 static bool isRendererReady( intf_thread_t *p_intf )
1234 intf_sys_t *p_sys = p_intf->p_sys;
1235 int i;
1237 /* Check if there are more items to render */
1238 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
1240 if( p_sys->render[i].i_state == FBOSD_STATE_RESERVED )
1241 return false;
1243 return true;
1246 /*****************************************************************************
1247 * Run: thread
1248 *****************************************************************************
1249 * This part of the interface is in a separate thread so that we can call
1250 * exec() from within it without annoying the rest of the program.
1251 *****************************************************************************/
1252 static void Run( intf_thread_t *p_intf )
1254 intf_sys_t *p_sys = p_intf->p_sys;
1255 int canc = vlc_savecancel();
1257 while( vlc_object_alive( p_intf ) )
1259 int i;
1261 /* Is there somthing to render? */
1262 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
1264 if( p_sys->render[i].i_state == FBOSD_STATE_RENDER )
1266 Render( p_intf, &p_sys->render[i] );
1267 RenderClear( p_intf, &p_sys->render[i] );
1271 if( p_sys->b_clear )
1273 SetOverlayTransparency( p_intf, true );
1275 var_SetString( p_intf, "fbosd-image", "" );
1276 var_SetString( p_intf, "fbosd-text", "" );
1278 p_sys->b_clear = false;
1279 p_sys->b_need_update = true;
1282 if( p_sys->b_need_update && p_sys->p_overlay &&
1283 isRendererReady( p_intf ) )
1285 int ret;
1286 #if defined(FBOSD_BLENDING)
1287 /* Reverse alpha channel to work around FPGA bug */
1288 InvertAlpha( p_intf, &p_sys->p_overlay, p_sys->fmt_out );
1289 #endif
1290 ret = write( p_sys->i_fd, p_sys->p_overlay->p[0].p_pixels,
1291 p_sys->i_page_size );
1292 if( ret < 0 )
1293 msg_Err( p_intf, "unable to write to overlay" );
1294 lseek( p_sys->i_fd, 0, SEEK_SET );
1296 /* clear the picture */
1297 memset( p_sys->p_overlay->p[0].p_pixels, 0xFF, p_sys->i_page_size );
1298 p_sys->b_need_update = false;
1301 msleep( INTF_IDLE_SLEEP );
1304 End( p_intf );
1305 vlc_restorecancel( canc );
1308 static int OverlayCallback( vlc_object_t *p_this, char const *psz_cmd,
1309 vlc_value_t oldval, vlc_value_t newval, void *p_data )
1311 intf_thread_t *p_intf = (intf_thread_t *) p_this;
1312 intf_sys_t *p_sys = p_intf->p_sys;
1313 VLC_UNUSED(oldval); VLC_UNUSED(p_data);
1315 if( !strncmp( psz_cmd, "fbosd-display", 13 ) )
1317 p_sys->b_need_update = true;
1319 else if( !strncmp( psz_cmd, "fbosd-clear", 11 ) )
1321 int i;
1322 /* Clear the entire render list */
1323 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
1325 RenderClear( p_intf, &p_sys->render[i] );
1327 p_sys->b_clear = true;
1329 else if( !strncmp( psz_cmd, "fbosd-render", 12 ) )
1331 int i;
1332 /* Are we already busy with on slot ? */
1333 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
1335 if( p_sys->render[i].i_state == FBOSD_STATE_RESERVED )
1337 p_sys->render[i].i_state = FBOSD_STATE_RENDER;
1338 break;
1342 else
1344 int i;
1345 /* Are we already busy with on slot ? */
1346 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
1348 if( p_sys->render[i].i_state == FBOSD_STATE_RESERVED )
1349 break;
1351 /* No, then find first FREE slot */
1352 if( i == FBOSD_RENDER_MAX )
1354 for( i = 0; i < FBOSD_RENDER_MAX; i++ )
1356 if( p_sys->render[i].i_state == FBOSD_STATE_FREE )
1357 break;
1359 if( i == FBOSD_RENDER_MAX )
1361 msg_Warn( p_this, "render space depleated" );
1362 return VLC_SUCCESS;
1365 /* Found a free slot */
1366 p_sys->render[i].i_state = FBOSD_STATE_RESERVED;
1367 if( !strncmp( psz_cmd, "fbosd-image", 11 ) )
1369 free( p_sys->render[i].psz_string );
1370 p_sys->render[i].psz_string = strdup( newval.psz_string );
1371 p_sys->render[i].i_type = FBOSD_RENDER_IMAGE;
1373 else if( !strncmp( psz_cmd, "fbosd-text", 10 ) )
1375 free( p_sys->render[i].psz_string );
1376 p_sys->render[i].psz_string = strdup( newval.psz_string );
1377 p_sys->render[i].i_type = FBOSD_RENDER_TEXT;
1379 else if( !strncmp( psz_cmd, "fbosd-x", 7 ) )
1381 p_sys->render[i].b_absolute = false;
1382 p_sys->render[i].i_x = (newval.i_int < p_sys->i_width) ?
1383 newval.i_int : p_sys->i_width;
1385 else if( !strncmp( psz_cmd, "fbosd-y", 7 ) )
1387 p_sys->render[i].b_absolute = false;
1388 p_sys->render[i].i_y = (newval.i_int < p_sys->i_height) ?
1389 newval.i_int : p_sys->i_height;
1391 else if( !strncmp( psz_cmd, "fbosd-position", 14 ) )
1393 p_sys->render[i].b_absolute = true;
1394 p_sys->render[i].i_pos = newval.i_int;
1396 else if( !strncmp( psz_cmd, "fbosd-font-size", 15 ) )
1398 p_sys->render[i].p_text_style->i_font_size = newval.i_int;
1400 else if( !strncmp( psz_cmd, "fbosd-font-color", 16 ) )
1402 p_sys->render[i].p_text_style->i_font_color = newval.i_int;
1404 else if( !strncmp( psz_cmd, "fbosd-font-opacity", 18 ) )
1406 p_sys->render[i].p_text_style->i_font_alpha = 255 - newval.i_int;
1408 else if( !strncmp( psz_cmd, "fbosd-alpha", 11 ) )
1410 p_sys->render[i].i_alpha = newval.i_int;
1413 return VLC_SUCCESS;