1 /*****************************************************************************
2 * updatevlc.cpp : Check for VLC updates dialog
3 *****************************************************************************
4 * Copyright (C) 2000-2004 the VideoLAN team
7 * Authors: Antoine Cellerier <dionoea@videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
30 #include <wx/progdlg.h>
32 #include "wxwindows.h"
34 #include "vlc_block.h"
35 #include "vlc_stream.h"
38 /* define UPDATE_VLC_OS and UPDATE_VLC_ARCH */
39 /* todo : move this somewhere else (isn't wx specific) */
42 # define UPDATE_VLC_OS "windows"
43 # define UPDATE_VLC_ARCH "i386"
46 # define UPDATE_VLC_OS "macosx"
47 # define UPDATE_VLC_ARCH "ppc"
49 # define UPDATE_VLC_OS "windows"
50 # define UPDATE_VLC_ARCH "i386"
54 /* arch == "*" and os == "*" concern non OS or arch specific stuff */
56 #define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status"
57 #define UPDATE_VLC_MIRRORS_URL "http://update.videolan.org/mirrors"
59 #define UPDATE_VLC_DOWNLOAD_BUFFER_SIZE 2048
61 class UpdatesTreeItem : public wxTreeItemData
64 UpdatesTreeItem( wxString _url ):wxTreeItemData()
71 /*****************************************************************************
73 *****************************************************************************/
75 /* IDs for the controls and the menu commands */
81 UpdatesTreeActivate_Event
84 BEGIN_EVENT_TABLE(UpdateVLC, wxFrame)
86 EVT_BUTTON(wxID_OK, UpdateVLC::OnButtonClose)
87 EVT_BUTTON(CheckForUpdate_Event, UpdateVLC::OnCheckForUpdate)
90 EVT_CHOICE(MirrorChoice_Event, UpdateVLC::OnMirrorChoice)
93 EVT_TREE_ITEM_ACTIVATED(UpdatesTreeActivate_Event, UpdateVLC::OnUpdatesTreeActivate)
95 /* Hide the window when the user closes the window */
96 EVT_CLOSE(UpdateVLC::OnClose)
100 /*****************************************************************************
102 *****************************************************************************/
103 UpdateVLC::UpdateVLC( intf_thread_t *_p_intf, wxWindow *p_parent ):
104 wxFrame( p_parent, -1, wxU(_("Check for updates ...")), wxDefaultPosition,
105 wxDefaultSize, wxDEFAULT_FRAME_STYLE )
107 /* Initializations */
109 release_type = wxT( "stable" );
110 SetIcon( *p_intf->p_sys->p_icon );
111 SetAutoLayout( TRUE );
113 /* Create a panel to put everything in */
114 wxPanel *panel = new wxPanel( this, -1 );
115 panel->SetAutoLayout( TRUE );
118 new wxTreeCtrl( panel, UpdatesTreeActivate_Event, wxDefaultPosition,
120 wxTR_HAS_BUTTONS | wxTR_HIDE_ROOT | wxSUNKEN_BORDER );
122 /* Place everything in sizers */
123 wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
124 wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
125 wxBoxSizer *subpanel_sizer = new wxBoxSizer( wxHORIZONTAL );
126 panel_sizer->Add( updates_tree, 0, wxGROW | wxALL, 5 );
127 wxButton *update_button =
128 new wxButton( panel, CheckForUpdate_Event,
129 wxU(_("Check for updates now !")) );
130 subpanel_sizer->Add( update_button, 0, wxALL, 5 );
131 wxArrayString *choices_array = new wxArrayString();
132 choices_array->Add( wxT("") );
134 new wxChoice( panel, MirrorChoice_Event, wxDefaultPosition,
135 wxSize( 200, -1 ), *choices_array );
136 subpanel_sizer->Add( mirrors_choice, 0, wxALL, 5 );
137 subpanel_sizer->Layout();
138 panel_sizer->Add( subpanel_sizer, 0, wxALL , 0 );
139 panel_sizer->Layout();
140 panel->SetSizerAndFit( panel_sizer );
141 main_sizer->Add( panel, 0, wxALL | wxGROW, 0 );
142 main_sizer->Layout();
143 SetSizerAndFit( main_sizer );
145 UpdateMirrorsChoice();
150 UpdateVLC::~UpdateVLC()
154 /* this function gets all the info from the xml files hosted on
155 http://update.videolan.org/ and stores it in appropriate lists */
156 void UpdateVLC::GetData()
158 stream_t *p_stream = NULL;
159 char *psz_eltname = NULL;
160 char *psz_name = NULL;
161 char *psz_value = NULL;
162 char *psz_eltvalue = NULL;
164 xml_reader_t *p_xml_reader = NULL;
168 struct update_file_t tmp_file;
169 struct update_version_t tmp_version;
170 std::list<update_version_t>::iterator it;
171 std::list<update_file_t>::iterator it_files;
173 struct update_mirror_t tmp_mirror;
175 p_xml = xml_Create( p_intf );
178 msg_Err( p_intf, "Failed to open XML parser" );
179 // FIXME : display error message in dialog
183 p_stream = stream_UrlNew( p_intf, UPDATE_VLC_STATUS_URL );
186 msg_Err( p_intf, "Failed to open %s for reading",
187 UPDATE_VLC_STATUS_URL );
188 // FIXME : display error message in dialog
192 p_xml_reader = xml_ReaderCreate( p_xml, p_stream );
196 msg_Err( p_intf, "Failed to open %s for parsing",
197 UPDATE_VLC_STATUS_URL );
198 // FIXME : display error message in dialog
206 while( xml_ReaderRead( p_xml_reader ) == 1 )
208 switch( xml_ReaderNodeType( p_xml_reader ) )
212 // TODO : print message
215 case XML_READER_STARTELEM:
216 psz_eltname = xml_ReaderName( p_xml_reader );
219 // TODO : print message
222 msg_Dbg( p_intf, "element name : %s", psz_eltname );
223 while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
225 psz_name = xml_ReaderName( p_xml_reader );
226 psz_value = xml_ReaderValue( p_xml_reader );
227 if( !psz_name || !psz_value )
229 // TODO : print message
233 msg_Dbg( p_intf, " attribute %s = %s",
234 psz_name, psz_value );
237 if( strcmp( psz_eltname, "version" ) == 0 )
239 if( !strcmp( psz_name, "type" ) )
240 tmp_version.type = wxU( psz_value );
241 if( !strcmp( psz_name, "major" ) )
242 tmp_version.major = wxU( psz_value );
243 if( !strcmp( psz_name, "minor" ) )
244 tmp_version.minor = wxU( psz_value );
245 if( !strcmp( psz_name, "revision" ) )
246 tmp_version.revision = wxU( psz_value );
247 if( !strcmp( psz_name, "extra" ) )
248 tmp_version.extra = wxU( psz_value );
250 if( !strcmp( psz_eltname, "file" ) )
252 if( !strcmp( psz_name, "type" ) )
253 tmp_file.type = wxU( psz_value );
254 if( !strcmp( psz_name, "md5" ) )
255 tmp_file.md5 = wxU( psz_value );
256 if( !strcmp( psz_name, "size" ) )
257 tmp_file.size = wxU( psz_value );
258 if( !strcmp( psz_name, "url" ) )
259 tmp_file.url = wxU( psz_value );
260 if( !strcmp( psz_name, "desciption" ) )
261 tmp_file.description = wxU( psz_value );
264 if( !strcmp( psz_name, "name" )
265 && ( !strcmp( psz_value, UPDATE_VLC_OS )
266 || !strcmp( psz_value, "*" ) )
267 && !strcmp( psz_eltname, "os" ) )
271 if( b_os && !strcmp( psz_name, "name" )
272 && ( !strcmp( psz_value, UPDATE_VLC_ARCH )
273 || !strcmp( psz_value, "*" ) )
274 && !strcmp( psz_eltname, "arch" ) )
281 if( ( b_os && b_arch && strcmp( psz_eltname, "arch" ) ) )
283 if( !strcmp( psz_eltname, "version" ) )
285 it = m_versions.begin();
286 while( it != m_versions.end() )
288 if( it->type == tmp_version.type
289 && it->major == tmp_version.major
290 && it->minor == tmp_version.minor
291 && it->revision == tmp_version.revision
292 && it->extra == tmp_version.extra )
298 if( it == m_versions.end() )
300 m_versions.push_back( tmp_version );
301 it = m_versions.begin();
302 while( it != m_versions.end() )
304 if( it->type == tmp_version.type
305 && it->major == tmp_version.major
306 && it->minor == tmp_version.minor
307 && it->revision == tmp_version.revision
308 && it->extra == tmp_version.extra )
315 tmp_version.type = wxT( "" );
316 tmp_version.major = wxT( "" );
317 tmp_version.minor = wxT( "" );
318 tmp_version.revision = wxT( "" );
319 tmp_version.extra = wxT( "" );
321 if( !strcmp( psz_eltname, "file" ) )
323 it->m_files.push_back( tmp_file );
324 tmp_file.type = wxT( "" );
325 tmp_file.md5 = wxT( "" );
326 tmp_file.size = wxT( "" );
327 tmp_file.url = wxT( "" );
328 tmp_file.description = wxT( "" );
334 case XML_READER_ENDELEM:
335 psz_eltname = xml_ReaderName( p_xml_reader );
338 // TODO : print message
341 msg_Dbg( p_intf, "element end : %s", psz_eltname );
342 if( !strcmp( psz_eltname, "os" ) )
344 if( !strcmp( psz_eltname, "arch" ) )
349 case XML_READER_TEXT:
350 psz_eltvalue = xml_ReaderValue( p_xml_reader );
351 msg_Dbg( p_intf, " text : %s", psz_eltvalue );
352 /* This doesn't look safe ... but it works */
353 it->m_files.back().description = wxU( psz_eltvalue );
354 free( psz_eltvalue );
359 if( p_xml_reader && p_xml ) xml_ReaderDelete( p_xml, p_xml_reader );
360 if( p_stream ) stream_Delete( p_stream );
362 p_stream = stream_UrlNew( p_intf, UPDATE_VLC_MIRRORS_URL );
365 msg_Err( p_intf, "Failed to open %s for reading",
366 UPDATE_VLC_MIRRORS_URL );
367 // FIXME : display error message in dialog
371 p_xml_reader = xml_ReaderCreate( p_xml, p_stream );
375 msg_Err( p_intf, "Failed to open %s for parsing",
376 UPDATE_VLC_MIRRORS_URL );
377 // FIXME : display error message in dialog
384 while( xml_ReaderRead( p_xml_reader ) == 1 )
386 switch( xml_ReaderNodeType( p_xml_reader ) )
390 // TODO : print message
393 case XML_READER_STARTELEM:
394 psz_eltname = xml_ReaderName( p_xml_reader );
397 // TODO : print message
400 msg_Dbg( p_intf, "element name : %s", psz_eltname );
401 while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )
403 psz_name = xml_ReaderName( p_xml_reader );
404 psz_value = xml_ReaderValue( p_xml_reader );
405 if( !psz_name || !psz_value )
407 // TODO : print message
411 msg_Dbg( p_intf, " attribute %s = %s",
412 psz_name, psz_value );
413 if( !strcmp( psz_eltname, "mirror" ) )
415 if( !strcmp( psz_name, "name" ) )
416 tmp_mirror.name = wxU( psz_value );
417 if( !strcmp( psz_name, "location" ) )
418 tmp_mirror.location = wxU( psz_value );
420 if( !strcmp( psz_eltname, "url" ) )
422 if( !strcmp( psz_name, "type" ) )
423 tmp_mirror.type = wxU( psz_value );
424 if( !strcmp( psz_name, "base" ) )
425 tmp_mirror.base_url = wxU( psz_value );
430 if( !strcmp( psz_eltname, "url" ) )
432 m_mirrors.push_back( tmp_mirror );
433 tmp_mirror.type = wxT( "" );
434 tmp_mirror.base_url = wxT( "" );
439 case XML_READER_ENDELEM:
440 psz_eltname = xml_ReaderName( p_xml_reader );
443 // TODO : print message
446 msg_Dbg( p_intf, "element end : %s", psz_eltname );
447 if( !strcmp( psz_eltname, "mirror" ) )
449 tmp_mirror.name = wxT( "" );
450 tmp_mirror.location = wxT( "" );
455 case XML_READER_TEXT:
456 psz_eltvalue = xml_ReaderValue( p_xml_reader );
457 msg_Dbg( p_intf, " text : %s", psz_eltvalue );
458 free( psz_eltvalue );
464 if( p_xml_reader && p_xml ) xml_ReaderDelete( p_xml, p_xml_reader );
465 if( p_stream ) stream_Delete( p_stream );
466 if( p_xml ) xml_Delete( p_xml );
469 void UpdateVLC::UpdateUpdatesTree()
472 std::list<update_version_t>::iterator it;
473 std::list<update_file_t>::iterator it_files;
474 std::list<update_mirror_t>::iterator it_mirrors;
476 int selection = mirrors_choice->GetSelection();
477 wxString base_url = wxT( "" );
481 it_mirrors = m_mirrors.begin();
482 while( it_mirrors != m_mirrors.end() && selection )
487 if( it_mirrors != m_mirrors.end() ) base_url = it_mirrors->base_url;
491 updates_tree->DeleteAllItems();
494 parent = updates_tree->AppendItem( updates_root, wxT( "" ) );
495 updates_tree->AppendItem( parent,
496 wxT( "Current version : "PACKAGE_VERSION ),
497 -1, -1, new UpdatesTreeItem( wxT( "" ) ));
498 it = m_versions.begin();
499 while( it != m_versions.end() )
501 wxTreeItemId cat = updates_tree->AppendItem( parent,
502 wxT("VLC media player ")+ it->major + wxT(".")
503 + it->minor + wxT(".") + it->revision + wxT("-")
504 + it->extra + wxT(" (") + it->type + wxT(")"),
505 -1, -1, new UpdatesTreeItem( wxT( "" ) ));
506 it_files = it->m_files.begin();
507 while( it_files != it->m_files.end() )
509 wxString url = (it_files->url[0]=='/' ? base_url : wxT( "" ) )
512 updates_tree->AppendItem( cat, it_files->description,
513 -1, -1, new UpdatesTreeItem( url ) );
514 updates_tree->AppendItem( file,
515 wxU(_("type : ")) + it_files->type,
516 -1, -1, new UpdatesTreeItem( url ));
517 updates_tree->AppendItem( file, wxU(_("URL : ")) + url,
518 -1, -1, new UpdatesTreeItem( url ));
519 if( it_files->size != wxT( "" ) )
520 updates_tree->AppendItem( file,
521 wxU(_("file size : ")) + it_files->size,
522 -1, -1, new UpdatesTreeItem( url ));
523 if( it_files->md5 != wxT( "" ) )
524 updates_tree->AppendItem( file,
525 wxU(_("file md5 hash : ")) + it_files->md5,
526 -1, -1, new UpdatesTreeItem( url ));
530 updates_tree->Expand( cat );
534 void UpdateVLC::UpdateMirrorsChoice()
536 std::list<update_mirror_t>::iterator it_mirrors;
538 mirrors_choice->Clear();
539 mirrors_choice->Append( wxU(_("Choose a mirror")) );
540 it_mirrors = m_mirrors.begin();
541 while( it_mirrors != m_mirrors.end() )
543 mirrors_choice->Append( it_mirrors->name + wxT(" (")
544 + it_mirrors->location + wxT(") [")
545 + it_mirrors->type + wxT("]") );
548 mirrors_choice->SetSelection( 0 );
551 /*void UpdateVLC::UpdateUpdateVLC()
554 UpdateMirrorsChoice();
557 void UpdateVLC::OnButtonClose( wxCommandEvent& event )
563 void UpdateVLC::OnClose( wxCloseEvent& WXUNUSED(event) )
568 void UpdateVLC::OnCheckForUpdate( wxCommandEvent& event )
571 UpdateMirrorsChoice();
575 void UpdateVLC::OnMirrorChoice( wxCommandEvent& event )
580 void UpdateVLC::OnUpdatesTreeActivate( wxTreeEvent& event )
583 ((UpdatesTreeItem *)(updates_tree->GetItemData(event.GetItem())))->url;
584 if( url != wxT( "" ) ? url[0] != '/' : false )
586 wxFileDialog *filedialog =
587 new wxFileDialog( updates_tree, wxU(_("Save file ...")),
588 wxT(""), url.AfterLast( '/' ), wxT("*.*"),
589 wxSAVE | wxOVERWRITE_PROMPT );
590 if( filedialog->ShowModal() == wxID_OK )
592 DownloadFile( url, filedialog->GetPath() );
597 void UpdateVLC::DownloadFile( wxString url, wxString dst )
599 msg_Dbg( p_intf, "Downloading %s to %s",
600 (const char *)url.mb_str(), (const char *)dst.mb_str() );
602 stream_t *p_stream = NULL;
603 p_stream = stream_UrlNew( p_intf, (const char *)url.mb_str() );
606 msg_Err( p_intf, "Failed to open %s for reading", (const char *)url.mb_str() );
607 // FIXME : display error message in dialog
612 p_file = fopen( (const char *)dst.mb_str(), "w" );
615 msg_Err( p_intf, "Failed to open %s for writing", (const char *)dst.mb_str() );
616 // FIXME : display error message in dialog
621 wxProgressDialog *progressdialog =
622 new wxProgressDialog( wxU(_("Downloading...")),
623 wxU(wxT("Src: ") +url + wxT("\nDst: ") +dst ),
624 (int)(stream_Size(p_stream)/UPDATE_VLC_DOWNLOAD_BUFFER_SIZE), NULL,
625 wxPD_ELAPSED_TIME | wxPD_REMAINING_TIME | wxPD_AUTO_HIDE
628 void *buffer = (void *)malloc( UPDATE_VLC_DOWNLOAD_BUFFER_SIZE );
629 while( stream_Read( p_stream, buffer, UPDATE_VLC_DOWNLOAD_BUFFER_SIZE ) )
631 fwrite( buffer, UPDATE_VLC_DOWNLOAD_BUFFER_SIZE, 1, p_file);
632 if( !progressdialog->Update(++i_progress) )
636 if( p_stream ) stream_Delete( p_stream );
637 progressdialog->Destroy();
638 msg_Warn( p_intf, "User aborted download" );
642 progressdialog->Destroy();
643 msg_Dbg( p_intf, "Download finished" );
646 if( p_stream ) stream_Delete( p_stream );