]> git.sesse.net Git - vlc/blob - src/playlist/control.c
3ee0f5e06b727aaf8fe52d19b3b2c183fb858c46
[vlc] / src / playlist / control.c
1 /*****************************************************************************
2  * control.c : Handle control of the playlist & running through it
3  *****************************************************************************
4  * Copyright (C) 1999-2004 the VideoLAN team
5  * $Id$
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <vlc_common.h>
29 #include "vlc_playlist.h"
30 #include "playlist_internal.h"
31 #include <assert.h>
32
33 /*****************************************************************************
34  * Local prototypes
35  *****************************************************************************/
36 static int PlaylistVAControl( playlist_t * p_playlist, int i_query, va_list args );
37
38 /*****************************************************************************
39  * Playlist control
40  *****************************************************************************/
41
42 static vlc_mutex_t global_lock = VLC_STATIC_MUTEX;
43
44 #undef pl_Hold
45 playlist_t *pl_Hold (vlc_object_t *obj)
46 {
47     playlist_t *pl;
48     libvlc_int_t *p_libvlc = obj->p_libvlc;
49
50     vlc_mutex_lock (&global_lock);
51     pl = libvlc_priv (p_libvlc)->p_playlist;
52     assert (pl != NULL);
53
54     if (!libvlc_priv (p_libvlc)->playlist_active)
55     {
56          playlist_Activate (pl);
57          libvlc_priv (p_libvlc)->playlist_active = true;
58     }
59
60     /* The playlist should hold itself with vlc_object_hold() if ever. */
61     assert (VLC_OBJECT (pl) != obj);
62     if (pl)
63         vlc_object_hold (pl);
64     vlc_mutex_unlock (&global_lock);
65     return pl;
66 }
67
68 #undef pl_Release
69 void pl_Release( vlc_object_t *p_this )
70 {
71     playlist_t *pl = libvlc_priv (p_this->p_libvlc)->p_playlist;
72     assert( pl != NULL );
73
74     /* The rule is that pl_Release() should act on
75        the same object than pl_Hold() */
76     assert( VLC_OBJECT(pl) != p_this);
77
78     vlc_object_release( pl );
79 }
80
81 void pl_Deactivate (libvlc_int_t *p_libvlc)
82 {
83     bool deactivate;
84
85     vlc_mutex_lock (&global_lock);
86     deactivate = libvlc_priv (p_libvlc)->playlist_active;
87     vlc_mutex_unlock (&global_lock);
88
89     if (deactivate)
90         playlist_Deactivate (libvlc_priv (p_libvlc)->p_playlist);
91 }
92
93 void playlist_Lock( playlist_t *pl )
94 {
95     vlc_mutex_lock( &pl_priv(pl)->lock );
96 }
97
98 void playlist_Unlock( playlist_t *pl )
99 {
100     vlc_mutex_unlock( &pl_priv(pl)->lock );
101 }
102
103 void playlist_AssertLocked( playlist_t *pl )
104 {
105     vlc_assert_locked( &pl_priv(pl)->lock );
106 }
107
108 int playlist_Control( playlist_t * p_playlist, int i_query,
109                       bool b_locked, ... )
110 {
111     va_list args;
112     int i_result;
113     PL_LOCK_IF( !b_locked );
114     va_start( args, b_locked );
115     i_result = PlaylistVAControl( p_playlist, i_query, args );
116     va_end( args );
117     PL_UNLOCK_IF( !b_locked );
118
119     return i_result;
120 }
121
122 static int PlaylistVAControl( playlist_t * p_playlist, int i_query, va_list args )
123 {
124     playlist_item_t *p_item, *p_node;
125
126     PL_ASSERT_LOCKED;
127
128     if( !vlc_object_alive( p_playlist ) )
129         return VLC_EGENERIC;
130
131     if( playlist_IsEmpty( p_playlist ) && i_query != PLAYLIST_STOP )
132         return VLC_EGENERIC;
133
134     switch( i_query )
135     {
136     case PLAYLIST_STOP:
137         pl_priv(p_playlist)->request.i_status = PLAYLIST_STOPPED;
138         pl_priv(p_playlist)->request.b_request = true;
139         pl_priv(p_playlist)->request.p_item = NULL;
140         break;
141
142     // Node can be null, it will keep the same. Use with care ...
143     // Item null = take the first child of node
144     case PLAYLIST_VIEWPLAY:
145         p_node = (playlist_item_t *)va_arg( args, playlist_item_t * );
146         p_item = (playlist_item_t *)va_arg( args, playlist_item_t * );
147         if ( p_node == NULL )
148         {
149             p_node = get_current_status_node( p_playlist );
150             assert( p_node );
151         }
152         pl_priv(p_playlist)->request.i_status = PLAYLIST_RUNNING;
153         pl_priv(p_playlist)->request.i_skip = 0;
154         pl_priv(p_playlist)->request.b_request = true;
155         pl_priv(p_playlist)->request.p_node = p_node;
156         pl_priv(p_playlist)->request.p_item = p_item;
157         if( p_item && var_GetBool( p_playlist, "random" ) )
158             pl_priv(p_playlist)->b_reset_currently_playing = true;
159         break;
160
161     case PLAYLIST_PLAY:
162         if( pl_priv(p_playlist)->p_input )
163         {
164             var_SetInteger( pl_priv(p_playlist)->p_input, "state", PLAYING_S );
165             break;
166         }
167         else
168         {
169             pl_priv(p_playlist)->request.i_status = PLAYLIST_RUNNING;
170             pl_priv(p_playlist)->request.b_request = true;
171             pl_priv(p_playlist)->request.p_node = get_current_status_node( p_playlist );
172             pl_priv(p_playlist)->request.p_item = get_current_status_item( p_playlist );
173             pl_priv(p_playlist)->request.i_skip = 0;
174         }
175         break;
176
177     case PLAYLIST_PAUSE:
178         if( !pl_priv(p_playlist)->p_input )
179         {    /* FIXME: is this really useful without input? */
180              pl_priv(p_playlist)->status.i_status = PLAYLIST_PAUSED;
181              break;
182         }
183
184         if( var_GetInteger( pl_priv(p_playlist)->p_input, "state" ) == PAUSE_S )
185         {
186             pl_priv(p_playlist)->status.i_status = PLAYLIST_RUNNING;
187             var_SetInteger( pl_priv(p_playlist)->p_input, "state", PLAYING_S );
188         }
189         else
190         {
191             pl_priv(p_playlist)->status.i_status = PLAYLIST_PAUSED;
192             var_SetInteger( pl_priv(p_playlist)->p_input, "state", PAUSE_S );
193         }
194         break;
195
196     case PLAYLIST_SKIP:
197         pl_priv(p_playlist)->request.p_node = get_current_status_node( p_playlist );
198         pl_priv(p_playlist)->request.p_item = get_current_status_item( p_playlist );
199         pl_priv(p_playlist)->request.i_skip = (int) va_arg( args, int );
200         /* if already running, keep running */
201         if( pl_priv(p_playlist)->status.i_status != PLAYLIST_STOPPED )
202             pl_priv(p_playlist)->request.i_status = pl_priv(p_playlist)->status.i_status;
203         pl_priv(p_playlist)->request.b_request = true;
204         break;
205
206     default:
207         msg_Err( p_playlist, "unknown playlist query" );
208         return VLC_EBADVAR;
209     }
210     vlc_cond_signal( &pl_priv(p_playlist)->signal );
211
212     return VLC_SUCCESS;
213 }
214
215 /*****************************************************************************
216  * Preparse control
217  *****************************************************************************/
218 /** Enqueue an item for preparsing */
219 int playlist_PreparseEnqueue( playlist_t *p_playlist,
220                               input_item_t *p_item, bool b_locked )
221 {
222     playlist_private_t *p_sys = pl_priv(p_playlist);
223
224     PL_LOCK_IF( !b_locked );
225     if( p_sys->p_preparser )
226         playlist_preparser_Push( p_sys->p_preparser, p_item );
227     PL_UNLOCK_IF( !b_locked );
228
229     return VLC_SUCCESS;
230 }
231
232 int playlist_AskForArtEnqueue( playlist_t *p_playlist,
233                                input_item_t *p_item, bool b_locked )
234 {
235     playlist_private_t *p_sys = pl_priv(p_playlist);
236
237     PL_LOCK_IF( !b_locked );
238     if( p_sys->p_fetcher )
239         playlist_fetcher_Push( p_sys->p_fetcher, p_item );
240     PL_UNLOCK_IF( !b_locked );
241
242     return VLC_SUCCESS;
243 }
244