X-Git-Url: http://git.dolda2000.com/gitweb/?a=blobdiff_plain;f=clients%2Fgui-shell%2Fdsh.c;h=48d67e91728c42a17f655226b94dc6d86d06769e;hb=f782eb973d16b411ff67a743829d16cbd51427b4;hp=b7c9f63e00d1bdfd06207edcfbc01a7c6ac4ba1a;hpb=71aeadfc17b4c10c01a9ccd34f95a11e158ef343;p=doldaconnect.git diff --git a/clients/gui-shell/dsh.c b/clients/gui-shell/dsh.c index b7c9f63..48d67e9 100644 --- a/clients/gui-shell/dsh.c +++ b/clients/gui-shell/dsh.c @@ -46,6 +46,9 @@ struct trinfo { int ostate; + int opos, spos, speed; + time_t lastprog; + double sprog; }; void updatewrite(void); @@ -133,6 +136,10 @@ void inittr(struct dc_transfer *tr) tr->udata = tri = memset(smalloc(sizeof(*tri)), 0, sizeof(*tri)); tr->destroycb = destroytr; tri->ostate = tr->state; + tri->spos = tri->opos = tr->curpos; + tri->speed = -1; + tri->lastprog = time(NULL); + tri->sprog = ntime(); } #ifdef HAVE_NOTIFY @@ -154,26 +161,120 @@ void notify(NotifyNotification **n, char *cat, char *title, char *body, ...) } #endif +/* XXX: Achtung! Too DC-specific! */ +wchar_t *getfilename(wchar_t *path) +{ + wchar_t *p; + + if((p = wcsrchr(path, L'\\')) == NULL) + return(path); + else + return(p + 1); +} + +char *bytes2si(long long bytes) +{ + int i; + double b; + char *sd; + static char ret[64]; + + b = bytes; + for(i = 0; (b >= 1024) && (i < 4); i++) + b /= 1024; + if(i == 0) + sd = "B"; + else if(i == 1) + sd = "kiB"; + else if(i == 2) + sd = "MiB"; + else if(i == 3) + sd = "GiB"; + else + sd = "TiB"; + snprintf(ret, 64, "%.1f %s", b, sd); + return(ret); +} + +void updatetooltip(void) +{ + struct dc_transfer *tr; + struct trinfo *tri; + int t, i, a, st, bc, bt; + char *buf; + size_t bufsize, bufdata; + + t = i = a = 0; + st = bc = bt = -1; + for(tr = dc_transfers; tr != NULL; tr = tr->next) { + if(tr->dir != DC_TRNSD_DOWN) + continue; + tri = tr->udata; + t++; + if(tr->state == DC_TRNS_WAITING) + i++; + else if((tr->state == DC_TRNS_HS) || (tr->state == DC_TRNS_MAIN)) + a++; + if((tr->state == DC_TRNS_MAIN)) { + if(bt == -1) + bc = bt = 0; + bc += tr->curpos; + bt += tr->size; + if(tri->speed != -1) { + if(st == -1) + st = 0; + st += tri->speed; + } + } + } + buf = NULL; + bufsize = bufdata = 0; + bprintf(buf, "%s: %i", _("Transfers"), t); + if(t > 0) + bprintf(buf, " (%i/%i)", i, a); + if(bt > 0) + bprintf(buf, ", %.1f%%", (double)bc / (double)bt); + if(st != -1) + bprintf(buf, ", %s/s", bytes2si(st)); + addtobuf(buf, 0); + gtk_status_icon_set_tooltip(tray, buf); + free(buf); +} + void trstatechange(struct dc_transfer *tr, int ostate) { - if(ostate == DC_TRNS_MAIN) { + struct trinfo *tri; + + tri = tr->udata; + if((ostate == DC_TRNS_MAIN) && (tr->dir == DC_TRNSD_DOWN)) { if(tr->state == DC_TRNS_DONE) { #ifdef HAVE_NOTIFY - notify(&trnote, "transfer.complete", _("Transfer complete"), _("Finished downloading %ls from %ls"), tr->path, tr->peernick); + if(dcpid == 0) + notify(&trnote, "transfer.complete", _("Transfer complete"), _("Finished downloading %ls from %ls"), getfilename(tr->path), tr->peernick); #endif } else { #ifdef HAVE_NOTIFY - notify(&trnote, "transfer.error", _("Transfer interrupted"), _("The transfer of %ls from %ls was interrupted from the other side"), tr->path, tr->peernick); + if(dcpid == 0) + notify(&trnote, "transfer.error", _("Transfer interrupted"), _("The transfer of %ls from %ls was interrupted from the other side"), getfilename(tr->path), tr->peernick); #endif } } + if(tr->state == DC_TRNS_MAIN) { + tri->speed = -1; + tri->spos = tr->curpos; + tri->sprog = ntime(); + } } void updatetrinfo(void) { struct dc_transfer *tr; struct trinfo *tri; + time_t now; + double dnow; + now = time(NULL); + dnow = ntime(); for(tr = dc_transfers; tr != NULL; tr = tr->next) { if(tr->udata == NULL) { inittr(tr); @@ -183,8 +284,24 @@ void updatetrinfo(void) trstatechange(tr, tri->ostate); tri->ostate = tr->state; } + if(tri->opos != tr->curpos) { + tri->opos = tr->curpos; + tri->lastprog = now; + } +#ifdef NOTIFY + if((tr->state = DC_TRNS_MAIN) && (now - tri->lastprog > 600)) { + if(dcpid == 0) + notify(&trnote, "transfer.error", _("Transfer stalled"), _("The transfer of %ls from %ls has not made progress for 10 minutes"), getfilename(tr->path), tr->peernick); + } +#endif + if((tr->state == DC_TRNS_MAIN) && (dnow - tri->sprog > 10)) { + tri->speed = ((double)(tr->curpos - tri->spos) / (dnow - tri->sprog)); + tri->spos = tr->curpos; + tri->sprog = dnow; + } } } + updatetooltip(); } void trlscb(int resp, void *data) @@ -192,13 +309,18 @@ void trlscb(int resp, void *data) updatetrinfo(); } +gint trupdatecb(gpointer data) +{ + updatetrinfo(); + return(TRUE); +} + void logincb(int err, wchar_t *reason, void *data) { if(err != DC_LOGIN_ERR_SUCCESS) { msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Could not connect to server")); exit(1); } - gtk_status_icon_set_tooltip(tray, "Dolda Connect"); dc_queuecmd(NULL, NULL, L"notify", L"trans:act", L"on", L"trans:prog", L"on", NULL); dc_gettrlistasync(trlscb, NULL); connected = 1; @@ -234,6 +356,7 @@ void dcfdcb(gpointer data, gint source, GdkInputCondition cond) dc_uimisc_handlenotify(resp); updatetrinfo(); } + dc_freeresp(resp); } updatewrite(); } @@ -347,6 +470,19 @@ void dolcon(void) } } +void cb_shm_dolconf_activate(GtkWidget *uu1, gpointer uu2) +{ + int i; + + if((dcpid = fork()) == 0) { + for(i = 3; i < FD_SETSIZE; i++) + close(i); + execlp("dolconf", "dolconf", NULL); + perror("dolconf"); + exit(127); + } +} + void cb_shm_dolcon_activate(GtkWidget *uu1, gpointer uu2) { dolcon(); @@ -436,6 +572,7 @@ int main(int argc, char **argv) else startdaemon(); + g_timeout_add(10000, trupdatecb, NULL); gtk_main(); return(0);