1 /*****************************************************************************
2 * item.c : Playlist item functions
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: item.c,v 1.3 2003/11/23 16:24:20 garf Exp $
7 * Authors: Samuel Hocevar <sam@zoy.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
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 General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
23 #include <stdlib.h> /* free(), strtol() */
24 #include <stdio.h> /* sprintf() */
25 #include <string.h> /* strerror() */
31 #include "vlc_playlist.h"
34 * Add an MRL to the playlist. This is a simplified version of
35 * playlist_AddExt inculded for convenince. It equals calling playlist_AddExt
36 * with psz_name == psz_target and i_duration == -1
39 int playlist_Add( playlist_t *p_playlist, const char *psz_target,
40 const char **ppsz_options, int i_options,
41 int i_mode, int i_pos )
43 return playlist_AddExt( p_playlist, psz_target, psz_target, -1,
44 ppsz_options, i_options, i_mode, i_pos );
48 * Add a MRL into the playlist.
50 * \param p_playlist the playlist to add into
51 * \param psz_uri the mrl to add to the playlist
52 * \param psz_name a text giving a name or description of this item
53 * \param i_duration a hint about the duration of this item, in miliseconds, or
55 * \param ppsz_options array of options
56 * \param i_options number of items in ppsz_options
57 * \param i_mode the mode used when adding
58 * \param i_pos the position in the playlist where to add. If this is
59 * PLAYLIST_END the item will be added at the end of the playlist
60 * regardless of it's size
61 * \return always returns 0
63 int playlist_AddExt( playlist_t *p_playlist, const char * psz_uri,
64 const char * psz_name, mtime_t i_duration,
65 const char **ppsz_options, int i_options, int i_mode,
68 playlist_item_t * p_item;
70 p_item = malloc( sizeof( playlist_item_t ) );
73 msg_Err( p_playlist, "out of memory" );
76 p_item->psz_name = strdup( psz_name );
77 p_item->psz_uri = strdup( psz_uri );
78 p_item->psz_author = strdup( "" );
79 p_item->i_duration = i_duration;
82 p_item->b_autodeletion = VLC_FALSE;
83 p_item->b_enabled = VLC_TRUE;
84 p_item->i_group = PLAYLIST_TYPE_MANUAL;
86 p_item->ppsz_options = NULL;
87 p_item->i_options = i_options;
93 p_item->ppsz_options = (char **)malloc( i_options * sizeof(char *) );
94 for( i = 0; i < i_options; i++ )
95 p_item->ppsz_options[i] = strdup( ppsz_options[i] );
99 return playlist_AddItem( p_playlist, p_item, i_mode, i_pos );
103 * Add a playlist item into a playlist
105 * \param p_playlist the playlist to insert into
106 * \param p_item the playlist item to insert
107 * \param i_mode the mode used when adding
108 * \param i_pos the possition in the playlist where to add. If this is
109 * PLAYLIST_END the item will be added at the end of the playlist
110 * regardless of it's size
111 * \return always returns 0
113 int playlist_AddItem( playlist_t *p_playlist, playlist_item_t * p_item,
114 int i_mode, int i_pos)
118 vlc_mutex_lock( &p_playlist->object_lock );
121 * CHECK_INSERT : checks if the item is already enqued before
124 if ( i_mode & PLAYLIST_CHECK_INSERT )
128 if ( p_playlist->pp_items )
130 for ( j = 0; j < p_playlist->i_size; j++ )
132 if ( !strcmp( p_playlist->pp_items[j]->psz_uri, p_item->psz_uri ) )
134 if( p_item->psz_name )
136 free( p_item->psz_name );
138 if( p_item->psz_uri )
140 free( p_item->psz_uri );
142 if( p_item->i_options )
145 for( i_opt = 0; i_opt < p_item->i_options; i_opt++ )
147 free( p_item->ppsz_options[i_opt] );
149 free( p_item->ppsz_options );
151 if( p_item->psz_author )
153 free( p_item->psz_author );
156 vlc_mutex_unlock( &p_playlist->object_lock );
161 i_mode &= ~PLAYLIST_CHECK_INSERT;
162 i_mode |= PLAYLIST_APPEND;
166 msg_Dbg( p_playlist, "adding playlist item « %s » ( %s )", p_item->psz_name, p_item->psz_uri);
168 /* Create the new playlist item */
171 /* Do a few boundary checks and allocate space for the item */
172 if( i_pos == PLAYLIST_END )
174 if( i_mode & PLAYLIST_INSERT )
176 i_mode &= ~PLAYLIST_INSERT;
177 i_mode |= PLAYLIST_APPEND;
180 i_pos = p_playlist->i_size - 1;
183 if( !(i_mode & PLAYLIST_REPLACE)
184 || i_pos < 0 || i_pos >= p_playlist->i_size )
186 /* Additional boundary checks */
187 if( i_mode & PLAYLIST_APPEND )
196 else if( i_pos > p_playlist->i_size )
198 i_pos = p_playlist->i_size;
201 INSERT_ELEM( p_playlist->pp_items,
205 p_playlist->i_enabled ++;
207 if( p_playlist->i_index >= i_pos )
209 p_playlist->i_index++;
214 /* i_mode == PLAYLIST_REPLACE and 0 <= i_pos < p_playlist->i_size */
215 if( p_playlist->pp_items[i_pos]->psz_name )
217 free( p_playlist->pp_items[i_pos]->psz_name );
219 if( p_playlist->pp_items[i_pos]->psz_uri )
221 free( p_playlist->pp_items[i_pos]->psz_uri );
223 /* XXX: what if the item is still in use? */
224 free( p_playlist->pp_items[i_pos] );
225 p_playlist->pp_items[i_pos] = p_item;
228 if( i_mode & PLAYLIST_GO )
230 p_playlist->i_index = i_pos;
231 if( p_playlist->p_input )
233 input_StopThread( p_playlist->p_input );
235 p_playlist->i_status = PLAYLIST_RUNNING;
238 vlc_mutex_unlock( &p_playlist->object_lock );
240 val.b_bool = VLC_TRUE;
241 var_Set( p_playlist, "intf-change", val );
247 * delete an item from a playlist.
249 * \param p_playlist the playlist to remove from.
250 * \param i_pos the position of the item to remove
253 int playlist_Delete( playlist_t * p_playlist, int i_pos )
256 vlc_mutex_lock( &p_playlist->object_lock );
258 /* if i_pos is the current played item, playlist should stop playing it */
259 if( ( p_playlist->i_status == PLAYLIST_RUNNING) && (p_playlist->i_index == i_pos) )
261 playlist_Command( p_playlist, PLAYLIST_STOP, 0 );
264 if( i_pos >= 0 && i_pos < p_playlist->i_size )
266 msg_Dbg( p_playlist, "deleting playlist item « %s »",
267 p_playlist->pp_items[i_pos]->psz_name );
269 if( p_playlist->pp_items[i_pos]->psz_name )
271 free( p_playlist->pp_items[i_pos]->psz_name );
273 if( p_playlist->pp_items[i_pos]->psz_uri )
275 free( p_playlist->pp_items[i_pos]->psz_uri );
277 if( p_playlist->pp_items[i_pos]->psz_author )
279 free( p_playlist->pp_items[i_pos]->psz_author );
281 if( p_playlist->pp_items[i_pos]->i_options )
285 for( i = 0; i < p_playlist->pp_items[i_pos]->i_options; i++ )
286 free( p_playlist->pp_items[i_pos]->ppsz_options[i] );
288 free( p_playlist->pp_items[i_pos]->ppsz_options );
291 /* XXX: what if the item is still in use? */
292 free( p_playlist->pp_items[i_pos] );
294 if( i_pos <= p_playlist->i_index )
296 p_playlist->i_index--;
299 /* Renumber the playlist */
300 REMOVE_ELEM( p_playlist->pp_items,
303 if( p_playlist->i_enabled > 0 )
304 p_playlist->i_enabled--;
307 vlc_mutex_unlock( &p_playlist->object_lock );
309 val.b_bool = VLC_TRUE;
310 var_Set( p_playlist, "intf-change", val );
316 * Disables a playlist item
318 * \param p_playlist the playlist to disable from.
319 * \param i_pos the position of the item to disable
322 int playlist_Disable( playlist_t * p_playlist, int i_pos )
325 vlc_mutex_lock( &p_playlist->object_lock );
328 if( i_pos >= 0 && i_pos < p_playlist->i_size )
330 msg_Dbg( p_playlist, "disabling playlist item « %s »",
331 p_playlist->pp_items[i_pos]->psz_name );
333 if( p_playlist->pp_items[i_pos]->b_enabled == VLC_TRUE )
334 p_playlist->i_enabled--;
335 p_playlist->pp_items[i_pos]->b_enabled = VLC_FALSE;
338 vlc_mutex_unlock( &p_playlist->object_lock );
340 val.b_bool = VLC_TRUE;
341 var_Set( p_playlist, "intf-change", val );
347 * Enables a playlist item
349 * \param p_playlist the playlist to enable from.
350 * \param i_pos the position of the item to enable
353 int playlist_Enable( playlist_t * p_playlist, int i_pos )
356 vlc_mutex_lock( &p_playlist->object_lock );
358 if( i_pos >= 0 && i_pos < p_playlist->i_size )
360 msg_Dbg( p_playlist, "enabling playlist item « %s »",
361 p_playlist->pp_items[i_pos]->psz_name );
363 if( p_playlist->pp_items[i_pos]->b_enabled == VLC_FALSE )
364 p_playlist->i_enabled++;
366 p_playlist->pp_items[i_pos]->b_enabled = VLC_TRUE;
369 vlc_mutex_unlock( &p_playlist->object_lock );
371 val.b_bool = VLC_TRUE;
372 var_Set( p_playlist, "intf-change", val );
378 * Disables a playlist group
380 * \param p_playlist the playlist to disable from.
381 * \param i_pos the id of the group to disable
384 int playlist_DisableGroup( playlist_t * p_playlist, int i_group)
388 vlc_mutex_lock( &p_playlist->object_lock );
390 msg_Dbg(p_playlist,"Disabling group %i",i_group);
391 for( i = 0 ; i< p_playlist->i_size; i++ )
393 if( p_playlist->pp_items[i]->i_group == i_group )
395 msg_Dbg( p_playlist, "disabling playlist item « %s »",
396 p_playlist->pp_items[i]->psz_name );
398 if( p_playlist->pp_items[i]->b_enabled == VLC_TRUE )
399 p_playlist->i_enabled--;
401 p_playlist->pp_items[i]->b_enabled = VLC_FALSE;
404 vlc_mutex_unlock( &p_playlist->object_lock );
406 val.b_bool = VLC_TRUE;
407 var_Set( p_playlist, "intf-change", val );
413 * Enables a playlist group
415 * \param p_playlist the playlist to enable from.
416 * \param i_pos the id of the group to enable
419 int playlist_EnableGroup( playlist_t * p_playlist, int i_group)
423 vlc_mutex_lock( &p_playlist->object_lock );
425 for( i = 0 ; i< p_playlist->i_size; i++ )
427 if( p_playlist->pp_items[i]->i_group == i_group )
429 msg_Dbg( p_playlist, "enabling playlist item « %s »",
430 p_playlist->pp_items[i]->psz_name );
432 if( p_playlist->pp_items[i]->b_enabled == VLC_FALSE )
433 p_playlist->i_enabled++;
435 p_playlist->pp_items[i]->b_enabled = VLC_TRUE;
438 vlc_mutex_unlock( &p_playlist->object_lock );
440 val.b_bool = VLC_TRUE;
441 var_Set( p_playlist, "intf-change", val );
447 * Move an item in a playlist
449 * Move the item in the playlist with position i_pos before the current item
450 * at position i_newpos.
451 * \param p_playlist the playlist to move items in
452 * \param i_pos the position of the item to move
453 * \param i_newpos the position of the item that will be behind the moved item
457 int playlist_Move( playlist_t * p_playlist, int i_pos, int i_newpos)
460 vlc_mutex_lock( &p_playlist->object_lock );
462 /* take into account that our own row disappears. */
463 if ( i_pos < i_newpos ) i_newpos--;
465 if( i_pos >= 0 && i_newpos >=0 && i_pos <= p_playlist->i_size
466 && i_newpos <= p_playlist->i_size )
468 playlist_item_t * temp;
470 msg_Dbg( p_playlist, "moving playlist item « %s » (%i -> %i)",
471 p_playlist->pp_items[i_pos]->psz_name, i_pos,
474 if( i_pos == p_playlist->i_index )
476 p_playlist->i_index = i_newpos;
478 else if( i_pos > p_playlist->i_index && i_newpos <= p_playlist->i_index )
480 p_playlist->i_index++;
482 else if( i_pos < p_playlist->i_index && i_newpos >= p_playlist->i_index )
484 p_playlist->i_index--;
487 if ( i_pos < i_newpos )
489 temp = p_playlist->pp_items[i_pos];
490 while ( i_pos < i_newpos )
492 p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos+1];
495 p_playlist->pp_items[i_newpos] = temp;
497 else if ( i_pos > i_newpos )
499 temp = p_playlist->pp_items[i_pos];
500 while ( i_pos > i_newpos )
502 p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos-1];
505 p_playlist->pp_items[i_newpos] = temp;
509 vlc_mutex_unlock( &p_playlist->object_lock );
511 val.b_bool = VLC_TRUE;
512 var_Set( p_playlist, "intf-change", val );