chapters.cpp 6.36 KB
Newer Older
1
/*****************************************************************************
Pere Orga's avatar
Pere Orga committed
2
 * chapters.cpp : matroska demuxer
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *****************************************************************************
 * Copyright (C) 2003-2004 the VideoLAN team
 * $Id$
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Steve Lhomme <steve.lhomme@free.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

25
#include "chapters.hpp"
26

27
#include "chapter_command.hpp"
28

29
chapter_item_c::~chapter_item_c()
30
{
Denis Charmet's avatar
Denis Charmet committed
31 32 33 34
    if( p_segment_uid )
        delete p_segment_uid;
    if( p_segment_edition_uid )
        delete p_segment_edition_uid;
35 36
    vlc_delete_all( codecs );
    vlc_delete_all( sub_chapters );
37 38 39 40 41 42
}

chapter_item_c *chapter_item_c::BrowseCodecPrivate( unsigned int codec_id,
                                    bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
                                    const void *p_cookie,
                                    size_t i_cookie_size )
43
{
Denis Charmet's avatar
Denis Charmet committed
44
    VLC_UNUSED( codec_id );
45 46 47
    // this chapter
    std::vector<chapter_codec_cmds_c*>::const_iterator index = codecs.begin();
    while ( index != codecs.end() )
48
    {
49 50
        if ( match( **index ,p_cookie, i_cookie_size ) )
            return this;
51
        ++index;
52
    }
Denis Charmet's avatar
Denis Charmet committed
53
    return NULL;
54 55
}

56
void chapter_item_c::Append( const chapter_item_c & chapter )
57
{
58
    // we are appending content for the same chapter UID
59
    size_t i;
60
    chapter_item_c *p_chapter;
61

62
    for ( i=0; i<chapter.sub_chapters.size(); i++ )
63
    {
64 65
        p_chapter = FindChapter( chapter.sub_chapters[i]->i_uid );
        if ( p_chapter != NULL )
66
        {
67 68 69 70 71
            p_chapter->Append( *chapter.sub_chapters[i] );
        }
        else
        {
            sub_chapters.push_back( chapter.sub_chapters[i] );
72 73 74 75
        }
    }
}

76
chapter_item_c * chapter_item_c::FindChapter( int64_t i_find_uid )
77
{
78 79
    size_t i;
    chapter_item_c *p_result = NULL;
80

81 82
    if ( i_uid == i_find_uid )
        return this;
83

84
    for ( i=0; i<sub_chapters.size(); i++)
85
    {
86 87 88
        p_result = sub_chapters[i]->FindChapter( i_find_uid );
        if ( p_result != NULL )
            break;
89
    }
90
    return p_result;
91 92
}

93
std::string chapter_item_c::GetCodecName( bool f_for_title ) const
94
{
95
    std::string result;
96

97 98
    std::vector<chapter_codec_cmds_c*>::const_iterator index = codecs.begin();
    while ( index != codecs.end() )
99
    {
100 101 102
        result = (*index)->GetCodecName( f_for_title );
        if ( result != "" )
            break;
103
        ++index;
104 105
    }

106 107
    return result;
}
108

109 110 111
int16 chapter_item_c::GetTitleNumber( ) const
{
    int result = -1;
112

113 114 115 116 117 118
    std::vector<chapter_codec_cmds_c*>::const_iterator index = codecs.begin();
    while ( index != codecs.end() )
    {
        result = (*index)->GetTitleNumber( );
        if ( result >= 0 )
            break;
119
        ++index;
120 121
    }

122 123
    return result;
}
124

125
bool chapter_item_c::ParentOf( const chapter_item_c & item ) const
126
{
127 128
    if ( &item == this )
        return true;
129

130 131
    std::vector<chapter_item_c*>::const_iterator index = sub_chapters.begin();
    while ( index != sub_chapters.end() )
132
    {
133 134
        if ( (*index)->ParentOf( item ) )
            return true;
135
        ++index;
136 137
    }

138
    return false;
139 140 141 142 143 144 145 146 147
}

bool chapter_item_c::Enter( bool b_do_subs )
{
    bool f_result = false;
    std::vector<chapter_codec_cmds_c*>::iterator index = codecs.begin();
    while ( index != codecs.end() )
    {
        f_result |= (*index)->Enter();
148
        ++index;
149 150 151 152 153 154 155 156 157
    }

    if ( b_do_subs )
    {
        // sub chapters
        std::vector<chapter_item_c*>::iterator index_ = sub_chapters.begin();
        while ( index_ != sub_chapters.end() )
        {
            f_result |= (*index_)->Enter( true );
158
            ++index_;
159 160 161 162 163 164 165 166 167 168 169 170 171
        }
    }
    return f_result;
}

bool chapter_item_c::Leave( bool b_do_subs )
{
    bool f_result = false;
    b_is_leaving = true;
    std::vector<chapter_codec_cmds_c*>::iterator index = codecs.begin();
    while ( index != codecs.end() )
    {
        f_result |= (*index)->Leave();
172
        ++index;
173 174 175 176 177 178 179 180 181
    }

    if ( b_do_subs )
    {
        // sub chapters
        std::vector<chapter_item_c*>::iterator index_ = sub_chapters.begin();
        while ( index_ != sub_chapters.end() )
        {
            f_result |= (*index_)->Leave( true );
182
            ++index_;
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
        }
    }
    b_is_leaving = false;
    return f_result;
}

bool chapter_item_c::EnterAndLeave( chapter_item_c *p_item, bool b_final_enter )
{
    chapter_item_c *p_common_parent = p_item;

    // leave, up to a common parent
    while ( p_common_parent != NULL && !p_common_parent->ParentOf( *this ) )
    {
        if ( !p_common_parent->b_is_leaving && p_common_parent->Leave( false ) )
            return true;
198
        p_common_parent = p_common_parent->p_parent;
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
    }

    // enter from the parent to <this>
    if ( p_common_parent != NULL )
    {
        do
        {
            if ( p_common_parent == this )
                return Enter( true );

            for ( size_t i = 0; i<p_common_parent->sub_chapters.size(); i++ )
            {
                if ( p_common_parent->sub_chapters[i]->ParentOf( *this ) )
                {
                    p_common_parent = p_common_parent->sub_chapters[i];
                    if ( p_common_parent != this )
                        if ( p_common_parent->Enter( false ) )
                            return true;

                    break;
                }
            }
        } while ( 1 );
    }

    if ( b_final_enter )
        return Enter( true );
    else
        return false;
}



232 233
/* Chapter Edition Class */
std::string chapter_edition_c::GetMainName() const
234
{
235
    if ( sub_chapters.size() )
236
    {
237
        return sub_chapters[0]->GetCodecName( true );
238
    }
239
    return "";
240 241
}