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 *****************************************************************************/
42 #include <vlc_common.h>
43 #include <vlc_modules.h>
44 #include <vlc_interface.h>
45 #include <vlc_playlist_legacy.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
;
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
),
76 if( unlikely(p_intf
== NULL
) )
79 /* Variable used for interface spawning */
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)
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 */
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 );
107 if( p_intf
->p_module
== NULL
)
109 msg_Err( p_intf
, "no suitable interface module" );
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
);
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
);
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
);
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
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
))
176 if (input_item_AddOptions(item
, optc
, optv
, flags
) == VLC_SUCCESS
)
178 playlist_Lock(playlist
);
179 if (playlist_NodeAddInput(playlist
, item
, playlist
->p_playing
,
182 playlist_Unlock(playlist
);
184 input_item_Release(item
);
188 void libvlc_InternalPlay(libvlc_int_t
*libvlc
)
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
);
208 if (unlikely(playlist
== NULL
))
212 ret
= intf_Create(playlist
, name
);
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"))
221 msg_Info(libvlc
, _("Running vlc with the default interface. "
222 "Use 'cvlc' to use vlc without interface."));
224 ret
= intf_Create(playlist
, intf
);
228 if (ret
!= VLC_SUCCESS
)
229 msg_Err(libvlc
, "interface \"%s\" initialization failed", name
);
234 * Stops and destroys all interfaces, then the playlist.
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
)
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
);
278 msg_Err( obj
, "interface \"%s\" initialization failed",
281 (void) var
; (void) old
;