]> git.sesse.net Git - vlc/blob - src/interface/intf_plst.c
ce7b9a68829c03b9cbbca93fbc6e08a627f82bb7
[vlc] / src / interface / intf_plst.c
1 /*****************************************************************************
2  * intf_plst.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_plst.h"
36
37 #include "main.h"
38
39 /*****************************************************************************
40  * Local prototypes
41  *****************************************************************************/
42 static void NextItem( playlist_t * p_playlist );
43
44 /*****************************************************************************
45  * intf_PlstCreate: create playlist
46  *****************************************************************************
47  * Create a playlist structure.
48  *****************************************************************************/
49 playlist_t * intf_PlstCreate ( 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_PlstInit: initialize playlist
67  *****************************************************************************
68  * Initialize a playlist structure.
69  *****************************************************************************/
70 void intf_PlstInit ( 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_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 )
98 {
99     int i_index;
100     playlist_item_t * p_item;
101
102     vlc_mutex_lock( &p_playlist->change_lock );
103
104     if( i_pos == PLAYLIST_END )
105     {
106         i_pos = p_playlist->i_size;
107     }
108     else if( i_pos > p_playlist->i_size )
109     {
110         intf_ErrMsg( "intf error: inserting item beyond playlist size" );
111         vlc_mutex_unlock( &p_playlist->change_lock );
112         return( -1 );
113     }
114
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 ) );
119
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-- )
122     {
123         p_playlist->p_item[ i_index ] = p_playlist->p_item[ i_index - 1 ];
124     }
125
126     /* Insert the new item */
127     p_item = &p_playlist->p_item[ i_pos ];
128
129     p_item->i_type = 0;
130     p_item->i_status = 0;
131     p_item->psz_name = strdup( psz_item );
132
133     intf_WarnMsg( 1, "intf: added %s to playlist", psz_item );
134
135     vlc_mutex_unlock( &p_playlist->change_lock );
136
137     return( 0 );
138 }
139
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 )
147 {
148     vlc_mutex_lock( &p_playlist->change_lock );
149
150     NextItem( p_playlist );
151
152     vlc_mutex_unlock( &p_playlist->change_lock );
153 }
154
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 )
162 {
163     vlc_mutex_lock( &p_playlist->change_lock );
164     p_playlist->i_mode = -p_playlist->i_mode;
165     
166     NextItem( p_playlist );
167
168     p_playlist->i_mode = -p_playlist->i_mode;
169     vlc_mutex_unlock( &p_playlist->change_lock );
170 }
171
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 )
178 {
179     int i_index;
180     char * psz_name;
181
182     vlc_mutex_lock( &p_playlist->change_lock );
183
184     if( !p_playlist->i_size || i_pos >= p_playlist->i_size )
185     {
186         intf_ErrMsg( "intf error: deleting item beyond playlist size" );
187         vlc_mutex_unlock( &p_playlist->change_lock );
188         return( -1 );
189     }
190
191     /* Store the location of the item's name */
192     psz_name = p_playlist->p_item[ i_pos ].psz_name;
193
194     /* Fill the room by moving the next items */
195     for( i_index = i_pos; i_index < p_playlist->i_size - 1; i_index++ )
196     {
197         p_playlist->p_item[ i_index ] = p_playlist->p_item[ i_index + 1 ];
198     }
199
200     if( i_pos < p_playlist->i_index )
201         p_playlist->i_index--;
202         
203     
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 ) );
208
209     intf_WarnMsg( 1, "intf: removed %s from playlist", psz_name );
210     
211
212     /* Delete the item */
213     free( psz_name );
214
215     vlc_mutex_unlock( &p_playlist->change_lock );
216
217     return( 0 );
218 }
219
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 )
226 {
227     int i_index;
228
229     for( i_index = p_playlist->i_size - 1; p_playlist->i_size; i_index-- )
230     {
231         intf_PlstDelete( p_playlist, i_index );
232     }
233
234     vlc_mutex_destroy( &p_playlist->change_lock );
235
236     if( p_playlist->current.psz_name != NULL )
237     {
238         free( p_playlist->current.psz_name );
239     }
240
241     free( p_playlist );
242
243     intf_WarnMsg( 1, "intf: playlist destroyed" );
244 }
245 void intf_PlstJumpto( playlist_t * p_playlist , int i_pos)
246 {
247     vlc_mutex_lock( &p_playlist->change_lock );
248  
249     p_playlist->i_index = i_pos;
250     
251     if( p_playlist->i_index != -1 )
252     {
253         if( p_playlist->current.psz_name != NULL )
254         {
255             free( p_playlist->current.psz_name );
256         }
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 );
260         }
261
262     vlc_mutex_unlock( &p_playlist->change_lock );
263 }   
264
265
266 /*****************************************************************************
267  * Following functions are local
268  *****************************************************************************/
269
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 )
277 {
278     if( !p_playlist->i_size )
279     {
280         p_playlist->i_index = -1;
281     }
282     else
283     {
284         switch( p_playlist->i_mode )
285         {
286         case PLAYLIST_FORWARD:
287             p_playlist->i_index++;
288             if( p_playlist->i_index > p_playlist->i_size - 1 )
289             {
290                 p_playlist->i_index = -1;
291             }
292         break;
293
294         case PLAYLIST_FORWARD_LOOP:
295             p_playlist->i_index++;
296             if( p_playlist->i_index > p_playlist->i_size - 1 )
297             {
298                 p_playlist->i_index = 0;
299             }
300         break;
301
302         case PLAYLIST_BACKWARD:
303             p_playlist->i_index--;
304             if( p_playlist->i_index < 0 )
305             {
306                 p_playlist->i_index = -1;
307             }
308         break;
309
310         case PLAYLIST_BACKWARD_LOOP:
311             p_playlist->i_index--;
312             if( p_playlist->i_index < 0 )
313             {
314                 p_playlist->i_index = p_playlist->i_size - 1;
315             }
316         break;
317
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 )
322             {
323                 p_playlist->i_index = 0;
324             }
325         break;
326
327         case PLAYLIST_RANDOM:
328             /* FIXME: TODO ! */
329             p_playlist->i_index++;
330             if( p_playlist->i_index > p_playlist->i_size - 1 )
331             {
332                 p_playlist->i_index = 0;
333             }
334         break;
335         }
336
337         /* Duplicate the playlist entry */
338         if( p_playlist->i_index != -1 )
339         {
340             if( p_playlist->current.psz_name != NULL )
341             {
342                 free( p_playlist->current.psz_name );
343             }
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 );
347         }
348     }
349 }
350