]> git.sesse.net Git - vlc/blob - src/playlist/item.c
src/playlist/item.c:
[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.2 2003/11/22 12:35:17 sigmunau 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 >= 0 && i_pos < p_playlist->i_size )
259     {
260         msg_Dbg( p_playlist, "deleting playlist item « %s »",
261                              p_playlist->pp_items[i_pos]->psz_name );
262
263         if( p_playlist->pp_items[i_pos]->psz_name )
264         {
265             free( p_playlist->pp_items[i_pos]->psz_name );
266         }
267         if( p_playlist->pp_items[i_pos]->psz_uri )
268         {
269             free( p_playlist->pp_items[i_pos]->psz_uri );
270         }
271         if( p_playlist->pp_items[i_pos]->psz_author )
272         {
273             free( p_playlist->pp_items[i_pos]->psz_author );
274         }
275         if( p_playlist->pp_items[i_pos]->i_options )
276         {
277             int i;
278
279             for( i = 0; i < p_playlist->pp_items[i_pos]->i_options; i++ )
280                 free( p_playlist->pp_items[i_pos]->ppsz_options[i] );
281
282             free( p_playlist->pp_items[i_pos]->ppsz_options );
283         }
284
285         /* XXX: what if the item is still in use? */
286         free( p_playlist->pp_items[i_pos] );
287
288         if( i_pos <= p_playlist->i_index )
289         {
290             p_playlist->i_index--;
291         }
292
293         /* Renumber the playlist */
294         REMOVE_ELEM( p_playlist->pp_items,
295                      p_playlist->i_size,
296                      i_pos );
297         if( p_playlist->i_enabled > 0 )
298             p_playlist->i_enabled--;
299     }
300
301     vlc_mutex_unlock( &p_playlist->object_lock );
302
303     val.b_bool = VLC_TRUE;
304     var_Set( p_playlist, "intf-change", val );
305
306     return 0;
307 }
308
309 /**
310  * Disables a playlist item
311  *
312  * \param p_playlist the playlist to disable from.
313  * \param i_pos the position of the item to disable
314  * \return returns 0
315  */
316 int playlist_Disable( playlist_t * p_playlist, int i_pos )
317 {
318     vlc_value_t     val;
319     vlc_mutex_lock( &p_playlist->object_lock );
320
321
322     if( i_pos >= 0 && i_pos < p_playlist->i_size )
323     {
324         msg_Dbg( p_playlist, "disabling playlist item « %s »",
325                              p_playlist->pp_items[i_pos]->psz_name );
326
327         if( p_playlist->pp_items[i_pos]->b_enabled == VLC_TRUE )
328             p_playlist->i_enabled--;
329         p_playlist->pp_items[i_pos]->b_enabled = VLC_FALSE;
330     }
331
332     vlc_mutex_unlock( &p_playlist->object_lock );
333
334     val.b_bool = VLC_TRUE;
335     var_Set( p_playlist, "intf-change", val );
336
337     return 0;
338 }
339
340 /**
341  * Enables a playlist item
342  *
343  * \param p_playlist the playlist to enable from.
344  * \param i_pos the position of the item to enable
345  * \return returns 0
346  */
347 int playlist_Enable( playlist_t * p_playlist, int i_pos )
348 {
349     vlc_value_t     val;
350     vlc_mutex_lock( &p_playlist->object_lock );
351
352     if( i_pos >= 0 && i_pos < p_playlist->i_size )
353     {
354         msg_Dbg( p_playlist, "enabling playlist item « %s »",
355                              p_playlist->pp_items[i_pos]->psz_name );
356
357         if( p_playlist->pp_items[i_pos]->b_enabled == VLC_FALSE )
358             p_playlist->i_enabled++;
359
360         p_playlist->pp_items[i_pos]->b_enabled = VLC_TRUE;
361     }
362
363     vlc_mutex_unlock( &p_playlist->object_lock );
364
365     val.b_bool = VLC_TRUE;
366     var_Set( p_playlist, "intf-change", val );
367
368     return 0;
369 }
370
371 /**
372  * Disables a playlist group
373  *
374  * \param p_playlist the playlist to disable from.
375  * \param i_pos the id of the group to disable
376  * \return returns 0
377  */
378 int playlist_DisableGroup( playlist_t * p_playlist, int i_group)
379 {
380     vlc_value_t     val;
381     int i;
382     vlc_mutex_lock( &p_playlist->object_lock );
383
384     msg_Dbg(p_playlist,"Disabling group %i",i_group);
385     for( i = 0 ; i< p_playlist->i_size; i++ )
386     {
387         if( p_playlist->pp_items[i]->i_group == i_group )
388         {
389             msg_Dbg( p_playlist, "disabling playlist item « %s »",
390                            p_playlist->pp_items[i]->psz_name );
391
392             if( p_playlist->pp_items[i]->b_enabled == VLC_TRUE )
393                 p_playlist->i_enabled--;
394
395             p_playlist->pp_items[i]->b_enabled = VLC_FALSE;
396         }
397     }
398     vlc_mutex_unlock( &p_playlist->object_lock );
399
400     val.b_bool = VLC_TRUE;
401     var_Set( p_playlist, "intf-change", val );
402
403     return 0;
404 }
405
406 /**
407  * Enables a playlist group
408  *
409  * \param p_playlist the playlist to enable from.
410  * \param i_pos the id of the group to enable
411  * \return returns 0
412  */
413 int playlist_EnableGroup( playlist_t * p_playlist, int i_group)
414 {
415     vlc_value_t     val;
416     int i;
417     vlc_mutex_lock( &p_playlist->object_lock );
418
419     for( i = 0 ; i< p_playlist->i_size; i++ )
420     {
421         if( p_playlist->pp_items[i]->i_group == i_group )
422         {
423             msg_Dbg( p_playlist, "enabling playlist item « %s »",
424                            p_playlist->pp_items[i]->psz_name );
425
426             if( p_playlist->pp_items[i]->b_enabled == VLC_FALSE )
427                 p_playlist->i_enabled++;
428
429             p_playlist->pp_items[i]->b_enabled = VLC_TRUE;
430         }
431     }
432     vlc_mutex_unlock( &p_playlist->object_lock );
433
434     val.b_bool = VLC_TRUE;
435     var_Set( p_playlist, "intf-change", val );
436
437     return 0;
438 }
439
440 /**
441  * Move an item in a playlist
442  *
443  * Move the item in the playlist with position i_pos before the current item
444  * at position i_newpos.
445  * \param p_playlist the playlist to move items in
446  * \param i_pos the position of the item to move
447  * \param i_newpos the position of the item that will be behind the moved item
448  *        after the move
449  * \return returns 0
450  */
451 int playlist_Move( playlist_t * p_playlist, int i_pos, int i_newpos)
452 {
453     vlc_value_t     val;
454     vlc_mutex_lock( &p_playlist->object_lock );
455
456     /* take into account that our own row disappears. */
457     if ( i_pos < i_newpos ) i_newpos--;
458
459     if( i_pos >= 0 && i_newpos >=0 && i_pos <= p_playlist->i_size
460                      && i_newpos <= p_playlist->i_size )
461     {
462         playlist_item_t * temp;
463
464         msg_Dbg( p_playlist, "moving playlist item « %s » (%i -> %i)",
465                              p_playlist->pp_items[i_pos]->psz_name, i_pos,
466                              i_newpos );
467
468         if( i_pos == p_playlist->i_index )
469         {
470             p_playlist->i_index = i_newpos;
471         }
472         else if( i_pos > p_playlist->i_index && i_newpos <= p_playlist->i_index )
473         {
474             p_playlist->i_index++;
475         }
476         else if( i_pos < p_playlist->i_index && i_newpos >= p_playlist->i_index )
477         {
478             p_playlist->i_index--;
479         }
480
481         if ( i_pos < i_newpos )
482         {
483             temp = p_playlist->pp_items[i_pos];
484             while ( i_pos < i_newpos )
485             {
486                 p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos+1];
487                 i_pos++;
488             }
489             p_playlist->pp_items[i_newpos] = temp;
490         }
491         else if ( i_pos > i_newpos )
492         {
493             temp = p_playlist->pp_items[i_pos];
494             while ( i_pos > i_newpos )
495             {
496                 p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos-1];
497                 i_pos--;
498             }
499             p_playlist->pp_items[i_newpos] = temp;
500         }
501     }
502
503     vlc_mutex_unlock( &p_playlist->object_lock );
504
505     val.b_bool = VLC_TRUE;
506     var_Set( p_playlist, "intf-change", val );
507
508     return 0;
509 }