]> git.sesse.net Git - vlc/commitdiff
* Handle dialogs needing answer
authorClément Stenac <zorglub@videolan.org>
Sun, 11 Dec 2005 16:06:19 +0000 (16:06 +0000)
committerClément Stenac <zorglub@videolan.org>
Sun, 11 Dec 2005 16:06:19 +0000 (16:06 +0000)
* Handle interfaces not providing interaction correctly
* Add a new helper to request authentication
* Add return codes

include/vlc_interaction.h
include/vlc_interface.h
include/vlc_symbols.h
src/input/input.c
src/interface/interaction.c

index e2891016860251aa2cd7ede95d447fb17155e7c1..b76cf57925473b227fb1508556679d213f5a23de 100644 (file)
@@ -39,7 +39,7 @@ enum
 {
     WIDGET_TEXT,                        //< Text display
     WIDGET_PROGRESS,                    //< A progress bar
-    WIDGET_INPUT                       //< Input (backed up by a variable)
+    WIDGET_INPUT_TEXT                   //< Input (backed up by a variable)
 };
 
 /**
@@ -52,16 +52,39 @@ struct interaction_dialog_t
     char           *psz_title;          //< Title
     char           *psz_description;    //< Descriptor string
 
-    /* For dialogs */
     int             i_widgets;          //< Nu,ber of dialog widgets
     user_widget_t **pp_widgets;         //< Dialog widgets
 
-    vlc_bool_t      b_reusable;         //< Do we have to reuse this ?
-
     void *          p_private;          //< Private interface data
-    int             i_status;           //< Dialog status;
 
+    int             i_status;           //< Dialog status;
     int             i_action;           //< Action to perform;
+    int             i_flags;            //< Misc flags
+    int             i_return;           //< Return status
+
+    interaction_t  *p_interaction;      //< Parent interaction object
+    vlc_object_t   *p_parent;           //< The vlc object that asked
+                                        //for interaction
+};
+
+/**
+ * Possible flags . Reusable and button types
+ */
+#define DIALOG_REUSABLE      0x01
+#define DIALOG_OK_CANCEL     0x02
+#define DIALOG_YES_NO        0x04
+#define DIALOG_YES_NO_CANCEL 0x04
+#define DIALOG_GOT_ANSWER    0x08
+
+/**
+ * Possible return codes
+ */
+enum
+{
+    DIALOG_DEFAULT,
+    DIALOG_OK_YES,
+    DIALOG_NO,
+    DIALOG_CANCELLED
 };
 
 /**
@@ -69,12 +92,13 @@ struct interaction_dialog_t
  */
 enum
 {
-    NEW_DIALOG,
-    SENT_DIALOG,
-    UPDATED_DIALOG,
-    ANSWERED_DIALOG,
-    HIDING_DIALOG,
-    HIDDEN_DIALOG,
+    NEW_DIALOG,                 //< Just created
+    SENT_DIALOG,                //< Sent to interface
+    UPDATED_DIALOG,             //< Update to send
+    ANSWERED_DIALOG,            //< Got "answer"
+    HIDING_DIALOG,              //< Hiding requested
+    HIDDEN_DIALOG,              //< Now hidden. Requesting destruction
+    DESTROYED_DIALOG,           //< Interface has destroyed it
 };
 
 /**
@@ -82,11 +106,9 @@ enum
  */
 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)
