1 /*****************************************************************************
2 * intf_playlist.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_playlist.h"
39 /*****************************************************************************
41 *****************************************************************************/
42 static void NextItem( playlist_t * p_playlist );
44 /*****************************************************************************
45 * intf_PlaylistCreate: create playlist
46 *****************************************************************************
47 * Create a playlist structure.
48 *****************************************************************************/
49 playlist_t * intf_PlaylistCreate ( 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_PlaylistInit: initialize playlist
67 *****************************************************************************
68 * Initialize a playlist structure.
69 *****************************************************************************/
70 void intf_PlaylistInit ( 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_PlaylistAdd: 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_PlaylistAdd( playlist_t * p_playlist, int i_pos,
98 const char * psz_item )
101 playlist_item_t * p_item;
103 vlc_mutex_lock( &p_playlist->change_lock );
105 if( i_pos == PLAYLIST_END )
107 i_pos = p_playlist->i_size;
109 else if( i_pos > p_playlist->i_size )
111 intf_ErrMsg( "intf error: inserting item beyond playlist size" );
112 vlc_mutex_unlock( &p_playlist->change_lock );
116 /* Increment playlist size */
117 p_playlist->i_size++;
118 p_playlist->p_item = realloc( p_playlist->p_item,
119 p_playlist->i_size * sizeof( playlist_item_t ) );
121 /* Move second place of the playlist to make room for new item */
122 for( i_index = p_playlist->i_size - 1; i_index > i_pos; i_index-- )
124 p_playlist->p_item[ i_index ] = p_playlist->p_item[ i_index - 1 ];
127 /* Insert the new item */
128 p_item = &p_playlist->p_item[ i_pos ];
131 p_item->i_status = 0;
132 p_item->psz_name = strdup( psz_item );
134 intf_WarnMsg( 1, "intf: added `%s' to playlist", psz_item );
136 vlc_mutex_unlock( &p_playlist->change_lock );
141 /*****************************************************************************
142 * intf_PlaylistNext: switch to next playlist item
143 *****************************************************************************
144 * Switch to the next item of the playlist. If there is no next item, the
145 * position of the resulting item is set to -1.
146 *****************************************************************************/
147 void intf_PlaylistNext( playlist_t * p_playlist )
149 vlc_mutex_lock( &p_playlist->change_lock );
151 NextItem( p_playlist );
153 vlc_mutex_unlock( &p_playlist->change_lock );
156 /*****************************************************************************
157 * intf_PlaylistPrev: switch to previous playlist item
158 *****************************************************************************
159 * Switch to the previous item of the playlist. If there is no previous
160 * item, the position of the resulting item is set to -1.
161 *****************************************************************************/
162 void intf_PlaylistPrev( playlist_t * p_playlist )
164 vlc_mutex_lock( &p_playlist->change_lock );
165 p_playlist->i_mode = -p_playlist->i_mode;
167 NextItem( p_playlist );
169 p_playlist->i_mode = -p_playlist->i_mode;
170 vlc_mutex_unlock( &p_playlist->change_lock );
173 /*****************************************************************************
174 * intf_PlaylistDelete: delete an item from the playlist
175 *****************************************************************************
176 * Delete the item in the playlist with position i_pos.
177 *****************************************************************************/
178 int intf_PlaylistDelete( playlist_t * p_playlist, int i_pos )
183 vlc_mutex_lock( &p_playlist->change_lock );
185 if( !p_playlist->i_size || i_pos >= p_playlist->i_size )
187 intf_ErrMsg( "intf error: deleting item beyond playlist size" );
188 vlc_mutex_unlock( &p_playlist->change_lock );
192 /* Store the location of the item's name */
193 psz_name = p_playlist->p_item[ i_pos ].psz_name;
195 /* Fill the room by moving the next items */
196 for( i_index = i_pos; i_index < p_playlist->i_size - 1; i_index++ )
198 p_playlist->p_item[ i_index ] = p_playlist->p_item[ i_index + 1 ];
201 if( i_pos < p_playlist->i_index )
202 p_playlist->i_index--;
205 /* Decrement playlist size */
206 p_playlist->i_size--;
207 p_playlist->p_item = realloc( p_playlist->p_item,
208 p_playlist->i_size * sizeof( playlist_item_t ) );
210 intf_WarnMsg( 1, "intf: removed `%s' from playlist", psz_name );
213 /* Delete the item */
216 vlc_mutex_unlock( &p_playlist->change_lock );
221 /*****************************************************************************
222 * intf_PlaylistDestroy: destroy the playlist
223 *****************************************************************************
224 * Delete all items in the playlist and free the playlist structure.
225 *****************************************************************************/
226 void intf_PlaylistDestroy( playlist_t * p_playlist )
230 for( i_index = p_playlist->i_size - 1; p_playlist->i_size; i_index-- )
232 intf_PlaylistDelete( p_playlist, i_index );
235 vlc_mutex_destroy( &p_playlist->change_lock );
237 if( p_playlist->current.psz_name != NULL )
239 free( p_playlist->current.psz_name );
244 intf_WarnMsg( 1, "intf: playlist destroyed" );
246 void intf_PlaylistJumpto( playlist_t * p_playlist , int i_pos)
248 vlc_mutex_lock( &p_playlist->change_lock );
250 p_playlist->i_index = i_pos;
252 if( p_playlist->i_index != -1 )
254 if( p_playlist->current.psz_name != NULL )
256 free( p_playlist->current.psz_name );
258 p_playlist->current = p_playlist->p_item[ p_playlist->i_index ];
259 p_playlist->current.psz_name
260 = strdup( p_playlist->current.psz_name );
263 vlc_mutex_unlock( &p_playlist->change_lock );
267 /*****************************************************************************
268 * Following functions are local
269 *****************************************************************************/
271 /*****************************************************************************
272 * NextItem: select next playlist item
273 *****************************************************************************
274 * This function copies the next playlist item to the current structure,
275 * depending on the playlist browsing mode.
276 *****************************************************************************/
277 static void NextItem( playlist_t * p_playlist )
279 if( !p_playlist->i_size )
281 p_playlist->i_index = -1;
285 switch( p_playlist->i_mode )
287 case PLAYLIST_FORWARD:
288 p_playlist->i_index++;
289 if( p_playlist->i_index > p_playlist->i_size - 1 )
291 p_playlist->i_index = -1;
295 case PLAYLIST_FORWARD_LOOP:
296 p_playlist->i_index++;
297 if( p_playlist->i_index > p_playlist->i_size - 1 )
299 p_playlist->i_index = 0;
303 case PLAYLIST_BACKWARD:
304 p_playlist->i_index--;
305 if( p_playlist->i_index < 0 )
307 p_playlist->i_index = -1;
311 case PLAYLIST_BACKWARD_LOOP:
312 p_playlist->i_index--;
313 if( p_playlist->i_index < 0 )
315 p_playlist->i_index = p_playlist->i_size - 1;
319 case PLAYLIST_REPEAT_CURRENT:
320 /* Just repeat what we were doing */
321 if( p_playlist->i_index < 0
322 || p_playlist->i_index > p_playlist->i_size - 1 )
324 p_playlist->i_index = 0;
328 case PLAYLIST_RANDOM:
330 p_playlist->i_index++;
331 if( p_playlist->i_index > p_playlist->i_size - 1 )
333 p_playlist->i_index = 0;
338 /* Duplicate the playlist entry */
339 if( p_playlist->i_index != -1 )
341 if( p_playlist->current.psz_name != NULL )
343 free( p_playlist->current.psz_name );
345 p_playlist->current = p_playlist->p_item[ p_playlist->i_index ];
346 p_playlist->current.psz_name
347 = strdup( p_playlist->current.psz_name );