1 /*****************************************************************************
2 * osd_widgets.c : OSD widgets manipulation functions
3 *****************************************************************************
4 * Copyright (C) 2004-2005 the VideoLAN team
7 * Author: Yoann Peronneau <yoann@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> /* free() */
31 #include <vlc_video.h>
32 #include <vlc_filter.h>
35 #define STYLE_FILLED 1
37 /*****************************************************************************
39 *****************************************************************************/
40 static void DrawRect( subpicture_t
*, int, int, int, int, short );
41 static void DrawTriangle( subpicture_t
*, int, int, int, int, short );
42 static int CreatePicture( spu_t
*, subpicture_t
*, int, int, int, int );
43 static subpicture_t
*osd_CreateWidget( spu_t
*, int );
45 /*****************************************************************************
46 * Draws a rectangle at the given position in the subpic.
47 * It may be filled (fill == STYLE_FILLED) or empty (fill == STYLE_EMPTY).
48 *****************************************************************************/
49 static void DrawRect( subpicture_t
*p_subpic
, int i_x1
, int i_y1
,
50 int i_x2
, int i_y2
, short fill
)
53 uint8_t *p_a
= p_subpic
->p_region
->picture
.A_PIXELS
;
54 int i_pitch
= p_subpic
->p_region
->picture
.Y_PITCH
;
56 if( fill
== STYLE_FILLED
)
58 for( y
= i_y1
; y
<= i_y2
; y
++ )
60 for( x
= i_x1
; x
<= i_x2
; x
++ )
62 p_a
[ x
+ i_pitch
* y
] = 0xff;
68 for( y
= i_y1
; y
<= i_y2
; y
++ )
70 p_a
[ i_x1
+ i_pitch
* y
] = 0xff;
71 p_a
[ i_x2
+ i_pitch
* y
] = 0xff;
73 for( x
= i_x1
; x
<= i_x2
; x
++ )
75 p_a
[ x
+ i_pitch
* i_y1
] = 0xff;
76 p_a
[ x
+ i_pitch
* i_y2
] = 0xff;
81 /*****************************************************************************
82 * Draws a triangle at the given position in the subpic.
83 * It may be filled (fill == STYLE_FILLED) or empty (fill == STYLE_EMPTY).
84 *****************************************************************************/
85 static void DrawTriangle( subpicture_t
*p_subpic
, int i_x1
, int i_y1
,
86 int i_x2
, int i_y2
, short fill
)
89 uint8_t *p_a
= p_subpic
->p_region
->picture
.A_PIXELS
;
90 int i_pitch
= p_subpic
->p_region
->picture
.Y_PITCH
;
92 i_mid
= i_y1
+ ( ( i_y2
- i_y1
) >> 1 );
96 if( fill
== STYLE_FILLED
)
98 for( y
= i_y1
; y
<= i_mid
; y
++ )
101 for( x
= i_x1
; x
<= i_x1
+ h
&& x
<= i_x2
; x
++ )
103 p_a
[ x
+ i_pitch
* y
] = 0xff;
104 p_a
[ x
+ i_pitch
* ( i_y2
- h
) ] = 0xff;
110 for( y
= i_y1
; y
<= i_mid
; y
++ )
113 p_a
[ i_x1
+ i_pitch
* y
] = 0xff;
114 p_a
[ i_x1
+ h
+ i_pitch
* y
] = 0xff;
115 p_a
[ i_x1
+ i_pitch
* ( i_y2
- h
) ] = 0xff;
116 p_a
[ i_x1
+ h
+ i_pitch
* ( i_y2
- h
) ] = 0xff;
122 if( fill
== STYLE_FILLED
)
124 for( y
= i_y1
; y
<= i_mid
; y
++ )
127 for( x
= i_x1
; x
>= i_x1
- h
&& x
>= i_x2
; x
-- )
129 p_a
[ x
+ i_pitch
* y
] = 0xff;
130 p_a
[ x
+ i_pitch
* ( i_y2
- h
) ] = 0xff;
136 for( y
= i_y1
; y
<= i_mid
; y
++ )
139 p_a
[ i_x1
+ i_pitch
* y
] = 0xff;
140 p_a
[ i_x1
- h
+ i_pitch
* y
] = 0xff;
141 p_a
[ i_x1
+ i_pitch
* ( i_y2
- h
) ] = 0xff;
142 p_a
[ i_x1
- h
+ i_pitch
* ( i_y2
- h
) ] = 0xff;
148 /*****************************************************************************
149 * Create Picture: creates subpicture region and picture
150 *****************************************************************************/
151 static int CreatePicture( spu_t
*p_spu
, subpicture_t
*p_subpic
,
152 int i_x
, int i_y
, int i_width
, int i_height
)
154 uint8_t *p_y
, *p_u
, *p_v
, *p_a
;
158 /* Create a new subpicture region */
159 memset( &fmt
, 0, sizeof(video_format_t
) );
160 fmt
.i_chroma
= VLC_FOURCC('Y','U','V','A');
162 fmt
.i_width
= fmt
.i_visible_width
= i_width
;
163 fmt
.i_height
= fmt
.i_visible_height
= i_height
;
164 fmt
.i_x_offset
= fmt
.i_y_offset
= 0;
165 p_subpic
->p_region
= p_subpic
->pf_create_region( VLC_OBJECT(p_spu
), &fmt
);
166 if( !p_subpic
->p_region
)
168 msg_Err( p_spu
, "cannot allocate SPU region" );
172 p_subpic
->p_region
->i_x
= i_x
;
173 p_subpic
->p_region
->i_y
= i_y
;
174 p_y
= p_subpic
->p_region
->picture
.Y_PIXELS
;
175 p_u
= p_subpic
->p_region
->picture
.U_PIXELS
;
176 p_v
= p_subpic
->p_region
->picture
.V_PIXELS
;
177 p_a
= p_subpic
->p_region
->picture
.A_PIXELS
;
178 i_pitch
= p_subpic
->p_region
->picture
.Y_PITCH
;
180 /* Initialize the region pixels (only the alpha will be changed later) */
181 memset( p_y
, 0xff, i_pitch
* p_subpic
->p_region
->fmt
.i_height
);
182 memset( p_u
, 0x80, i_pitch
* p_subpic
->p_region
->fmt
.i_height
);
183 memset( p_v
, 0x80, i_pitch
* p_subpic
->p_region
->fmt
.i_height
);
184 memset( p_a
, 0x00, i_pitch
* p_subpic
->p_region
->fmt
.i_height
);
189 /*****************************************************************************
190 * Creates and initializes an OSD widget.
191 *****************************************************************************/
192 subpicture_t
*osd_CreateWidget( spu_t
*p_spu
, int i_channel
)
194 subpicture_t
*p_subpic
;
195 mtime_t i_now
= mdate();
197 /* Create and initialize a subpicture */
198 p_subpic
= spu_CreateSubpicture( p_spu
);
199 if( p_subpic
== NULL
) return NULL
;
201 p_subpic
->i_channel
= i_channel
;
202 p_subpic
->i_start
= i_now
;
203 p_subpic
->i_stop
= i_now
+ 1200000;
204 p_subpic
->b_ephemer
= VLC_TRUE
;
205 p_subpic
->b_fade
= VLC_TRUE
;
210 /*****************************************************************************
211 * Displays an OSD slider.
212 * Types are: OSD_HOR_SLIDER and OSD_VERT_SLIDER.
213 *****************************************************************************/
214 int osd_Slider( vlc_object_t
*p_this
, spu_t
*p_spu
,
215 int i_render_width
, int i_render_height
,
216 int i_margin_left
, int i_margin_bottom
,
217 int i_channel
, int i_position
, short i_type
)
219 subpicture_t
*p_subpic
;
220 int i_x_margin
, i_y_margin
, i_x
, i_y
, i_width
, i_height
;
222 p_subpic
= osd_CreateWidget( p_spu
, i_channel
);
223 if( p_subpic
== NULL
)
228 i_y_margin
= i_render_height
/ 10;
229 i_x_margin
= i_y_margin
+ i_margin_left
;
230 i_y_margin
+= i_margin_bottom
;
232 if( i_type
== OSD_HOR_SLIDER
)
234 i_width
= i_render_width
- 2 * i_x_margin
;
235 i_height
= i_render_height
/ 20;
237 i_y
= i_render_height
- i_y_margin
- i_height
;
241 i_width
= i_render_width
/ 40;
242 i_height
= i_render_height
- 2 * i_y_margin
;
243 i_x
= i_render_width
- i_x_margin
- i_width
;
247 /* Create subpicture region and picture */
248 CreatePicture( p_spu
, p_subpic
, i_x
, i_y
, i_width
, i_height
);
250 if( i_type
== OSD_HOR_SLIDER
)
252 int i_x_pos
= ( i_width
- 2 ) * i_position
/ 100;
253 DrawRect( p_subpic
, i_x_pos
- 1, 2, i_x_pos
+ 1,
254 i_height
- 3, STYLE_FILLED
);
255 DrawRect( p_subpic
, 0, 0, i_width
- 1, i_height
- 1, STYLE_EMPTY
);
257 else if( i_type
== OSD_VERT_SLIDER
)
259 int i_y_pos
= i_height
/ 2;
260 DrawRect( p_subpic
, 2, i_height
- ( i_height
- 2 ) * i_position
/ 100,
261 i_width
- 3, i_height
- 3, STYLE_FILLED
);
262 DrawRect( p_subpic
, 1, i_y_pos
, 1, i_y_pos
, STYLE_FILLED
);
263 DrawRect( p_subpic
, i_width
- 2, i_y_pos
,
264 i_width
- 2, i_y_pos
, STYLE_FILLED
);
265 DrawRect( p_subpic
, 0, 0, i_width
- 1, i_height
- 1, STYLE_EMPTY
);
268 spu_DisplaySubpicture( p_spu
, p_subpic
);
273 /*****************************************************************************
274 * Displays an OSD icon.
275 * Types are: OSD_PLAY_ICON, OSD_PAUSE_ICON, OSD_SPEAKER_ICON, OSD_MUTE_ICON
276 *****************************************************************************/
277 int osd_Icon( vlc_object_t
*p_this
, spu_t
*p_spu
,
278 int i_render_width
, int i_render_height
, int i_margin_right
,
279 int i_margin_top
, int i_channel
, short i_type
)
281 subpicture_t
*p_subpic
;
282 int i_x_margin
, i_y_margin
, i_x
, i_y
, i_width
, i_height
;
284 p_subpic
= osd_CreateWidget( p_spu
, i_channel
);
285 if( p_subpic
== NULL
)
290 i_y_margin
= i_render_height
/ 15;
291 i_x_margin
= i_y_margin
+ i_margin_right
;
292 i_y_margin
+= i_margin_top
;
293 i_width
= i_render_width
/ 20;
295 i_x
= i_render_width
- i_x_margin
- i_width
;
298 /* Create subpicture region and picture */
299 CreatePicture( p_spu
, p_subpic
, i_x
, i_y
, i_width
, i_height
);
301 if( i_type
== OSD_PAUSE_ICON
)
303 int i_bar_width
= i_width
/ 3;
304 DrawRect( p_subpic
, 0, 0, i_bar_width
- 1, i_height
-1, STYLE_FILLED
);
305 DrawRect( p_subpic
, i_width
- i_bar_width
, 0,
306 i_width
- 1, i_height
- 1, STYLE_FILLED
);
308 else if( i_type
== OSD_PLAY_ICON
)
310 int i_mid
= i_height
>> 1;
311 int i_delta
= ( i_width
- i_mid
) >> 1;
312 int i_y2
= ( ( i_height
- 1 ) >> 1 ) * 2;
313 DrawTriangle( p_subpic
, i_delta
, 0, i_width
- i_delta
, i_y2
,
316 else if( i_type
== OSD_SPEAKER_ICON
|| i_type
== OSD_MUTE_ICON
)
318 int i_mid
= i_height
>> 1;
319 int i_delta
= ( i_width
- i_mid
) >> 1;
320 int i_y2
= ( ( i_height
- 1 ) >> 1 ) * 2;
321 DrawRect( p_subpic
, i_delta
, i_mid
/ 2, i_width
- i_delta
,
322 i_height
- 1 - i_mid
/ 2, STYLE_FILLED
);
323 DrawTriangle( p_subpic
, i_width
- i_delta
, 0, i_delta
, i_y2
,
325 if( i_type
== OSD_MUTE_ICON
)
327 uint8_t *p_a
= p_subpic
->p_region
->picture
.A_PIXELS
;
328 int i_pitch
= p_subpic
->p_region
->picture
.Y_PITCH
;
330 for( i
= 1; i
< i_pitch
; i
++ )
332 int k
= i
+ ( i_height
- i
- 1 ) * i_pitch
;
333 p_a
[ k
] = 0xff - p_a
[ k
];
338 spu_DisplaySubpicture( p_spu
, p_subpic
);