]> git.sesse.net Git - vlc/blob - src/interface/intf_playlist.c
* Bug fixes and enhancements in the Gtk+/Gnome interfaces.
[vlc] / src / interface / intf_playlist.c
1 /*****************************************************************************
2  * intf_playlist.c : Playlist management functions
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  *
6  * Authors: Samuel Hocevar <sam@zoy.org>
7  *
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.
12  * 
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.
17  *
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  *****************************************************************************/
22 #include "defs.h"
23
24 #include "config.h"
25
26 #include <stdlib.h>                                      /* free(), strtol() */
27 #include <stdio.h>                                              /* sprintf() */
28 #include <string.h>                                            /* strerror() */
29 #include <errno.h>                                                 /* ENOMEM */
30
31 #include "common.h"
32 #include "threads.h"
33
34 #include "intf_msg.h"
35 #include "intf_playlist.h"
36
37 #include "main.h"
38
39 /*****************************************************************************
40  * Local prototypes
41  *****************************************************************************/
42 static void NextItem( playlist_t * p_playlist );
43
44 /*****************************************************************************
45  * intf_PlaylistCreate: create playlist
46  *****************************************************************************
47  * Create a playlist structure.
48  *****************************************************************************/
49 playlist_t * intf_PlaylistCreate ( void )
50 {
51     playlist_t *p_playlist;
52
53     /* Allocate structure */
54     p_playlist = malloc( sizeof( playlist_t ) );
55     if( !p_playlist )
56     {
57         intf_ErrMsg( "intf error: couldn't create playlist (%s)",
58                      strerror( ENOMEM ) );
59         return( NULL );
60     }
61
62     return( p_playlist );
63 }
64
65 /*****************************************************************************
66  * intf_PlaylistInit: initialize playlist
67  *****************************************************************************
68  * Initialize a playlist structure.
69  *****************************************************************************/
70 void intf_PlaylistInit ( playlist_t * p_playlist )
71 {
72     vlc_mutex_init( &p_playlist->change_lock );
73
74     p_playlist->i_index = -1;    /* -1 means we are not playing anything yet */
75     p_playlist->i_size = 0;
76
77     p_playlist->i_mode = PLAYLIST_FORWARD;
78     p_playlist->i_seed = 0;
79
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;
84
85     /* The playlist is empty */
86     p_playlist->p_item = NULL;
87
88     intf_WarnMsg( 1, "intf: playlist initialized" );
89 }
90
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 )
99 {
100     int i_index;
101     playlist_item_t * p_item;
102
103     vlc_mutex_lock( &p_playlist->change_lock );
104
105     if( i_pos == PLAYLIST_END )
106     {
107         i_pos = p_playlist->i_size;
108     }
109     else if( i_pos > p_playlist->i_size )
110     {
111         intf_ErrMsg( "intf error: inserting item beyond playlist size" );
112         vlc_mutex_unlock( &p_playlist->change_lock );
113         return( -1 );
114     }
115
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 ) );
120
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-- )
123     {
124         p_playlist->p_item[ i_index ] = p_playlist->p_item[ i_index - 1 ];
125     }
126
127     /* Insert the new item */
128     p_item = &p_playlist->p_item[ i_pos ];
129
130     p_item->i_type = 0;
131     p_item->i_status = 0;
132     p_item->psz_name = strdup( psz_item );
133
134     intf_WarnMsg( 1, "intf: added `%s' to playlist", psz_item );
135
136     vlc_mutex_unlock( &p_playlist->change_lock );
137
138     return( 0 );
139 }
140
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 )
148 {
149     vlc_mutex_lock( &p_playlist->change_lock );
150
151     NextItem( p_playlist );
152
153     vlc_mutex_unlock( &p_playlist->change_lock );
154 }
155
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 )
163 {
164     vlc_mutex_lock( &p_playlist->change_lock );
165     p_playlist->i_mode = -p_playlist->i_mode;
166     
167     NextItem( p_playlist );
168
169     p_playlist->i_mode = -p_playlist->i_mode;
170     vlc_mutex_unlock( &p_playlist->change_lock );
171 }
172
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 )
179 {
180     int i_index;
181     char * psz_name;
182
183     vlc_mutex_lock( &p_playlist->change_lock );
184
185     if( !p_playlist->i_size || i_pos >= p_playlist->i_size )
186     {
187         intf_ErrMsg( "intf error: deleting item beyond playlist size" );
188         vlc_mutex_unlock( &p_playlist->change_lock );
189         return( -1 );
190     }
191
192     /* Store the location of the item's name */
193     psz_name = p_playlist->p_item[ i_pos ].psz_name;
194
195     /* Fill the room by moving the next items */
196     for( i_index = i_pos; i_index < p_playlist->i_size - 1; i_index++ )
197     {
198         p_playlist->p_item[ i_index ] = p_playlist->p_item[ i_index + 1 ];
199     }
200
201     if( i_pos < p_playlist->i_index )
202         p_playlist->i_index--;
203         
204     
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 ) );
209
210     intf_WarnMsg( 1, "intf: removed `%s' from playlist", psz_name );
211     
212
213     /* Delete the item */
214     free( psz_name );
215
216     vlc_mutex_unlock( &p_playlist->change_lock );
217
218     return( 0 );
219 }
220
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 )
227 {
228     int i_index;
229
230     for( i_index = p_playlist->i_size - 1; p_playlist->i_size; i_index-- )
231     {
232         intf_PlaylistDelete( p_playlist, i_index );
233     }
234
235     vlc_mutex_destroy( &p_playlist->change_lock );
236
237     if( p_playlist->current.psz_name != NULL )
238     {
239         free( p_playlist->current.psz_name );
240     }
241
242     free( p_playlist );
243
244     intf_WarnMsg( 1, "intf: playlist destroyed" );
245 }
246 void intf_PlaylistJumpto( playlist_t * p_playlist , int i_pos)
247 {
248     vlc_mutex_lock( &p_playlist->change_lock );
249  
250     p_playlist->i_index = i_pos;
251     
252     if( p_playlist->i_index != -1 )
253     {
254         if( p_playlist->current.psz_name != NULL )
255         {
256             free( p_playlist->current.psz_name );
257         }
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 );
261         }
262
263     vlc_mutex_unlock( &p_playlist->change_lock );
264 }   
265
266
267 /*****************************************************************************
268  * Following functions are local
269  *****************************************************************************/
270
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 )
278 {
279     if( !p_playlist->i_size )
280     {
281         p_playlist->i_index = -1;
282     }
283     else
284     {
285         switch( p_playlist->i_mode )
286         {
287         case PLAYLIST_FORWARD:
288             p_playlist->i_index++;
289             if( p_playlist->i_index > p_playlist->i_size - 1 )
290             {
291                 p_playlist->i_index = -1;
292             }
293         break;
294
295         case PLAYLIST_FORWARD_LOOP:
296             p_playlist->i_index++;
297             if( p_playlist->i_index > p_playlist->i_size - 1 )
298             {
299                 p_playlist->i_index = 0;
300             }
301         break;
302
303         case PLAYLIST_BACKWARD:
304             p_playlist->i_index--;
305             if( p_playlist->i_index < 0 )
306             {
307                 p_playlist->i_index = -1;
308             }
309         break;
310
311         case PLAYLIST_BACKWARD_LOOP:
312             p_playlist->i_index--;
313             if( p_playlist->i_index < 0 )
314             {
315                 p_playlist->i_index = p_playlist->i_size - 1;
316             }
317         break;
318
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 )
323             {
324                 p_playlist->i_index = 0;
325             }
326         break;
327
328         case PLAYLIST_RANDOM:
329             /* FIXME: TODO ! */
330             p_playlist->i_index++;
331             if( p_playlist->i_index > p_playlist->i_size - 1 )
332             {
333                 p_playlist->i_index = 0;
334             }
335         break;
336         }
337
338         /* Duplicate the playlist entry */
339         if( p_playlist->i_index != -1 )
340         {
341             if( p_playlist->current.psz_name != NULL )
342             {
343                 free( p_playlist->current.psz_name );
344             }
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 );
348         }
349     }
350 }
351