/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 | } |