⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 progress.c

📁 linux下流媒体下载程序代码
💻 C
字号:
/*********************************************************************** *    progress.c:  download management functions *********************************************************************** * Copyright (C) 2007 metro <me_t_ro@yahoo.com> * * This file is part of msdl, media stream downloader * display progress of donwload. * * 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., * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. * ***********************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/time.h>#include "msdl.h"#include "msdllib.h"#include "display.h"#include "network.h"#include "progress.h"static void fill_buffer_with_ws(char *buffer,int buflen);void progress_dl_start(struct progressinfo_t *pgi){    gettimeofday(&(pgi->tv_dl_start),NULL);    memcpy(&(pgi->tv_last_disp_update), &(pgi->tv_dl_start),sizeof(struct timeval));    memcpy(&(pgi->tv_last_speed_update),&(pgi->tv_dl_start),sizeof(struct timeval));    memcpy(&(pgi->tv_last_etl_speed_update), &(pgi->tv_dl_start),sizeof(struct timeval));        pgi->last_speed_size_written = 0;    pgi->last_etl_speed_size_written = 0;    pgi->speed = 0;    pgi->etl_speed = 0;}void progress_update(struct progressinfo_t *pgi,		     uint64_t entire_size,uint64_t size_written){    /*     * tv_last_time is to update download speed.     */    struct timeval tv_cur_time;    struct timeval tv_diff_disp;              /* time since last display update   */    struct timeval tv_diff_speed;             /* time since last speed update     */    struct timeval tv_diff_etl_speed;         /* time since last etl speed update */    struct timeval tv_uptime;                 /* time since donwload start        */    gettimeofday(&tv_cur_time,NULL);    timersub(&tv_cur_time,&(pgi->tv_last_disp_update),&tv_diff_disp);    timersub(&tv_cur_time,&(pgi->tv_last_speed_update),&tv_diff_speed);    timersub(&tv_cur_time,&(pgi->tv_last_etl_speed_update),&tv_diff_etl_speed);    timersub(&tv_cur_time,&(pgi->tv_dl_start),&tv_uptime);        /* 1 sec speed update     */    if(tv_diff_speed.tv_sec >= PROGRESS_SPEED_UPDATE_THRESHOLD) {	/* update speed */	pgi->speed = (size_written - pgi->last_speed_size_written) / tv_diff_speed.tv_sec;	/* update last_* info */	pgi->last_speed_size_written = size_written;	memcpy(&(pgi->tv_last_speed_update),&tv_cur_time,sizeof(struct timeval));    }    /* last 3 second speed for remain time guess */    if(tv_diff_etl_speed.tv_sec >= PROGRESS_ETL_SPEED_UPDATE_THRESHOLD) {	/* update etl speed */	pgi->etl_speed =	    (size_written - pgi->last_etl_speed_size_written) / tv_diff_etl_speed.tv_sec;			pgi->last_etl_speed_size_written = size_written;	memcpy(&(pgi->tv_last_etl_speed_update),&tv_cur_time,sizeof(struct timeval));    }    /* 0.5 sec display update */    if(tv_diff_disp.tv_sec >= 1 || tv_diff_disp.tv_usec > 500000) {	/* update output */		/*	 * if uptime was less than 8 seconds, don't display ETA.	 * you can just wait.	 */	if(tv_uptime.tv_sec < PROGRESS_ETL_DISPLAY_MIN_TIME) {	    display_progress_info(entire_size,size_written,pgi->speed,-1);	}	else {	    display_progress_info(entire_size,size_written,pgi->speed,pgi->etl_speed);	}	/* update display */	memcpy(&(pgi->tv_last_disp_update),&tv_cur_time,sizeof(struct timeval));    }}/* * progress line look like this.. * DL: xxxxx/xxxxx B -- xxx%           6.1K/s (11chars)    ETA --:--:--  * * @filsize    : entire file size (what server told) * @downloaded : current file size (downloaded) * @speed      : speed to display bandwidth * @etl_speed  : speed for ETA */void display_progress_info(uint64_t filesize,uint64_t downloaded,			   int64_t speed,int64_t etl_speed){    int termwidth = get_current_termwidth();        char *buffer = xmalloc(termwidth);    static char column1[45];    static char column2[11];    static char column3[13];        memset(buffer,0,termwidth);        create_recved_bytes(column1,45,filesize,downloaded);    strncat(buffer,column1,termwidth - 1);    fill_buffer_with_ws(buffer,termwidth-24);    create_dl_speed(column2,11,speed);    strncat(buffer,column2,termwidth - 1);    fill_buffer_with_ws(buffer,termwidth-13);        create_remain_time(column3,13,filesize,downloaded,etl_speed);    strncat(buffer,column3,termwidth - 1);    fill_buffer_with_ws(buffer,termwidth);        display(MSDL_NOR,"\r%s",buffer);    free(buffer);}/* * get time since pgi.tv_dl_start * return value: uptime in second */time_t progress_get_dl_uptime(struct progressinfo_t *pgi,struct timeval *tv_uptime){    struct timeval tvu,tvcur;        gettimeofday(&tvcur,NULL);    timersub(&tvcur,&(pgi->tv_dl_start),&tvu);        if(tv_uptime) {	memcpy(tv_uptime,&tvu,sizeof(struct timeval));    }    return tvu.tv_sec;}/* * get donwload bandwidth so far. * counts from dl_start in progressinfo * return value: bandwidth */int64_t progress_get_average_bandwidth(struct progressinfo_t *pgi,uint64_t current_size){    struct timeval tv_uptime;    double seconds;    progress_get_dl_uptime(pgi,&tv_uptime);    if(tv_uptime.tv_sec == 0 && tv_uptime.tv_usec == 0) {	return -1; /* 0 microseconds passed, which is very illegal... */    }    else {	seconds = tv_uptime.tv_sec + (double)tv_uptime.tv_usec * 0.000001;	return (int64_t)((double)current_size / seconds);    }    return -1;}static void fill_buffer_with_ws(char *buffer,int buflen){    if(strlen(buffer) < buflen) {	memset(buffer + strlen(buffer),' ',buflen - strlen(buffer) - 1);    }    buffer[buflen - 1] = '\0';}/* * display download progress. */void create_recved_bytes(char *buffer,int width,			 uint64_t filesize,uint64_t downloaded){    memset(buffer,0,width);    if(width < 45) {	return;    }    if(filesize == 0) {	snprintf(buffer,width - 1,"DL: %lld B",(long long)downloaded);    }    else {	/* snprintf is safe. */	snprintf(buffer,width - 1,"DL: %lld/%lld B -- %3d%%", /* 15chars + numsx2 */		 (long long)downloaded,		 (long long)filesize,		 (int)(((double)downloaded/(double)filesize) * 100));    }}/* * display download speed. * empty string if speed < 0 */void create_dl_speed(char *buffer,int width,		     int64_t speed){    memset(buffer,0,width);    if(width < 11) {	return;    }    if(speed < 0) {	strncpy(buffer,"",width);    }    else if(speed > 1000000000000LL) {	snprintf(buffer,width - 1,"%.1fT/s",(double)speed / 1000000000000LL);    }    else if(speed > 1000000000) {	snprintf(buffer,width - 1,"%.1fG/s",(double)speed / 1000000000);    }    else if(speed > 1000000) {	snprintf(buffer,width - 1,"%.1fM/s",(double)speed / 1000000);    }    else if(speed > 1000) {	snprintf(buffer,width - 1,"%.1fK/s",(double)speed / 1000);    }    else {	snprintf(buffer,width - 1,"%.1dB/s",(int)speed);    }}/* * display ETL (Estimated Time Left) * empty string if etl_speed < 0 */void create_remain_time(char *buffer,int width,			uint64_t entire_size,uint64_t current_size,int64_t etl_speed){    memset(buffer,0,width);    if(width < 13) {	return; /* prevent overflow */    }    if(etl_speed < 0) {	strncpy(buffer,"",width);    }    else if(entire_size && entire_size == current_size) {	snprintf(buffer,width - 1,"Complete");                  /* 8 chars */    }    else if(entire_size) {	uint64_t etl = 0;	if(etl_speed) {	    etl = (entire_size - current_size)/ etl_speed;	}		if((etl_speed == 0) || (etl / 3600) > 100) { /* etl == 0 || 2slow:) */	    snprintf(buffer,width - 1,"ETA --:--");             /* 9 chars */	}	else {	    if(etl/3600) { /* have to display hour */		snprintf(buffer,width - 1,"ETA %02d:%02d:%02d", /* 12 chars */			 (int)(etl / 3600),(int)((etl % 3600 / 60)),(int)(etl % 60));	    }	    else {		snprintf(buffer,width - 1,"ETA %02d:%02d",      /* 9 chars  */			 (int)((etl % 3600 / 60)),(int)(etl % 60));	    }	}    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -