intf: fix win32 build
[vlc.git] / src / interface / interface.c
blobbdcc1364e6a04c275a3c1cf6445bf61e41d6469b
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
8 * Authors: Vincent Seguin <seguin@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
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 Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /**
26 * \file
27 * This file contains functions related to interface management
31 /*****************************************************************************
32 * Preamble
33 *****************************************************************************/
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
39 #include <unistd.h>
41 #include <vlc_common.h>
42 #include <vlc_modules.h>
43 #include <vlc_interface.h>
44 #include <vlc_playlist_legacy.h>
45 #include <vlc_playlist.h>
46 #include "libvlc.h"
47 #include "playlist_legacy/playlist_internal.h"
48 #include "../lib/libvlc_internal.h"
49 #include "input/player.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;
65 /**
66 * Creates the playlist if necessary, and return a pointer to it.
67 * @note The playlist is not reference-counted. So the pointer is only valid
68 * until intf_DestroyAll() destroys interfaces.
70 static playlist_t *intf_GetPlaylist(libvlc_int_t *libvlc)
72 playlist_t *playlist;
74 vlc_mutex_lock(&lock);
75 playlist = libvlc_priv(libvlc)->playlist;
76 if (playlist == NULL)
78 playlist = playlist_Create(VLC_OBJECT(libvlc));
79 libvlc_priv(libvlc)->playlist = playlist;
81 vlc_mutex_unlock(&lock);
83 return playlist;
86 static void
87 PlaylistConfigureFromVariables(vlc_playlist_t *playlist, vlc_object_t *obj)
89 enum vlc_playlist_playback_order order;
90 if (var_InheritBool(obj, "random"))
91 order = VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM;
92 else
93 order = VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL;
95 /* repeat = repeat current; loop = repeat all */
96 enum vlc_playlist_playback_repeat repeat;
97 if (var_InheritBool(obj, "repeat"))
98 repeat = VLC_PLAYLIST_PLAYBACK_REPEAT_CURRENT;
99 else if (var_InheritBool(obj, "loop"))
100 repeat = VLC_PLAYLIST_PLAYBACK_REPEAT_ALL;
101 else
102 repeat = VLC_PLAYLIST_PLAYBACK_REPEAT_NONE;
104 enum vlc_player_media_stopped_action media_stopped_action;
105 if (var_InheritBool(obj, "play-and-exit"))
106 media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_EXIT;
107 else if (var_InheritBool(obj, "play-and-stop"))
108 media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_STOP;
109 else if (var_InheritBool(obj, "play-and-pause"))
110 media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_PAUSE;
111 else
112 media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_CONTINUE;
114 bool start_paused = var_InheritBool(obj, "start-paused");
116 vlc_playlist_Lock(playlist);
117 vlc_playlist_SetPlaybackOrder(playlist, order);
118 vlc_playlist_SetPlaybackRepeat(playlist, repeat);
120 vlc_player_t *player = vlc_playlist_GetPlayer(playlist);
122 /* the playlist and the player share the same lock, and this is not an
123 * implementation detail */
124 vlc_player_SetMediaStoppedAction(player, media_stopped_action);
125 vlc_player_SetStartPaused(player, start_paused);
127 vlc_playlist_Unlock(playlist);
130 vlc_playlist_t *
131 vlc_intf_GetMainPlaylist(intf_thread_t *intf)
133 libvlc_int_t *libvlc = vlc_object_instance(intf);
134 libvlc_priv_t *priv = libvlc_priv(libvlc);
136 vlc_mutex_lock(&lock);
137 vlc_playlist_t *playlist = priv->main_playlist;
138 if (priv->main_playlist == NULL)
140 playlist = priv->main_playlist = vlc_playlist_New(VLC_OBJECT(libvlc));
141 if (playlist)
142 PlaylistConfigureFromVariables(playlist, VLC_OBJECT(libvlc));
144 vlc_mutex_unlock(&lock);
146 return playlist;
149 static int intf_CreateInternal( libvlc_int_t *libvlc, playlist_t *playlist,
150 const char *chain )
152 assert( !!libvlc != !!playlist );
153 if (!playlist)
155 playlist = intf_GetPlaylist(libvlc);
156 if (!playlist)
157 return VLC_EGENERIC;
159 libvlc_priv_t *priv = libvlc_priv(vlc_object_instance(playlist));
161 /* Allocate structure */
162 intf_thread_t *p_intf = vlc_custom_create( playlist, sizeof( *p_intf ),
163 "interface" );
164 if( unlikely(p_intf == NULL) )
165 return VLC_ENOMEM;
167 /* Variable used for interface spawning */
168 vlc_value_t val;
169 var_Create( p_intf, "intf-add", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
170 var_Change( p_intf, "intf-add", VLC_VAR_SETTEXT, _("Add Interface") );
171 #if !defined(_WIN32) && defined(HAVE_ISATTY)
172 if( isatty( 0 ) )
173 #endif
175 val.psz_string = (char *)"rc,none";
176 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, val, _("Console") );
178 val.psz_string = (char *)"telnet,none";
179 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, val, _("Telnet") );
180 val.psz_string = (char *)"http,none";
181 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, val, _("Web") );
182 val.psz_string = (char *)"gestures,none";
183 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, val,
184 _("Mouse Gestures") );
186 var_AddCallback( p_intf, "intf-add", AddIntfCallback, playlist );
188 /* Choose the best module */
189 char *module;
191 p_intf->p_cfg = NULL;
192 free( config_ChainCreate( &module, &p_intf->p_cfg, chain ) );
193 p_intf->p_module = module_need( p_intf, "interface", module, true );
194 free(module);
195 if( p_intf->p_module == NULL )
197 msg_Err( p_intf, "no suitable interface module" );
198 goto error;
201 vlc_mutex_lock( &lock );
202 p_intf->p_next = priv->interfaces;
203 priv->interfaces = p_intf;
204 vlc_mutex_unlock( &lock );
206 return VLC_SUCCESS;
208 error:
209 if( p_intf->p_module )
210 module_unneed( p_intf, p_intf->p_module );
211 config_ChainDestroy( p_intf->p_cfg );
212 vlc_object_delete(p_intf);
213 return VLC_EGENERIC;
217 * Create and start an interface.
219 * @param playlist playlist and parent object for the interface
220 * @param chain configuration chain string
221 * @return VLC_SUCCESS or an error code
223 int intf_Create( libvlc_int_t *libvlc, const char *chain )
225 return intf_CreateInternal( libvlc, NULL, chain );
229 * Inserts an item in the playlist.
231 * This function is used during initialization. Unlike playlist_Add() and
232 * variants, it inserts an item to the beginning of the playlist. That is
233 * meant to compensate for the reverse parsing order of the command line.
235 * @note This function may <b>not</b> be called at the same time as
236 * intf_DestroyAll().
238 int intf_InsertItem(libvlc_int_t *libvlc, const char *mrl, unsigned optc,
239 const char *const *optv, unsigned flags)
241 playlist_t *playlist = intf_GetPlaylist(libvlc);
242 input_item_t *item = input_item_New(mrl, NULL);
244 if (unlikely(item == NULL))
245 return -1;
247 int ret = -1;
249 if (input_item_AddOptions(item, optc, optv, flags) == VLC_SUCCESS)
251 playlist_Lock(playlist);
252 if (playlist_NodeAddInput(playlist, item, playlist->p_playing,
253 0) != NULL)
254 ret = 0;
255 playlist_Unlock(playlist);
257 input_item_Release(item);
258 return ret;
261 void libvlc_InternalPlay(libvlc_int_t *libvlc)
263 playlist_t *pl;
265 vlc_mutex_lock(&lock);
266 pl = libvlc_priv(libvlc)->playlist;
267 vlc_mutex_unlock(&lock);
269 if (pl != NULL && var_GetBool(pl, "playlist-autostart"))
270 playlist_Control(pl, PLAYLIST_PLAY, false);
274 * Starts an interface plugin.
276 int libvlc_InternalAddIntf(libvlc_int_t *libvlc, const char *name)
278 playlist_t *playlist = intf_GetPlaylist(libvlc);
279 int ret;
281 if (unlikely(playlist == NULL))
282 ret = VLC_ENOMEM;
283 else
284 if (name != NULL)
285 ret = intf_CreateInternal(NULL, playlist, name);
286 else
287 { /* Default interface */
288 char *intf = var_InheritString(libvlc, "intf");
289 if (intf == NULL) /* "intf" has not been set */
291 #if !defined(_WIN32) && !defined(__OS2__)
292 if (!var_InheritBool(libvlc, "daemon"))
293 #endif
294 msg_Info(libvlc, _("Running vlc with the default interface. "
295 "Use 'cvlc' to use vlc without interface."));
297 ret = intf_CreateInternal(NULL, playlist, intf);
298 free(intf);
299 name = "default";
301 if (ret != VLC_SUCCESS)
302 msg_Err(libvlc, "interface \"%s\" initialization failed", name);
303 return ret;
307 * Stops and destroys all interfaces, then the playlist.
308 * @warning FIXME
309 * @param libvlc the LibVLC instance
311 void intf_DestroyAll(libvlc_int_t *libvlc)
313 libvlc_priv_t *priv = libvlc_priv(libvlc);
314 playlist_t *playlist;
316 vlc_mutex_lock(&lock);
317 playlist = libvlc_priv(libvlc)->playlist;
318 if (playlist != NULL)
320 intf_thread_t *intf, **pp = &priv->interfaces;
322 while ((intf = *pp) != NULL)
324 *pp = intf->p_next;
325 vlc_mutex_unlock(&lock);
327 module_unneed(intf, intf->p_module);
328 config_ChainDestroy(intf->p_cfg);
329 var_DelCallback(intf, "intf-add", AddIntfCallback, playlist);
330 vlc_object_delete(intf);
332 vlc_mutex_lock(&lock);
335 libvlc_priv(libvlc)->playlist = NULL;
337 vlc_mutex_unlock(&lock);
339 if (playlist != NULL)
340 playlist_Destroy(playlist);
343 /* Following functions are local */
345 static int AddIntfCallback( vlc_object_t *obj, char const *var,
346 vlc_value_t old, vlc_value_t cur, void *data )
348 playlist_t *playlist = data;
350 int ret = intf_CreateInternal( NULL, playlist, cur.psz_string );
351 if( ret )
352 msg_Err( obj, "interface \"%s\" initialization failed",
353 cur.psz_string );
355 (void) var; (void) old;
356 return ret;