/src/vlc/modules/demux/mkv/chapters.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /***************************************************************************** |
2 | | * chapters.cpp : matroska demuxer |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2003-2004 VLC authors and VideoLAN |
5 | | * |
6 | | * Authors: Laurent Aimar <fenrir@via.ecp.fr> |
7 | | * Steve Lhomme <steve.lhomme@free.fr> |
8 | | * |
9 | | * This program is free software; you can redistribute it and/or modify it |
10 | | * under the terms of the GNU Lesser General Public License as published by |
11 | | * the Free Software Foundation; either version 2.1 of the License, or |
12 | | * (at your option) any later version. |
13 | | * |
14 | | * This program is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | * GNU Lesser General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General Public License |
20 | | * along with this program; if not, write to the Free Software Foundation, |
21 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
22 | | *****************************************************************************/ |
23 | | |
24 | | #include "chapters.hpp" |
25 | | |
26 | | #include "chapter_command.hpp" |
27 | | |
28 | | #include <vlc_arrays.h> |
29 | | |
30 | | #include <functional> |
31 | | #include <algorithm> |
32 | | |
33 | | namespace mkv { |
34 | | |
35 | | chapter_item_c::~chapter_item_c() |
36 | 0 | { |
37 | 0 | delete p_segment_uid; |
38 | 0 | delete p_segment_edition_uid; |
39 | 0 | vlc_delete_all( codecs ); |
40 | 0 | vlc_delete_all( sub_chapters ); |
41 | 0 | } |
42 | | |
43 | | chapter_item_c *chapter_item_c::BrowseCodecPrivate( chapter_codec_id codec_id, |
44 | | chapter_cmd_match match ) |
45 | 0 | { |
46 | | // this chapter |
47 | 0 | for (const mkv::chapter_codec_cmds_c *index : codecs) |
48 | 0 | { |
49 | 0 | if ( index->i_codec_id == codec_id && |
50 | 0 | match( *index ) ) |
51 | 0 | return this; |
52 | 0 | } |
53 | 0 | return NULL; |
54 | 0 | } |
55 | | |
56 | | void chapter_item_c::Append( const chapter_item_c & chapter ) |
57 | 0 | { |
58 | | // we are appending content for the same chapter UID |
59 | 0 | size_t i; |
60 | 0 | chapter_item_c *p_chapter; |
61 | |
|
62 | 0 | for ( i=0; i<chapter.sub_chapters.size(); i++ ) |
63 | 0 | { |
64 | 0 | p_chapter = FindChapter( chapter.sub_chapters[i]->i_uid ); |
65 | 0 | if ( p_chapter != NULL ) |
66 | 0 | { |
67 | 0 | p_chapter->Append( *chapter.sub_chapters[i] ); |
68 | 0 | } |
69 | 0 | else |
70 | 0 | { |
71 | 0 | sub_chapters.push_back( chapter.sub_chapters[i] ); |
72 | 0 | } |
73 | 0 | } |
74 | 0 | } |
75 | | |
76 | | chapter_item_c * chapter_item_c::FindChapter( chapter_uid i_find_uid ) |
77 | 0 | { |
78 | 0 | size_t i; |
79 | 0 | chapter_item_c *p_result = NULL; |
80 | |
|
81 | 0 | if ( i_uid == i_find_uid ) |
82 | 0 | return this; |
83 | | |
84 | 0 | for ( i=0; i<sub_chapters.size(); i++) |
85 | 0 | { |
86 | 0 | p_result = sub_chapters[i]->FindChapter( i_find_uid ); |
87 | 0 | if ( p_result != NULL ) |
88 | 0 | break; |
89 | 0 | } |
90 | 0 | return p_result; |
91 | 0 | } |
92 | | |
93 | | std::string chapter_item_c::GetCodecName( bool f_for_title ) const |
94 | 0 | { |
95 | 0 | std::string result; |
96 | |
|
97 | 0 | for (const mkv::chapter_codec_cmds_c *index : codecs) |
98 | 0 | { |
99 | 0 | result = index->GetCodecName( f_for_title ); |
100 | 0 | if ( !result.empty () ) |
101 | 0 | break; |
102 | 0 | } |
103 | |
|
104 | 0 | return result; |
105 | 0 | } |
106 | | |
107 | | int16_t chapter_item_c::GetTitleNumber( ) const |
108 | 0 | { |
109 | 0 | int result = -1; |
110 | |
|
111 | 0 | for (const mkv::chapter_codec_cmds_c *index : codecs) |
112 | 0 | { |
113 | 0 | result = index->GetTitleNumber( ); |
114 | 0 | if ( result >= 0 ) |
115 | 0 | break; |
116 | 0 | } |
117 | |
|
118 | 0 | return result; |
119 | 0 | } |
120 | | |
121 | | bool chapter_item_c::ParentOf( const chapter_item_c & item ) const |
122 | 0 | { |
123 | 0 | if ( &item == this ) |
124 | 0 | return true; |
125 | | |
126 | 0 | std::vector<chapter_item_c*>::const_iterator index = sub_chapters.begin(); |
127 | 0 | while ( index != sub_chapters.end() ) |
128 | 0 | { |
129 | 0 | if ( (*index)->ParentOf( item ) ) |
130 | 0 | return true; |
131 | 0 | ++index; |
132 | 0 | } |
133 | | |
134 | 0 | return false; |
135 | 0 | } |
136 | | |
137 | | bool chapter_item_c::EnterLeaveHelper_ ( bool do_subs, |
138 | | bool (chapter_codec_cmds_c::* co_cb) (), |
139 | | bool (chapter_item_c ::* ch_cb) (bool) |
140 | 0 | ) { |
141 | 0 | bool f_result = false; |
142 | |
|
143 | 0 | f_result |= std::count_if ( codecs.begin (), codecs.end (), |
144 | 0 | std::mem_fn (co_cb) |
145 | 0 | ); |
146 | |
|
147 | 0 | if ( do_subs ) |
148 | 0 | { |
149 | 0 | using std::placeholders::_1; |
150 | 0 | f_result |= count_if ( sub_chapters.begin (), sub_chapters.end (), |
151 | 0 | std::bind( std::mem_fn( ch_cb ), _1, true ) |
152 | 0 | ); |
153 | 0 | } |
154 | |
|
155 | 0 | return f_result; |
156 | 0 | } |
157 | | |
158 | | bool chapter_item_c::Enter( bool b_do_subs ) |
159 | 0 | { |
160 | 0 | return EnterLeaveHelper_ (b_do_subs, |
161 | 0 | &chapter_codec_cmds_c::Enter, |
162 | 0 | &chapter_item_c::Enter |
163 | 0 | ); |
164 | 0 | } |
165 | | |
166 | | bool chapter_item_c::Leave( bool b_do_subs ) |
167 | 0 | { |
168 | 0 | b_is_leaving = true; |
169 | |
|
170 | 0 | bool f_result = EnterLeaveHelper_ (b_do_subs, |
171 | 0 | &chapter_codec_cmds_c::Leave, |
172 | 0 | &chapter_item_c::Leave |
173 | 0 | ); |
174 | |
|
175 | 0 | b_is_leaving = false; |
176 | 0 | return f_result; |
177 | 0 | } |
178 | | |
179 | | bool chapter_item_c::EnterAndLeave( chapter_item_c *p_leaving_chapter, bool b_final_enter ) |
180 | 0 | { |
181 | 0 | chapter_item_c *p_common_parent = p_leaving_chapter; |
182 | | |
183 | | // leave, up to a common parent |
184 | 0 | while ( p_common_parent != NULL && !p_common_parent->ParentOf( *this ) ) |
185 | 0 | { |
186 | 0 | if ( !p_common_parent->b_is_leaving && p_common_parent->Leave( false ) ) |
187 | 0 | return true; |
188 | 0 | p_common_parent = p_common_parent->p_parent; |
189 | 0 | } |
190 | | |
191 | | // enter from the parent to <this> |
192 | 0 | if ( p_common_parent != NULL ) |
193 | 0 | { |
194 | 0 | do |
195 | 0 | { |
196 | 0 | if ( p_common_parent == this ) |
197 | 0 | return Enter( true ); |
198 | | |
199 | 0 | for ( size_t i = 0; i<p_common_parent->sub_chapters.size(); i++ ) |
200 | 0 | { |
201 | 0 | if ( p_common_parent->sub_chapters[i]->ParentOf( *this ) ) |
202 | 0 | { |
203 | 0 | p_common_parent = p_common_parent->sub_chapters[i]; |
204 | 0 | if ( p_common_parent != this ) |
205 | 0 | if ( p_common_parent->Enter( false ) ) |
206 | 0 | return true; |
207 | | |
208 | 0 | break; |
209 | 0 | } |
210 | 0 | } |
211 | 0 | } while ( 1 ); |
212 | 0 | } |
213 | | |
214 | 0 | if ( b_final_enter ) |
215 | 0 | return Enter( true ); |
216 | 0 | else |
217 | 0 | return false; |
218 | 0 | } |
219 | | |
220 | | |
221 | | |
222 | | /* Chapter Edition Class */ |
223 | | std::string chapter_edition_c::GetMainName() const |
224 | 0 | { |
225 | 0 | if ( sub_chapters.size() ) |
226 | 0 | { |
227 | 0 | return sub_chapters[0]->GetCodecName( true ); |
228 | 0 | } |
229 | 0 | return ""; |
230 | 0 | } |
231 | | |
232 | | } // namespace |