Coverage Report

Created: 2026-01-10 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/src/player/title.c
Line
Count
Source
1
/*****************************************************************************
2
 * player_title.c: Player title implementation
3
 *****************************************************************************
4
 * Copyright © 2018-2019 VLC authors and VideoLAN
5
 *
6
 * This program is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU Lesser General Public License as published by
8
 * the Free Software Foundation; either version 2.1 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with this program; if not, write to the Free Software Foundation,
18
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19
 *****************************************************************************/
20
21
#ifdef HAVE_CONFIG_H
22
# include "config.h"
23
#endif
24
25
#include <limits.h>
26
#include <stdckdint.h>
27
28
#include <vlc_common.h>
29
#include "player.h"
30
31
struct vlc_player_title_list *
32
vlc_player_title_list_Hold(struct vlc_player_title_list *titles)
33
0
{
34
0
    vlc_atomic_rc_inc(&titles->rc);
35
0
    return titles;
36
0
}
37
38
void
39
vlc_player_title_list_Release(struct vlc_player_title_list *titles)
40
0
{
41
0
    if (!vlc_atomic_rc_dec(&titles->rc))
42
0
        return;
43
0
    for (size_t title_idx = 0; title_idx < titles->count; ++title_idx)
44
0
    {
45
0
        struct vlc_player_title *title = &titles->array[title_idx];
46
0
        free((char *)title->name);
47
0
        for (size_t chapter_idx = 0; chapter_idx < title->chapter_count;
48
0
             ++chapter_idx)
49
0
        {
50
0
            const struct vlc_player_chapter *chapter =
51
0
                &title->chapters[chapter_idx];
52
0
            free((char *)chapter->name);
53
0
        }
54
0
        free((void *)title->chapters);
55
0
    }
56
0
    free(titles);
57
0
}
58
59
static char *
60
input_title_GetName(const struct input_title_t *input_title, int idx,
61
                    int title_offset)
62
0
{
63
0
    int ret;
64
0
    char length_str[MSTRTIME_MAX_SIZE + sizeof(" []")];
65
66
0
    if (input_title->i_length > 0)
67
0
    {
68
0
        strcpy(length_str, " [");
69
0
        vlc_tick_to_str(&length_str[2], input_title->i_length);
70
0
        strcat(length_str, "]");
71
0
    }
72
0
    else
73
0
        length_str[0] = '\0';
74
75
0
    char *dup;
76
0
    if (input_title->psz_name && input_title->psz_name[0] != '\0')
77
0
        ret = asprintf(&dup, "%s%s", input_title->psz_name, length_str);
78
0
    else
79
0
        ret = asprintf(&dup, _("Title %i%s"), idx + title_offset, length_str);
80
0
    if (ret == -1)
81
0
        return NULL;
82
0
    return dup;
83
0
}
84
85
static char *
86
seekpoint_GetName(seekpoint_t *seekpoint, int idx, int chapter_offset)
87
0
{
88
0
    if (seekpoint->psz_name && seekpoint->psz_name[0] != '\0' )
89
0
        return strdup(seekpoint->psz_name);
90
91
0
    char *dup;
92
0
    int ret = asprintf(&dup, _("Chapter %i"), idx + chapter_offset);
93
0
    if (ret == -1)
94
0
        return NULL;
95
0
    return dup;
96
0
}
97
98
struct vlc_player_title_list *
99
vlc_player_title_list_Create(input_title_t *const *array, size_t count,
100
                             int title_offset, int chapter_offset)
101
0
{
102
0
    if (count == 0)
103
0
        return NULL;
104
105
    /* Allocate the struct + the whole list */
106
0
    size_t size;
107
0
    if (ckd_mul(&size, count, sizeof(struct vlc_player_title)))
108
0
        return NULL;
109
0
    if (ckd_add(&size, size, sizeof(struct vlc_player_title_list)))
110
0
        return NULL;
111
0
    struct vlc_player_title_list *titles = malloc(size);
112
0
    if (!titles)
113
0
        return NULL;
114
115
0
    vlc_atomic_rc_init(&titles->rc);
116
0
    titles->count = count;
117
118
0
    for (size_t title_idx = 0; title_idx < titles->count; ++title_idx)
119
0
    {
120
0
        const struct input_title_t *input_title = array[title_idx];
121
0
        struct vlc_player_title *title = &titles->array[title_idx];
122
123
0
        title->name = input_title_GetName(input_title, title_idx, title_offset);
124
0
        title->length = input_title->i_length;
125
0
        title->flags = input_title->i_flags;
126
0
        const size_t seekpoint_count = input_title->i_seekpoint > 0 ?
127
0
                                       input_title->i_seekpoint : 0;
128
0
        title->chapter_count = seekpoint_count;
129
130
0
        struct vlc_player_chapter *chapters = title->chapter_count == 0 ? NULL :
131
0
            vlc_alloc(title->chapter_count, sizeof(*chapters));
132
133
0
        if (chapters)
134
0
        {
135
0
            for (size_t chapter_idx = 0; chapter_idx < title->chapter_count;
136
0
                 ++chapter_idx)
137
0
            {
138
0
                struct vlc_player_chapter *chapter = &chapters[chapter_idx];
139
0
                seekpoint_t *seekpoint = input_title->seekpoint[chapter_idx];
140
141
0
                chapter->name = seekpoint_GetName(seekpoint, chapter_idx,
142
0
                                                  chapter_offset);
143
0
                chapter->time = seekpoint->i_time_offset;
144
0
                if (!chapter->name) /* Will trigger the error path */
145
0
                    title->chapter_count = chapter_idx;
146
0
            }
147
0
        }
148
0
        else if (seekpoint_count > 0) /* Will trigger the error path */
149
0
            title->chapter_count = 0;
150
151
0
        title->chapters = chapters;
152
153
0
        if (!title->name || seekpoint_count != title->chapter_count)
154
0
        {
155
            /* Release titles up to title_idx */
156
0
            titles->count = title_idx;
157
0
            vlc_player_title_list_Release(titles);
158
0
            return NULL;
159
0
        }
160
0
    }
161
0
    return titles;
162
0
}
163
164
const struct vlc_player_title *
165
vlc_player_title_list_GetAt(struct vlc_player_title_list *titles, size_t idx)
166
0
{
167
0
    assert(idx < titles->count);
168
0
    return &titles->array[idx];
169
0
}
170
171
size_t
172
vlc_player_title_list_GetCount(struct vlc_player_title_list *titles)
173
0
{
174
0
    return titles->count;
175
0
}