/*****************************************************************************
* playtree.cpp
*****************************************************************************
- * Copyright (C) 2005 VideoLAN
- * $Id: playlist.hpp 8659 2004-09-07 21:16:49Z gbazin $
+ * Copyright (C) 2005 the VideoLAN team
+ * $Id$
*
* Authors: Antoine Cellerier <dionoea@videolan.org>
+ * Clément Stenac <zorglub@videolan.org>
+ * Erwan Tulou <erwan10@videolan.org>
*
* 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
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
-#include <vlc/vlc.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
#include "playtree.hpp"
+#include <vlc_playlist.h>
+#include <vlc_url.h>
#include "../utils/ustring.hpp"
-#include "charset.h"
-
Playtree::Playtree( intf_thread_t *pIntf )
- :VarTree( pIntf, /*m_parent = */NULL )
+ : VarTree( pIntf ), m_pPlaylist( pIntf->p_sys->p_playlist )
{
- // Get the VLC playlist object
- m_pPlaylist = pIntf->p_sys->p_playlist;
-
- // Try to guess the current charset
- char *pCharset;
- vlc_current_charset( &pCharset );
- iconvHandle = vlc_iconv_open( "UTF-8", pCharset );
- msg_Dbg( pIntf, "Using character encoding: %s", pCharset );
- free( pCharset );
-
- if( iconvHandle == (vlc_iconv_t)-1 )
- {
- msg_Warn( pIntf, "Unable to do requested conversion" );
- }
-
+ getPositionVar().addObserver( this );
buildTree();
}
Playtree::~Playtree()
{
- if( iconvHandle != (vlc_iconv_t)-1 ) vlc_iconv_close( iconvHandle );
- // TODO : check that everything is destroyed
+ getPositionVar().delObserver( this );
}
void Playtree::delSelected()
{
- // TODO
- notify();
+ for( Iterator it = m_children.begin(); it != m_children.end(); )
+ {
+ if( it->isSelected() && !it->isReadonly() )
+ {
+ playlist_Lock( m_pPlaylist );
+
+ playlist_item_t *pItem =
+ playlist_ItemGetById( m_pPlaylist, it->getId() );
+ if( pItem )
+ {
+ if( pItem->i_children == -1 )
+ {
+ playlist_DeleteFromInput( m_pPlaylist, pItem->p_input,
+ pl_Locked );
+ }
+ else
+ {
+ playlist_NodeDelete( m_pPlaylist, pItem, true, false );
+ }
+ }
+ playlist_Unlock( m_pPlaylist );
+
+ it = it->getNextSiblingOrUncle();
+ }
+ else
+ {
+ it = getNextItem( it );
+ }
+ }
}
-void Playtree::action( VarTree *pItem )
+void Playtree::action( VarTree *pElem )
{
- vlc_mutex_lock( &m_pPlaylist->object_lock );
- VarTree::Iterator it;
- if( pItem->size() )
- {
- it = pItem->begin();
- while( it->size() ) it = it->begin();
- }
- playlist_Control( m_pPlaylist,
- PLAYLIST_VIEWPLAY,
- m_pPlaylist->status.i_view,
- pItem->size()
- ? (playlist_item_t *)pItem->m_pData
- : (playlist_item_t *)pItem->parent()->m_pData,
- pItem->size()
- ? (playlist_item_t *)it->m_pData
- : (playlist_item_t *)pItem->m_pData
- );
- vlc_mutex_unlock( &m_pPlaylist->object_lock );
+ playlist_Lock( m_pPlaylist );
+
+ playlist_item_t *pItem =
+ playlist_ItemGetById( m_pPlaylist, pElem->getId() );
+ if( pItem )
+ {
+ playlist_Control( m_pPlaylist, PLAYLIST_VIEWPLAY,
+ pl_Locked, pItem->p_parent, pItem );
+ }
+
+ playlist_Unlock( m_pPlaylist );
}
void Playtree::onChange()
{
- /* FIXME : updateTree could be a nice idea so we don't have to
- * start from scratch each time the playlist changes */
buildTree();
- notify();
+ tree_update descr( tree_update::ResetAll, end() );
+ notify( &descr );
}
-void Playtree::buildNode( playlist_item_t *p_node, VarTree &m_pNode )
+void Playtree::onUpdateItem( int id )
{
- fprintf( stderr, "\e[32;1mPlaytree::buildNode\e[0m\n");
- for( int i = 0; i < p_node->i_children; i++ )
- {
- fprintf( stderr, "\e[33;1m"__FILE__ "%d :\e[0m adding playtree item : %s\n", __LINE__, p_node->pp_children[i]->input.psz_name );
- UString *pName = new UString( getIntf(), p_node->pp_children[i]->input.psz_name );
- m_pNode.add( UStringPtr( pName ),
- false,
- m_pPlaylist->status.p_item == p_node->pp_children[i],
- true,
- p_node->pp_children[i] );
- if( p_node->pp_children[i]->i_children )
+ Iterator it = findById( id );
+ if( it != m_children.end() )
+ {
+ // Update the item
+ playlist_Lock( m_pPlaylist );
+ playlist_item_t *pNode =
+ playlist_ItemGetById( m_pPlaylist, it->getId() );
+ if( !pNode )
+ {
+ playlist_Unlock( m_pPlaylist );
+ return;
+ }
+
+ char *psz_name = input_item_GetTitleFbName( pNode->p_input );
+ UString *pName = new UString( getIntf(), psz_name );
+ free(psz_name);
+ playlist_Unlock( m_pPlaylist );
+
+ if( *pName != *(it->getString()) )
{
- buildNode( p_node->pp_children[i], m_pNode.back() );
+ it->setString( UStringPtr( pName ) );
+
+ tree_update descr(
+ tree_update::ItemUpdated, IteratorVisible( it, this ) );
+ notify( &descr );
}
}
+ else
+ {
+ msg_Warn( getIntf(), "cannot find node with id %d", id );
+ }
+}
+
+void Playtree::onUpdateCurrent( bool b_active )
+{
+ if( b_active )
+ {
+ playlist_Lock( m_pPlaylist );
+
+ playlist_item_t* current = playlist_CurrentPlayingItem( m_pPlaylist );
+ if( !current )
+ {
+ playlist_Unlock( m_pPlaylist );
+ return;
+ }
+
+ Iterator it = findById( current->i_id );
+ if( it != m_children.end() )
+ {
+ it->setPlaying( true );
+
+ tree_update descr(
+ tree_update::ItemUpdated, IteratorVisible( it, this ) );
+ notify( &descr );
+ }
+
+ playlist_Unlock( m_pPlaylist );
+ }
+ else
+ {
+ for( Iterator it = m_children.begin(); it != m_children.end();
+ it = getNextItem( it ) )
+ {
+ if( it->isPlaying() )
+ {
+ it->setPlaying( false );
+
+ tree_update descr(
+ tree_update::ItemUpdated, IteratorVisible( it, this ) );
+ notify( &descr );
+ break;
+ }
+ }
+ }
+}
+
+void Playtree::onDelete( int i_id )
+{
+ Iterator it = findById( i_id ) ;
+ if( it != m_children.end() )
+ {
+ VarTree* parent = it->parent();
+ if( parent )
+ {
+ tree_update descr(
+ tree_update::DeletingItem, IteratorVisible( it, this ) );
+ notify( &descr );
+
+ parent->removeChild( it );
+ m_allItems.erase( i_id );
+
+ tree_update descr2(
+ tree_update::ItemDeleted, end() );
+ notify( &descr2 );
+ }
+ }
+}
+
+void Playtree::onAppend( playlist_add_t *p_add )
+{
+ Iterator it_node = findById( p_add->i_node );
+ if( it_node != m_children.end() )
+ {
+ playlist_Lock( m_pPlaylist );
+ playlist_item_t *pItem =
+ playlist_ItemGetById( m_pPlaylist, p_add->i_item );
+ if( !pItem )
+ {
+ playlist_Unlock( m_pPlaylist );
+ return;
+ }
+
+ int pos;
+ for( pos = 0; pos < pItem->p_parent->i_children; pos++ )
+ if( pItem->p_parent->pp_children[pos] == pItem ) break;
+
+ char *psz_name = input_item_GetTitleFbName( pItem->p_input );
+ UString *pName = new UString( getIntf(), psz_name );
+ free( 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;
+
+ playlist_Unlock( m_pPlaylist );
+
+ tree_update descr(
+ tree_update::ItemInserted,
+ IteratorVisible( it, this ) );
+ notify( &descr );
+ }
+}
+
+void Playtree::buildNode( playlist_item_t *pNode, VarTree &rTree )
+{
+ 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;
+
+ for( int i = 0; i < pNode->i_children; i++ )
+ {
+ buildNode( pNode->pp_children[i], *it );
+ }
}
void Playtree::buildTree()
{
clear();
- vlc_mutex_lock( &m_pPlaylist->object_lock );
+ playlist_Lock( m_pPlaylist );
- playlist_view_t *p_view;
- p_view = playlist_ViewFind( m_pPlaylist, VIEW_CATEGORY );
- /* TODO : let the user chose the view type */
+ for( int i = 0; i < m_pPlaylist->p_root->i_children; i++ )
+ {
+ buildNode( m_pPlaylist->p_root->pp_children[i], *this );
+ }
- clear();
- /* XXX : do we need Playlist::clear() instead of VarTree::clear() ? */
+ playlist_Unlock( m_pPlaylist );
+}
+
+void Playtree::onUpdateSlider()
+{
+ tree_update descr( tree_update::SliderChanged, end() );
+ notify( &descr );
+}
+
+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;
- /* Set the root's name */
- UString *pName = new UString( getIntf(), p_view->p_root->input.psz_name );
- m_cString = UStringPtr( pName );
+ playlist_Lock( m_pPlaylist );
- buildNode( p_view->p_root, *this );
+ if( p_elem == this )
+ {
+ for( Iterator it = m_children.begin(); it != m_children.end(); ++it )
+ {
+ if( it->getId() == m_pPlaylist->p_local_category->i_id )
+ {
+ p_elem = &*it;
+ break;
+ }
+ }
+ }
+
+ if( p_elem->getId() == m_pPlaylist->p_local_category->i_id )
+ {
+ p_node = m_pPlaylist->p_local_category;
+ i_pos = 0;
+ p_elem->setExpanded( true );
+ }
+ else if( p_elem->getId() == m_pPlaylist->p_ml_category->i_id )
+ {
+ p_node = m_pPlaylist->p_ml_category;
+ i_pos = 0;
+ p_elem->setExpanded( true );
+ }
+ else if( p_elem->size() && p_elem->isExpanded() )
+ {
+ 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++;
+ }
- vlc_mutex_unlock( &m_pPlaylist->object_lock );
- checkParents( NULL );
+ if( !p_node )
+ goto fin;
+
+ for( list<string>::const_iterator it = files.begin();
+ it != files.end(); ++it, i_pos++, first = false )
+ {
+ input_item_t *pItem;
+
+ if( strstr( it->c_str(), "://" ) )
+ pItem = input_item_New( it->c_str(), NULL );
+ else
+ {
+ char *psz_uri = vlc_path2uri( it->c_str(), NULL );
+ if( psz_uri == NULL )
+ continue;
+ pItem = input_item_New( psz_uri, NULL );
+ free( psz_uri );
+ }
+
+ if( pItem == NULL)
+ continue;
+
+ 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 );
+ }
+
+fin:
+ playlist_Unlock( m_pPlaylist );
+}
+
+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();
}