]> git.sesse.net Git - vlc/commitdiff
VLC update checker in the wxWidgets interface (in help menu)
authorAntoine Cellerier <dionoea@videolan.org>
Sun, 24 Jul 2005 21:03:20 +0000 (21:03 +0000)
committerAntoine Cellerier <dionoea@videolan.org>
Sun, 24 Jul 2005 21:03:20 +0000 (21:03 +0000)
xml files used for the updates are located at http://update.videolan.org

extensive testing ... code cleaning ... would be greatly appreciated

include/vlc_interface.h
modules/gui/wxwindows/Modules.am
modules/gui/wxwindows/dialogs.cpp
modules/gui/wxwindows/interface.cpp
modules/gui/wxwindows/updatevlc.cpp [new file with mode: 0644]
modules/gui/wxwindows/wxwindows.h

index 1a29d578534eab3821faef3e4651c1e10ca87e3e..556c1719e099846c006b182bc3a0d125ec31bae5 100644 (file)
@@ -157,6 +157,8 @@ VLC_EXPORT( void,              intf_Destroy,    ( intf_thread_t * ) );
 
 #define INTF_DIALOG_FILE_GENERIC 30
 
+#define INTF_DIALOG_UPDATEVLC   90
+
 #define INTF_DIALOG_EXIT       99
 
 /* Useful text messages shared by interfaces */
index de182917ee85358c9f463b5f5b64bd95a1cc18ee..7492d813bb5841a4940857a3d6c1f452520e4e40 100644 (file)
@@ -17,6 +17,7 @@ SOURCES_wxwindows = \
        preferences_widgets.h \
        timer.cpp \
        fileinfo.cpp \
+       updatevlc.cpp \
        subtitles.cpp \
        bookmarks.cpp \
        video.cpp \
index aee8b3282b141541e980dd1cd4674094d7daac56..287ea43bf18b774a03209cdfe24c3306a8f3ca70 100644 (file)
@@ -50,6 +50,7 @@ private:
     void Open( int i_access_method, int i_arg );
 
     /* Event handlers (these functions should _not_ be virtual) */
+    void OnUpdateVLC( wxCommandEvent& event );
     void OnExit( wxCommandEvent& event );
     void OnPlaylist( wxCommandEvent& event );
     void OnMessages( wxCommandEvent& event );
@@ -89,6 +90,7 @@ public:
     wxFrame             *p_prefs_dialog;
     wxWindow            *p_bookmarks_dialog;
     wxFileDialog        *p_file_generic_dialog;
+    UpdateVLC           *p_updatevlc_dialog;
 };
 
 DEFINE_LOCAL_EVENT_TYPE( wxEVT_DIALOG );
@@ -126,6 +128,8 @@ BEGIN_EVENT_TABLE(DialogsProvider, wxFrame)
                 DialogsProvider::OnPopupMenu)
     EVT_COMMAND(INTF_DIALOG_EXIT, wxEVT_DIALOG,
                 DialogsProvider::OnExitThread)
+    EVT_COMMAND(INTF_DIALOG_UPDATEVLC, wxEVT_DIALOG,
+                DialogsProvider::OnUpdateVLC)
 END_EVENT_TABLE()
 
 wxWindow *CreateDialogsProvider( intf_thread_t *p_intf, wxWindow *p_parent )
@@ -151,6 +155,7 @@ DialogsProvider::DialogsProvider( intf_thread_t *_p_intf, wxWindow *p_parent )
     p_wizard_dialog = NULL;
     p_bookmarks_dialog = NULL;
     p_dir_dialog = NULL;
+    p_updatevlc_dialog = NULL;
 
     /* Give our interface a nice little icon */
     p_intf->p_sys->p_icon = new wxIcon( vlc_xpm );
@@ -219,6 +224,7 @@ DialogsProvider::~DialogsProvider()
     if( p_file_generic_dialog ) delete p_file_generic_dialog;
     if( p_wizard_dialog ) delete p_wizard_dialog;
     if( p_bookmarks_dialog ) delete p_bookmarks_dialog;
+    if( p_updatevlc_dialog ) delete p_updatevlc_dialog;
 
 
     if( p_intf->p_sys->p_icon ) delete p_intf->p_sys->p_icon;
