📄 update.c
字号:
//TODO: testunsigned int update_iterator_PrevFile( update_iterator_t *p_uit ){ int r,f=-1,old_r; if( !p_uit ) return UPDATE_FAIL; old_r=p_uit->i_r; /* if the update iterator was already in a "no match" state, start over * (begin at the end of the list) */ if( p_uit->i_r == -1 ) p_uit->i_r = p_uit->p_u->i_releases - 1; p_uit->i_f = p_uit->p_u->p_releases[p_uit->i_r].i_files + 1; vlc_mutex_lock( &p_uit->p_u->lock ); for( r = p_uit->i_r; r >= 0; r-- ) { if( !( p_uit->p_u->p_releases[r].i_status & p_uit->i_rs ) ) continue; for( f =( r==p_uit->i_r ? p_uit->i_f - 1 : p_uit->p_u->p_releases[r].i_files ); f >= 0; f-- ) { if( p_uit->p_u->p_releases[r].p_files[f].i_type & p_uit->i_t ) { goto done;/* "double break" */ } } } done: p_uit->i_r = r; p_uit->i_f = f; r = p_uit->p_u->i_releases; if( old_r == p_uit->i_r ) { update_iterator_GetData( p_uit ); vlc_mutex_unlock( &p_uit->p_u->lock ); return UPDATE_SUCCESS|UPDATE_FILE; } else if( p_uit->i_r == -1 ) { p_uit->i_r = -1; p_uit->i_f = -1; update_iterator_GetData( p_uit ); vlc_mutex_unlock( &p_uit->p_u->lock ); return UPDATE_FAIL; } else { update_iterator_GetData( p_uit ); vlc_mutex_unlock( &p_uit->p_u->lock ); return UPDATE_SUCCESS|UPDATE_RELEASE|UPDATE_FILE; }}/** * Finds the next mirror in the update tree * * \param update iterator * \return UPDATE_FAIL if we can't find the next mirror, UPDATE_SUCCESS|UPDATE_MIRROR otherwise */unsigned int update_iterator_NextMirror( update_iterator_t *p_uit ){ if( !p_uit ) return UPDATE_FAIL; vlc_mutex_lock( &p_uit->p_u->lock ); p_uit->i_m++; if( p_uit->i_m >= p_uit->p_u->i_mirrors ) p_uit->i_m = -1; update_iterator_GetData( p_uit ); vlc_mutex_unlock( &p_uit->p_u->lock ); return p_uit->i_m == -1 ? UPDATE_FAIL : UPDATE_SUCCESS|UPDATE_MIRROR;}/** * Finds the previous mirror in the update tree * * \param update iterator * \return UPDATE_FAIL if we can't find a previous mirror, UPDATE_SUCCESS|UPDATE_MIRROR otherwise */unsigned int update_iterator_PrevMirror( update_iterator_t *p_uit ){ if( !p_uit ) return UPDATE_FAIL; vlc_mutex_lock( &p_uit->p_u->lock ); p_uit->i_m--; update_iterator_GetData( p_uit ); vlc_mutex_unlock( &p_uit->p_u->lock ); return p_uit->i_m == -1 ? UPDATE_FAIL : UPDATE_SUCCESS|UPDATE_MIRROR;}/** * Change the update iterator's position in the file and mirrors tree * If position is negative, don't change it * * \param i_m position in mirrors list * \param i_r position in releases list * \param i_f position in release's files list * \return UPDATE_FAIL when changing position fails or position wasn't changed, a combination of UPDATE_MIRROR, UPDATE_RELEASE and UPDATE_FILE otherwise */unsigned int update_iterator_ChooseMirrorAndFile( update_iterator_t *p_uit, int i_m, int i_r, int i_f ){ unsigned int i_val = 0; if( !p_uit ) return 0; vlc_mutex_lock( &p_uit->p_u->lock ); if( i_m >= 0 ) { if( i_m < p_uit->p_u->i_mirrors ) { if( i_m != p_uit->i_m ) i_val |= UPDATE_MIRROR; p_uit->i_m = i_m; } else i_m = -1; } if( i_r >= 0 ) { if( i_r < p_uit->p_u->i_releases ) { if( i_r != p_uit->i_r ) i_val |= UPDATE_FILE; p_uit->i_r = i_r; } else i_r = -1; } if( i_f >= 0 ) { if( i_r >= 0 && i_r < p_uit->p_u->i_releases && i_f < p_uit->p_u->p_releases[p_uit->i_r].i_files ) { if( i_f != p_uit->i_f ) i_val |= UPDATE_FILE; p_uit->i_f = i_f; } else i_f = -1; } update_iterator_GetData( p_uit ); vlc_mutex_unlock( &p_uit->p_u->lock ); if( ( i_m < 0 || p_uit->i_m >= 0 ) && ( i_r < 0 || p_uit->i_r >= 0 ) && ( i_f < 0 || p_uit->i_f >= 0 ) ) { /* Everything worked */ return UPDATE_SUCCESS|i_val; } else { /* Something failed */ return UPDATE_FAIL; }}/** * Fills the iterator data (file, release and mirror structs) * The update struct should be locked before calling this function. * * \param p_uit update iterator * \return nothing */void update_iterator_GetData( update_iterator_t *p_uit ){ struct update_release_t *p_r = NULL; struct update_file_t *p_f = NULL; struct update_mirror_t *p_m = NULL; update_iterator_ClearData( p_uit ); if( p_uit->i_m >= 0 ) { p_m = p_uit->p_u->p_mirrors + p_uit->i_m; p_uit->mirror.psz_name = STRDUP( p_m->psz_name ); p_uit->mirror.psz_location = STRDUP( p_m->psz_location ); p_uit->mirror.psz_type = STRDUP( p_m->psz_type ); } if( p_uit->i_r >= 0 ) { p_r = p_uit->p_u->p_releases + p_uit->i_r; asprintf( &p_uit->release.psz_version, "%s.%s.%s-%s", p_r->psz_major, p_r->psz_minor, p_r->psz_revision, p_r->psz_extra ); p_uit->release.psz_svn_revision = STRDUP( p_r->psz_svn_revision ); p_uit->release.i_type = p_r->i_type; p_uit->release.i_status = p_r->i_status; if( p_uit->i_f >= 0 ) { p_f = p_r->p_files + p_uit->i_f; p_uit->file.i_type = p_f->i_type; p_uit->file.psz_md5 = STRDUP( p_f->psz_md5 ); p_uit->file.l_size = p_f->l_size; p_uit->file.psz_description = STRDUP( p_f->psz_description); if( p_f->psz_url[0] == '/' ) { if( p_m ) { asprintf( &p_uit->file.psz_url, "%s%s", p_m->psz_base_url, p_f->psz_url ); } } else { p_uit->file.psz_url = STRDUP( p_f->psz_url ); } } }}/** * Clears the iterator data (file, release and mirror structs) * * \param p_uit update iterator * \return nothing */void update_iterator_ClearData( update_iterator_t *p_uit ){ p_uit->file.i_type = UPDATE_FILE_TYPE_NONE; FREE( p_uit->file.psz_md5 ); p_uit->file.l_size = 0; FREE( p_uit->file.psz_description ); FREE( p_uit->file.psz_url ); FREE( p_uit->release.psz_version ); FREE( p_uit->release.psz_svn_revision ); p_uit->release.i_type = UPDATE_RELEASE_TYPE_UNSTABLE; p_uit->release.i_status = UPDATE_RELEASE_STATUS_NONE; FREE( p_uit->mirror.psz_name ); FREE( p_uit->mirror.psz_location ); FREE( p_uit->mirror.psz_type );}/** * Perform an action on the update iterator * Only the first matching action is performed. * * \param p_uit update iterator * \param i_action update action bitmask. can be a combination of UPDATE_NEXT, UPDATE_PREV, UPDATE_MIRROR, UPDATE_RELEASE, UPDATE_FILE, UPDATE_RESET * \return UPDATE_FAIL if action fails, UPDATE_SUCCESS|(combination of UPDATE_MIRROR, UPDATE_RELEASE and UPDATE_FILE if these changed) otherwise */unsigned int update_iterator_Action( update_iterator_t *p_uit, int i_action ){ if( i_action & UPDATE_RESET ) { return update_iterator_Reset( p_uit ); } else if( i_action & UPDATE_MIRROR ) { if( i_action & UPDATE_PREV ) { return update_iterator_PrevMirror( p_uit ); } else { return update_iterator_NextMirror( p_uit ); } } /*else if( i_action & UPDATE_RELEASE ) { if( i_action & UPDATE_PREV ) { return update_iterator_PrevRelease( p_uit ); } else { return update_iterator_NextRelease( p_uit ); } }*/ else if( i_action & UPDATE_FILE ) { if( i_action & UPDATE_PREV ) { return update_iterator_PrevFile( p_uit ); } else { return update_iterator_NextFile( p_uit ); } } else { return UPDATE_SUCCESS; }}/** * Object to launch download thread in a different object */typedef struct { VLC_COMMON_MEMBERS char *psz_dest; //< Download destination char *psz_src; //< Download source char *psz_status; //< Download status displayed in progress dialog} download_thread_t;void update_download_for_real( download_thread_t *p_this );/** * Download the file selected by the update iterator. This function will * launch the download in a new thread (downloads can be long) * * \param p_uit update iterator * \param psz_dest destination file path * \return nothing */void update_download( update_iterator_t *p_uit, char *psz_dest ){ download_thread_t *p_dt = vlc_object_create( p_uit->p_u->p_vlc, sizeof( download_thread_t ) ); p_dt->psz_dest = strdup( psz_dest ); p_dt->psz_src = strdup( p_uit->file.psz_url ); asprintf( &p_dt->psz_status, "%s - %s (%s)\nSource: %s\nDestination: %s", p_uit->file.psz_description, p_uit->release.psz_version, p_uit->release.psz_svn_revision, p_uit->file.psz_url, psz_dest); vlc_thread_create( p_dt, "download thread", update_download_for_real, VLC_THREAD_PRIORITY_LOW, VLC_FALSE );}/** * Convert a long int size in bytes to a string * * \param l_size the size in bytes * \return the size as a string */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;}/** * The true download function. * * \param p_this the download_thread_t object * \return nothing */void update_download_for_real( download_thread_t *p_this ){ char *psz_dest = p_this->psz_dest; char *psz_src = p_this->psz_src; stream_t *p_stream; vlc_t *p_vlc = p_this->p_vlc; FILE *p_file = NULL; void *p_buffer; char *psz_status; int i_progress; long int l_size, l_done = 0; vlc_thread_ready( p_this ); asprintf( &psz_status, "%s\nDownloading... 0.0/? %.1f%% done", p_this->psz_status, 0.0 ); i_progress = intf_UserProgress( p_vlc, "Downloading...", psz_status, 0.0 ); p_stream = stream_UrlNew( p_vlc, psz_src ); if( !p_stream ) { msg_Err( p_vlc, "Failed to open %s for reading", psz_src ); intf_UserFatal( p_vlc, "Downloading...", "Failed to open %s for reading", psz_src ); intf_UserHide( p_vlc, i_progress ); } else { p_file = utf8_fopen( psz_dest, "w" ); if( !p_file ) { msg_Err( p_vlc, "Failed to open %s for writing", psz_dest ); intf_UserFatal( p_vlc, "Downloading...", "Failed to open %s for writing", psz_dest ); intf_UserHide( p_vlc, i_progress ); } else { long int l_read; char *psz_s1; char *psz_s2; l_size = stream_Size(p_stream); p_buffer = (void *)malloc( 1<<10 ); while( ( l_read = stream_Read( p_stream, p_buffer, 1<<10 ) ) ) { float f_progress; fwrite( p_buffer, l_read, 1, p_file ); l_done += l_read; free( psz_status ); f_progress = 100.0*(float)l_done/(float)l_size; psz_s1 = size_str( l_done ); psz_s2 = size_str( l_size ); asprintf( &psz_status, "%s\nDownloading... %s/%s (%.1f%%) done", p_this->psz_status, psz_s1, psz_s2, f_progress ); free( psz_s1 ); free( psz_s2 ); intf_UserProgressUpdate( p_vlc, i_progress, psz_status, f_progress ); } free( p_buffer ); fclose( p_file ); stream_Delete( p_stream ); free( psz_status ); psz_s2 = size_str( l_size ); asprintf( &psz_status, "%s\nDone %s (100.00%%)", p_this->psz_status, psz_s2 ); free( psz_s2 ); intf_UserProgressUpdate( p_vlc, i_progress, psz_status, 100.0 ); free( psz_status ); } } free( p_this->psz_dest ); free( p_this->psz_src ); free( p_this->psz_status );#ifdef WIN32 CloseHandle( p_this->thread_id );#endif vlc_object_destroy( p_this );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -