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
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 *****************************************************************************/
28 * This file contains functions related to interface management
32 /*****************************************************************************
34 *****************************************************************************/
43 #include <vlc_common.h>
44 #include <vlc_modules.h>
45 #include <vlc_interface.h>
46 #include <vlc_playlist.h>
48 #include "playlist/playlist_internal.h"
49 #include "../lib/libvlc_internal.h"
51 static int AddIntfCallback( vlc_object_t *, char const *,
52 vlc_value_t , vlc_value_t , void * );
54 /* This lock ensures that the playlist is created only once (per instance). It
55 * also protects the list of running interfaces against concurrent access,
56 * either to add or remove an interface.
58 * However, it does NOT protect from destruction of the playlist by
59 * intf_DestroyAll(). Instead, care must be taken that intf_Create() and any
60 * other function that depends on the playlist is only called BEFORE
61 * intf_DestroyAll() has the possibility to destroy all interfaces.
63 static vlc_mutex_t lock = VLC_STATIC_MUTEX;
66 * Create and start an interface.
68 * @param playlist playlist and parent object for the interface
69 * @param chain configuration chain string
70 * @return VLC_SUCCESS or an error code
72 int intf_Create( playlist_t *playlist, const char *chain )
74 /* Allocate structure */
75 intf_thread_t *p_intf = vlc_custom_create( playlist, sizeof( *p_intf ),
77 if( unlikely(p_intf == NULL) )
80 /* Variable used for interface spawning */
81 vlc_value_t val, text;
82 var_Create( p_intf, "intf-add", VLC_VAR_STRING |
83 VLC_VAR_HASCHOICE | VLC_VAR_ISCOMMAND );
84 text.psz_string = _("Add Interface");
85 var_Change( p_intf, "intf-add", VLC_VAR_SETTEXT, &text, NULL );
86 #if !defined(_WIN32) && defined(HAVE_ISATTY)
90 val.psz_string = (char *)"rc,none";
91 text.psz_string = (char *)_("Console");
92 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
94 val.psz_string = (char *)"telnet,none";
95 text.psz_string = (char *)_("Telnet");
96 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
97 val.psz_string = (char *)"http,none";
98 text.psz_string = (char *)_("Web");
99 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
100 val.psz_string = (char *)"logger,none";
101 text.psz_string = (char *)_("Debug logging");
102 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
103 val.psz_string = (char *)"gestures,none";
104 text.psz_string = (char *)_("Mouse Gestures");
105 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
107 var_AddCallback( p_intf, "intf-add", AddIntfCallback, playlist );
109 /* Choose the best module */
112 p_intf->p_cfg = NULL;
113 free( config_ChainCreate( &module, &p_intf->p_cfg, chain ) );
114 p_intf->p_module = module_need( p_intf, "interface", module, true );
116 if( p_intf->p_module == NULL )
118 msg_Err( p_intf, "no suitable interface module" );
122 vlc_mutex_lock( &lock );
123 p_intf->p_next = pl_priv( playlist )->interface;
124 pl_priv( playlist )->interface = p_intf;
125 vlc_mutex_unlock( &lock );
130 if( p_intf->p_module )
131 module_unneed( p_intf, p_intf->p_module );
132 config_ChainDestroy( p_intf->p_cfg );
133 vlc_object_release( p_intf );
138 * Creates the playlist if necessary, and return a pointer to it.
139 * @note The playlist is not reference-counted. So the pointer is only valid
140 * until intf_DestroyAll() destroys interfaces.
142 static playlist_t *intf_GetPlaylist(libvlc_int_t *libvlc)
144 playlist_t *playlist;
146 vlc_mutex_lock(&lock);
147 playlist = libvlc_priv(libvlc)->playlist;
148 if (playlist == NULL)
150 playlist = playlist_Create(VLC_OBJECT(libvlc));
151 libvlc_priv(libvlc)->playlist = playlist;
153 vlc_mutex_unlock(&lock);
159 * Inserts an item in the playlist used by interfaces.
160 * @note This function may <b>not</b> be called at the same time as
163 void intf_InsertItem(libvlc_int_t *libvlc, const char *mrl, unsigned optc,
164 const char *const *optv, unsigned flags)
166 playlist_AddExt(intf_GetPlaylist(libvlc), mrl, NULL, PLAYLIST_INSERT,
167 0, -1, optc, optv, flags, true, pl_Unlocked);
170 void libvlc_InternalPlay(libvlc_int_t *libvlc)
174 vlc_mutex_lock(&lock);
175 pl = libvlc_priv(libvlc)->playlist;
176 vlc_mutex_unlock(&lock);
178 if (pl != NULL && var_GetBool(pl, "playlist-autostart"))
179 playlist_Control(pl, PLAYLIST_PLAY, false);
183 * Starts an interface plugin.
185 int libvlc_InternalAddIntf(libvlc_int_t *libvlc, const char *name)
187 playlist_t *playlist = intf_GetPlaylist(libvlc);
190 if (unlikely(playlist == NULL))
194 ret = intf_Create(playlist, name);
196 { /* Default interface */
197 char *intf = var_InheritString(libvlc, "intf");
198 if (intf == NULL) /* "intf" has not been set */
200 #if !defined(_WIN32) && !defined(__OS2__)
201 char *pidfile = var_InheritString(libvlc, "pidfile");
206 msg_Info(libvlc, _("Running vlc with the default interface. "
207 "Use 'cvlc' to use vlc without interface."));
209 ret = intf_Create(playlist, intf);
213 if (ret != VLC_SUCCESS)
214 msg_Err(libvlc, "interface \"%s\" initialization failed", name);
219 * Stops and destroys all interfaces, then the playlist.
221 * @param libvlc the LibVLC instance
223 void intf_DestroyAll(libvlc_int_t *libvlc)
225 playlist_t *playlist;
227 vlc_mutex_lock(&lock);
228 playlist = libvlc_priv(libvlc)->playlist;
229 if (playlist != NULL)
231 intf_thread_t *intf, **pp = &(pl_priv(playlist)->interface);
233 while ((intf = *pp) != NULL)
236 vlc_mutex_unlock(&lock);
238 module_unneed(intf, intf->p_module);
239 config_ChainDestroy(intf->p_cfg);
240 var_DelCallback(intf, "intf-add", AddIntfCallback, playlist);
241 vlc_object_release(intf);
243 vlc_mutex_lock(&lock);
246 libvlc_priv(libvlc)->playlist = NULL;
248 vlc_mutex_unlock(&lock);
250 if (playlist != NULL)
251 playlist_Destroy(playlist);
254 /* Following functions are local */
256 static int AddIntfCallback( vlc_object_t *obj, char const *var,
257 vlc_value_t old, vlc_value_t cur, void *data )
259 playlist_t *playlist = data;
261 int ret = intf_Create( playlist, cur.psz_string );
263 msg_Err( obj, "interface \"%s\" initialization failed",
266 (void) var; (void) old;