]> git.sesse.net Git - vlc/commitdiff
src/*, include/* : update core functions. (Should make it relatively easy
authorAntoine Cellerier <dionoea@videolan.org>
Thu, 2 Feb 2006 17:29:06 +0000 (17:29 +0000)
committerAntoine Cellerier <dionoea@videolan.org>
Thu, 2 Feb 2006 17:29:06 +0000 (17:29 +0000)
                   to use in interfaces)
                   The downloadable plugins part still needs some work.

modules/control/rc.c : add function to query updates (mainly used for testing)

modules/gui/wxwidgets/* : update pannel.

14 files changed:
Makefile.am
include/vlc_common.h
include/vlc_symbols.h
include/vlc_update.h [new file with mode: 0644]
modules/control/rc.c
modules/gui/wxwidgets/bitmaps/update_ascii.xpm [new file with mode: 0644]
modules/gui/wxwidgets/bitmaps/update_binary.xpm [new file with mode: 0644]
modules/gui/wxwidgets/bitmaps/update_document.xpm [new file with mode: 0644]
modules/gui/wxwidgets/bitmaps/update_info.xpm [new file with mode: 0644]
modules/gui/wxwidgets/bitmaps/update_source.xpm [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/updatevlc.cpp
modules/gui/wxwidgets/dialogs/updatevlc.hpp
src/misc/modules.c
src/misc/update.c [new file with mode: 0644]

index 6306d6604085518dfd4250777cb01d41331ed43b..0c36d110564b8732fcfb53e819938997f0c1c245 100644 (file)
@@ -131,6 +131,7 @@ HEADERS_include = \
        include/vlc_symbols.h \
        include/vlc_threads_funcs.h \
        include/vlc_threads.h \
+       include/vlc_update.h \
        include/vlc_video.h \
        include/vlc_vlm.h \
        include/vlc_vod.h \
@@ -466,6 +467,7 @@ SOURCES_libvlc_common = \
        src/misc/objects.c \
        src/misc/variables.c \
        src/misc/error.c \
+       src/misc/update.c \
        src/misc/vlm.c \
        src/misc/xml.c \
        src/misc/version.c \
index 77670e2ddb169fe5448bf91e8b20735e49782eba..3f16671f93a89ebfe85d0cc8f3d217da96588a01 100644 (file)
@@ -416,12 +416,16 @@ typedef struct vlm_schedule_t vlm_schedule_t;
 /* divers */
 typedef struct vlc_meta_t    vlc_meta_t;
 
+/* Stats */
 typedef struct counter_t     counter_t;
 typedef struct counter_sample_t counter_sample_t;
 typedef struct stats_handler_t stats_handler_t;
 typedef struct input_stats_t input_stats_t;
 typedef struct global_stats_t global_stats_t;
 
+/* Update */
+typedef struct update_t update_t;
+typedef struct update_iterator_t update_iterator_t;
 
 /*****************************************************************************
  * Variable callbacks
index 804f536ff321ac69249327cecf5a8180021887f4..190850f47e0918e4b2da656717cc7f83c8d4c641 100644 (file)
@@ -84,6 +84,7 @@ void __intf_UserHide (vlc_object_t *, int);
 int __config_LoadConfigFile (vlc_object_t *, const char *);
 int vlc_asprintf (char **, const char *, ...);
 int __var_Change (vlc_object_t *, const char *, int, vlc_value_t *, vlc_value_t *);
+update_iterator_t * update_iterator_New (update_t *);
 int playlist_Disable (playlist_t *, playlist_item_t *);
 char * vlc_input_item_GetInfo (input_item_t *p_i, const char *psz_cat,const char *psz_name);
 int vout_VarCallback (vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void *);
@@ -91,6 +92,7 @@ session_descriptor_t* sout_AnnounceSessionCreate (void);
 void __osd_Volume (vlc_object_t *);
 int vlc_vasprintf (char **, const char *, va_list);
 int playlist_Sort (playlist_t *, int, int);
+void update_Check (update_t *, vlc_bool_t);
 int aout_DecDelete (aout_instance_t *, aout_input_t *);
 int vlc_strcasecmp (const char *s1, const char *s2);
 sout_packetizer_input_t * sout_InputNew (sout_instance_t *, es_format_t *);
@@ -136,6 +138,7 @@ stream_t * __stream_UrlNew (vlc_object_t *p_this, const char *psz_url);
 sout_mux_t * sout_MuxNew (sout_instance_t*, char *, sout_access_out_t *);
 stream_t * __stream_DemuxNew (vlc_object_t *p_obj, char *psz_demux, es_out_t *out);
 int vout_ShowTextRelative (vout_thread_t *, int, char *, text_style_t *, int, int, int, mtime_t);
+unsigned int update_iterator_Action (update_iterator_t *, int);
 void __stats_TimerDump (vlc_object_t*, const char *);
 int block_FifoPut (block_fifo_t *, block_t *);
 int playlist_ItemAddParent (playlist_item_t *, int,playlist_item_t *);
@@ -161,6 +164,7 @@ int httpd_UrlCatch (httpd_url_t *, int i_msg, httpd_callback_t, httpd_callback_s
 void __vlc_object_yield (vlc_object_t *);
 const char * VLC_CompileBy (void);
 playlist_item_t * playlist_LockItemGetByPos (playlist_t *, int);
+void update_Delete (update_t *);
 input_thread_t * __input_CreateThread (vlc_object_t *, input_item_t *);
 const char * DecodeLanguage (uint16_t);
 int __aout_VolumeSet (vlc_object_t *, audio_volume_t);
@@ -220,6 +224,7 @@ void __stats_ComputeGlobalStats (vlc_object_t*,global_stats_t*);
 char * vlc_strndup (const char *s, size_t n);
 void vout_PlacePicture (vout_thread_t *, unsigned int, unsigned int, unsigned int *, unsigned int *, unsigned int *, unsigned int *);
 float __config_GetFloat (vlc_object_t *, const char *);
+void update_iterator_Delete (update_iterator_t *);
 playlist_item_t * playlist_ItemGetById (playlist_t *, int);
 const char * vlc_gai_strerror (int);
 void net_ListenClose (int *fd);
@@ -345,6 +350,7 @@ int playlist_PreparseEnqueue (playlist_t *, input_item_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 *);
+unsigned int update_iterator_ChooseMirrorAndFile (update_iterator_t *, int, int, int);
 void intf_InteractionManage (playlist_t *);
 char * mstrtime (char *psz_buffer, mtime_t date);
 void aout_FormatPrepare (audio_sample_format_t * p_format);
@@ -356,6 +362,7 @@ xml_t * __xml_Create (vlc_object_t *);
 msg_subscription_t* __msg_Subscribe (vlc_object_t *, int);
 const char * VLC_Version (void);
 session_descriptor_t* sout_AnnounceRegisterSDP (sout_instance_t *,const char *, const char *, announce_method_t*);
+update_t * __update_New (vlc_object_t *);
 char * stream_ReadLine (stream_t *);
 int playlist_PreparseEnqueueItem (playlist_t *, playlist_item_t *);
 void __osd_MenuPrev (vlc_object_t *);
@@ -364,6 +371,7 @@ module_t * config_FindModule (vlc_object_t *, const char *);
 void aout_VolumeSoftInit (aout_instance_t *);
 void block_FifoRelease (block_fifo_t *);
 void block_FifoEmpty (block_fifo_t *);
+void update_download (update_iterator_t *, char *);
 int playlist_ItemAddOption (playlist_item_t *, const char *);
 void aout_VolumeNoneInit (aout_instance_t *);
 void aout_DateInit (audio_date_t *, uint32_t);
@@ -903,6 +911,14 @@ struct module_symbols_t
     void (*__stats_ComputeGlobalStats_inner) (vlc_object_t*,global_stats_t*);
     void (*__stats_TimerStop_inner) (vlc_object_t*, const char *);
     void (*__stats_TimersDumpAll_inner) (vlc_object_t*);
+    update_iterator_t * (*update_iterator_New_inner) (update_t *);
+    void (*update_Check_inner) (update_t *, vlc_bool_t);
+    unsigned int (*update_iterator_Action_inner) (update_iterator_t *, int);
+    void (*update_Delete_inner) (update_t *);
+    void (*update_iterator_Delete_inner) (update_iterator_t *);
+    unsigned int (*update_iterator_ChooseMirrorAndFile_inner) (update_iterator_t *, int, int, int);
+    update_t * (*__update_New_inner) (vlc_object_t *);
+    void (*update_download_inner) (update_iterator_t *, char *);
 };
 #  if defined (__PLUGIN__)
 #  define aout_FiltersCreatePipeline (p_symbols)->aout_FiltersCreatePipeline_inner
@@ -1339,6 +1355,14 @@ struct module_symbols_t
 #  define __stats_ComputeGlobalStats (p_symbols)->__stats_ComputeGlobalStats_inner
 #  define __stats_TimerStop (p_symbols)->__stats_TimerStop_inner
 #  define __stats_TimersDumpAll (p_symbols)->__stats_TimersDumpAll_inner
+#  define update_iterator_New (p_symbols)->update_iterator_New_inner
+#  define update_Check (p_symbols)->update_Check_inner
+#  define update_iterator_Action (p_symbols)->update_iterator_Action_inner
+#  define update_Delete (p_symbols)->update_Delete_inner
+#  define update_iterator_Delete (p_symbols)->update_iterator_Delete_inner
+#  define update_iterator_ChooseMirrorAndFile (p_symbols)->update_iterator_ChooseMirrorAndFile_inner
+#  define __update_New (p_symbols)->__update_New_inner
+#  define update_download (p_symbols)->update_download_inner
 #  elif defined (HAVE_DYNAMIC_PLUGINS) && !defined (__BUILTIN__)
 /******************************************************************
  * STORE_SYMBOLS: store VLC APIs into p_symbols for plugin access.
@@ -1778,6 +1802,14 @@ struct module_symbols_t
     ((p_symbols)->__stats_ComputeGlobalStats_inner) = __stats_ComputeGlobalStats; \
     ((p_symbols)->__stats_TimerStop_inner) = __stats_TimerStop; \
     ((p_symbols)->__stats_TimersDumpAll_inner) = __stats_TimersDumpAll; \
+    ((p_symbols)->update_iterator_New_inner) = update_iterator_New; \
+    ((p_symbols)->update_Check_inner) = update_Check; \
+    ((p_symbols)->update_iterator_Action_inner) = update_iterator_Action; \
+    ((p_symbols)->update_Delete_inner) = update_Delete; \
+    ((p_symbols)->update_iterator_Delete_inner) = update_iterator_Delete; \
+    ((p_symbols)->update_iterator_ChooseMirrorAndFile_inner) = update_iterator_ChooseMirrorAndFile; \
+    ((p_symbols)->__update_New_inner) = __update_New; \
+    ((p_symbols)->update_download_inner) = update_download; \
     (p_symbols)->net_ConvertIPv4_deprecated = NULL; \
     (p_symbols)->__stats_CounterGet_deprecated = NULL; \
     (p_symbols)->__stats_TimerDumpAll_deprecated = NULL; \
diff --git a/include/vlc_update.h b/include/vlc_update.h
new file mode 100644 (file)
index 0000000..d4ecbdc
--- /dev/null
@@ -0,0 +1,171 @@
+/*****************************************************************************
+ * vlc_update.h: VLC update and plugins download
+ *****************************************************************************
+ * Copyright (C) 2005 the VideoLAN team
+ * $Id: $
+ *
+ * Authors: Antoine Cellerier <dionoea -at- videolan -dot- org>
+ *
+ * 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 release 2 of the License, or
+ * (at your option) any later release.
+ *
+ * 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.
+ *****************************************************************************/
+
+#ifndef _VLC_UPDATE_H
+#define _VLC_UPDATE_H
+
+#include <vlc/vlc.h>
+
+#define UPDATE_FILE_TYPE_ALL    (~0)
+#define UPDATE_FILE_TYPE_NONE   0
+
+#define UPDATE_FILE_TYPE_UNDEF      1
+#define UPDATE_FILE_TYPE_INFO       2
+#define UPDATE_FILE_TYPE_SOURCE     4
+#define UPDATE_FILE_TYPE_BINARY     8
+#define UPDATE_FILE_TYPE_PLUGIN     16
+
+#define UPDATE_RELEASE_STATUS_ALL       (~0)
+#define UPDATE_RELEASE_STATUS_NONE      0
+
+#define UPDATE_RELEASE_STATUS_OLDER     1
+#define UPDATE_RELEASE_STATUS_EQUAL     2
+#define UPDATE_RELEASE_STATUS_NEWER     4
+
+#define UPDATE_RELEASE_TYPE_STABLE      1
+#define UPDATE_RELEASE_TYPE_TESTING     2
+#define UPDATE_RELEASE_TYPE_UNSTABLE    4
+
+#define UPDATE_FAIL     0
+#define UPDATE_SUCCESS  1
+#define UPDATE_NEXT     0
+#define UPDATE_PREV     2
+#define UPDATE_MIRROR   4
+#define UPDATE_RELEASE  8
+#define UPDATE_FILE     16
+#define UPDATE_RESET    32
+
+/**
+ * Describes an update file
+ */
+struct update_file_t
+{
+    int i_type;             //< File type
+    char* psz_md5;          //< MD5 hash
+    long int l_size;        //< File size in bytes
+    char* psz_url;          //< Relative (to a mirror) or absolute url
+    char* psz_description;  //< Plain text description
+};
+
+/**
+ * Describes an update VLC release number
+ */
+struct update_release_t
+{
+    char* psz_major;        //< Version major string
+    char* psz_minor;        //< Version minor string
+    char* psz_revision;     //< Version revision string
+    char* psz_extra;        //< Version extra string
+
+    char* psz_svn_revision; //< SVN revision
+
+    int i_type;             //< Release type
+
+    int i_status;           //< Release status compared to current VLC version
+
+    struct update_file_t* p_files; //< Files list
+    int i_files;            //< Number of files in the files list
+};
+
+/**
+ * Describes a mirror
+ */
+struct update_mirror_t
+{
+    char *psz_name;         //< Mirror name
+    char *psz_location;     //< Mirror geographical location
+    char *psz_type;         //< Mirror type (FTP, HTTP, ...)
+
+    char *psz_base_url;     //< Mirror base url
+
+};
+
+/**
+ * The update object. Stores (and caches) all information relative to updates
+ */
+struct update_t
+{
+    vlc_t *p_vlc;
+
+    vlc_mutex_t lock;
+
+    struct update_release_t *p_releases;    //< Releases (version) list
+    int i_releases;                         //< Number of releases
+    vlc_bool_t b_releases;                  //< True if we have a releases list
+
+    struct update_mirror_t *p_mirrors;      //< Mirrors list
+    int i_mirrors;                          //< Number of mirrors
+    vlc_bool_t b_mirrors;                   //< True if we have a mirrors list
+};
+
+/**
+ * The update iterator structure. Usefull to browse the update object seamlessly
+ */
+struct update_iterator_t
+{
+    update_t *p_u;  //< Pointer to VLC update object
+
+    int i_r;        //< Position in the releases list
+    int i_f;        //< Position in the release's files list
+    int i_m;        //< Position in the mirrors list
+
+    int i_t;        //< File type bitmask
+    int i_rs;       //< Release status bitmask
+    int i_rt;       //< Release type bitmask
+
+    struct
+    {
+        int i_type;             //< Type
+        char* psz_md5;          //< MD5 hash
+        long int l_size;        //< Size in bytes
+        char* psz_url;          //< Absolute URL
+        char* psz_description;  //< Description
+    } file;         //< Local 'copy' of the current file's information
+    struct
+    {
+        char *psz_version;      //< Version string
+        char *psz_svn_revision; //< SVN revision
+        int i_status;           //< Status
+        int i_type;             //< Type
+    } release;      //< Local 'copy' of the current release's information
+    struct
+    {
+        char *psz_name;         //< Name
+        char *psz_location;     //< Geographical location
+        char *psz_type;         //< Type (HTTP, FTP, ...)
+    } mirror;       //< Local 'copy' of the current mirror's information
+};
+
+#define update_New( a ) __update_New( VLC_OBJECT( a ) )
+
+VLC_EXPORT( update_t *, __update_New, ( vlc_object_t * ) );
+VLC_EXPORT( void, update_Delete, (update_t * ) );
+VLC_EXPORT( void, update_Check, ( update_t *, vlc_bool_t ) );
+
+VLC_EXPORT( update_iterator_t *, update_iterator_New, ( update_t * ) );
+VLC_EXPORT( void, update_iterator_Delete, ( update_iterator_t * ) );
+VLC_EXPORT( unsigned int, update_iterator_Action, ( update_iterator_t *, int ) );
+VLC_EXPORT( unsigned int, update_iterator_ChooseMirrorAndFile, ( update_iterator_t *, int, int, int ) );
+VLC_EXPORT( void, update_download, ( update_iterator_t *, char * ) );
+
+#endif
index 2d4d4bf0053c6fb862c4edcfda0e03250931188c..5d366c58e79cecfc51eea5c18466c2066e890bd8 100644 (file)
@@ -39,6 +39,7 @@
 #include <vlc/vout.h>
 #include <vlc_video.h>
 #include <vlc_osd.h>
+#include <vlc_update.h>
 
 #ifdef HAVE_UNISTD_H
 #    include <unistd.h>
@@ -95,6 +96,7 @@ static int  AudioConfig  ( vlc_object_t *, char const *,
                            vlc_value_t, vlc_value_t, void * );
 static int  Menu         ( vlc_object_t *, char const *,
                            vlc_value_t, vlc_value_t, void * );
+static void checkUpdates( intf_thread_t *p_intf, char *psz_arg );
 
 /* Status Callbacks */
 static int TimeOffsetChanged( vlc_object_t *, char const *,
@@ -350,7 +352,7 @@ static void Deactivate( vlc_object_t *p_this )
 #endif
         free( p_intf->p_sys->psz_unix_path );
     }
-    vlc_mutex_destroy( &p_intf->p_sys->status_lock );    
+    vlc_mutex_destroy( &p_intf->p_sys->status_lock );
     free( p_intf->p_sys );
 }
 
