1 /*****************************************************************************
2 * interaction.c: User interaction functions
3 *****************************************************************************
4 * Copyright (C) 1998-2004 VideoLAN
5 * $Id: interface.c 10147 2005-03-05 17:18:30Z gbazin $
7 * Authors: Clément Stenac <zorglub@videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
26 * This file contains functions related to user interaction management
29 /*****************************************************************************
31 *****************************************************************************/
32 #include <stdlib.h> /* free(), strtol() */
33 #include <stdio.h> /* FILE */
34 #include <string.h> /* strerror() */
37 #include <vlc/input.h>
39 #include "vlc_interaction.h"
40 #include "vlc_interface.h"
41 #include "vlc_playlist.h"
43 /*****************************************************************************
45 *****************************************************************************/
46 static void intf_InteractionInit( playlist_t *p_playlist );
47 static interaction_t * intf_InteractionGet( vlc_object_t *p_this );
48 static void intf_InteractionSearchInterface( interaction_t *
50 static int intf_WaitAnswer( interaction_t *p_interact,
51 interaction_dialog_t *p_dialog );
52 static int intf_Send( interaction_t *p_interact,
53 interaction_dialog_t *p_dialog );
54 static interaction_dialog_t *intf_InteractionGetById( vlc_object_t* , int );
57 * Send an interaction element to the user
59 * \param p_this the calling vlc_object_t
60 * \param p_interact the interaction element
61 * \return VLC_SUCCESS or an error code
63 int __intf_Interact( vlc_object_t *p_this, interaction_dialog_t *
67 interaction_t *p_interaction = intf_InteractionGet( p_this );
69 /* Get an id, if we don't already have one */
70 if( p_dialog->i_id == 0 )
72 p_dialog->i_id = ++p_interaction->i_last_id;
75 if( p_dialog->i_type == INTERACT_ASK )
77 return intf_WaitAnswer( p_interaction, p_dialog );
81 return intf_Send( p_interaction, p_dialog );
86 * Destroy the interaction system
88 void intf_InteractionDestroy( interaction_t *p_interaction )
90 /// \todo Code this, and call it
94 * The main interaction processing loop
95 * This function is called from the playlist loop
97 * \param p_playlist the parent playlist
100 void intf_InteractionManage( playlist_t *p_playlist )
103 interaction_t *p_interaction;
105 p_interaction = p_playlist->p_interaction;
108 if( p_interaction->i_dialogs == 0 ) return;
110 vlc_mutex_lock( &p_interaction->object_lock );
112 intf_InteractionSearchInterface( p_interaction );
114 if( !p_interaction->p_intf )
116 vlc_mutex_unlock( &p_interaction->object_lock );
118 /// \todo Remove all dialogs as we can't display them
122 vlc_object_yield( p_interaction->p_intf );
124 for( i_index = 0 ; i_index < p_interaction->i_dialogs; i_index ++ )
126 interaction_dialog_t *p_dialog = p_interaction->pp_dialogs[i_index];
128 if( p_dialog->b_have_answer )
130 /// \todo Signal we have an answer
131 // - If have answer, signal what is waiting
132 // (vlc_cond ? dangerous in case of pb ?)
134 // Ask interface to hide it
135 p_interaction->p_intf->pf_interact( p_interaction->p_intf,
136 p_dialog, INTERACT_HIDE );
140 if( p_dialog->b_updated )
142 p_dialog->b_finished = VLC_FALSE;
143 p_interaction->p_intf->pf_interact( p_interaction->p_intf,
144 p_dialog, INTERACT_UPDATE );
147 if( p_dialog->b_finished && !p_dialog->b_reusable )
149 /// \todo Destroy the dialog
151 // This is truly a new dialog, send it.
152 p_interaction->p_intf->pf_interact( p_interaction->p_intf,
153 p_dialog, INTERACT_NEW );
156 vlc_object_release( p_interaction->p_intf );
158 vlc_mutex_unlock( &p_playlist->p_interaction->object_lock );
163 #define INTERACT_INIT( new ) \
164 new = (interaction_dialog_t*)malloc( \
165 sizeof( interaction_dialog_t ) ); \
166 new->i_widgets = 0; \
167 new->pp_widgets = NULL; \
168 new->psz_title = NULL; \
169 new->psz_description = NULL; \
172 #define INTERACT_FREE( new ) \
173 if( new->psz_title ) free( new->psz_title ); \
174 if( new->psz_description ) free( new->psz_description );
176 /** Helper function to send a fatal message
177 * \param p_this Parent vlc_object
178 * \param i_id A predefined ID, 0 if not applicable
179 * \param psz_title Title for the dialog
180 * \param psz_format The message to display
182 void __intf_UserFatal( vlc_object_t *p_this, int i_id,
183 const char *psz_title,
184 const char *psz_format, ... )
187 interaction_dialog_t *p_new = NULL;
188 user_widget_t *p_widget = NULL;
192 p_new = intf_InteractionGetById( p_this, i_id );
196 INTERACT_INIT( p_new );
199 p_new->i_type = INTERACT_FATAL;
200 p_new->psz_title = strdup( psz_title );
202 p_widget = (user_widget_t* )malloc( sizeof( user_widget_t ) );
204 p_widget->i_type = WIDGET_TEXT;
206 va_start( args, psz_format );
207 vasprintf( &p_widget->psz_text, psz_format, args );
210 INSERT_ELEM ( p_new->pp_widgets,
215 intf_Interact( p_this, p_new );
219 /** Helper function to build a progress bar
220 * \param p_this Parent vlc object
222 interaction_dialog_t *__intf_ProgressBuild( vlc_object_t *p_this,
223 const char *psz_text )
225 interaction_dialog_t *p_new = (interaction_dialog_t *)malloc(
226 sizeof( interaction_dialog_t ) );
235 /**********************************************************************
236 * The following functions are local
237 **********************************************************************/
239 /* Get the interaction object. Create it if needed */
240 static interaction_t * intf_InteractionGet( vlc_object_t *p_this )
242 playlist_t *p_playlist;
243 interaction_t *p_interaction;
245 p_playlist = (playlist_t*) vlc_object_find( p_this, VLC_OBJECT_PLAYLIST,
253 if( p_playlist->p_interaction == NULL )
255 intf_InteractionInit( p_playlist );
258 p_interaction = p_playlist->p_interaction;
260 vlc_object_release( p_playlist );
262 return p_interaction;
265 /* Create the interaction object in the given playlist object */
266 static void intf_InteractionInit( playlist_t *p_playlist )
268 interaction_t *p_interaction;
270 msg_Dbg( p_playlist, "initializing interaction system" );
272 p_interaction = vlc_object_create( VLC_OBJECT( p_playlist ),
273 sizeof( interaction_t ) );
276 msg_Err( p_playlist,"out of memory" );
280 p_interaction->i_dialogs = 0;
281 p_interaction->pp_dialogs = NULL;
282 p_interaction->p_intf = NULL;
283 p_interaction->i_last_id = DIALOG_LAST_PREDEFINED + 1;
285 vlc_mutex_init( p_interaction , &p_interaction->object_lock );
287 p_playlist->p_interaction = p_interaction;
290 /* Look for an interface suitable for interaction */
291 static void intf_InteractionSearchInterface( interaction_t *p_interaction )
296 p_interaction->p_intf = NULL;
298 p_list = vlc_list_find( p_interaction, VLC_OBJECT_INTF, FIND_ANYWHERE );
301 msg_Err( p_interaction, "Unable to create module list" );
305 for( i_index = 0; i_index < p_list->i_count; i_index ++ )
307 intf_thread_t *p_intf = (intf_thread_t *)
308 p_list->p_values[i_index].p_object;
309 if( p_intf->pf_interact != NULL )
311 p_interaction->p_intf = p_intf;
315 vlc_list_release ( p_list );
318 /* Add a dialog to the queue and wait for answer */
319 static int intf_WaitAnswer( interaction_t *p_interact, interaction_dialog_t *p_dialog )
321 // TODO: Add to queue, wait for answer
325 /* Add a dialog to the queue and return */
326 static int intf_Send( interaction_t *p_interact, interaction_dialog_t *p_dialog )
328 vlc_mutex_lock( &p_interact->object_lock );
330 /// \todo Check first it does not exist !!!
331 INSERT_ELEM( p_interact->pp_dialogs,
332 p_interact->i_dialogs,
333 p_interact->i_dialogs,
335 vlc_mutex_unlock( &p_interact->object_lock );
339 /* Find an interaction dialog by its id */
340 static interaction_dialog_t *intf_InteractionGetById( vlc_object_t* p_this,
343 interaction_t *p_interaction = intf_InteractionGet( p_this );
346 for( i = 0 ; i< p_interaction->i_dialogs; i++ )
348 if( p_interaction->pp_dialogs[i]->i_id == i_id )
350 return p_interaction->pp_dialogs[i];