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_block.h>
30 #include <vlc_filter.h>
32 #include <vlc_events.h>
33 #include <vlc_input_item.h>
37 /* Layout percentage defines */
40 #define EPG_NAME_SIZE 0.05
41 #define EPG_PROGRAM_SIZE 0.03
43 #define NO_EPG N_( "No EPG found for this program." )
46 static subpicture_region_t
* vout_OSDEpgSlider( vout_thread_t
*p_vout
,
48 int i_width
, int i_height
,
52 subpicture_region_t
*p_region
;
54 /* Create a new subpicture region */
55 video_format_Init( &fmt
, VLC_CODEC_YUVA
);
56 fmt
.i_width
= fmt
.i_visible_width
= i_width
;
57 fmt
.i_height
= fmt
.i_visible_height
= i_height
;
61 p_region
= subpicture_region_New( &fmt
);
64 msg_Err( p_vout
, "Cannot allocate SPU region." );
71 picture_t
*p_picture
= p_region
->p_picture
;
73 f_ratio
= __MIN( __MAX( f_ratio
, 0 ), 1 );
74 int i_filled_part_width
= f_ratio
* i_width
;
76 for( int j
= 0; j
< i_height
; j
++ )
78 for( int i
= 0; i
< i_width
; i
++ )
80 #define WRITE_COMP( plane, value ) \
81 p_picture->p[plane].p_pixels[p_picture->p[plane].i_pitch * j + i] = value
83 /* Draw the slider. */
84 bool is_outline
= j
== 0 || j
== i_height
- 1
85 || i
== 0 || i
== i_width
- 1;
86 WRITE_COMP( 0, is_outline
? 0x00 : 0xff );
87 WRITE_COMP( 1, 0x80 );
88 WRITE_COMP( 2, 0x80 );
90 /* We can see the video through the part of the slider
91 which corresponds to the leaving time. */
92 bool is_border
= j
< 3 || j
> i_height
- 4
93 || i
< 3 || i
> i_width
- 4
94 || i
< i_filled_part_width
;
95 WRITE_COMP( 3, is_border
? 0xff : 0x00 );
105 static subpicture_region_t
* vout_OSDEpgText( vout_thread_t
*p_vout
,
106 const char *psz_string
,
108 int i_size
, uint32_t i_color
)
111 subpicture_region_t
*p_region
;
116 /* Create a new subpicture region */
117 video_format_Init( &fmt
, VLC_CODEC_TEXT
);
121 p_region
= subpicture_region_New( &fmt
);
124 msg_Err( p_vout
, "Cannot allocate SPU region." );
128 /* Set subpicture parameters */
129 p_region
->psz_text
= strdup( psz_string
);
130 p_region
->i_align
= 0;
135 p_region
->p_style
= text_style_New();
136 if( p_region
->p_style
)
138 p_region
->p_style
->i_font_size
= i_size
;
139 p_region
->p_style
->i_font_color
= i_color
;
140 p_region
->p_style
->i_font_alpha
= 0;
147 static subpicture_region_t
* vout_BuildOSDEpg( vout_thread_t
*p_vout
,
150 int i_visible_height
)
152 subpicture_region_t
*p_region_ret
;
153 subpicture_region_t
**pp_region
= &p_region_ret
;
155 time_t i_test
= time( NULL
);
157 /* Display the name of the channel. */
158 *pp_region
= vout_OSDEpgText( p_vout
,
160 i_visible_width
* EPG_LEFT
,
161 i_visible_height
* EPG_TOP
,
162 i_visible_height
* EPG_NAME_SIZE
,
168 /* Display the name of the current program. */
169 pp_region
= &(* pp_region
)->p_next
;
170 *pp_region
= vout_OSDEpgText( p_vout
, p_epg
->p_current
->psz_name
,
171 i_visible_width
* ( EPG_LEFT
+ 0.025 ),
172 i_visible_height
* ( EPG_TOP
+ 0.05 ),
173 i_visible_height
* EPG_PROGRAM_SIZE
,
179 /* Display the current program time slider. */
180 pp_region
= &(* pp_region
)->p_next
;
181 *pp_region
= vout_OSDEpgSlider( p_vout
,
182 i_visible_width
* EPG_LEFT
,
183 i_visible_height
* ( EPG_TOP
+ 0.1 ),
184 i_visible_width
* ( 1 - 2 * EPG_LEFT
),
185 i_visible_height
* 0.05,
186 ( i_test
- p_epg
->p_current
->i_start
)
187 / (float)p_epg
->p_current
->i_duration
);
192 /* Format the hours of the beginning and the end of the current program. */
193 struct tm tm_start
, tm_end
;
194 time_t t_start
= p_epg
->p_current
->i_start
;
195 time_t t_end
= p_epg
->p_current
->i_start
+ p_epg
->p_current
->i_duration
;
196 localtime_r( &t_start
, &tm_start
);
197 localtime_r( &t_end
, &tm_end
);
200 snprintf( psz_start
, sizeof(psz_start
), "%2.2d:%2.2d",
201 tm_start
.tm_hour
, tm_start
.tm_min
);
202 snprintf( psz_end
, sizeof(psz_end
), "%2.2d:%2.2d",
203 tm_end
.tm_hour
, tm_end
.tm_min
);
205 /* Display those hours. */
206 pp_region
= &(* pp_region
)->p_next
;
207 *pp_region
= vout_OSDEpgText( p_vout
, psz_start
,
208 i_visible_width
* ( EPG_LEFT
+ 0.02 ),
209 i_visible_height
* ( EPG_TOP
+ 0.15 ),
210 i_visible_height
* EPG_PROGRAM_SIZE
,
216 pp_region
= &(* pp_region
)->p_next
;
217 *pp_region
= vout_OSDEpgText( p_vout
, psz_end
,
218 i_visible_width
* ( 1 - EPG_LEFT
- 0.085 ),
219 i_visible_height
* ( EPG_TOP
+ 0.15 ),
220 i_visible_height
* EPG_PROGRAM_SIZE
,
228 * \brief Show EPG information about the current program of an input item
229 * \param p_vout pointer to the vout the information is to be showed on
230 * \param p_input pointer to the input item the information is to be showed
232 int vout_OSDEpg( vout_thread_t
*p_vout
, input_item_t
*p_input
)
235 mtime_t i_now
= mdate();
237 char *psz_now_playing
= input_item_GetNowPlaying( p_input
);
238 vlc_epg_t
*p_epg
= NULL
;
240 vlc_mutex_lock( &p_input
->lock
);
242 /* Look for the current program EPG event */
243 for( int i
= 0; i
< p_input
->i_epg
; i
++ )
245 vlc_epg_t
*p_tmp
= p_input
->pp_epg
[i
];
247 if( p_tmp
->p_current
&& p_tmp
->p_current
->psz_name
248 && psz_now_playing
!= NULL
249 && !strcmp( p_tmp
->p_current
->psz_name
, psz_now_playing
) )
251 p_epg
= vlc_epg_New( p_tmp
->psz_name
);
252 vlc_epg_Merge( p_epg
, p_tmp
);
257 vlc_mutex_unlock( &p_input
->lock
);
259 /* If no EPG event has been found. */
263 p_spu
= subpicture_New();
266 vlc_epg_Delete( p_epg
);
270 p_spu
->i_channel
= DEFAULT_CHAN
;
271 p_spu
->i_start
= i_now
;
272 p_spu
->i_stop
= i_now
+ 3000 * INT64_C(1000);
273 p_spu
->b_ephemer
= true;
274 p_spu
->b_absolute
= true;
275 p_spu
->b_fade
= true;
277 /* Build the EPG event subpictures. */
278 p_spu
->p_region
= vout_BuildOSDEpg( p_vout
, p_epg
,
279 p_vout
->fmt_in
.i_width
,
280 p_vout
->fmt_in
.i_height
);
282 vlc_epg_Delete( p_epg
);
283 spu_DisplaySubpicture( p_vout
->p_spu
, p_spu
);