1 /*****************************************************************************
2 * item.c : Playlist item functions
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: item.c,v 1.8 2003/12/05 02:12:53 rocky 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() */
30 #include <vlc/input.h>
32 #include "vlc_playlist.h"
35 * Add an MRL to the playlist. This is a simplified version of
36 * playlist_AddExt inculded for convenince. It equals calling playlist_AddExt
37 * with psz_name == psz_target and i_duration == -1
40 int playlist_Add( playlist_t *p_playlist, const char *psz_target,
41 const char **ppsz_options, int i_options,
42 int i_mode, int i_pos )
44 return playlist_AddExt( p_playlist, psz_target, psz_target, -1,
45 ppsz_options, i_options, i_mode, i_pos );
49 * Add a MRL into the playlist.
51 * \param p_playlist the playlist to add into
52 * \param psz_uri the mrl to add to the playlist
53 * \param psz_name a text giving a name or description of this item
54 * \param i_duration a hint about the duration of this item, in microseconds,
56 * \param ppsz_options array of options
57 * \param i_options number of items in ppsz_options
58 * \param i_mode the mode used when adding
59 * \param i_pos the position in the playlist where to add. If this is
60 * PLAYLIST_END the item will be added at the end of the playlist
61 * regardless of it's size
62 * \return always returns 0
64 int playlist_AddExt( playlist_t *p_playlist, const char * psz_uri,
65 const char * psz_name, mtime_t i_duration,
66 const char **ppsz_options, int i_options, int i_mode,
69 playlist_item_t * p_item;
71 p_item = malloc( sizeof( playlist_item_t ) );
74 msg_Err( p_playlist, "out of memory" );
77 p_item->psz_name = strdup( psz_name );
78 p_item->psz_uri = strdup( psz_uri );
79 p_item->psz_author = strdup( "" );
80 p_item->i_duration = i_duration;
83 p_item->b_autodeletion = VLC_FALSE;
84 p_item->b_enabled = VLC_TRUE;
85 p_item->i_group = PLAYLIST_TYPE_MANUAL;
87 p_item->ppsz_options = NULL;
88 p_item->i_options = i_options;
94 p_item->ppsz_options = malloc( i_options * sizeof(char *) );
95 for( i = 0; i < i_options; i++ )
97 p_item->ppsz_options[i] = strdup( ppsz_options[i] );
102 return playlist_AddItem( p_playlist, p_item, i_mode, i_pos );
106 * Add a playlist item into a playlist
108 * \param p_playlist the playlist to insert into
109 * \param p_item the playlist item to insert
110 * \param i_mode the mode used when adding
111 * \param i_pos the possition in the playlist where to add. If this is
112 * PLAYLIST_END the item will be added at the end of the playlist
113 * regardless of it's size
114 * \return always returns 0
116 int playlist_AddItem( playlist_t *p_playlist, playlist_item_t * p_item,
117 int i_mode, int i_pos)
121 vlc_mutex_lock( &p_playlist->object_lock );
124 * CHECK_INSERT : checks if the item is already enqued before
127 if ( i_mode & PLAYLIST_CHECK_INSERT )
131 if ( p_playlist->pp_items )
133 for ( j = 0; j < p_playlist->i_size; j++ )
135 if ( !strcmp( p_playlist->pp_items[j]->psz_uri, p_item->psz_uri ) )
137 if( p_item->psz_name )
139 free( p_item->psz_name );
141 if( p_item->psz_uri )
143 free( p_item->psz_uri );
145 if( p_item->i_options )
148 for( i_opt = 0; i_opt < p_item->i_options; i_opt++ )
150 free( p_item->ppsz_options[i_opt] );
152 free( p_item->ppsz_options );
154 if( p_item->psz_author )
156 free( p_item->psz_author );
159 vlc_mutex_unlock( &p_playlist->object_lock );
164 i_mode &= ~PLAYLIST_CHECK_INSERT;
165 i_mode |= PLAYLIST_APPEND;
169 msg_Dbg( p_playlist, "adding playlist item « %s » ( %s )", p_item->psz_name, p_item->psz_uri);
171 /* Create the new playlist item */
174 /* Do a few boundary checks and allocate space for the item */
175 if( i_pos == PLAYLIST_END )
177 if( i_mode & PLAYLIST_INSERT )
179 i_mode &= ~PLAYLIST_INSERT;
180 i_mode |= PLAYLIST_APPEND;
183 i_pos = p_playlist->i_size - 1;
186 if( !(i_mode & PLAYLIST_REPLACE)
187 || i_pos < 0 || i_pos >= p_playlist->i_size )
189 /* Additional boundary checks */
190 if( i_mode & PLAYLIST_APPEND )
199 else if( i_pos > p_playlist->i_size )
201 i_pos = p_playlist->i_size;
204 INSERT_ELEM( p_playlist->pp_items,
208 p_playlist->i_enabled ++;
210 if( p_playlist->i_index >= i_pos )
212 p_playlist->i_index++;
217 /* i_mode == PLAYLIST_REPLACE and 0 <= i_pos < p_playlist->i_size */
218 if( p_playlist->pp_items[i_pos]->psz_name )
220 free( p_playlist->pp_items[i_pos]->psz_name );
222 if( p_playlist->pp_items[i_pos]->psz_uri )
224 free( p_playlist->pp_items[i_pos]->psz_uri );
226 if( p_playlist->pp_items[i_pos]->psz_author )
228 free( p_playlist->pp_items[i_pos]->psz_author );
230 /* XXX: what if the item is still in use? */
231 free( p_playlist->pp_items[i_pos] );
232 p_playlist->pp_items[i_pos] = p_item;
235 if( i_mode & PLAYLIST_GO )
237 p_playlist->i_index = i_pos;
238 if( p_playlist->p_input )
240 input_StopThread( p_playlist->p_input );
242 p_playlist->i_status = PLAYLIST_RUNNING;
245 vlc_mutex_unlock( &p_playlist->object_lock );
247 val.b_bool = VLC_TRUE;
248 var_Set( p_playlist, "intf-change", val );
254 * delete an item from a playlist.
256 * \param p_playlist the playlist to remove from.
257 * \param i_pos the position of the item to remove
260 int playlist_Delete( playlist_t * p_playlist, int i_pos )
264 /* if i_pos is the current played item, playlist should stop playing it */
265 if( ( p_playlist->i_status == PLAYLIST_RUNNING) && (p_playlist->i_index == i_pos) )
267 playlist_Command( p_playlist, PLAYLIST_STOP, 0 );
270 vlc_mutex_lock( &p_playlist->object_lock );
271 if( i_pos >= 0 && i_pos < p_playlist->i_size )
273 playlist_item_t *p_item = p_playlist->pp_items[i_pos];
275 msg_Dbg( p_playlist, "deleting playlist item « %s »",
278 if( p_item->psz_name )
280 free( p_item->psz_name );
282 if( p_item->psz_uri )
284 free( p_item->psz_uri );
286 if( p_item->psz_author )
288 free( p_item->psz_author );
290 if( p_item->i_options > 0 )
294 for( i = 0; i < p_item->i_options; i++ )
296 free( p_item->ppsz_options[i] );
299 free( p_item->ppsz_options );
302 /* XXX: what if the item is still in use? */
305 if( i_pos <= p_playlist->i_index )
307 p_playlist->i_index--;
310 /* Renumber the playlist */
311 REMOVE_ELEM( p_playlist->pp_items,
314 if( p_playlist->i_enabled > 0 )
315 p_playlist->i_enabled--;
318 vlc_mutex_unlock( &p_playlist->object_lock );
320 val.b_bool = VLC_TRUE;
321 var_Set( p_playlist, "intf-change", val );
327 * Disables a playlist item
329 * \param p_playlist the playlist to disable from.
330 * \param i_pos the position of the item to disable
333 int playlist_Disable( playlist_t * p_playlist, int i_pos )
336 vlc_mutex_lock( &p_playlist->object_lock );
339 if( i_pos >= 0 && i_pos < p_playlist->i_size )
341 msg_Dbg( p_playlist, "disabling playlist item « %s »",
342 p_playlist->pp_items[i_pos]->psz_name );
344 if( p_playlist->pp_items[i_pos]->b_enabled == VLC_TRUE )
345 p_playlist->i_enabled--;
346 p_playlist->pp_items[i_pos]->b_enabled = VLC_FALSE;
349 vlc_mutex_unlock( &p_playlist->object_lock );
351 val.b_bool = VLC_TRUE;
352 var_Set( p_playlist, "intf-change", val );
358 * Enables a playlist item
360 * \param p_playlist the playlist to enable from.
361 * \param i_pos the position of the item to enable
364 int playlist_Enable( playlist_t * p_playlist, int i_pos )
367 vlc_mutex_lock( &p_playlist->object_lock );
369 if( i_pos >= 0 && i_pos < p_playlist->i_size )
371 msg_Dbg( p_playlist, "enabling playlist item « %s »",
372 p_playlist->pp_items[i_pos]->psz_name );
374 if( p_playlist->pp_items[i_pos]->b_enabled == VLC_FALSE )
375 p_playlist->i_enabled++;
377 p_playlist->pp_items[i_pos]->b_enabled = VLC_TRUE;
380 vlc_mutex_unlock( &p_playlist->object_lock );
382 val.b_bool = VLC_TRUE;
383 var_Set( p_playlist, "intf-change", val );
389 * Disables a playlist group
391 * \param p_playlist the playlist to disable from.
392 * \param i_pos the id of the group to disable
395 int playlist_DisableGroup( playlist_t * p_playlist, int i_group)
399 vlc_mutex_lock( &p_playlist->object_lock );
401 msg_Dbg(p_playlist,"Disabling group %i",i_group);
402 for( i = 0 ; i< p_playlist->i_size; i++ )
404 if( p_playlist->pp_items[i]->i_group == i_group )
406 msg_Dbg( p_playlist, "disabling playlist item « %s »",
407 p_playlist->pp_items[i]->psz_name );
409 if( p_playlist->pp_items[i]->b_enabled == VLC_TRUE )
410 p_playlist->i_enabled--;
412 p_playlist->pp_items[i]->b_enabled = VLC_FALSE;
415 vlc_mutex_unlock( &p_playlist->object_lock );
417 val.b_bool = VLC_TRUE;
418 var_Set( p_playlist, "intf-change", val );
424 * Enables a playlist group
426 * \param p_playlist the playlist to enable from.
427 * \param i_pos the id of the group to enable
430 int playlist_EnableGroup( playlist_t * p_playlist, int i_group)
434 vlc_mutex_lock( &p_playlist->object_lock );
436 for( i = 0 ; i< p_playlist->i_size; i++ )
438 if( p_playlist->pp_items[i]->i_group == i_group )
440 msg_Dbg( p_playlist, "enabling playlist item « %s »",
441 p_playlist->pp_items[i]->psz_name );
443 if( p_playlist->pp_items[i]->b_enabled == VLC_FALSE )
444 p_playlist->i_enabled++;
446 p_playlist->pp_items[i]->b_enabled = VLC_TRUE;
449 vlc_mutex_unlock( &p_playlist->object_lock );
451 val.b_bool = VLC_TRUE;
452 var_Set( p_playlist, "intf-change", val );
458 * Move an item in a playlist
460 * Move the item in the playlist with position i_pos before the current item
461 * at position i_newpos.
462 * \param p_playlist the playlist to move items in
463 * \param i_pos the position of the item to move
464 * \param i_newpos the position of the item that will be behind the moved item
468 int playlist_Move( playlist_t * p_playlist, int i_pos, int i_newpos)
471 vlc_mutex_lock( &p_playlist->object_lock );
473 /* take into account that our own row disappears. */
474 if ( i_pos < i_newpos ) i_newpos--;
476 if( i_pos >= 0 && i_newpos >=0 && i_pos <= p_playlist->i_size
477 && i_newpos <= p_playlist->i_size )
479 playlist_item_t * temp;
481 msg_Dbg( p_playlist, "moving playlist item « %s » (%i -> %i)",
482 p_playlist->pp_items[i_pos]->psz_name, i_pos,
485 if( i_pos == p_playlist->i_index )
487 p_playlist->i_index = i_newpos;
489 else if( i_pos > p_playlist->i_index && i_newpos <= p_playlist->i_index )
491 p_playlist->i_index++;
493 else if( i_pos < p_playlist->i_index && i_newpos >= p_playlist->i_index )
495 p_playlist->i_index--;
498 if ( i_pos < i_newpos )
500 temp = p_playlist->pp_items[i_pos];
501 while ( i_pos < i_newpos )
503 p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos+1];
506 p_playlist->pp_items[i_newpos] = temp;
508 else if ( i_pos > i_newpos )
510 temp = p_playlist->pp_items[i_pos];
511 while ( i_pos > i_newpos )
513 p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos-1];
516 p_playlist->pp_items[i_newpos] = temp;
520 vlc_mutex_unlock( &p_playlist->object_lock );
522 val.b_bool = VLC_TRUE;
523 var_Set( p_playlist, "intf-change", val );