+    INTERACT_PROGRESS,          //< Progress bar (in the main interface ?)
+    INTERACT_DIALOG_ONEWAY,     //< Dialog box without feedback
+    INTERACT_DIALOG_TWOWAY,     //< Dialog box with feedback
 };
 
 /**
@@ -95,9 +117,7 @@ enum
 enum
 {
     DIALOG_FIRST,
-    DIALOG_NOACCESS,
-    DIALOG_NOCODEC,
-    DIALOG_NOAUDIO,
+    DIALOG_ERRORS,
 
     DIALOG_LAST_PREDEFINED,
 };
@@ -124,7 +144,8 @@ enum
 {
     INTERACT_NEW,
     INTERACT_UPDATE,
-    INTERACT_HIDE
+    INTERACT_HIDE,
+    INTERACT_DESTROY
 };
 
 /***************************************************************************
@@ -134,8 +155,10 @@ enum
 #define intf_Interact( a,b ) __intf_Interact( VLC_OBJECT(a), b )
 VLC_EXPORT( int,__intf_Interact,( vlc_object_t *,interaction_dialog_t * ) );
 
-#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*, ...) );
+#define intf_UserFatal( a, c, d, e... ) __intf_UserFatal( a,c,d, ## e )
+VLC_EXPORT( void, __intf_UserFatal,( vlc_object_t*, const char*, const char*, ...) );
+#define intf_UserLoginPassword( a, b, c, d, e... ) __intf_UserLoginPassword( a,b,c,d,e)
+VLC_EXPORT( int, __intf_UserLoginPassword,( vlc_object_t*, const char*, const char*, char **, char **) );
 
 VLC_EXPORT( void, intf_InteractionManage,( playlist_t *) );
 VLC_EXPORT( void, intf_InteractionDestroy,( interaction_t *) );
index b05f1d78b1ad9b3da3789b85593ac9c3f3c6f114..701cc1b8a73f416eca240733798061948cfc5c51 100644 (file)
@@ -92,6 +92,7 @@ struct intf_thread_t
  *****************************************************************************/
 struct intf_dialog_args_t
 {
+    intf_thread_t *p_intf;
     char *psz_title;
 
     char **psz_results;
@@ -104,6 +105,9 @@ struct intf_dialog_args_t
     char *psz_extensions;
     vlc_bool_t b_save;
     vlc_bool_t b_multiple;
+
+    /* Specific to INTF_DIALOG_INTERACTION */
+    interaction_dialog_t *p_dialog;
 };
 
 /*****************************************************************************
@@ -160,6 +164,7 @@ VLC_EXPORT( void,              intf_Destroy,    ( intf_thread_t * ) );
 #define INTF_DIALOG_POPUPMENU  20
 
 #define INTF_DIALOG_FILE_GENERIC 30
+#define INTF_DIALOG_INTERACTION 50
 
 #define INTF_DIALOG_UPDATEVLC   90
 #define INTF_DIALOG_VLM   91
index 6f1d28ec794b22da32bd9d040385a7a0bfc0512d..1a1a19a606bad045273fc04850347f05217b5901 100644 (file)
@@ -145,6 +145,7 @@ int playlist_Export (playlist_t *, const char *, const char *);
 demux_t * __demux2_New (vlc_object_t *p_obj, char *psz_access, char *psz_demux, char *psz_path, stream_t *s, es_out_t *out, vlc_bool_t);
 int __vlc_threads_end (vlc_object_t *);
 int sout_AccessOutRead (sout_access_out_t *, block_t *);
+int __intf_UserLoginPassword (vlc_object_t*, const char*, const char*, char **, char **);
 int demux2_vaControlHelper (stream_t *, int64_t i_start, int64_t i_end, int i_bitrate, int i_align, int i_query, va_list args);
 int httpd_UrlCatch (httpd_url_t *, int i_msg, httpd_callback_t, httpd_callback_sys_t *);
 void __vlc_object_yield (vlc_object_t *);
@@ -297,7 +298,7 @@ subpicture_t * spu_CreateSubpicture (spu_t *);
 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*, ...);
+void __intf_UserFatal (vlc_object_t*, 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);
@@ -858,7 +859,8 @@ struct module_symbols_t
     int (*__intf_Interact_inner) (vlc_object_t *,interaction_dialog_t *);
     void (*intf_InteractionManage_inner) (playlist_t *);
     void (*intf_InteractionDestroy_inner) (interaction_t *);
-    void (*__intf_UserFatal_inner) (vlc_object_t*, int, const char*, const char*, ...);
+    void (*__intf_UserFatal_inner) (vlc_object_t*, const char*, const char*, ...);
+    int (*__intf_UserLoginPassword_inner) (vlc_object_t*, const char*, const char*, char **, char **);
 };
 #  if defined (__PLUGIN__)
 #  define aout_FiltersCreatePipeline (p_symbols)->aout_FiltersCreatePipeline_inner
@@ -1274,6 +1276,7 @@ struct module_symbols_t
 #  define intf_InteractionManage (p_symbols)->intf_InteractionManage_inner
 #  define intf_InteractionDestroy (p_symbols)->intf_InteractionDestroy_inner
 #  define __intf_UserFatal (p_symbols)->__intf_UserFatal_inner
+#  define __intf_UserLoginPassword (p_symbols)->__intf_UserLoginPassword_inner
 #  elif defined (HAVE_DYNAMIC_PLUGINS) && !defined (__BUILTIN__)
 /******************************************************************
  * STORE_SYMBOLS: store VLC APIs into p_symbols for plugin access.
@@ -1692,6 +1695,7 @@ struct module_symbols_t
     ((p_symbols)->intf_InteractionManage_inner) = intf_InteractionManage; \
     ((p_symbols)->intf_InteractionDestroy_inner) = intf_InteractionDestroy; \
     ((p_symbols)->__intf_UserFatal_inner) = __intf_UserFatal; \
+    ((p_symbols)->__intf_UserLoginPassword_inner) = __intf_UserLoginPassword; \
     (p_symbols)->net_ConvertIPv4_deprecated = NULL; \
 
 #  endif /* __PLUGIN__ */