@@ -479,3 +485,15 @@ void DialogsProvider::OnExitThread( wxCommandEvent& WXUNUSED(event) )
 {
     wxTheApp->ExitMainLoop();
 }
+
+void DialogsProvider::OnUpdateVLC( wxCommandEvent& WXUNUSED(event) )
+{
+    /* Show/hide the file info window */
+    if( !p_updatevlc_dialog )
+        p_updatevlc_dialog = new UpdateVLC( p_intf, this );
+
+    if( p_updatevlc_dialog )
+    {
+        p_updatevlc_dialog->Show( !p_updatevlc_dialog->IsShown() );
+    }
+}
index a1ca67beebfae28efb0674da97fc2f4b62e3af1a..378dbb8f34311239b504ad7a6540b4e11aade9a5 100644 (file)
@@ -156,6 +156,7 @@ enum
      * this standard value as otherwise it won't be handled properly under Mac
      * (where it is special and put into the "Apple" menu) */
     About_Event = wxID_ABOUT,
+    UpdateVLC_Event,
 
     Iconize_Event
 };
@@ -164,6 +165,7 @@ BEGIN_EVENT_TABLE(Interface, wxFrame)
     /* Menu events */
     EVT_MENU(Exit_Event, Interface::OnExit)
     EVT_MENU(About_Event, Interface::OnAbout)
+    EVT_MENU(UpdateVLC_Event, Interface::OnShowDialog)
 
     EVT_MENU(Playlist_Event, Interface::OnShowDialog)
     EVT_MENU(Logs_Event, Interface::OnShowDialog)
@@ -432,6 +434,8 @@ void Interface::CreateOurMenuBar()
     /* Create the "Help" menu */
     wxMenu *help_menu = new wxMenu;
     help_menu->Append( About_Event, wxU(_("About VLC media player")) );
+    help_menu->AppendSeparator();
+    help_menu->Append( UpdateVLC_Event, wxU(_("Check for updates ...")) );
 
     /* Append the freshly created menus to the menu bar... */
     wxMenuBar *menubar = new wxMenuBar();
@@ -913,6 +917,9 @@ void Interface::OnShowDialog( wxCommandEvent& event )
         case Bookmarks_Event:
             i_id = INTF_DIALOG_BOOKMARKS;
             break;
+        case UpdateVLC_Event:
+            i_id = INTF_DIALOG_UPDATEVLC;
+            break;
         default:
             i_id = INTF_DIALOG_FILE;
             break;
