From: Antoine Cellerier Date: Sun, 24 Jul 2005 21:03:20 +0000 (+0000) Subject: VLC update checker in the wxWidgets interface (in help menu) X-Git-Tag: 0.8.4~1171 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=e34daedfae3bc4f23ddef242c3d3a41eb3655c29;p=vlc VLC update checker in the wxWidgets interface (in help menu) xml files used for the updates are located at http://update.videolan.org extensive testing ... code cleaning ... would be greatly appreciated --- diff --git a/include/vlc_interface.h b/include/vlc_interface.h index 1a29d57853..556c1719e0 100644 --- a/include/vlc_interface.h +++ b/include/vlc_interface.h @@ -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 */ diff --git a/modules/gui/wxwindows/Modules.am b/modules/gui/wxwindows/Modules.am index de182917ee..7492d813bb 100644 --- a/modules/gui/wxwindows/Modules.am +++ b/modules/gui/wxwindows/Modules.am @@ -17,6 +17,7 @@ SOURCES_wxwindows = \ preferences_widgets.h \ timer.cpp \ fileinfo.cpp \ + updatevlc.cpp \ subtitles.cpp \ bookmarks.cpp \ video.cpp \ diff --git a/modules/gui/wxwindows/dialogs.cpp b/modules/gui/wxwindows/dialogs.cpp index aee8b3282b..287ea43bf1 100644 --- a/modules/gui/wxwindows/dialogs.cpp +++ b/modules/gui/wxwindows/dialogs.cpp @@ -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() ); + } +} diff --git a/modules/gui/wxwindows/interface.cpp b/modules/gui/wxwindows/interface.cpp index a1ca67beeb..378dbb8f34 100644 --- a/modules/gui/wxwindows/interface.cpp +++ b/modules/gui/wxwindows/interface.cpp @@ -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 index 0000000000..b2184a8b09 --- /dev/null +++ b/modules/gui/wxwindows/updatevlc.cpp @@ -0,0 +1,647 @@ +/***************************************************************************** + * updatevlc.cpp : Check for VLC updates dialog + ***************************************************************************** + * Copyright (C) 2000-2004 the VideoLAN team + * $Id$ + * + * Authors: Antoine Cellerier + * + * 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 +#include + +#include + +#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::iterator it; + std::list::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::iterator it; + std::list::iterator it_files; + std::list::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::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 ); +} diff --git a/modules/gui/wxwindows/wxwindows.h b/modules/gui/wxwindows/wxwindows.h index 5936b3ddf3..58150834cb 100644 --- a/modules/gui/wxwindows/wxwindows.h +++ b/modules/gui/wxwindows/wxwindows.h @@ -29,6 +29,8 @@ /* Let vlc take care of the i18n stuff */ #define WXINTL_NO_GETTEXT_MACRO +#include + #include #include @@ -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 m_files; + }; + + std::list m_versions; + + struct update_mirror_t + { + wxString name; + wxString location; + wxString type; + wxString base_url; + }; + + std::list m_mirrors; +}; + #if wxUSE_DRAG_AND_DROP /* Drag and Drop class */ class DragAndDrop: public wxFileDropTarget