index 5ab59b5085a31842dac2f056652db0beeca5a7ef..69c4f8c7d8ed3b8a3b0f88a64c26a6ab3921fb80 100644 (file)
@@ -2095,9 +2095,8 @@ static int InputSourceInit( input_thread_t *p_input,
         if( in->p_access == NULL )
         {
             msg_Err( p_input, "no suitable access module for `%s'", psz_mrl );
-            intf_UserFatal( VLC_OBJECT( p_input), DIALOG_NOACCESS,
-                            "Error opening stream",
-                            "Unable to open '%s'", psz_mrl );
+            intf_UserFatal( VLC_OBJECT( p_input),
+                            _("Errors"),"Unable to open '%s'", psz_mrl );
             goto error;
         }
 
@@ -2167,6 +2166,8 @@ static int InputSourceInit( input_thread_t *p_input,
         {
             msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
                      psz_access, psz_demux, psz_path );
+            intf_UserFatal( VLC_OBJECT( p_input), _("Errors"),
+                            "Unrecognized format for '%s'", psz_mrl );
             goto error;
         }
 
index e276e2bf1664bb477369d383d5e42f8f54da1d13..2cfcb3e987f00d15adb7a8dafa8e480a5430abe3 100644 (file)
@@ -63,7 +63,6 @@ static interaction_dialog_t *intf_InteractionGetById( vlc_object_t* , int );
 int  __intf_Interact( vlc_object_t *p_this, interaction_dialog_t *
                                     p_dialog )
 {
-
     interaction_t *p_interaction = intf_InteractionGet( p_this );
 
     /* Get an id, if we don't already have one */
@@ -72,12 +71,16 @@ int  __intf_Interact( vlc_object_t *p_this, interaction_dialog_t *
         p_dialog->i_id = ++p_interaction->i_last_id;
     }
 
-    if( p_dialog->i_type == INTERACT_ASK )
+    p_dialog->p_interaction = p_interaction;
+    p_dialog->p_parent = p_this;
+
+    if( p_dialog->i_type == INTERACT_DIALOG_TWOWAY )
     {
         return intf_WaitAnswer( p_interaction, p_dialog );
     }
     else
     {
+        p_dialog->i_flags |=  DIALOG_GOT_ANSWER;
         return intf_Send( p_interaction, p_dialog );
     }
 }
@@ -114,59 +117,78 @@ void intf_InteractionManage( playlist_t *p_playlist )
 
     if( !p_interaction->p_intf )
     {
-        vlc_mutex_unlock( &p_interaction->object_lock );
-
-        /// \todo Remove all dialogs as we can't display them
-        return;
+        // We mark all dialogs as answered with their "default" answer
+        for( i_index = 0 ; i_index < p_interaction->i_dialogs; i_index ++ )
+        {
+            interaction_dialog_t *p_dialog = p_interaction->pp_dialogs[i_index];
+            p_dialog->i_return = DIALOG_DEFAULT;
+            if( p_dialog->i_flags & DIALOG_OK_CANCEL )
+                p_dialog->i_return = DIALOG_CANCELLED;
+            if( p_dialog->i_flags & DIALOG_YES_NO_CANCEL )
+                p_dialog->i_return = DIALOG_CANCELLED;
+            p_dialog->i_status = ANSWERED_DIALOG;
+        }
+    }
+    else
+    {
+        vlc_object_yield( p_interaction->p_intf );
     }
-
-    vlc_object_yield( p_interaction->p_intf );
 
     for( i_index = 0 ; i_index < p_interaction->i_dialogs; i_index ++ )
     {
         interaction_dialog_t *p_dialog = p_interaction->pp_dialogs[i_index];
-
         switch( p_dialog->i_status )
         {
         case ANSWERED_DIALOG:
-            /// \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
             msg_Dbg( p_interaction, "Hiding dialog %i", p_dialog->i_id );
             p_dialog->i_action = INTERACT_HIDE;
             val.p_address = p_dialog;
-            var_Set( p_interaction->p_intf, "interaction", val );
+            if( p_interaction->p_intf )
+                var_Set( p_interaction->p_intf, "interaction", val );
             p_dialog->i_status = HIDING_DIALOG;
             break;
         case UPDATED_DIALOG:
             p_dialog->i_action = INTERACT_UPDATE;
             val.p_address = p_dialog;
-            var_Set( p_interaction->p_intf, "interaction", val );
+            if( p_interaction->p_intf )
+                var_Set( p_interaction->p_intf, "interaction", val );
             p_dialog->i_status = SENT_DIALOG;
             msg_Dbg( p_interaction, "Updating dialog %i, %i widgets",
                                     p_dialog->i_id, p_dialog->i_widgets );
             break;
         case HIDDEN_DIALOG:
-            if( !p_dialog->b_reusable )
+            if( !(p_dialog->i_flags & DIALOG_GOT_ANSWER) ) break;
+            if( !(p_dialog->i_flags & DIALOG_REUSABLE) )
             {
-                /// \todo Destroy the dialog
+                msg_Dbg( p_interaction, "Destroying dialog %i",
+                                                p_dialog->i_id );
+                p_dialog->i_action = INTERACT_DESTROY;
+                val.p_address = p_dialog;
+                if( p_interaction->p_intf )
+                    var_Set( p_interaction->p_intf, "interaction", val );
             }
             break;
+        case DESTROYED_DIALOG:
+            // Interface has now destroyed it, remove it
+            /// \todo Remove it from the list
+            /// \todo Free data fields
+            free( p_dialog );
         case NEW_DIALOG:
             // This is truly a new dialog, send it.
             p_dialog->i_action = INTERACT_NEW;
             val.p_address = p_dialog;
-            var_Set( p_interaction->p_intf, "interaction", val );
-            msg_Dbg( p_interaction, "Creating dialog %i to interface %i, %i widgets",
-                                        p_dialog->i_id, p_interaction->p_intf->i_object_id, p_dialog->i_widgets );
+            if( p_interaction->p_intf )
+                var_Set( p_interaction->p_intf, "interaction", val );
             p_dialog->i_status = SENT_DIALOG;
             break;
         }
     }
 
-    vlc_object_release( p_interaction->p_intf );
+    if( p_interaction->p_intf )
+    {
+        vlc_object_release( p_interaction->p_intf );
+    }
 
     vlc_mutex_unlock( &p_playlist->p_interaction->object_lock );
 }
