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 *****************************************************************************/
27 * This file contains functions related to interface management
31 /*****************************************************************************
33 *****************************************************************************/
41 #include <vlc_common.h>
42 #include <vlc_modules.h>
43 #include <vlc_interface.h>
44 #include <vlc_playlist.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 * );
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
;
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
;
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
;
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
));
109 PlaylistConfigureFromVariables(playlist
, VLC_OBJECT(libvlc
));
111 vlc_mutex_unlock(&priv
->lock
);
117 vlc_intf_GetMainPlaylist(intf_thread_t
*intf
)
119 vlc_playlist_t
*pl
= libvlc_GetMainPlaylist(vlc_object_instance(intf
));
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
)
134 libvlc_priv_t
*priv
= libvlc_priv(libvlc
);
136 /* Ensure that each interfaces can access the main playlist */
137 if (libvlc_GetMainPlaylist(libvlc
) == NULL
)
140 /* Allocate structure */
141 intf_thread_t
*p_intf
= vlc_custom_create( libvlc
, sizeof( *p_intf
),
143 if( unlikely(p_intf
== NULL
) )
146 /* Variable used for interface spawning */
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)
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 */
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 );
174 if( p_intf
->p_module
== NULL
)
176 msg_Err( p_intf
, "no suitable interface module" );
180 vlc_mutex_lock(&priv
->lock
);
181 p_intf
->p_next
= priv
->interfaces
;
182 priv
->interfaces
= p_intf
;
183 vlc_mutex_unlock(&priv
->lock
);
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
);
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
))
212 if (input_item_AddOptions(item
, optc
, optv
, flags
) == VLC_SUCCESS
)
214 vlc_playlist_t
*playlist
= libvlc_GetMainPlaylist(libvlc
);
217 vlc_playlist_Lock(playlist
);
218 ret
= vlc_playlist_InsertOne(playlist
, 0, item
);
219 vlc_playlist_Unlock(playlist
);
222 input_item_Release(item
);
226 void libvlc_InternalPlay(libvlc_int_t
*libvlc
)
228 if (!var_InheritBool(VLC_OBJECT(libvlc
), "playlist-autostart"))
230 vlc_playlist_t
*playlist
= libvlc_GetMainPlaylist(libvlc
);
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
;
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
);
260 * Starts an interface plugin.
262 int libvlc_InternalAddIntf(libvlc_int_t
*libvlc
, const char *name
)
267 ret
= intf_Create(libvlc
, name
);
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
);
281 if (ret
!= VLC_SUCCESS
)
282 msg_Err(libvlc
, "interface \"%s\" initialization failed", name
);
287 * Stops and destroys all interfaces, then the playlist.
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
)
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
);
320 msg_Err( obj
, "interface \"%s\" initialization failed",
323 (void) var
; (void) old
; (void) data
;