]> git.sesse.net Git - vlc/blob - src/playlist/item.c
* src/playlist/*: when deleting the currently playing item, skip it instead of stoppi...
[vlc] / src / playlist / item.c
1 /*****************************************************************************
2  * item.c : Playlist item functions
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: item.c,v 1.9 2003/12/13 17:16:11 gbazin 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 <stdlib.h>                                      /* free(), strtol() */
24 #include <stdio.h>                                              /* sprintf() */
25 #include <string.h>                                            /* strerror() */
26
27 #include <vlc/vlc.h>
28 #include <vlc/vout.h>
29 #include <vlc/sout.h>
30 #include <vlc/input.h>
31
32 #include "vlc_playlist.h"
33
34 /**
35  * Add an MRL to the playlist. This is a simplified version of
36  * playlist_AddExt inculded for convenince. It equals calling playlist_AddExt
37  * with psz_name == psz_target and i_duration == -1
38  */
39
40 int playlist_Add( playlist_t *p_playlist, const char *psz_target,
41                   const char **ppsz_options, int i_options,
42                   int i_mode, int i_pos )
43 {
44     return playlist_AddExt( p_playlist, psz_target, psz_target, -1,
45                             ppsz_options, i_options, i_mode, i_pos );
46 }
47
48 /**
49  * Add a MRL into the playlist.
50  *
51  * \param p_playlist the playlist to add into
52  * \param psz_uri the mrl to add to the playlist
53  * \param psz_name a text giving a name or description of this item
54  * \param i_duration a hint about the duration of this item, in microseconds, 
55  *        or -1 if unknown.
56  * \param ppsz_options array of options
57  * \param i_options number of items in ppsz_options
58  * \param i_mode the mode used when adding
59  * \param i_pos the position in the playlist where to add. If this is
60  *        PLAYLIST_END the item will be added at the end of the playlist
61  *        regardless of it's size
62  * \return always returns 0
63 */
64 int playlist_AddExt( playlist_t *p_playlist, const char * psz_uri,
65                      const char * psz_name, mtime_t i_duration,
66                      const char **ppsz_options, int i_options, int i_mode,
67                      int i_pos )
68 {
69     playlist_item_t * p_item;
70
71     p_item = malloc( sizeof( playlist_item_t ) );
72     if( p_item == NULL )
73     {
74         msg_Err( p_playlist, "out of memory" );
75     }
76
77     p_item->psz_name   = strdup( psz_name );
78     p_item->psz_uri    = strdup( psz_uri );
79     p_item->psz_author = strdup( "" );
80     p_item->i_duration = i_duration;
81     p_item->i_type = 0;
82     p_item->i_status = 0;
83     p_item->b_autodeletion = VLC_FALSE;
84     p_item->b_enabled = VLC_TRUE;
85     p_item->i_group = PLAYLIST_TYPE_MANUAL;
86
87     p_item->ppsz_options = NULL;
88     p_item->i_options = i_options;
89
90     if( i_options > 0 )
91     {
92         int i;
93
94         p_item->ppsz_options = malloc( i_options * sizeof(char *) );
95         for( i = 0; i < i_options; i++ )
96         {
97             p_item->ppsz_options[i] = strdup( ppsz_options[i] );
98         }
99
100     }
101
102     return playlist_AddItem( p_playlist, p_item, i_mode, i_pos );
103 }
104
105 /**
106  * Add a playlist item into a playlist
107  *
108  * \param p_playlist the playlist to insert into
109  * \param p_item the playlist item to insert
110  * \param i_mode the mode used when adding
111  * \param i_pos the possition in the playlist where to add. If this is
112  *        PLAYLIST_END the item will be added at the end of the playlist
113  *        regardless of it's size
114  * \return always returns 0
115 */
116 int playlist_AddItem( playlist_t *p_playlist, playlist_item_t * p_item,
117                 int i_mode, int i_pos)
118 {
119     vlc_value_t     val;
120
121     vlc_mutex_lock( &p_playlist->object_lock );
122
123     /*
124      * CHECK_INSERT : checks if the item is already enqued before
125      * enqueing it
126      */
127     if ( i_mode & PLAYLIST_CHECK_INSERT )
128     {
129          int j;
130
131          if ( p_playlist->pp_items )
132          {
133              for ( j = 0; j < p_playlist->i_size; j++ )
134              {
135                  if ( !strcmp( p_playlist->pp_items[j]->psz_uri, p_item->psz_uri ) )
136                  {
137                       if( p_item->psz_name )
138                       {
139                           free( p_item->psz_name );
140                       }
141                       if( p_item->psz_uri )
142                       {
143                           free( p_item->psz_uri );
144                       }
145                       if( p_item->i_options )
146                       {
147                           int i_opt;
148                           for( i_opt = 0; i_opt < p_item->i_options; i_opt++ )
149                           {
150                               free( p_item->ppsz_options[i_opt] );
151                           }
152                           free( p_item->ppsz_options );
153                       }
154                       if( p_item->psz_author )
155                       {
156                           free( p_item->psz_author );
157                       }
158                       free( p_item );
159                       vlc_mutex_unlock( &p_playlist->object_lock );
160                       return 0;
161                  }
162              }
163          }
164          i_mode &= ~PLAYLIST_CHECK_INSERT;
165          i_mode |= PLAYLIST_APPEND;
166     }
167
168
169     msg_Dbg( p_playlist, "adding playlist item « %s » ( %s )", p_item->psz_name, p_item->psz_uri);
170
171     /* Create the new playlist item */
172
173
174     /* Do a few boundary checks and allocate space for the item */
175     if( i_pos == PLAYLIST_END )
176     {
177         if( i_mode & PLAYLIST_INSERT )
178         {
179             i_mode &= ~PLAYLIST_INSERT;
180             i_mode |= PLAYLIST_APPEND;
181         }
182
183         i_pos = p_playlist->i_size - 1;
184     }
185
186     if( !(i_mode & PLAYLIST_REPLACE)
187          || i_pos < 0 || i_pos >= p_playlist->i_size )
188     {
189         /* Additional boundary checks */
190         if( i_mode & PLAYLIST_APPEND )
191         {
192             i_pos++;
193         }
194
195         if( i_pos < 0 )
196         {
197             i_pos = 0;
198         }
199         else if( i_pos > p_playlist->i_size )
200         {
201             i_pos = p_playlist->i_size;
202         }
203
204         INSERT_ELEM( p_playlist->pp_items,
205                      p_playlist->i_size,
206                      i_pos,
207                      p_item );
208         p_playlist->i_enabled ++;
209
210         if( p_playlist->i_index >= i_pos )
211         {
212             p_playlist->i_index++;
213         }
214     }
215     else
216     {
217         /* i_mode == PLAYLIST_REPLACE and 0 <= i_pos < p_playlist->i_size */
218         if( p_playlist->pp_items[i_pos]->psz_name )
219         {
220             free( p_playlist->pp_items[i_pos]->psz_name );
221         }
222         if( p_playlist->pp_items[i_pos]->psz_uri )
223         {
224             free( p_playlist->pp_items[i_pos]->psz_uri );
225         }
226         if( p_playlist->pp_items[i_pos]->psz_author )
227         {
228             free( p_playlist->pp_items[i_pos]->psz_author );
229         }
230         /* XXX: what if the item is still in use? */
231         free( p_playlist->pp_items[i_pos] );
232         p_playlist->pp_items[i_pos] = p_item;
233     }
234
235     if( i_mode & PLAYLIST_GO )
236     {
237         p_playlist->i_index = i_pos;
238         if( p_playlist->p_input )
239         {
240             input_StopThread( p_playlist->p_input );
241         }
242         p_playlist->i_status = PLAYLIST_RUNNING;
243     }
244
245     vlc_mutex_unlock( &p_playlist->object_lock );
246
247     val.b_bool = VLC_TRUE;
248     var_Set( p_playlist, "intf-change", val );
249
250     return 0;
251 }
252
253 /**
254  * delete an item from a playlist.
255  *
256  * \param p_playlist the playlist to remove from.
257  * \param i_pos the position of the item to remove
258  * \return returns 0
259  */
260 int playlist_Delete( playlist_t * p_playlist, int i_pos )
261 {
262     vlc_value_t     val;
263
264     /* if i_pos is the current played item, playlist should stop playing it */
265     if( p_playlist->i_status == PLAYLIST_RUNNING &&
266         p_playlist->i_index == i_pos )
267     {
268         playlist_Command( p_playlist, PLAYLIST_SKIP, 1 );
269     }
270
271     vlc_mutex_lock( &p_playlist->object_lock );
272     if( i_pos >= 0 && i_pos < p_playlist->i_size )
273     {
274         playlist_item_t *p_item = p_playlist->pp_items[i_pos];
275
276         msg_Dbg( p_playlist, "deleting playlist item « %s »",
277                  p_item->psz_name );
278
279         if( p_item->psz_name )
280         {
281             free( p_item->psz_name );
282         }
283         if( p_item->psz_uri )
284         {
285             free( p_item->psz_uri );
286         }
287         if( p_item->psz_author )
288         {
289             free( p_item->psz_author );
290         }
291         if( p_item->i_options > 0 )
292         {
293             int i;
294
295             for( i = 0; i < p_item->i_options; i++ )
296             {
297                 free( p_item->ppsz_options[i] );
298             }
299
300             free( p_item->ppsz_options );
301         }
302
303         /* XXX: what if the item is still in use? */
304         free( p_item );
305
306         if( i_pos <= p_playlist->i_index )
307         {
308             p_playlist->i_index--;
309         }
310
311         /* Renumber the playlist */
312         REMOVE_ELEM( p_playlist->pp_items,
313                      p_playlist->i_size,
314                      i_pos );
315         if( p_playlist->i_enabled > 0 )
316             p_playlist->i_enabled--;
317     }
318
319     vlc_mutex_unlock( &p_playlist->object_lock );
320
321     val.b_bool = VLC_TRUE;
322     var_Set( p_playlist, "intf-change", val );
323
324     return 0;
325 }
326
327 /**
328  * Disables a playlist item
329  *
330  * \param p_playlist the playlist to disable from.
331  * \param i_pos the position of the item to disable
332  * \return returns 0
333  */
334 int playlist_Disable( playlist_t * p_playlist, int i_pos )
335 {
336     vlc_value_t     val;
337     vlc_mutex_lock( &p_playlist->object_lock );
338
339
340     if( i_pos >= 0 && i_pos < p_playlist->i_size )
341     {
342         msg_Dbg( p_playlist, "disabling playlist item « %s »",
343                              p_playlist->pp_items[i_pos]->psz_name );
344
345         if( p_playlist->pp_items[i_pos]->b_enabled == VLC_TRUE )
346             p_playlist->i_enabled--;
347         p_playlist->pp_items[i_pos]->b_enabled = VLC_FALSE;
348     }
349
350     vlc_mutex_unlock( &p_playlist->object_lock );
351
352     val.b_bool = VLC_TRUE;
353     var_Set( p_playlist, "intf-change", val );
354
355     return 0;
356 }
357
358 /**
359  * Enables a playlist item
360  *
361  * \param p_playlist the playlist to enable from.
362  * \param i_pos the position of the item to enable
363  * \return returns 0
364  */
365 int playlist_Enable( playlist_t * p_playlist, int i_pos )
366 {
367     vlc_value_t     val;
368     vlc_mutex_lock( &p_playlist->object_lock );
369
370     if( i_pos >= 0 && i_pos < p_playlist->i_size )
371     {
372         msg_Dbg( p_playlist, "enabling playlist item « %s »",
373                              p_playlist->pp_items[i_pos]->psz_name );
374
375         if( p_playlist->pp_items[i_pos]->b_enabled == VLC_FALSE )
376             p_playlist->i_enabled++;
377
378         p_playlist->pp_items[i_pos]->b_enabled = VLC_TRUE;
379     }
380
381     vlc_mutex_unlock( &p_playlist->object_lock );
382
383     val.b_bool = VLC_TRUE;
384     var_Set( p_playlist, "intf-change", val );
385
386     return 0;
387 }
388
389 /**
390  * Disables a playlist group
391  *
392  * \param p_playlist the playlist to disable from.
393  * \param i_pos the id of the group to disable
394  * \return returns 0
395  */
396 int playlist_DisableGroup( playlist_t * p_playlist, int i_group)
397 {
398     vlc_value_t     val;
399     int i;
400     vlc_mutex_lock( &p_playlist->object_lock );
401
402     msg_Dbg(p_playlist,"Disabling group %i",i_group);
403     for( i = 0 ; i< p_playlist->i_size; i++ )
404     {
405         if( p_playlist->pp_items[i]->i_group == i_group )
406         {
407             msg_Dbg( p_playlist, "disabling playlist item « %s »",
408                            p_playlist->pp_items[i]->psz_name );
409
410             if( p_playlist->pp_items[i]->b_enabled == VLC_TRUE )
411                 p_playlist->i_enabled--;
412
413             p_playlist->pp_items[i]->b_enabled = VLC_FALSE;
414         }
415     }
416     vlc_mutex_unlock( &p_playlist->object_lock );
417
418     val.b_bool = VLC_TRUE;
419     var_Set( p_playlist, "intf-change", val );
420
421     return 0;
422 }
423
424 /**
425  * Enables a playlist group
426  *
427  * \param p_playlist the playlist to enable from.
428  * \param i_pos the id of the group to enable
429  * \return returns 0
430  */
431 int playlist_EnableGroup( playlist_t * p_playlist, int i_group)
432 {
433     vlc_value_t     val;
434     int i;
435     vlc_mutex_lock( &p_playlist->object_lock );
436
437     for( i = 0 ; i< p_playlist->i_size; i++ )
438     {
439         if( p_playlist->pp_items[i]->i_group == i_group )
440         {
441             msg_Dbg( p_playlist, "enabling playlist item « %s »",
442                            p_playlist->pp_items[i]->psz_name );
443
444             if( p_playlist->pp_items[i]->b_enabled == VLC_FALSE )
445                 p_playlist->i_enabled++;
446
447             p_playlist->pp_items[i]->b_enabled = VLC_TRUE;
448         }
449     }
450     vlc_mutex_unlock( &p_playlist->object_lock );
451
452     val.b_bool = VLC_TRUE;
453     var_Set( p_playlist, "intf-change", val );
454
455     return 0;
456 }
457
458 /**
459  * Move an item in a playlist
460  *
461  * Move the item in the playlist with position i_pos before the current item
462  * at position i_newpos.
463  * \param p_playlist the playlist to move items in
464  * \param i_pos the position of the item to move
465  * \param i_newpos the position of the item that will be behind the moved item
466  *        after the move
467  * \return returns 0
468  */
469 int playlist_Move( playlist_t * p_playlist, int i_pos, int i_newpos)
470 {
471     vlc_value_t     val;
472     vlc_mutex_lock( &p_playlist->object_lock );
473
474     /* take into account that our own row disappears. */
475     if ( i_pos < i_newpos ) i_newpos--;
476
477     if( i_pos >= 0 && i_newpos >=0 && i_pos <= p_playlist->i_size
478                      && i_newpos <= p_playlist->i_size )
479     {
480         playlist_item_t * temp;
481
482         msg_Dbg( p_playlist, "moving playlist item « %s » (%i -> %i)",
483                              p_playlist->pp_items[i_pos]->psz_name, i_pos,
484                              i_newpos );
485
486         if( i_pos == p_playlist->i_index )
487         {
488             p_playlist->i_index = i_newpos;
489         }
490         else if( i_pos > p_playlist->i_index && i_newpos <= p_playlist->i_index )
491         {
492             p_playlist->i_index++;
493         }
494         else if( i_pos < p_playlist->i_index && i_newpos >= p_playlist->i_index )
495         {
496             p_playlist->i_index--;
497         }
498
499         if ( i_pos < i_newpos )
500         {
501             temp = p_playlist->pp_items[i_pos];
502             while ( i_pos < i_newpos )
503             {
504                 p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos+1];
505                 i_pos++;
506             }
507             p_playlist->pp_items[i_newpos] = temp;
508         }
509         else if ( i_pos > i_newpos )
510         {
511             temp = p_playlist->pp_items[i_pos];
512             while ( i_pos > i_newpos )
513             {
514                 p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos-1];
515                 i_pos--;
516             }
517             p_playlist->pp_items[i_newpos] = temp;
518         }
519     }
520
521     vlc_mutex_unlock( &p_playlist->object_lock );
522
523     val.b_bool = VLC_TRUE;
524     var_Set( p_playlist, "intf-change", val );
525
526     return 0;
527 }