]> git.sesse.net Git - vlc/blob - src/playlist/item.c
Grmbl, it was obvious I would forget to add the new files
[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.1 2003/10/29 18:00:46 zorglub 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                       free( p_item );
143                       vlc_mutex_unlock( &p_playlist->object_lock );
144                       return 0;
145                  }
146              }
147          }
148          i_mode &= ~PLAYLIST_CHECK_INSERT;
149          i_mode |= PLAYLIST_APPEND;
150     }
151
152
153     msg_Dbg( p_playlist, "adding playlist item « %s » ( %s )", p_item->psz_name, p_item->psz_uri);
154
155     /* Create the new playlist item */
156
157
158     /* Do a few boundary checks and allocate space for the item */
159     if( i_pos == PLAYLIST_END )
160     {
161         if( i_mode & PLAYLIST_INSERT )
162         {
163             i_mode &= ~PLAYLIST_INSERT;
164             i_mode |= PLAYLIST_APPEND;
165         }
166
167         i_pos = p_playlist->i_size - 1;
168     }
169
170     if( !(i_mode & PLAYLIST_REPLACE)
171          || i_pos < 0 || i_pos >= p_playlist->i_size )
172     {
173         /* Additional boundary checks */
174         if( i_mode & PLAYLIST_APPEND )
175         {
176             i_pos++;
177         }
178
179         if( i_pos < 0 )
180         {
181             i_pos = 0;
182         }
183         else if( i_pos > p_playlist->i_size )
184         {
185             i_pos = p_playlist->i_size;
186         }
187
188         INSERT_ELEM( p_playlist->pp_items,
189                      p_playlist->i_size,
190                      i_pos,
191                      p_item );
192         p_playlist->i_enabled ++;
193
194         if( p_playlist->i_index >= i_pos )
195         {
196             p_playlist->i_index++;
197         }
198     }
199     else
200     {
201         /* i_mode == PLAYLIST_REPLACE and 0 <= i_pos < p_playlist->i_size */
202         if( p_playlist->pp_items[i_pos]->psz_name )
203         {
204             free( p_playlist->pp_items[i_pos]->psz_name );
205         }
206         if( p_playlist->pp_items[i_pos]->psz_uri )
207         {
208             free( p_playlist->pp_items[i_pos]->psz_uri );
209         }
210         /* XXX: what if the item is still in use? */
211         free( p_playlist->pp_items[i_pos] );
212         p_playlist->pp_items[i_pos] = p_item;
213     }
214
215     if( i_mode & PLAYLIST_GO )
216     {
217         p_playlist->i_index = i_pos;
218         if( p_playlist->p_input )
219         {
220             input_StopThread( p_playlist->p_input );
221         }
222         p_playlist->i_status = PLAYLIST_RUNNING;
223     }
224
225     vlc_mutex_unlock( &p_playlist->object_lock );
226
227     val.b_bool = VLC_TRUE;
228     var_Set( p_playlist, "intf-change", val );
229
230     return 0;
231 }
232
233 /**
234  * delete an item from a playlist.
235  *
236  * \param p_playlist the playlist to remove from.
237  * \param i_pos the position of the item to remove
238  * \return returns 0
239  */
240 int playlist_Delete( playlist_t * p_playlist, int i_pos )
241 {
242     vlc_value_t     val;
243     vlc_mutex_lock( &p_playlist->object_lock );
244
245     if( i_pos >= 0 && i_pos < p_playlist->i_size )
246     {
247         msg_Dbg( p_playlist, "deleting playlist item « %s »",
248                              p_playlist->pp_items[i_pos]->psz_name );
249
250         if( p_playlist->pp_items[i_pos]->psz_name )
251         {
252             free( p_playlist->pp_items[i_pos]->psz_name );
253         }
254         if( p_playlist->pp_items[i_pos]->psz_uri )
255         {
256             free( p_playlist->pp_items[i_pos]->psz_uri );
257         }
258         if( p_playlist->pp_items[i_pos]->psz_author )
259         {
260             free( p_playlist->pp_items[i_pos]->psz_author );
261         }
262         if( p_playlist->pp_items[i_pos]->i_options )
263         {
264             int i;
265
266             for( i = 0; i < p_playlist->pp_items[i_pos]->i_options; i++ )
267                 free( p_playlist->pp_items[i_pos]->ppsz_options[i] );
268
269             free( p_playlist->pp_items[i_pos]->ppsz_options );
270         }
271
272         /* XXX: what if the item is still in use? */
273         free( p_playlist->pp_items[i_pos] );
274
275         if( i_pos <= p_playlist->i_index )
276         {
277             p_playlist->i_index--;
278         }
279
280         /* Renumber the playlist */
281         REMOVE_ELEM( p_playlist->pp_items,
282                      p_playlist->i_size,
283                      i_pos );
284         if( p_playlist->i_enabled > 0 )
285             p_playlist->i_enabled--;
286     }
287
288     vlc_mutex_unlock( &p_playlist->object_lock );
289
290     val.b_bool = VLC_TRUE;
291     var_Set( p_playlist, "intf-change", val );
292
293     return 0;
294 }
295
296 /**
297  * Disables a playlist item
298  *
299  * \param p_playlist the playlist to disable from.
300  * \param i_pos the position of the item to disable
301  * \return returns 0
302  */
303 int playlist_Disable( playlist_t * p_playlist, int i_pos )
304 {
305     vlc_value_t     val;
306     vlc_mutex_lock( &p_playlist->object_lock );
307
308
309     if( i_pos >= 0 && i_pos < p_playlist->i_size )
310     {
311         msg_Dbg( p_playlist, "disabling playlist item « %s »",
312                              p_playlist->pp_items[i_pos]->psz_name );
313
314         if( p_playlist->pp_items[i_pos]->b_enabled == VLC_TRUE )
315             p_playlist->i_enabled--;
316         p_playlist->pp_items[i_pos]->b_enabled = VLC_FALSE;
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  * Enables a playlist item
329  *
330  * \param p_playlist the playlist to enable from.
331  * \param i_pos the position of the item to enable
332  * \return returns 0
333  */
334 int playlist_Enable( playlist_t * p_playlist, int i_pos )
335 {
336     vlc_value_t     val;
337     vlc_mutex_lock( &p_playlist->object_lock );
338
339     if( i_pos >= 0 && i_pos < p_playlist->i_size )
340     {
341         msg_Dbg( p_playlist, "enabling playlist item « %s »",
342                              p_playlist->pp_items[i_pos]->psz_name );
343
344         if( p_playlist->pp_items[i_pos]->b_enabled == VLC_FALSE )
345             p_playlist->i_enabled++;
346
347         p_playlist->pp_items[i_pos]->b_enabled = VLC_TRUE;
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  * Disables a playlist group
360  *
361  * \param p_playlist the playlist to disable from.
362  * \param i_pos the id of the group to disable
363  * \return returns 0
364  */
365 int playlist_DisableGroup( playlist_t * p_playlist, int i_group)
366 {
367     vlc_value_t     val;
368     int i;
369     vlc_mutex_lock( &p_playlist->object_lock );
370
371     msg_Dbg(p_playlist,"Disabling group %i",i_group);
372     for( i = 0 ; i< p_playlist->i_size; i++ )
373     {
374         if( p_playlist->pp_items[i]->i_group == i_group )
375         {
376             msg_Dbg( p_playlist, "disabling playlist item « %s »",
377                            p_playlist->pp_items[i]->psz_name );
378
379             if( p_playlist->pp_items[i]->b_enabled == VLC_TRUE )
380                 p_playlist->i_enabled--;
381
382             p_playlist->pp_items[i]->b_enabled = VLC_FALSE;
383         }
384     }
385     vlc_mutex_unlock( &p_playlist->object_lock );
386
387     val.b_bool = VLC_TRUE;
388     var_Set( p_playlist, "intf-change", val );
389
390     return 0;
391 }
392
393 /**
394  * Enables a playlist group
395  *
396  * \param p_playlist the playlist to enable from.
397  * \param i_pos the id of the group to enable
398  * \return returns 0
399  */
400 int playlist_EnableGroup( playlist_t * p_playlist, int i_group)
401 {
402     vlc_value_t     val;
403     int i;
404     vlc_mutex_lock( &p_playlist->object_lock );
405
406     for( i = 0 ; i< p_playlist->i_size; i++ )
407     {
408         if( p_playlist->pp_items[i]->i_group == i_group )
409         {
410             msg_Dbg( p_playlist, "enabling playlist item « %s »",
411                            p_playlist->pp_items[i]->psz_name );
412
413             if( p_playlist->pp_items[i]->b_enabled == VLC_FALSE )
414                 p_playlist->i_enabled++;
415
416             p_playlist->pp_items[i]->b_enabled = VLC_TRUE;
417         }
418     }
419     vlc_mutex_unlock( &p_playlist->object_lock );
420
421     val.b_bool = VLC_TRUE;
422     var_Set( p_playlist, "intf-change", val );
423
424     return 0;
425 }
426
427 /**
428  * Move an item in a playlist
429  *
430  * Move the item in the playlist with position i_pos before the current item
431  * at position i_newpos.
432  * \param p_playlist the playlist to move items in
433  * \param i_pos the position of the item to move
434  * \param i_newpos the position of the item that will be behind the moved item
435  *        after the move
436  * \return returns 0
437  */
438 int playlist_Move( playlist_t * p_playlist, int i_pos, int i_newpos)
439 {
440     vlc_value_t     val;
441     vlc_mutex_lock( &p_playlist->object_lock );
442
443     /* take into account that our own row disappears. */
444     if ( i_pos < i_newpos ) i_newpos--;
445
446     if( i_pos >= 0 && i_newpos >=0 && i_pos <= p_playlist->i_size
447                      && i_newpos <= p_playlist->i_size )
448     {
449         playlist_item_t * temp;
450
451         msg_Dbg( p_playlist, "moving playlist item « %s » (%i -> %i)",
452                              p_playlist->pp_items[i_pos]->psz_name, i_pos,
453                              i_newpos );
454
455         if( i_pos == p_playlist->i_index )
456         {
457             p_playlist->i_index = i_newpos;
458         }
459         else if( i_pos > p_playlist->i_index && i_newpos <= p_playlist->i_index )
460         {
461             p_playlist->i_index++;
462         }
463         else if( i_pos < p_playlist->i_index && i_newpos >= p_playlist->i_index )
464         {
465             p_playlist->i_index--;
466         }
467
468         if ( i_pos < i_newpos )
469         {
470             temp = p_playlist->pp_items[i_pos];
471             while ( i_pos < i_newpos )
472             {
473                 p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos+1];
474                 i_pos++;
475             }
476             p_playlist->pp_items[i_newpos] = temp;
477         }
478         else if ( i_pos > i_newpos )
479         {
480             temp = p_playlist->pp_items[i_pos];
481             while ( i_pos > i_newpos )
482             {
483                 p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos-1];
484                 i_pos--;
485             }
486             p_playlist->pp_items[i_newpos] = temp;
487         }
488     }
489
490     vlc_mutex_unlock( &p_playlist->object_lock );
491
492     val.b_bool = VLC_TRUE;
493     var_Set( p_playlist, "intf-change", val );
494
495     return 0;
496 }