playtree.cpp 8.93 KB
Newer Older
1 2 3
/*****************************************************************************
 * playtree.cpp
 *****************************************************************************
Clément Stenac's avatar
Clément Stenac committed
4
 * Copyright (C) 2005 the VideoLAN team
5
 * $Id$
6 7
 *
 * Authors: Antoine Cellerier <dionoea@videolan.org>
Clément Stenac's avatar
Clément Stenac committed
8
 *          Clément Stenac <zorglub@videolan.org>
9
 *          Erwan Tulou    <erwan10@videolan.org>
10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * 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
Antoine Cellerier's avatar
Antoine Cellerier committed
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 25
 *****************************************************************************/

26 27 28 29
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

30
#include <vlc_common.h>
31 32

#include "playtree.hpp"
Clément Stenac's avatar
Clément Stenac committed
33
#include <vlc_playlist.h>
34
#include <vlc_url.h>
35 36
#include "../utils/ustring.hpp"

37 38
Playtree::Playtree( intf_thread_t *pIntf )
    : VarTree( pIntf ), m_pPlaylist( pIntf->p_sys->p_playlist )
39
{
40
    getPositionVar().addObserver( this );
41 42 43 44 45
    buildTree();
}

Playtree::~Playtree()
{
46
    getPositionVar().delObserver( this );
47 48 49 50
}

void Playtree::delSelected()
{
51
    for( Iterator it = m_children.begin(); it != m_children.end(); )
52
    {
53
        if( it->isSelected() && !it->isReadonly() )
54
        {
55 56 57 58 59
            playlist_Lock( m_pPlaylist );

            playlist_item_t *pItem =
                playlist_ItemGetById( m_pPlaylist, it->getId() );
            if( pItem )
60
            {
61 62 63 64 65 66 67 68 69
                if( pItem->i_children == -1 )
                {
                    playlist_DeleteFromInput( m_pPlaylist, pItem->p_input,
                                              pl_Locked );
                }
                else
                {
                    playlist_NodeDelete( m_pPlaylist, pItem, true, false );
                }
70
            }
71 72 73
            playlist_Unlock( m_pPlaylist );

            it = it->getNextSiblingOrUncle();
74
        }
75 76
        else
        {
77
            it = getNextItem( it );
78
        }
79
    }
80 81
}

82
void Playtree::action( VarTree *pElem )
83
{
84
    playlist_Lock( m_pPlaylist );
85

86 87 88
    playlist_item_t *pItem =
        playlist_ItemGetById( m_pPlaylist, pElem->getId() );
    if( pItem )
89
    {
90 91
        playlist_Control( m_pPlaylist, PLAYLIST_VIEWPLAY,
                          pl_Locked, pItem->p_parent, pItem );
92 93
    }

94
    playlist_Unlock( m_pPlaylist );
95 96 97 98 99
}

void Playtree::onChange()
{
    buildTree();
100
    tree_update descr( tree_update::ResetAll, end() );
Clément Stenac's avatar
Clément Stenac committed
101
    notify( &descr );
102 103
}

Clément Stenac's avatar
Clément Stenac committed
104
void Playtree::onUpdateItem( int id )
105
{
106
    Iterator it = findById( id );
107
    if( it != m_children.end() )
108
    {
109
        // Update the item
110 111 112 113 114 115 116 117 118
        playlist_Lock( m_pPlaylist );
        playlist_item_t *pNode =
            playlist_ItemGetById( m_pPlaylist, it->getId() );
        if( !pNode )
        {
            playlist_Unlock( m_pPlaylist );
            return;
        }

119
        UString *pName = new UString( getIntf(), pNode->p_input->psz_name );
120
        playlist_Unlock( m_pPlaylist );
Erwan Tulou's avatar
Erwan Tulou committed
121

122 123 124 125 126 127 128 129
        if( *pName != *(it->getString()) )
        {
            it->setString( UStringPtr( pName ) );

            tree_update descr(
                tree_update::ItemUpdated, IteratorVisible( it, this ) );
            notify( &descr );
        }
130 131 132
    }
    else
    {
133
        msg_Warn( getIntf(), "cannot find node with id %d", id );
134
    }
Clément Stenac's avatar
Clément Stenac committed
135 136
}

137
void Playtree::onUpdateCurrent( bool b_active )
138
{
Erwan Tulou's avatar
Erwan Tulou committed
139
    if( b_active )
140 141
    {
        playlist_Lock( m_pPlaylist );
142

143 144 145 146 147 148 149 150
        playlist_item_t* current = playlist_CurrentPlayingItem( m_pPlaylist );
        if( !current )
        {
            playlist_Unlock( m_pPlaylist );
            return;
        }

        Iterator it = findById( current->i_id );
151 152
        if( it != m_children.end() )
        {
153
            it->setPlaying( true );
154

155 156 157 158 159
            tree_update descr(
                tree_update::ItemUpdated, IteratorVisible( it, this ) );
            notify( &descr );
        }

160
        playlist_Unlock( m_pPlaylist );
161 162 163 164 165 166 167 168 169
    }
    else
    {
        for( Iterator it = m_children.begin(); it != m_children.end();
             it = getNextItem( it ) )
        {
            if( it->isPlaying() )
            {
                it->setPlaying( false );
170

171 172 173 174 175 176
                tree_update descr(
                    tree_update::ItemUpdated, IteratorVisible( it, this ) );
                notify( &descr );
                break;
            }
        }
Erwan Tulou's avatar
Erwan Tulou committed
177
    }
178 179
}

