]> git.sesse.net Git - vlc/blob - src/interface/intf_playlist.c
37cf3e38c2bf8f4c893acfad213cbe4e921e9876
[vlc] / src / interface / intf_playlist.c
1 /*****************************************************************************
2  * intf_playlist.c : Playlist management functions
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  * $Id: intf_playlist.c,v 1.6 2001/05/15 14:49:48 stef Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *
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.
13  * 
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.
18  *
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 "defs.h"
24
25 #include "config.h"
26
27 #include <stdlib.h>                                      /* free(), strtol() */
28 #include <stdio.h>                                              /* sprintf() */
29 #include <string.h>                                            /* strerror() */
30 #include <errno.h>                                                 /* ENOMEM */
31
32 #include "common.h"
33 #include "threads.h"
34
35 #include "intf_msg.h"
36 #include "intf_playlist.h"
37
38 #include "main.h"
39
40 /*****************************************************************************
41  * Local prototypes
42  *****************************************************************************/
43 static void NextItem( playlist_t * p_playlist );
44
45 /*****************************************************************************
46  * intf_PlaylistCreate: create playlist
47  *****************************************************************************
48  * Create a playlist structure.
49  *****************************************************************************/
50 playlist_t * intf_PlaylistCreate ( void )
51 {
52     playlist_t *p_playlist;
53
54     /* Allocate structure */
55     p_playlist = malloc( sizeof( playlist_t ) );
56     if( !p_playlist )
57     {
58         intf_ErrMsg( "intf error: couldn't create playlist (%s)",
59                      strerror( ENOMEM ) );
60         return( NULL );
61     }
62
63     return( p_playlist );
64 }
65
66 /*****************************************************************************
67  * intf_PlaylistInit: initialize playlist
68  *****************************************************************************
69  * Initialize a playlist structure.
70  *****************************************************************************/
71 void intf_PlaylistInit ( playlist_t * p_playlist )
72 {
73     vlc_mutex_init( &p_playlist->change_lock );
74
75     p_playlist->i_index = -1;    /* -1 means we are not playing anything yet */
76     p_playlist->i_size = 0;
77
78     p_playlist->i_mode = PLAYLIST_FORWARD;
79     p_playlist->i_seed = 0;
80     p_playlist->b_stopped = 0;
81
82     /* There is no current item */
83     p_playlist->current.i_type = 0;
84     p_playlist->current.i_status = 0;
85     p_playlist->current.psz_name = NULL;
86
87     /* The playlist is empty */
88     p_playlist->p_item = NULL;
89
90     intf_WarnMsg( 3, "intf: playlist initialized" );
91 }
92
93 /*****************************************************************************
94  * intf_PlaylistAdd: add an item to the playlist
95  *****************************************************************************
96  * Add an item to the playlist at position i_pos. If i_pos is PLAYLIST_END,
97  * add it at the end regardless of the playlist current size.
98  *****************************************************************************/
99 int intf_PlaylistAdd( playlist_t * p_playlist, int i_pos,
100                       const char * psz_item )
101 {
102     int i_index;
103     playlist_item_t * p_item;
104
105     vlc_mutex_lock( &p_playlist->change_lock );
106
107     if( i_pos == PLAYLIST_END )
108     {
109         i_pos = p_playlist->i_size;
110     }
111     else if( i_pos > p_playlist->i_size )
112     {
113         intf_ErrMsg( "intf error: inserting item beyond playlist size" );
114         vlc_mutex_unlock( &p_playlist->change_lock );
115         return( -1 );
116     }
117
118     /* Increment playlist size */
119     p_playlist->i_size++;
120     p_playlist->p_item = realloc( p_playlist->p_item,
121                     p_playlist->i_size * sizeof( playlist_item_t ) );
122
123     /* Move second place of the playlist to make room for new item */
124     for( i_index = p_playlist->i_size - 1; i_index > i_pos; i_index-- )
125     {
126         p_playlist->p_item[ i_index ] = p_playlist->p_item[ i_index - 1 ];
127     }
128
129     /* Insert the new item */
130     p_item = &p_playlist->p_item[ i_pos ];
131
132     p_item->i_type = 0;
133     p_item->i_status = 0;
134     p_item->psz_name = strdup( psz_item );
135
136     intf_WarnMsg( 3, "intf: added `%s' to playlist", psz_item );
137
138     vlc_mutex_unlock( &p_playlist->change_lock );
139
140     return( 0 );
141 }
142
143 /*****************************************************************************
144  * intf_PlaylistNext: switch to next playlist item
145  *****************************************************************************
146  * Switch to the next item of the playlist. If there is no next item, the
147  * position of the resulting item is set to -1.
148  *****************************************************************************/
149 void intf_PlaylistNext( playlist_t * p_playlist )
150 {
151     vlc_mutex_lock( &p_playlist->change_lock );
152
153     NextItem( p_playlist );
154
155     vlc_mutex_unlock( &p_playlist->change_lock );
156 }
157
158 /*****************************************************************************
159  * intf_PlaylistPrev: switch to previous playlist item
160  *****************************************************************************
161  * Switch to the previous item of the playlist. If there is no previous
162  * item, the position of the resulting item is set to -1.
163  *****************************************************************************/
164 void intf_PlaylistPrev( playlist_t * p_playlist )
165 {
166     vlc_mutex_lock( &p_playlist->change_lock );
167     p_playlist->i_mode = -p_playlist->i_mode;
168     
169     NextItem( p_playlist );
170
171     p_playlist->i_mode = -p_playlist->i_mode;
172     vlc_mutex_unlock( &p_playlist->change_lock );
173 }
174
175 /*****************************************************************************
176  * intf_PlaylistDelete: delete an item from the playlist
177  *****************************************************************************
178  * Delete the item in the playlist with position i_pos.
179  *****************************************************************************/
180 int intf_PlaylistDelete( playlist_t * p_playlist, int i_pos )
181 {
182     int i_index;
183     char * psz_name;
184
185     vlc_mutex_lock( &p_playlist->change_lock );
186
187     if( !p_playlist->i_size || i_pos >= p_playlist->i_size )
188     {
189         intf_ErrMsg( "intf error: deleting item beyond playlist size" );
190         vlc_mutex_unlock( &p_playlist->change_lock );
191         return( -1 );
192     }
193
194     /* Store the location of the item's name */
195     psz_name = p_playlist->p_item[ i_pos ].psz_name;
196
197     /* Fill the room by moving the next items */
198     for( i_index = i_pos; i_index < p_playlist->i_size - 1; i_index++ )
199     {
200         p_playlist->p_item[ i_index ] = p_playlist->p_item[ i_index + 1 ];
201     }
202
203     if( i_pos < p_playlist->i_index )
204         p_playlist->i_index--;
205         
206     
207     /* Decrement playlist size */
208     p_playlist->i_size--;
209     p_playlist->p_item = realloc( p_playlist->p_item,
210                     p_playlist->i_size * sizeof( playlist_item_t ) );
211
212     intf_WarnMsg( 3, "intf: removed `%s' from playlist", psz_name );
213     
214
215     /* Delete the item */
216     free( psz_name );
217
218     vlc_mutex_unlock( &p_playlist->change_lock );
219
220     return( 0 );
221 }
222
223 /*****************************************************************************
224  * intf_PlaylistDestroy: destroy the playlist
225  *****************************************************************************
226  * Delete all items in the playlist and free the playlist structure.
227  *****************************************************************************/
228 void intf_PlaylistDestroy( playlist_t * p_playlist )
229 {
230     int i_index;
231
232     for( i_index = p_playlist->i_size - 1; p_playlist->i_size; i_index-- )
233     {
234         intf_PlaylistDelete( p_playlist, i_index );
235     }
236
237     vlc_mutex_destroy( &p_playlist->change_lock );
238
239     if( p_playlist->current.psz_name != NULL )
240     {
241         free( p_playlist->current.psz_name );
242     }
243
244     free( p_playlist );
245
246     intf_WarnMsg( 3, "intf: playlist destroyed" );
247 }
248
249 /*****************************************************************************
250  * intf_PlaylistJumpto: go to a specified position in playlist.
251  *****************************************************************************/
252 void intf_PlaylistJumpto( playlist_t * p_playlist , int i_pos)
253 {
254     vlc_mutex_lock( &p_playlist->change_lock );
255  
256     p_playlist->i_index = i_pos;
257     
258     if( p_playlist->i_index != -1 )
259     {
260         if( p_playlist->current.psz_name != NULL )
261         {
262             free( p_playlist->current.psz_name );
263         }
264
265         p_playlist->current = p_playlist->p_item[ p_playlist->i_index ];
266         p_playlist->current.psz_name
267                             = strdup( p_playlist->current.psz_name );
268
269     }
270     p_main->p_playlist->b_stopped = 0;
271
272     vlc_mutex_unlock( &p_playlist->change_lock );
273 }   
274
275
276 /*****************************************************************************
277  * Following functions are local
278  *****************************************************************************/
279
280 /*****************************************************************************
281  * NextItem: select next playlist item
282  *****************************************************************************
283  * This function copies the next playlist item to the current structure,
284  * depending on the playlist browsing mode.
285  *****************************************************************************/
286 static void NextItem( playlist_t * p_playlist )
287 {
288     if( !p_playlist->i_size )
289     {
290         p_playlist->i_index = -1;
291     }
292     else
293     {
294         switch( p_playlist->i_mode )
295         {
296         case PLAYLIST_FORWARD:
297             p_playlist->i_index++;
298             if( p_playlist->i_index > p_playlist->i_size - 1 )
299             {
300                 p_playlist->i_index = -1;
301             }
302         break;
303
304         case PLAYLIST_FORWARD_LOOP:
305             p_playlist->i_index++;
306             if( p_playlist->i_index > p_playlist->i_size - 1 )
307             {
308                 p_playlist->i_index = 0;
309             }
310         break;
311
312         case PLAYLIST_BACKWARD:
313             p_playlist->i_index--;
314             if( p_playlist->i_index < 0 )
315             {
316                 p_playlist->i_index = -1;
317             }
318         break;
319
320         case PLAYLIST_BACKWARD_LOOP:
321             p_playlist->i_index--;
322             if( p_playlist->i_index < 0 )
323             {
324                 p_playlist->i_index = p_playlist->i_size - 1;
325             }
326         break;
327
328         case PLAYLIST_REPEAT_CURRENT:
329             /* Just repeat what we were doing */
330             if( p_playlist->i_index < 0
331                     || p_playlist->i_index > p_playlist->i_size - 1 )
332             {
333                 p_playlist->i_index = 0;
334             }
335         break;
336
337         case PLAYLIST_RANDOM:
338             /* FIXME: TODO ! */
339             p_playlist->i_index++;
340             if( p_playlist->i_index > p_playlist->i_size - 1 )
341             {
342                 p_playlist->i_index = 0;
343             }
344         break;
345         }
346
347         /* Duplicate the playlist entry */
348         if( p_playlist->i_index != -1 )
349         {
350             if( p_playlist->current.psz_name != NULL )
351             {
352                 free( p_playlist->current.psz_name );
353             }
354             p_playlist->current = p_playlist->p_item[ p_playlist->i_index ];
355             p_playlist->current.psz_name
356                                 = strdup( p_playlist->current.psz_name );
357         }
358     }
359 }
360