vlc_bool_t b_have_answer; //< Has an answer been given ?
vlc_bool_t b_reusable; //< Do we have to reuse this ?
+ vlc_bool_t b_updated; //< Update for this one ?
+ vlc_bool_t b_finished; //< Hidden by interface
void * p_private; //< Private interface data
};
+/**
+ * Possible interaction types
+ */
+enum
+{
+ INTERACT_PROGRESS, //< Progress bar
+ INTERACT_WARNING, //< Warning message ("codec not supported")
+ INTERACT_FATAL, //< Fatal message ("File not found")
+ INTERACT_FATAL_LIST, //< List of fatal messages ("File not found")
+ INTERACT_ASK, //< Full-featured dialog box (password)
+};
+
+/**
+ * Predefined reusable dialogs
+ */
+enum
+{
+ DIALOG_NOACCESS,
+ DIALOG_NOCODEC,
+ DIALOG_NOAUDIO,
+
+ DIALOG_LAST_PREDEFINED,
+};
+
/**
* This structure contains the active interaction dialogs, and is
* used by teh manager
int i_dialogs; //< Number of dialogs
interaction_dialog_t **pp_dialogs; //< Dialogs
-};
+ intf_thread_t *p_intf; //< Interface to use
+
+ int i_last_id; //< Last attributed ID
+};
/**
- * Possible interaction types
+ * Possible actions
*/
enum
{
- INTERACT_PROGRESS, //< Progress bar
- INTERACT_WARNING, //< Warning message ("codec not supported")
- INTERACT_FATAL, //< Fatal message ("File not found")
- INTERACT_ASK, //< Full-featured dialog box (password)
+ INTERACT_NEW,
+ INTERACT_UPDATE,
+ INTERACT_HIDE
};
+/***************************************************************************
+ * Exported symbols
+ ***************************************************************************/
+
#define intf_Interact( a,b ) __intf_Interact( VLC_OBJECT(a), b )
VLC_EXPORT( int,__intf_Interact,( vlc_object_t *,interaction_dialog_t * ) );
-#if 0
-VLC_NO_EXPORT_YET( int,__intf_InteractionManage,( playlist_t *) );
-#endif
-
-VLC_EXPORT( void, intf_UserFatal,( vlc_object_t*, const char*, const char*, ...));
+#define intf_UserFatal( a,b, c, d, e... ) __intf_UserFatal( a,b,c,d, ## e )
+VLC_EXPORT( void, __intf_UserFatal,( vlc_object_t*, int, const char*, const char*, ...) );
+VLC_EXPORT( void, intf_InteractionManage,( playlist_t *) );
+VLC_EXPORT( void, intf_InteractionDestroy,( interaction_t *) );
void httpd_FileDelete (httpd_file_t *);
module_t * __module_Need (vlc_object_t *, const char *, const char *, vlc_bool_t);
const char * VLC_Changeset (void);
+void intf_InteractionDestroy (interaction_t *);
void LocaleFree (const char *);
void __vlc_object_attach (vlc_object_t *, vlc_object_t *);
stream_t * __stream_UrlNew (vlc_object_t *p_this, const char *psz_url);
void httpd_MsgAdd (httpd_message_t *, char *psz_name, char *psz_value, ...);
int vout_vaControlDefault (vout_thread_t *, int, va_list);
int playlist_NodeEmpty (playlist_t *, playlist_item_t *, vlc_bool_t);
+void __intf_UserFatal (vlc_object_t*, int, const char*, const char*, ...);
spu_t * __spu_Create (vlc_object_t *);
int playlist_NodeRemoveItem (playlist_t *,playlist_item_t*,playlist_item_t *);
int __net_Accept (vlc_object_t *, int *, mtime_t);
aout_buffer_t * aout_FifoPop (aout_instance_t * p_aout, aout_fifo_t * p_fifo);
int __vout_InitPicture (vlc_object_t *p_this, picture_t *p_pic, uint32_t i_chroma, int i_width, int i_height, int i_aspect);
int playlist_LockClear (playlist_t *);
+void intf_InteractionManage (playlist_t *);
char * mstrtime (char *psz_buffer, mtime_t date);
void aout_FormatPrepare (audio_sample_format_t * p_format);
void spu_DisplaySubpicture (spu_t *, subpicture_t *);
void mwait (mtime_t date);
void __config_ResetAll (vlc_object_t *);
httpd_redirect_t * httpd_RedirectNew (httpd_host_t *, const char *psz_url_dst, const char *psz_url_src);
-void intf_UserFatal (vlc_object_t*, const char*, const char*, ...);
playlist_item_t * playlist_LockItemGetById (playlist_t *, int);
mtime_t date_Get (const date_t *);
int aout_DecPlay (aout_instance_t *, aout_input_t *, aout_buffer_t *);
void (*__input_Read_inner) (vlc_object_t *, input_item_t *, vlc_bool_t);
int (*__net_ConnectUDP_inner) (vlc_object_t *p_this, const char *psz_host, int i_port, int hlim);
int (*__intf_Interact_inner) (vlc_object_t *,interaction_dialog_t *);
- void (*intf_UserFatal_inner) (vlc_object_t*, const char*, const char*, ...);
+ void (*intf_InteractionManage_inner) (playlist_t *);
+ void (*intf_InteractionDestroy_inner) (interaction_t *);
+ void (*__intf_UserFatal_inner) (vlc_object_t*, int, const char*, const char*, ...);
};
# if defined (__PLUGIN__)
# define aout_FiltersCreatePipeline (p_symbols)->aout_FiltersCreatePipeline_inner
# define __input_Read (p_symbols)->__input_Read_inner
# define __net_ConnectUDP (p_symbols)->__net_ConnectUDP_inner
# define __intf_Interact (p_symbols)->__intf_Interact_inner
-# define intf_UserFatal (p_symbols)->intf_UserFatal_inner
+# define intf_InteractionManage (p_symbols)->intf_InteractionManage_inner
+# define intf_InteractionDestroy (p_symbols)->intf_InteractionDestroy_inner
+# define __intf_UserFatal (p_symbols)->__intf_UserFatal_inner
# elif defined (HAVE_DYNAMIC_PLUGINS) && !defined (__BUILTIN__)
/******************************************************************
* STORE_SYMBOLS: store VLC APIs into p_symbols for plugin access.
((p_symbols)->__input_Read_inner) = __input_Read; \
((p_symbols)->__net_ConnectUDP_inner) = __net_ConnectUDP; \
((p_symbols)->__intf_Interact_inner) = __intf_Interact; \
- ((p_symbols)->intf_UserFatal_inner) = intf_UserFatal; \
+ ((p_symbols)->intf_InteractionManage_inner) = intf_InteractionManage; \
+ ((p_symbols)->intf_InteractionDestroy_inner) = intf_InteractionDestroy; \
+ ((p_symbols)->__intf_UserFatal_inner) = __intf_UserFatal; \
(p_symbols)->net_ConvertIPv4_deprecated = NULL; \
# endif /* __PLUGIN__ */
* This file contains functions related to user interaction management
*/
-
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "vlc_interface.h"
#include "vlc_playlist.h"
-static void intf_InteractionInit( playlist_t *p_playlist );
-static int intf_WaitAnswer( intf_thread_t *p_intf, interaction_dialog_t *p_interact );
-static int intf_Send( intf_thread_t *p_intf, interaction_dialog_t *p_interact );
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static void intf_InteractionInit( playlist_t *p_playlist );
+static interaction_t * intf_InteractionGet( vlc_object_t *p_this );
+static void intf_InteractionSearchInterface( interaction_t *
+ p_interaction );
+static int intf_WaitAnswer( interaction_t *p_interact,
+ interaction_dialog_t *p_dialog );
+static int intf_Send( interaction_t *p_interact,
+ interaction_dialog_t *p_dialog );
+static interaction_dialog_t *intf_InteractionGetById( vlc_object_t* , int );
/**
* Send an interaction element to the user
* \return VLC_SUCCESS or an error code
*/
int __intf_Interact( vlc_object_t *p_this, interaction_dialog_t *
- p_interact )
+ p_dialog )
{
- vlc_list_t *p_list;
- int i_index;
- intf_thread_t *p_chosen_intf;
+ interaction_t *p_interaction = intf_InteractionGet( p_this );
- /* Search a suitable intf */
- p_list = vlc_list_find( p_this, VLC_OBJECT_INTF, FIND_ANYWHERE );
- if( !p_list )
+ /* Get an id, if we don't already have one */
+ if( p_dialog->i_id == 0 )
{
- msg_Err( p_this, "Unable to create module list" );
- return VLC_FALSE;
+ p_dialog->i_id = ++p_interaction->i_last_id;
}
- p_chosen_intf = NULL;
- for( i_index = 0; i_index < p_list->i_count; i_index ++ )
+ if( p_dialog->i_type == INTERACT_ASK )
{
- intf_thread_t *p_intf = (intf_thread_t *)
- p_list->p_values[i_index].p_object;
- if( p_intf->pf_interact != NULL )
- {
- p_chosen_intf = p_intf;
- break;
- }
+ return intf_WaitAnswer( p_interaction, p_dialog );
}
- if( !p_chosen_intf )
+ else
{
- msg_Dbg( p_this, "No interface suitable for interaction" );
- return VLC_FALSE;
+ return intf_Send( p_interaction, p_dialog );
}
- msg_Dbg( p_this, "found an interface for interaction" );
+}
- /* Find id, if we don't already have one */
- if( p_interact->i_id == 0 )
- {
- p_interact->i_id = ++p_chosen_intf->i_last_id;
- }
+/**
+ * Destroy the interaction system
+ */
+void intf_InteractionDestroy( interaction_t *p_interaction )
+{
+ /// \todo Code this, and call it
+}
+
+/**
+ * The main interaction processing loop
+ * This function is called from the playlist loop
+ *
+ * \param p_playlist the parent playlist
+ * \return nothing
+ */
+void intf_InteractionManage( playlist_t *p_playlist )
+{
+ int i_index;
+ interaction_t *p_interaction;
+
+ p_interaction = p_playlist->p_interaction;
+
+ // Nothing to do
+ if( p_interaction->i_dialogs == 0 ) return;
+
+ vlc_mutex_lock( &p_interaction->object_lock );
+
+ intf_InteractionSearchInterface( p_interaction );
- if( p_interact->i_type == INTERACT_ASK )
+ if( !p_interaction->p_intf )
{
- return intf_WaitAnswer( p_chosen_intf, p_interact );
+ vlc_mutex_unlock( &p_interaction->object_lock );
+
+ /// \todo Remove all dialogs as we can't display them
+ return;
}
- else
+
+ vlc_object_yield( p_interaction->p_intf );
+
+ for( i_index = 0 ; i_index < p_interaction->i_dialogs; i_index ++ )
{
- return intf_Send( p_chosen_intf, p_interact );
+ interaction_dialog_t *p_dialog = p_interaction->pp_dialogs[i_index];
+
+ if( p_dialog->b_have_answer )
+ {
+ /// \todo Signal we have an answer
+ // - If have answer, signal what is waiting
+ // (vlc_cond ? dangerous in case of pb ?)
+
+ // Ask interface to hide it
+ p_interaction->p_intf->pf_interact( p_interaction->p_intf,
+ p_dialog, INTERACT_HIDE );
+
+ }
+
+ if( p_dialog->b_updated )
+ {
+ p_dialog->b_finished = VLC_FALSE;
+ p_interaction->p_intf->pf_interact( p_interaction->p_intf,
+ p_dialog, INTERACT_UPDATE );
+ }
+
+ if( p_dialog->b_finished && !p_dialog->b_reusable )
+ {
+ /// \todo Destroy the dialog
+ }
+ // This is truly a new dialog, send it.
+ p_interaction->p_intf->pf_interact( p_interaction->p_intf,
+ p_dialog, INTERACT_NEW );
}
+
+ vlc_object_release( p_interaction->p_intf );
+
+ vlc_mutex_unlock( &p_playlist->p_interaction->object_lock );
}
-int intf_WaitAnswer( intf_thread_t *p_intf, interaction_dialog_t *p_interact )
+
+
+#define INTERACT_INIT( new ) \
+ new = (interaction_dialog_t*)malloc( \
+ sizeof( interaction_dialog_t ) ); \
+ new->i_widgets = 0; \
+ new->pp_widgets = NULL; \
+ new->psz_title = NULL; \
+ new->psz_description = NULL; \
+ new->i_id = 0;
+
+#define INTERACT_FREE( new ) \
+ if( new->psz_title ) free( new->psz_title ); \
+ if( new->psz_description ) free( new->psz_description );
+
+/** Helper function to send a fatal message
+ * \param p_this Parent vlc_object
+ * \param i_id A predefined ID, 0 if not applicable
+ * \param psz_title Title for the dialog
+ * \param psz_format The message to display
+ * */
+void __intf_UserFatal( vlc_object_t *p_this, int i_id,
+ const char *psz_title,
+ const char *psz_format, ... )
{
- // TODO: Add to queue, wait for answer
- return VLC_SUCCESS;
+ va_list args;
+ interaction_dialog_t *p_new = NULL;
+ user_widget_t *p_widget = NULL;
+
+ if( i_id > 0 )
+ {
+ p_new = intf_InteractionGetById( p_this, i_id );
+ }
+ if( !p_new )
+ {
+ INTERACT_INIT( p_new );
+ }
+
+ p_new->i_type = INTERACT_FATAL;
+ p_new->psz_title = strdup( psz_title );
+
+ p_widget = (user_widget_t* )malloc( sizeof( user_widget_t ) );
+
+ p_widget->i_type = WIDGET_TEXT;
+
+ va_start( args, psz_format );
+ vasprintf( &p_widget->psz_text, psz_format, args );
+ va_end( args );
+
+ INSERT_ELEM ( p_new->pp_widgets,
+ p_new->i_widgets,
+ p_new->i_widgets,
+ p_widget );
+
+ intf_Interact( p_this, p_new );
}
-int intf_Send( intf_thread_t *p_intf, interaction_dialog_t *p_interact )
+#if 0
+/** Helper function to build a progress bar
+ * \param p_this Parent vlc object
+ */
+interaction_dialog_t *__intf_ProgressBuild( vlc_object_t *p_this,
+ const char *psz_text )
{
- // TODO: Add to queue, return
- return VLC_SUCCESS;
+ interaction_dialog_t *p_new = (interaction_dialog_t *)malloc(
+ sizeof( interaction_dialog_t ) );
+
+
+ return p_new;
}
+#endif
-// The playlist manages the user interaction to avoid creating another thread
-void intf_InteractionManage( playlist_t *p_playlist )
+
+
+/**********************************************************************
+ * The following functions are local
+ **********************************************************************/
+
+/* Get the interaction object. Create it if needed */
+static interaction_t * intf_InteractionGet( vlc_object_t *p_this )
{
+ playlist_t *p_playlist;
+ interaction_t *p_interaction;
+
+ p_playlist = (playlist_t*) vlc_object_find( p_this, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ if( !p_playlist )
+ {
+ return NULL;
+ }
+
if( p_playlist->p_interaction == NULL )
{
intf_InteractionInit( p_playlist );
}
- vlc_mutex_lock( &p_playlist->p_interaction->object_lock );
+ p_interaction = p_playlist->p_interaction;
- /* Todo:
- * - Walk the queue
- * - If blocking
- * - If have answer, signal what is waiting (vlc_cond ? dangerous in case of pb ?)
- * And then, if not reusable, destroy
- * - If have update, send update
- */
+ vlc_object_release( p_playlist );
- vlc_mutex_unlock( &p_playlist->p_interaction->object_lock );
+ return p_interaction;
}
+/* Create the interaction object in the given playlist object */
static void intf_InteractionInit( playlist_t *p_playlist )
{
interaction_t *p_interaction;
- p_interaction = vlc_object_create( VLC_OBJECT( p_playlist ), sizeof( interaction_t ) );
+
+ msg_Dbg( p_playlist, "initializing interaction system" );
+
+ p_interaction = vlc_object_create( VLC_OBJECT( p_playlist ),
+ sizeof( interaction_t ) );
if( !p_interaction )
{
msg_Err( p_playlist,"out of memory" );
p_interaction->i_dialogs = 0;
p_interaction->pp_dialogs = NULL;
+ p_interaction->p_intf = NULL;
+ p_interaction->i_last_id = DIALOG_LAST_PREDEFINED + 1;
+
+ vlc_mutex_init( p_interaction , &p_interaction->object_lock );
+
+ p_playlist->p_interaction = p_interaction;
}
-/** Helper function to build a progress bar */
-interaction_dialog_t *__intf_ProgressBuild( vlc_object_t *p_this,
- const char *psz_text )
+/* Look for an interface suitable for interaction */
+static void intf_InteractionSearchInterface( interaction_t *p_interaction )
{
- interaction_dialog_t *p_new = (interaction_dialog_t *)malloc(
- sizeof( interaction_dialog_t ) );
+ vlc_list_t *p_list;
+ int i_index;
+ p_interaction->p_intf = NULL;
- return p_new;
-}
-
-#define INTERACT_INIT( new ) \
- interaction_dialog_t *new = (interaction_dialog_t*)malloc( \
- sizeof( interaction_dialog_t ) ); \
- new->i_widgets = 0; \
- new->pp_widgets = NULL; \
- new->psz_title = NULL; \
- new->psz_description = NULL; \
- new->i_id = 0;
+ p_list = vlc_list_find( p_interaction, VLC_OBJECT_INTF, FIND_ANYWHERE );
+ if( !p_list )
+ {
+ msg_Err( p_interaction, "Unable to create module list" );
+ return;
+ }
-#define INTERACT_FREE( new ) \
- if( new->psz_title ) free( new->psz_title ); \
- if( new->psz_description ) free( new->psz_description );
+ for( i_index = 0; i_index < p_list->i_count; i_index ++ )
+ {
+ intf_thread_t *p_intf = (intf_thread_t *)
+ p_list->p_values[i_index].p_object;
+ if( p_intf->pf_interact != NULL )
+ {
+ p_interaction->p_intf = p_intf;
+ break;
+ }
+ }
+ vlc_list_release ( p_list );
+}
-/** Helper function to send a fatal message */
-void intf_UserFatal( vlc_object_t *p_this, const char *psz_title,
- const char *psz_format, ... )
+/* Add a dialog to the queue and wait for answer */
+static int intf_WaitAnswer( interaction_t *p_interact, interaction_dialog_t *p_dialog )
{
- va_list args;
+ // TODO: Add to queue, wait for answer
+ return VLC_SUCCESS;
+}
- INTERACT_INIT( p_new );
- p_new->i_type = INTERACT_FATAL;
- p_new->psz_title = strdup( psz_title );
+/* Add a dialog to the queue and return */
+static int intf_Send( interaction_t *p_interact, interaction_dialog_t *p_dialog )
+{
+ vlc_mutex_lock( &p_interact->object_lock );
- va_start( args, psz_format );
- vasprintf( &p_new->psz_description, psz_format, args );
- va_end( args );
+ /// \todo Check first it does not exist !!!
+ INSERT_ELEM( p_interact->pp_dialogs,
+ p_interact->i_dialogs,
+ p_interact->i_dialogs,
+ p_dialog );
+ vlc_mutex_unlock( &p_interact->object_lock );
+ return VLC_SUCCESS;
+}
- intf_Interact( p_this, p_new );
+/* Find an interaction dialog by its id */
+static interaction_dialog_t *intf_InteractionGetById( vlc_object_t* p_this,
+ int i_id )
+{
+ interaction_t *p_interaction = intf_InteractionGet( p_this );
+ int i;
- INTERACT_FREE( p_new );
+ for( i = 0 ; i< p_interaction->i_dialogs; i++ )
+ {
+ if( p_interaction->pp_dialogs[i]->i_id == i_id )
+ {
+ return p_interaction->pp_dialogs[i];
+ }
+ }
+ return NULL;
}