1 /*****************************************************************************
2 * intf_plst.c : Playlist management functions
3 *****************************************************************************
4 * Copyright (C) 1999, 2000 VideoLAN
6 * Authors: Samuel Hocevar <sam@zoy.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 *****************************************************************************/
26 #include <stdlib.h> /* free(), strtol() */
27 #include <stdio.h> /* sprintf() */
28 #include <string.h> /* strerror() */
29 #include <errno.h> /* ENOMEM */
35 #include "intf_plst.h"
39 /*****************************************************************************
41 *****************************************************************************/
42 static void NextItem( playlist_t * p_playlist );
44 /*****************************************************************************
45 * intf_PlstCreate: create playlist
46 *****************************************************************************
47 * Create a playlist structure.
48 *****************************************************************************/
49 playlist_t * intf_PlstCreate ( void )
51 playlist_t *p_playlist;
53 /* Allocate structure */
54 p_playlist = malloc( sizeof( playlist_t ) );
57 intf_ErrMsg( "intf error: couldn't create playlist (%s)",
65 /*****************************************************************************
66 * intf_PlstInit: initialize playlist
67 *****************************************************************************
68 * Initialize a playlist structure.
69 *****************************************************************************/
70 void intf_PlstInit ( playlist_t * p_playlist )
72 vlc_mutex_init( &p_playlist->change_lock );
74 p_playlist->i_index = -1; /* -1 means we are not playing anything yet */
75 p_playlist->i_size = 0;
77 p_playlist->i_mode = PLAYLIST_FORWARD;
78 p_playlist->i_seed = 0;
80 /* There is no current item */
81 p_playlist->current.i_type = 0;
82 p_playlist->current.i_status = 0;
83 p_playlist->current.psz_name = NULL;
85 /* The playlist is empty */
86 p_playlist->p_item = NULL;
88 intf_WarnMsg( 1, "intf: playlist initialized" );
91 /*****************************************************************************
92 * intf_PlstAdd: add an item to the playlist
93 *****************************************************************************
94 * Add an item to the playlist at position i_pos. If i_pos is PLAYLIST_END,
95 * add it at the end regardless of the playlist current size.
96 *****************************************************************************/
97 int intf_PlstAdd( playlist_t * p_playlist, int i_pos, char * psz_item )
100 playlist_item_t * p_item;
102 vlc_mutex_lock( &p_playlist->change_lock );
104 if( i_pos == PLAYLIST_END )
106 i_pos = p_playlist->i_size;
108 else if( i_pos > p_playlist->i_size )
110 intf_ErrMsg( "intf error: inserting item beyond playlist size" );
111 vlc_mutex_unlock( &p_playlist->change_lock );
115 /* Increment playlist size */
116 p_playlist->i_size++;
117 p_playlist->p_item = realloc( p_playlist->p_item,
118 p_playlist->i_size * sizeof( playlist_item_t ) );
120 /* Move second place of the playlist to make room for new item */
121 for( i_index = p_playlist->i_size - 1; i_index > i_pos; i_index-- )
123 p_playlist->p_item[ i_index ] = p_playlist->p_item[ i_index - 1 ];
126 /* Insert the new item */
127 p_item = &p_playlist->p_item[ i_pos ];
130 p_item->i_status = 0;
131 p_item->psz_name = strdup( psz_item );
133 intf_WarnMsg( 1, "intf: added %s to playlist", psz_item );
135 vlc_mutex_unlock( &p_playlist->change_lock );
140 /*****************************************************************************
141 * intf_PlstNext: switch to next playlist item
142 *****************************************************************************
143 * Switch to the next item of the playlist. If there is no next item, the
144 * position of the resulting item is set to -1.
145 *****************************************************************************/
146 void intf_PlstNext( playlist_t * p_playlist )
148 vlc_mutex_lock( &p_playlist->change_lock );
150 NextItem( p_playlist );
152 vlc_mutex_unlock( &p_playlist->change_lock );
155 /*****************************************************************************
156 * intf_PlstPrev: switch to previous playlist item
157 *****************************************************************************
158 * Switch to the previous item of the playlist. If there is no previous
159 * item, the position of the resulting item is set to -1.
160 *****************************************************************************/
161 void intf_PlstPrev( playlist_t * p_playlist )
163 vlc_mutex_lock( &p_playlist->change_lock );
164 p_playlist->i_mode = -p_playlist->i_mode;
166 NextItem( p_playlist );
168 p_playlist->i_mode = -p_playlist->i_mode;
169 vlc_mutex_unlock( &p_playlist->change_lock );
172 /*****************************************************************************
173 * intf_PlstDelete: delete an item from the playlist
174 *****************************************************************************
175 * Delete the item in the playlist with position i_pos.
176 *****************************************************************************/
177 int intf_PlstDelete( playlist_t * p_playlist, int i_pos )
182 vlc_mutex_lock( &p_playlist->change_lock );
184 if( !p_playlist->i_size || i_pos >= p_playlist->i_size )
186 intf_ErrMsg( "intf error: deleting item beyond playlist size" );
187 vlc_mutex_unlock( &p_playlist->change_lock );
191 /* Store the location of the item's name */
192 psz_name = p_playlist->p_item[ i_pos ].psz_name;
194 /* Fill the room by moving the next items */
195 for( i_index = i_pos; i_index < p_playlist->i_size - 1; i_index++ )
197 p_playlist->p_item[ i_index ] = p_playlist->p_item[ i_index + 1 ];
200 if( i_pos < p_playlist->i_index )
201 p_playlist->i_index--;
204 /* Decrement playlist size */
205 p_playlist->i_size--;
206 p_playlist->p_item = realloc( p_playlist->p_item,
207 p_playlist->i_size * sizeof( playlist_item_t ) );
209 intf_WarnMsg( 1, "intf: removed %s from playlist", psz_name );
212 /* Delete the item */
215 vlc_mutex_unlock( &p_playlist->change_lock );
220 /*****************************************************************************
221 * intf_PlstDestroy: destroy the playlist
222 *****************************************************************************
223 * Delete all items in the playlist and free the playlist structure.
224 *****************************************************************************/
225 void intf_PlstDestroy( playlist_t * p_playlist )
229 for( i_index = p_playlist->i_size - 1; p_playlist->i_size; i_index-- )
231 intf_PlstDelete( p_playlist, i_index );
234 vlc_mutex_destroy( &p_playlist->change_lock );
236 if( p_playlist->current.psz_name != NULL )
238 free( p_playlist->current.psz_name );
243 intf_WarnMsg( 1, "intf: playlist destroyed" );
245 void intf_PlstJumpto( playlist_t * p_playlist , int i_pos)
247 vlc_mutex_lock( &p_playlist->change_lock );
249 p_playlist->i_index = i_pos;
251 if( p_playlist->i_index != -1 )
253 if( p_playlist->current.psz_name != NULL )
255 free( p_playlist->current.psz_name );
257 p_playlist->current = p_playlist->p_item[ p_playlist->i_index ];
258 p_playlist->current.psz_name
259 = strdup( p_playlist->current.psz_name );
262 vlc_mutex_unlock( &p_playlist->change_lock );
266 /*****************************************************************************
267 * Following functions are local
268 *****************************************************************************/
270 /*****************************************************************************
271 * NextItem: select next playlist item
272 *****************************************************************************
273 * This function copies the next playlist item to the current structure,
274 * depending on the playlist browsing mode.
275 *****************************************************************************/
276 static void NextItem( playlist_t * p_playlist )
278 if( !p_playlist->i_size )
280 p_playlist->i_index = -1;
284 switch( p_playlist->i_mode )
286 case PLAYLIST_FORWARD:
287 p_playlist->i_index++;
288 if( p_playlist->i_index > p_playlist->i_size - 1 )
290 p_playlist->i_index = -1;
294 case PLAYLIST_FORWARD_LOOP:
295 p_playlist->i_index++;
296 if( p_playlist->i_index > p_playlist->i_size - 1 )
298 p_playlist->i_index = 0;
302 case PLAYLIST_BACKWARD:
303 p_playlist->i_index--;
304 if( p_playlist->i_index < 0 )
306 p_playlist->i_index = -1;
310 case PLAYLIST_BACKWARD_LOOP:
311 p_playlist->i_index--;
312 if( p_playlist->i_index < 0 )
314 p_playlist->i_index = p_playlist->i_size - 1;
318 case PLAYLIST_REPEAT_CURRENT:
319 /* Just repeat what we were doing */
320 if( p_playlist->i_index < 0
321 || p_playlist->i_index > p_playlist->i_size - 1 )
323 p_playlist->i_index = 0;
327 case PLAYLIST_RANDOM:
329 p_playlist->i_index++;
330 if( p_playlist->i_index > p_playlist->i_size - 1 )
332 p_playlist->i_index = 0;
337 /* Duplicate the playlist entry */
338 if( p_playlist->i_index != -1 )
340 if( p_playlist->current.psz_name != NULL )
342 free( p_playlist->current.psz_name );
344 p_playlist->current = p_playlist->p_item[ p_playlist->i_index ];
345 p_playlist->current.psz_name
346 = strdup( p_playlist->current.psz_name );