bool vlc_epg_AddEvent( vlc_epg_t *p_epg, vlc_epg_event_t *p_evt ) { ssize_t i_pos = -1; /* Insertions are supposed in sequential order first */ if( p_epg->i_event ) { if( p_epg->pp_event[0]->i_start > p_evt->i_start ) { i_pos = 0; } else if ( p_epg->pp_event[p_epg->i_event - 1]->i_start >= p_evt->i_start ) { /* Do bisect search lower start time entry */ size_t i_lower = 0; size_t i_upper = p_epg->i_event - 1; while( i_lower < i_upper ) { size_t i_split = ( i_lower + i_upper ) / 2; vlc_epg_event_t *p_cur = p_epg->pp_event[i_split]; if( p_cur->i_start < p_evt->i_start ) { i_lower = i_split + 1; } else if ( p_cur->i_start >= p_evt->i_start ) { i_upper = i_split; } } i_pos = i_lower; } } if( i_pos != -1 ) { /* There can be only one event at same time */ if( p_epg->pp_event[i_pos]->i_start == p_evt->i_start ) { vlc_epg_event_Delete( p_epg->pp_event[i_pos] ); if( p_epg->p_current == p_epg->pp_event[i_pos] ) p_epg->p_current = p_evt; p_epg->pp_event[i_pos] = p_evt; return true; } else { TAB_INSERT( p_epg->i_event, p_epg->pp_event, p_evt, i_pos ); } } else TAB_APPEND( p_epg->i_event, p_epg->pp_event, p_evt ); return true; }
/***************************************************************************** * Import cut marks and convert them to seekpoints (chapters). *****************************************************************************/ static void ImportMarks( access_t *p_access ) { access_sys_t *p_sys = p_access->p_sys; FILE *marksfile = OpenRelativeFile( p_access, "marks" ); if( !marksfile ) return; FILE *indexfile = OpenRelativeFile( p_access, "index" ); if( !indexfile ) { fclose( marksfile ); return; } /* get the length of this recording (index stores 8 bytes per frame) */ struct stat st; if( fstat( fileno( indexfile ), &st ) ) { fclose( marksfile ); fclose( indexfile ); return; } int64_t i_frame_count = st.st_size / 8; /* Put all cut marks in a "dummy" title */ input_title_t *p_marks = vlc_input_title_New(); if( !p_marks ) { fclose( marksfile ); fclose( indexfile ); return; } p_marks->psz_name = strdup( _("VDR Cut Marks") ); p_marks->i_length = i_frame_count * (int64_t)( CLOCK_FREQ / p_sys->fps ); uint64_t *offsetv = NULL; size_t offsetc = 0; /* offset for chapter positions */ int i_chapter_offset = p_sys->fps / 1000 * var_InheritInteger( p_access, "vdr-chapter-offset" ); /* minimum chapter size in frames */ int i_min_chapter_size = p_sys->fps * MIN_CHAPTER_SIZE; /* the last chapter started at this frame (init to 0 so * we skip useless chapters near the beginning as well) */ int64_t i_prev_chapter = 0; /* parse lines of the form "0:00:00.00 foobar" */ char *line = NULL; size_t line_len; while( ReadLine( &line, &line_len, marksfile ) ) { int64_t i_frame = ParseFrameNumber( line, p_sys->fps ); /* skip chapters which are near the end or too close to each other */ if( i_frame - i_prev_chapter < i_min_chapter_size || i_frame >= i_frame_count - i_min_chapter_size ) continue; i_prev_chapter = i_frame; /* move chapters (simple workaround for inaccurate cut marks) */ if( i_frame > -i_chapter_offset ) i_frame += i_chapter_offset; else i_frame = 0; uint64_t i_offset; uint16_t i_file_number; if( !ReadIndexRecord( indexfile, p_sys->b_ts_format, i_frame, &i_offset, &i_file_number ) ) continue; if( i_file_number < 1 || i_file_number > FILE_COUNT ) continue; /* add file sizes to get the "global" offset */ seekpoint_t *sp = vlc_seekpoint_New(); if( !sp ) continue; sp->i_time_offset = i_frame * (int64_t)( CLOCK_FREQ / p_sys->fps ); sp->psz_name = strdup( line ); TAB_APPEND( p_marks->i_seekpoint, p_marks->seekpoint, sp ); TAB_APPEND( offsetc, offsetv, i_offset ); for( int i = 0; i + 1 < i_file_number; ++i ) offsetv[offsetc - 1] += FILE_SIZE( i ); } /* add a chapter at the beginning if missing */ if( p_marks->i_seekpoint > 0 && offsetv[0] > 0 ) { seekpoint_t *sp = vlc_seekpoint_New(); if( sp ) { sp->i_time_offset = 0; sp->psz_name = strdup( _("Start") ); TAB_INSERT( p_marks->i_seekpoint, p_marks->seekpoint, sp, 0 ); TAB_INSERT( offsetc, offsetv, UINT64_C(0), 0 ); } } if( p_marks->i_seekpoint > 0 ) { p_sys->p_marks = p_marks; p_sys->offsets = offsetv; } else { vlc_input_title_Delete( p_marks ); TAB_CLEAN( offsetc, offsetv ); } fclose( marksfile ); fclose( indexfile ); }
void vlc_epg_Merge( vlc_epg_t *p_dst_epg, const vlc_epg_t *p_src_epg ) { if( p_src_epg->i_event == 0 ) return; size_t i_dst=0; size_t i_src=0; for( ; i_src < p_src_epg->i_event; i_src++ ) { bool b_current = ( p_src_epg->pp_event[i_src] == p_src_epg->p_current ); vlc_epg_event_t *p_src = vlc_epg_event_Duplicate( p_src_epg->pp_event[i_src] ); if( unlikely(!p_src) ) return; const int64_t i_src_end = p_src->i_start + p_src->i_duration; while( i_dst < p_dst_epg->i_event ) { vlc_epg_event_t *p_dst = p_dst_epg->pp_event[i_dst]; const int64_t i_dst_end = p_dst->i_start + p_dst->i_duration; /* appended is before current, no overlap */ if( p_dst->i_start >= i_src_end ) { break; } /* overlap case: appended would contain current's start (or are identical) */ else if( ( p_dst->i_start >= p_src->i_start && p_dst->i_start < i_src_end ) || /* overlap case: appended would contain current's end */ ( i_dst_end > p_src->i_start && i_dst_end <= i_src_end ) ) { vlc_epg_event_Delete( p_dst ); if( p_dst_epg->p_current == p_dst ) { b_current |= true; p_dst_epg->p_current = NULL; } TAB_ERASE( p_dst_epg->i_event, p_dst_epg->pp_event, i_dst ); } else { i_dst++; } } TAB_INSERT( p_dst_epg->i_event, p_dst_epg->pp_event, p_src, i_dst ); if( b_current ) p_dst_epg->p_current = p_src; } /* Remaining/trailing ones */ for( ; i_src < p_src_epg->i_event; i_src++ ) { vlc_epg_event_t *p_src = vlc_epg_event_Duplicate( p_src_epg->pp_event[i_src] ); if( unlikely(!p_src) ) return; TAB_APPEND( p_dst_epg->i_event, p_dst_epg->pp_event, p_src ); if( p_src_epg->pp_event[i_src] == p_src_epg->p_current ) p_dst_epg->p_current = p_src; } vlc_epg_Prune( p_dst_epg ); }
void vlc_epg_AddEvent( vlc_epg_t *p_epg, int64_t i_start, int i_duration, const char *psz_name, const char *psz_short_description, const char *psz_description, uint8_t i_rating ) { vlc_epg_event_t *p_evt = vlc_epg_Event_New( i_start, i_duration, psz_name, psz_short_description, psz_description, i_rating ); if( unlikely(!p_evt) ) return; int i_pos = -1; /* Insertions are supposed in sequential order first */ if( p_epg->i_event ) { if( p_epg->pp_event[0]->i_start > i_start ) { i_pos = 0; } else if ( p_epg->pp_event[p_epg->i_event - 1]->i_start >= i_start ) { /* Do bisect search lower start time entry */ int i_lower = 0; int i_upper = p_epg->i_event - 1; while( i_lower < i_upper ) { int i_split = ( (size_t)i_lower + i_upper ) / 2; vlc_epg_event_t *p_cur = p_epg->pp_event[i_split]; if( p_cur->i_start < i_start ) { i_lower = i_split + 1; } else if ( p_cur->i_start >= i_start ) { i_upper = i_split; } } i_pos = i_lower; } } if( i_pos != -1 ) { if( p_epg->pp_event[i_pos]->i_start == i_start )/* There can be only one event at same time */ { vlc_epg_Event_Delete( p_epg->pp_event[i_pos] ); if( p_epg->p_current == p_epg->pp_event[i_pos] ) p_epg->p_current = p_evt; p_epg->pp_event[i_pos] = p_evt; return; } else { TAB_INSERT( p_epg->i_event, p_epg->pp_event, p_evt, i_pos ); } } else TAB_APPEND( p_epg->i_event, p_epg->pp_event, p_evt ); }