/** * \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; }
static void OSDEpgDestroy(subpicture_t *subpic) { subpicture_updater_sys_t *sys = subpic->updater.p_sys; vlc_epg_Delete(sys->epg); free(sys); }
void input_item_Release( input_item_t *p_item ) { input_item_owner_t *owner = item_owner(p_item); if( atomic_fetch_sub(&owner->refs, 1) != 1 ) return; vlc_event_manager_fini( &p_item->event_manager ); free( p_item->psz_name ); free( p_item->psz_uri ); if( p_item->p_stats != NULL ) { vlc_mutex_destroy( &p_item->p_stats->lock ); free( p_item->p_stats ); } if( p_item->p_meta != NULL ) vlc_meta_Delete( p_item->p_meta ); for( input_item_opaque_t *o = p_item->opaques, *next; o != NULL; o = next ) { next = o->next; free( o ); } for( int i = 0; i < p_item->i_options; i++ ) free( p_item->ppsz_options[i] ); TAB_CLEAN( p_item->i_options, p_item->ppsz_options ); free( p_item->optflagv ); for( int i = 0; i < p_item->i_es; i++ ) { es_format_Clean( p_item->es[i] ); free( p_item->es[i] ); } TAB_CLEAN( p_item->i_es, p_item->es ); for( int i = 0; i < p_item->i_epg; i++ ) vlc_epg_Delete( p_item->pp_epg[i] ); TAB_CLEAN( p_item->i_epg, p_item->pp_epg ); for( int i = 0; i < p_item->i_categories; i++ ) info_category_Delete( p_item->pp_categories[i] ); TAB_CLEAN( p_item->i_categories, p_item->pp_categories ); for( int i = 0; i < p_item->i_slaves; i++ ) input_item_slave_Delete( p_item->pp_slaves[i] ); TAB_CLEAN( p_item->i_slaves, p_item->pp_slaves ); vlc_mutex_destroy( &p_item->lock ); free( owner ); }
static inline void input_item_Clean( input_item_t *p_i ) { int i; vlc_event_manager_fini( &p_i->event_manager ); free( p_i->psz_name ); free( p_i->psz_uri ); if( p_i->p_stats ) { vlc_mutex_destroy( &p_i->p_stats->lock ); free( p_i->p_stats ); } if( p_i->p_meta ) vlc_meta_Delete( p_i->p_meta ); for( i = 0; i < p_i->i_options; i++ ) free( p_i->ppsz_options[i] ); TAB_CLEAN( p_i->i_options, p_i->ppsz_options ); free( p_i->optflagv); for( i = 0; i < p_i->i_es; i++ ) { es_format_Clean( p_i->es[i] ); free( p_i->es[i] ); } TAB_CLEAN( p_i->i_es, p_i->es ); for( i = 0; i < p_i->i_tracks; i++ ) input_item_track_Delete( p_i->tracks[i] ); TAB_CLEAN( p_i->tracks, p_i->tracks ); for( i = 0; i < p_i->i_epg; i++ ) vlc_epg_Delete( p_i->pp_epg[i] ); TAB_CLEAN( p_i->i_epg, p_i->pp_epg ); for( i = 0; i < p_i->i_categories; i++ ) info_category_Delete( p_i->pp_categories[i] ); TAB_CLEAN( p_i->i_categories, p_i->pp_categories ); vlc_mutex_destroy( &p_i->lock ); }
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; }
//#define EPG_DEBUG void input_item_SetEpg( input_item_t *p_item, const vlc_epg_t *p_update, bool b_current_source ) { vlc_epg_t *p_epg = vlc_epg_Duplicate( p_update ); if( !p_epg ) return; vlc_mutex_lock( &p_item->lock ); /* */ vlc_epg_t **pp_epg = NULL; for( int i = 0; i < p_item->i_epg; i++ ) { if( p_item->pp_epg[i]->i_source_id == p_update->i_source_id && p_item->pp_epg[i]->i_id == p_update->i_id ) { pp_epg = &p_item->pp_epg[i]; break; } } /* replace with new version */ if( pp_epg ) { vlc_epg_Delete( *pp_epg ); if( *pp_epg == p_item->p_epg_table ) /* current table can have changed */ p_item->p_epg_table = NULL; *pp_epg = p_epg; } else { TAB_APPEND( p_item->i_epg, p_item->pp_epg, p_epg ); } if( b_current_source && p_epg->b_present ) p_item->p_epg_table = p_epg; 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( size_t 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 vlc_event_send( &p_item->event_manager, &(vlc_event_t){ .type = vlc_InputItemInfoChanged, } );