core: playlist: expose a main playlist instance
[vlc.git] / src / interface / interface.c
blob0f47e06fd8a7578838e48674446fd1e39473b2af
1 /*****************************************************************************
2 * interface.c: interface access for other threads
3 * This library provides basic functions for threads to interact with user
4 * interface, such as command line.
5 *****************************************************************************
6 * Copyright (C) 1998-2007 VLC authors and VideoLAN
7 * $Id$
9 * Authors: Vincent Seguin <seguin@via.ecp.fr>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
26 /**
27 * \file
28 * This file contains functions related to interface management
32 /*****************************************************************************
33 * Preamble
34 *****************************************************************************/
36 #ifdef HAVE_CONFIG_H
37 # include "config.h"
38 #endif
40 #include <unistd.h>
42 #include <vlc_common.h>
43 #include <vlc_modules.h>
44 #include <vlc_interface.h>
45 #include <vlc_playlist_legacy.h>
46 #include "libvlc.h"
47 #include "playlist_legacy/playlist_internal.h"
48 #include "../lib/libvlc_internal.h"
50 static int AddIntfCallback( vlc_object_t *, char const *,
51 vlc_value_t , vlc_value_t , void * );
53 /* This lock ensures that the playlist is created only once (per instance). It
54 * also protects the list of running interfaces against concurrent access,
55 * either to add or remove an interface.
57 * However, it does NOT protect from destruction of the playlist by
58 * intf_DestroyAll(). Instead, care must be taken that intf_Create() and any
59 * other function that depends on the playlist is only called BEFORE
60 * intf_DestroyAll() has the possibility to destroy all interfaces.
62 static vlc_mutex_t lock = VLC_STATIC_MUTEX;
64 /**
65 * Create and start an interface.
67 * @param playlist playlist and parent object for the interface
68 * @param chain configuration chain string
69 * @return VLC_SUCCESS or an error code
71 int intf_Create( playlist_t *playlist, const char *chain )
73 /* Allocate structure */
74 intf_thread_t *p_intf = vlc_custom_create( playlist, sizeof( *p_intf ),
75 "interface" );
76 if( unlikely(p_intf == NULL) )
77 return VLC_ENOMEM;
79 /* Variable used for interface spawning */
80 vlc_value_t val;
81 var_Create( p_intf, "intf-add", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
82 var_Change( p_intf, "intf-add", VLC_VAR_SETTEXT, _("Add Interface") );
83 #if !defined(_WIN32) && defined(HAVE_ISATTY)
84 if( isatty( 0 ) )
85 #endif
87 val.psz_string = (char *)"rc,none";
88 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, val, _("Console") );
90 val.psz_string = (char *)"telnet,none";
91 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, val, _("Telnet") );
92 val.psz_string = (char *)"http,none";
93 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, val, _("Web") );
94 val.psz_string = (char *)"gestures,none";
95 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, val,
96 _("Mouse Gestures") );
98 var_AddCallback( p_intf, "intf-add", AddIntfCallback, playlist );
100 /* Choose the best module */
101 char *module;
103 p_intf->p_cfg = NULL;
104 free( config_ChainCreate( &module, &p_intf->p_cfg, chain ) );
105 p_intf->p_module = module_need( p_intf, "interface", module, true );
106 free(module);
107 if( p_intf->p_module == NULL )
109 msg_Err( p_intf, "no suitable interface module" );
110 goto error;
113 vlc_mutex_lock( &lock );
114 p_intf->p_next = pl_priv( playlist )->interface;
115 pl_priv( playlist )->interface = p_intf;
116 vlc_mutex_unlock( &lock );
118 return VLC_SUCCESS;
120 error:
121 if( p_intf->p_module )
122 module_unneed( p_intf, p_intf->p_module );
123 config_ChainDestroy( p_intf->p_cfg );
124 vlc_object_release( p_intf );
125 return VLC_EGENERIC;
129 * Creates the playlist if necessary, and return a pointer to it.
130 * @note The playlist is not reference-counted. So the pointer is only valid
131 * until intf_DestroyAll() destroys interfaces.
133 static playlist_t *intf_GetPlaylist(libvlc_int_t *libvlc)
135 playlist_t *playlist;
137 vlc_mutex_lock(&lock);
138 playlist = libvlc_priv(libvlc)->playlist;
139 if (playlist == NULL)
141 playlist = playlist_Create(VLC_OBJECT(libvlc));
142 libvlc_priv(libvlc)->playlist = playlist;
144 vlc_mutex_unlock(&lock);
146 return playlist;
149 vlc_playlist_t *
150 vlc_intf_GetMainPlaylist(intf_thread_t *intf)
152 return libvlc_priv(intf->obj.libvlc)->main_playlist;
156 * Inserts an item in the playlist.
158 * This function is used during initialization. Unlike playlist_Add() and
159 * variants, it inserts an item to the beginning of the playlist. That is
160 * meant to compensate for the reverse parsing order of the command line.
162 * @note This function may <b>not</b> be called at the same time as
163 * intf_DestroyAll().
165 int intf_InsertItem(libvlc_int_t *libvlc, const char *mrl, unsigned optc,
166 const char *const *optv, unsigned flags)
168 playlist_t *playlist = intf_GetPlaylist(libvlc);
169 input_item_t *item = input_item_New(mrl, NULL);
171 if (unlikely(item == NULL))
172 return -1;
174 int ret = -1;
176 if (input_item_AddOptions(item, optc, optv, flags) == VLC_SUCCESS)
178 playlist_Lock(playlist);
179 if (playlist_NodeAddInput(playlist, item, playlist->p_playing,
180 0) != NULL)
181 ret = 0;
182 playlist_Unlock(playlist);
184 input_item_Release(item);
185 return ret;
188 void libvlc_InternalPlay(libvlc_int_t *libvlc)
190 playlist_t *pl;
192 vlc_mutex_lock(&lock);
193 pl = libvlc_priv(libvlc)->playlist;
194 vlc_mutex_unlock(&lock);
196 if (pl != NULL && var_GetBool(pl, "playlist-autostart"))
197 playlist_Control(pl, PLAYLIST_PLAY, false);
201 * Starts an interface plugin.
203 int libvlc_InternalAddIntf(libvlc_int_t *libvlc, const char *name)
205 playlist_t *playlist = intf_GetPlaylist(libvlc);
206 int ret;
208 if (unlikely(playlist == NULL))
209 ret = VLC_ENOMEM;
210 else
211 if (name != NULL)
212 ret = intf_Create(playlist, name);
213 else
214 { /* Default interface */
215 char *intf = var_InheritString(libvlc, "intf");
216 if (intf == NULL) /* "intf" has not been set */
218 #if !defined(_WIN32) && !defined(__OS2__)
219 if (!var_InheritBool(libvlc, "daemon"))
220 #endif
221 msg_Info(libvlc, _("Running vlc with the default interface. "
222 "Use 'cvlc' to use vlc without interface."));
224 ret = intf_Create(playlist, intf);
225 free(intf);
226 name = "default";
228 if (ret != VLC_SUCCESS)
229 msg_Err(libvlc, "interface \"%s\" initialization failed", name);
230 return ret;
234 * Stops and destroys all interfaces, then the playlist.
235 * @warning FIXME
236 * @param libvlc the LibVLC instance
238 void intf_DestroyAll(libvlc_int_t *libvlc)
240 playlist_t *playlist;
242 vlc_mutex_lock(&lock);
243 playlist = libvlc_priv(libvlc)->playlist;
244 if (playlist != NULL)
246 intf_thread_t *intf, **pp = &(pl_priv(playlist)->interface);
248 while ((intf = *pp) != NULL)
250 *pp = intf->p_next;
251 vlc_mutex_unlock(&lock);
253 module_unneed(intf, intf->p_module);
254 config_ChainDestroy(intf->p_cfg);
255 var_DelCallback(intf, "intf-add", AddIntfCallback, playlist);
256 vlc_object_release(intf);
258 vlc_mutex_lock(&lock);
261 libvlc_priv(libvlc)->playlist = NULL;
263 vlc_mutex_unlock(&lock);
265 if (playlist != NULL)
266 playlist_Destroy(playlist);
269 /* Following functions are local */
271 static int AddIntfCallback( vlc_object_t *obj, char const *var,
272 vlc_value_t old, vlc_value_t cur, void *data )
274 playlist_t *playlist = data;
276 int ret = intf_Create( playlist, cur.psz_string );
277 if( ret )
278 msg_Err( obj, "interface \"%s\" initialization failed",
279 cur.psz_string );
281 (void) var; (void) old;
282 return ret;