contrib: rav1e: update to v0.4.1
[vlc.git] / modules / gui / skins2 / vars / playtree.cpp
1 /*****************************************************************************
2  * playtree.cpp
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
5  *
6  * Authors: Antoine Cellerier <dionoea@videolan.org>
7  *          ClĂ©ment Stenac <zorglub@videolan.org>
8  *          Erwan Tulou    <erwan10@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <vlc_common.h>
30
31 #include "playtree.hpp"
32 #include <vlc_playlist.h>
33 #include <vlc_input_item.h>
34 #include <vlc_url.h>
35 #include "../utils/ustring.hpp"
36
37 Playtree::Playtree( intf_thread_t *pIntf )
38     : VarTree( pIntf ), m_currentIndex( -1 )
39 {
40     getPositionVar().addObserver( this );
41     buildTree();
42 }
43
44 Playtree::~Playtree()
45 {
46     getPositionVar().delObserver( this );
47 }
48
49 void Playtree::delSelected()
50 {
51     for( Iterator it = m_children.begin(); it != m_children.end(); )
52     {
53         if( it->isSelected() && !it->isReadonly() )
54         {
55             vlc_playlist_Lock( getPL() );
56             ssize_t idx = vlc_playlist_IndexOfMedia( getPL(), it->getMedia() );
57             if( idx != -1 )
58                 vlc_playlist_Remove( getPL(), idx, 1 ),
59             vlc_playlist_Unlock( getPL() );
60
61             it = it->getNextSiblingOrUncle();
62         }
63         else
64         {
65             it = getNextItem( it );
66         }
67     }
68 }
69
70 void Playtree::action( VarTree *pElem )
71 {
72     if( !pElem->getMedia() )
73         return;
74     vlc_playlist_Lock( getPL() );
75     ssize_t idx = vlc_playlist_IndexOfMedia( getPL(), pElem->getMedia() );
76     if( idx != -1 )
77         vlc_playlist_PlayAt( getPL(), idx );
78     vlc_playlist_Unlock( getPL() );
79 }
80
81 void Playtree::onChange()
82 {
83     buildTree();
84     tree_update descr( tree_update::ResetAll, end() );
85     notify( &descr );
86 }
87
88 void Playtree::onUpdateItem( int pos )
89 {
90     Iterator it = getPlaylistIt( pos  );
91     if( it != m_children.end() )
92     {
93         vlc_playlist_Lock( getPL() );
94         vlc_playlist_item_t *item = vlc_playlist_Get( getPL(), pos );
95         input_item_t* media = vlc_playlist_item_GetMedia( item ) ;
96         if( media != it->getMedia() )
97             it->setMedia( media );
98         vlc_playlist_Unlock( getPL() );
99
100         bool updateNeeded = false;
101
102         bool isPlaying = (pos == m_currentIndex);
103         if( it->isPlaying() != isPlaying )
104         {
105             it->setPlaying( isPlaying );
106             updateNeeded = true;
107         }
108
109         UString *pName = getTitle( media );
110         if( *pName != *(it->getString()) )
111         {
112             it->setString( UStringPtr( pName ) );
113             updateNeeded = true;
114         }
115         else
116         {
117             delete pName;
118         }
119
120         if( updateNeeded )
121         {
122             tree_update descr(
123                 tree_update::ItemUpdated, IteratorVisible( it, this ) );
124             notify( &descr );
125         }
126     }
127 }
128
129 void Playtree::onUpdatePlaying( int pos )
130 {
131     if( m_currentIndex != -1 && m_currentIndex != pos )
132     {
133         // de-highlight previous item
134         Iterator it = getPlaylistIt( m_currentIndex );
135         it->setPlaying( false );
136
137         tree_update descr(
138             tree_update::ItemUpdated, IteratorVisible( it, this ) );
139         notify( &descr );
140     }
141     m_currentIndex = pos;
142     if( m_currentIndex != -1 )
143     {
144         // highlight new item
145         Iterator it = getPlaylistIt( m_currentIndex );
146         it->setPlaying( true );
147
148         tree_update descr(
149             tree_update::ItemUpdated, IteratorVisible( it, this ) );
150         notify( &descr );
151     }
152 }
153
154 void Playtree::onDelete( int pos )
155 {
156     Iterator it = getPlaylistIt( pos );
157     if( it != m_children.end() )
158     {
159         VarTree* parent = it->parent();
160         if( parent )
161         {
162             tree_update descr(
163                 tree_update::DeletingItem, IteratorVisible( it, this ) );
164             notify( &descr );
165
166             parent->removeChild( it );
167
168             tree_update descr2(
169                 tree_update::ItemDeleted, end() );
170             notify( &descr2 );
171         }
172     }
173 }
174
175 void Playtree::onAppend( int pos )
176 {
177     Iterator it_node = m_children.begin();
178     it_node->setExpanded( true );
179
180     vlc_playlist_Lock( getPL() );
181     vlc_playlist_item_t *item = vlc_playlist_Get( getPL(), pos );
182     input_item_t* media = vlc_playlist_item_GetMedia( item ) ;
183     bool isPlaying = pos == vlc_playlist_GetCurrentIndex( getPL() );
184     vlc_playlist_Unlock( getPL() );
185
186     UString *pName = getTitle( media );
187     Iterator it = it_node->add( media, UStringPtr( pName ),
188                                 false, isPlaying, false, false, pos );
189
190     tree_update descr( tree_update::ItemInserted,
191                        IteratorVisible( it, this ) );
192     notify( &descr );
193 }
194
195 void Playtree::buildNode( int pos, VarTree &rTree )
196 {
197     vlc_playlist_item_t *item = vlc_playlist_Get( getPL(), pos );
198     input_item_t *media = vlc_playlist_item_GetMedia( item );
199     UString *pName = getTitle( media );
200     bool isPlaying = pos == vlc_playlist_GetCurrentIndex(getPL());
201     (void)rTree.add( media, UStringPtr( pName ),
202                      false, isPlaying, false, false, -1 );
203 }
204
205 void Playtree::buildTree()
206 {
207     clear();
208
209     // build playlist entry
210     UString *pName = new UString( getIntf(), _( "Playlist" ) );
211     Iterator it = add( NULL, UStringPtr( pName ),
212                        false, false, false, false, -1 );
213
214     vlc_playlist_Lock( getPL() );
215     size_t count = vlc_playlist_Count( getPL() );
216     for( size_t pos = 0; pos < count; pos++ )
217     {
218         if( pos == 0 )
219             it->setExpanded( true );
220         buildNode( pos , *it );
221     }
222     vlc_playlist_Unlock( getPL() );
223 }
224
225 void Playtree::onUpdateSlider()
226 {
227     tree_update descr( tree_update::SliderChanged, end() );
228     notify( &descr );
229 }
230
231 void Playtree::insertItems( VarTree& elem, const std::list<std::string>& files, bool start )
232 {
233     bool first = start;
234     VarTree* p_elem = &elem;
235     VarTree* pNode = NULL;
236     int i_pos = -1;
237
238     if( p_elem == this )
239         p_elem = &*getPlaylistIt();
240
241     if( p_elem == &*getPlaylistIt() )
242     {
243         pNode = p_elem;
244         i_pos = 0;
245         p_elem->setExpanded( true );
246     }
247     else
248     if( p_elem->size() && p_elem->isExpanded() )
249     {
250         pNode = p_elem;
251         i_pos = 0;
252     }
253     else
254     {
255         pNode = p_elem->parent() ? p_elem->parent() : p_elem;
256         i_pos = p_elem->getIndex();
257         i_pos++;
258     }
259
260     assert( pNode != NULL );
261
262     vlc_playlist_Lock( getPL() );
263     for( std::list<std::string>::const_iterator it = files.begin();
264          it != files.end(); ++it, i_pos++ )
265     {
266         input_item_t *pItem;
267
268         if( strstr( it->c_str(), "://" ) )
269             pItem = input_item_New( it->c_str(), NULL );
270         else
271         {
272             char *psz_uri = vlc_path2uri( it->c_str(), NULL );
273             if( psz_uri == NULL )
274                 continue;
275             pItem = input_item_New( psz_uri, NULL );
276             free( psz_uri );
277         }
278
279         if( pItem == NULL)
280             continue;
281
282         vlc_playlist_Insert( getPL(),i_pos, &pItem, 1 );
283         if( first )
284         {
285             first = false;
286             vlc_playlist_PlayAt( getPL(),i_pos );
287         }
288     }
289     vlc_playlist_Unlock( getPL() );
290
291 }
292
293 UString* Playtree::getTitle( input_item_t *pItem )
294 {
295     char *psz_name = input_item_GetTitleFbName( pItem );
296     UString *pTitle = new UString( getIntf(), psz_name );
297     free( psz_name );
298     return pTitle;
299 }
300
301 VarTree::Iterator Playtree::getPlaylistIt( int pos )
302 {
303     // Playlist Node
304     Iterator it = m_children.begin();
305     if( pos == -1 )
306         return it;
307
308     // first playlist item  (pos=0)
309     it = getNextItem( it );
310     for( int i = 0; i < pos; i++ )
311         it = getNextItem( it );
312     return it;
313 }