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