From: RĂ©mi Duraffort Date: Tue, 18 Dec 2007 15:51:29 +0000 (+0000) Subject: Add fonctions to the update system : all is in a thread now. The rc interface doesn... X-Git-Tag: 0.9.0-test0~4023 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=77c834e9255cc30ff51d3107f89a6514f42ab937;p=vlc Add fonctions to the update system : all is in a thread now. The rc interface doesn't use the update system for the moment and there isn't any encryption for the moment ... --- diff --git a/include/vlc_update.h b/include/vlc_update.h index cfac788f55..92f2581b2a 100644 --- a/include/vlc_update.h +++ b/include/vlc_update.h @@ -283,6 +283,7 @@ VLC_EXPORT( update_t *, __update_New, ( vlc_object_t * ) ); VLC_EXPORT( void, update_Delete, ( update_t * ) ); VLC_EXPORT( void, update_Check, ( update_t * ) ); VLC_EXPORT( int, update_CompareReleaseToCurrent, ( update_t * ) ); +VLC_EXPORT( void, update_Download, ( update_t *, char* ) ); /** * @} diff --git a/modules/control/rc.c b/modules/control/rc.c index 94c4858165..54d5673dd1 100644 --- a/modules/control/rc.c +++ b/modules/control/rc.c @@ -2114,19 +2114,12 @@ static input_item_t *parse_MRL( intf_thread_t *p_intf, char *psz_mrl ) #ifdef UPDATE_CHECK static void checkUpdates( intf_thread_t *p_intf ) { + /*TODO: - modify this to delete p_update to avoid a memory leak ! + - complete the function wich is not working obiously ! update_t *p_u = update_New( p_intf ); - if( p_u == NULL ) return; + var_AddCallback( p_intf->p_libvlc, "update-notify", updatesCallback, p_intf ); - update_Check( p_u ); msg_rc( "\nChecking for updates" ); - - if( update_CompareReleaseToCurrent( p_u ) == UpdateReleaseStatusNewer ) - msg_rc( "\n+----[ VLC %i.%i.%i%s ] ", p_u->release.i_major, - p_u->release.i_minor, - p_u->release.i_revision, - p_u->release.psz_extra ); - else - msg_rc( "\n+----Last version" ); - update_Delete( p_u ); + update_Check( p_u );*/ } #endif diff --git a/modules/gui/qt4/dialogs/help.cpp b/modules/gui/qt4/dialogs/help.cpp index 44886269b7..87e1548ff9 100644 --- a/modules/gui/qt4/dialogs/help.cpp +++ b/modules/gui/qt4/dialogs/help.cpp @@ -41,6 +41,8 @@ #include #include #include +#include +#include HelpDialog *HelpDialog::instance = NULL; @@ -165,38 +167,54 @@ void AboutDialog::close() } #ifdef UPDATE_CHECK + +/***************************************************************************** + * UpdateDialog + *****************************************************************************/ +/* callback to get information from the core */ +static int updateCallback( vlc_object_t *p_this, char const *psz_cmd, + vlc_value_t oldval, vlc_value_t newval, void *data ) +{ + UpdateDialog* UDialog = (UpdateDialog *)data; + QEvent *event = new QEvent( QEvent::User ); + QApplication::postEvent( UDialog, event ); + return VLC_SUCCESS; +} + UpdateDialog *UpdateDialog::instance = NULL; UpdateDialog::UpdateDialog( intf_thread_t *_p_intf ) : QVLCFrame( _p_intf ) { setWindowTitle( qtr( "Update" ) ); - resize( 320, 120 ); + resize( 120, 80 ); QGridLayout *layout = new QGridLayout( this ); - updateBrowser = new QTextBrowser( this ); - updateBrowser->setOpenExternalLinks( true ); - updateBrowser->setHtml( qtr( " \ -
Push the update button to get the updates
" ) ); - QPushButton *closeButton = new QPushButton( qtr( "&Close" ) ); - QPushButton *updateButton = new QPushButton( qtr( "&Update List" ) ); + updateButton = new QPushButton( qtr( "&Update List" ) ); updateButton->setDefault( true ); QDialogButtonBox *buttonBox = new QDialogButtonBox( Qt::Horizontal ); buttonBox->addButton( updateButton, QDialogButtonBox::ActionRole ); buttonBox->addButton( closeButton, QDialogButtonBox::AcceptRole ); - layout->addWidget( updateBrowser, 0, 0 ); + updateLabel = new QLabel( qtr( "Checking for the update..." ) ); + updateLabel->setWordWrap( true ); + + layout->addWidget( updateLabel, 0, 0 ); layout->addWidget( buttonBox, 1, 0 ); - BUTTONACT( updateButton, updateOrUpload() ); + BUTTONACT( updateButton, UpdateOrDownload() ); BUTTONACT( closeButton, close() ); + /* create the update structure and the callback */ p_update = update_New( _p_intf ); + var_AddCallback( _p_intf->p_libvlc, "update-notify", updateCallback, this ); + b_checked = false; } UpdateDialog::~UpdateDialog() { + var_DelCallback( p_update->p_libvlc, "update-notify", updateCallback, this ); update_Delete( p_update ); } @@ -205,22 +223,52 @@ void UpdateDialog::close() toggleVisible(); } -void UpdateDialog::updateOrUpload() +/* Check for updates */ +void UpdateDialog::UpdateOrDownload() +{ + if( !b_checked ) + { + updateButton->setEnabled( false ); + update_Check( p_update ); + } + else + { + updateButton->setEnabled( false ); + QString dest_dir = QFileDialog::getExistingDirectory( this, qtr( "Select a directory ..." ), + qfu( p_update->p_libvlc->psz_homedir ) ); + + if( dest_dir != "" ) + { + toggleVisible(); + update_Download( p_update, qtu( dest_dir ) ); + } + else + updateButton->setEnabled( true ); + } +} + +/* Handle the events */ +void UpdateDialog::customEvent( QEvent *event ) { - update_Check( p_update ); + updateNotify(); +} +/* Notify the end of the update_Check */ +void UpdateDialog::updateNotify() +{ if( update_CompareReleaseToCurrent( p_update ) == UpdateReleaseStatusNewer ) { - updateBrowser->setHtml( qtr( " \ -