@@ -187,19 +209,20 @@ void intf_InteractionManage( playlist_t *p_playlist )
         if( new->psz_title ) free( new->psz_title );                    \
         if( new->psz_description ) free( new->psz_description );
 
-/** Helper function to send a fatal message
+/** Helper function to send an error 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,
+void __intf_UserFatal( vlc_object_t *p_this,
                        const char *psz_title,
                        const char *psz_format, ... )
 {
     va_list args;
     interaction_dialog_t *p_new = NULL;
     user_widget_t *p_widget = NULL;
+    int i_id = DIALOG_ERRORS;
 
     if( i_id > 0 )
     {
@@ -215,7 +238,9 @@ void __intf_UserFatal( vlc_object_t *p_this, int i_id,
         p_new->i_status = UPDATED_DIALOG;
     }
 
-    p_new->i_type = INTERACT_FATAL;
+    p_new->i_flags |= DIALOG_REUSABLE;
+
+    p_new->i_type = INTERACT_DIALOG_ONEWAY;
     p_new->psz_title = strdup( psz_title );
 
     p_widget = (user_widget_t* )malloc( sizeof( user_widget_t ) );
@@ -234,22 +259,63 @@ void __intf_UserFatal( vlc_object_t *p_this, int i_id,
     intf_Interact( p_this, p_new );
 }
 
-#if 0
-/** Helper function to build a progress bar
- * \param p_this   Parent vlc object
+/** Helper function to make a login/password box
+ *  \param p_this           Parent vlc_object
+ *  \param psz_title        Title for the dialog
+ *  \param psz_description  A description
+ *  \param ppsz_login       Returned login
+ *  \param ppsz_password    Returned password
+ *  \return                 1 if user clicked Cancel, 0 if OK
  */
