1 /*****************************************************************************
2 * video_epg.c : EPG manipulation functions
3 *****************************************************************************
4 * Copyright (C) 2010 Adrien Maglo
6 * Author: Adrien Maglo <magsoft@videolan.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
27 #include <vlc_common.h>
29 #include <vlc_vout_osd.h>
30 #include <vlc_events.h>
31 #include <vlc_input_item.h>
34 /* Layout percentage defines */
37 #define EPG_NAME_SIZE 0.05
38 #define EPG_PROGRAM_SIZE 0.03
40 static subpicture_region_t
* vout_OSDEpgSlider( int i_x
, int i_y
,
41 int i_width
, int i_height
,
45 subpicture_region_t
*p_region
;
47 /* Create a new subpicture region */
48 video_format_Init( &fmt
, VLC_CODEC_YUVA
);
49 fmt
.i_width
= fmt
.i_visible_width
= i_width
;
50 fmt
.i_height
= fmt
.i_visible_height
= i_height
;
54 p_region
= subpicture_region_New( &fmt
);
61 picture_t
*p_picture
= p_region
->p_picture
;
63 f_ratio
= __MIN( __MAX( f_ratio
, 0 ), 1 );
64 int i_filled_part_width
= f_ratio
* i_width
;
66 for( int j
= 0; j
< i_height
; j
++ )
68 for( int i
= 0; i
< i_width
; i
++ )
70 #define WRITE_COMP( plane, value ) \
71 p_picture->p[plane].p_pixels[p_picture->p[plane].i_pitch * j + i] = value
73 /* Draw the slider. */
74 bool is_outline
= j
== 0 || j
== i_height
- 1
75 || i
== 0 || i
== i_width
- 1;
76 WRITE_COMP( 0, is_outline
? 0x00 : 0xff );
77 WRITE_COMP( 1, 0x80 );
78 WRITE_COMP( 2, 0x80 );
80 /* We can see the video through the part of the slider
81 which corresponds to the leaving time. */
82 bool is_border
= j
< 3 || j
> i_height
- 4
83 || i
< 3 || i
> i_width
- 4
84 || i
< i_filled_part_width
;
85 WRITE_COMP( 3, is_border
? 0xff : 0x00 );
95 static subpicture_region_t
* vout_OSDEpgText( const char *psz_string
,
97 int i_size
, uint32_t i_color
)
100 subpicture_region_t
*p_region
;
105 /* Create a new subpicture region */
106 video_format_Init( &fmt
, VLC_CODEC_TEXT
);
110 p_region
= subpicture_region_New( &fmt
);
114 /* Set subpicture parameters */
115 p_region
->psz_text
= strdup( psz_string
);
116 p_region
->i_align
= 0;
121 p_region
->p_style
= text_style_New();
122 if( p_region
->p_style
)
124 p_region
->p_style
->i_font_size
= i_size
;
125 p_region
->p_style
->i_font_color
= i_color
;
126 p_region
->p_style
->i_font_alpha
= 0;
133 static subpicture_region_t
* vout_BuildOSDEpg( vlc_epg_t
*p_epg
,
136 int i_visible_height
)
138 subpicture_region_t
*p_region_ret
;
139 subpicture_region_t
**pp_region
= &p_region_ret
;
141 time_t i_test
= time( NULL
);
143 /* Display the name of the channel. */
144 *pp_region
= vout_OSDEpgText( p_epg
->psz_name
,
145 i_x
+ i_visible_width
* EPG_LEFT
,
146 i_y
+ i_visible_height
* EPG_TOP
,
147 i_visible_height
* EPG_NAME_SIZE
,
153 /* Display the name of the current program. */
154 pp_region
= &(* pp_region
)->p_next
;
155 *pp_region
= vout_OSDEpgText( p_epg
->p_current
->psz_name
,
156 i_x
+ i_visible_width
* ( EPG_LEFT
+ 0.025 ),
157 i_y
+ i_visible_height
* ( EPG_TOP
+ 0.05 ),
158 i_visible_height
* EPG_PROGRAM_SIZE
,
164 /* Display the current program time slider. */
165 pp_region
= &(* pp_region
)->p_next
;
166 *pp_region
= vout_OSDEpgSlider( i_x
+ i_visible_width
* EPG_LEFT
,
167 i_y
+ i_visible_height
* ( EPG_TOP
+ 0.1 ),
168 i_visible_width
* ( 1 - 2 * EPG_LEFT
),
169 i_visible_height
* 0.05,
170 ( i_test
- p_epg
->p_current
->i_start
)
171 / (float)p_epg
->p_current
->i_duration
);
176 /* Format the hours of the beginning and the end of the current program. */
177 struct tm tm_start
, tm_end
;
178 time_t t_start
= p_epg
->p_current
->i_start
;
179 time_t t_end
= p_epg
->p_current
->i_start
+ p_epg
->p_current
->i_duration
;
180 localtime_r( &t_start
, &tm_start
);
181 localtime_r( &t_end
, &tm_end
);
184 snprintf( psz_start
, sizeof(psz_start
), "%2.2d:%2.2d",
185 tm_start
.tm_hour
, tm_start
.tm_min
);
186 snprintf( psz_end
, sizeof(psz_end
), "%2.2d:%2.2d",
187 tm_end
.tm_hour
, tm_end
.tm_min
);
189 /* Display those hours. */
190 pp_region
= &(* pp_region
)->p_next
;
191 *pp_region
= vout_OSDEpgText( psz_start
,
192 i_x
+ i_visible_width
* ( EPG_LEFT
+ 0.02 ),
193 i_y
+ i_visible_height
* ( EPG_TOP
+ 0.15 ),
194 i_visible_height
* EPG_PROGRAM_SIZE
,
200 pp_region
= &(* pp_region
)->p_next
;
201 *pp_region
= vout_OSDEpgText( psz_end
,
202 i_x
+ i_visible_width
* ( 1 - EPG_LEFT
- 0.085 ),
203 i_y
+ i_visible_height
* ( EPG_TOP
+ 0.15 ),
204 i_visible_height
* EPG_PROGRAM_SIZE
,
210 struct subpicture_updater_sys_t
215 static int OSDEpgValidate( subpicture_t
*p_subpic
,
216 bool has_src_changed
, const video_format_t
*p_fmt_src
,
217 bool has_dst_changed
, const video_format_t
*p_fmt_dst
,
220 VLC_UNUSED(p_subpic
); VLC_UNUSED(i_ts
); VLC_UNUSED(p_fmt_src
);
221 VLC_UNUSED(has_dst_changed
); VLC_UNUSED(p_fmt_dst
);
223 if( !has_src_changed
&& !has_dst_changed
)
228 static void OSDEpgUpdate( subpicture_t
*p_subpic
,
229 const video_format_t
*p_fmt_src
,
230 const video_format_t
*p_fmt_dst
,
233 subpicture_updater_sys_t
*p_sys
= p_subpic
->updater
.p_sys
;
234 VLC_UNUSED(p_fmt_dst
); VLC_UNUSED(i_ts
);
236 p_subpic
->i_original_picture_width
= p_fmt_src
->i_width
;
237 p_subpic
->i_original_picture_height
= p_fmt_src
->i_height
;
238 p_subpic
->p_region
= vout_BuildOSDEpg( p_sys
->p_epg
,
239 p_fmt_src
->i_x_offset
,
240 p_fmt_src
->i_y_offset
,
241 p_fmt_src
->i_visible_width
,
242 p_fmt_src
->i_visible_height
);
245 static void OSDEpgDestroy( subpicture_t
*p_subpic
)
247 subpicture_updater_sys_t
*p_sys
= p_subpic
->updater
.p_sys
;
249 vlc_epg_Delete( p_sys
->p_epg
);
254 * \brief Show EPG information about the current program of an input item
255 * \param p_vout pointer to the vout the information is to be showed on
256 * \param p_input pointer to the input item the information is to be showed
258 int vout_OSDEpg( vout_thread_t
*p_vout
, input_item_t
*p_input
)
261 mtime_t i_now
= mdate();
263 char *psz_now_playing
= input_item_GetNowPlaying( p_input
);
264 vlc_epg_t
*p_epg
= NULL
;
266 vlc_mutex_lock( &p_input
->lock
);
268 /* Look for the current program EPG event */
269 for( int i
= 0; i
< p_input
->i_epg
; i
++ )
271 vlc_epg_t
*p_tmp
= p_input
->pp_epg
[i
];
273 if( p_tmp
->p_current
&& p_tmp
->p_current
->psz_name
274 && psz_now_playing
!= NULL
275 && !strcmp( p_tmp
->p_current
->psz_name
, psz_now_playing
) )
277 p_epg
= vlc_epg_New( p_tmp
->psz_name
);
278 vlc_epg_Merge( p_epg
, p_tmp
);
283 vlc_mutex_unlock( &p_input
->lock
);
285 /* If no EPG event has been found. */
289 subpicture_updater_sys_t
*p_sys
= malloc( sizeof( *p_sys
) );
292 vlc_epg_Delete( p_epg
);
295 p_sys
->p_epg
= p_epg
;
296 subpicture_updater_t updater
= {
297 .pf_validate
= OSDEpgValidate
,
298 .pf_update
= OSDEpgUpdate
,
299 .pf_destroy
= OSDEpgDestroy
,
303 p_spu
= subpicture_New( &updater
);
306 vlc_epg_Delete( p_sys
->p_epg
);
311 p_spu
->i_channel
= SPU_DEFAULT_CHANNEL
;
312 p_spu
->i_start
= i_now
;
313 p_spu
->i_stop
= i_now
+ 3000 * INT64_C(1000);
314 p_spu
->b_ephemer
= true;
315 p_spu
->b_absolute
= true;
316 p_spu
->b_fade
= true;
318 vout_PutSubpicture( p_vout
, p_spu
);