" ) + qtu( (QString)p_update->release.psz_desc ) + - qtr( "

You can download the latest version of VLC release.psz_url ) + qtr( "\">here
" ) ); + b_checked = true; + updateButton->setText( "Download" ); + updateLabel->setText( qtr( "There is a new version of vlc :\n" ) + qfu( p_update->release.psz_desc ) ); } else { - updateBrowser->setHtml( " \ -
You have the latest version of VLC.
" ); + updateLabel->setText( qtr( "You have the latest version of vlc" ) ); } + adjustSize(); + updateButton->setEnabled( true ); } + #endif diff --git a/modules/gui/qt4/dialogs/help.hpp b/modules/gui/qt4/dialogs/help.hpp index a8fdb1d8bd..8669646d16 100644 --- a/modules/gui/qt4/dialogs/help.hpp +++ b/modules/gui/qt4/dialogs/help.hpp @@ -30,6 +30,9 @@ class QPushButton; class QTextBrowser; +class QLabel; +class QEvent; +class QPushButton; class HelpDialog : public QVLCFrame { @@ -71,6 +74,7 @@ public slots: }; #ifdef UPDATE_CHECK + class UpdateDialog : public QVLCFrame { Q_OBJECT; @@ -82,15 +86,20 @@ public: return instance; } virtual ~UpdateDialog(); + void updateNotify(); private: UpdateDialog( intf_thread_t * ); static UpdateDialog *instance; update_t *p_update; - QTextBrowser *updateBrowser; + QPushButton *updateButton; + QLabel *updateLabel; + void customEvent( QEvent * ); + bool b_checked; + private slots: void close(); - void updateOrUpload(); + void UpdateOrDownload(); }; #endif diff --git a/src/misc/update.c b/src/misc/update.c index 14a930b311..0e86bd2831 100644 --- a/src/misc/update.c +++ b/src/misc/update.c @@ -82,6 +82,8 @@ static void GetUpdateFile( update_t *p_update ); static int extracmp( char *psz_1, char *psz_2 ); static int CompareReleases( const struct update_release_t *p1, const struct update_release_t *p2 ); +static char * size_str( long int l_size ); + /***************************************************************************** * OpenPGP functions @@ -764,6 +766,9 @@ update_t *__update_New( vlc_object_t *p_this ) p_update->release.psz_url = NULL; p_update->release.psz_desc = NULL; + var_Create( p_this->p_libvlc, "update-notify", VLC_VAR_INTEGER | + VLC_VAR_ISCOMMAND ); + return p_update; } @@ -779,6 +784,8 @@ void update_Delete( update_t *p_update ) vlc_mutex_destroy( &p_update->lock ); + var_Destroy( p_update->p_libvlc, "update-notify" ); + FREENULL( p_update->release.psz_svnrev ); FREENULL( p_update->release.psz_extra ); FREENULL( p_update->release.psz_url ); @@ -807,7 +814,7 @@ static void EmptyRelease( update_t *p_update ) /** * Get the update file and parse it - * *p_update has to be unlocked when calling this function + * *p_update has to be locked when calling this function * * \param p_update pointer to update struct * \return nothing @@ -822,8 +829,6 @@ static void GetUpdateFile( update_t *p_update ) char *psz_svnrev = NULL; char *psz_line = NULL; - vlc_mutex_lock( &p_update->lock ); - p_stream = stream_UrlNew( p_update->p_libvlc, UPDATE_VLC_STATUS_URL ); if( !p_stream ) { @@ -877,12 +882,22 @@ static void GetUpdateFile( update_t *p_update ) p_update->release.psz_desc = psz_line; error: - vlc_mutex_unlock( &p_update->lock ); - if( p_stream ) stream_Delete( p_stream ); } + +/** + * Struct to launch the check in an other thread + */ +typedef struct +{ + VLC_COMMON_MEMBERS + update_t *p_update; +} update_check_thread_t; + +void update_CheckReal( update_check_thread_t *p_uct ); + /** * Check for updates * @@ -893,9 +908,24 @@ void update_Check( update_t *p_update ) { assert( p_update ); - EmptyRelease( p_update ); + update_check_thread_t *p_uct = vlc_object_create( p_update->p_libvlc, + sizeof( update_check_thread_t ) ); + p_uct->p_update = p_update; + + vlc_thread_create( p_uct, "check for update", update_CheckReal, + VLC_THREAD_PRIORITY_LOW, VLC_FALSE ); +} + +void update_CheckReal( update_check_thread_t *p_uct ) +{ + vlc_mutex_lock( &p_uct->p_update->lock ); + + EmptyRelease( p_uct->p_update ); + GetUpdateFile( p_uct->p_update ); + + vlc_mutex_unlock( &p_uct->p_update->lock ); - GetUpdateFile( p_update ); + var_TriggerCallback( p_uct->p_update->p_libvlc, "update-notify" ); } /** @@ -922,6 +952,7 @@ static int extracmp( char *psz_1, char *psz_2 ) return strcmp( psz_1, psz_2 ); } } + /** * Compare two release numbers * @@ -932,6 +963,10 @@ static int extracmp( char *psz_1, char *psz_2 ) static int CompareReleases( const struct update_release_t *p1, const struct update_release_t *p2 ) { + /* The string musn't be NULL if we don't want a segfault with strcmp */ + if( !p1->psz_extra || !p2->psz_extra || !p1->psz_svnrev || !p2->psz_svnrev ) + return UpdateReleaseStatusEqual; + int32_t d; d = ( p1->i_major << 24 ) + ( p1->i_minor << 16 ) + ( p1->i_revision << 8 ); d = d - ( p2->i_major << 24 ) - ( p2->i_minor << 16 ) - ( p2->i_revision << 8 ); @@ -951,7 +986,7 @@ static int CompareReleases( const struct update_release_t *p1, /** * Compare a given release's version number to the current VLC's one * - * \param p a release + * \param p_update structure * \return UpdateReleaseStatus(Older|Equal|Newer) */ int update_CompareReleaseToCurrent( update_t *p_update ) @@ -976,13 +1011,149 @@ int update_CompareReleaseToCurrent( update_t *p_update ) else c.psz_extra = STRDUP( "" ); c.psz_svnrev = STRDUP( VLC_Changeset() ); - i_result = CompareReleases( &p_update->release, &c ); - free( c.psz_extra ); free( c.psz_svnrev ); } + return i_result; } +/** + * Convert a long int size in bytes to a string + * + * \param l_size the size in bytes + * \return the size as a string + */ +static char *size_str( long int l_size ) +{ + char *psz_tmp; + if( l_size>> 30 ) + asprintf( &psz_tmp, "%.1f GB", (float)l_size/(1<<30) ); + if( l_size >> 20 ) + asprintf( &psz_tmp, "%.1f MB", (float)l_size/(1<<20) ); + else if( l_size >> 10 ) + asprintf( &psz_tmp, "%.1f kB", (float)l_size/(1<<10) ); + else + asprintf( &psz_tmp, "%ld B", l_size ); + return psz_tmp; +} + + +/* + * Struct to launch the download in a thread + */ +typedef struct +{ + VLC_COMMON_MEMBERS + update_t *p_update; + char *psz_destdir; +} update_download_thread_t; + +void update_DownloadReal( update_download_thread_t *p_udt ); + +/** + * Download the file given in the update_t + * + * \param p_update structure + * \param dir to store the download file + * \return nothing + */ +void update_Download( update_t *p_update, char *psz_destdir ) +{ + assert( p_update ); + + update_download_thread_t *p_udt = vlc_object_create( p_update->p_libvlc, + sizeof( update_download_thread_t ) ); + + p_udt->p_update = p_update; + p_udt->psz_destdir = STRDUP( psz_destdir ); + + vlc_thread_create( p_udt, "download update", update_DownloadReal, + VLC_THREAD_PRIORITY_LOW, VLC_FALSE ); +} +void update_DownloadReal( update_download_thread_t *p_udt ) +{ + int i_progress = 0; + long int l_size; + long int l_downloaded = 0; + char *psz_status; + char *psz_downloaded; + char *psz_size; + char *psz_destfile; + char *psz_tmpdestfile; + + FILE *p_file = NULL; + stream_t *p_stream; + void* p_buffer; + int i_read; + + update_t *p_update = p_udt->p_update; + char *psz_destdir = p_udt->psz_destdir; + + /* Open the stream */ + p_stream = stream_UrlNew( p_update->p_libvlc, p_update->release.psz_url ); + + if( !p_stream ) + { + msg_Err( p_update->p_libvlc, "Failed to open %s for reading", p_update->release.psz_url ); + } + else + { + /* Get the stream size and open the output file */ + l_size = stream_Size( p_stream ); + + psz_tmpdestfile = strrchr( p_update->release.psz_url, '/' ); + psz_tmpdestfile++; + asprintf( &psz_destfile, "%s%s", psz_destdir, psz_tmpdestfile ); + + p_file = utf8_fopen( psz_destfile, "w" ); + if( !p_file ) + { + msg_Err( p_update->p_libvlc, "Failed to open %s for writing", psz_destfile ); + } + else + { + /* Create a buffer and fill it with the downloaded file */ + p_buffer = (void *)malloc( 1 << 10 ); + if( p_buffer ) + { + psz_size = size_str( l_size ); + asprintf( &psz_status, "%s\nDownloading... O.O/%s %.1f%% done", p_update->release.psz_url, psz_size, 0.0 ); + i_progress = intf_UserProgress( p_update->p_libvlc, "Downloading ...", psz_status, 0.0, 0 ); + free( psz_status ); + + while( ( i_read = stream_Read( p_stream, p_buffer, 1 << 10 ) ) && + !intf_ProgressIsCancelled( p_update->p_libvlc, i_progress ) ) + { + fwrite( p_buffer, i_read, 1, p_file ); + + l_downloaded += i_read; + psz_downloaded = size_str( l_downloaded ); + asprintf( &psz_status, "%s\nDonwloading... %s/%s %.1f%% done", p_update->release.psz_url, + psz_size, psz_downloaded, 100.0*(float)l_downloaded/(float)l_size ); + intf_ProgressUpdate( p_update->p_libvlc, i_progress, psz_status, 10.0, 0 ); + free( psz_downloaded ); + free( psz_status ); + } + + /* If the user cancelled the download */ + if( !intf_ProgressIsCancelled( p_update->p_libvlc, i_progress ) ) + { + asprintf( &psz_status, "%s\nDone %s (100.0%%)", p_update->release.psz_url, psz_size ); + intf_ProgressUpdate( p_update->p_libvlc, i_progress, psz_status, 100.0, 0 ); + free( psz_status ); + } + free( p_buffer ); + free( psz_size ); + } + fclose( p_file ); + if( intf_ProgressIsCancelled( p_update->p_libvlc, i_progress ) ) + remove( psz_destfile ); + } + stream_Delete( p_stream ); + } + free( psz_destdir ); +} + #endif