]> git.sesse.net Git - vlc/blob - src/playlist/item-ext.c
d8f876a89684a28e106c3307ec524aa606f37ff8
[vlc] / src / playlist / item-ext.c
1 /*****************************************************************************
2  * item-ext.c : Exported playlist item functions
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: item-ext.c,v 1.2 2004/01/05 14:42:14 zorglub 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  * \return the position of the new item
45 */
46 int playlist_Add( playlist_t *p_playlist, const char * psz_uri,
47                      const char *psz_name, int i_mode, int i_pos )
48 {
49     playlist_item_t * p_item;
50
51     p_item = malloc( sizeof( playlist_item_t ) );
52     if( p_item == NULL )
53     {
54         msg_Err( p_playlist, "out of memory" );
55     }
56     if( psz_uri == NULL)
57     {
58         msg_Err( p_playlist, "Not adding NULL item");
59         return -1;
60     }
61     p_item->psz_uri    = strdup( psz_uri );
62     if( psz_name != NULL )
63     {
64         p_item->psz_name   = strdup( psz_name );
65     }
66     else
67     {
68         p_item->psz_name = strdup ( psz_uri );
69     }
70     p_item->i_status = 0;
71     p_item->b_autodeletion = VLC_FALSE;
72     p_item->b_enabled = VLC_TRUE;
73     p_item->i_group = PLAYLIST_TYPE_MANUAL;
74     p_item->i_duration = -1;
75
76     p_item->pp_categories = NULL;
77     p_item->i_categories = 0;
78
79     playlist_CreateItemCategory( p_item, _("General") );
80     playlist_CreateItemCategory( p_item, _("Options") );
81     return playlist_AddItem( p_playlist, p_item, i_mode, i_pos );
82 }
83
84 /**
85  * Search the position of an item by its id
86  * \param p_playlist the playlist
87  * \param i_id the id to find
88  * \return the position, or -1 on failure
89  */
90 int playlist_GetPositionById( playlist_t * p_playlist , int i_id )
91 {
92     int i;
93     for( i =  0 ; i < p_playlist->i_size ; i++ )
94     {
95         if( p_playlist->pp_items[i]->i_id == i_id )
96         {
97             return i;
98         }
99     }
100     return -1;
101 }
102
103
104 /**
105  * Search an item by its id
106  * \param p_playlist the playlist
107  * \param i_id the id to find
108  * \return the item, or NULL on failure
109  */
110 playlist_item_t * playlist_GetItemById( playlist_t * p_playlist , int i_id )
111 {
112     int i;
113     for( i =  0 ; i < p_playlist->i_size ; i++ )
114     {
115         if( p_playlist->pp_items[i]->i_id == i_id )
116         {
117             return p_playlist->pp_items[i];
118         }
119     }
120     return NULL;
121 }
122
123 /**********************************************************************
124  * playlist_item_t structure accessors
125  * These functions give access to the fields of the playlist_item_t
126  * structure
127  **********************************************************************/
128
129 /**
130  * Set the group of a playlist item
131  *
132  * \param p_playlist the playlist
133  * \param i_item the item of which we change the group
134  * \param i_group the new group
135  * \return 0 on success, -1 on failure
136  */
137 int playlist_SetGroup( playlist_t *p_playlist, int i_item, int i_group )
138 {
139     char *psz_group;
140     /* Check the existence of the playlist */
141     if( p_playlist == NULL)
142     {
143         return -1;
144     }
145     /* Get a correct item */
146     if( i_item >= 0 && i_item < p_playlist->i_size )
147     {
148     }
149     else if( p_playlist->i_size > 0 )
150     {
151         i_item = p_playlist->i_index;
152     }
153     else
154     {
155         return -1;
156     }
157
158     psz_group = playlist_FindGroup( p_playlist , i_group );
159     if( psz_group != NULL)
160     {
161         p_playlist->pp_items[i_item]->i_group = i_group ;
162     }
163     return 0;
164 }
165
166 /**
167  * Set the name of a playlist item
168  *
169  * \param p_playlist the playlist
170  * \param i_item the item of which we change the name
171  * \param psz_name the new name
172  * \return VLC_SUCCESS on success, VLC_EGENERIC on failure
173  */
174 int playlist_SetName( playlist_t *p_playlist, int i_item, char *psz_name )
175 {
176     vlc_value_t val;
177
178     /* Check the existence of the playlist */
179     if( p_playlist == NULL)
180     {
181         return -1;
182     }
183     /* Get a correct item */
184     if( i_item >= 0 && i_item < p_playlist->i_size )
185     {
186     }
187     else if( p_playlist->i_size > 0 )
188     {
189         i_item = p_playlist->i_index;
190     }
191     else
192     {
193         return -1;
194     }
195
196     if( p_playlist->pp_items[i_item]->psz_name)
197         free( p_playlist->pp_items[i_item]->psz_name );
198
199     if( psz_name )
200         p_playlist->pp_items[i_item]->psz_name = strdup( psz_name );
201
202     val.b_bool = i_item;
203     var_Set( p_playlist, "item-change", val );
204     return VLC_SUCCESS;
205 }
206
207 /**
208  * Set the duration of a playlist item
209  *
210  * \param p_playlist the playlist
211  * \param i_item the item of which we change the name
212  * \param i_duration the duration to set
213  * \return VLC_SUCCESS on success, VLC_EGENERIC on failure
214  */
215 int playlist_SetDuration( playlist_t *p_playlist, int i_item, int i_duration )
216 {
217     char psz_buffer[MSTRTIME_MAX_SIZE];
218     vlc_value_t val;
219
220     /* Check the existence of the playlist */
221     if( p_playlist == NULL)
222     {
223         return -1;
224     }
225     /* Get a correct item */
226     if( i_item >= 0 && i_item < p_playlist->i_size )
227     {
228     }
229     else if( p_playlist->i_size > 0 )
230     {
231         i_item = p_playlist->i_index;
232     }
233     else
234     {
235         return VLC_EGENERIC;
236     }
237
238     p_playlist->pp_items[i_item]->i_duration = i_duration;
239     if( i_duration != -1 )
240     {
241         secstotimestr( psz_buffer, i_duration/1000000 );
242     }
243     else
244     {
245         memcpy( psz_buffer, "--:--:--", sizeof("--:--:--") );
246     }
247     playlist_AddInfo( p_playlist, i_item, _("General") , _("Duration"),
248                       "%s", psz_buffer );
249
250     val.b_bool = i_item;
251     var_Set( p_playlist, "item-change", val );
252     return VLC_SUCCESS;
253 }
254
255 /**********************************************************************
256  * Actions on existing playlist items
257  **********************************************************************/
258
259
260 /**
261  * delete an item from a playlist.
262  *
263  * \param p_playlist the playlist to remove from.
264  * \param i_pos the position of the item to remove
265  * \return returns 0
266  */
267 int playlist_Delete( playlist_t * p_playlist, int i_pos )
268 {
269     vlc_value_t     val;
270     int i,j;
271
272     /* if i_pos is the current played item, playlist should stop playing it */
273     if( ( p_playlist->i_status == PLAYLIST_RUNNING) && (p_playlist->i_index == i_pos) )
274     {
275         playlist_Command( p_playlist, PLAYLIST_STOP, 0 );
276     }
277
278     vlc_mutex_lock( &p_playlist->object_lock );
279     if( i_pos >= 0 && i_pos < p_playlist->i_size )
280     {
281         playlist_item_t *p_item = p_playlist->pp_items[i_pos];
282
283         msg_Dbg( p_playlist, "deleting playlist item « %s »",
284                  p_item->psz_name );
285
286         if( p_item->psz_name )
287         {
288             free( p_item->psz_name );
289         }
290         if( p_item->psz_uri )
291         {
292             free( p_item->psz_uri );
293         }
294
295         /* Free the info categories. Welcome to the segfault factory */
296         if( p_item->i_categories > 0 )
297         {
298             for( i = 0; i < p_item->i_categories; i++ )
299             {
300                 for( j= 0 ; j < p_item->pp_categories[i]->i_infos; j++)
301                 {
302                     if( p_item->pp_categories[i]->pp_infos[j]->psz_name)
303                     {
304                         free( p_item->pp_categories[i]->
305                                       pp_infos[j]->psz_name);
306                     }
307                     if( p_item->pp_categories[i]->pp_infos[j]->psz_value)
308                     {
309                         free( p_item->pp_categories[i]->
310                                       pp_infos[j]->psz_value);
311                     }
312                     free( p_item->pp_categories[i]->pp_infos[j] );
313                 }
314                 if( p_item->pp_categories[i]->psz_name)
315                 {
316                     free( p_item->pp_categories[i]->psz_name );
317                 }
318                 free( p_item->pp_categories[i] );
319             }
320         }
321
322         /* XXX: what if the item is still in use? */
323         free( p_item );
324
325         if( i_pos <= p_playlist->i_index )
326         {
327             p_playlist->i_index--;
328         }
329
330         /* Renumber the playlist */
331         REMOVE_ELEM( p_playlist->pp_items,
332                      p_playlist->i_size,
333                      i_pos );
334         if( p_playlist->i_enabled > 0 )
335             p_playlist->i_enabled--;
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  * Disables a playlist item
348  *
349  * \param p_playlist the playlist to disable from.
350  * \param i_pos the position of the item to disable
351  * \return returns 0
352  */
353 int playlist_Disable( playlist_t * p_playlist, int i_pos )
354 {
355     vlc_value_t     val;
356     vlc_mutex_lock( &p_playlist->object_lock );
357
358
359     if( i_pos >= 0 && i_pos < p_playlist->i_size )
360     {
361         msg_Dbg( p_playlist, "disabling playlist item « %s »",
362                              p_playlist->pp_items[i_pos]->psz_name );
363
364         if( p_playlist->pp_items[i_pos]->b_enabled == VLC_TRUE )
365             p_playlist->i_enabled--;
366         p_playlist->pp_items[i_pos]->b_enabled = VLC_FALSE;
367     }
368
369     vlc_mutex_unlock( &p_playlist->object_lock );
370
371     val.b_bool = i_pos;
372     var_Set( p_playlist, "item-change", val );
373
374     return 0;
375 }
376
377 /**
378  * Enables a playlist item
379  *
380  * \param p_playlist the playlist to enable from.
381  * \param i_pos the position of the item to enable
382  * \return returns 0
383  */
384 int playlist_Enable( playlist_t * p_playlist, int i_pos )
385 {
386     vlc_value_t     val;
387     vlc_mutex_lock( &p_playlist->object_lock );
388
389     if( i_pos >= 0 && i_pos < p_playlist->i_size )
390     {
391         msg_Dbg( p_playlist, "enabling playlist item « %s »",
392                              p_playlist->pp_items[i_pos]->psz_name );
393
394         if( p_playlist->pp_items[i_pos]->b_enabled == VLC_FALSE )
395             p_playlist->i_enabled++;
396
397         p_playlist->pp_items[i_pos]->b_enabled = VLC_TRUE;
398     }
399
400     vlc_mutex_unlock( &p_playlist->object_lock );
401
402     val.b_bool = i_pos;
403     var_Set( p_playlist, "item-change", val );
404
405     return 0;
406 }
407
408 /**
409  * Disables a playlist group
410  *
411  * \param p_playlist the playlist to disable from.
412  * \param i_pos the id of the group to disable
413  * \return returns 0
414  */
415 int playlist_DisableGroup( playlist_t * p_playlist, int i_group)
416 {
417     vlc_value_t     val;
418     int i;
419     vlc_mutex_lock( &p_playlist->object_lock );
420
421     msg_Dbg(p_playlist,"Disabling group %i",i_group);
422     for( i = 0 ; i< p_playlist->i_size; i++ )
423     {
424         if( p_playlist->pp_items[i]->i_group == i_group )
425         {
426             msg_Dbg( p_playlist, "disabling playlist item « %s »",
427                            p_playlist->pp_items[i]->psz_name );
428
429             if( p_playlist->pp_items[i]->b_enabled == VLC_TRUE )
430                 p_playlist->i_enabled--;
431
432             p_playlist->pp_items[i]->b_enabled = VLC_FALSE;
433             val.b_bool = i;
434             var_Set( p_playlist, "item-change", val );
435         }
436     }
437     vlc_mutex_unlock( &p_playlist->object_lock );
438
439     return 0;
440 }
441
442 /**
443  * Enables a playlist group
444  *
445  * \param p_playlist the playlist to enable from.
446  * \param i_pos the id of the group to enable
447  * \return returns 0
448  */
449 int playlist_EnableGroup( playlist_t * p_playlist, int i_group)
450 {
451     vlc_value_t     val;
452     int i;
453     vlc_mutex_lock( &p_playlist->object_lock );
454
455     for( i = 0 ; i< p_playlist->i_size; i++ )
456     {
457         if( p_playlist->pp_items[i]->i_group == i_group )
458         {
459             msg_Dbg( p_playlist, "enabling playlist item « %s »",
460                            p_playlist->pp_items[i]->psz_name );
461
462             if( p_playlist->pp_items[i]->b_enabled == VLC_FALSE )
463                 p_playlist->i_enabled++;
464
465             p_playlist->pp_items[i]->b_enabled = VLC_TRUE;
466             val.b_bool = i;
467             var_Set( p_playlist, "item-change", val );
468         }
469     }
470     vlc_mutex_unlock( &p_playlist->object_lock );
471
472     return 0;
473 }
474
475 /**
476  * Move an item in a playlist
477  *
478  * Move the item in the playlist with position i_pos before the current item
479  * at position i_newpos.
480  * \param p_playlist the playlist to move items in
481  * \param i_pos the position of the item to move
482  * \param i_newpos the position of the item that will be behind the moved item
483  *        after the move
484  * \return returns 0
485  */
486 int playlist_Move( playlist_t * p_playlist, int i_pos, int i_newpos)
487 {
488     vlc_value_t     val;
489     vlc_mutex_lock( &p_playlist->object_lock );
490
491     /* take into account that our own row disappears. */
492     if ( i_pos < i_newpos ) i_newpos--;
493
494     if( i_pos >= 0 && i_newpos >=0 && i_pos <= p_playlist->i_size
495                      && i_newpos <= p_playlist->i_size )
496     {
497         playlist_item_t * temp;
498
499         msg_Dbg( p_playlist, "moving playlist item « %s » (%i -> %i)",
500                              p_playlist->pp_items[i_pos]->psz_name, i_pos,
501                              i_newpos );
502
503         if( i_pos == p_playlist->i_index )
504         {
505             p_playlist->i_index = i_newpos;
506         }
507         else if( i_pos > p_playlist->i_index && i_newpos <= p_playlist->i_index )
508         {
509             p_playlist->i_index++;
510         }
511         else if( i_pos < p_playlist->i_index && i_newpos >= p_playlist->i_index )
512         {
513             p_playlist->i_index--;
514         }
515
516         if ( i_pos < i_newpos )
517         {
518             temp = p_playlist->pp_items[i_pos];
519             while ( i_pos < i_newpos )
520             {
521                 p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos+1];
522                 i_pos++;
523             }
524             p_playlist->pp_items[i_newpos] = temp;
525         }
526         else if ( i_pos > i_newpos )
527         {
528             temp = p_playlist->pp_items[i_pos];
529             while ( i_pos > i_newpos )
530             {
531                 p_playlist->pp_items[i_pos] = p_playlist->pp_items[i_pos-1];
532                 i_pos--;
533             }
534             p_playlist->pp_items[i_newpos] = temp;
535         }
536     }
537
538     vlc_mutex_unlock( &p_playlist->object_lock );
539
540     val.b_bool = VLC_TRUE;
541     var_Set( p_playlist, "intf-change", val );
542
543     return 0;
544 }