-interaction_dialog_t *__intf_ProgressBuild( vlc_object_t *p_this,
-                                            const char *psz_text )
+int __intf_UserLoginPassword( vlc_object_t *p_this,
+                              const char *psz_title,
+                              const char *psz_description,
+                              char **ppsz_login,
+                              char **ppsz_password )
 {
-    interaction_dialog_t *p_new = (interaction_dialog_t *)malloc(
-                                        sizeof( interaction_dialog_t ) );
+    int i_ret;
+    interaction_dialog_t *p_new = NULL;
+    user_widget_t *p_widget = NULL;
 
+    INTERACT_INIT( p_new );
 
-    return p_new;
-}
-#endif
+    p_new->i_type = INTERACT_DIALOG_TWOWAY;
+    p_new->psz_title = strdup( psz_title );
+
+    /* Text */
+    p_widget = (user_widget_t* )malloc( sizeof( user_widget_t ) );
+    p_widget->i_type = WIDGET_TEXT;
+    p_widget->psz_text = strdup( psz_description );
+    INSERT_ELEM ( p_new->pp_widgets, p_new->i_widgets,
+                  p_new->i_widgets,  p_widget );
+
+    /* Login */
+    p_widget = (user_widget_t* )malloc( sizeof( user_widget_t ) );
+    p_widget->i_type = WIDGET_INPUT_TEXT;
+    p_widget->psz_text = strdup( _("Login") );
+    p_widget->val.psz_string = NULL;
+    INSERT_ELEM ( p_new->pp_widgets, p_new->i_widgets,
+                  p_new->i_widgets,  p_widget );
 
+    /* Password */
+    p_widget = (user_widget_t* )malloc( sizeof( user_widget_t ) );
+    p_widget->i_type = WIDGET_INPUT_TEXT;
+    p_widget->psz_text = strdup( _("Password") );
+    p_widget->val.psz_string = NULL;
+    INSERT_ELEM ( p_new->pp_widgets, p_new->i_widgets,
+                  p_new->i_widgets,  p_widget );
 