diff --git a/modules/gui/wxwindows/updatevlc.cpp b/modules/gui/wxwindows/updatevlc.cpp
new file mode 100644 (file)
index 0000000..b2184a8
--- /dev/null
@@ -0,0 +1,647 @@
+/*****************************************************************************
+ * updatevlc.cpp : Check for VLC updates dialog
+ *****************************************************************************
+ * Copyright (C) 2000-2004 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Antoine Cellerier <dionoea@videolan.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 version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+#include <wx/progdlg.h>
+
+#include "wxwindows.h"
+
+#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 SYS_DARWIN
+#   define UPDATE_VLC_OS "macosx"
+#   define UPDATE_VLC_ARCH "ppc"
+#else
+#   define UPDATE_VLC_OS "windows"
+#   define UPDATE_VLC_ARCH "i386"
+#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.
+ *****************************************************************************/
+
+/* IDs for the controls and the menu commands */
+enum
+{
+    Close_Event,
+    CheckForUpdate_Event,
+    MirrorChoice_Event,
+    UpdatesTreeActivate_Event
+};
+
+BEGIN_EVENT_TABLE(UpdateVLC, wxFrame)
+    /* Button events */
+    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)
+
+    /* Hide the window when the user closes the window */
+    EVT_CLOSE(UpdateVLC::OnClose)
+
+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 )
+{
+    /* Initializations */
+    p_intf = _p_intf;
+    release_type = wxT( "stable" );
+    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 );
+
+    /* 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, 0, wxGROW | wxALL, 5 );
+    wxButton *update_button =
+        new wxButton( panel, CheckForUpdate_Event,
+                      wxU(_("Check for updates now !")) );
+    subpanel_sizer->Add( update_button, 0, wxALL, 5 );
+    wxArrayString *choices_array = new wxArrayString();
+    choices_array->Add( wxT("") );
+    mirrors_choice =
+        new wxChoice( panel, MirrorChoice_Event, wxDefaultPosition,
+                      wxSize( 200, -1 ), *choices_array );
+    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, 0, wxALL | wxGROW, 0 );
+    main_sizer->Layout();
+    SetSizerAndFit( main_sizer );
+
+    UpdateMirrorsChoice();
+    UpdateUpdatesTree();
+}
+
+
+UpdateVLC::~UpdateVLC()
+{
+}
+
+/* this function gets all the info from the xml files hosted on
+http://update.videolan.org/ and stores it in appropriate lists */
+void UpdateVLC::GetData()
+{
+    stream_t *p_stream = NULL;
+    char *psz_eltname = NULL;
+    char *psz_name = NULL;
+    char *psz_value = NULL;
+    char *psz_eltvalue = NULL;
+    xml_t *p_xml = NULL;
+    xml_reader_t *p_xml_reader = NULL;
+    bool b_os = false;
+    bool b_arch = false;
+
+    struct update_file_t tmp_file;
+    struct update_version_t tmp_version;
+    std::list<update_version_t>::iterator it;
+    std::list<update_file_t>::iterator it_files;
+
+    struct update_mirror_t tmp_mirror;
+
+    p_xml = xml_Create( p_intf );
+    if( !p_xml )
+    {
+        msg_Err( p_intf, "Failed to open XML parser" );
+        // FIXME : display error message in dialog
+        return;
+    }
+
+    p_stream = stream_UrlNew( p_intf, UPDATE_VLC_STATUS_URL );
+    if( !p_stream )
+    {
+        msg_Err( p_intf, "Failed to open %s for reading",
+                 UPDATE_VLC_STATUS_URL );
+        // FIXME : display error message in dialog
+        return;
+    }
+
+    p_xml_reader = xml_ReaderCreate( p_xml, p_stream );
+
+    if( !p_xml_reader )
+    {
+        msg_Err( p_intf, "Failed to open %s for parsing",
+                 UPDATE_VLC_STATUS_URL );
+        // FIXME : display error message in dialog
+        return;
+    }
+
+    /* empty tree */
+    m_versions.clear();
+
+    /* build tree */
+    while( xml_ReaderRead( p_xml_reader ) == 1 )
+    {
+        switch( xml_ReaderNodeType( p_xml_reader ) )
+        {
+            // Error
+            case -1:
+                // TODO : print message
+                return;
+
+            case XML_READER_STARTELEM:
+                psz_eltname = xml_ReaderName( p_xml_reader );
+                if( !psz_eltname )
+                {
+                    // TODO : print message
+                    return;
+                }
+                msg_Dbg( p_intf, "element name : %s", psz_eltname );
+                while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
+                {
+                    psz_name = xml_ReaderName( p_xml_reader );
+                    psz_value = xml_ReaderValue( p_xml_reader );
+                    if( !psz_name || !psz_value )
+                    {
+                        // TODO : print message
+                        free( psz_eltname );
+                        return;
+                    }
+                    msg_Dbg( p_intf, "  attribute %s = %s",
+                             psz_name, psz_value );
+                    if( b_os && b_arch )
+                    {
+                        if( strcmp( psz_eltname, "version" ) == 0 )
+                        {
+                            if( !strcmp( psz_name, "type" ) )
+                                tmp_version.type = wxU( psz_value );
+                            if( !strcmp( psz_name, "major" ) )
+                                tmp_version.major = wxU( psz_value );
+                            if( !strcmp( psz_name, "minor" ) )
+                                tmp_version.minor = wxU( psz_value );
+                            if( !strcmp( psz_name, "revision" ) )
+                                tmp_version.revision = wxU( psz_value );
+                            if( !strcmp( psz_name, "extra" ) )
+                                tmp_version.extra = wxU( psz_value );
+                        }
+                        if( !strcmp( psz_eltname, "file" ) )
+                        {
+                            if( !strcmp( psz_name, "type" ) )
+                                tmp_file.type = wxU( psz_value );
+                            if( !strcmp( psz_name, "md5" ) )
+                                tmp_file.md5 = wxU( psz_value );
+                            if( !strcmp( psz_name, "size" ) )
+                                tmp_file.size = wxU( psz_value );
+                            if( !strcmp( psz_name, "url" ) )
+                                tmp_file.url = wxU( psz_value );
+                            if( !strcmp( psz_name, "desciption" ) )
+                                tmp_file.description = wxU( psz_value );
+                        }
+                    }
+                    if( !strcmp( psz_name, "name" )
+                        && ( !strcmp( psz_value, UPDATE_VLC_OS )
+                           || !strcmp( psz_value, "*" ) )
+                        && !strcmp( psz_eltname, "os" ) )
+                    {
+                        b_os = true;
+                    }
+                    if( b_os && !strcmp( psz_name, "name" )
+                        && ( !strcmp( psz_value, UPDATE_VLC_ARCH )
+                           || !strcmp( psz_value, "*" ) )
+                        && !strcmp( psz_eltname, "arch" ) )
+                    {
+                        b_arch = true;
+                    }
+                    free( psz_name );
+                    free( psz_value );
+                }
+                if( ( b_os && b_arch && strcmp( psz_eltname, "arch" ) ) )
+                {
+                    if( !strcmp( psz_eltname, "version" ) )
+                    {
+                        it = m_versions.begin();
+                        while( it != m_versions.end() )
+                        {
+                            if( it->type == tmp_version.type
+                                && it->major == tmp_version.major
+                                && it->minor == tmp_version.minor
+                                && it->revision == tmp_version.revision
+                                && it->extra == tmp_version.extra )
+                            {
+                                break;
+                            }
+                            it++;
+                        }
+                        if( it == m_versions.end() )
+                        {
+                            m_versions.push_back( tmp_version );
+                            it = m_versions.begin();
+                            while( it != m_versions.end() )
+                            {
+                                if( it->type == tmp_version.type
+                                    && it->major == tmp_version.major
+                                    && it->minor == tmp_version.minor
+                                    && it->revision == tmp_version.revision
+                                    && it->extra == tmp_version.extra )
+                                {
+                                    break;
+                                }
+                                it++;
+                            }
+                        }
+                        tmp_version.type = wxT( "" );
+                        tmp_version.major = wxT( "" );
+                        tmp_version.minor = wxT( "" );
+                        tmp_version.revision = wxT( "" );
+                        tmp_version.extra = wxT( "" );
+                    }
+                    if( !strcmp( psz_eltname, "file" ) )
+                    {
+                        it->m_files.push_back( tmp_file );
+                        tmp_file.type = wxT( "" );
+                        tmp_file.md5 = wxT( "" );
+                        tmp_file.size = wxT( "" );
+                        tmp_file.url = wxT( "" );
+                        tmp_file.description = wxT( "" );
+                    }
+                }
+                free( psz_eltname );
+                break;
+
+            case XML_READER_ENDELEM:
+                psz_eltname = xml_ReaderName( p_xml_reader );
+                if( !psz_eltname )
+                {
+                    // TODO : print message
+                    return;
+                }
+                msg_Dbg( p_intf, "element end : %s", psz_eltname );
+                if( !strcmp( psz_eltname, "os" ) )
+                    b_os = false;
+                if( !strcmp( psz_eltname, "arch" ) )
+                    b_arch = false;
+                free( psz_eltname );
+                break;
+
+            case XML_READER_TEXT:
+                psz_eltvalue = xml_ReaderValue( p_xml_reader );
+                msg_Dbg( p_intf, "  text : %s", psz_eltvalue );
+                /* This doesn't look safe ... but it works */
+                it->m_files.back().description = wxU( psz_eltvalue );
+                free( psz_eltvalue );
+                break;
+        }
+    }
+
+    if( p_xml_reader && p_xml ) xml_ReaderDelete( p_xml, p_xml_reader );
+    if( p_stream ) stream_Delete( p_stream );
+
+    p_stream = stream_UrlNew( p_intf, UPDATE_VLC_MIRRORS_URL );
+    if( !p_stream )
+    {
+        msg_Err( p_intf, "Failed to open %s for reading",
+                 UPDATE_VLC_MIRRORS_URL );
+        // FIXME : display error message in dialog
+        return;
+    }
+
+    p_xml_reader = xml_ReaderCreate( p_xml, p_stream );
+
+    if( !p_xml_reader )
+    {
+        msg_Err( p_intf, "Failed to open %s for parsing",
+                 UPDATE_VLC_MIRRORS_URL );
+        // FIXME : display error message in dialog
+        return;
+    }
+    /* empty list */
+    m_mirrors.clear();
+
+    /* build list */
+    while( xml_ReaderRead( p_xml_reader ) == 1 )
+    {
+        switch( xml_ReaderNodeType( p_xml_reader ) )
+        {
+            // Error
+            case -1:
+                // TODO : print message
+                return;
+
+            case XML_READER_STARTELEM:
+                psz_eltname = xml_ReaderName( p_xml_reader );
+                if( !psz_eltname )
+                {
+                    // TODO : print message
+                    return;
+                }
+                msg_Dbg( p_intf, "element name : %s", psz_eltname );
+                while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
+                {
+                    psz_name = xml_ReaderName( p_xml_reader );
+                    psz_value = xml_ReaderValue( p_xml_reader );
+                    if( !psz_name || !psz_value )
+                    {
+                        // TODO : print message
+                        free( psz_eltname );
+                        return;
+                    }
+                    msg_Dbg( p_intf, "  attribute %s = %s",
+                             psz_name, psz_value );
+                    if( !strcmp( psz_eltname, "mirror" ) )
+                    {
+                        if( !strcmp( psz_name, "name" ) )
+                            tmp_mirror.name = wxU( psz_value );
+                        if( !strcmp( psz_name, "location" ) )
+                            tmp_mirror.location = wxU( psz_value );
+                    }
+                    if( !strcmp( psz_eltname, "url" ) )
+                    {
+                        if( !strcmp( psz_name, "type" ) )
+                            tmp_mirror.type = wxU( psz_value );
+                        if( !strcmp( psz_name, "base" ) )
+                            tmp_mirror.base_url = wxU( psz_value );
+                    }
+                    free( psz_name );
+                    free( psz_value );
+                }
+                if( !strcmp( psz_eltname, "url" ) )
+                {
+                    m_mirrors.push_back( tmp_mirror );
+                    tmp_mirror.type = wxT( "" );
+                    tmp_mirror.base_url = wxT( "" );
+                }
+                free( psz_eltname );
+                break;
+
+            case XML_READER_ENDELEM:
+                psz_eltname = xml_ReaderName( p_xml_reader );
+                if( !psz_eltname )
+                {
+                    // TODO : print message
+                    return;
+                }
+                msg_Dbg( p_intf, "element end : %s", psz_eltname );
+                if( !strcmp( psz_eltname, "mirror" ) )
+                {
+                    tmp_mirror.name = wxT( "" );
+                    tmp_mirror.location = wxT( "" );
+                }
+                free( psz_eltname );
+                break;
+
+            case XML_READER_TEXT:
+                psz_eltvalue = xml_ReaderValue( p_xml_reader );
+                msg_Dbg( p_intf, "  text : %s", psz_eltvalue );
+                free( psz_eltvalue );
+                break;
+        }
+    }
+
+
+    if( p_xml_reader && p_xml ) xml_ReaderDelete( p_xml, p_xml_reader );
+    if( p_stream ) stream_Delete( p_stream );
+    if( p_xml ) xml_Delete( p_xml );
+}
+
+void UpdateVLC::UpdateUpdatesTree()
+{
+    wxTreeItemId parent;
+    std::list<update_version_t>::iterator it;
+    std::list<update_file_t>::iterator it_files;
+    std::list<update_mirror_t>::iterator it_mirrors;
+
+    int selection = mirrors_choice->GetSelection();
+    wxString base_url = wxT( "" );
+
+    if( selection-- )
+    {
+        it_mirrors = m_mirrors.begin();
+        while( it_mirrors != m_mirrors.end() && selection )
+        {
+            it_mirrors++;
+            selection--;
+        }
+        if( it_mirrors != m_mirrors.end() ) base_url = it_mirrors->base_url;
+    }
+
+    /* empty tree */
+    updates_tree->DeleteAllItems();
+
+    /* build tree */
+    parent = updates_tree->AppendItem( updates_root, wxT( "" ) );
+    updates_tree->AppendItem( parent,
+                             wxT( "Current version : "PACKAGE_VERSION ),
+                             -1, -1, new UpdatesTreeItem( wxT( "" ) ));
+    it = m_versions.begin();
+    while( it != m_versions.end() )
+    {
+        wxTreeItemId cat = updates_tree->AppendItem( parent,
+                         wxT("VLC media player ")+ it->major + wxT(".")
+                         + it->minor + wxT(".") + it->revision + wxT("-")
+                         + it->extra + wxT(" (") + it->type + wxT(")"),
+                         -1, -1, new UpdatesTreeItem( wxT( "" ) ));
+        it_files = it->m_files.begin();
+        while( it_files != it->m_files.end() )
+        {
+            wxString url = (it_files->url[0]=='/' ? base_url : wxT( "" ) )
+                           + it_files->url;
+            wxTreeItemId file =
+                updates_tree->AppendItem( cat, it_files->description,
+                   -1, -1, new UpdatesTreeItem( url ) );
+            updates_tree->AppendItem( file,
+                wxU(_("type : ")) + it_files->type,
+                -1, -1, new UpdatesTreeItem( url ));
+            updates_tree->AppendItem( file, wxU(_("URL : ")) + url,
+                                      -1, -1, new UpdatesTreeItem( url ));
+            if( it_files->size != wxT( "" ) )
+                updates_tree->AppendItem( file,
+                    wxU(_("file size : ")) + it_files->size,
+                    -1, -1, new UpdatesTreeItem( url ));
+            if( it_files->md5 != wxT( "" ) )
+                updates_tree->AppendItem( file,
+                    wxU(_("file md5 hash : ")) + it_files->md5,
+                    -1, -1, new UpdatesTreeItem( url ));
+            it_files ++;
+        }
+        it ++;
+        updates_tree->Expand( cat );
+    }
+}
+
+void UpdateVLC::UpdateMirrorsChoice()
+{
+    std::list<update_mirror_t>::iterator it_mirrors;
+
+    mirrors_choice->Clear();
+    mirrors_choice->Append( wxU(_("Choose a mirror")) );
+    it_mirrors = m_mirrors.begin();
+    while( it_mirrors != m_mirrors.end() )
+    {
+        mirrors_choice->Append( it_mirrors->name + wxT(" (")
+                                + it_mirrors->location + wxT(") [")
+                                + it_mirrors->type + wxT("]") );
+        it_mirrors++;
+    }
+    mirrors_choice->SetSelection( 0 );
+}
+
+/*void UpdateVLC::UpdateUpdateVLC()
+{
+    UpdateUpdatesTree();
+    UpdateMirrorsChoice();
+}*/
+
+void UpdateVLC::OnButtonClose( wxCommandEvent& event )
+{
+    wxCloseEvent cevent;
+    OnClose(cevent);
+}
+
+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 )
+    {
+        wxFileDialog *filedialog =
+            new wxFileDialog( updates_tree, 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 )
+{
+    msg_Dbg( p_intf, "Downloading %s to %s",
+             (const char *)url.mb_str(), (const char *)dst.mb_str() );
+
+    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;
+    }
+
+    FILE *p_file = NULL;
+    p_file = fopen( (const char *)dst.mb_str(), "w" );
+    if( !p_file )
+    {
+        msg_Err( p_intf, "Failed to open %s for writing", (const char *)dst.mb_str() );
+        // FIXME : display error message in dialog
+        return;
+    }
+
+    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) )
+        {
+            free( buffer );
+            fclose( p_file );
+            if( p_stream ) stream_Delete( p_stream );
+            progressdialog->Destroy();
+            msg_Warn( p_intf, "User aborted download" );
+            return;
+        }
+    }
+    progressdialog->Destroy();
+    msg_Dbg( p_intf, "Download finished" );
+    free( buffer );
+    fclose( p_file );
+    if( p_stream ) stream_Delete( p_stream );
+}
index 5936b3ddf36c445b8132ac8fa0a590675af129ae..58150834cb81c2319bd34cc11686d1be49c0998e 100644 (file)
@@ -29,6 +29,8 @@
 /* Let vlc take care of the i18n stuff */
 #define WXINTL_NO_GETTEXT_MACRO
 
+#include <list>
+
 #include <wx/wxprec.h>
 #include <wx/wx.h>
 
@@ -1047,6 +1049,67 @@ private:
 
 };
 
+/* Update VLC */
+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 );
+
+    DECLARE_EVENT_TABLE();
+
+    intf_thread_t *p_intf;
+    wxTreeCtrl *updates_tree;
+    wxTreeItemId updates_root;
+
+    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;
+};
+
 #if wxUSE_DRAG_AND_DROP
 /* Drag and Drop class */
 class DragAndDrop: public wxFileDropTarget