Coverage Report

Created: 2025-08-25 06:17

/src/vlc/src/misc/epg.c
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************
2
 * epg.c: Electronic Program Guide
3
 *****************************************************************************
4
 * Copyright (C) 2007 VLC authors and VideoLAN
5
 *
6
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7
 *
8
 * This program is free software; you can redistribute it and/or modify it
9
 * under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation; either version 2.1 of the License, or
11
 * (at your option) any later version.
12
 *
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 Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program; if not, write to the Free Software Foundation,
20
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21
 *****************************************************************************/
22
23
/*****************************************************************************
24
 * Preamble
25
 *****************************************************************************/
26
27
#ifdef HAVE_CONFIG_H
28
# include "config.h"
29
#endif
30
31
#include <vlc_common.h>
32
#include <vlc_arrays.h>
33
#include <vlc_epg.h>
34
35
static void vlc_epg_event_Clean(vlc_epg_event_t *p_event)
36
0
{
37
0
    for(int i=0; i<p_event->i_description_items; i++)
38
0
    {
39
0
        free(p_event->description_items[i].psz_key);
40
0
        free(p_event->description_items[i].psz_value);
41
0
    }
42
0
    free(p_event->description_items);
43
0
    free(p_event->psz_description);
44
0
    free(p_event->psz_short_description);
45
0
    free(p_event->psz_name);
46
0
}
47
48
void vlc_epg_event_Delete(vlc_epg_event_t *p_event)
49
0
{
50
0
    vlc_epg_event_Clean(p_event);
51
0
    free(p_event);
52
0
}
53
54
static void vlc_epg_event_Init(vlc_epg_event_t *p_event, uint16_t i_id,
55
                               int64_t i_start, uint32_t i_duration)
56
0
{
57
0
    memset(p_event, 0, sizeof(*p_event));
58
0
    p_event->i_start = i_start;
59
0
    p_event->i_id = i_id;
60
0
    p_event->i_duration = i_duration;
61
0
    p_event->i_description_items = 0;
62
0
    p_event->description_items = NULL;
63
0
}
64
65
vlc_epg_event_t * vlc_epg_event_New(uint16_t i_id,
66
                                    int64_t i_start, uint32_t i_duration)
67
0
{
68
0
    vlc_epg_event_t *p_event = (vlc_epg_event_t *) malloc(sizeof(*p_event));
69
0
    if(p_event)
70
0
        vlc_epg_event_Init(p_event, i_id, i_start, i_duration);
71
72
0
    return p_event;
73
0
}
74
75
vlc_epg_event_t * vlc_epg_event_Duplicate( const vlc_epg_event_t *p_src )
76
0
{
77
0
    vlc_epg_event_t *p_evt = vlc_epg_event_New( p_src->i_id, p_src->i_start,
78
0
                                                p_src->i_duration );
79
0
    if( likely(p_evt) )
80
0
    {
81
0
        if( p_src->psz_description )
82
0
            p_evt->psz_description = strdup( p_src->psz_description );
83
0
        if( p_src->psz_name )
84
0
            p_evt->psz_name = strdup( p_src->psz_name );
85
0
        if( p_src->psz_short_description )
86
0
            p_evt->psz_short_description = strdup( p_src->psz_short_description );
87
0
        if( p_src->i_description_items )
88
0
        {
89
0
            p_evt->description_items = malloc( sizeof(*p_evt->description_items) *
90
0
                                               p_src->i_description_items );
91
0
            if( p_evt->description_items )
92
0
            {
93
0
                for( int i=0; i<p_src->i_description_items; i++ )
94
0
                {
95
0
                    p_evt->description_items[i].psz_key =
96
0
                            strdup( p_src->description_items[i].psz_key );
97
0
                    p_evt->description_items[i].psz_value =
98
0
                            strdup( p_src->description_items[i].psz_value );
99
0
                    if(!p_evt->description_items[i].psz_value ||
100
0
                       !p_evt->description_items[i].psz_key)
101
0
                    {
102
0
                        free(p_evt->description_items[i].psz_key);
103
0
                        free(p_evt->description_items[i].psz_value);
104
0
                        break;
105
0
                    }
106
0
                    p_evt->i_description_items++;
107
0
                }
108
0
            }
109
0
        }
110
0
        p_evt->i_rating = p_src->i_rating;
111
0
    }
112
0
    return p_evt;
113
0
}
114
115
static void vlc_epg_Init( vlc_epg_t *p_epg, uint32_t i_id, uint16_t i_source_id )
116
0
{
117
0
    p_epg->i_id = i_id;
118
0
    p_epg->i_source_id = i_source_id;
119
0
    p_epg->psz_name = NULL;
120
0
    p_epg->p_current = NULL;
121
0
    p_epg->b_present = false;
122
0
    TAB_INIT( p_epg->i_event, p_epg->pp_event );
123
0
}
124
125
static void vlc_epg_Clean( vlc_epg_t *p_epg )
126
0
{
127
0
    size_t i;
128
0
    for( i = 0; i < p_epg->i_event; i++ )
129
0
        vlc_epg_event_Delete( p_epg->pp_event[i] );
130
0
    TAB_CLEAN( p_epg->i_event, p_epg->pp_event );
131
0
    free( p_epg->psz_name );
132
0
}
133
134
bool vlc_epg_AddEvent( vlc_epg_t *p_epg, vlc_epg_event_t *p_evt )
135
0
{
136
0
    ssize_t i_pos = -1;
137
138
    /* Insertions are supposed in sequential order first */
139
0
    if( p_epg->i_event )
140
0
    {
141
0
        if( p_epg->pp_event[0]->i_start > p_evt->i_start )
142
0
        {
143
0
            i_pos = 0;
144
0
        }
145
0
        else if ( p_epg->pp_event[p_epg->i_event - 1]->i_start >= p_evt->i_start )
146
0
        {
147
            /* Do bisect search lower start time entry */
148
0
            size_t i_lower = 0;
149
0
            size_t i_upper = p_epg->i_event - 1;
150
151
0
            while( i_lower < i_upper )
152
0
            {
153
0
                size_t i_split = ( i_lower + i_upper ) / 2;
154
0
                vlc_epg_event_t *p_cur = p_epg->pp_event[i_split];
155
156
0
                if( p_cur->i_start < p_evt->i_start )
157
0
                {
158
0
                    i_lower = i_split + 1;
159
0
                }
160
0
                else if ( p_cur->i_start >= p_evt->i_start )
161
0
                {
162
0
                    i_upper = i_split;
163
0
                }
164
0
            }
165
0
            i_pos = i_lower;
166
0
        }
167
0
    }
168
169
0
    if( i_pos != -1 )
170
0
    {
171
        /* There can be only one event at same time */
172
0
        if( p_epg->pp_event[i_pos]->i_start == p_evt->i_start )
173
0
        {
174
0
            vlc_epg_event_Delete( p_epg->pp_event[i_pos] );
175
0
            if( p_epg->p_current == p_epg->pp_event[i_pos] )
176
0
                p_epg->p_current = p_evt;
177
0
            p_epg->pp_event[i_pos] = p_evt;
178
0
            return true;
179
0
        }
180
0
        else
181
0
        {
182
0
            TAB_INSERT( p_epg->i_event, p_epg->pp_event, p_evt, i_pos );
183
0
        }
184
0
    }
185
0
    else
186
0
        TAB_APPEND( p_epg->i_event, p_epg->pp_event, p_evt );
187
188
0
    return true;
189
0
}
190
191
vlc_epg_t *vlc_epg_New( uint32_t i_id, uint16_t i_source_id )
192
0
{
193
0
    vlc_epg_t *p_epg = malloc( sizeof(*p_epg) );
194
0
    if( p_epg )
195
0
        vlc_epg_Init( p_epg, i_id, i_source_id );
196
0
    return p_epg;
197
0
}
198
199
void vlc_epg_Delete( vlc_epg_t *p_epg )
200
0
{
201
0
    vlc_epg_Clean( p_epg );
202
0
    free( p_epg );
203
0
}
204
205
void vlc_epg_SetCurrent( vlc_epg_t *p_epg, int64_t i_start )
206
0
{
207
0
    size_t i;
208
0
    p_epg->p_current = NULL;
209
0
    if( i_start < 0 )
210
0
        return;
211
212
0
    for( i = 0; i < p_epg->i_event; i++ )
213
0
    {
214
0
        if( p_epg->pp_event[i]->i_start == i_start )
215
0
        {
216
0
            p_epg->p_current = p_epg->pp_event[i];
217
0
            break;
218
0
        }
219
0
    }
220
0
}
221
222
vlc_epg_t * vlc_epg_Duplicate( const vlc_epg_t *p_src )
223
0
{
224
0
    vlc_epg_t *p_epg = vlc_epg_New( p_src->i_id, p_src->i_source_id );
225
0
    if( p_epg )
226
0
    {
227
0
        p_epg->psz_name = ( p_src->psz_name ) ? strdup( p_src->psz_name ) : NULL;
228
0
        p_epg->b_present = p_src->b_present;
229
0
        for( size_t i=0; i<p_src->i_event; i++ )
230
0
        {
231
0
            vlc_epg_event_t *p_dup = vlc_epg_event_Duplicate( p_src->pp_event[i] );
232
0
            if( p_dup )
233
0
            {
234
0
                if( p_src->p_current == p_src->pp_event[i] )
235
0
                    p_epg->p_current = p_dup;
236
0
                TAB_APPEND( p_epg->i_event, p_epg->pp_event, p_dup );
237
0
            }
238
0
        }
239
0
    }
240
0
    return p_epg;
241
0
}