Legend:
- Unmodified
- Added
- Removed
-
trunk/gtk/conf.c
r7 r24 450 450 for(ii = 0; ii < count; ii++) { 451 451 /* XXX need a better way to query running/stopped state */ 452 paused = (TR_STATUS_STOPPING == torrents[ii].status || 453 TR_STATUS_STOPPED == torrents[ii].status || 454 TR_STATUS_PAUSE == torrents[ii].status); 452 paused = ((TR_STATUS_STOPPING | TR_STATUS_PAUSE) & torrents[ii].status); 455 453 torrentfile = g_strescape(torrents[ii].info.torrent, ""); 456 454 torrentdir = g_strescape(torrents[ii].folder, ""); -
trunk/gtk/main.c
r23 r24 77 77 gboolean 78 78 exitcheck(gpointer gdata); 79 void 80 stoptransmission(void *tr); 79 81 GtkWidget * 80 82 makewind_toolbar(struct cbdata *data); … … 105 107 void 106 108 actionclick(GtkWidget *widget, gpointer gdata); 109 gint 110 intrevcmp(gconstpointer a, gconstpointer b); 107 111 void 108 112 doubleclick(GtkWidget *widget, GtkTreePath *path, GtkTreeViewColumn *col, … … 169 173 tr = tr_init(); 170 174 175 setuphandlers(stoptransmission, tr); 176 171 177 if(cf_init(tr_getPrefsDirectory(), &err)) { 172 178 if(cf_lock(&err)) { … … 202 208 gtk_widget_show_all(stateerr); 203 209 } else { 204 gtk_widget_show(errmsg_full(NULL, ( errfunc_t)gtk_main_quit,210 gtk_widget_show(errmsg_full(NULL, (callbackfunc_t)gtk_main_quit, 205 211 NULL, "%s", err)); 206 212 g_free(err); 207 213 } 208 214 } else { 209 gtk_widget_show(errmsg_full(NULL, ( errfunc_t)gtk_main_quit,215 gtk_widget_show(errmsg_full(NULL, (callbackfunc_t)gtk_main_quit, 210 216 NULL, "%s", err)); 211 217 g_free(err); … … 309 315 data->timer = -1; 310 316 317 blocksigs(); 318 311 319 for(ii = tr_torrentStat(data->tr, &st); 0 < ii; ii--) { 312 320 if(TR_TORRENT_NEEDS_STOP(st[ii-1].status)) { … … 320 328 free(st); 321 329 330 unblocksigs(); 331 322 332 /* XXX should disable widgets or something */ 323 333 … … 340 350 int ii; 341 351 352 blocksigs(); 353 342 354 for(ii = tr_torrentStat(data->cbdata->tr, &st); 0 < ii; ii--) { 343 if(TR_STATUS_PAUSE ==st[ii-1].status) {355 if(TR_STATUS_PAUSE & st[ii-1].status) { 344 356 /*fprintf(stderr, "quit: closing %i %s\n", ii, st[ii-1].info.name);*/ 345 357 tr_torrentClose(data->cbdata->tr, ii - 1); … … 354 366 time(NULL) - data->started < TRACKER_EXIT_TIMEOUT) { 355 367 updatemodel(data->cbdata); 368 unblocksigs(); 356 369 return TRUE; 357 370 } 358 359 /*fprintf(stderr, "quit: giving up on %i torrents\n",360 tr_torrentCount(data->cbdata->tr));*/361 362 for(ii = tr_torrentCount(data->cbdata->tr); 0 < ii; ii--)363 tr_torrentClose(data->cbdata->tr, ii - 1);364 371 365 372 /* exit otherwise */ … … 369 376 data->timer = -1; 370 377 378 /*fprintf(stderr, "quit: giving up on %i torrents\n", 379 tr_torrentCount(data->cbdata->tr));*/ 380 stoptransmission(data->cbdata->tr); 381 clearhandlers(); 382 unblocksigs(); 383 371 384 gtk_widget_destroy(GTK_WIDGET(data->cbdata->wind)); 372 tr_close(data->cbdata->tr);373 385 g_free(data->cbdata); 374 386 g_free(data); … … 376 388 377 389 return FALSE; 390 } 391 392 void 393 stoptransmission(void *tr) { 394 while(0 < tr_torrentCount(tr)) 395 tr_torrentClose(tr, 0); 396 tr_close(tr); 378 397 } 379 398 … … 590 609 char *upstr, *downstr, *str; 591 610 611 blocksigs(); 612 592 613 max = tr_torrentStat(data->tr, &st); 593 614 for(ii = 0; ii < max; ii++) { … … 626 647 /* the status of the selected item may have changed, so update the buttons */ 627 648 fixbuttons(NULL, data); 649 650 unblocksigs(); 628 651 629 652 return TRUE; … … 791 814 assert(actindex < ALEN(actionitems)); 792 815 816 blocksigs(); 793 817 updatesave = FALSE; 794 818 count = tr_torrentStat(data->tr, &sb); 795 819 796 for(ii = g_list_ first(ids); NULL != ii; ii = ii->next) {820 for(ii = g_list_sort(ids, intrevcmp); NULL != ii; ii = ii->next) { 797 821 index = GPOINTER_TO_INT(ii->data); 798 822 if(index >= count) { … … 820 844 tr_torrentClose(data->tr, index); 821 845 updatesave = TRUE; 846 /* XXX should only unselect deleted rows */ 847 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(data->view)); 822 848 break; 823 849 case ACT_INFO: … … 836 862 } 837 863 864 unblocksigs(); 865 838 866 if(FROM_BUTTON == from) 839 867 g_list_free(ids); 868 } 869 870 gint 871 intrevcmp(gconstpointer a, gconstpointer b) { 872 int aint = GPOINTER_TO_INT(a); 873 int bint = GPOINTER_TO_INT(b); 874 875 if(bint > aint) 876 return 1; 877 else if(bint < aint) 878 return -1; 879 else 880 return 0; 840 881 } 841 882 … … 867 908 } 868 909 910 blocksigs(); 911 869 912 if(0 != tr_torrentInit(tr, torrent)) { 913 unblocksigs(); 870 914 /* XXX would be nice to have errno strings, are they printed to stdout? */ 871 915 errmsg(parentwind, "Failed to open torrent file %s", torrent); … … 887 931 if(!paused) 888 932 tr_torrentStart(tr, tr_torrentCount(tr) - 1); 933 934 unblocksigs(); 935 889 936 return TRUE; 890 937 } … … 909 956 ret = cf_savestate(count, stat, &errstr); 910 957 else { 958 blocksigs(); 911 959 count = tr_torrentStat(tr, &st); 960 unblocksigs(); 912 961 ret = cf_savestate(count, st, &errstr); 913 962 free(st); -
trunk/gtk/util.c
r11 r24 28 28 #include <sys/stat.h> 29 29 #include <errno.h> 30 #include <signal.h> 30 31 #include <stdarg.h> 31 32 #include <string.h> … … 35 36 #include "util.h" 36 37 38 static void 39 sigexithandler(int sig); 37 40 static void 38 41 errcb(GtkWidget *wind, int resp, gpointer data); … … 99 102 } 100 103 104 static int exit_sigs[] = {SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGUSR2}; 105 static callbackfunc_t exit_func = NULL; 106 static void *exit_data = NULL; 107 static int exit_block_level = 0; 108 109 void 110 setuphandlers(callbackfunc_t func, void *data) { 111 struct sigaction sa; 112 unsigned int ii; 113 114 exit_data = data; 115 exit_func = func; 116 117 bzero(&sa, sizeof(sa)); 118 sa.sa_handler = sigexithandler; 119 for(ii = 0; ii < ALEN(exit_sigs); ii++) 120 sigaction(exit_sigs[ii], &sa, NULL); 121 } 122 123 void 124 clearhandlers(void) { 125 struct sigaction sa; 126 unsigned int ii; 127 128 bzero(&sa, sizeof(sa)); 129 sa.sa_handler = SIG_DFL; 130 for(ii = 0; ii < ALEN(exit_sigs); ii++) 131 sigaction(exit_sigs[ii], &sa, NULL); 132 } 133 134 static void 135 sigexithandler(int sig) { 136 exit_func(exit_data); 137 clearhandlers(); 138 raise(sig); 139 } 140 141 void 142 blocksigs(void) { 143 sigset_t mask; 144 unsigned int ii; 145 146 if(0 < (exit_block_level++)) 147 return; 148 149 sigemptyset(&mask); 150 for(ii = 0; ii < ALEN(exit_sigs); ii++) 151 sigaddset(&mask, exit_sigs[ii]); 152 sigprocmask(SIG_BLOCK, &mask, NULL); 153 } 154 155 void 156 unblocksigs(void) { 157 sigset_t mask; 158 unsigned int ii; 159 160 if(0 < (--exit_block_level)) 161 return; 162 163 sigemptyset(&mask); 164 for(ii = 0; ii < ALEN(exit_sigs); ii++) 165 sigaddset(&mask, exit_sigs[ii]); 166 sigprocmask(SIG_UNBLOCK, &mask, NULL); 167 } 168 101 169 GtkWidget * 102 170 errmsg(GtkWindow *wind, const char *format, ...) { … … 112 180 113 181 GtkWidget * 114 errmsg_full(GtkWindow *wind, errfunc_t func, void *data,182 errmsg_full(GtkWindow *wind, callbackfunc_t func, void *data, 115 183 const char *format, ...) { 116 184 GtkWidget *dialog; … … 125 193 126 194 GtkWidget * 127 verrmsg(GtkWindow *wind, errfunc_t func, void *data,195 verrmsg(GtkWindow *wind, callbackfunc_t func, void *data, 128 196 const char *format, va_list ap) { 129 197 GtkWidget *dialog; … … 156 224 errcb(GtkWidget *widget, int resp SHUTUP, gpointer data) { 157 225 GList *funcdata; 158 errfunc_t func;226 callbackfunc_t func; 159 227 160 228 if(NULL != data) { -
trunk/gtk/util.h
r11 r24 41 41 #define ALEN(a) (sizeof(a) / sizeof((a)[0])) 42 42 43 /* used for a callback function with a data parameter */ 44 typedef void (*callbackfunc_t)(void*); 45 46 /* try to interpret a string as a textual representation of a boolean */ 43 47 gboolean 44 48 strbool(const char *str); 45 49 50 /* return a human-readable string for the size given in bytes with the 51 requested number of decimal places. the string must be g_free()d */ 46 52 char * 47 53 readablesize(guint64 size, int decimals); 48 54 55 /* create a directory and any missing parent directories */ 49 56 gboolean 50 57 mkdir_p(const char *name, mode_t mode); 51 58 52 typedef void (*errfunc_t)(void*); 59 /* set up a handler for various fatal signals */ 60 void 61 setuphandlers(callbackfunc_t func, void *data); 62 63 /* clear the handlers for fatal signals */ 64 void 65 clearhandlers(void); 66 67 /* blocks and unblocks delivery of fatal signals. calls to these 68 functions can be nested as long as unblocksigs() is called exactly 69 as many times as blocksigs(). only the first blocksigs() will 70 block signals and only the last unblocksigs() will unblock them. */ 71 void 72 blocksigs(void); 73 void 74 unblocksigs(void); 53 75 54 76 /* if wind is NULL then you must call gtk_widget_show on the returned widget */ … … 62 84 63 85 GtkWidget * 64 errmsg_full(GtkWindow *wind, errfunc_t func, void *data,86 errmsg_full(GtkWindow *wind, callbackfunc_t func, void *data, 65 87 const char *format, ...) 66 88 #ifdef __GNUC__ … … 70 92 71 93 GtkWidget * 72 verrmsg(GtkWindow *wind, errfunc_t func, void *data,94 verrmsg(GtkWindow *wind, callbackfunc_t func, void *data, 73 95 const char *format, va_list ap); 74 96
Note: See TracChangeset
for help on using the changeset viewer.