]> git.sesse.net Git - vlc/blob - src/playlist/item-ext.c
* Fixed some doxygen comments.
[vlc] / src / playlist / item-ext.c
1 /*****************************************************************************
2  * item-ext.c : Exported playlist item functions
3  *****************************************************************************
4  * Copyright (C) 1999-2004 VideoLAN
5  * $Id: item-ext.c,v 1.7 2004/01/10 14:24:33 hartman Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *          Clément Stenac <zorglub@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24 #include <stdlib.h>                                      /* free(), strtol() */
25 #include <stdio.h>                                              /* sprintf() */
26 #include <string.h>                                            /* strerror() */
27
28 #include <vlc/vlc.h>
29 #include <vlc/vout.h>
30 #include <vlc/sout.h>
31
32 #include "vlc_playlist.h"
33
34 /**
35  * Add a MRL into the playlist.
36  *
37  * \param p_playlist the playlist to add into
38  * \param psz_uri the mrl to add to the playlist
39  * \param psz_name a text giving a name or description of this item
40  * \param i_mode the mode used when adding
41  * \param i_pos the position in the playlist where to add. If this is
42  *        PLAYLIST_END the item will be added at the end of the playlist
43  *        regardless of it's size
44  * \param i_duration length of the item in milliseconds.
45  * \return the position of the new item
46 */
47 int playlist_AddWDuration( playlist_t *p_playlist, const char * psz_uri,
48                            const char *psz_name, int i_mode, int i_pos,
49                            mtime_t i_duration )
50 {
51     playlist_item_t * p_item;
52
53     p_item = malloc( sizeof( playlist_item_t ) );
54     if( p_item == NULL )
55     {
56         msg_Err( p_playlist, "out of memory" );
57     }
58     if( psz_uri == NULL)
59     {
60         msg_Err( p_playlist, "Not adding NULL item");
61         return -1;
62     }
63     p_item->psz_uri    = strdup( psz_uri );
64     if( psz_name != NULL )
65     {
66         p_item->psz_name   = strdup( psz_name );
67     }
68     else
69     {
70         p_item->psz_name = strdup ( psz_uri );
71     }
72     p_item->i_status = 0;
73     p_item->b_autodeletion = VLC_FALSE;
74     p_item->b_enabled = VLC_TRUE;
75     p_item->i_group = PLAYLIST_TYPE_MANUAL;
76     p_item->i_duration = i_duration;
77
78     p_item->pp_categories = NULL;
79     p_item->i_categories = 0;
80
81     playlist_CreateItemCategory( p_item, _("General") );
82     playlist_CreateItemCategory( p_item, _("Options") );
83     return playlist_AddItem( p_playlist, p_item, i_mode, i_pos );
84 }
85
86 /**
87  * Add a MRL into the playlist.
88  *
89  * \param p_playlist the playlist to add into
90  * \param psz_uri the mrl to add to the playlist
91  * \param psz_name a text giving a name or description of this item
92  * \param i_mode the mode used when adding
93  * \param i_pos the position in the playlist where to add. If this is
94  *        PLAYLIST_END the item will be added at the end of the playlist
95  *        regardless of it's size
96  * \return the position of the new item
97 */
98 int playlist_Add( playlist_t *p_playlist, const char * psz_uri,
99                      const char *psz_name, int i_mode, int i_pos )
100 {
101   return playlist_AddWDuration ( p_playlist, psz_uri, psz_name, i_mode, i_pos,
102                                  -1 );
103 }
104
105 /**
106  * Search the position of an item by its id
107  * \param p_playlist the playlist
108  * \param i_id the id to find
109  * \return the position, or -1 on failure
110  */
111 int playlist_GetPositionById( playlist_t * p_playlist , int i_id )
112 {
113     int i;
114     for( i =  0 ; i < p_playlist->i_size ; i++ )
115     {
116         if( p_playlist->pp_items[i]->i_id == i_id )
117         {
118             return i;
119         }
120     }
121     return -1;
122 }
123
124
125 /**
126  * Search an item by its id
127  * \param p_playlist the playlist
128  * \param i_id the id to find
129  * \return the item, or NULL on failure
130  */
131 playlist_item_t * playlist_GetItemById( playlist_t * p_playlist , int i_id )
132 {
133     int i;
134     for( i =  0 ; i < p_playlist->i_size ; i++ )
135     {
136         if( p_playlist->pp_items[i]->i_id == i_id )
137         {
138             return p_playlist->pp_items[i];
139         }
140     }
141     return NULL;
142 }
143
144 /**********************************************************************
145  * playlist_item_t structure accessors
146  * These functions give access to the fields of the playlist_item_t
147  * structure
148  **********************************************************************/
149
150 /**
151  * Set the group of a playlist item
152  *
153  * \param p_playlist the playlist
154  * \param i_pos the postition of the item of which we change the group
155  * \param i_group the new group
156  * \return 0 on success, -1 on failure
157  */
158 int playlist_SetGroup( playlist_t *p_playlist, int i_pos, int i_group )
159 {
160     char *psz_group;
161     /* Check the existence of the playlist */
162     if( p_playlist == NULL)
163     {
164         return -1;
165     }
166     /* Get a correct item */
167     if( i_pos >= 0 && i_pos < p_playlist->i_size )
168     {
169     }
170     else if( p_playlist->i_size > 0 )
171     {
172         i_pos = p_playlist->i_index;
173     }
174     else
175     {
176         return -1;
177     }
178
179     psz_group = playlist_FindGroup( p_playlist , i_group );
180     if( psz_group != NULL)
181     {
182         p_playlist->pp_items[i_pos]->i_group = i_group ;
183     }
184     return 0;
185 }
186
187 /**
188  * Set the name of a playlist item
189  *
190  * \param p_playlist the playlist
191  * \param i_pos the position of the item of which we change the name
192  * \param psz_name the new name
193  * \return VLC_SUCCESS on success, VLC_EGENERIC on failure
194  */
195 int playlist_SetName( playlist_t *p_playlist, int i_pos, char *psz_name )
196 {
197     vlc_value_t val;
198
199     /* Check the existence of the playlist */
200     if( p_playlist == NULL)
201     {
202         return -1;
203     }
204     /* Get a correct item */
205     if( i_pos >= 0 && i_pos < p_playlist->i_size )
206     {
207     }
208     else if( p_playlist->i_size > 0 )
209     {
210         i_pos = p_playlist->i_index;
211     }
212     else
213     {
214         return -1;
215     }
216
217     if( p_playlist->pp_items[i_pos]->psz_name)
218         free( p_playlist->pp_items[i_pos]->psz_name );
219
220     if( psz_name )
221         p_playlist->pp_items[i_pos]->psz_name = strdup( psz_name );
222
223     val.b_bool = i_pos;
224     var_Set( p_playlist, "item-change", val );
225     return VLC_SUCCESS;
226 }
227
228 /**
229  * Set the duration of a playlist item
230  *
231  * \param p_playlist the playlist
232  * \param i_pos the position of the item of which we change the duration
233  * \param i_duration the duration to set
234  * \return VLC_SUCCESS on success, VLC_EGENERIC on failure
235  */
236 int playlist_SetDuration( playlist_t *p_playlist, int i_pos, mtime_t i_duration )
237 {
238     char psz_buffer[MSTRTIME_MAX_SIZE];
239     vlc_value_t val;
240
241     /* Check the existence of the playlist */
242     if( p_playlist == NULL)
243     {
244         return -1;
245     }
246     /* Get a correct item */
247     if( i_pos >= 0 && i_pos < p_playlist->i_size )
248     {
249     }
250     else if( p_playlist->i_size > 0 )
251     {
252         i_pos = p_playlist->i_index;
253     }
254     else
255     {
256         return VLC_EGENERIC;
257     }
258
259     p_playlist->pp_items[i_pos]->i_duration = i_duration;
260     if( i_duration != -1 )
261     {
262         secstotimestr( psz_buffer, i_duration/1000000 );
263     }
264     else
265     {
266         memcpy( psz_buffer, "--:--:--", sizeof("--:--:--") );
267     }
268     playlist_AddInfo( p_playlist, i_pos, _("General") , _("Duration"),
269                       "%s", psz_buffer );
270
271     val.b_bool = i_pos;
272     var_Set( p_playlist, "item-change", val );
273     return VLC_SUCCESS;
274 }
275
276 /**********************************************************************
277  * Actions on existing playlist items
278  **********************************************************************/
279
280
281 /**
282  * delete an item from a playlist.
283  *
284  * \param p_playlist the playlist to remove from.
285  * \param i_pos the position of the item to remove
286  * \return returns 0
287  */
288 int playlist_Delete( playlist_t * p_playlist, int i_pos )
289 {
290     vlc_value_t     val;
291     int i,j;
292
293     /* if i_pos is the current played item, playlist should stop playing it */
294     if( ( p_playlist->i_status == PLAYLIST_RUNNING) && (p_playlist->i_index == i_pos) )
295     {
296         playlist_Command( p_playlist, PLAYLIST_STOP, 0 );
297     }
298
299     vlc_mutex_lock( &p_playlist->object_lock );
300     if( i_pos >= 0 && i_pos < p_playlist->i_size )
301     {
302         playlist_item_t *p_item = p_playlist->pp_items[i_pos];
303
304         msg_Dbg( p_playlist, "deleting playlist item « %s »",
305                  p_item->psz_name );
306
307         if( p_item->psz_name )
308         {
309             free( p_item->psz_name );
310         }
311         if( p_item->psz_uri )
312         {
313             free( p_item->psz_uri );
314         }
315
316         /* Free the info categories. Welcome to the segfault factory */
317         if( p_item->i_categories > 0 )
318         {
319             for( i = 0; i < p_item->i_categories; i++ )
320             {
321                 for( j= 0 ; j < p_item->pp_categories[i]->i_infos; j++)
322                 {
323                     if( p_item->pp_categories[i]->pp_infos[j]->psz_name)
324                     {
325                         free( p_item->pp_categories[i]->
326                                       pp_infos[j]->psz_name);
327                     }
328                     if( p_item->pp_categories[i]->pp_infos[j]->psz_value)
329                     {
330                         free( p_item->pp_categories[i]->
331                                       pp_infos[j]->psz_value);
332                     }
333                     free( p_item->pp_categories[i]->pp_infos[j] );
334                 }
335                 if( p_item->pp_categories[i]->i_infos )
336                     free( p_item->pp_categories[i]->pp_infos );
337
338                 if( p_item->pp_categories[i]->psz_name)
339                 {
340                     free( p_item->pp_categories[i]->psz_name );
341                 }
342                 free( p_item->pp_categories[i] );
343             }
344             free( p_item->pp_categories );
345         }
346
347         /* XXX: what if the item is still in use? */
348         free( p_item );
349
350         if( i_pos <= p_playlist->i_index )
351         {
352             p_playlist->i_index--;
353         }
354
355         /* Renumber the playlist */
356         REMOVE_ELEM( p_playlist->pp_items,
357                      p_playlist->i_size,
358                      i_pos );
359         if( p_playlist->i_enabled > 0 )
360             p_playlist->i_enabled--;
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
373 /**
374  * Clear all playlist items
375  *
376  * \param p_playlist the playlist to be cleared.
377  * \return returns 0
378  */
379 int playlist_Clear( playlist_t * p_playlist ) {
380
381     while( p_playlist->i_groups > 0 )
382     {
383         playlist_DeleteGroup( p_playlist, p_playlist->pp_groups[0]->i_id );
384     }
385
386     while( p_playlist->i_size > 0 )
387     {
388         playlist_Delete( p_playlist, 0 );
389     }
390     return 0;
391 }
392
393
394 /**
395  * Disables a playlist item
396  *
397  * \param p_playlist the playlist to disable from.
398  * \param i_pos the position of the item to disable
399  * \return returns 0
400  */
401 int playlist_Disable( playlist_t * p_playlist, int i_pos )
402 {
403     vlc_value_t     val;
404     vlc_mutex_lock( &p_playlist->object_lock );
405
406
407     if( i_pos >= 0 && i_pos < p_playlist->i_size )
408     {
409         msg_Dbg( p_playlist, "disabling playlist item « %s »",
410                              p_playlist->pp_items[i_pos]->psz_name );
411
412         if( p_playlist->pp_items[i_pos]->b_enabled == VLC_TRUE )
413             p_playlist->i_enabled--;
414         p_playlist->pp_items[i_pos]->b_enabled = VLC_FALSE;
415     }
416
417     vlc_mutex_unlock( &p_playlist->object_lock );
418
419     val.b_bool = i_pos;
420     var_Set( p_playlist, "item-change", val );
421
422     return 0;
423 }
424
425 /**
426  * Enables a playlist item
427  *
428  * \param p_playlist the playlist to enable from.
429  * \param i_pos the position of the item to enable
430  * \return returns 0
431  */
432 int playlist_Enable( playlist_t * p_playlist, int i_pos )
433 {
434     vlc_value_t     val;
435     vlc_mutex_lock( &p_playlist->object_lock );
436
437     if( i_pos >= 0 && i_pos < p_playlist->i_size )
438     {
439         msg_Dbg( p_playlist, "enabling playlist item « %s »",
440                              p_playlist->pp_items[i_pos]->psz_name );
441
442         if( p_playlist->pp_items[i_pos]->b_enabled == VLC_FALSE )
443             p_playlist->i_enabled++;
444
445         p_playlist->pp_items[i_pos]->b_enabled = VLC_TRUE;
446     }
447
448     vlc_mutex_unlock( &p_playlist->object_lock );
449
450     val.b_bool = i_pos;
451     var_Set( p_playlist, "item-change", val );
452
453     return 0;
454 }
455
456 /**
457  * Disables a playlist group
458  *
459  * \param p_playlist the playlist to disable from.
460  * \param i_group the id of the group to disable
461  * \return returns 0
462  */
463 int playlist_DisableGroup( playlist_t * p_playlist, int i_group)
464 {
465     vlc_value_t     val;
466     int i;
467     vlc_mutex_lock( &p_playlist->object_lock );
468
469     msg_Dbg(p_playlist,"Disabling group %i",i_group);
470     for( i = 0 ; i< p_playlist->i_size; i++ )
471     {
472         if( p_playlist->pp_items[i]->i_group == i_group )
473         {
474             msg_Dbg( p_playlist, "disabling playlist item « %s »",
475                            p_playlist->pp_items[i]->psz_name );
476
477             if( p_playlist->pp_items[i]->b_enabled == VLC_TRUE )
478                 p_playlist->i_enabled--;
479
480             p_playlist->pp_items[i]->b_enabled = VLC_FALSE;
481             val.b_bool = i;
482             var_Set( p_playlist, "item-change", val );
483         }
484     }
485     vlc_mutex_unlock( &p_playlist->object_lock );
486
487     return 0;
488 }
489
490 /**
491  * Enables a playlist group
492  *
493  * \param p_playlist the playlist to enable from.
494  * \param i_group the id of the group to enable
495  * \return returns 0
496  */
497 int playlist_EnableGroup( playlist_t * p_playlist, int i_group)
498 {
499     vlc_value_t     val;
500     int i;
501     vlc_mutex_lock( &p_playlist->object_lock );
502
503     for( i = 0 ; i< p_playlist->i_size; i++ )
504     {
505         if( p_playlist->pp_items[i]->i_group == i_group )
506         {
507             msg_Dbg( p_playlist, "enabling playlist item « %s »",
508                            p_playlist->pp_items[i]->psz_name );
509
510             if( p_playlist->pp_items[i]->b_enabled == VLC_FALSE )
511                 p_playlist->i_enabled++;
512
513             p_playlist->pp_items[i]->b_enabled = VLC_TRUE;
514             val.b_bool = i;
515             var_Set( p_playlist, "item-change", val );
516         }
517     }
518     vlc_mutex_unlock( &p_playlist->object_lock );
519
520     return 0;
521 }
522
523 /**
524  * Move an item in a playlist
525  *
526  * Move the item in the playlist with position i_pos before the current item
527  * at position i_newpos.
528  * \param p_playlist the playlist to move items in
529  * \param i_pos the position of the item to move
530  * \param i_newpos the position of the item that will be behind the moved item
531  *        after the move
532  * \return returns 0
533  */
534 int playlist_Move( playlist_t * p_playlist, int i_pos, int i_newpos)
535 {
536     vlc_value_t     val;
537     vlc_mutex_lock( &p_playlist->object_lock );
538
539     /* take into account that our own row disappears. */
540     if ( i_pos < i_newpos ) i_newpos--;
541
542     if( i_pos >= 0 && i_newpos >=0 && i_pos <= p_playlist->i_size
543                      && i_newpos <= p_playlist->i_size )
544     {
545         playlist_item_t * temp;
546
547         msg_Dbg( p_playlist, "moving playlist item « %s » (%i -> %i)",
548                              p_playlist->pp_items[i_pos]->psz_name, i_pos,
549                              i_newpos );
550
551         if( i_pos == p_playlist->i_index )
552         {
553             p_playlist->i_index = i_newpos;
554         }
555         else if( i_pos > p_playlist->i_index && i_newpos <= p_playlist->i_index )
556         {
557             p_playlist->i_index++;
558         }
559         else if( i_pos < p_playlist->i_index && i_newpos >= p_playlist->i_index )
560         {
561             p_playlist->i_index--;
562         }
563
564         if ( i_pos < i_newpos )
565         {
566             temp = p_playlist->pp_items[i_pos];
567             while ( i_pos < i_newpos )
568             {
569                 p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos+1];
570                 i_pos++;
571             }
572             p_playlist->pp_items[i_newpos] = temp;
573         }
574         else if ( i_pos > i_newpos )
575         {
576             temp = p_playlist->pp_items[i_pos];
577             while ( i_pos > i_newpos )
578             {
579                 p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos-1];
580                 i_pos--;
581             }
582             p_playlist->pp_items[i_newpos] = temp;
583         }
584     }
585
586     vlc_mutex_unlock( &p_playlist->object_lock );
587
588     val.b_bool = VLC_TRUE;
589     var_Set( p_playlist, "intf-change", val );
590
591     return 0;
592 }