@@ -459,7 +461,7 @@ static void RegisterCallbacks( intf_thread_t *p_intf )
 
     /* OSD menu commands */
     var_Create( p_intf, "menu", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
-    var_AddCallback( p_intf, "menu", Menu, NULL ); 
+    var_AddCallback( p_intf, "menu", Menu, NULL );
 
     /* DVD commands */
     var_Create( p_intf, "pause", VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
@@ -793,6 +795,10 @@ static void Run( intf_thread_t *p_intf )
 
             Help( p_intf, b_longhelp );
         }
+        else if( !strcmp( psz_cmd, "check-updates" ) )
+        {
+            checkUpdates( p_intf, psz_arg );
+        }
         else switch( psz_cmd[0] )
         {
         case 'f':
@@ -944,6 +950,9 @@ static void Help( intf_thread_t *p_intf, vlc_bool_t b_longhelp)
         msg_rc(_("| mosaic-cols #. . . . . . . . . . .number of cols"));
         msg_rc(_("| mosaic-keep-aspect-ratio {0,1} . . .aspect ratio"));
         msg_rc(  "| ");
+        msg_rc(_("| check-updates [newer] [equal] [older]\n"
+                 "|               [undef] [info] [source] [binary] [plugin]"));
+        msg_rc(  "| ");
     }
     msg_rc(_("| help . . . . . . . . . . . . . this help message"));
     msg_rc(_("| longhelp . . . . . . . . . a longer help message"));
@@ -1245,7 +1254,7 @@ static int Playlist( vlc_object_t *p_this, char const *psz_cmd,
         if( p_playlist->p_input )
         {
             vlc_value_t val;
+
             var_Get( p_playlist->p_input, "rate", &val );
             if( val.i_int != INPUT_RATE_DEFAULT )
             {
@@ -1260,10 +1269,10 @@ static int Playlist( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if (!strcmp( psz_cmd, "goto" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = atoi( newval.psz_string );
-            playlist_Goto( p_playlist, val.i_int); 
+            playlist_Goto( p_playlist, val.i_int);
         }
     }
     else if( !strcmp( psz_cmd, "stop" ) )
@@ -1387,7 +1396,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
             val.psz_string = newval.psz_string;
             var_Set( p_input->p_libvlc, "marq-marquee", val );
         }
-        else 
+        else
         {
                 val.psz_string = "";
                 var_Set( p_input->p_libvlc, "marq-marquee", val);
@@ -1395,7 +1404,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "marq-x" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = atoi( newval.psz_string );
             var_Set( p_input->p_libvlc, "marq-x", val );
@@ -1403,7 +1412,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "marq-y" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = atoi( newval.psz_string );
             var_Set( p_input->p_libvlc, "marq-y", val );
@@ -1411,7 +1420,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "marq-position" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = atoi( newval.psz_string );
             var_Set( p_input->p_libvlc, "marq-position", val );
@@ -1419,7 +1428,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "marq-color" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = strtol( newval.psz_string, NULL, 0 );
             var_Set( p_input->p_libvlc, "marq-color", val );
@@ -1427,7 +1436,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "marq-opacity" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = strtol( newval.psz_string, NULL, 0 );
             var_Set( p_input->p_libvlc, "marq-opacity", val );
@@ -1435,7 +1444,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "marq-size" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = atoi( newval.psz_string );
             var_Set( p_input->p_libvlc, "marq-size", val );
@@ -1443,7 +1452,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "marq-timeout" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = atoi( newval.psz_string );
             var_Set( p_input, "marq-timeout", val );
@@ -1552,7 +1561,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
             val.psz_string = newval.psz_string;
             var_Set( p_input->p_libvlc, "time-format", val );
         }
-        else 
+        else
         {
             val.psz_string = "";
             var_Set( p_input->p_libvlc, "time-format", val);
@@ -1560,7 +1569,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "time-x" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = atoi( newval.psz_string );
             var_Set( p_input->p_libvlc, "time-x", val );
@@ -1568,7 +1577,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "time-y" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = atoi( newval.psz_string );
             var_Set( p_input->p_libvlc, "time-y", val );
@@ -1576,7 +1585,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "time-position" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = atoi( newval.psz_string );
             var_Set( p_input->p_libvlc, "time-position", val );
@@ -1584,7 +1593,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "time-color" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = strtol( newval.psz_string, NULL, 0 );
             var_Set( p_input->p_libvlc, "time-color", val );
@@ -1592,7 +1601,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "time-opacity" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = strtol( newval.psz_string, NULL, 0 );
             var_Set( p_input->p_libvlc, "time-opacity", val );
@@ -1600,7 +1609,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "time-size" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = atoi( newval.psz_string );
             var_Set( p_input->p_libvlc, "time-size", val );
@@ -1616,7 +1625,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "logo-x" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = atoi( newval.psz_string );
             var_Set( p_input->p_libvlc, "logo-x", val );
@@ -1624,7 +1633,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "logo-y" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = atoi( newval.psz_string );
             var_Set( p_input->p_libvlc, "logo-y", val );
@@ -1632,7 +1641,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "logo-position" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = atoi( newval.psz_string );
             var_Set( p_input->p_libvlc, "logo-position", val );
@@ -1640,7 +1649,7 @@ static int Other( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "logo-transparency" ) )
     {
-        if( strlen( newval.psz_string ) > 0) 
+        if( strlen( newval.psz_string ) > 0)
         {
             val.i_int = strtol( newval.psz_string, NULL, 0 );
             var_Set( p_input->p_libvlc, "logo-transparency", val );
@@ -2150,3 +2159,120 @@ static playlist_item_t *parse_MRL( intf_thread_t *p_intf, char *psz_mrl )
 
     return p_item;
 }
+
+/*****************************************************************************
+ * checkUpdates : check for updates
+ ****************************************************************************/
+static void checkUpdates( intf_thread_t *p_intf, char *psz_arg )
+{
+    update_iterator_t *p_uit;
+    update_t *p_u = update_New( p_intf );
+    if( p_u == NULL ) return;
+    p_uit = update_iterator_New( p_u );
+    if( p_uit )
+    {
+        int s = 0, t = 0;
+
+        if( strstr( psz_arg, "newer" ) )
+            s |= UPDATE_RELEASE_STATUS_NEWER;
+        if( strstr( psz_arg, "equal" ) )
+            s |= UPDATE_RELEASE_STATUS_EQUAL;
+        if( strstr( psz_arg, "older" ) )
+            s |= UPDATE_RELEASE_STATUS_OLDER;
+        if( s ) p_uit->i_rs = s;
+        else p_uit->i_rs = UPDATE_RELEASE_STATUS_NEWER;
+
+        if( strstr( psz_arg, "undef" ) )
+            t |= UPDATE_FILE_TYPE_UNDEF;
+        if( strstr( psz_arg, "info" ) )
+            t |= UPDATE_FILE_TYPE_INFO;
+        if( strstr( psz_arg, "source" ) )
+            t |= UPDATE_FILE_TYPE_SOURCE;
+        if( strstr( psz_arg, "binary" ) )
+            t |= UPDATE_FILE_TYPE_BINARY;
+        if( strstr( psz_arg, "plugin" ) )
+            t |= UPDATE_FILE_TYPE_PLUGIN;
+        if( t ) p_uit->i_t = t;
+
+        update_Check( p_u, VLC_FALSE );
+        update_iterator_Action( p_uit, UPDATE_MIRROR );
+        msg_rc( "\nUsing mirror: %s (%s) [%s]",
+                p_uit->mirror.psz_name,
+                p_uit->mirror.psz_location,
+                p_uit->mirror.psz_type );
+        while( (s = update_iterator_Action( p_uit, UPDATE_FILE )) != UPDATE_FAIL )
+        {
+            char *psz_tmp;
+            if( s & UPDATE_RELEASE )
+            {
+                switch( p_uit->release.i_status )
+                {
+                    case UPDATE_RELEASE_STATUS_OLDER:
+                        psz_tmp = strdup( "older" );
+                        break;
+                    case UPDATE_RELEASE_STATUS_EQUAL:
+                        psz_tmp = strdup( "equal" );
+                        break;
+                    case UPDATE_RELEASE_STATUS_NEWER:
+                        psz_tmp = strdup( "newer" );
+                        break;
+                    default:
+                        psz_tmp = strdup( "?!?" );
+                        break;
+                }
+                msg_rc( "\n+----[ VLC %s %s (%s) ] ",
+                        p_uit->release.psz_version,
+                        p_uit->release.psz_svn_revision,
+                        psz_tmp );
+                free( psz_tmp );
+            }
+            switch( p_uit->file.i_type )
+            {
+                case UPDATE_FILE_TYPE_UNDEF:
+                    psz_tmp = strdup( "undef" );
+                    break;
+                case UPDATE_FILE_TYPE_INFO:
+                    psz_tmp = strdup( "info" );
+                    break;
+                case UPDATE_FILE_TYPE_SOURCE:
+                    psz_tmp = strdup( "source" );
+                    break;
+                case UPDATE_FILE_TYPE_BINARY:
+                    psz_tmp = strdup( "binary" );
+                    break;
+                case UPDATE_FILE_TYPE_PLUGIN:
+                    psz_tmp = strdup( "plugin" );
+                    break;
+                default:
+                    psz_tmp = strdup( "?!?" );
+                    break;
+            }
+            msg_rc( "| %s (%s)", p_uit->file.psz_description, psz_tmp );
+            free( psz_tmp );
+            if( p_uit->file.l_size )
+            {
+                if( p_uit->file.l_size > 1024 * 1024 * 1024 )
+                    asprintf( &psz_tmp, "(%ld GB)",
+                              p_uit->file.l_size / (1024*1024*1024) );
+                if( p_uit->file.l_size > 1024 * 1024 )
+                    asprintf( &psz_tmp, "(%ld MB)",
+                              p_uit->file.l_size / (1024*1024) );
+                else if( p_uit->file.l_size > 1024 )
+                    asprintf( &psz_tmp, "(%ld kB)",
+                              p_uit->file.l_size / 1024 );
+                else
+                    asprintf( &psz_tmp, "(%ld B)", p_uit->file.l_size );
+            }
+            else
+            {
+                psz_tmp = strdup( "" );
+            }
+            msg_rc( "| %s %s", p_uit->file.psz_url, psz_tmp );
+            msg_rc( "+----" );
+            free( psz_tmp );
+        }
+        msg_rc( "" );
+        update_iterator_Delete( p_uit );
+    }
+    update_Delete( p_u );
+}
diff --git a/modules/gui/wxwidgets/bitmaps/update_ascii.xpm b/modules/gui/wxwidgets/bitmaps/update_ascii.xpm
new file mode 100644 (file)
index 0000000..5eef123
--- /dev/null
@@ -0,0 +1,133 @@
+/* XPM */
+static char * update_ascii_xpm[] = {
+"34 34 96 2",
+"      c None",
+".     c #BCBCBC",
+"+     c #F7F7F7",
+"@     c #F3F3F3",
+"#     c #F1F1F1",
+"$     c #EFEFEF",
+"%     c #ECECEC",
+"&     c #EAEAEA",
+"*     c #E9E9E9",
+"=     c #C2C2C2",
+"-     c #808080",
+";     c #FFFFFF",
+">     c #FEFEFE",
+",     c #FBFBFB",
+"'     c #F2F2F2",
+")     c #EEEEEE",
+"!     c #E3E3E3",
+"~     c #BDBDBD",
+"{     c #C0C0C0",
+"]     c #BBBBBB",
+"^     c #B6B6B6",
+"/     c #AFAFAF",
+"(     c #A2A2A2",
+"_     c #8E8E8E",
+":     c #828282",
+"<     c #FCFCFC",
+"[     c #F8F8F8",
+"}     c #AEAEAE",
+"|     c #A9A9A9",
+"1     c #9E9E9E",
+"2     c #C4C4C4",
+"3     c #BABABA",
+"4     c #CACACA",
+"5     c #C9C9C9",
+"6     c #B5B5B5",
+"7     c #F9F9F9",
+"8     c #E0E0E0",
+"9     c #CCCCCC",
+"0     c #BEBEBE",
+"a     c #FDFDFD",
+"b     c #FAFAFA",
+"c     c #F5F5F5",
+"d     c #BFBFBF",
+"e     c #A0A0A0",
+"f     c #D5D5D5",
+"g     c #C6C6C6",
+"h     c #F4F4F4",
+"i     c #C1C1C1",
+"j     c #E1E1E1",
+"k     c #DBDBDB",
+"l     c #CECECE",
+"m     c #F6F6F6",
+"n     c #D4D4D4",
+"o     c #E4E4E4",
+"p     c #DEDEDE",
+"q     c #D1D1D1",
+"r     c #EBEBEB",
+"s     c #B8B8B8",
+"t     c #B7B7B7",
+"u     c #DCDCDC",
+"v     c #D3D3D3",
+"w     c #F0F0F0",
+"x     c #E8E8E8",
+"y     c #868686",
+"z     c #DADADA",
+"A     c #D2D2D2",
+"B     c #E7E7E7",
+"C     c #878787",
+"D     c #888888",
+"E     c #E5E5E5",
+"F     c #E2E2E2",
+"G     c #D7D7D7",
+"H     c #DFDFDF",
+"I     c #D0D0D0",
+"J     c #E6E6E6",
+"K     c #DDDDDD",
+"L     c #767676",
+"M     c #777777",
+"N     c #CDCDCD",
+"O     c #EDEDED",
+"P     c #D8D8D8",
+"Q     c #B9B9B9",
+"R     c #D6D6D6",
+"S     c #B3B3B3",
+"T     c #CBCBCB",
+"U     c #CFCFCF",
+"V     c #787878",
+"W     c #ACACAC",
+"X     c #A6A6A6",
+"Y     c #9D9D9D",
+"Z     c #9A9A9A",
+"`     c #969696",
+" .    c #919191",
+"..    c #8C8C8C",
+"+.    c #848484",
+"@.    c #818181",
+"                                                                    ",
+"        . . . . . . . . . . . . . . . .                             ",
+"        . + + + + + + + + @ # $ % & * = -                           ",
+"        . + ; ; ; ; ; ; ; ; > ; , ' ) = ; -                         ",
+"        . + ; ; ; ; ; ; ; ; > ; ; , ' = ; ; -                       ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; , = ! ; ; -                     ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; ; = ! ! ; ; -                   ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; ; = ! ! ! ; ; -                 ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; ; = ! ! ! ! ; ; -               ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; ; ~ { ] ^ / ( _ : -             ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; ; < [ # } | 1 2 / -             ",
+"        . + ; ; ; ; ; ; ; ; ; ; ; ; ; ; , ' ] 3 4 5 6 -             ",
+"        . + ; ; ; ; ; ; ; ; ; ; ; ; < 7 + $ ~ 1 8 9 0 -             ",
+"        . + ; ; ; ; ; ; ; ; ; ; a b + c # $ d e 8 f g -             ",
+"        . + ; ; ; ; ; ; ; ; ; b [ + h # $ ) i ( j k l -             ",
+"        . + ; ; ; ; ; ; ; < 7 + m @ ' $ $ & n o ! p q -             ",
+"        . + ; ; ; ; ; ; , 7 [ c c ' $ $ r * s t n u v -             ",
+"        . + ; ; ; ; ; , b [ m c ' w $ % * x 3 y 8 z A -             ",
+"        . + ; ; ; ; < < [ [ m @ # $ % * x B ] C 8 u q -             ",
+"        . + ; ; ; ; , b + m @ # $ % * x B o . D 8 z A -             ",
+"        . + ; ; ; , b + c h # $ % * * E o F n 8 8 G q -             ",
+"        . + ; ; , 7 [ c @ # ) % & x E o j H ^ 6 u f I -             ",
+"        . + ; , 7 + c ' w ) % & B J ! j H K t L 8 n l -             ",
+"        . + ; 7 m h ' w ) r * x o ! j p K k t M 8 n N -             ",
+"        . + b m h ' w O r * x o F j p K k P Q M 8 q l -             ",
+"        Q + [ h # $ O r * B J F j p u k P R n 8 8 N N -             ",
+"        6 + c # $ O r * B J F 8 p u k G R v Q s H 4 9 -             ",
+"        S + @ $ O r * B o ! 8 p u z G f v q Q M 8 4 T -             ",
+"        / + # O r * B o F 8 K u z G f v I U s V 8 4 5 -             ",
+"        W + ) r * B o ! F 8 u k P n n q q N Q V 8 4 5 -             ",
+"        | + x J ! j H u z P R n n A I U l N n ! 8 5 5 -             ",
+"        | X ( Y Z `  ...D +.@.- - - - - - - - - - - - -             ",
+"                                                                    ",
+"                                                                    "};
diff --git a/modules/gui/wxwidgets/bitmaps/update_binary.xpm b/modules/gui/wxwidgets/bitmaps/update_binary.xpm
new file mode 100644 (file)
index 0000000..3ace9ae
--- /dev/null
@@ -0,0 +1,329 @@
+/* XPM */
+static char * update_binary_xpm[] = {
+"34 34 292 2",
+"      c None",
+".     c #BCBCBC",
+"+     c #F7F7F7",
+"@     c #F3F3F3",
+"#     c #F1F1F1",
+"$     c #EFEFEF",
+"%     c #ECECEC",
+"&     c #EAEAEA",
+"*     c #E9E9E9",
+"=     c #C2C2C2",
+"-     c #808080",
+";     c #FFFFFF",
+">     c #FEFEFE",
+",     c #FBFBFB",
+"'     c #F2F2F2",
+")     c #EEEEEE",
+"!     c #E3E3E3",
+"~     c #647EAA",
+"{     c #5B77A6",
+"]     c #6584AD",
+"^     c #718DB3",
+"/     c #5F7FAA",
+"(     c #6080AB",
+"_     c #5C7AA7",
+":     c #6684AC",
+"<     c #5D7EAA",
+"[     c #6E97BD",
+"}     c #6F98BE",
+"|     c #6082AD",
+"1     c #F6F6F8",
+"2     c #FDFDFD",
+"3     c #BDBDBD",
+"4     c #C0C0C0",
+"5     c #BBBBBB",
+"6     c #B6B6B6",
+"7     c #AFAFAF",
+"8     c #A2A2A2",
+"9     c #8E8E8E",
+"0     c #828282",
+"a     c #FBFCFD",
+"b     c #5A79A7",
+"c     c #6081AB",
+"d     c #6385AE",
+"e     c #688CB1",
+"f     c #7CA1C3",
+"g     c #799FC2",
+"h     c #D8E2ED",
+"i     c #F5F6F7",
+"j     c #F9F9F9",
+"k     c #F8F8F8",
+"l     c #DBDBDB",
+"m     c #D0D0D0",
+"n     c #C4C4C4",
+"o     c #5975A4",
+"p     c #607BA8",
+"q     c #5C78A7",
+"r     c #6587AE",
+"s     c #7298BF",
+"t     c #7CA2C5",
+"u     c #84A7C7",
+"v     c #8AABC9",
+"w     c #D7E2EC",
+"x     c #5D7BA8",
+"y     c #E8E8E8",
+"z     c #E2E2E2",
+"A     c #D8D8D8",
+"B     c #C9C9C9",
+"C     c #B5B5B5",
+"D     c #5D7DA8",
+"E     c #C3D4E4",
+"F     c #E3EBF2",
+"G     c #DCE6EF",
+"H     c #B7CBDE",
+"I     c #80A4C5",
+"J     c #96B4CF",
+"K     c #9CB8D3",
+"L     c #ABC2D8",
+"M     c #E1E2E5",
+"N     c #EEEFF0",
+"O     c #EBEBEB",
+"P     c #E4E4E4",
+"Q     c #DADADA",
+"R     c #CCCCCC",
+"S     c #BEBEBE",
+"T     c #A9C1D8",
+"U     c #E6EDF3",
+"V     c #B0C5DB",
+"W     c #91B1CE",
+"X     c #A0BAD3",
+"Y     c #98B6D1",
+"Z     c #9EB9D3",
+"`     c #A6BFD7",
+" .    c #ADC4DA",
+"..    c #C1D2E2",
+"+.    c #DDE7F0",
+"@.    c #7F9AB8",
+"#.    c #E0E1E3",
+"$.    c #EBEBEC",
+"%.    c #D5D5D5",
+"&.    c #C6C6C6",
+"*.    c #B9CDE0",
+"=.    c #D4E0EB",
+"-.    c #97B5D0",
+";.    c #749CC1",
+">.    c #6386AE",
+",.    c #5771A2",
+"'.    c #A7C0D8",
+").    c #B1C6DC",
+"!.    c #BBCEE0",
+"~.    c #CBDAE8",
+"{.    c #D1DEEA",
+"].    c #718DB1",
+"^.    c #E5E5E6",
+"/.    c #E7E7E7",
+"(.    c #DEDEDE",
+"_.    c #CECECE",
+":.    c #E0E8F1",
+"<.    c #5976A6",
+"[.    c #6279A5",
+"}.    c #B7BBC4",
+"|.    c #B9BDC5",
+"1.    c #B2C8DD",
+"2.    c #C9D8E6",
+"3.    c #DFE8F0",
+"4.    c #6082AB",
+"5.    c #D5D6D9",
+"6.    c #E1E1E2",
+"7.    c #E0E0E0",
+"8.    c #D1D1D1",
+"9.    c #D9E4EE",
+"0.    c #A4BED7",
+"a.    c #BABEC7",
+"b.    c #BFC3CB",
+"c.    c #C2C5CC",
+"d.    c #6182AE",
+"e.    c #D0DEE9",
+"f.    c #C6D5E5",
+"g.    c #8DAECC",
+"h.    c #5A76A5",
+"i.    c #D5D6D8",
+"j.    c #E5E5E5",
+"k.    c #DCDCDC",
+"l.    c #D3D3D3",
+"m.    c #668AAF",
+"n.    c #86A9C9",
+"o.    c #B5BAC3",
+"p.    c #BEC2CA",
+"q.    c #C9CCD2",
+"r.    c #D1D3D8",
+"s.    c #D9DBDF",
+"t.    c #94B3CF",
+"u.    c #5A78A5",
+"v.    c #C9CACE",
+"w.    c #D2D2D2",
+"x.    c #C4D5E5",
+"y.    c #B8BCC5",
+"z.    c #CED1D7",
+"A.    c #DEDFE3",
+"B.    c #EAEBED",
+"C.    c #7AA0C3",
+"D.    c #6589AE",
+"E.    c #BEC0C6",
+"F.    c #DFDFDF",
+"G.    c #5F80AA",
+"H.    c #6D94BC",
+"I.    c #698EB4",
+"J.    c #CEDCE9",
+"K.    c #678BB0",
+"L.    c #BDC1C9",
+"M.    c #E4E6E9",
+"N.    c #EFF0F1",
+"O.    c #DBE5EE",
+"P.    c #E6ECF3",
+"Q.    c #5972A1",
+"R.    c #A8ACB4",
+"S.    c #B8BBC1",
+"T.    c #81A5C6",
+"U.    c #A3BCD4",
+"V.    c #637AA6",
+"W.    c #C6C9D0",
+"X.    c #DEE0E4",
+"Y.    c #EEEFF1",
+"Z.    c #F5F7FA",
+"`.    c #6177A3",
+" +    c #A5A9B2",
+".+    c #ABAFB7",
+"++    c #BBBEC3",
+"@+    c #DDDDDD",
+"#+    c #D7D7D7",
+"$+    c #9AB6D1",
+"%+    c #6382AB",
+"&+    c #CBCED4",
+"*+    c #D6E1EB",
+"=+    c #EBF1F6",
+"-+    c #CCDAE9",
+";+    c #ABAEB6",
+">+    c #B7BABF",
+",+    c #C7C9CC",
+"'+    c #A3BDD6",
+")+    c #AEC5DB",
+"!+    c #EFF2F6",
+"~+    c #F6F9FB",
+"{+    c #A4A8B1",
+"]+    c #B8BBC0",
+"^+    c #D2D3D4",
+"/+    c #D4D4D4",
+"(+    c #5E7EA9",
+"_+    c #B4C9DD",
+":+    c #BECFE1",
+"<+    c #EAF0F5",
+"[+    c #F9FBFC",
+"}+    c #FCFDFD",
+"|+    c #657EA7",
+"1+    c #B3B6BC",
+"2+    c #C6C7CB",
+"3+    c #D6D6D6",
+"4+    c #CDCDCD",
+"5+    c #C2D3E3",
+"6+    c #D1DFEA",
+"7+    c #E4ECF3",
+"8+    c #ACC3D9",
+"9+    c #E9EEF4",
+"0+    c #85A8C8",
+"a+    c #BBBDC2",
+"b+    c #CDCED0",
+"c+    c #D4D5D5",
+"d+    c #9BB7D2",
+"e+    c #B6B9BE",
+"f+    c #CACBCD",
+"g+    c #D3D3D4",
+"h+    c #F2F6F9",
+"i+    c #6079A4",
+"j+    c #A3A7AF",
+"k+    c #B0B3B8",
+"l+    c #C6C7C9",
+"m+    c #CFD0D0",
+"n+    c #CACACA",
+"o+    c #B4B8C0",
+"p+    c #93B2CE",
+"q+    c #A3A7B0",
+"r+    c #A1A5AE",
+"s+    c #A1A5AD",
+"t+    c #A5A8B0",
+"u+    c #B3B5BA",
+"v+    c #C5C6C8",
+"w+    c #CECECF",
+"x+    c #CBCBCB",
+"y+    c #909398",
+"z+    c #BFC2C9",
+"A+    c #B8BBC3",
+"B+    c #82A6C7",
+"C+    c #5771A1",
+"D+    c #ADB1B7",
+"E+    c #B0B3B9",
+"F+    c #AFB2B8",
+"G+    c #AEB0B6",
+"H+    c #BFC1C4",
+"I+    c #C9CACB",
+"J+    c #9D9EA1",
+"K+    c #D6D8DC",
+"L+    c #C9CCD1",
+"M+    c #BDBFC6",
+"N+    c #A5A9B1",
+"O+    c #B7BAC0",
+"P+    c #C2C3C7",
+"Q+    c #C7C9CB",
+"R+    c #C6C7CA",
+"S+    c #C3C4C7",
+"T+    c #CACACB",
+"U+    c #CFCFCF",
+"V+    c #A4A5A5",
+"W+    c #EBEBED",
+"X+    c #DADBDD",
+"Y+    c #CDCFD2",
+"Z+    c #BABCC2",
+"`+    c #A7ABB2",
+" @    c #B3B6BB",
+".@    c #C2C4C7",
+"+@    c #CDCDCF",
+"@@    c #D0D1D1",
+"#@    c #CECFCF",
+"$@    c #CDCDCE",
+"%@    c #A8A8A8",
+"&@    c #A4A4A5",
+"*@    c #9F9FA0",
+"=@    c #969798",
+"-@    c #8B8D90",
+";@    c #7E8086",
+">@    c #777A7F",
+",@    c #76797E",
+"'@    c #7B7C80",
+")@    c #7F7F81",
+"                                                                    ",
+"        . . . . . . . . . . . . . . . .                             ",
+"        . + + + + + + + + @ # $ % & * = -                           ",
+"        . + ; ; ; ; ; ; ; ; > ; , ' ) = ; -                         ",
+"        . + ; ; ; ; ; ; ; ; > ; ; , ' = ; ; -                       ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; , = ! ; ; -                     ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; ; = ! ! ; ; -                   ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; ; = ! ! ! ; ; -                 ",
+"        . + ; ; ; ~ { ; ; ; ] ^ ; ; ; = ! ! ! ! ; ; -               ",
+"        . + ; ; { / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 -             ",
+"        . + a b ( c | d e } f g h | i j k # * l m n 7 -             ",
+"        o p q < / ( c r s t u v w u x i j ' y z A B C -             ",
+"      o D / x r E F G H I u J K L v { M N ) O P Q R S -             ",
+"      { / _ T U V W I I X Y Z `  ...+.@.#.$.O ! l %.&.-             ",
+"      _ D *.=.-.;.>.( { ,.*.'.).!.E ~.{.].^.& /.(.l _.-             ",
+"    _ ( } :.J [ c <.[.}.|.| 1.!.E 2.3.w 4.5.6./.7.(.8.-             ",
+"  _ c ( 9.0.s c o }.a.b.c.d.!.E e.+.G f.g.h.i.j.z k.l.-             ",
+"_ c | m.G n.d.o o.p.q.r.s.>.f.{.+.2.'.t.u u.v.z 7.Q w.-             ",
+"_ d.d g.x.} _ y.b.z.A.B.r f.{.+.f.Z C.D.c o E.F.F.k.8.-             ",
+"G.d.H.I.J.K.o L.z.M.N.r f.=.O.P.'.g | x Q.R.S.k.k.Q w.-             ",
+"  / ;.T.U.I.V.W.X.Y.r 2.w 9.F Z.K D.D `. +.+++@+#+#+8.-             ",
+"  ( u W $+` %+&+>.D.J.*+O.F =+; -+c ,. +;+>+,+l %.%.m -             ",
+"  ( W $+'+)+..>.E J.w :.U !+~+; h ( {+;+]+,+^+A #+/+_.-             ",
+"(+t.Y '+V _+:+x.{.9.U <+[+}+; x.T -.|+1+2+^+3+3+/+/+4+-             ",
+"  c x.J...5+2.6+O.7+f.8+` 9+e.'.0+m._ a+b+c+3+l.w.8._.-             ",
+"    d.J g.*+6+9.<+E d+C.K.r t.t.D./ ,.e+f+g+l.w.m 4+4+-             ",
+"      < _ W F h+:.0.f | D ,.i+b _ ,.j+k+l+m+8.m R n+R -             ",
+"        ,.o+[ e.5+p+r D `.q+q+j+r+s+t+u+v+w+m x+x+n+x+-             ",
+"        y+z+A+( v B+( C+{+R.D+E+F+G+u+H+I+_.x+x+x+n+B -             ",
+"        J+K+L+M+o u.o N+.+O+P+Q+R+S+l+T+U+4+R n+n+n+B -             ",
+"        V+W+X+Y+Z+;+N+`+ @.@+@m @@#@$@_._.4+R x+B B B -             ",
+"        %@&@*@=@-@;@>@,@'@)@- - - - - - - - - - - - - -             ",
+"                                                                    ",
+"                                                                    "};
diff --git a/modules/gui/wxwidgets/bitmaps/update_document.xpm b/modules/gui/wxwidgets/bitmaps/update_document.xpm
new file mode 100644 (file)
index 0000000..5c19396
--- /dev/null
@@ -0,0 +1,139 @@
+/* XPM */
+static char * update_document_xpm[] = {
+"34 34 102 2",
+"      c None",
+".     c #BCBCBC",
+"+     c #F7F7F7",
+"@     c #F3F3F3",
+"#     c #F1F1F1",
+"$     c #EFEFEF",
+"%     c #ECECEC",
+"&     c #EAEAEA",
+"*     c #E9E9E9",
+"=     c #C2C2C2",
+"-     c #808080",
+";     c #FFFFFF",
+">     c #FEFEFE",
+",     c #FBFBFB",
+"'     c #F2F2F2",
+")     c #EEEEEE",
+"!     c #B2B2B2",
+"~     c #E3E3E3",
+"{     c #B1B1B1",
+"]     c #BDBDBD",
+"^     c #C0C0C0",
+"/     c #B6B6B6",
+"(     c #AFAFAF",
+"_     c #A2A2A2",
+":     c #8E8E8E",
+"<     c #828282",
+"[     c #EDEDED",
+"}     c #E2E2E2",
+"|     c #DBDBDB",
+"1     c #D0D0D0",
+"2     c #C4C4C4",
+"3     c #FAFAFA",
+"4     c #F4F4F4",
+"5     c #D8D8D8",
+"6     c #C9C9C9",
+"7     c #B5B5B5",
+"8     c #E6E6E6",
+"9     c #DCDCDC",
+"0     c #DADADA",
+"a     c #CCCCCC",
+"b     c #BEBEBE",
+"c     c #ADADAD",
+"d     c #A8A8A8",
+"e     c #EBEBEB",
+"f     c #DFDFDF",
+"g     c #D7D7D7",
+"h     c #D5D5D5",
+"i     c #C6C6C6",
+"j     c #F9F9F9",
+"k     c #F6F6F6",
+"l     c #E7E7E7",
+"m     c #CECECE",
+"n     c #AEAEAE",
+"o     c #ABABAB",
+"p     c #AAAAAA",
+"q     c #A4A4A4",
+"r     c #9F9F9F",
+"s     c #D1D1D1",
+"t     c #F8F8F8",
+"u     c #E0E0E0",
+"v     c #DEDEDE",
+"w     c #D3D3D3",
+"x     c #A6A6A6",
+"y     c #A5A5A5",
+"z     c #D2D2D2",
+"A     c #F5F5F5",
+"B     c #A1A1A1",
+"C     c #CBCBCB",
+"D     c #C8C8C8",
+"E     c #9D9D9D",
+"F     c #ACACAC",
+"G     c #E5E5E5",
+"H     c #E4E4E4",
+"I     c #9C9C9C",
+"J     c #DDDDDD",
+"K     c #A3A3A3",
+"L     c #E1E1E1",
+"M     c #9A9A9A",
+"N     c #A7A7A7",
+"O     c #A0A0A0",
+"P     c #9E9E9E",
+"Q     c #9B9B9B",
+"R     c #989898",
+"S     c #D4D4D4",
+"T     c #CDCDCD",
+"U     c #F0F0F0",
+"V     c #E8E8E8",
+"W     c #D6D6D6",
+"X     c #B9B9B9",
+"Y     c #969696",
+"Z     c #959595",
+"`     c #939393",
+" .    c #B3B3B3",
+"..    c #999999",
+"+.    c #919191",
+"@.    c #CACACA",
+"#.    c #CFCFCF",
+"$.    c #A9A9A9",
+"%.    c #8C8C8C",
+"&.    c #888888",
+"*.    c #848484",
+"=.    c #818181",
+"        . . . . . . . . . . . . . . . .                             ",
+"        . + + + + + + + + @ # $ % & * = -                           ",
+"        . + ; ; ; ; ; ; ; ; > ; , ' ) = ; -                         ",
+"        . + ; ; ; ; ; ; ; ; > ; ; , ' = ; ; -                       ",
+"        . + ; ! ! ! ; ; ; ; > ; ; ; , = ~ ; ; -                     ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; ; = ~ ~ ; ; -                   ",
+"        . + ; ! ! ! ! ! ! ! { ! ! ; ; = ~ ~ ~ ; ; -                 ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; ; = ~ ~ ~ ~ ; ; -               ",
+"        . + ; ! ! ! ! ! ! ! { ! ! ; ; ] ^ . / ( _ : < -             ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; ; , [ } * | 1 2 ( -             ",
+"        . + ; ! ! ! ! ! ! ! ! ! ! ; ; ; 3 4 ~ ~ 5 6 7 -             ",
+"        . + ; ; ; ; ; ; ; ; ; ; ; ; ; 3 3 ' 8 9 0 a b -             ",
+"        . + ; ! ! ! ! ! ! ! ! ! ! ! ( c d d e f g h i -             ",
+"        . + ; ; ; ; ; ; ; ; ; ; ; , j k $ $ [ l | 0 m -             ",
+"        . + ; ! ! ! ! ! ! ! ! ! n c o p d q q r } 5 s -             ",
+"        . + ; ; ; ; ; ; ; ; ; 3 t k 4 # $ * * l u v w -             ",
+"        . + ; ! ! ! ! ! ! ! n c o p d x y q r r } 9 z -             ",
+"        . + ; ; ; ; ; ; > 3 t A @ ' $ [ e * } } u 0 s -             ",
+"        . + ; ! ! ! ! { c c o @ d x y q _ B r f f 9 z -             ",
+"        . + ; ; ; ; , 3 + k @ # x C C 6 D i E 9 9 0 s -             ",
+"        . + ; ! ! ( n F o p d $ q e * G H } I J g g 1 -             ",
+"        . + ; ; , j t A @ # ) % K * G H L f M | h h m -             ",
+"        . + ; ( c F o d N x q & B O P E Q M R 5 g S T -             ",
+"        . + ; j k 4 ' U ) e * V H ~ L v J | 5 W S S m -             ",
+"        X + 3 o p d N y q _ B r E E M M R Y Z ` z s T -             ",
+"        7 + t 4 # $ [ e * l 8 } L v 9 | 5 W w z 1 T a -             ",
+"         .+ A d x y q _ B O E I M ..R Y Z ` +.+.a @.C -             ",
+"        ( + @ $ [ e * l H ~ u v 9 0 g h w s 1 C C @.6 -             ",
+"        F + # y e _ B H } u J 9 0 g h w 1 #.C C C @.6 -             ",
+"        F + ) e * l H ~ } u 9 | 5 S S s s T a @.@.@.6 -             ",
+"        $.+ V 8 ~ L f 9 0 5 W S S z 1 #.m T a C 6 6 6 -             ",
+"        $.x _ E M Y +.%.&.*.=.- - - - - - - - - - - - -             ",
+"                                                                    ",
+"                                                                    "};
diff --git a/modules/gui/wxwidgets/bitmaps/update_info.xpm b/modules/gui/wxwidgets/bitmaps/update_info.xpm
new file mode 100644 (file)
index 0000000..3f99ce8
--- /dev/null
@@ -0,0 +1,308 @@
+/* XPM */
+static char * update_info_xpm[] = {
+"34 34 271 2",
+"      c None",
+".     c #BCBCBC",
+"+     c #F7F7F7",
+"@     c #F3F3F3",
+"#     c #F1F1F1",
+"$     c #EFEFEF",
+"%     c #ECECEC",
+"&     c #EAEAEA",
+"*     c #E9E9E9",
+"=     c #C2C2C2",
+"-     c #808080",
+";     c #FFFFFF",
+">     c #FEFEFE",
+",     c #FBFBFB",
+"'     c #F2F2F2",
+")     c #EEEEEE",
+"!     c #E3E3E3",
+"~     c #BDBDBD",
+"{     c #C0C0C0",
+"]     c #BBBBBB",
+"^     c #B6B6B6",
+"/     c #AFAFAF",
+"(     c #A2A2A2",
+"_     c #8E8E8E",
+":     c #828282",
+"<     c #FCFCFC",
+"[     c #F8F8F8",
+"}     c #DBDBDB",
+"|     c #D0D0D0",
+"1     c #C4C4C4",
+"2     c #F0F1F4",
+"3     c #D5DAE9",
+"4     c #B2BFD9",
+"5     c #9DACCF",
+"6     c #E8E8E8",
+"7     c #E2E2E2",
+"8     c #D8D8D8",
+"9     c #C9C9C9",
+"0     c #B5B5B5",
+"a     c #F7F8FA",
+"b     c #C8D0E2",
+"c     c #8FA9DA",
+"d     c #789ED7",
+"e     c #87AFDF",
+"f     c #98BCE4",
+"g     c #8CA7D8",
+"h     c #C2CBDC",
+"i     c #E7E8EA",
+"j     c #EBEBEB",
+"k     c #E4E4E4",
+"l     c #DADADA",
+"m     c #CCCCCC",
+"n     c #BEBEBE",
+"o     c #ADBFE1",
+"p     c #85A9DB",
+"q     c #97BBE4",
+"r     c #AFC6E8",
+"s     c #B0C7E9",
+"t     c #AEC5E7",
+"u     c #A8C2E5",
+"v     c #92B0E1",
+"w     c #7F9DD7",
+"x     c #A5B4D4",
+"y     c #DDDFE1",
+"z     c #D5D5D5",
+"A     c #C6C6C6",
+"B     c #F7F8FB",
+"C     c #AFC0E3",
+"D     c #87ABDC",
+"E     c #A2BCE3",
+"F     c #A5BEE4",
+"G     c #9EBDE3",
+"H     c #9AB8E1",
+"I     c #99B9E0",
+"J     c #92B3E1",
+"K     c #91B1E0",
+"L     c #78A2D6",
+"M     c #A2B6D6",
+"N     c #E0E1E3",
+"O     c #DEDEDE",
+"P     c #CECECE",
+"Q     c #CAD6EA",
+"R     c #89ADDB",
+"S     c #87AADE",
+"T     c #79A2DA",
+"U     c #6C9CD7",
+"V     c #678FD2",
+"W     c #5F8CD0",
+"X     c #5886D3",
+"Y     c #618CD2",
+"Z     c #6890D3",
+"`     c #76A1D7",
+" .    c #7196D2",
+"..    c #B7C0D4",
+"+.    c #D1D1D1",
+"@.    c #F1F3F7",
+"#.    c #93B0DE",
+"$.    c #6C93D6",
+"%.    c #638ED4",
+"&.    c #5381CE",
+"*.    c #4472C5",
+"=.    c #3868C1",
+"-.    c #3262BB",
+";.    c #FDFDFD",
+">.    c #2047A9",
+",.    c #325CB3",
+"'.    c #3666BD",
+").    c #386DC5",
+"!.    c #4678CB",
+"~.    c #4A7ACC",
+"{.    c #7998C9",
+"].    c #D5D7DA",
+"^.    c #DCDCDC",
+"/.    c #D3D3D3",
+"(.    c #D4DCEC",
+"_.    c #6187CC",
+":.    c #4674C9",
+"<.    c #3867BD",
+"[.    c #2F56AE",
+"}.    c #2951A2",
+"|.    c #274996",
+"1.    c #264895",
+"2.    c #183289",
+"3.    c #254492",
+"4.    c #254897",
+"5.    c #2A509D",
+"6.    c #2D55A6",
+"7.    c #4B6CB6",
+"8.    c #B9BFCF",
+"9.    c #D2D2D2",
+"0.    c #A9B7D5",
+"a.    c #3A62B5",
+"b.    c #2A57AB",
+"c.    c #264F9B",
+"d.    c #26448F",
+"e.    c #223D83",
+"f.    c #203A7D",
+"g.    c #1E3879",
+"h.    c #1F3974",
+"i.    c #122871",
+"j.    c #1F3A7E",
+"k.    c #214388",
+"l.    c #2E4E98",
+"m.    c #949EB9",
+"n.    c #95A4C8",
+"o.    c #203E83",
+"p.    c #11276E",
+"q.    c #1B346E",
+"r.    c #1A336D",
+"s.    c #1C376F",
+"t.    c #1F3D7F",
+"u.    c #808CAC",
+"v.    c #8E9AB4",
+"w.    c #2F55AC",
+"x.    c #2D53A2",
+"y.    c #183593",
+"z.    c #1C3473",
+"A.    c #79839D",
+"B.    c #D7D7D7",
+"C.    c #9CA7C0",
+"D.    c #274286",
+"E.    c #3261B7",
+"F.    c #3464BB",
+"G.    c #244376",
+"H.    c #838EA3",
+"I.    c #C4CAD8",
+"J.    c #38538D",
+"K.    c #4C7FCB",
+"L.    c #4A78CB",
+"M.    c #406FC5",
+"N.    c #2654BB",
+"O.    c #284AB7",
+"P.    c #34497F",
+"Q.    c #A9AFBB",
+"R.    c #D4D4D4",
+"S.    c #E5E7ED",
+"T.    c #697C9F",
+"U.    c #8CAEE1",
+"V.    c #7CA5DD",
+"W.    c #739BD8",
+"X.    c #3C61C1",
+"Y.    c #4275C9",
+"Z.    c #596990",
+"`.    c #C3C5CA",
+" +    c #CDCDCD",
+".+    c #FAFAFA",
+"++    c #B4BDCE",
+"@+    c #4C6DB8",
+"#+    c #D3DCF0",
+"$+    c #CDDAEE",
+"%+    c #C4D6EF",
+"&+    c #BBD3EC",
+"*+    c #8FA3D6",
+"=+    c #859DD4",
+"-+    c #7C97CF",
+";+    c #6F8BD0",
+">+    c #7DA8DE",
+",+    c #3D5591",
+"'+    c #9CA4B5",
+")+    c #B9B9B9",
+"!+    c #F4F4F4",
+"~+    c #E7E9ED",
+"{+    c #919EB6",
+"]+    c #4772BF",
+"^+    c #CDDAEF",
+"/+    c #EDF3F8",
+"(+    c #EAF2F9",
+"_+    c #E7EEF8",
+":+    c #E5EBF6",
+"<+    c #E0E9F5",
+"[+    c #DBE6F4",
+"}+    c #D6E1F1",
+"|+    c #92B3E0",
+"1+    c #39589E",
+"2+    c #818DA6",
+"3+    c #CACBCF",
+"4+    c #F5F5F5",
+"5+    c #DADDE5",
+"6+    c #8F9CB7",
+"7+    c #618BCF",
+"8+    c #B4C8E8",
+"9+    c #F7F8FC",
+"0+    c #F1F4FA",
+"a+    c #F1F2FA",
+"b+    c #F2F6FB",
+"c+    c #DFE8F4",
+"d+    c #9EBDE2",
+"e+    c #4D75BF",
+"f+    c #8290A9",
+"g+    c #C1C4CB",
+"h+    c #CACACA",
+"i+    c #B3B3B3",
+"j+    c #EDEDED",
+"k+    c #E0E2E6",
+"l+    c #ACB4C8",
+"m+    c #6A85BA",
+"n+    c #658ED2",
+"o+    c #7BA5D9",
+"p+    c #A5C0E6",
+"q+    c #729FD7",
+"r+    c #628BCF",
+"s+    c #647CB2",
+"t+    c #9EA6BA",
+"u+    c #C9CBCF",
+"v+    c #CBCBCB",
+"w+    c #E7E7E7",
+"x+    c #D0D3D9",
+"y+    c #B3BCCE",
+"z+    c #8E9EC1",
+"A+    c #7F8BAD",
+"B+    c #7E8AAC",
+"C+    c #8A9BBD",
+"D+    c #ABB3C6",
+"E+    c #C2C6CC",
+"F+    c #CFCFCF",
+"G+    c #ACACAC",
+"H+    c #E0E0E0",
+"I+    c #A9A9A9",
+"J+    c #E6E6E6",
+"K+    c #E1E1E1",
+"L+    c #DFDFDF",
+"M+    c #D6D6D6",
+"N+    c #A6A6A6",
+"O+    c #9D9D9D",
+"P+    c #9A9A9A",
+"Q+    c #969696",
+"R+    c #919191",
+"S+    c #8C8C8C",
+"T+    c #888888",
+"U+    c #848484",
+"V+    c #818181",
+"                                                                    ",
+"        . . . . . . . . . . . . . . . .                             ",
+"        . + + + + + + + + @ # $ % & * = -                           ",
+"        . + ; ; ; ; ; ; ; ; > ; , ' ) = ; -                         ",
+"        . + ; ; ; ; ; ; ; ; > ; ; , ' = ; ; -                       ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; , = ! ; ; -                     ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; ; = ! ! ; ; -                   ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; ; = ! ! ! ; ; -                 ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; ; = ! ! ! ! ; ; -               ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; ; ~ { ] ^ / ( _ : -             ",
+"        . + ; ; ; ; ; ; ; ; > ; ; ; ; < [ # * } | 1 / -             ",
+"        . + ; ; ; ; ; < 2 3 4 5 5 4 3 2 [ ' 6 7 8 9 0 -             ",
+"        . + ; ; ; ; a b c d e f f e d g h i j k l m n -             ",
+"        . + ; ; ; 2 o p q r s s r t u v w x y ! } z A -             ",
+"        . + ; ; B C D E F G H I J K J I J L M N O } P -             ",
+"        . + ; < Q R K S T U V W X X Y Z U `  ...O O +.-             ",
+"        . + ; @.#.$.%.&.*.=.-.;.;.>.,.'.).!.~.{.].^./.-             ",
+"        . + ; (._.:.<.[.}.|.1.;.;.2.3.4.5.6.,.7.8.l 9.-             ",
+"        . + ; 0.a.b.c.d.e.f.g.h.i.i.h.g.j.k.3.l.m.^.+.-             ",
+"        . + ; n.c.c.d.k.o.f.;.;.;.p.q.r.s.h.f.t.u.l 9.-             ",
+"        . + ; v.k.w.b.x.}.}.5.;.< y.4.4.1.3.d.z.A.B.+.-             ",
+"        . + ; C.D.E.F.F.-.E.,.< < >.[.b.6.6.}.G.H.z | -             ",
+"        . + ; I.J.=.K.L.:.*.M.< < N.O.=.<.'.6.P.Q.R.P -             ",
+"        . + ; S.T.*.K U.V.W.< < < < X.K.L.Y.}.Z.`.R. +-             ",
+"        . + .+@ ++@+u #+$+%+&+*+=+-+;+>+W.*.,+'+| +.P -             ",
+"        )++ [ !+~+{+]+^+/+(+_+:+<+[+}+$+|+1+2+3+|  + +-             ",
+"        0 + 4+# $ 5+6+7+8+_+9+0+a+b+c+d+e+f+g+| m h+m -             ",
+"        i++ @ $ j+j k+l+m+n+o+p+p+q+r+s+t+u+| v+v+h+v+-             ",
+"        / + # j+j * w+7 x+y+z+A+B+C+D+E+P F+v+v+v+h+9 -             ",
+"        G++ ) j * w+k ! 7 H+^.} 8 R.R.+.+. +m h+h+h+9 -             ",
+"        I++ 6 J+! K+L+^.l 8 M+R.R.9.| F+P  +m v+9 9 9 -             ",
+"        I+N+( O+P+Q+R+S+T+U+V+- - - - - - - - - - - - -             ",
+"                                                                    ",
+"                                                                    "};
diff --git a/modules/gui/wxwidgets/bitmaps/update_source.xpm b/modules/gui/wxwidgets/bitmaps/update_source.xpm
new file mode 100644 (file)
index 0000000..7b7552b
--- /dev/null
@@ -0,0 +1,180 @@
+/* XPM */
+static char * update_source_xpm[] = {
+"34 34 143 2",
+"      c None",
+".     c #BCBCBC",
+"+     c #F7F7F7",
+"@     c #F3F3F3",
+"#     c #F1F1F1",
+"$     c #EFEFEF",
+"%     c #ECECEC",
+"&     c #EAEAEA",
+"*     c #E9E9E9",
+"=     c #C2C2C2",
+"-     c #808080",
+";     c #FFFFFF",
+">     c #003377",
+",     c #CEDBEB",
+"'     c #FBFBFB",
+")     c #F2F2F2",
+"!     c #EEEEEE",
+"~     c #BFD0E5",
+"{     c #E3E3E3",
+"]     c #FEFEFE",
+"^     c #004F33",
+"/     c #BDCEE4",
+"(     c #C2E1CF",
+"_     c #CCE6D7",
+":     c #B6DBC5",
+"<     c #BDBDBD",
+"[     c #C0C0C0",
+"}     c #B6B6B6",
+"|     c #AFAFAF",
+"1     c #A2A2A2",
+"2     c #8E8E8E",
+"3     c #828282",
+"4     c #008437",
+"5     c #EDEDED",
+"6     c #E2E2E2",
+"7     c #DBDBDB",
+"8     c #D0D0D0",
+"9     c #C4C4C4",
+"0     c #BCDDCA",
+"a     c #B9DBC7",
+"b     c #CEE4D7",
+"c     c #FAFAFA",
+"d     c #F4F4F4",
+"e     c #D8D8D8",
+"f     c #C9C9C9",
+"g     c #B5B5B5",
+"h     c #C5E0D0",
+"i     c #B7D8C5",
+"j     c #E6E6E6",
+"k     c #DCDCDC",
+"l     c #DADADA",
+"m     c #CCCCCC",
+"n     c #BEBEBE",
+"o     c #BCDDC9",
+"p     c #C6E0D1",
+"q     c #F9F9F9",
+"r     c #EBEBEB",
+"s     c #DFDFDF",
+"t     c #D7D7D7",
+"u     c #D5D5D5",
+"v     c #C6C6C6",
+"w     c #F6F6F6",
+"x     c #E7E7E7",
+"y     c #CECECE",
+"z     c #767676",
+"A     c #8B8B8B",
+"B     c #9F9F9F",
+"C     c #B3B3B3",
+"D     c #C7C7C7",
+"E     c #9E9E9E",
+"F     c #898989",
+"G     c #616161",
+"H     c #4C4C4C",
+"I     c #383838",
+"J     c #E4E4E4",
+"K     c #D1D1D1",
+"L     c #8D8D8D",
+"M     c #9A9A9A",
+"N     c #ACACAC",
+"O     c #888888",
+"P     c #777777",
+"Q     c #676767",
+"R     c #585858",
+"S     c #A5A5A5",
+"T     c #E0E0E0",
+"U     c #DEDEDE",
+"V     c #D3D3D3",
+"W     c #E5E5E5",
+"X     c #D2D2D2",
+"Y     c #000000",
+"Z     c #8C8C8C",
+"`     c #BFBFBF",
+" .    c #D6D6D6",
+"..    c #565656",
+"+.    c #454545",
+"@.    c #989898",
+"#.    c #737373",
+"$.    c #9B9B9B",
+"%.    c #656565",
+"&.    c #4B4B4B",
+"*.    c #848484",
+"=.    c #DDDDDD",
+"-.    c #F8F8F8",
+";.    c #F5F5F5",
+">.    c #E1E1E1",
+",.    c #F0F0F0",
+"'.    c #080808",
+").    c #D4D4D4",
+"!.    c #CDCDCD",
+"~.    c #272727",
+"{.    c #1E1E1E",
+"].    c #2D2D2D",
+"^.    c #232323",
+"/.    c #D9D9D9",
+"(.    c #343434",
+"_.    c #B9B9B9",
+":.    c #555555",
+"<.    c #E8E8E8",
+"[.    c #444444",
+"}.    c #535353",
+"|.    c #7A7A7A",
+"1.    c #6E6E6E",
+"2.    c #626262",
+"3.    c #6A6A6A",
+"4.    c #606060",
+"5.    c #595959",
+"6.    c #636363",
+"7.    c #CACACA",
+"8.    c #CBCBCB",
+"9.    c #747474",
+"0.    c #727272",
+"a.    c #707070",
+"b.    c #6B6B6B",
+"c.    c #686868",
+"d.    c #7B7B7B",
+"e.    c #CFCFCF",
+"f.    c #929292",
+"g.    c #A9A9A9",
+"h.    c #A6A6A6",
+"i.    c #9D9D9D",
+"j.    c #969696",
+"k.    c #919191",
+"l.    c #818181",
+"        . . . . . . . . . . . . . . . .                             ",
+"        . + + + + + + + + @ # $ % & * = -                           ",
+"        . + ; ; ; ; ; ; ; > , ; ' ) ! = ; -                         ",
+"        . + ; ; ; ; ; ; ; > ~ ; ; ' ) = ; ; -                       ",
+"        . + ; ; ; ; ; ; ; > ~ ; ; ; ' = { ; ; -                     ",
+"        . + ; ; ; ; ; ; ; ; ] ; ; ; ; = { { ; ; -                   ",
+"        . + ; ; ; ^ ^ ; ; > / ; ; ; ; = { { { ; ; -                 ",
+"        . + ; ; ^ ( _ ^ ; ; ] ; ; ; ; = { { { { ; ; -               ",
+"        . + ; ; : ; ; ^ ; ; ] ; ; ; ; < [ . } | 1 2 3 -             ",
+"        . + ; ; ; ; ^ : ; ; 4 4 ; ; ; ' 5 6 * 7 8 9 | -             ",
+"        . + ; ; ; ; 0 ; ; 4 a b 4 ; 4 ; c d { { e f g -             ",
+"        . + ; ; ; ^ ; ; ; 4 ; ; h ; i c c ) j k l m n -             ",
+"        . + ; ; ; o ; ; ; p 4 ; ; ; ' q ) ) r s t u v -             ",
+"        . + ; ; ; ; ; ; ; ; ; ; ; ' q w $ $ 5 x 7 l y -             ",
+"        . + z A B C D k D C E F z G H I ) r r J 6 e K -             ",
+"        . + ; f L M N < N M O P Q R S # $ * * x T U V -             ",
+"        . + z F E C D k D C E F z G H I 5 r W W 6 k X -             ",
+"        . + z F E C Y Z S `  .; z G H I r * 6 6 T l K -             ",
+"        . + z F E C D Y `  .; F z G H I * x J s s k X -             ",
+"        . + V P O M N < Y ; O P Q ..+.@.x J 6 k k l K -             ",
+"        . + ; g #.- 2 $.2 - #.%.R &.*.W J 6 T =.t t 8 -             ",
+"        . + ; ; ' q -.;.@ # ! % & * W J >.s =.7 u u y -             ",
+"        . + ; ' q Y Y Y ,.'.% Y Y Y { >.s =.7 e t ).!.-             ",
+"        . + ; q w ~.j {.! ].* ^./.(.>.U =.7 e  .).).y -             ",
+"        _.+ c w d :.7 +.r +.<.[.8 }.U =.7 e  .V X K !.-             ",
+"        g + -.d # |.1.2.* 3.j 4.5.6.k 7 e  .V X 8 !.m -             ",
+"        C + ;.# $ 5 r * x j 6 T U k 7 t  .V K 8 m 7.8.-             ",
+"        | + @ $ 5 9.* 0.a.1.T b.k c.t u V K 8 8.8.7.f -             ",
+"        N + # 5 r A x O ).*.=.- l d.u V 8 e.8.8.8.7.f -             ",
+"        N + ! r * 1 J $.8 @.k f.e L ).K K !.m 7.7.7.f -             ",
+"        g.+ <.j { >.s k l e  .).).X 8 e.y !.m 8.f f f -             ",
+"        g.h.1 i.M j.k.Z O *.l.- - - - - - - - - - - - -             ",
+"                                                                    ",
+"                                                                    "};
index e0988db28bd9252604ec5df99b4251554ffd4552..790b6fa7dc81fe4344ab7ed7afb48bad72f0fec1 100644 (file)
  * Preamble
  *****************************************************************************/
 #include "updatevlc.hpp"
-#include <wx/progdlg.h>
-#include <wx/treectrl.h>
+#include <wx/listctrl.h>
+#include <wx/imaglist.h>
+#include <wx/thread.h>
+
+#include "bitmaps/update_ascii.xpm"
+#include "bitmaps/update_binary.xpm"
+#include "bitmaps/update_document.xpm"
+#include "bitmaps/update_info.xpm"
+#include "bitmaps/update_source.xpm"
 
 #include "vlc_block.h"
 #include "vlc_stream.h"
-#include "vlc_xml.h"
-
-/* define UPDATE_VLC_OS and UPDATE_VLC_ARCH */
-/* todo : move this somewhere else (isn't wx specific) */
-
-#ifdef WIN32
-#   define UPDATE_VLC_OS "windows"
-#   define UPDATE_VLC_ARCH "i386"
-#else
-#ifdef __APPLE__
-#   define UPDATE_VLC_OS "macosx"
-#   define UPDATE_VLC_ARCH "ppc"
-#else
-#   define UPDATE_VLC_OS "*"
-#   define UPDATE_VLC_ARCH "*"
-#endif
-#endif
-
-/* arch == "*" and os == "*" concern non OS or arch specific stuff */
-
-#define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status"
-#define UPDATE_VLC_MIRRORS_URL "http://update.videolan.org/mirrors"
 
 #define UPDATE_VLC_DOWNLOAD_BUFFER_SIZE 2048
 
-class UpdatesTreeItem : public wxTreeItemData
-{
-    public:
-        UpdatesTreeItem( wxString _url ):wxTreeItemData()
-        {
-            url = _url;
-        }
-        wxString url;
-};
-
 /*****************************************************************************
  * Event Table.
  *****************************************************************************/
@@ -74,8 +49,7 @@ enum
 {
     Close_Event,
     CheckForUpdate_Event,
-    MirrorChoice_Event,
-    UpdatesTreeActivate_Event
+    ChooseItem_Event
 };
 
 BEGIN_EVENT_TABLE(UpdateVLC, wxFrame)
@@ -83,11 +57,8 @@ BEGIN_EVENT_TABLE(UpdateVLC, wxFrame)
     EVT_BUTTON(wxID_OK, UpdateVLC::OnButtonClose)
     EVT_BUTTON(CheckForUpdate_Event, UpdateVLC::OnCheckForUpdate)
 
-    /* Choice events */
-    EVT_CHOICE(MirrorChoice_Event, UpdateVLC::OnMirrorChoice)
-
-    /* Tree events */
-    EVT_TREE_ITEM_ACTIVATED(UpdatesTreeActivate_Event, UpdateVLC::OnUpdatesTreeActivate)
+    /* CtrlList events */
+    EVT_LIST_ITEM_ACTIVATED( ChooseItem_Event, UpdateVLC::OnChooseItem )
 
     /* Hide the window when the user closes the window */
     EVT_CLOSE(UpdateVLC::OnClose)
@@ -98,515 +69,31 @@ END_EVENT_TABLE()
  * Constructor.
  *****************************************************************************/
 UpdateVLC::UpdateVLC( intf_thread_t *_p_intf, wxWindow *p_parent ):
-    wxFrame( p_parent, -1, wxU(_("Check for updates ...")), wxDefaultPosition,
-             wxDefaultSize, wxDEFAULT_FRAME_STYLE )
+    wxFrame( p_parent, -1, wxU(_("VLC media player - Updates")),
+             wxDefaultPosition, wxDefaultSize,
+         wxSYSTEM_MENU|wxCLOSE_BOX|wxFRAME_FLOAT_ON_PARENT|wxFRAME_TOOL_WINDOW)
 {
     /* Initializations */
     p_intf = _p_intf;
-    release_type = wxT( "testing" );
     SetIcon( *p_intf->p_sys->p_icon );
     SetAutoLayout( TRUE );
 
-    /* Create a panel to put everything in */
-    wxPanel *panel = new wxPanel( this, -1 );
-    panel->SetAutoLayout( TRUE );
-
-    updates_tree =
-        new wxTreeCtrl( panel, UpdatesTreeActivate_Event, wxDefaultPosition,
-                        wxSize( 400, 200 ),
-                        wxTR_HAS_BUTTONS | wxTR_HIDE_ROOT | wxSUNKEN_BORDER );
-    updates_tree->AddRoot( wxU(_("root" )), -1, -1, NULL );
-
-    /* Place everything in sizers */
     wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
-    wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
-    wxBoxSizer *subpanel_sizer = new wxBoxSizer( wxHORIZONTAL );
-    panel_sizer->Add( updates_tree, 1, wxGROW | wxALL, 5 );
     wxButton *update_button =
-        new wxButton( panel, CheckForUpdate_Event,
+        new wxButton( this, CheckForUpdate_Event,
                       wxU(_("Check for updates now !")) );
-    subpanel_sizer->Add( update_button, 0, wxALL, 5 );
-//wxChoice constructor prototype changes with 2.5
-#if wxCHECK_VERSION(2,5,0)
-    wxArrayString *choices_array = new wxArrayString();
-    choices_array->Add( wxT("") );
-    mirrors_choice =
-        new wxChoice( panel, MirrorChoice_Event, wxDefaultPosition,
-                      wxSize( 200, -1 ), *choices_array );
-#else
-    wxString choices_array = wxT("");
-    mirrors_choice =
-        new wxChoice( panel, -1, wxDefaultPosition,
-                      wxSize( 200, -1 ),1, *choices_array );
-#endif
-    subpanel_sizer->Add( mirrors_choice, 0, wxALL, 5 );
-    subpanel_sizer->Layout();
-    panel_sizer->Add( subpanel_sizer, 0, wxALL , 0 );
-    panel_sizer->Layout();
-    panel->SetSizerAndFit( panel_sizer );
-    main_sizer->Add( panel, 1, wxALL | wxGROW, 0 );
-    main_sizer->Layout();
+    main_sizer->Add( update_button );
     SetSizerAndFit( main_sizer );
 
-    UpdateMirrorsChoice();
-    UpdateUpdatesTree();
+    p_u = update_New( p_intf );
 }
 
 
 UpdateVLC::~UpdateVLC()
 {
-    fprintf( stderr, "Fooing\n");
-}
-
-/* this function gets all the info from the xml files hosted on
-http://update.videolan.org/ and stores it in appropriate lists */
-void UpdateVLC::GetData()
-{
-    stream_t *p_stream = NULL;
-    char *psz_eltname = NULL;
-    char *psz_name = NULL;
-    char *psz_value = NULL;
-    char *psz_eltvalue = NULL;
-    xml_t *p_xml = NULL;
-    xml_reader_t *p_xml_reader = NULL;
-    bool b_os = false;
-    bool b_arch = false;
-
-    struct update_file_t tmp_file;
-    struct update_version_t tmp_version;
-    std::list<update_version_t>::iterator it;
-    std::list<update_file_t>::iterator it_files;
-
-    struct update_mirror_t tmp_mirror;
-
-    p_xml = xml_Create( p_intf );
-    if( !p_xml )
-    {
-        msg_Err( p_intf, "Failed to open XML parser" );
-        // FIXME : display error message in dialog
-        return;
-    }
-
-    p_stream = stream_UrlNew( p_intf, UPDATE_VLC_STATUS_URL );
-    if( !p_stream )
-    {
-        msg_Err( p_intf, "Failed to open %s for reading",
-                 UPDATE_VLC_STATUS_URL );
-        // FIXME : display error message in dialog
-        return;
-    }
-
-    p_xml_reader = xml_ReaderCreate( p_xml, p_stream );
-
-    if( !p_xml_reader )
-    {
-        msg_Err( p_intf, "Failed to open %s for parsing",
-                 UPDATE_VLC_STATUS_URL );
-        // FIXME : display error message in dialog
-        return;
-    }
-
-    /* empty tree */
-    m_versions.clear();
-
-    /* build tree */
-    while( xml_ReaderRead( p_xml_reader ) == 1 )
-    {
-        switch( xml_ReaderNodeType( p_xml_reader ) )
-        {
-            // Error
-            case -1:
-                // TODO : print message
-                return;
-
-            case XML_READER_STARTELEM:
-                psz_eltname = xml_ReaderName( p_xml_reader );
-                if( !psz_eltname )
-                {
-                    // TODO : print message
-                    return;
-                }
-                msg_Dbg( p_intf, "element name : %s", psz_eltname );
-                while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
-                {
-                    psz_name = xml_ReaderName( p_xml_reader );
-                    psz_value = xml_ReaderValue( p_xml_reader );
-                    if( !psz_name || !psz_value )
-                    {
-                        // TODO : print message
-                        free( psz_eltname );
-                        return;
-                    }
-                    msg_Dbg( p_intf, "  attribute %s = %s",
-                             psz_name, psz_value );
-                    if( b_os && b_arch )
-                    {
-                        if( strcmp( psz_eltname, "version" ) == 0 )
-                        {
-                            if( !strcmp( psz_name, "type" ) )
-                                tmp_version.type = wxU( psz_value );
-                            if( !strcmp( psz_name, "major" ) )
-                                tmp_version.major = wxU( psz_value );
-                            if( !strcmp( psz_name, "minor" ) )
-                                tmp_version.minor = wxU( psz_value );
-                            if( !strcmp( psz_name, "revision" ) )
-                                tmp_version.revision = wxU( psz_value );
-                            if( !strcmp( psz_name, "extra" ) )
-                                tmp_version.extra = wxU( psz_value );
-                        }
-                        if( !strcmp( psz_eltname, "file" ) )
-                        {
-                            if( !strcmp( psz_name, "type" ) )
-                                tmp_file.type = wxU( psz_value );
-                            if( !strcmp( psz_name, "md5" ) )
-                                tmp_file.md5 = wxU( psz_value );
-                            if( !strcmp( psz_name, "size" ) )
-                                tmp_file.size = wxU( psz_value );
-                            if( !strcmp( psz_name, "url" ) )
-                                tmp_file.url = wxU( psz_value );
-                        }
-                    }
-                    if( !strcmp( psz_name, "name" )
-                        && ( !strcmp( psz_value, UPDATE_VLC_OS )
-                           || !strcmp( psz_value, "*" ) )
-                        && !strcmp( psz_eltname, "os" ) )
-                    {
-                        b_os = true;
-                    }
-                    if( b_os && !strcmp( psz_name, "name" )
-                        && ( !strcmp( psz_value, UPDATE_VLC_ARCH )
-                           || !strcmp( psz_value, "*" ) )
-                        && !strcmp( psz_eltname, "arch" ) )
-                    {
-                        b_arch = true;
-                    }
-                    free( psz_name );
-                    free( psz_value );
-                }
-                if( ( b_os && b_arch && strcmp( psz_eltname, "arch" ) ) )
-                {
-                    if( !strcmp( psz_eltname, "version" ) )
-                    {
-                        it = m_versions.begin();
-                        while( it != m_versions.end() )
-                        {
-                            if( it->type == tmp_version.type
-                                && it->major == tmp_version.major
-                                && it->minor == tmp_version.minor
-                                && it->revision == tmp_version.revision
-                                && it->extra == tmp_version.extra )
-                            {
-                                break;
-                            }
-                            it++;
-                        }
-                        if( it == m_versions.end() )
-                        {
-                            m_versions.push_back( tmp_version );
-                            it = m_versions.begin();
-                            while( it != m_versions.end() )
-                            {
-                                if( it->type == tmp_version.type
-                                    && it->major == tmp_version.major
-                                    && it->minor == tmp_version.minor
-                                    && it->revision == tmp_version.revision
-                                    && it->extra == tmp_version.extra )
-                                {
-                                    break;
-                                }
-                                it++;
-                            }
-                        }
-                        tmp_version.type = wxT( "" );
-                        tmp_version.major = wxT( "" );
-                        tmp_version.minor = wxT( "" );
-                        tmp_version.revision = wxT( "" );
-                        tmp_version.extra = wxT( "" );
-                    }
-                    if( !strcmp( psz_eltname, "file" ) )
-                    {
-                        it->m_files.push_back( tmp_file );
-                        tmp_file.type = wxT( "" );
-                        tmp_file.md5 = wxT( "" );
-                        tmp_file.size = wxT( "" );
-                        tmp_file.url = wxT( "" );
-                        tmp_file.description = wxT( "" );
-                    }
-                }
-                free( psz_eltname );
-                break;
-
-            case XML_READER_ENDELEM:
-                psz_eltname = xml_ReaderName( p_xml_reader );
-                if( !psz_eltname )
-                {
-                    // TODO : print message
-                    return;
-                }
-                msg_Dbg( p_intf, "element end : %s", psz_eltname );
-                if( !strcmp( psz_eltname, "os" ) )
-                    b_os = false;
-                if( !strcmp( psz_eltname, "arch" ) )
-                    b_arch = false;
-                free( psz_eltname );
-                break;
-
-            case XML_READER_TEXT:
-                psz_eltvalue = xml_ReaderValue( p_xml_reader );
-                msg_Dbg( p_intf, "  text : %s", psz_eltvalue );
-                /* This doesn't look safe ... but it works */
-                if( !m_versions.empty() )
-                    if( !it->m_files.empty() )
-                        it->m_files.back().description = wxU( psz_eltvalue );
-                free( psz_eltvalue );
-                break;
-        }
-    }
-
-    if( p_xml_reader && p_xml ) xml_ReaderDelete( p_xml, p_xml_reader );
-    if( p_stream ) stream_Delete( p_stream );
-
-    p_stream = stream_UrlNew( p_intf, UPDATE_VLC_MIRRORS_URL );
-    if( !p_stream )
-    {
-        msg_Err( p_intf, "Failed to open %s for reading",
-                 UPDATE_VLC_MIRRORS_URL );
-        // FIXME : display error message in dialog
-        return;
-    }
-
-    p_xml_reader = xml_ReaderCreate( p_xml, p_stream );
-
-    if( !p_xml_reader )
-    {
-        msg_Err( p_intf, "Failed to open %s for parsing",
-                 UPDATE_VLC_MIRRORS_URL );
-        // FIXME : display error message in dialog
-        return;
-    }
-    /* empty list */
-    m_mirrors.clear();
-
-    /* build list */
-    while( xml_ReaderRead( p_xml_reader ) == 1 )
-    {
-        switch( xml_ReaderNodeType( p_xml_reader ) )
-        {
-            // Error
-            case -1:
-                // TODO : print message
-                return;
-
-            case XML_READER_STARTELEM:
-                psz_eltname = xml_ReaderName( p_xml_reader );
-                if( !psz_eltname )
-                {
-                    // TODO : print message
-                    return;
-                }
-                msg_Dbg( p_intf, "element name : %s", psz_eltname );
-                while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
-                {
-                    psz_name = xml_ReaderName( p_xml_reader );
-                    psz_value = xml_ReaderValue( p_xml_reader );
-                    if( !psz_name || !psz_value )
-                    {
-                        // TODO : print message
-                        free( psz_eltname );
-                        return;
-                    }
-                    msg_Dbg( p_intf, "  attribute %s = %s",
-                             psz_name, psz_value );
-                    if( !strcmp( psz_eltname, "mirror" ) )
-                    {
-                        if( !strcmp( psz_name, "name" ) )
-                            tmp_mirror.name = wxU( psz_value );
-                        if( !strcmp( psz_name, "location" ) )
-                            tmp_mirror.location = wxU( psz_value );
-                    }
-                    if( !strcmp( psz_eltname, "url" ) )
-                    {
-                        if( !strcmp( psz_name, "type" ) )
-                            tmp_mirror.type = wxU( psz_value );
-                        if( !strcmp( psz_name, "base" ) )
-                            tmp_mirror.base_url = wxU( psz_value );
-                    }
-                    free( psz_name );
-                    free( psz_value );
-                }
-                if( !strcmp( psz_eltname, "url" ) )
-                {
-                    m_mirrors.push_back( tmp_mirror );
-                    tmp_mirror.type = wxT( "" );
-                    tmp_mirror.base_url = wxT( "" );
-                }
-                free( psz_eltname );
-                break;
-
-            case XML_READER_ENDELEM:
-                psz_eltname = xml_ReaderName( p_xml_reader );
-                if( !psz_eltname )
-                {
-                    // TODO : print message
-                    return;
-                }
-                msg_Dbg( p_intf, "element end : %s", psz_eltname );
-                if( !strcmp( psz_eltname, "mirror" ) )
-                {
-                    tmp_mirror.name = wxT( "" );
-                    tmp_mirror.location = wxT( "" );
-                }
-                free( psz_eltname );
-                break;
-
-            case XML_READER_TEXT:
-                psz_eltvalue = xml_ReaderValue( p_xml_reader );
-                msg_Dbg( p_intf, "  text : %s", psz_eltvalue );
-                free( psz_eltvalue );
-                break;
-        }
-    }
-
-
-    if( p_xml_reader && p_xml ) xml_ReaderDelete( p_xml, p_xml_reader );
-    if( p_stream ) stream_Delete( p_stream );
-    if( p_xml ) xml_Delete( p_xml );
-}
-
-void UpdateVLC::UpdateUpdatesTree()
-{
-    wxTreeItemId parent;
-    std::list<update_version_t>::iterator it;
-    std::list<update_file_t>::iterator it_files;
-    std::list<update_mirror_t>::iterator it_mirrors;
-
-    int selection = mirrors_choice->GetSelection();
-    wxString base_url = wxT( "" );
-
-    if( selection-- )
-    {
-        it_mirrors = m_mirrors.begin();
-        while( it_mirrors != m_mirrors.end() && selection )
-        {
-            it_mirrors++;
-            selection--;
-        }
-        if( it_mirrors != m_mirrors.end() ) base_url = it_mirrors->base_url;
-    }
-
-    /* empty tree */
-    updates_tree->DeleteAllItems();
-
-    /* build tree */
-    parent=updates_tree->AddRoot( wxU(_("root" )), -1, -1, NULL );
-    updates_tree->AppendItem( parent,
-                             wxT( "Current version : VLC media player "PACKAGE_VERSION_MAJOR"."PACKAGE_VERSION_MINOR"."PACKAGE_VERSION_REVISION"-"PACKAGE_VERSION_EXTRA ),
-                             -1, -1, new UpdatesTreeItem( wxT( "" ) ));
-    it = m_versions.begin();
-    while( it != m_versions.end() )
-    {
-        if( it->type != release_type )
-        {
-            it++;
-            continue;
-        }
-
-        if( release_type != wxT( "stable" ) && it->type == wxT( "stable" ) )
-        {
-            it++;
-            continue;
-        }
-
-        if( release_type != wxT( "stable" ) && release_type != wxT( "testing" )
-            && it->type == wxT( "testing" ) )
-        {
-            it++;
-            continue;
-        }
-
-        if( release_type != wxT( "stable" ) && release_type != wxT( "testing" )
-            && release_type != wxT( "nightly" ) )
-        {
-            it++;
-            continue;
-        }
-
-        if( atoi((const char *)it->major.mb_str()) <
-            atoi(PACKAGE_VERSION_MAJOR)
-         || ( atoi((const char *)it->major.mb_str()) ==
-              atoi(PACKAGE_VERSION_MAJOR)
-         && ( atoi((const char *)it->minor.mb_str()) <
-               atoi(PACKAGE_VERSION_MINOR)
-         || ( atoi((const char *)it->minor.mb_str()) ==
-              atoi(PACKAGE_VERSION_MINOR)
-         && ( atoi((const char *)it->revision.mb_str()) <
-               atoi(PACKAGE_VERSION_REVISION)
-         || ( atoi((const char *)it->revision.mb_str()) ==
-              atoi(PACKAGE_VERSION_REVISION) ) ) ) ) ) )
-        {
-            /* version is older or equal tu current version.
-            FIXME : how do we handle the extra version number ? */
-            it++;
-            continue;
-        }
-        wxTreeItemId cat = updates_tree->AppendItem( parent,
-                         wxT("New Version : VLC media player ")
-                         + it->major + wxT(".")
-                         + it->minor + wxT(".") + it->revision + wxT("-")
-                         + it->extra + wxT(" (") + it->type + wxT(")"),
-                         -1, -1, new UpdatesTreeItem( wxT( "" ) ));
-        it_files = it->m_files.begin();
-        while( it_files != it->m_files.end() )
-        {
-            wxString url = (it_files->url[0]=='/' ? base_url : wxT( "" ) )
-                           + it_files->url;
-            wxTreeItemId file =
-                updates_tree->AppendItem( cat, it_files->description,
-                   -1, -1, new UpdatesTreeItem( url ) );
-            updates_tree->AppendItem( file,
-                wxU(_("type : ")) + it_files->type,
-                -1, -1, new UpdatesTreeItem( url ));
-            updates_tree->AppendItem( file, wxU(_("URL : ")) + url,
-                                      -1, -1, new UpdatesTreeItem( url ));
-            if( it_files->size != wxT( "" ) )
-                updates_tree->AppendItem( file,
-                    wxU(_("file size : ")) + it_files->size,
-                    -1, -1, new UpdatesTreeItem( url ));
-            if( it_files->md5 != wxT( "" ) )
-                updates_tree->AppendItem( file,
-                    wxU(_("file md5 hash : ")) + it_files->md5,
-                    -1, -1, new UpdatesTreeItem( url ));
-            it_files ++;
-        }
-        it ++;
-        updates_tree->Expand( cat );
-        updates_tree->Expand( parent );
-    }
+    update_Delete( p_u );
 }
 
-void UpdateVLC::UpdateMirrorsChoice()
-{
-    std::list<update_mirror_t>::iterator it_mirrors;
-
-    mirrors_choice->Clear();
-    mirrors_choice->Append( wxU(_("Choose a mirror")) );
-    it_mirrors = m_mirrors.begin();
-    while( it_mirrors != m_mirrors.end() )
-    {
-        mirrors_choice->Append( it_mirrors->name + wxT(" (")
-                                + it_mirrors->location + wxT(") [")
-                                + it_mirrors->type + wxT("]") );
-        it_mirrors++;
-    }
-    mirrors_choice->SetSelection( 0 );
-}
-
-/*void UpdateVLC::UpdateUpdateVLC()
-{
-    UpdateUpdatesTree();
-    UpdateMirrorsChoice();
-}*/
-
 void UpdateVLC::OnButtonClose( wxCommandEvent& event )
 {
     wxCloseEvent cevent;
@@ -620,83 +107,121 @@ void UpdateVLC::OnClose( wxCloseEvent& WXUNUSED(event) )
 
 void UpdateVLC::OnCheckForUpdate( wxCommandEvent& event )
 {
-    GetData();
-    UpdateMirrorsChoice();
-    UpdateUpdatesTree();
-}
-
-void UpdateVLC::OnMirrorChoice( wxCommandEvent& event )
-{
-    UpdateUpdatesTree();
-}
-
-void UpdateVLC::OnUpdatesTreeActivate( wxTreeEvent& event )
-{
-    wxString url =
-      ((UpdatesTreeItem *)(updates_tree->GetItemData(event.GetItem())))->url;
-    if( url != wxT( "" ) ? url[0] != '/' : false )
+    update_Check( p_u, VLC_FALSE );
+    update_iterator_t *p_uit = update_iterator_New( p_u );
+    if( p_uit )
     {
-        wxFileDialog *filedialog =
-            new wxFileDialog( updates_tree, wxU(_("Save file ...")),
-                              wxT(""), url.AfterLast( '/' ), wxT("*.*"),
-                              wxSAVE | wxOVERWRITE_PROMPT );
-        if( filedialog->ShowModal() == wxID_OK )
+        wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
+
+        p_uit->i_rs = UPDATE_RELEASE_STATUS_NEWER;
+        p_uit->i_t = UPDATE_FILE_TYPE_ALL;
+        update_iterator_Action( p_uit, UPDATE_MIRROR );
+
+        DestroyChildren();
+
+        wxListCtrl *list =
+            new wxListCtrl( this, ChooseItem_Event,
+                            wxDefaultPosition, wxSize( 400, 300 ),
+                            wxLC_AUTOARRANGE|wxLC_SINGLE_SEL );
+        wxImageList *images = new wxImageList( 32, 32, TRUE );
+        images->Add( wxIcon( update_ascii_xpm ) );
+        images->Add( wxIcon( update_info_xpm ) );
+        images->Add( wxIcon( update_source_xpm ) );
+        images->Add( wxIcon( update_binary_xpm ) );
+        images->Add( wxIcon( update_document_xpm ) );
+        list->AssignImageList( images, wxIMAGE_LIST_SMALL );
+        while( update_iterator_Action( p_uit, UPDATE_FILE ) != UPDATE_FAIL )
         {
-            DownloadFile( url, filedialog->GetPath() );
+            /*wxButton *update_button =
+                new wxButton( this, Download_Event,
+                      wxU(p_uit->file.psz_description) );
+            main_sizer->Add( update_button, 0, wxALIGN_CENTER );*/
+            int i_image;
+            switch( p_uit->file.i_type )
+            {
+                case UPDATE_FILE_TYPE_INFO:
+                    i_image = 1;
+                    break;
+                case UPDATE_FILE_TYPE_SOURCE:
+                    i_image = 2;
+                    break;
+                case UPDATE_FILE_TYPE_BINARY:
+                    i_image = 3;
+                    break;
+                case UPDATE_FILE_TYPE_PLUGIN:
+                    i_image = 4;
+                    break;
+                default:
+                    i_image = 0;
+            }
+            list->InsertItem( list->GetItemCount(),
+                              wxU(p_uit->file.psz_description)+wxU("\n")
+                              + wxU(p_uit->release.psz_version)+wxU(" (")
+                              + wxU(p_uit->release.psz_svn_revision)+wxU(")"),
+                              i_image );
         }
+
+        main_sizer->Add( new wxStaticText( this, -1, wxU( _("\nAvailable updates and related downloads:\n(Double click on a file to download it)\n" ) ) ) );
+        main_sizer->Add( list/*, 0, wxEXPAND */);
+        SetSizerAndFit( main_sizer );
+        Layout();
+        update_iterator_Delete( p_uit );
     }
 }
 
-void UpdateVLC::DownloadFile( wxString url, wxString dst )
+class DownloadThread : public wxThread
 {
-    char *psz_local = ToLocale( dst.mb_str() );
-    msg_Dbg( p_intf, "Downloading %s to %s",
-             (const char *)url.mb_str(), psz_local );
-
-    stream_t *p_stream = NULL;
-    p_stream = stream_UrlNew( p_intf, (const char *)url.mb_str() );
-    if( !p_stream )
+    public:
+    DownloadThread( update_iterator_t *p_uit, char *psz_dest )
+        :p_uit( p_uit ),psz_dest( psz_dest )
     {
-        msg_Err( p_intf, "Failed to open %s for reading", (const char *)url.mb_str() );
-        // FIXME : display error message in dialog
-        return;
+            Create();
+            Run();
     }
+    ExitCode Entry()
+    {
+        update_download( p_uit, psz_dest );
+        update_iterator_Delete( p_uit );
+        LocaleFree( psz_dest );
+        return 0;
+    };
+    update_iterator_t *p_uit;
+    char *psz_dest;
+};
 
-    FILE *p_file = NULL;
-    p_file = fopen( psz_local, "w" );
-    if( !p_file )
+void UpdateVLC::OnChooseItem( wxListEvent& event )
+{
+    update_iterator_t *p_uit = update_iterator_New( p_u );
+    if( p_uit )
     {
-        msg_Err( p_intf, "Failed to open %s for writing", psz_local );
-        // FIXME : display error message in dialog
-        return;
-    }
-    LocaleFree( psz_local );
+        p_uit->i_rs = UPDATE_RELEASE_STATUS_NEWER;
+        p_uit->i_t = UPDATE_FILE_TYPE_ALL;
+        update_iterator_Action( p_uit, UPDATE_MIRROR );
 
-    int i_progress = 0;
-    wxProgressDialog *progressdialog =
-        new wxProgressDialog( wxU(_("Downloading...")),
-        wxU(wxT("Src: ") +url + wxT("\nDst: ") +dst ),
-        (int)(stream_Size(p_stream)/UPDATE_VLC_DOWNLOAD_BUFFER_SIZE), NULL,
-        wxPD_ELAPSED_TIME | wxPD_REMAINING_TIME | wxPD_AUTO_HIDE
-        | wxPD_CAN_ABORT );
+        int i_count = 0;
+        while( update_iterator_Action( p_uit, UPDATE_FILE ) != UPDATE_FAIL )
+        {
+            if( i_count == event.GetIndex() )
+                break;
+            i_count++;
+        }
+        wxString url = wxU( p_uit->file.psz_url );
+        wxFileDialog *filedialog =
+                    new wxFileDialog( this, wxU(_("Save file ...")),
+                        wxT(""), url.AfterLast( '/' ), wxT("*.*"),
+                        wxSAVE | wxOVERWRITE_PROMPT );
+        if( filedialog->ShowModal() == wxID_OK )
+        {
+            char *psz_dest = ToLocale( filedialog->GetPath().mb_str() );
 
-    void *buffer = (void *)malloc( UPDATE_VLC_DOWNLOAD_BUFFER_SIZE );
-    while( stream_Read( p_stream, buffer, UPDATE_VLC_DOWNLOAD_BUFFER_SIZE ) )
-    {
-        fwrite( buffer, UPDATE_VLC_DOWNLOAD_BUFFER_SIZE, 1, p_file);
-        if( !progressdialog->Update(++i_progress) )
+            /* Launch the download process in a new thread so it doesn't
+             * block the interface */
+            new DownloadThread( p_uit, psz_dest );
+        }
+        else
         {
-            free( buffer );
-            fclose( p_file );
-            if( p_stream ) stream_Delete( p_stream );
-            progressdialog->Destroy();
-            msg_Warn( p_intf, "User aborted download" );
-            return;
+            update_iterator_Delete( p_uit );
         }
+        delete filedialog;
     }
-    progressdialog->Destroy();
-    msg_Dbg( p_intf, "Download finished" );
-    free( buffer );
-    fclose( p_file );
-    if( p_stream ) stream_Delete( p_stream );
 }
index 3d4e0fc9105c4f7b79b708052102ff216785a3e6..70262b87f58e12b501597d6561b009762d87cdb2 100644 (file)
 #ifndef _WXVLC_UPDATEVLC_H_
 #define _WXVLC_UPDATEVLC_H_
 
+#include <vlc_update.h>
+
 #include "wxwidgets.hpp"
 #include <wx/treectrl.h>
-#include <list>
 
 class wxTreeCtrl;
 
@@ -35,60 +36,19 @@ namespace wxvlc
     class UpdateVLC: public wxFrame
     {
     public:
-        /** Constructor */
         UpdateVLC( intf_thread_t *p_intf, wxWindow *p_parent );
         virtual ~UpdateVLC();
 
     private:
         void OnButtonClose( wxCommandEvent& event );
         void OnClose( wxCloseEvent& WXUNUSED(event) );
-        void GetData();
         void OnCheckForUpdate( wxCommandEvent& event );
-        void OnMirrorChoice( wxCommandEvent& event );
-        void UpdateUpdatesTree();
-        void UpdateMirrorsChoice();
-        void OnUpdatesTreeActivate( wxTreeEvent& event );
-        void DownloadFile( wxString url, wxString dst );
+        void OnChooseItem( wxListEvent& event );
 
         DECLARE_EVENT_TABLE();
 
         intf_thread_t *p_intf;
-        wxTreeCtrl *updates_tree;
-
-        wxChoice *mirrors_choice;
-
-        wxString release_type; /* could be "stable", "test", "nightly" ... */
-
-        struct update_file_t
-        {
-            wxString type;
-            wxString md5;
-            wxString size;
-            wxString url;
-            wxString description;
-        };
-
-        struct update_version_t
-        {
-            wxString type;
-            wxString major;
-            wxString minor;
-            wxString revision;
-            wxString extra;
-            std::list<update_file_t> m_files;
-        };
-
-        std::list<update_version_t> m_versions;
-
-        struct update_mirror_t
-        {
-            wxString name;
-            wxString location;
-            wxString type;
-            wxString base_url;
-        };
-
-        std::list<update_mirror_t> m_mirrors;
+        update_t *p_u;
     };
 };
 
index 743ac519638829bd27e1ab2c92055e14108328f4..b11815cf04483c348b65086462dd0286ea02ee0b 100644 (file)
 #include "vlc_image.h"
 #include "vlc_osd.h"
 
+#include "vlc_update.h"
+
 #if defined( _MSC_VER ) && defined( UNDER_CE )
 #    include "modules_builtin_evc.h"
 #elif defined( _MSC_VER )
diff --git a/src/misc/update.c b/src/misc/update.c
new file mode 100644 (file)
index 0000000..fb185d3
--- /dev/null
@@ -0,0 +1,1257 @@
+/*****************************************************************************
+ * update.c: VLC update and plugins download
+ *****************************************************************************
+ * Copyright (C) 2005 the VideoLAN team
+ * $Id: $
+ *
+ * Authors: Antoine Cellerier <dionoea -at- videolan -dot- org>
+ *
+ * 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 release 2 of the License, or
+ * (at your option) any later release.
+ *
+ * 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.
+ *****************************************************************************/
+
+/* TODO
+ * --> check release types.
+ * --> make sure that the version comparision method is ok.
+ */
+
+/**
+ *   \file
+ *   This file contains functions related to VLC and plugins update management
+ */
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>                                      /* malloc(), free() */
+#include <ctype.h>                                              /* tolower() */
+#include <unistd.h>
+
+#include <vlc/vlc.h>
+
+#include "vlc_update.h"
+
+#include "vlc_block.h"
+#include "vlc_stream.h"
+#include "vlc_xml.h"
+#include "vlc_interaction.h"
+
+/*****************************************************************************
+ * Misc defines
+ *****************************************************************************/
+
+/* All release notes and source packages should match on "*"
+ * Only binary installers are OS specific ( we only provide these
+ * for Win32, Mac OS X, WincCE, beos(?) ) */
+#if defined( UNDER_CE )
+#   define UPDATE_VLC_OS "*"
+#   define UPDATE_VLC_ARCH "*"
+#elif defined( WIN32 )
+#   define UPDATE_VLC_OS "windows"
+#   define UPDATE_VLC_ARCH "i386"
+#elif defined( __APPLE__ )
+#   define UPDATE_VLC_OS "macosx"
+#   if defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc64__ )
+#       define UPDATE_VLC_ARCH "ppc"
+#   else
+#       define UPDATE_VLC_ARCH "x86"
+#   endif
+#elif defined( SYS_BEOS )
+#   define UPDATE_VLC_OS "beos"
+#   define UPDATE_VLC_ARCH "i386"
+#else
+#   define UPDATE_VLC_OS "*"
+#   define UPDATE_VLC_ARCH "*"
+#endif
+
+#define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status.xml"
+#define UPDATE_VLC_MIRRORS_URL "http://update.videolan.org/mirrors.xml"
+
+#define FREE( a ) free(a);a=NULL;
+#define STRDUP( a ) ( a ? strdup( a ) : NULL )
+
+/*****************************************************************************
+ * Local Prototypes
+ *****************************************************************************/
+
+void FreeMirrorsList( update_t * );
+void FreeReleasesList( update_t * );
+void GetMirrorsList( update_t *, vlc_bool_t );
+void GetFilesList( update_t *, vlc_bool_t );
+
+int CompareReleases( struct update_release_t *, struct update_release_t * );
+int CompareReleaseToCurrent( struct update_release_t * );
+
+unsigned int update_iterator_Reset( update_iterator_t * );
+unsigned int update_iterator_NextFile( update_iterator_t * );
+unsigned int update_iterator_PrevFile( update_iterator_t * );
+unsigned int update_iterator_NextMirror( update_iterator_t * );
+unsigned int update_iterator_PrevMirror( update_iterator_t * );
+
+void update_iterator_GetData( update_iterator_t * );
+void update_iterator_ClearData( update_iterator_t * );
+
+/*****************************************************************************
+ * Update_t functions
+ *****************************************************************************/
+
+/**
+ * Create a new update VLC struct
+ *
+ * \param p_this the calling vlc_object
+ * \return pointer to new update_t or NULL
+ */
+update_t *__update_New( vlc_object_t *p_this )
+{
+    update_t *p_update;
+
+    if( p_this == NULL ) return NULL;
+
+    p_update = (update_t *)malloc( sizeof( update_t ) );
+
+    vlc_mutex_init( p_this, &p_update->lock );
+
+    p_update->p_vlc = p_this->p_vlc;
+
+    p_update->p_releases = NULL;
+    p_update->i_releases = 0;
+    p_update->b_releases = VLC_FALSE;
+
+    p_update->p_mirrors = NULL;
+    p_update->i_mirrors = 0;
+    p_update->b_mirrors = VLC_FALSE;
+
+    return p_update;
+}
+
+/**
+ * Delete an update_t struct
+ *
+ * \param p_update update_t* pointer
+ * \return nothing
+ */
+void update_Delete( update_t *p_update )
+{
+    vlc_mutex_destroy( &p_update->lock );
+    FreeMirrorsList( p_update );
+    FreeReleasesList( p_update );
+    free( p_update );
+}
+
+/**
+ * Empty the mirrors list
+ * *p_update should be locked before using this function
+ *
+ * \param p_update pointer to the update struct
+ * \return nothing
+ */
+void FreeMirrorsList( update_t *p_update )
+{
+    int i;
+
+    for( i = 0; i < p_update->i_mirrors; i++ )
+    {
+        free( p_update->p_mirrors[i].psz_name );
+        free( p_update->p_mirrors[i].psz_location );
+        free( p_update->p_mirrors[i].psz_type );
+        free( p_update->p_mirrors[i].psz_base_url );
+    }
+    FREE( p_update->p_mirrors );
+    p_update->i_mirrors = 0;
+    p_update->b_mirrors = VLC_FALSE;
+}
+
+/**
+ * Empty the releases list
+ * *p_update should be locked before calling this function
+ *
+ * \param p_update pointer to the update struct
+ * \return nothing
+ */
+void FreeReleasesList( update_t *p_update )
+{
+    int i;
+
+    for( i = 0; i < p_update->i_releases; i++ )
+    {
+        int j;
+        struct update_release_t *p_release = (p_update->p_releases + i);
+        for( j = 0; j < p_release->i_files; j++ )
+        {
+            free( p_release->p_files[j].psz_md5 );
+            free( p_release->p_files[j].psz_url );
+            free( p_release->p_files[j].psz_description );
+        }
+        free( p_release->psz_major );
+        free( p_release->psz_minor );
+        free( p_release->psz_revision );
+        free( p_release->psz_extra );
+        free( p_release->psz_svn_revision );
+        free( p_release->p_files );
+    }
+    FREE( p_update->p_releases );
+    p_update->i_releases = 0;
+    p_update->b_releases = VLC_FALSE;
+}
+
+/**
+ * Get the mirrors list XML file and parse it
+ * *p_update has to be unlocked when calling this function
+ *
+ * \param p_update pointer to the update struct
+ * \param b_force set to VLC_TRUE if you want to force the mirrors list update
+ * \return nothing
+ */
+void GetMirrorsList( update_t *p_update, vlc_bool_t b_force )
+{
+    stream_t *p_stream = NULL;
+
+    xml_t *p_xml = NULL;
+    xml_reader_t *p_xml_reader = NULL;
+
+    char *psz_eltname = NULL;
+    //char *psz_eltvalue = NULL;
+    char *psz_name = NULL;
+    char *psz_value = NULL;
+
+    struct update_mirror_t tmp_mirror = {0};
+
+    vlc_mutex_lock( &p_update->lock );
+
+    if( p_update->b_mirrors && b_force == VLC_FALSE )
+    {
+        vlc_mutex_unlock( &p_update->lock );
+        return;
+    }
+
+    p_xml = xml_Create( p_update->p_vlc );
+    if( !p_xml )
+    {
+        msg_Err( p_update->p_vlc, "Failed to open XML parser" );
+        goto error;
+    }
+
+    p_stream = stream_UrlNew( p_update->p_vlc, UPDATE_VLC_MIRRORS_URL );
+    if( !p_stream )
+    {
+        msg_Err( p_update->p_vlc, "Failed to open %s for reading",
+                 UPDATE_VLC_MIRRORS_URL );
+        goto error;
+    }
+
+    p_xml_reader = xml_ReaderCreate( p_xml, p_stream );
+
+    if( !p_xml_reader )
+    {
+        msg_Err( p_update->p_vlc, "Failed to open %s for parsing",
+                 UPDATE_VLC_MIRRORS_URL );
+        goto error;
+    }
+
+    if( p_update->p_mirrors )
+    {
+        FreeMirrorsList( p_update );
+    }
+
+    while( xml_ReaderRead( p_xml_reader ) == 1 )
+    {
+        switch( xml_ReaderNodeType( p_xml_reader ) )
+        {
+            case -1:
+                msg_Err( p_update->p_vlc, "Error while parsing %s",
+                         UPDATE_VLC_MIRRORS_URL );
+                goto error;
+
+            case XML_READER_STARTELEM:
+                psz_eltname = xml_ReaderName( p_xml_reader );
+                if( !psz_eltname )
+                {
+                    msg_Err( p_update->p_vlc, "Error while parsing %s",
+                             UPDATE_VLC_MIRRORS_URL );
+                    goto error;
+                }
+
+                while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
+                {
+                    psz_name = xml_ReaderName( p_xml_reader );
+                    psz_value = xml_ReaderValue( p_xml_reader );
+
+                    if( !psz_name || !psz_value )
+                    {
+                        msg_Err( p_update->p_vlc, "Error while parsing %s",
+                                 UPDATE_VLC_MIRRORS_URL );
+                        goto error;
+                    }
+
+                    if( !strcmp( psz_eltname, "mirror" ) )
+                    {
+                        if( !strcmp( psz_name, "name" ) )
+                            tmp_mirror.psz_name = STRDUP( psz_value );
+                        else if( !strcmp( psz_name, "location" ) )
+                            tmp_mirror.psz_location = STRDUP( psz_value );
+                    }
+                    else if( !strcmp( psz_eltname, "url" ) )
+                    {
+                        if( !strcmp( psz_name, "type" ) )
+                            tmp_mirror.psz_type = STRDUP( psz_value );
+                        else if( !strcmp( psz_name, "base" ) )
+                            tmp_mirror.psz_base_url = STRDUP( psz_value );
+                    }
+                    FREE( psz_name );
+                    FREE( psz_value );
+                }
+                if( !strcmp( psz_eltname, "url" ) )
+                {
+                    /* append to mirrors list */
+                    p_update->p_mirrors =
+                    (struct update_mirror_t *)realloc( p_update->p_mirrors,
+                                       (++(p_update->i_mirrors))
+                                       *sizeof( struct update_mirror_t ) );
+                    p_update->p_mirrors[ p_update->i_mirrors - 1 ] =
+                        tmp_mirror;
+                    tmp_mirror.psz_name = STRDUP( tmp_mirror.psz_name );
+                    tmp_mirror.psz_location = STRDUP( tmp_mirror.psz_location );
+                    tmp_mirror.psz_type = NULL;
+                    tmp_mirror.psz_base_url = NULL;
+                }
+                FREE( psz_eltname );
+                break;
+
+            case XML_READER_ENDELEM:
+                psz_eltname = xml_ReaderName( p_xml_reader );
+                if( !psz_eltname )
+                {
+                    msg_Err( p_update->p_vlc, "Error while parsing %s",
+                             UPDATE_VLC_MIRRORS_URL );
+                    goto error;
+                }
+
+                if( !strcmp( psz_eltname, "mirror" ) )
+                {
+                    FREE( tmp_mirror.psz_name );
+                    FREE( tmp_mirror.psz_location );
+                }
+
+                FREE( psz_eltname );
+                break;
+
+            /*case XML_READER_TEXT:
+                psz_eltvalue = xml_ReaderValue( p_xml_reader );
+                FREE( psz_eltvalue );
+                break;*/
+        }
+    }
+
+    p_update->b_mirrors = VLC_TRUE;
+
+    error:
+        vlc_mutex_unlock( &p_update->lock );
+
+        free( psz_eltname );
+        //free( psz_eltvalue );
+        free( psz_name );
+        free( psz_value );
+
+        free( tmp_mirror.psz_name );
+        free( tmp_mirror.psz_location );
+        free( tmp_mirror.psz_type );
+        free( tmp_mirror.psz_base_url );
+
+        if( p_xml_reader && p_xml )
+            xml_ReaderDelete( p_xml, p_xml_reader );
+        if( p_stream )
+            stream_Delete( p_stream );
+        if( p_xml )
+            xml_Delete( p_xml );
+}
+
+/**
+ * Get the files list XML file and parse it
+ * *p_update has to be unlocked when calling this function
+ *
+ * \param p_update pointer to update struct
+ * \param b_force set to VLC_TRUE if you want to force the files list update
+ * \return nothing
+ */
+void GetFilesList( update_t *p_update, vlc_bool_t b_force )
+{
+    stream_t *p_stream = NULL;
+
+    xml_t *p_xml = NULL;
+    xml_reader_t *p_xml_reader = NULL;
+
+    char *psz_eltname = NULL;
+    char *psz_eltvalue = NULL;
+    char *psz_name = NULL;
+    char *psz_value = NULL;
+
+    struct update_release_t *p_release = NULL;
+    struct update_release_t tmp_release = {0};
+    struct update_file_t tmp_file = {0};
+    tmp_release.i_type = UPDATE_RELEASE_TYPE_STABLE;
+
+    vlc_bool_t b_os = VLC_FALSE, b_arch = VLC_FALSE;
+
+    vlc_mutex_lock( &p_update->lock );
+
+    if( p_update->b_releases && b_force == VLC_FALSE )
+    {
+        vlc_mutex_unlock( &p_update->lock );
+        return;
+    }
+
+    p_xml = xml_Create( p_update->p_vlc );
+    if( !p_xml )
+    {
+        msg_Err( p_update->p_vlc, "Failed to open XML parser" );
+        goto error;
+    }
+
+    p_stream = stream_UrlNew( p_update->p_vlc, UPDATE_VLC_STATUS_URL );
+    if( !p_stream )
+    {
+        msg_Err( p_update->p_vlc, "Failed to open %s for reading",
+                 UPDATE_VLC_STATUS_URL );
+        goto error;
+    }
+
+    p_xml_reader = xml_ReaderCreate( p_xml, p_stream );
+
+    if( !p_xml_reader )
+    {
+        msg_Err( p_update->p_vlc, "Failed to open %s for parsing",
+                 UPDATE_VLC_STATUS_URL );
+        goto error;
+    }
+
+    if( p_update->p_releases )
+    {
+        FreeReleasesList( p_update );
+    }
+
+    while( xml_ReaderRead( p_xml_reader ) == 1 )
+    {
+        switch( xml_ReaderNodeType( p_xml_reader ) )
+        {
+            case -1:
+                msg_Err( p_update->p_vlc, "Error while parsing %s",
+                         UPDATE_VLC_STATUS_URL );
+                goto error;
+
+            case XML_READER_STARTELEM:
+                psz_eltname = xml_ReaderName( p_xml_reader );
+                if( !psz_eltname )
+                {
+                    msg_Err( p_update->p_vlc, "Error while parsing %s",
+                             UPDATE_VLC_STATUS_URL );
+                    goto error;
+                }
+
+                while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
+                {
+                    psz_name = xml_ReaderName( p_xml_reader );
+                    psz_value = xml_ReaderValue( p_xml_reader );
+
+                    if( !psz_name || !psz_value )
+                    {
+                        msg_Err( p_update->p_vlc, "Error while parsing %s",
+                                 UPDATE_VLC_STATUS_URL );
+                        goto error;
+                    }
+
+                    if( b_os && b_arch )
+                    {
+                        if( strcmp( psz_eltname, "version" ) == 0 )
+                        {
+                            if( !strcmp( psz_name, "major" ) )
+                                tmp_release.psz_major = STRDUP( psz_value );
+                            else if( !strcmp( psz_name, "minor" ) )
+                                tmp_release.psz_minor = STRDUP( psz_value );
+                            else if( !strcmp( psz_name, "revision" ) )
+                                tmp_release.psz_revision = STRDUP( psz_value );
+                            else if( !strcmp( psz_name, "extra" ) )
+                                tmp_release.psz_extra = STRDUP( psz_value );
+                            else if( !strcmp( psz_name, "svn" ) )
+                                tmp_release.psz_svn_revision =
+                                                           STRDUP( psz_value );
+                            else if( !strcmp( psz_name, "version" ) )
+                            {
+                                if( !strcmp( psz_value, "unstable" ) )
+                                    tmp_release.i_type =
+                                                  UPDATE_RELEASE_TYPE_UNSTABLE;
+                                else if( !strcmp( psz_value, "testing" ) )
+                                    tmp_release.i_type =
+                                                  UPDATE_RELEASE_TYPE_TESTING;
+                                else
+                                    tmp_release.i_type =
+                                                  UPDATE_RELEASE_TYPE_STABLE;
+                            }
+                        }
+                        else if( !strcmp( psz_eltname, "file" ) )
+                        {
+                            if( !strcmp( psz_name, "type" ) )
+                            {
+                                if( !strcmp( psz_value, "info" ) )
+                                    tmp_file.i_type = UPDATE_FILE_TYPE_INFO;
+                                else if( !strcmp( psz_value, "source" ) )
+                                    tmp_file.i_type = UPDATE_FILE_TYPE_SOURCE;
+                                else if( !strcmp( psz_value, "binary" ) )
+                                    tmp_file.i_type = UPDATE_FILE_TYPE_BINARY;
+                                else if( !strcmp( psz_value, "plugin" ) )
+                                    tmp_file.i_type = UPDATE_FILE_TYPE_PLUGIN;
+                                else
+                                    tmp_file.i_type = UPDATE_FILE_TYPE_UNDEF;
+                            }
+                            else if( !strcmp( psz_name, "md5" ) )
+                                tmp_file.psz_md5 = STRDUP( psz_value );
+                            else if( !strcmp( psz_name, "size" ) )
+                                tmp_file.l_size = atol( psz_value );
+                            else if( !strcmp( psz_name, "url" ) )
+                                tmp_file.psz_url = STRDUP( psz_value );
+                        }
+                    }
+                    if( !strcmp( psz_name, "name" )
+                        && ( !strcmp( psz_value, UPDATE_VLC_OS )
+                           || !strcmp( psz_value, "*" ) )
+                        && !strcmp( psz_eltname, "os" ) )
+                    {
+                        b_os = VLC_TRUE;
+                    }
+                    if( b_os && !strcmp( psz_name, "name" )
+                        && ( !strcmp( psz_value, UPDATE_VLC_ARCH )
+                           || !strcmp( psz_value, "*" ) )
+                        && !strcmp( psz_eltname, "arch" ) )
+                    {
+                        b_arch = VLC_TRUE;
+                    }
+                    FREE( psz_name );
+                    FREE( psz_value );
+                }
+                if( ( b_os && b_arch && strcmp( psz_eltname, "arch" ) ) )
+                {
+                    if( !strcmp( psz_eltname, "version" ) )
+                    {
+                        int i;
+                        /* look for a previous occurence of this release */
+                        for( i = 0; i < p_update->i_releases; i++ )
+                        {
+                            p_release = p_update->p_releases + i;
+                            if( CompareReleases( p_release, &tmp_release )
+                                == UPDATE_RELEASE_STATUS_EQUAL )
+                            {
+                                break;
+                            }
+                        }
+                        /* if this is the first time that we see this release,
+                         * append it to the list of releases */
+                        if( i == p_update->i_releases )
+                        {
+                            tmp_release.i_status =
+                                CompareReleaseToCurrent( &tmp_release );
+                            p_update->p_releases =
+               (struct update_release_t *)realloc( p_update->p_releases,
+               (++(p_update->i_releases))*sizeof( struct update_release_t ) );
+                            p_update->p_releases[ p_update->i_releases - 1 ] =
+                                tmp_release;
+                            p_release =
+                                p_update->p_releases + p_update->i_releases - 1;
+                            tmp_release.psz_major = NULL;
+                            tmp_release.psz_minor = NULL;
+                            tmp_release.psz_revision = NULL;
+                            tmp_release.psz_extra = NULL;
+                            tmp_release.psz_svn_revision = NULL;
+                            tmp_release.i_type = UPDATE_RELEASE_TYPE_STABLE;
+                            tmp_release.i_status = 0;
+                            tmp_release.p_files = NULL;
+                            tmp_release.i_files = 0;
+                        }
+                        else
+                        {
+                            FREE( tmp_release.psz_major );
+                            FREE( tmp_release.psz_minor );
+                            FREE( tmp_release.psz_revision );
+                            FREE( tmp_release.psz_extra );
+                            FREE( tmp_release.psz_svn_revision );
+                            tmp_release.i_type = UPDATE_RELEASE_TYPE_STABLE;
+                            FREE( tmp_release.p_files );
+                            tmp_release.i_files = 0;
+                        }
+                    }
+                    else if( !strcmp( psz_eltname, "file" ) )
+                    {
+                        /* append file to p_release's file list */
+                        if( p_release == NULL )
+                        {
+                            goto error;
+                        }
+                        p_release->p_files =
+                    (struct update_file_t *)realloc( p_release->p_files,
+                    (++(p_release->i_files))*sizeof( struct update_file_t ) );
+                        p_release->p_files[ p_release->i_files - 1 ] = tmp_file;
+                        tmp_file.i_type = UPDATE_FILE_TYPE_UNDEF;
+                        tmp_file.psz_md5 = NULL;
+                        tmp_file.l_size = 0;
+                        tmp_file.psz_url = NULL;
+                        tmp_file.psz_description = NULL;
+                    }
+                }
+                FREE( psz_eltname );
+                break;
+
+            case XML_READER_ENDELEM:
+                psz_eltname = xml_ReaderName( p_xml_reader );
+                if( !psz_eltname )
+                {
+                    msg_Err( p_update->p_vlc, "Error while parsing %s",
+                             UPDATE_VLC_STATUS_URL );
+                    goto error;
+                }
+
+                if( !strcmp( psz_eltname, "os" ) )
+                    b_os = VLC_FALSE;
+                else if( !strcmp( psz_eltname, "arch" ) )
+                    b_arch = VLC_FALSE;
+                FREE( psz_eltname );
+                break;
+
+            case XML_READER_TEXT:
+                psz_eltvalue = xml_ReaderValue( p_xml_reader );
+                if( p_release && p_release->i_files )
+                    p_release->p_files[ p_release->i_files - 1 ]
+                               .psz_description = STRDUP( psz_eltvalue );
+                FREE( psz_eltvalue );
+                break;
+        }
+    }
+
+    p_update->b_releases = VLC_TRUE;
+
+    error:
+        vlc_mutex_unlock( &p_update->lock );
+
+        free( psz_eltname );
+        free( psz_eltvalue );
+        free( psz_name );
+        free( psz_value );
+
+        free( tmp_release.psz_major );
+        free( tmp_release.psz_minor );
+        free( tmp_release.psz_revision );
+        free( tmp_release.psz_extra );
+        free( tmp_release.psz_svn_revision );
+
+        free( tmp_file.psz_md5 );
+        free( tmp_file.psz_url );
+        free( tmp_file.psz_description );
+
+        if( p_xml_reader && p_xml )
+            xml_ReaderDelete( p_xml, p_xml_reader );
+        if( p_stream )
+            stream_Delete( p_stream );
+        if( p_xml )
+            xml_Delete( p_xml );
+}
+
+/**
+ * Check for updates
+ *
+ * \param p_update pointer to update struct
+ * \param b_force set to VLC_TRUE if you want to force the update
+ * \returns nothing
+ */
+void update_Check( update_t *p_update, vlc_bool_t b_force )
+{
+    if( p_update == NULL ) return;
+    GetMirrorsList( p_update, b_force );
+    GetFilesList( p_update, b_force );
+}
+
+/**
+ * Compare two release numbers
+ * The comparision algorith basically performs an alphabetical order (strcmp)
+ * comparision of each of the version number elements until it finds two
+ * different ones. This is the tricky function.
+ *
+ * \param p1 first release
+ * \param p2 second release
+ * \return like strcmp
+ */
+int CompareReleases( struct update_release_t *p1, struct update_release_t *p2 )
+{
+    int d;
+    if( ( d = strcmp( p1->psz_major, p2->psz_major ) ) ) ;
+    else if( ( d = strcmp( p1->psz_minor, p2->psz_minor ) ) ) ;
+    else if( ( d = strcmp( p1->psz_revision, p2->psz_revision ) ) ) ;
+    else
+    {
+        d = strcmp( p1->psz_extra, p2->psz_extra );
+        if( d<0 )
+        {
+        /* FIXME:
+         * not num < NULL < num
+         * -test and -svn releases are thus always considered older than
+         * -'' or -0 releases, which is the best i could come up with */
+            char *psz_end1;
+            char *psz_end2;
+            strtol( p1->psz_extra, &psz_end1, 10 );
+            strtol( p2->psz_extra, &psz_end2, 10 );
+            if( psz_end2 == p2->psz_extra
+             && ( psz_end1 != p1->psz_extra || *p1->psz_extra == '\0' ) )
+                d = 1;
+        }
+    }
+    if( d < 0 )
+        return UPDATE_RELEASE_STATUS_OLDER;
+    else if( d == 0 )
+        return UPDATE_RELEASE_STATUS_EQUAL;
+    else
+        return UPDATE_RELEASE_STATUS_NEWER;
+}
+
+/**
+ * Compare a given release's version number to the current VLC's one
+ *
+ * \param p a release
+ * \return >0 if newer, 0 if equal and <0 if older
+ */
+int CompareReleaseToCurrent( struct update_release_t *p )
+{
+    struct update_release_t c = {0};
+    int r;
+    c.psz_major = STRDUP( PACKAGE_VERSION_MAJOR );
+    c.psz_minor = STRDUP( PACKAGE_VERSION_MINOR );
+    c.psz_revision = STRDUP( PACKAGE_VERSION_REVISION );
+    c.psz_extra = STRDUP( PACKAGE_VERSION_EXTRA );
+    r =  CompareReleases( p, &c );
+    free( c.psz_major );
+    free( c.psz_minor );
+    free( c.psz_revision );
+    free( c.psz_extra );
+    return r;
+}
+
+/*****************************************************************************
+ * Updatei_iterator_t functions
+ *****************************************************************************/
+
+/**
+ * Create a new update iterator structure. This structure can then be used to
+ * describe a position and move through the update and mirror trees/lists.
+ * This will use an existing update struct or create a new one if none is
+ * found
+ *
+ * \param p_u the calling update_t
+ * \return a pointer to an update iterator
+ */
+update_iterator_t *update_iterator_New( update_t *p_u )
+{
+    update_iterator_t *p_uit = NULL;
+
+    if( p_u == NULL )
+        return NULL;
+
+    p_uit = (update_iterator_t *)malloc( sizeof( update_iterator_t ) );
+    if( p_uit == NULL ) return NULL;
+
+    p_uit->p_u = p_u;
+
+    p_uit->i_m = -1;
+    p_uit->i_r = -1;
+    p_uit->i_f = -1;
+
+    p_uit->i_t = UPDATE_FILE_TYPE_ALL;
+    p_uit->i_rs = UPDATE_RELEASE_STATUS_ALL;
+    p_uit->i_rt = UPDATE_RELEASE_TYPE_STABLE;
+
+    p_uit->file.i_type = UPDATE_FILE_TYPE_NONE;
+    p_uit->file.psz_md5 = NULL;
+    p_uit->file.psz_url = NULL;
+    p_uit->file.l_size = 0;
+    p_uit->file.psz_description = NULL;
+
+    p_uit->release.psz_version = NULL;
+    p_uit->release.psz_svn_revision = NULL;
+    p_uit->release.i_type = UPDATE_RELEASE_TYPE_UNSTABLE;
+    p_uit->release.i_status = UPDATE_RELEASE_STATUS_NONE;
+
+    p_uit->mirror.psz_name = NULL;
+    p_uit->mirror.psz_location = NULL;
+    p_uit->mirror.psz_type = NULL;
+
+    return p_uit;
+}
+
+/**
+ * Delete an update iterator structure (duh!)
+ *
+ * \param p_uit pointer to an update iterator
+ * \return nothing
+ */
+void update_iterator_Delete( update_iterator_t *p_uit )
+{
+    if( !p_uit ) return;
+    update_iterator_ClearData( p_uit );
+    free( p_uit );
+}
+
+/**
+ * Reset an update_iterator_t structure
+ *
+ * \param p_uit pointer to an update iterator
+ * \return UPDATE_FAIL upon error, UPDATE_SUCCESS otherwise
+ */
+unsigned int update_iterator_Reset( update_iterator_t *p_uit )
+{
+    if( !p_uit ) return UPDATE_FAIL;
+
+    p_uit->i_r = -1;
+    p_uit->i_f = -1;
+    p_uit->i_m = -1;
+
+    update_iterator_ClearData( p_uit );
+    return UPDATE_SUCCESS;
+}
+
+/**
+ * Finds the next file in the update tree that matches status and type
+ * requirements set in the update_iterator
+ *
+ * \param p_uit update iterator
+ * \return UPDATE_FAIL if we can't find the next file, UPDATE_SUCCESS|UPDATE_FILE if we stay in the same release, UPDATE_SUCCESS|UPDATE_RELEASE|UPDATE_FILE if we change the release index
+ */
+unsigned int update_iterator_NextFile( update_iterator_t *p_uit )
+{
+    int r,f=-1,old_r;
+
+    if( !p_uit ) return UPDATE_FAIL;
+
+    old_r=p_uit->i_r;
+
+    /* if the update iterator was already in a "no match" state, start over */
+    if( p_uit->i_r == -1 ) p_uit->i_r = 0;
+    //if( p_uit->i_f == -1 ) p_uit->i_f = 0;
+
+    vlc_mutex_lock( &p_uit->p_u->lock );
+
+    for( r = p_uit->i_r; r < p_uit->p_u->i_releases; r++ )
+    {
+        if( !( p_uit->p_u->p_releases[r].i_status & p_uit->i_rs ) ) continue;
+        for( f = ( r == p_uit->i_r ? p_uit->i_f + 1 : 0 );
+             f < p_uit->p_u->p_releases[r].i_files; f++ )
+        {
+            if( p_uit->p_u->p_releases[r].p_files[f].i_type & p_uit->i_t )
+            {
+                goto done;/* "double break" */
+            }
+        }
+    }
+    done:
+    p_uit->i_r = r;
+    p_uit->i_f = f;
+
+    r = p_uit->p_u->i_releases;
+
+    if( old_r == p_uit->i_r )
+    {
+        update_iterator_GetData( p_uit );
+        vlc_mutex_unlock( &p_uit->p_u->lock );
+        return UPDATE_SUCCESS|UPDATE_FILE;
+    }
+    else if( p_uit->i_r == r )
+    {
+        p_uit->i_r = -1;
+        p_uit->i_f = -1;
+        update_iterator_GetData( p_uit );
+        vlc_mutex_unlock( &p_uit->p_u->lock );
+        return UPDATE_FAIL;
+    }
+    else
+    {
+        update_iterator_GetData( p_uit );
+        vlc_mutex_unlock( &p_uit->p_u->lock );
+        return UPDATE_SUCCESS|UPDATE_RELEASE|UPDATE_FILE;
+    }
+}
+
+/**
+ * Finds the previous file in the update tree that matches status and type
+ * requirements set in the update_iterator
+ *
+ * \param p_uit update iterator
+ * \return UPDATE_FAIL if we can't find the previous file, UPDATE_SUCCESS|UPDATE_FILE if we stay in the same release, UPDATE_SUCCESS|UPDATE_RELEASE|UPDATE_FILE if we change the release index
+ */
+//TODO: test
+unsigned int update_iterator_PrevFile( update_iterator_t *p_uit )
+{
+    int r,f=-1,old_r;
+
+    if( !p_uit ) return UPDATE_FAIL;
+
+    old_r=p_uit->i_r;
+
+    /* if the update iterator was already in a "no match" state, start over
+     * (begin at the end of the list) */
+    if( p_uit->i_r == -1 ) p_uit->i_r = p_uit->p_u->i_releases - 1;
+    p_uit->i_f = p_uit->p_u->p_releases[p_uit->i_r].i_files + 1;
+
+    vlc_mutex_lock( &p_uit->p_u->lock );
+
+    for( r = p_uit->i_r; r >= 0; r-- )
+    {
+        if( !( p_uit->p_u->p_releases[r].i_status & p_uit->i_rs ) ) continue;
+        for( f =( r==p_uit->i_r ? p_uit->i_f - 1 : p_uit->p_u->p_releases[r].i_files );
+             f >= 0; f-- )
+        {
+            if( p_uit->p_u->p_releases[r].p_files[f].i_type & p_uit->i_t )
+            {
+                goto done;/* "double break" */
+            }
+        }
+    }
+    done:
+    p_uit->i_r = r;
+    p_uit->i_f = f;
+
+    r = p_uit->p_u->i_releases;
+
+    if( old_r == p_uit->i_r )
+    {
+        update_iterator_GetData( p_uit );
+        vlc_mutex_unlock( &p_uit->p_u->lock );
+        return UPDATE_SUCCESS|UPDATE_FILE;
+    }
+    else if( p_uit->i_r == -1 )
+    {
+        p_uit->i_r = -1;
+        p_uit->i_f = -1;
+        update_iterator_GetData( p_uit );
+        vlc_mutex_unlock( &p_uit->p_u->lock );
+        return UPDATE_FAIL;
+    }
+    else
+    {
+        update_iterator_GetData( p_uit );
+        vlc_mutex_unlock( &p_uit->p_u->lock );
+        return UPDATE_SUCCESS|UPDATE_RELEASE|UPDATE_FILE;
+    }
+}
+
+/**
+ * Finds the next mirror in the update tree
+ *
+ * \param update iterator
+ * \return UPDATE_FAIL if we can't find the next mirror, UPDATE_SUCCESS|UPDATE_MIRROR otherwise
+ */
+unsigned int update_iterator_NextMirror( update_iterator_t *p_uit )
+{
+    if( !p_uit ) return UPDATE_FAIL;
+    vlc_mutex_lock( &p_uit->p_u->lock );
+    p_uit->i_m++;
+    if( p_uit->i_m >= p_uit->p_u->i_mirrors ) p_uit->i_m = -1;
+    update_iterator_GetData( p_uit );
+    vlc_mutex_unlock( &p_uit->p_u->lock );
+    return p_uit->i_m == -1 ? UPDATE_FAIL : UPDATE_SUCCESS|UPDATE_MIRROR;
+}
+
+/**
+ * Finds the previous mirror in the update tree
+ *
+ * \param update iterator
+ * \return UPDATE_FAIL if we can't find a previous mirror, UPDATE_SUCCESS|UPDATE_MIRROR otherwise
+ */
+unsigned int update_iterator_PrevMirror( update_iterator_t *p_uit )
+{
+    if( !p_uit ) return UPDATE_FAIL;
+    vlc_mutex_lock( &p_uit->p_u->lock );
+    p_uit->i_m--;
+    update_iterator_GetData( p_uit );
+    vlc_mutex_unlock( &p_uit->p_u->lock );
+    return p_uit->i_m == -1 ? UPDATE_FAIL : UPDATE_SUCCESS|UPDATE_MIRROR;
+}
+
+/**
+ * Change the update iterator's position in the file and mirrors tree
+ * If position is negative, don't change it
+ *
+ * \param i_m position in mirrors list
+ * \param i_r position in releases list
+ * \param i_f position in release's files list
+ * \return UPDATE_FAIL when changing position fails or position wasn't changed, a combination of UPDATE_MIRROR, UPDATE_RELEASE and UPDATE_FILE otherwise
+ */
+unsigned int update_iterator_ChooseMirrorAndFile( update_iterator_t *p_uit,
+                                        int i_m, int i_r, int i_f )
+{
+    unsigned int i_val = 0;
+
+    if( !p_uit ) return 0;
+    vlc_mutex_lock( &p_uit->p_u->lock );
+
+    if( i_m >= 0 )
+    {
+        if( i_m < p_uit->p_u->i_mirrors )
+        {
+            if( i_m != p_uit->i_m )
+                i_val |= UPDATE_MIRROR;
+            p_uit->i_m = i_m;
+        }
+        else i_m = -1;
+    }
+
+    if( i_r >= 0 )
+    {
+        if( i_r < p_uit->p_u->i_releases )
+        {
+            if( i_r != p_uit->i_r )
+                i_val |= UPDATE_FILE;
+            p_uit->i_r = i_r;
+        }
+        else i_r = -1;
+    }
+
+    if( i_f >= 0 )
+    {
+        if( i_r >= 0 && i_r < p_uit->p_u->i_releases
+            && i_f < p_uit->p_u->p_releases[p_uit->i_r].i_files )
+        {
+            if( i_f != p_uit->i_f )
+                i_val |= UPDATE_FILE;
+            p_uit->i_f = i_f;
+        }
+        else i_f = -1;
+    }
+
+    update_iterator_GetData( p_uit );
+    vlc_mutex_unlock( &p_uit->p_u->lock );
+
+    if(    ( i_m < 0 || p_uit->i_m >= 0 )
+        && ( i_r < 0 || p_uit->i_r >= 0 )
+        && ( i_f < 0 || p_uit->i_f >= 0 ) )
+    {
+        /* Everything worked */
+        return UPDATE_SUCCESS|i_val;
+    }
+    else
+    {
+        /* Something failed */
+        return UPDATE_FAIL;
+    }
+}
+
+/**
+ * Fills the iterator data (file, release and mirror structs)
+ * The update struct should be locked before calling this function.
+ *
+ * \param p_uit update iterator
+ * \return nothing
+ */
+void update_iterator_GetData( update_iterator_t *p_uit )
+{
+    struct update_release_t *p_r = NULL;
+    struct update_file_t *p_f = NULL;
+    struct update_mirror_t *p_m = NULL;
+
+    update_iterator_ClearData( p_uit );
+
+    if( p_uit->i_m >= 0 )
+    {
+        p_m = p_uit->p_u->p_mirrors + p_uit->i_m;
+        p_uit->mirror.psz_name = STRDUP( p_m->psz_name );
+        p_uit->mirror.psz_location = STRDUP( p_m->psz_location );
+        p_uit->mirror.psz_type = STRDUP( p_m->psz_type );
+    }
+
+    if( p_uit->i_r >= 0 )
+    {
+        p_r = p_uit->p_u->p_releases + p_uit->i_r;
+        asprintf( &p_uit->release.psz_version, "%s.%s.%s-%s",
+                                              p_r->psz_major,
+                                              p_r->psz_minor,
+                                              p_r->psz_revision,
+                                              p_r->psz_extra );
+        p_uit->release.psz_svn_revision = STRDUP( p_r->psz_svn_revision );
+        p_uit->release.i_type = p_r->i_type;
+        p_uit->release.i_status = p_r->i_status;
+        if( p_uit->i_f >= 0 )
+        {
+            p_f = p_r->p_files + p_uit->i_f;
+            p_uit->file.i_type = p_f->i_type;
+            p_uit->file.psz_md5 = STRDUP( p_f->psz_md5 );
+            p_uit->file.l_size = p_f->l_size;
+            p_uit->file.psz_description = STRDUP( p_f->psz_description);
+            if( p_f->psz_url[0] == '/' )
+            {
+                if( p_m )
+                {
+                    asprintf( &p_uit->file.psz_url, "%s%s",
+                              p_m->psz_base_url, p_f->psz_url );
+                }
+            }
+            else
+            {
+                p_uit->file.psz_url = STRDUP( p_f->psz_url );
+            }
+        }
+    }
+}
+
+/**
+ * Clears the iterator data (file, release and mirror structs)
+ *
+ * \param p_uit update iterator
+ * \return nothing
+ */
+void update_iterator_ClearData( update_iterator_t *p_uit )
+{
+    p_uit->file.i_type = UPDATE_FILE_TYPE_NONE;
+    FREE( p_uit->file.psz_md5 );
+    p_uit->file.l_size = 0;
+    FREE( p_uit->file.psz_description );
+    FREE( p_uit->file.psz_url );
+    FREE( p_uit->release.psz_version );
+    FREE( p_uit->release.psz_svn_revision );
+    p_uit->release.i_type = UPDATE_RELEASE_TYPE_UNSTABLE;
+    p_uit->release.i_status = UPDATE_RELEASE_STATUS_NONE;
+    FREE( p_uit->mirror.psz_name );
+    FREE( p_uit->mirror.psz_location );
+    FREE( p_uit->mirror.psz_type );
+}
+
+/**
+ * Perform an action on the update iterator
+ * Only the first matching action is performed.
+ *
+ * \param p_uit update iterator
+ * \param i_action update action bitmask. can be a combination of UPDATE_NEXT, UPDATE_PREV, UPDATE_MIRROR, UPDATE_RELEASE, UPDATE_FILE, UPDATE_RESET
+ * \return UPDATE_FAIL if action fails, UPDATE_SUCCESS|(combination of UPDATE_MIRROR, UPDATE_RELEASE and UPDATE_FILE if these changed) otherwise
+ */
+unsigned int update_iterator_Action( update_iterator_t *p_uit, int i_action )
+{
+    if( i_action & UPDATE_RESET )
+    {
+        return update_iterator_Reset( p_uit );
+    }
+    else
+    if( i_action & UPDATE_MIRROR )
+    {
+        if( i_action & UPDATE_PREV )
+        {
+            return update_iterator_PrevMirror( p_uit );
+        }
+        else
+        {
+            return update_iterator_NextMirror( p_uit );
+        }
+    }
+    /*else if( i_action & UPDATE_RELEASE )
+    {
+        if( i_action & UPDATE_PREV )
+        {
+            return update_iterator_PrevRelease( p_uit );
+        }
+        else
+        {
+            return update_iterator_NextRelease( p_uit );
+        }
+    }*/
+    else if( i_action & UPDATE_FILE )
+    {
+        if( i_action & UPDATE_PREV )
+        {
+            return update_iterator_PrevFile( p_uit );
+        }
+        else
+        {
+            return update_iterator_NextFile( p_uit );
+        }
+    }
+    else
+    {
+        return UPDATE_SUCCESS;
+    }
+}
+
+/**
+ * Download the file selected by the update iterator
+ *
+ * \param p_uit update iterator
+ * \param psz_dest destination file path
+ * \return nothing
+ */
+void update_download( update_iterator_t *p_uit, char *psz_dest )
+{
+    char *psz_src = p_uit->file.psz_url;
+    stream_t *p_stream;
+    vlc_t *p_vlc = p_uit->p_u->p_vlc;
+
+    FILE *p_file = NULL;
+    void *p_buffer;
+
+    char *psz_status;
+
+    int i_progress;
+    int i_size;
+    int i_done = 0;
+
+    p_stream = stream_UrlNew( p_vlc, psz_src );
+    if( !p_stream )
+    {
+        msg_Err( p_vlc, "Failed to open %s for reading", psz_src );
+        return;
+    }
+
+    p_file = fopen( psz_dest, "w" );
+    if( !p_file )
+    {
+        msg_Err( p_vlc, "Failed to open %s for writing", psz_dest );
+        return;
+    }
+
+    i_size = (int)(stream_Size(p_stream)/(1<<10));
+    p_buffer = (void *)malloc( 1<<10 );
+
+    asprintf( &psz_status,
+              "%s - %s (%s)\n"
+              "Source: %s\n"
+              "Destination: %s\n"
+              "Downloading... %.1f%% done",
+              p_uit->file.psz_description, p_uit->release.psz_version,
+              p_uit->release.psz_svn_revision, p_uit->file.psz_url,
+              psz_dest, 0.0 );
+    i_progress = intf_UserProgress( p_vlc, "Downloading...", psz_status, 0.0 );
+
+    while( stream_Read( p_stream, p_buffer, 1<<10 ) )
+    {
+        float f_progress;
+
+        fwrite( p_buffer, 1<<10, 1, p_file );
+
+        i_done++;
+        free( psz_status );
+        f_progress = 100.0*(float)i_done/(float)i_size;
+        asprintf( &psz_status,
+                  "%s - %s (%s)\n"
+                  "Source: %s\n"
+                  "Destination: %s\n"
+                  "Downloading... %.1f%% done",
+                  p_uit->file.psz_description, p_uit->release.psz_version,
+                  p_uit->release.psz_svn_revision, p_uit->file.psz_url,
+                  psz_dest, f_progress );
+        intf_UserProgressUpdate( p_vlc, i_progress, psz_status, f_progress );
+    }
+
+    free( p_buffer );
+    free( psz_status );
+    fclose( p_file );
+    stream_Delete( p_stream );
+}