]> git.sesse.net Git - vlc/blob - src/interface/intf_playlist.c
* Header cleaning: filled all empty authors fields, added CVS $Id stuff.
[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.2 2001/03/21 13:42:34 sam 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
81     /* There is no current item */
82     p_playlist->current.i_type = 0;
83     p_playlist->current.i_status = 0;
84     p_playlist->current.psz_name = NULL;
85
86     /* The playlist is empty */
87     p_playlist->p_item = NULL;
88
89     intf_WarnMsg( 1, "intf: playlist initialized" );
90 }
91
92 /*****************************************************************************
93  * intf_PlaylistAdd: add an item to the playlist
94  *****************************************************************************
95  * Add an item to the playlist at position i_pos. If i_pos is PLAYLIST_END,
96  * add it at the end regardless of the playlist current size.
97  *****************************************************************************/
98 int intf_PlaylistAdd( playlist_t * p_playlist, int i_pos,
99                       const char * psz_item )
100 {
101     int i_index;
102     playlist_item_t * p_item;
103
104     vlc_mutex_lock( &p_playlist->change_lock );
105
106     if( i_pos == PLAYLIST_END )
107     {
108         i_pos = p_playlist->i_size;
109     }
110     else if( i_pos > p_playlist->i_size )
111     {
112         intf_ErrMsg( "intf error: inserting item beyond playlist size" );
113         vlc_mutex_unlock( &p_playlist->change_lock );
114         return( -1 );
115     }
116
117     /* Increment playlist size */
118     p_playlist->i_size++;
119     p_playlist->p_item = realloc( p_playlist->p_item,
120                     p_playlist->i_size * sizeof( playlist_item_t ) );
121
122     /* Move second place of the playlist to make room for new item */
123     for( i_index = p_playlist->i_size - 1; i_index > i_pos; i_index-- )
124     {
125         p_playlist->p_item[ i_index ] = p_playlist->p_item[ i_index - 1 ];
126     }
127
128     /* Insert the new item */
129     p_item = &p_playlist->p_item[ i_pos ];
130
131     p_item->i_type = 0;
132     p_item->i_status = 0;
133     p_item->psz_name = strdup( psz_item );
134
135     intf_WarnMsg( 1, "intf: added `%s' to playlist", psz_item );
136
137     vlc_mutex_unlock( &p_playlist->change_lock );
138
139     return( 0 );
140 }
141
142 /*****************************************************************************
143  * intf_PlaylistNext: switch to next playlist item
144  *****************************************************************************
145  * Switch to the next item of the playlist. If there is no next item, the
146  * position of the resulting item is set to -1.
147  *****************************************************************************/
148 void intf_PlaylistNext( playlist_t * p_playlist )
149 {
150     vlc_mutex_lock( &p_playlist->change_lock );
151
152     NextItem( p_playlist );
153
154     vlc_mutex_unlock( &p_playlist->change_lock );
155 }
156
157 /*****************************************************************************
158  * intf_PlaylistPrev: switch to previous playlist item
159  *****************************************************************************
160  * Switch to the previous item of the playlist. If there is no previous
161  * item, the position of the resulting item is set to -1.
162  *****************************************************************************/
163 void intf_PlaylistPrev( playlist_t * p_playlist )
164 {
165     vlc_mutex_lock( &p_playlist->change_lock );
166     p_playlist->i_mode = -p_playlist->i_mode;
167     
168     NextItem( p_playlist );
169
170     p_playlist->i_mode = -p_playlist->i_mode;
171     vlc_mutex_unlock( &p_playlist->change_lock );
172 }
173
174 /*****************************************************************************
175  * intf_PlaylistDelete: delete an item from the playlist
176  *****************************************************************************
177  * Delete the item in the playlist with position i_pos.
178  *****************************************************************************/
179 int intf_PlaylistDelete( playlist_t * p_playlist, int i_pos )
180 {
181     int i_index;
182     char * psz_name;
183
184     vlc_mutex_lock( &p_playlist->change_lock );
185
186     if( !p_playlist->i_size || i_pos >= p_playlist->i_size )
187     {
188         intf_ErrMsg( "intf error: deleting item beyond playlist size" );
189         vlc_mutex_unlock( &p_playlist->change_lock );
190         return( -1 );
191     }
192
193     /* Store the location of the item's name */
194     psz_name = p_playlist->p_item[ i_pos ].psz_name;
195
196     /* Fill the room by moving the next items */
197     for( i_index = i_pos; i_index < p_playlist->i_size - 1; i_index++ )
198     {
199         p_playlist->p_item[ i_index ] = p_playlist->p_item[ i_index + 1 ];
200     }
201
202     if( i_pos < p_playlist->i_index )
203         p_playlist->i_index--;
204         
205     
206     /* Decrement playlist size */
207     p_playlist->i_size--;
208     p_playlist->p_item = realloc( p_playlist->p_item,
209                     p_playlist->i_size * sizeof( playlist_item_t ) );
210
211     intf_WarnMsg( 1, "intf: removed `%s' from playlist", psz_name );
212     
213
214     /* Delete the item */
215     free( psz_name );
216
217     vlc_mutex_unlock( &p_playlist->change_lock );
218
219     return( 0 );
220 }
221
222 /*****************************************************************************
223  * intf_PlaylistDestroy: destroy the playlist
224  *****************************************************************************
225  * Delete all items in the playlist and free the playlist structure.
226  *****************************************************************************/
227 void intf_PlaylistDestroy( playlist_t * p_playlist )
228 {
229     int i_index;
230
231     for( i_index = p_playlist->i_size - 1; p_playlist->i_size; i_index-- )
232     {
233         intf_PlaylistDelete( p_playlist, i_index );
234     }
235
236     vlc_mutex_destroy( &p_playlist->change_lock );
237
238     if( p_playlist->current.psz_name != NULL )
239     {
240         free( p_playlist->current.psz_name );
241     }
242
243     free( p_playlist );
244
245     intf_WarnMsg( 1, "intf: playlist destroyed" );
246 }
247 void intf_PlaylistJumpto( playlist_t * p_playlist , int i_pos)
248 {
249     vlc_mutex_lock( &p_playlist->change_lock );
250  
251     p_playlist->i_index = i_pos;
252     
253     if( p_playlist->i_index != -1 )
254     {
255         if( p_playlist->current.psz_name != NULL )
256         {
257             free( p_playlist->current.psz_name );
258         }
259         p_playlist->current = p_playlist->p_item[ p_playlist->i_index ];
260         p_playlist->current.psz_name
261                             = strdup( p_playlist->current.psz_name );
262         }
263
264     vlc_mutex_unlock( &p_playlist->change_lock );
265 }   
266
267
268 /*****************************************************************************
269  * Following functions are local
270  *****************************************************************************/
271
272 /*****************************************************************************
273  * NextItem: select next playlist item
274  *****************************************************************************
275  * This function copies the next playlist item to the current structure,
276  * depending on the playlist browsing mode.
277  *****************************************************************************/
278 static void NextItem( playlist_t * p_playlist )
279 {
280     if( !p_playlist->i_size )
281     {
282         p_playlist->i_index = -1;
283     }
284     else
285     {
286         switch( p_playlist->i_mode )
287         {
288         case PLAYLIST_FORWARD:
289             p_playlist->i_index++;
290             if( p_playlist->i_index > p_playlist->i_size - 1 )
291             {
292                 p_playlist->i_index = -1;
293             }
294         break;
295
296         case PLAYLIST_FORWARD_LOOP:
297             p_playlist->i_index++;
298             if( p_playlist->i_index > p_playlist->i_size - 1 )
299             {
300                 p_playlist->i_index = 0;
301             }
302         break;
303
304         case PLAYLIST_BACKWARD:
305             p_playlist->i_index--;
306             if( p_playlist->i_index < 0 )
307             {
308                 p_playlist->i_index = -1;
309             }
310         break;
311
312         case PLAYLIST_BACKWARD_LOOP:
313             p_playlist->i_index--;
314             if( p_playlist->i_index < 0 )
315             {
316                 p_playlist->i_index = p_playlist->i_size - 1;
317             }
318         break;
319
320         case PLAYLIST_REPEAT_CURRENT:
321             /* Just repeat what we were doing */
322             if( p_playlist->i_index < 0
323                     || p_playlist->i_index > p_playlist->i_size - 1 )
324             {
325                 p_playlist->i_index = 0;
326             }
327         break;
328
329         case PLAYLIST_RANDOM:
330             /* FIXME: TODO ! */
331             p_playlist->i_index++;
332             if( p_playlist->i_index > p_playlist->i_size - 1 )
333             {
334                 p_playlist->i_index = 0;
335             }
336         break;
337         }
338
339         /* Duplicate the playlist entry */
340         if( p_playlist->i_index != -1 )
341         {
342             if( p_playlist->current.psz_name != NULL )
343             {
344                 free( p_playlist->current.psz_name );
345             }
346             p_playlist->current = p_playlist->p_item[ p_playlist->i_index ];
347             p_playlist->current.psz_name
348                                 = strdup( p_playlist->current.psz_name );
349         }
350     }
351 }
352