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