decoder: fix abort on vout failure
[vlc.git] / src / interface / interface.c
blob37ecf0e6d92ca3334fcba43904456ca9288ef5e3
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.h>
45 #include "libvlc.h"
46 #include "../lib/libvlc_internal.h"
47 #include "player/player.h"
49 static int AddIntfCallback( vlc_object_t *, char const *,
50 vlc_value_t , vlc_value_t , void * );
52 static void
53 PlaylistConfigureFromVariables(vlc_playlist_t *playlist, vlc_object_t *obj)
55 enum vlc_playlist_playback_order order;
56 if (var_InheritBool(obj, "random"))
57 order = VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM;
58 else
59 order = VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL;
61 /* repeat = repeat current; loop = repeat all */
62 enum vlc_playlist_playback_repeat repeat;
63 if (var_InheritBool(obj, "repeat"))
64 repeat = VLC_PLAYLIST_PLAYBACK_REPEAT_CURRENT;
65 else if (var_InheritBool(obj, "loop"))
66 repeat = VLC_PLAYLIST_PLAYBACK_REPEAT_ALL;
67 else
68 repeat = VLC_PLAYLIST_PLAYBACK_REPEAT_NONE;
70 enum vlc_player_media_stopped_action media_stopped_action;
71 if (var_InheritBool(obj, "play-and-exit"))
72 media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_EXIT;
73 else if (var_InheritBool(obj, "play-and-stop"))
74 media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_STOP;
75 else if (var_InheritBool(obj, "play-and-pause"))
76 media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_PAUSE;
77 else
78 media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_CONTINUE;
80 bool start_paused = var_InheritBool(obj, "start-paused");
81 bool playlist_cork = var_InheritBool(obj, "playlist-cork");
83 vlc_playlist_Lock(playlist);
84 vlc_playlist_SetPlaybackOrder(playlist, order);
85 vlc_playlist_SetPlaybackRepeat(playlist, repeat);
87 vlc_player_t *player = vlc_playlist_GetPlayer(playlist);
89 /* the playlist and the player share the same lock, and this is not an
90 * implementation detail */
91 vlc_player_SetMediaStoppedAction(player, media_stopped_action);
92 vlc_player_SetStartPaused(player, start_paused);
93 vlc_player_SetPauseOnCork(player, playlist_cork);
95 vlc_playlist_Unlock(playlist);
98 static vlc_playlist_t *
99 libvlc_GetMainPlaylist(libvlc_int_t *libvlc)
101 libvlc_priv_t *priv = libvlc_priv(libvlc);
103 vlc_mutex_lock(&priv->lock);
104 vlc_playlist_t *playlist = priv->main_playlist;
105 if (priv->main_playlist == NULL)
107 playlist = priv->main_playlist = vlc_playlist_New(VLC_OBJECT(libvlc));
108 if (playlist)
109 PlaylistConfigureFromVariables(playlist, VLC_OBJECT(libvlc));
111 vlc_mutex_unlock(&priv->lock);
113 return playlist;
116 vlc_playlist_t *
117 vlc_intf_GetMainPlaylist(intf_thread_t *intf)
119 vlc_playlist_t *pl = libvlc_GetMainPlaylist(vlc_object_instance(intf));
120 assert(pl);
121 return pl;
125 * Create and start an interface.
127 * @param playlist playlist and parent object for the interface
128 * @param chain configuration chain string
129 * @return VLC_SUCCESS or an error code
131 int intf_Create( libvlc_int_t *libvlc, const char *chain )
133 assert( libvlc );
134 libvlc_priv_t *priv = libvlc_priv(libvlc);
136 /* Ensure that each interfaces can access the main playlist */
137 if (libvlc_GetMainPlaylist(libvlc) == NULL)
138 return VLC_ENOMEM;
140 /* Allocate structure */
141 intf_thread_t *p_intf = vlc_custom_create( libvlc, sizeof( *p_intf ),
142 "interface" );
143 if( unlikely(p_intf == NULL) )
144 return VLC_ENOMEM;
146 /* Variable used for interface spawning */
147 vlc_value_t val;
148 var_Create( p_intf, "intf-add", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
149 var_Change( p_intf, "intf-add", VLC_VAR_SETTEXT, _("Add Interface") );
150 #if !defined(_WIN32) && defined(HAVE_ISATTY)
151 if( isatty( 0 ) )
152 #endif
154 val.psz_string = (char *)"rc,none";
155 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, val, _("Console") );
157 val.psz_string = (char *)"telnet,none";
158 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, val, _("Telnet") );
159 val.psz_string = (char *)"http,none";
160 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, val, _("Web") );
161 val.psz_string = (char *)"gestures,none";
162 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, val,
163 _("Mouse Gestures") );
165 var_AddCallback( p_intf, "intf-add", AddIntfCallback, NULL );
167 /* Choose the best module */
168 char *module;
170 p_intf->p_cfg = NULL;
171 free( config_ChainCreate( &module, &p_intf->p_cfg, chain ) );
172 p_intf->p_module = module_need( p_intf, "interface", module, true );
173 free(module);
174 if( p_intf->p_module == NULL )
176 msg_Err( p_intf, "no suitable interface module" );
177 goto error;
180 vlc_mutex_lock(&priv->lock);
181 p_intf->p_next = priv->interfaces;
182 priv->interfaces = p_intf;
183 vlc_mutex_unlock(&priv->lock);
185 return VLC_SUCCESS;
187 error:
188 if( p_intf->p_module )
189 module_unneed( p_intf, p_intf->p_module );
190 config_ChainDestroy( p_intf->p_cfg );
191 vlc_object_delete(p_intf);
192 return VLC_EGENERIC;
196 * Inserts an item in the playlist.
198 * This function is used during initialization. It inserts an item to the
199 * beginning of the playlist. That is meant to compensate for the reverse
200 * parsing order of the command line.
202 int intf_InsertItem(libvlc_int_t *libvlc, const char *mrl, unsigned optc,
203 const char *const *optv, unsigned flags)
205 input_item_t *item = input_item_New(mrl, NULL);
207 if (unlikely(item == NULL))
208 return -1;
210 int ret = -1;
212 if (input_item_AddOptions(item, optc, optv, flags) == VLC_SUCCESS)
214 vlc_playlist_t *playlist = libvlc_GetMainPlaylist(libvlc);
215 if (playlist)
217 vlc_playlist_Lock(playlist);
218 ret = vlc_playlist_InsertOne(playlist, 0, item);
219 vlc_playlist_Unlock(playlist);
222 input_item_Release(item);
223 return ret;
226 void libvlc_InternalPlay(libvlc_int_t *libvlc)
228 if (!var_InheritBool(VLC_OBJECT(libvlc), "playlist-autostart"))
229 return;
230 vlc_playlist_t *playlist = libvlc_GetMainPlaylist(libvlc);
231 if (!playlist)
232 return;
233 vlc_playlist_Lock(playlist);
234 if (vlc_playlist_Count(playlist) > 0)
236 if (vlc_playlist_GetCurrentIndex(playlist) < 0)
237 vlc_playlist_GoTo(playlist, 0);
238 vlc_playlist_Start(playlist);
240 vlc_playlist_Unlock(playlist);
243 static void libvlc_AutoRun(libvlc_int_t *libvlc)
245 struct vlc_logger *log = libvlc->obj.logger;
246 module_t **mods;
247 ssize_t total = vlc_module_match("autorun", NULL, false, &mods, NULL);
249 for (ssize_t i = 0; i < total; i++) {
250 void (*func)(libvlc_int_t *) = vlc_module_map(log, mods[i]);
252 assert(func != NULL);
253 func(libvlc);
256 free(mods);
260 * Starts an interface plugin.
262 int libvlc_InternalAddIntf(libvlc_int_t *libvlc, const char *name)
264 int ret;
266 if (name != NULL)
267 ret = intf_Create(libvlc, name);
268 else
269 { /* Default interface */
270 libvlc_AutoRun(libvlc);
272 char *intf = var_InheritString(libvlc, "intf");
273 if (intf == NULL) /* "intf" has not been set */
274 msg_Info(libvlc, _("Running vlc with the default interface. "
275 "Use 'cvlc' to use vlc without interface."));
277 ret = intf_Create(libvlc, intf);
278 free(intf);
279 name = "default";
281 if (ret != VLC_SUCCESS)
282 msg_Err(libvlc, "interface \"%s\" initialization failed", name);
283 return ret;
287 * Stops and destroys all interfaces, then the playlist.
288 * @warning FIXME
289 * @param libvlc the LibVLC instance
291 void intf_DestroyAll(libvlc_int_t *libvlc)
293 libvlc_priv_t *priv = libvlc_priv(libvlc);
295 vlc_mutex_lock(&priv->lock);
296 intf_thread_t *intf, **pp = &priv->interfaces;
298 while ((intf = *pp) != NULL)
300 *pp = intf->p_next;
301 vlc_mutex_unlock(&priv->lock);
303 module_unneed(intf, intf->p_module);
304 config_ChainDestroy(intf->p_cfg);
305 var_DelCallback(intf, "intf-add", AddIntfCallback, NULL);
306 vlc_object_delete(intf);
308 vlc_mutex_lock(&priv->lock);
310 vlc_mutex_unlock(&priv->lock);
313 /* Following functions are local */
315 static int AddIntfCallback( vlc_object_t *obj, char const *var,
316 vlc_value_t old, vlc_value_t cur, void *data )
318 int ret = intf_Create( vlc_object_instance(obj), cur.psz_string );
319 if( ret )
320 msg_Err( obj, "interface \"%s\" initialization failed",
321 cur.psz_string );
323 (void) var; (void) old; (void) data;
324 return ret;