+    p_new->i_flags = DIALOG_OK_CANCEL;
+
+    i_ret = intf_Interact( p_this, p_new );
+
+    if( i_ret == DIALOG_OK_YES )
+    {
+        *ppsz_login = strdup( p_new->pp_widgets[1]->val.psz_string );
+        *ppsz_password = strdup( p_new->pp_widgets[2]->val.psz_string );
+    }
+    return i_ret;
+}
 
 /**********************************************************************
  * The following functions are local
@@ -337,20 +403,67 @@ static void intf_InteractionSearchInterface( interaction_t *p_interaction )
 /* Add a dialog to the queue and wait for answer */
 static int intf_WaitAnswer( interaction_t *p_interact, interaction_dialog_t *p_dialog )
 {
-    // TODO: Add to queue, wait for answer
-    return VLC_SUCCESS;
+    int i;
+    vlc_bool_t b_found = VLC_FALSE;
+    vlc_mutex_lock( &p_interact->object_lock );
+    for( i = 0 ; i< p_interact->i_dialogs; i++ )
+    {
+        if( p_interact->pp_dialogs[i]->i_id == p_dialog->i_id )
+        {
+            b_found = VLC_TRUE;
+        }
+    }
+    if( ! b_found )
+    {
+        INSERT_ELEM( p_interact->pp_dialogs,
+                     p_interact->i_dialogs,
+                     p_interact->i_dialogs,
+                     p_dialog );
+    }
+    else
+        p_dialog->i_status = UPDATED_DIALOG;
+    vlc_mutex_unlock( &p_interact->object_lock );
+
+    /// \todo Check that the initiating object is not dying
+    while( p_dialog->i_status != ANSWERED_DIALOG &&
+           p_dialog->i_status != HIDING_DIALOG &&
+           !p_dialog->p_parent->b_die )
+    {
+        msleep( 100000 );
+    }
+    /// \todo locking
+    if( p_dialog->p_parent->b_die )
+    {
+        p_dialog->i_return = DIALOG_CANCELLED;
+        p_dialog->i_status = ANSWERED_DIALOG;
+    }
+    p_dialog->i_flags |= DIALOG_GOT_ANSWER;
+    return p_dialog->i_return;
 }
 
 /* Add a dialog to the queue and return */
 static int intf_Send( interaction_t *p_interact, interaction_dialog_t *p_dialog )
 {
+    int i;
+    vlc_bool_t b_found = VLC_FALSE;
     vlc_mutex_lock( &p_interact->object_lock );
 
-    /// \todo Check first it does not exist !!!
-    INSERT_ELEM( p_interact->pp_dialogs,
-                 p_interact->i_dialogs,
-                 p_interact->i_dialogs,
-                 p_dialog );
+    for( i = 0 ; i< p_interact->i_dialogs; i++ )
+    {
+        if( p_interact->pp_dialogs[i]->i_id == p_dialog->i_id )
+        {
+            b_found = VLC_TRUE;
+        }
+    }
+    if( !b_found )
+    {
+        INSERT_ELEM( p_interact->pp_dialogs,
+                     p_interact->i_dialogs,
+                     p_interact->i_dialogs,
+                     p_dialog );
+    }
+    else
+        p_dialog->i_status = UPDATED_DIALOG;
     vlc_mutex_unlock( &p_interact->object_lock );
     return VLC_SUCCESS;
 }
@@ -362,6 +475,8 @@ static interaction_dialog_t *intf_InteractionGetById( vlc_object_t* p_this,
     interaction_t *p_interaction = intf_InteractionGet( p_this );
     int i;
 
+    if( !p_interaction ) return NULL;
+
     for( i = 0 ; i< p_interaction->i_dialogs; i++ )
     {
         if( p_interaction->pp_dialogs[i]->i_id == i_id )