Commit bcf42772 authored by Antoine Cellerier's avatar Antoine Cellerier

src/*, include/* : update core functions. (Should make it relatively easy

                   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.
parent 67d1feb2
......@@ -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 \
......
......@@ -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
......
......@@ -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; \
......
/*****************************************************************************
* 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
......@@ -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 *,
......@@ -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"));
......@@ -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 );
}
/* 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 +.@.- - - - - - - - - - - - - ",
" ",
" "};
/* 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 - ",
" %@&@*@=@-@;@>@,@'@)@- - - - - - - - - - - - - - ",
" ",
" "};
/* 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 +.%.&.*.=.- - - - - - - - - - - - - ",
" ",
" "};
/* 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+- - - - - - - - - - - - - ",
" ",
" "};
/* 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.- - - - - - - - - - - - - ",
" ",
" "};
......@@ -25,46 +25,21 @@
* 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,605 +69,159 @@ 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");
update_Delete( p_u );
}
/* 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()
void UpdateVLC::OnButtonClose( wxCommandEvent& event )
{
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;
}
wxCloseEvent cevent;
OnClose(cevent);
}
/* empty tree */
m_versions.clear();
void UpdateVLC::OnClose( wxCloseEvent& WXUNUSED(event) )
{
Hide();
}
/* build tree */
while( xml_ReaderRead( p_xml_reader ) == 1 )
{
switch( xml_ReaderNodeType( p_xml_reader ) )
void UpdateVLC::OnCheckForUpdate( wxCommandEvent& event )
{
update_Check( p_u, VLC_FALSE );
update_iterator_t *p_uit = update_iterator_New( p_u );
if( p_uit )
{
// Error
case -1:
// TODO : print message
return;
wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
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 )
{
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 )
{
/*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;
}
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 );
case UPDATE_FILE_TYPE_SOURCE:
i_image = 2;
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 );
case UPDATE_FILE_TYPE_BINARY:
i_image = 3;
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 );
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 );
}
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;
}
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 );
}
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()
class DownloadThread : public wxThread
{
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) ) ) ) ) ) )
public:
DownloadThread( update_iterator_t *p_uit, char *psz_dest )
:p_uit( p_uit ),psz_dest( psz_dest )
{
/* version is older or equal tu current version.
FIXME : how do we handle the extra version number ? */
it++;
continue;
Create();
Run();
}
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() )
ExitCode Entry()
{
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_download( p_uit, psz_dest );
update_iterator_Delete( p_uit );
LocaleFree( psz_dest );
return 0;
};
update_iterator_t *p_uit;
char *psz_dest;
};
void UpdateVLC::UpdateMirrorsChoice()
void UpdateVLC::OnChooseItem( wxListEvent& event )
{
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() )
update_iterator_t *p_uit = update_iterator_New( p_u );
if( p_uit )
{
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;
OnClose(cevent);
}
p_uit->i_rs = UPDATE_RELEASE_STATUS_NEWER;
p_uit->i_t = UPDATE_FILE_TYPE_ALL;
update_iterator_Action( p_uit, UPDATE_MIRROR );
void UpdateVLC::OnClose( wxCloseEvent& WXUNUSED(event) )
{
Hide();
}
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 )
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( updates_tree, wxU(_("Save file ...")),
new wxFileDialog( this, wxU(_("Save file ...")),
wxT(""), url.AfterLast( '/' ), wxT("*.*"),
wxSAVE | wxOVERWRITE_PROMPT );
if( filedialog->ShowModal() == wxID_OK )
{
DownloadFile( url, filedialog->GetPath() );
}
}
}
void UpdateVLC::DownloadFile( wxString url, wxString dst )
{
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 )
{
msg_Err( p_intf, "Failed to open %s for reading", (const char *)url.mb_str() );
// FIXME : display error message in dialog
return;
}
char *psz_dest = ToLocale( filedialog->GetPath().mb_str() );
FILE *p_file = NULL;
p_file = fopen( psz_local, "w" );
if( !p_file )
{
msg_Err( p_intf, "Failed to open %s for writing", psz_local );
// FIXME : display error message in dialog
return;
/* Launch the download process in a new thread so it doesn't
* block the interface */
new DownloadThread( p_uit, psz_dest );
}
LocaleFree( psz_local );
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 );
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) )
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 );
}
......@@ -24,9 +24,10 @@
#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;
};
};
......
......@@ -109,6 +109,8 @@
#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 )
......
/*****************************************************************************
* 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 );
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment