From 5afb060fb5643133bc5122733a4f642d9e22ba63 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Cl=C3=A9ment=20Stenac?= Date: Mon, 5 Dec 2005 15:51:39 +0000 Subject: [PATCH] Very beginning of the interaction framework (Refs:#27) --- Makefile.am | 1 + extras/make.pl | 6 +- include/vlc_common.h | 7 +- include/vlc_interaction.h | 93 +++++++++++++++++ include/vlc_interface.h | 5 + include/vlc_playlist.h | 6 ++ src/input/input.c | 1 + src/interface/interaction.c | 193 ++++++++++++++++++++++++++++++++++++ src/interface/interface.c | 1 + src/playlist/playlist.c | 12 +++ 10 files changed, 320 insertions(+), 5 deletions(-) create mode 100644 include/vlc_interaction.h create mode 100644 src/interface/interaction.c diff --git a/Makefile.am b/Makefile.am index 6109e05645..3ff67dc247 100644 --- a/Makefile.am +++ b/Makefile.am @@ -393,6 +393,7 @@ SOURCES_libvlc_common = \ src/libvlc.h \ src/interface/interface.c \ src/interface/intf_eject.c \ + src/interface/interaction.c \ src/playlist/playlist.c \ src/playlist/sort.c \ src/playlist/loadsave.c \ diff --git a/extras/make.pl b/extras/make.pl index b23bc19fbe..ee5663a306 100755 --- a/extras/make.pl +++ b/extras/make.pl @@ -29,18 +29,18 @@ while() $line =~ /^test\s\-z\s/ || $line =~ /^Making\sclean\sin\s\./ || $line =~ /^then\smv/ || - $line =~ /make\s\sall-recursive/ ) + $line =~ /make\s\sall-recursive/ || + $line =~ s/^[A-z0-9-]*ar\s[A-z0-9]*\s([A-z0-9\-_\/\.]*)\s.*//g || + $line =~ s/^rm\s\-f\s(.*)//g ) {} # Info elsif( $line =~ s/^.* (lib.*\.so).*/ LINK : $1/g || $line =~ s/^.* (lib.*\.o)\s\.\/(.*)/ COMPILE : $2/g || $line =~ s/^.* (lib.*\.o)\s`.*`(.*);\ \\/ COMPILE : $2/ || - $line =~ s/^[A-z0-9-]*ar\s[A-z0-9]*\s([A-z0-9\-_\/\.]*)\s.*/ ARCHIVE : $1/g || $line =~ s/^[A-z0-9-]*ranlib\s(.*)/ RANLIB : $1/g || $line =~ s/^Making\sall\sin\s(.*)/MAKE : $1/g || $line =~ s/^Making\sclean\sin\s(.*)/CLEAN : $1/g || - $line =~ s/^rm\s\-f\s(.*)/ REMOVE : $1/g || $line =~ s/.*\-o\s([^\s]*)\s.*/ BUILD : $1/g) { diff --git a/include/vlc_common.h b/include/vlc_common.h index abecaea009..5841bc077e 100644 --- a/include/vlc_common.h +++ b/include/vlc_common.h @@ -223,7 +223,7 @@ typedef enum { PLAYLIST_STOP, /**< No arg res=can fail*/ PLAYLIST_SKIP, /**< arg1=int, res=can fail*/ PLAYLIST_GOTO, /**< arg1=int res=can fail */ - PLAYLIST_VIEWGOTO, /**< arg1=int res=can fail */ + PLAYLIST_VIEWGOTO /**< arg1=int res=can fail */ } playlist_command_t; @@ -251,6 +251,9 @@ typedef struct intf_sys_t intf_sys_t; typedef struct intf_console_t intf_console_t; typedef struct intf_msg_t intf_msg_t; typedef struct intf_channel_t intf_channel_t; +typedef struct interaction_t interaction_t; +typedef struct interaction_dialog_t interaction_dialog_t; +typedef struct user_widget_t user_widget_t; /* Input */ typedef struct input_thread_t input_thread_t; @@ -338,7 +341,7 @@ typedef struct session_descriptor_t session_descriptor_t; typedef struct announce_method_t announce_method_t; typedef struct announce_handler_t announce_handler_t; typedef struct sap_handler_t sap_handler_t; -//typedef struct slp_session_t slp_session_t; +/* typedef struct slp_session_t slp_session_t; */ /* Decoders */ typedef struct decoder_t decoder_t; diff --git a/include/vlc_interaction.h b/include/vlc_interaction.h new file mode 100644 index 0000000000..b7b2bddcc6 --- /dev/null +++ b/include/vlc_interaction.h @@ -0,0 +1,93 @@ +/***************************************************************************** + * vlc_interaction.h: structures and function for user interaction + ***************************************************************************** + * Copyright (C) 1999-2004 VideoLAN + * $Id: vlc_interaction.h 7954 2004-06-07 22:19:12Z fenrir $ + * + * Authors: Clément Stenac + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + *****************************************************************************/ + +/** + * This structure describes an interaction widget + */ +struct user_widget_t +{ + int i_type; //< Type identifier; + char *psz_text; //< Free text + + vlc_value_t val; +}; + +/** + * Possible widget types + */ +enum +{ + WIDGET_TEXT, //< Text display + WIDGET_PROGRESS, //< A progress bar + WIDGET_INPUT //< Input (backed up by a variable) +}; + +/** + * This structure describes a piece of interaction with the user + */ +struct interaction_dialog_t +{ + int i_id; //< Unique ID + int i_type; //< Type identifier + 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_have_answer; //< Has an answer been given ? + vlc_bool_t b_reusable; //< Do we have to reuse this ? + + void * p_private; //< Private interface data +}; + +/** + * This structure contains the active interaction dialogs, and is + * used by teh manager + */ +struct interaction_t +{ + VLC_COMMON_MEMBERS + + int i_dialogs; //< Number of dialogs + interaction_dialog_t **pp_dialogs; //< Dialogs +}; + +/** + * Possible interaction types + */ +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) +}; + +#define intf_Interact( a,b ) __intf_Interact( VLC_OBJECT(a), b ) +VLC_EXPORT( int,__intf_Interact,( vlc_object_t *,interaction_dialog_t * ) ); + +VLC_EXPORT( int,__intf_InteractionManage,( playlist_t *) ); + +VLC_EXPORT( void, intf_UserFatal,( vlc_object_t*, const char*, const char*, ...)); diff --git a/include/vlc_interface.h b/include/vlc_interface.h index 4dab19532a..533aff28d3 100644 --- a/include/vlc_interface.h +++ b/include/vlc_interface.h @@ -23,6 +23,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/ + typedef struct intf_dialog_args_t intf_dialog_args_t; /** @@ -64,6 +65,10 @@ struct intf_thread_t void ( *pf_show_dialog ) ( intf_thread_t *, int, int, intf_dialog_args_t * ); + /** Interaction stuff */ + int i_last_id; + int ( *pf_interact ) ( intf_thread_t *, interaction_dialog_t *, vlc_bool_t ); + /** Video window callbacks */ void * ( *pf_request_window ) ( intf_thread_t *, vout_thread_t *, int *, int *, diff --git a/include/vlc_playlist.h b/include/vlc_playlist.h index aabd612ff6..3bd4ebb304 100644 --- a/include/vlc_playlist.h +++ b/include/vlc_playlist.h @@ -213,6 +213,12 @@ struct playlist_t vlc_mutex_t gc_lock; /**< Lock to protect the garbage collection */ + // The following members are about user interaction + // The playlist manages the user interaction to avoid creating another + // thread + vlc_bool_t b_manage_interaction; + interaction_t *p_interaction; + /*@}*/ }; diff --git a/src/input/input.c b/src/input/input.c index 96061150e5..5d1992523b 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -2094,6 +2094,7 @@ 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( p_input, "Unable to open '%s'", psz_mrl ); goto error; } diff --git a/src/interface/interaction.c b/src/interface/interaction.c new file mode 100644 index 0000000000..662d7bc721 --- /dev/null +++ b/src/interface/interaction.c @@ -0,0 +1,193 @@ +/***************************************************************************** + * interaction.c: User interaction functions + ***************************************************************************** + * Copyright (C) 1998-2004 VideoLAN + * $Id: interface.c 10147 2005-03-05 17:18:30Z gbazin $ + * + * Authors: Clément Stenac + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + *****************************************************************************/ + +/** + * \file + * This file contains functions related to user interaction management + */ + + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include /* free(), strtol() */ +#include /* FILE */ +#include /* strerror() */ + +#include +#include + +#include "vlc_interaction.h" +#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 ); + +/** + * Send an interaction element to the user + * + * \param p_this the calling vlc_object_t + * \param p_interact the interaction element + * \return VLC_SUCCESS or an error code + */ +int __intf_Interact( vlc_object_t *p_this, interaction_dialog_t * + p_interact ) +{ + vlc_list_t *p_list; + int i_index; + intf_thread_t *p_chosen_intf; + + + /* Search a suitable intf */ + p_list = vlc_list_find( p_this, VLC_OBJECT_INTF, FIND_ANYWHERE ); + if( !p_list ) + { + msg_Err( p_this, "Unable to create module list" ); + return VLC_FALSE; + } + + p_chosen_intf = NULL; + 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_chosen_intf = p_intf; + break; + } + } + if( !p_chosen_intf ) + { + msg_Dbg( p_this, "No interface suitable for interaction" ); + return VLC_FALSE; + } + 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; + } + + if( p_interact->i_type == INTERACT_ASK ) + { + return intf_WaitAnswer( p_chosen_intf, p_interact ); + } + else + { + return intf_Send( p_chosen_intf, p_interact ); + } +} + +int intf_WaitAnswer( intf_thread_t *p_intf, interaction_dialog_t *p_interact ) +{ + // TODO: Add to queue, wait for answer + return VLC_SUCCESS; +} + +int intf_Send( intf_thread_t *p_intf, interaction_dialog_t *p_interact ) +{ + // TODO: Add to queue, return + return VLC_SUCCESS; +} + +// The playlist manages the user interaction to avoid creating another thread +void intf_InteractionManage( playlist_t *p_playlist ) +{ + if( p_playlist->p_interaction == NULL ) + { + intf_InteractionInit( p_playlist ); + } + + vlc_mutex_lock( &p_playlist->p_interaction->object_lock ); + + /* 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_mutex_unlock( &p_playlist->p_interaction->object_lock ); +} + +static void intf_InteractionInit( playlist_t *p_playlist ) +{ + interaction_t *p_interaction; + p_interaction = vlc_object_create( VLC_OBJECT( p_playlist ), sizeof( interaction_t ) ); + if( !p_interaction ) + { + msg_Err( p_playlist,"out of memory" ); + return; + } + + p_interaction->i_dialogs = 0; + p_interaction->pp_dialogs = NULL; +} + +/** Helper function to build a progress bar */ +interaction_dialog_t *__intf_ProgressBuild( vlc_object_t *p_this, + const char *psz_text ) +{ + interaction_dialog_t *p_new = (interaction_dialog_t *)malloc( + sizeof( interaction_dialog_t ) ); + + + 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; + +#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 */ +void intf_UserFatal( vlc_object_t *p_this, const char *psz_title, + const char *psz_format, ... ) +{ + va_list args; + + INTERACT_INIT( p_new ); + p_new->i_type = INTERACT_FATAL; + p_new->psz_title = strdup( psz_title ); + + va_start( args, psz_format ); + vasprintf( &p_new->psz_description, psz_format, args ); + va_end( args ); + + intf_Interact( p_this, p_new ); + + INTERACT_FREE( p_new ); +} diff --git a/src/interface/interface.c b/src/interface/interface.c index e0fd705b73..a01fd64fe8 100644 --- a/src/interface/interface.c +++ b/src/interface/interface.c @@ -98,6 +98,7 @@ intf_thread_t* __intf_Create( vlc_object_t *p_this, const char *psz_module ) p_intf->pf_request_window = NULL; p_intf->pf_release_window = NULL; p_intf->pf_control_window = NULL; + p_intf->pf_interact = NULL; p_intf->b_play = VLC_FALSE; /* Choose the best module */ diff --git a/src/playlist/playlist.c b/src/playlist/playlist.c index c7621c8933..2e3c52cab8 100644 --- a/src/playlist/playlist.c +++ b/src/playlist/playlist.c @@ -32,6 +32,8 @@ #include "vlc_playlist.h" +#include "vlc_interaction.h" + #define TITLE_CATEGORY N_( "By category" ) #define TITLE_SIMPLE N_( "Manually added" ) #define TITLE_ALL N_( "All items, unsorted" ) @@ -194,9 +196,14 @@ playlist_t * __playlist_Create ( vlc_object_t *p_parent ) return NULL; } + // Preparse p_playlist->p_preparse->i_waiting = 0; p_playlist->p_preparse->pp_waiting = NULL; + // Interaction + p_playlist->b_manage_interaction = VLC_FALSE; + p_playlist->p_interaction = NULL; + vlc_object_attach( p_playlist->p_preparse, p_playlist ); if( vlc_thread_create( p_playlist->p_preparse, "preparser", RunPreparse, VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) ) @@ -577,6 +584,11 @@ static void RunThread ( playlist_t *p_playlist ) while( !p_playlist->b_die ) { + if( p_playlist->b_manage_interaction ) + { + intf_InteractionManage( p_playlist ); + } + vlc_mutex_lock( &p_playlist->object_lock ); /* First, check if we have something to do */ -- 2.39.2