/** * \brief Show EPG information about the current program of an input item * \param vout pointer to the vout the information is to be showed on * \param p_input pointer to the input item the information is to be showed */ int vout_OSDEpg(vout_thread_t *vout, input_item_t *input) { char *now_playing = input_item_GetNowPlaying(input); vlc_epg_t *epg = NULL; vlc_mutex_lock(&input->lock); /* Look for the current program EPG event */ for (int i = 0; i < input->i_epg; i++) { vlc_epg_t *tmp = input->pp_epg[i]; if (tmp->p_current && tmp->p_current->psz_name && now_playing != NULL && !strcmp(tmp->p_current->psz_name, now_playing)) { epg = vlc_epg_New(tmp->psz_name); vlc_epg_Merge(epg, tmp); break; } } vlc_mutex_unlock(&input->lock); /* If no EPG event has been found. */ if (epg == NULL) return VLC_EGENERIC; subpicture_updater_sys_t *sys = (subpicture_updater_sys_t *)malloc(sizeof(*sys)); // sunqueen modify if (!sys) { vlc_epg_Delete(epg); return VLC_EGENERIC; } sys->epg = epg; subpicture_updater_t updater = { // sunqueen modify start /*.pf_validate =*/ OSDEpgValidate, /*.pf_update =*/ OSDEpgUpdate, /*.pf_destroy =*/ OSDEpgDestroy, /*.p_sys =*/ sys // sunqueen modify end }; const mtime_t now = mdate(); subpicture_t *subpic = subpicture_New(&updater); if (!subpic) { vlc_epg_Delete(sys->epg); free(sys); return VLC_EGENERIC; } subpic->i_channel = SPU_DEFAULT_CHANNEL; subpic->i_start = now; subpic->i_stop = now + 3000 * INT64_C(1000); subpic->b_ephemer = true; subpic->b_absolute = true; subpic->b_fade = true; vout_PutSubpicture(vout, subpic); return VLC_SUCCESS; }
vlc_epg_t * vlc_epg_Duplicate( const vlc_epg_t *p_src ) { vlc_epg_t *p_epg = vlc_epg_New( p_src->i_id, p_src->i_source_id ); if( p_epg ) { p_epg->psz_name = ( p_src->psz_name ) ? strdup( p_src->psz_name ) : NULL; p_epg->b_present = p_src->b_present; for( size_t i=0; i<p_src->i_event; i++ ) { vlc_epg_event_t *p_dup = vlc_epg_event_Duplicate( p_src->pp_event[i] ); if( p_dup ) { if( p_src->p_current == p_src->pp_event[i] ) p_epg->p_current = p_dup; TAB_APPEND( p_epg->i_event, p_epg->pp_event, p_dup ); } } } return p_epg; }
void input_item_SetEpg( input_item_t *p_item, const vlc_epg_t *p_update ) { vlc_mutex_lock( &p_item->lock ); /* */ vlc_epg_t *p_epg = NULL; for( int i = 0; i < p_item->i_epg; i++ ) { vlc_epg_t *p_tmp = p_item->pp_epg[i]; if( (p_tmp->psz_name == NULL) != (p_update->psz_name == NULL) ) continue; if( p_tmp->psz_name && p_update->psz_name && strcmp(p_tmp->psz_name, p_update->psz_name) ) continue; p_epg = p_tmp; break; } /* */ if( !p_epg ) { p_epg = vlc_epg_New( p_update->psz_name ); if( p_epg ) TAB_APPEND( p_item->i_epg, p_item->pp_epg, p_epg ); } if( p_epg ) vlc_epg_Merge( p_epg, p_update ); vlc_mutex_unlock( &p_item->lock ); if( !p_epg ) return; #ifdef EPG_DEBUG char *psz_epg; if( asprintf( &psz_epg, "EPG %s", p_epg->psz_name ? p_epg->psz_name : "unknown" ) < 0 ) goto signal; input_item_DelInfo( p_item, psz_epg, NULL ); vlc_mutex_lock( &p_item->lock ); for( int i = 0; i < p_epg->i_event; i++ ) { const vlc_epg_event_t *p_evt = p_epg->pp_event[i]; time_t t_start = (time_t)p_evt->i_start; struct tm tm_start; char psz_start[128]; localtime_r( &t_start, &tm_start ); snprintf( psz_start, sizeof(psz_start), "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d", 1900 + tm_start.tm_year, 1 + tm_start.tm_mon, tm_start.tm_mday, tm_start.tm_hour, tm_start.tm_min, tm_start.tm_sec ); if( p_evt->psz_short_description || p_evt->psz_description ) InputItemAddInfo( p_item, psz_epg, psz_start, "%s (%2.2d:%2.2d) - %s %s", p_evt->psz_name, p_evt->i_duration/60/60, (p_evt->i_duration/60)%60, p_evt->psz_short_description ? p_evt->psz_short_description : "" , p_evt->psz_description ? p_evt->psz_description : "" ); else InputItemAddInfo( p_item, psz_epg, psz_start, "%s (%2.2d:%2.2d)", p_evt->psz_name, p_evt->i_duration/60/60, (p_evt->i_duration/60)%60 ); } vlc_mutex_unlock( &p_item->lock ); free( psz_epg ); signal: #endif if( p_epg->i_event > 0 ) { vlc_event_t event = { .type = vlc_InputItemInfoChanged, }; vlc_event_send( &p_item->event_manager, &event ); }
int main( void ) { test_init(); int i=1; /* Simple insert/current test */ printf("--test %d\n", i++); vlc_epg_t *p_epg = vlc_epg_New( 0, 0 ); assert(p_epg); EPG_ADD( p_epg, 42, 20, "A" ); EPG_ADD( p_epg, 62, 20, "B" ); EPG_ADD( p_epg, 82, 20, "C" ); EPG_ADD( p_epg, 102, 20, "D" ); print_order( p_epg ); assert_events( p_epg, "ABCD", 4 ); assert_current( p_epg, NULL ); vlc_epg_SetCurrent( p_epg, 82 ); assert_current( p_epg, "C" ); vlc_epg_Delete( p_epg ); /* Test reordering / head/tail inserts */ printf("--test %d\n", i++); p_epg = vlc_epg_New( 0, 0 ); assert(p_epg); EPG_ADD( p_epg, 82, 20, "C" ); EPG_ADD( p_epg, 62, 20, "B" ); EPG_ADD( p_epg, 102, 20, "D" ); EPG_ADD( p_epg, 42, 20, "A" ); print_order( p_epg ); assert_events( p_epg, "ABCD", 4 ); vlc_epg_Delete( p_epg ); /* Test reordering/bisect lookup on insert */ printf("--test %d\n", i++); p_epg = vlc_epg_New( 0, 0 ); assert(p_epg); EPG_ADD( p_epg, 142, 20, "F" ); EPG_ADD( p_epg, 122, 20, "E" ); EPG_ADD( p_epg, 102, 20, "D" ); EPG_ADD( p_epg, 82, 20, "C" ); EPG_ADD( p_epg, 42, 20, "A" ); EPG_ADD( p_epg, 62, 20, "B" ); print_order( p_epg ); assert_events( p_epg, "ABCDEF", 6 ); vlc_epg_Delete( p_epg ); /* Test deduplication and current pointer rebasing on insert */ printf("--test %d\n", i++); p_epg = vlc_epg_New( 0, 0 ); assert(p_epg); EPG_ADD( p_epg, 62, 20, "E" ); EPG_ADD( p_epg, 62, 20, "F" ); EPG_ADD( p_epg, 42, 20, "A" ); vlc_epg_SetCurrent( p_epg, 62 ); EPG_ADD( p_epg, 82, 20, "C" ); EPG_ADD( p_epg, 62, 20, "B" ); EPG_ADD( p_epg, 102, 20, "D" ); print_order( p_epg ); assert_events( p_epg, "ABCD", 4 ); assert_current( p_epg, "B" ); vlc_epg_Delete( p_epg ); /* Test epg merging */ printf("--test %d\n", i++); p_epg = vlc_epg_New( 0, 0 ); assert(p_epg); EPG_ADD( p_epg, 142, 20, "F" ); EPG_ADD( p_epg, 122, 20, "E" ); EPG_ADD( p_epg, 42, 20, "A" ); EPG_ADD( p_epg, 62, 20, "B" ); print_order( p_epg ); vlc_epg_t *p_epg2 = vlc_epg_New( 0, 0 ); assert(p_epg2); EPG_ADD( p_epg2, 102, 20, "D" ); EPG_ADD( p_epg2, 82, 20, "C" ); print_order( p_epg2 ); vlc_epg_Merge( p_epg, p_epg2 ); printf("merged " ); print_order( p_epg ); assert_events( p_epg, "ABCDEF", 6 ); assert_events( p_epg2, "CD", 2 ); /* should be untouched */ vlc_epg_Delete( p_epg ); vlc_epg_Delete( p_epg2 ); /* Test event overlapping */ printf("--test %d\n", i++); p_epg = vlc_epg_New( 0, 0 ); assert(p_epg); EPG_ADD( p_epg, 42, 20, "A" ); EPG_ADD( p_epg, 62, 20, "B" ); EPG_ADD( p_epg, 82, 20, "C" ); EPG_ADD( p_epg, 102, 20, "D" ); print_order( p_epg ); vlc_epg_SetCurrent( p_epg, 62 ); p_epg2 = vlc_epg_New( 0, 0 ); assert(p_epg2); EPG_ADD( p_epg2, 41, 30, "E" ); print_order( p_epg2 ); vlc_epg_Merge( p_epg, p_epg2 ); printf("merged " ); print_order( p_epg ); assert_events( p_epg, "ECD", 3 ); assert_current( p_epg, "E" ); EPG_ADD( p_epg2, 70, 42, "F" ); print_order( p_epg2 ); vlc_epg_Merge( p_epg, p_epg2 ); printf("merged " ); print_order( p_epg ); assert_events( p_epg, "F", 1 ); /* Test current overwriting */ printf("--test %d\n", i++); vlc_epg_SetCurrent( p_epg, 70 ); assert_current( p_epg, "F" ); print_order( p_epg ); print_order( p_epg2 ); vlc_epg_Merge( p_epg, p_epg2 ); printf("merged " ); print_order( p_epg ); assert_events( p_epg, "F", 1 ); assert_current( p_epg, "F" ); printf("--test %d\n", i++); print_order( p_epg ); EPG_ADD( p_epg2, 270, 42, "Z" ); vlc_epg_SetCurrent( p_epg2, 270 ); print_order( p_epg2 ); vlc_epg_Merge( p_epg, p_epg2 ); printf("merged " ); print_order( p_epg ); assert_current( p_epg, "Z" ); vlc_epg_Delete( p_epg ); vlc_epg_Delete( p_epg2 ); return 0; }
/** * \brief Show EPG information about the current program of an input item * \param p_vout pointer to the vout the information is to be showed on * \param p_input pointer to the input item the information is to be showed */ int vout_OSDEpg( vout_thread_t *p_vout, input_item_t *p_input ) { subpicture_t *p_spu; mtime_t i_now = mdate(); char *psz_now_playing = input_item_GetNowPlaying( p_input ); vlc_epg_t *p_epg = NULL; vlc_mutex_lock( &p_input->lock ); /* Look for the current program EPG event */ for( int i = 0; i < p_input->i_epg; i++ ) { vlc_epg_t *p_tmp = p_input->pp_epg[i]; if( p_tmp->p_current && p_tmp->p_current->psz_name && psz_now_playing != NULL && !strcmp( p_tmp->p_current->psz_name, psz_now_playing ) ) { p_epg = vlc_epg_New( p_tmp->psz_name ); vlc_epg_Merge( p_epg, p_tmp ); break; } } vlc_mutex_unlock( &p_input->lock ); /* If no EPG event has been found. */ if( p_epg == NULL ) return VLC_EGENERIC; subpicture_updater_sys_t *p_sys = malloc( sizeof( *p_sys ) ); if( !p_sys ) { vlc_epg_Delete( p_epg ); return VLC_EGENERIC; } p_sys->p_epg = p_epg; subpicture_updater_t updater = { .pf_validate = OSDEpgValidate, .pf_update = OSDEpgUpdate, .pf_destroy = OSDEpgDestroy, .p_sys = p_sys }; p_spu = subpicture_New( &updater ); if( !p_spu ) { vlc_epg_Delete( p_sys->p_epg ); free( p_sys ); return VLC_EGENERIC; } p_spu->i_channel = SPU_DEFAULT_CHANNEL; p_spu->i_start = i_now; p_spu->i_stop = i_now + 3000 * INT64_C(1000); p_spu->b_ephemer = true; p_spu->b_absolute = true; p_spu->b_fade = true; vout_PutSubpicture( p_vout, p_spu ); return VLC_SUCCESS; }