180 181
void Playtree::onDelete( int i_id )
{
182 183
    Iterator it = findById( i_id ) ;
    if( it != m_children.end() )
184
    {
185 186 187 188 189 190
        VarTree* parent = it->parent();
        if( parent )
        {
            tree_update descr(
                tree_update::DeletingItem, IteratorVisible( it, this ) );
            notify( &descr );
191

192 193
            parent->removeChild( it );
            m_allItems.erase( i_id );
194

195 196 197 198
            tree_update descr2(
                tree_update::ItemDeleted, end() );
            notify( &descr2 );
        }
199 200 201
    }
}

Clément Stenac's avatar
Clément Stenac committed
202 203
void Playtree::onAppend( playlist_add_t *p_add )
{
204 205
    Iterator it_node = findById( p_add->i_node );
    if( it_node != m_children.end() )
Clément Stenac's avatar
Clément Stenac committed
206
    {
207
        playlist_Lock( m_pPlaylist );
208
        playlist_item_t *pItem =
Erwan Tulou's avatar
Erwan Tulou committed
209
            playlist_ItemGetById( m_pPlaylist, p_add->i_item );
210
        if( !pItem )
Clément Stenac's avatar
Clément Stenac committed
211
        {
212
            playlist_Unlock( m_pPlaylist );
213
            return;
Clément Stenac's avatar
Clément Stenac committed
214
        }
Erwan Tulou's avatar
Erwan Tulou committed
215

216 217 218 219
        int pos;
        for( pos = 0; pos < pItem->p_parent->i_children; pos++ )
            if( pItem->p_parent->pp_children[pos] == pItem ) break;

220
        UString *pName = new UString( getIntf(),
221 222 223 224 225 226 227 228 229 230
                                      pItem->p_input->psz_name );

        playlist_item_t* current = playlist_CurrentPlayingItem( m_pPlaylist );

        Iterator it = it_node->add(
            p_add->i_item, UStringPtr( pName ), false, pItem == current,
            false, pItem->i_flags & PLAYLIST_RO_FLAG, pos );

        m_allItems[pItem->i_id] = &*it;

231
        playlist_Unlock( m_pPlaylist );
Erwan Tulou's avatar
Erwan Tulou committed
232

233 234 235
        tree_update descr(
            tree_update::ItemInserted,
            IteratorVisible( it, this ) );
Erwan Tulou's avatar
Erwan Tulou committed
236
        notify( &descr );
Clément Stenac's avatar
Clément Stenac committed
237
    }
238 239 240 241
}

void Playtree::buildNode( playlist_item_t *pNode, VarTree &rTree )
{
242 243 244 245 246 247 248
    UString *pName = new UString( getIntf(), pNode->p_input->psz_name );
    Iterator it = rTree.add(
        pNode->i_id, UStringPtr( pName ), false,
        playlist_CurrentPlayingItem(m_pPlaylist) == pNode,
        false, pNode->i_flags & PLAYLIST_RO_FLAG );
    m_allItems[pNode->i_id] = &*it;

249 250
    for( int i = 0; i < pNode->i_children; i++ )
    {
251
        buildNode( pNode->pp_children[i], *it );
252 253 254 255 256 257
    }
}

void Playtree::buildTree()
{
    clear();
258
    playlist_Lock( m_pPlaylist );
259

260 261 262 263
    for( int i = 0; i < m_pPlaylist->p_root->i_children; i++ )
    {
        buildNode( m_pPlaylist->p_root->pp_children[i], *this );
    }
264

265 266
    playlist_Unlock( m_pPlaylist );
}
267

268 269 270 271 272
void Playtree::onUpdateSlider()
{
    tree_update descr( tree_update::SliderChanged, end() );
    notify( &descr );
}
273

274 275 276 277 278 279 280 281
void Playtree::insertItems( VarTree& elem, const list<string>& files, bool start )
{
    bool first = true;
    VarTree* p_elem = &elem;
    playlist_item_t* p_node = NULL;
    int i_pos = -1;

    playlist_Lock( m_pPlaylist );
282

283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
    if( p_elem->getId() == m_pPlaylist->p_local_category->i_id )
    {
        p_node = m_pPlaylist->p_local_category;
        i_pos = 0;
    }
    else if( p_elem->getId() == m_pPlaylist->p_ml_category->i_id )
    {
        p_node = m_pPlaylist->p_ml_category;
        i_pos = 0;
    }
    else if( p_elem->size() )
    {
        p_node = playlist_ItemGetById( m_pPlaylist, p_elem->getId() );
        i_pos = 0;
    }
    else
    {
        p_node = playlist_ItemGetById( m_pPlaylist,
                                       p_elem->parent()->getId() );
        i_pos = p_elem->getIndex();
        i_pos++;
    }

    if( !p_node )
        goto fin;

    for( list<string>::const_iterator it = files.begin();
         it != files.end(); ++it, i_pos++, first = false )
    {
        char* psz_uri = make_URI( it->c_str(), NULL );
        if( !psz_uri )
            continue;

        input_item_t* pItem = input_item_New( m_pPlaylist, psz_uri, NULL );
        if( pItem )
        {
            int i_mode = PLAYLIST_APPEND;
            if( first && start )
                i_mode |= PLAYLIST_GO;

            playlist_NodeAddInput( m_pPlaylist, pItem, p_node,
                                   i_mode, i_pos, pl_Locked );
        }
        free( psz_uri );
    }

fin:
330
    playlist_Unlock( m_pPlaylist );
331
}
332

333 334 335 336 337 338 339 340
VarTree::Iterator Playtree::findById( int id )
{
    map<int,VarTree*>::iterator it = m_allItems.find( id );
    if( it == m_allItems.end() )
        return m_children.end();
    else
        return it->second->getSelf();
}