]> git.sesse.net Git - vlc/commitdiff
Add fonctions to the update system : all is in a thread now. The rc interface doesn...
authorRémi Duraffort <ivoire@videolan.org>
Tue, 18 Dec 2007 15:51:29 +0000 (15:51 +0000)
committerRémi Duraffort <ivoire@videolan.org>
Tue, 18 Dec 2007 15:51:29 +0000 (15:51 +0000)
include/vlc_update.h
modules/control/rc.c
modules/gui/qt4/dialogs/help.cpp
modules/gui/qt4/dialogs/help.hpp
src/misc/update.c

index cfac788f550b2d472a4acebac2e499d862e6088e..92f2581b2ac8a96804a3d907b785b103fddb9d37 100644 (file)
@@ -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* ) );
 
 /**
  * @}
index 94c485816525fa684f07366e99b0c627ebb7d774..54d5673dd17bfae2c72ad4e12063894c9e95cbe6 100644 (file)
@@ -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
index 44886269b7eee67cc3d7b3ce9286048274c424cf..87e1548ff98ad0ea409d583ed82bd14b7aa1215d 100644 (file)
@@ -41,6 +41,8 @@
 #include <QLabel>
 #include <QString>
 #include <QDialogButtonBox>
+#include <QEvent>
+#include <QFileDialog>
 
 
 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( "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=\"utf-8\" /></head> \
-                                  <body><center>Push the update button to get the updates</center></body></html>" ) );
-    
     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( "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=\"utf-8\" /></head> \
-                                      <body><center><p>" ) + qtu( (QString)p_update->release.psz_desc ) +
-                                      qtr( "</p>You can download the latest version of VLC <a href=\"" ) +
-                                      qtu( (QString)p_update->release.psz_url ) + qtr( "\">here</a></center></body></html>" ) );
+        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( "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=\"utf-8\" /></head> \
-                                 <body><center>You have the latest version of VLC.</center></body></html>" );
+        updateLabel->setText( qtr( "You have the latest version of vlc" ) );
     }
+    adjustSize();
+    updateButton->setEnabled( true );
 }
 
+
 #endif
index a8fdb1d8bdf811391054fea16c11bb76f9773c12..8669646d16f6f37399eb16208bed5745aadb81cb 100644 (file)
@@ -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
 
index 14a930b3115e77c6aa66cdb01d1409505367a859..0e86bd28313a719288ebfa85ab4cee25b2f74b52 100644 (file)
@@ -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