2 This program is free software; you can redistribute it and/or modify
3 it under the terms of the GNU General Public License as published by
4 the Free Software Foundation; either version 2 of the License, or
5 (at your option) any later version.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 #include <sys/types.h>
31 #ifdef ENABLE_HDDTEMP_QUERY
32 #include <sys/socket.h>
34 #include <netinet/in.h>
45 void update_swap_matrix(App
*app
) {
46 SwapMatrix
*sm
= &app
->sm
;
49 unsigned sw_in
= ceil(get_swapin_throughput()*4), sw_out
= ceil(get_swapout_throughput()*4);
50 for (i
=0; i
< sw_in
+sw_out
; i
++) {
51 col
= rand() % sm
->ncol
;
52 row
= rand() % sm
->nrow
;
53 if (sm
->intensity
[row
][col
] == 0) {
54 sm
->pre_cnt
[row
][col
] = rand() % 10; //(app->update_stats_mult);
56 sm
->intensity
[row
][col
] = app
->swap_matrix_lighting
* ((i
< sw_in
) ? -1 : +1);
60 void update_io_matrix_rw(App
*app
, float mbs
, int op
) {
61 IOMatrix
*io
= &app
->iom
;
63 if (mbs
> 10000) mbs
= 10000; /* very quick and ugly fix for the strange bug which only occurs in gkhdplop */
64 int bsz
= MAX(SQR(16*64./(app
->dock
->w
+ app
->dock
->h
)),2); /* 1024 for a 64x64 applet */
66 float v
= MIN(mbs
, bsz
); /* a throughput > 1MB/s will create more than one spot */
68 l
= calloc(1,sizeof(*l
)); assert(l
);
70 l
->n
= (int)(log2f(1+v
*1024)/10.);
72 l
->i
= rand() % io
->h
;
73 l
->j
= rand() % io
->w
;
78 void update_io_matrix(App
*app
) {
79 update_io_matrix_rw(app
, get_read_throughput(), OP_READ
);
80 update_io_matrix_rw(app
, get_write_throughput(), OP_WRITE
);
85 void evolve_io_matrix(App
*app
, DATA32
* __restrict buff
) {
86 IOMatrix
*io
= &app
->iom
;
88 int * __restrict pl
, * __restrict tmp
;
89 IO_op_lst
*o
= io
->ops
, *po
= NULL
, *no
;
91 io
->v
[o
->i
+1][o
->j
+1] = ((o
->op
== OP_READ
) ? +50000000 : -50000000);
94 if (po
) { po
->next
= no
; }
95 else { io
->ops
= no
; }
101 /* brain-dead diffusion */
103 int * __restrict l
= io
->v
[io
->h
+3];
104 for (j
=1; j
< io
->w
+1; ++j
) pl
[j
] = 0;
105 for (i
=1; i
< io
->h
+1; ++i
) {
107 for (j=1; j < io->w+1; ++j) {
108 l[j] = io->v[i][j]*0.99 + (io->v[i][j-1] + io->v[i][j+1] + pl[j] + io->v[i+1][j] - 4*io->v[i][j])/5.;
112 float *__restrict nl = io->v[i+1]+1;
113 float *__restrict cl = io->v[i];
114 for (j=1; j < io->w+1; ++j, ++cl) {
115 l[j] = (cl[1])*0.99 + (cl[0] + cl[2] + pl[j] + *nl++ - 4*cl[1])/5.;
118 int *__restrict dest
;
119 int *__restrict pn
= io
->v
[i
+1]+1;
120 int *__restrict pc
= io
->v
[i
]+1;
121 int *__restrict pp
= pl
+1;
122 int pj
,cj
=0,nj
=*pc
++;
123 for (j
=0, dest
=l
+1, pj
= 0.; j
< io
->w
; ++j
) {
124 pj
= cj
; cj
= nj
; nj
= *pc
++;
125 *dest
= (cj
* 37)/200 + (pj
+ nj
+ *pp
++ + *pn
++)/5;
126 /* *dest = 99*(cj + (pj + nj + *pp++ + *pn++)/(4))/200; */
127 //} for (j=0, dest=l+1; j < io->w; ++j) {
128 int v
= (int)(*dest
++ >> 10);
129 if (v
== 0) { *buff
++ = io
->cm
.p
[CMAPSZ
/2]; continue; }
130 if (v
> CMAPSZ
/4) { /* cheaper than a log(vv) ... */
131 v
= MIN(CMAPSZ
/4 + (v
-CMAPSZ
/4)/16,CMAPSZ
/2-1);
132 } else if (v
< -CMAPSZ
/4) {
133 v
= MAX(-CMAPSZ
/4 + (v
+CMAPSZ
/4)/16,-CMAPSZ
/2);
135 *buff
++ = io
->cm
.p
[v
+CMAPSZ
/2];
138 tmp
= pl
; pl
= io
->v
[i
]; io
->v
[i
] = l
; l
= tmp
;
139 io
->v
[io
->h
+2] = pl
; io
->v
[io
->h
+3] = l
;
145 static void draw_io_matrix(App
*app
, DATA32
* __restrict buff
) {
146 IOMatrix
*io
= &app
->iom
;
148 for (i
=0; i
< io
->h
; ++i
) {
149 for (j
=0; j
< io
->w
; ++j
) {
150 float vv
= io
->v
[i
+1][j
+1];
151 int v
= (int)(vv
* 32768); //((int)ldexpf(vv,15)); /* (int)v*(2^15) */
152 //if (v == 0) continue;
153 //if (v < 0) v*=3; /* write op are rare, so they are brighter .. */
154 if (v
> CMAPSZ
/4) { /* cheaper than a log(vv) ... */
155 v
= MIN(CMAPSZ
/4 + (v
-CMAPSZ
/4)/16,CMAPSZ
/2-1);
156 } else if (v
< -CMAPSZ
/4) {
157 v
= MAX(-CMAPSZ
/4 + (v
+CMAPSZ
/4)/16,-CMAPSZ
/2);
159 //assert(v+CMAPSZ/2>=0);
160 //assert(v+CMAPSZ/2 < sizeof io->cm.p);
161 *buff
++ /*[j+i*io->w]*/ = io
->cm
.p
[v
+CMAPSZ
/2];
167 void draw_swap_matrix(App
*app
) {
168 SwapMatrix
*sm
= &app
->sm
;
169 int rcnt
[sm
->nrow
+1], ccnt
[sm
->ncol
+1];
172 static int darkcnt
= 0;
173 memset(rcnt
, 0, sizeof rcnt
); memset(ccnt
, 0, sizeof ccnt
);
174 for (row
= 0; row
< sm
->nrow
; row
++) {
175 for (col
= 0; col
< sm
->ncol
; col
++) {
176 if (sm
->pre_cnt
[row
][col
]>0) { isswapping
= 1; sm
->pre_cnt
[row
][col
]--; }
179 if (isswapping
) darkcnt
= MIN(darkcnt
+1,7);
180 else darkcnt
= MAX(darkcnt
-1, 0);
182 /* darken everything */
184 imlib_context_set_color(0, 0, 0, (darkcnt
+1)*16);
185 imlib_image_fill_rectangle(0, 0, app
->dock
->w
, app
->dock
->h
);
188 for (row
= 0; row
< sm
->nrow
; row
++) {
189 for (col
= 0; col
< sm
->ncol
; col
++) {
190 if (sm
->intensity
[row
][col
] && sm
->pre_cnt
[row
][col
]==0) {
191 int v
= sm
->intensity
[row
][col
];
192 v
= (v
* app
->swap_matrix_luminosity
)/(int)app
->swap_matrix_lighting
;
193 rcnt
[row
] = MAX(rcnt
[row
],abs(v
)); ccnt
[col
] = MAX(ccnt
[col
],abs(v
));
194 rcnt
[row
+1] = MAX(rcnt
[row
+1],abs(v
)); ccnt
[col
+1] = MAX(ccnt
[col
+1],abs(v
));
196 /*if (v > 0) imlib_context_set_color(100+v, 155-v, 155-v, 250);
197 else imlib_context_set_color(0, 100-v, 0, 250);*/
198 if (v
> 0) imlib_context_set_color(255, 50, 50, MIN(v
+80,255));
199 else imlib_context_set_color(50, 255, 50, MIN(v
+80,255));
200 imlib_image_fill_rectangle(row
*sm
->w
+1,col
*sm
->w
+1,sm
->w
-1,sm
->w
-1);
202 if (sm
->intensity
[row
][col
] > 0) {
203 sm
->intensity
[row
][col
]--;
204 } else if (sm
->intensity
[row
][col
] < 0) {
205 sm
->intensity
[row
][col
]++;
212 for (row
= 0; row
< sm
->nrow
+1; row
++) {
214 imlib_context_set_color(255, 255, 255, MIN(rcnt
[row
]*2/3, 255));
215 imlib_image_draw_line(row
*sm
->w
,0,row
*sm
->w
,app
->dock
->w
,0);
218 for (col
= 0; col
< sm
->ncol
+1; col
++) {
220 imlib_context_set_color(255, 255, 255, MIN(ccnt
[col
]*2/3, 255));
221 imlib_image_draw_line(0,col
*sm
->w
,app
->dock
->h
,col
*sm
->w
,0);
226 float f2celsius(float Tf
) {
227 return (5./9.)*(Tf
-32.);
230 float celsius2f(float Tc
) {
231 return (9./5.)*Tc
+32.;
234 static void query_hddtemp(App
*app
) {
237 struct sockaddr_in addr
;
239 SET_VEC(app
->disk_temperature
, -1, 0, app
->nb_hd
);
240 if ((h
= gethostbyname("127.0.0.1")) == NULL
) {
241 fprintf(stderr
, "gethostbyname(localhost) failed : %s\n", strerror(errno
)); return;
243 if ((fd
= socket(h
->h_addrtype
, SOCK_STREAM
,0)) == -1) {
244 fprintf(stderr
, "can't create socket : %s\n", strerror(errno
)); return;
246 memset(&addr
,0,sizeof(struct sockaddr_in
));
247 addr
.sin_family
= AF_INET
;
248 addr
.sin_port
= htons(Prefs
.hddtemp_port
);
249 addr
.sin_addr
.s_addr
= ((struct in_addr
*)(h
->h_addr
))->s_addr
;
250 if (connect(fd
, (struct sockaddr
*)&addr
, sizeof addr
) < 0) {
252 fprintf(stderr
,"can't connect to 127.0.0.1:%d : %s\n", Prefs
.hddtemp_port
, strerror(errno
));
254 Prefs
.enable_hddtemp
= 0;
260 int nn
=read(fd
,buff
+n
,MAX((int)(sizeof buff
) - n
,0));
261 if (nn
<= 0) { if (nn
< 0) n
=nn
; break; }
263 } while (n
!= sizeof buff
);
265 BLAHBLAH(2,printf("n=%d, err=%s\n",n
, strerror(errno
)));
270 buff
[MIN(n
,(int)sizeof buff
- 1)] = 0;
271 for (dl
= first_hd_in_list(), cnt
= 0; dl
; dl
= next_hd_in_list(dl
), cnt
++) {
272 if (dl
->enable_hddtemp
) {
274 if ((s
=strstr(buff
, dl
->dev_path
))) { found
= 1; s
+= strlen(dl
->name
); }
277 if (s
&& ((s
=strchr(s
+1,'|')))) {
279 char *p
= strchr(++s
,'|'), oldv
=0;
282 if (*p
&& toupper(p
[1]) == 'F') unit
= 'F';
285 BLAHBLAH(1,printf("temperature of '%s' : %s %c\n", dl
->name
, s
, unit
));
286 if (strcmp(s
,"SLP") == 0) app
->disk_temperature
[cnt
] = -2;
289 if (unit
== 'C' && Prefs
.temperatures_unit
== 'F') {
290 temp
= (int)(floor(celsius2f(temp
)+.5));
291 } else if (unit
== 'F' && Prefs
.temperatures_unit
== 'C') {
292 temp
= (int)(floor(f2celsius(temp
)+.5));
294 app
->disk_temperature
[cnt
] = temp
;
296 if (p
) *p
= oldv
; /* or bug... */
299 ONLY_NTIMES(4,fprintf(stderr
, "could not find device '%s' in the output of hddtemp: '%s'\n", dl
->name
, buff
));
303 } else { fprintf(stderr
, "error with hddtemp: %s\n", strerror(errno
)); }
307 const char *power_mode_str(int m
) {
309 case HD_ACTIVE
: return "active/idle";
310 case HD_STANDBY
: return "standby";
311 case HD_SLEEP
: return "sleep";
314 return "unknown/error";
318 void sethw(App
*app
, int lw
, int lh
, int pos
, int *px
, int *py
, int *pw
, int *ph
) {
319 *px
= *py
= 0; *pw
= lw
; *ph
= lh
;
320 if (!(pos
& (AL_RIGHT
| AL_LEFT
| AL_HCENTER
))) *pw
= app
->dock
->w
;
321 if (pos
& AL_RIGHT
) *px
= app
->dock
->w
- lw
;
322 else if (pos
& AL_HCENTER
) *px
= (app
->dock
->w
- lw
)/2;
323 else if (pos
& AL_LEFT
) *px
= 0;
324 else { *px
= 0; *pw
= app
->dock
->w
; }
325 if (pos
& AL_BOTTOM
) *py
= app
->dock
->h
- lh
;
326 else if (pos
& AL_VCENTER
) *py
= (app
->dock
->h
- lh
)/2;
327 else if (pos
& AL_TOP
) *py
= 0;
328 else { *py
= 0; *ph
= app
->dock
->h
; }
331 static void my_imlib_text_draw(int x
, int y
, const char *s
) {
332 char s2
[100]; snprintf(s2
,100,"%s ",s
); /* my imlib2 often forgets half of the last character... */
333 imlib_text_draw(x
,y
,s2
);
336 int is_displayed(int hd_id
, int part_id
) {
337 return (((hd_id
== app
->filter_hd
) || (app
->filter_hd
== -1)) &&
338 ((part_id
== app
->filter_part
) || (app
->filter_part
== -1)));
341 void change_displayed_hd(int dir
) {
342 DiskList
*dl
= find_id(app
->filter_hd
, app
->filter_part
);
344 app
->filter_hd
= -1; app
->filter_part
= -1;
345 dl
= find_id(app
->filter_hd
, app
->filter_part
); assert(dl
);
348 if (app
->filter_hd
== -1 && app
->filter_part
== -1) {
349 app
->filter_hd
= -1; app
->filter_part
= 0;
350 } else if (app
->filter_hd
== -1 && app
->filter_part
== 0) {
351 app
->filter_hd
= first_dev_in_list()->hd_id
;
352 app
->filter_part
= -1;
353 } else if (app
->filter_hd
!= -1 && app
->filter_part
!= -1) {
354 DiskList
*dl2
= dl
->next
;
356 if (dl2
->hd_id
== app
->filter_hd
)
357 app
->filter_part
= dl2
->part_id
;
359 app
->filter_hd
= dl2
->hd_id
;
360 app
->filter_part
= -1;
364 app
->filter_part
= -1;
366 } else if (app
->filter_hd
!= -1) {
367 app
->filter_part
= dl
->part_id
;
369 app
->filter_hd
= dl
->hd_id
;
371 } else if (dir
< 0) { /* very very bourin */
372 int ph
, pph
, pp
, ppp
;
373 ph
= app
->filter_hd
; pp
= app
->filter_part
;
375 pph
= app
->filter_hd
; ppp
= app
->filter_part
;
376 change_displayed_hd(+1);
377 } while (!(app
->filter_hd
== ph
&& app
->filter_part
== pp
));
378 app
->filter_hd
= pph
; app
->filter_part
= ppp
;
380 app
->displayed_hd_changed
= 1;
383 void next_displayed_hd() {
384 BLAHBLAH(1,printf("next_displayed_hd() : filter_hd=%d, filter_part=%d\n", app
->filter_hd
, app
->filter_part
));
385 change_displayed_hd(-1);
386 init_stats(app
->update_display_delay_ms
*1e-3*app
->update_stats_mult
);
389 void prev_displayed_hd() {
390 BLAHBLAH(1,printf("prev_displayed_hd() : filter_hd=%d, filter_part=%d\n", app
->filter_hd
, app
->filter_part
));
391 change_displayed_hd(+1);
392 init_stats(app
->update_display_delay_ms
*1e-3*app
->update_stats_mult
);
395 const char *shorten_name(DiskList
*dl
) {
397 if (dl
->name
&& strlen(dl
->name
)) {
398 const char *p
= dl
->name
;
399 if (strchr(p
,'/')) p
= strrchr(p
,'/')+1;
400 if (strlen(p
) == 0) p
= dl
->name
;
401 snprintf(s
, sizeof s
, "%s%s", dl
->part_id
? " " : "", p
);
402 } else strncpy(s
, dl
->name
, sizeof s
);
406 static void draw_hdlist(App
*app
) {
407 if (Prefs
.hdlist_pos
== AL_NONE
) return;
410 int dev_cnt
, hd_cnt
, w
;
411 static int lw
= -1, lh
= -1, lx
= -1, ly
= -1, h
= -1,
414 if (!app
->smallfont
) return;
415 if (app
->displayed_hd_changed
) { lx
= -1; app
->displayed_hd_changed
= 0; }
416 imlib_context_set_font(app
->smallfont
);
418 if (lx
== -1 || reshape_cnt
!= app
->reshape_cnt
) {
421 //printf("update : first displayed(%d) = %p\n", cnt, dl);
423 for (dl
= first_dev_in_list(), dev_cnt
=hd_cnt
=-1; dl
; dl
= dl
->next
) {
424 if (dl
->part_id
== 0) ++hd_cnt
; if (!is_displayed(dl
->hd_id
, dl
->part_id
)) continue; ++dev_cnt
;
425 imlib_get_text_size(shorten_name(dl
),&w
,&h
);
429 if (!Prefs
.disable_hd_leds
) { lw
+= 5; }
430 if (Prefs
.enable_hddtemp
) imlib_get_text_size(" 000",&wtemp
,&h
);
431 if (lw
+ wtemp
> (int)(app
->dock
->w
*2/3)) { lw
= app
->dock
->w
; }
433 sethw(app
,lw
,lh
,Prefs
.hdlist_pos
,&lx
,&ly
,&lw
,&lh
);
434 reshape_cnt
= app
->reshape_cnt
;
437 imlib_context_set_color(100, 100, 100, 150);
438 imlib_image_fill_rectangle(lx
,ly
,lw
,lh
);
439 imlib_context_set_color(100, 100, 100, 200);
440 imlib_image_draw_rectangle(lx
-1,ly
-1,lw
+2,lh
+2);
442 for (dl
= first_dev_in_list(), dev_cnt
=hd_cnt
=-1; dl
; dl
= dl
->next
) {
443 if (dl
->part_id
==0) ++hd_cnt
; if (!is_displayed(dl
->hd_id
, dl
->part_id
)) continue; ++dev_cnt
;
444 int x
= lx
, y
= ly
+ lh
- dev_cnt
* h
;
445 if (!Prefs
.disable_hd_leds
) {
447 imlib_context_set_color(50, 255, 50, 25*dl
->touched_r
--);
448 imlib_image_fill_rectangle(lx
+1,y
-5,3,3);
451 imlib_context_set_color(255,100-10*dl
->touched_w
,100-10*dl
->touched_w
, 25*dl
->touched_w
- 1);
453 imlib_image_fill_rectangle(lx
+1,y
-9,3,3);
457 imlib_context_set_color(200, 255, 255, 200);
458 my_imlib_text_draw(x
,y
-h
,shorten_name(dl
));
459 if (dl
->part_id
==0 && app
->disk_temperature
[hd_cnt
] != -1) {
461 if (app
->disk_temperature
[hd_cnt
] != -2) {
462 snprintf(s
,200,"%d",app
->disk_temperature
[hd_cnt
]);
466 imlib_get_text_size(s
,&w
,&h
);
467 x
= lx
+ lw
- w
+ ((app
->disk_temperature
[hd_cnt
] != -2) ? -7 : -3);
468 imlib_context_set_color(255, 250, 100, 255);
469 my_imlib_text_draw(x
, y
-h
, s
);
470 imlib_context_set_color(255, 255, 255, 200);
472 /* below is a quick fix for the degree sign which is not drawn
473 properly by recent release of imlib -- many thanks to
474 Krzysztof Kotlenga for the patch */
476 //if (app->disk_temperature[hd_cnt] != -2) imlib_image_draw_ellipse(x+w+3, y - h + 2, 1, 1);
478 //if (app->disk_temperature[hd_cnt] != -2) imlib_image_draw_ellipse(x+w+3, y - h + 2, 1, 1);
479 /* imlib2 >= 1.1.1 workaround - imlib_image_draw_ellipse() can't properly draw circle with radius = 1 */
480 if (app
->disk_temperature
[hd_cnt
] != -2) {
482 poly = imlib_polygon_new();
483 imlib_polygon_add_point(poly, x+w+3, y-h+3);
484 imlib_polygon_add_point(poly, x+w+2, y-h+2);
485 imlib_polygon_add_point(poly, x+w+3, y-h+1);
486 imlib_polygon_add_point(poly, x+w+4, y-h+2);
487 imlib_image_draw_polygon(poly, 1);*/
488 /*imlib_image_draw_pixel(x+w+3, y-h+3, 0);
489 imlib_image_draw_pixel(x+w+2, y-h+2, 0);
490 imlib_image_draw_pixel(x+w+3, y-h+1, 0);
491 imlib_image_draw_pixel(x+w+4, y-h+2, 0);*/
494 imlib_image_draw_pixel(i
+1,j
,0);
495 imlib_image_draw_pixel(i
+2,j
,0);
496 imlib_image_draw_pixel(i
+3,j
+1,0);
497 imlib_image_draw_pixel(i
+3,j
+2,0);
498 imlib_image_draw_pixel(i
+1,j
+3,0);
499 imlib_image_draw_pixel(i
+2,j
+3,0);
500 imlib_image_draw_pixel(i
,j
+1,0);
501 imlib_image_draw_pixel(i
,j
+2,0);
507 static void draw_throughput(App
*app
) {
508 static int tpstep
= 0, tpw
, tph
;
509 static char tpmsg
[20];
510 static int lw
= -1, lh
= -1, lx
= -1, ly
= -1;
511 static int reshape_cnt
= 0;
512 if (Prefs
.popup_throughput_pos
== AL_NONE
) return;
514 if (!app
->bigfont
) return;
515 imlib_context_set_font(app
->bigfont
);
516 /* get dimensions (only once) */
517 if (lx
== -1 || app
->reshape_cnt
!= reshape_cnt
) {
518 imlib_get_text_size("00.0M/s",&lw
,&lh
);
519 if (lw
> (int)(app
->dock
->w
*3/4)) { lw
= app
->dock
->w
; }
520 sethw(app
,lw
,lh
,Prefs
.popup_throughput_pos
,&lx
,&ly
,&lw
,&lh
);
521 reshape_cnt
= app
->reshape_cnt
;
524 if (get_read_mean_throughput() + get_write_mean_throughput() > Prefs
.popup_throughput_threshold
) {
525 tpstep
= MIN(tpstep
+1,4);
526 snprintf(tpmsg
,sizeof tpmsg
, "%.1fM/s",get_read_mean_throughput() + get_write_mean_throughput());
527 imlib_get_text_size(tpmsg
,&tpw
,&tph
);
529 snprintf(tpmsg
,sizeof tpmsg
, "%.1fM",get_read_mean_throughput() + get_write_mean_throughput());
530 imlib_get_text_size(tpmsg
,&tpw
,&tph
);
532 } else if (tpstep
) tpstep
--;
534 imlib_context_set_color(128, 128, 128, tpstep
*30);
535 imlib_image_draw_rectangle(lx
-1,ly
-1,lw
+2,lh
+2);
536 imlib_context_set_color(128, 128, 128, 10+tpstep
*25);
537 imlib_image_fill_rectangle(lx
,ly
,lw
,lh
);
538 imlib_context_set_color(255, 255, 255, 50+tpstep
*50);
539 my_imlib_text_draw(lx
+ (lw
- tpw
)/2, ly
, tpmsg
);
543 static void draw(App
*app
) {
544 DATA32
*buff
= imlib_image_get_data();
546 if (!Prefs
.disable_io_matrix
) {
547 evolve_io_matrix(app
,buff
);
548 //draw_io_matrix(app,buff);
549 } else memset(buff
, 0, sizeof(DATA32
)*app
->dock
->w
*app
->dock
->h
);
550 imlib_image_put_back_data(buff
);
552 if (!Prefs
.disable_swap_matrix
) draw_swap_matrix(app
);
553 draw_throughput(app
);
556 void reshape(int w
, int h
) {
557 DockImlib2
*dock
= app
->dock
;
558 static int isinit
= 0;
559 dock
->w
= w
; dock
->h
= h
;
560 dock
->win_width
= dock
->w
+ dock
->x0
;
561 dock
->win_height
= dock
->h
+ dock
->y0
;
564 app
->sm
.nrow
= (dock
->w
-1) / app
->sm
.w
;
565 app
->sm
.ncol
= (dock
->h
-1) / app
->sm
.w
;
566 if (isinit
) FREE_ARR(app
->sm
.pre_cnt
);
567 ALLOC_ARR(app
->sm
.pre_cnt
, app
->sm
.nrow
, app
->sm
.ncol
);
568 if (isinit
) FREE_ARR(app
->sm
.intensity
)
569 ALLOC_ARR(app
->sm
.intensity
, app
->sm
.nrow
, app
->sm
.ncol
);
570 app
->iom
.w
= dock
->w
; app
->iom
.h
= dock
->h
;
571 if (isinit
) FREE_ARR((void*)app
->iom
.v
);
572 ALLOC_ARR(app
->iom
.v
,app
->iom
.h
+4, app
->iom
.w
+2);
573 if (isinit
) { dockimlib2_reset_imlib(dock
); }
579 static void event_loop(App
*app
) {
584 if (tic_cnt
% 5 == 0) {
585 XWindowAttributes attr
;
586 if (app
->dock
->normalwin
) {
587 XGetWindowAttributes(app
->dock
->display
, app
->dock
->normalwin
, &attr
);
588 app
->dock
->normalwin_mapped
= (attr
.map_state
== IsViewable
);
590 if (app
->dock
->iconwin
) {
591 XGetWindowAttributes(app
->dock
->display
, app
->dock
->iconwin
, &attr
);
592 app
->dock
->iconwin_mapped
= (attr
.map_state
== IsViewable
);
596 while (XPending(app
->dock
->display
)) {
597 XNextEvent(app
->dock
->display
, &ev
);
600 if (ev
.xclient
.message_type
== app
->dock
->atom_WM_PROTOCOLS
601 && ev
.xclient
.format
== 32
602 && (Atom
)ev
.xclient
.data
.l
[0] == app
->dock
->atom_WM_DELETE_WINDOW
) {
608 if (ev
.xbutton
.button
== Button4
) prev_displayed_hd(-1);
609 else if (ev
.xbutton
.button
== Button5
|| ev
.xbutton
.button
== Button1
) next_displayed_hd(+1);
611 case ConfigureNotify
: {
612 if (app
->dock
->iconwin
== None
&&
613 (ev
.xconfigure
.width
!= (int)app
->dock
->win_width
||
614 ev
.xconfigure
.height
!= (int)app
->dock
->win_height
)) {
615 app
->dock
->w
= app
->dock
->win_width
= ev
.xconfigure
.width
;
616 app
->dock
->h
= app
->dock
->win_height
= ev
.xconfigure
.height
;
617 reshape(ev
.xconfigure
.width
, ev
.xconfigure
.height
); //app->dock->w, app->dock->h, None);
618 /*printf("ConfigureNotify : %dx%d %dx%d\n",
619 ev.xconfigure.width, ev.xconfigure.height,
620 app->sm.nrow, app->sm.ncol);*/
625 if (tic_cnt
% app
->update_stats_mult
== 0) {
627 if (!Prefs
.disable_io_matrix
) update_io_matrix(app
);
628 if (!Prefs
.disable_swap_matrix
) update_swap_matrix(app
);
630 if (tic_cnt
% 100 == 5) {
631 # ifdef ENABLE_HDDTEMP_QUERY
632 if (Prefs
.enable_hddtemp
) {
636 # ifdef ENABLE_POWER_QUERY
637 if (Prefs
.enable_power_status
) {
638 DiskList
*dl
; int cnt
;
639 for (cnt
= 0, dl
= first_hd_in_list(); dl
; dl
= next_hd_in_list(dl
), ++cnt
) {
640 if (dl
->enable_power_status
&& !dl
->is_scsi
) {
641 char devname
[512]; snprintf(devname
, 512, "/dev/%s", dl
->name
);
642 app
->disk_power_mode
[cnt
] = query_power_mode(devname
);
648 //if (tic_cnt > 500) exit(1);
649 usleep(app
->update_display_delay_ms
* 1000);
651 dockimlib2_render(app
->dock
);
654 #endif /* ndef GKRELLM */
656 void setup_cmap(cmap
*m
) {
660 } colors0
[] = {{-128, 0xff8080},
670 colors1
[] = {{-128, 0xff0000},
679 colors2
[] = {{-128, 0x400000},
688 colors3
[] = {{-128, 0x500060},
695 colors4
[] = {{-128, 0x5000F0},
714 if (Prefs.iomatrix_colormap == n) { sz = sizeof(colors##n)/sizeof(*colors0); cdef = colors##n; }
717 SELMAP(0); SELMAP(1); SELMAP(2); SELMAP(3); SELMAP(4);
718 float x0
= cdef
[0].x0
, x1
= cdef
[sz
-1].x0
;
719 for (i
= 0; i
< sz
- 1; ++i
) {
720 int i0
= (int)((cdef
[i
].x0
-x0
)*CMAPSZ
/(x1
-x0
));
721 int i1
= (int)((cdef
[i
+1].x0
-x0
)*CMAPSZ
/(x1
-x0
));
722 int r1
= cdef
[i
].c
>>16 & 0xff, r2
= cdef
[i
+1].c
>>16 & 0xff;
723 int g1
= cdef
[i
].c
>> 8 & 0xff, g2
= cdef
[i
+1].c
>> 8 & 0xff;
724 int b1
= cdef
[i
].c
& 0xff, b2
= cdef
[i
+1].c
& 0xff;
726 for (j
=i0
; j
<= MIN(i1
,CMAPSZ
-1); ++j
) {
727 float alpha
= (j
-i0
+.5)/(float)(i1
-i0
);
729 (MIN((int)(r1
*(1-alpha
) + alpha
*r2
),255)<<16) +
730 (MIN((int)(g1
*(1-alpha
) + alpha
*g2
),255)<<8) +
731 (MIN((int)(b1
*(1-alpha
) + alpha
*b2
),255));
732 //printf("cmap[%d] = 0x%06x\n", j, m->p[j]);
737 unsigned getpos(const char *pp
) {
739 unsigned v
= AL_NONE
, i
;
740 if (!pp
|| !pp
[0]) return AL_NONE
;
741 if (strlen(pp
) > 2) { fprintf(stderr
, "invalid position specification: '%s'\n", pp
); exit(1); }
743 if (p
[0] == 'c') { char tmp
= p
[0]; p
[0] = p
[1]; p
[1] = tmp
; }
744 for (i
=0; i
< 2 && p
[i
]; ++i
) {
745 if (p
[i
] == 'r') { v
|= AL_RIGHT
; }
746 else if (p
[i
] == 'l') { v
|= AL_LEFT
; }
747 else if (p
[i
] == 't') { v
|= AL_TOP
; }
748 else if (p
[i
] == 'b') { v
|= AL_BOTTOM
; }
749 else if (p
[i
] == 'c') {
750 if (v
& (AL_LEFT
| AL_RIGHT
| AL_HCENTER
)) v
|= AL_VCENTER
; else v
|= AL_HCENTER
;
752 fprintf(stderr
, "unknown position specifier: '%c'\n", p
[i
]); exit(1);
758 void init_prefs(int argc
, char **argv
) {
760 /* Prefs already read from the gkrellm config file: */
761 Prefs
.disable_swap_matrix
= 0;
762 Prefs
.disable_io_matrix
= 0;
763 Prefs
.disable_hd_leds
= 0;
764 Prefs
.iomatrix_colormap
= 0;
765 Prefs
.popup_throughput_threshold
= 0.5; /* MB/s */
766 Prefs
.hdlist_pos
= AL_BOTTOM
+ AL_LEFT
;
767 Prefs
.enable_hddtemp
= 0;
768 Prefs
.bigfontname
= Prefs
.smallfontname
= NULL
;
770 Prefs
.xprefs
.dockapp_size
= 64;
772 Prefs
.hddtemp_port
= 7634;
773 Prefs
.enable_power_status
= 0;
774 Prefs
.debug_swapio
= 0; Prefs
.debug_disk_wr
= Prefs
.debug_disk_rd
= 0;
775 Prefs
.popup_throughput_pos
= AL_TOP
;
776 Prefs
.xprefs
.argc
= argc
; Prefs
.xprefs
.argv
= argv
;
777 Prefs
.xprefs
.flags
= 0;
778 Prefs
.temperatures_unit
= 'C';
782 void parse_options(int argc
, char **argv
) {
784 enum { OPT_DISPLAY
=1, OPT_SMALLFONT
, OPT_BIGFONT
, OPT_FONTPATH
,
785 OPT_NOSWAP
, OPT_NOIO
, OPT_NOLEDS
, OPT_HDLIST
, OPT_THROUGHPUT
, OPT_32
, OPT_56
, OPT_48
};
786 static struct option long_options
[] = {
791 {"farenheit",0,0,'F'},
792 {"display",1,0,OPT_DISPLAY
},
793 {"geometry",2,0,'g'},
794 {"smallfont",1,0,OPT_SMALLFONT
},
795 {"bigfont",1,0,OPT_BIGFONT
},
796 {"fontpath",1,0,OPT_FONTPATH
},
797 {"colormap",1,0,'c'},
798 {"noswap",0,0,OPT_NOSWAP
},
799 {"noio",0,0,OPT_NOIO
},
800 {"noleds",0,0,OPT_NOLEDS
},
801 {"hdlist",2,0,OPT_HDLIST
},
802 {"throughput",2,0,OPT_THROUGHPUT
},
808 int long_options_index
;
810 "wmhdplop " VERSION
" - monitor hard-drive (or partition) activity\n"
811 "A recent kernel is required (>2.4.20)\n"
812 "Usage: wmhdplop [options]\n"
814 " -h, --help print this.\n"
815 " -v, --verbose increase verbosity\n"
816 " -V, --version print version\n"
817 " -t[=port], --hddtemp[=port]\n"
818 " display hd temperatures, in Celsius degrees (requires hddtemp daemon running)\n"
819 " -F, --farenheit display hd temperatures in Farenheit degrees\n"
820 /* " -p : monitor harddrive power status (idle, standby or sleeping, as reported by hdparm -C)\n"
821 " note that this options requires that wmhd is suid..\n"*/ /* hddtemp already reports when a drive is asleep ... */
822 " --noswap disable the animation reflecting swap activity\n"
823 " --noio disable background animation reflecting disk activity\n"
824 " --noleds hide the small led indicating disk activity\n"
825 " --fontpath path add a new directory to the font search directory list\n"
826 " default: --fontpath=/usr/share/fonts/truetype (and subdirectories)\n"
827 " --fontpath=/usr/share/fonts/ttf (and subdirectories)\n"
828 " --fontpath=$HOME/.fonts (and subdirectories)\n"
829 " --smallfont fontname/size\n"
830 " --bigfont fontname/size\n"
831 " Set the 'small font' and the 'big font' name/size in pixel\n"
832 " (default: --smallfont=Vera/7 --bigfont=Arial_Black/10)\n"
833 " The font name are case-sensitive, and must correspound to the name\n"
834 " of a .ttf file which can be found in one of the fontpaths\n"
835 " By default, wmhdplop tries to load the following fonts:\n"
836 " * Arial_Black/10, FreeSansBold/11, VeraMoBd/9\n"
837 " * Vera/7, FreeSans/7, Trebuchet_MS/7\n"
838 " -c n, --colormap=n\n"
839 " select colormap number n\n"
840 " --hdlist[=pos] hide completely the list of drives with leds and temperatures (if no position given)\n"
841 " or change its location (default: 'B'). Possible positions are: 't','b','l','bl','bc','br',...\n"
842 " (t=top, b=bottom, l=left, r=right, c=centered, etc)\n"
843 " --throughput=mbs[,pos]\n"
844 " minimum io throughput (MB/s) that will be displayed in the popup display (default 0.5)\n"
845 " and position of the popup (same format than hdlist)\n"
846 " -g[=WxH+x+y], --geometry[=WxH+x+y]\n"
847 " start in window (i.e. undocked) mode with specified geometry (i.e -g 96x32 or -g 64x64+0+0)\n"
848 " --32, --48, --56\n"
849 " start in a reduced dockapp, for people whose dock is too small too contain 64x64 dockapps\n"
850 " -d device[:name] monitor activity on the specified hard-drive. This option can be\n"
851 " used many times. If you do not use it, all hard-drives will be monitored.\n"
852 " If an optional 'name' is given, it will be displayed instead of the /dev/hdx name\n"
853 " The device may also be a single partition.\n";
854 init_prefs(argc
, argv
);
857 c
= getopt_long(argc
, argv
, "g::hvVt::Fc:LP:d:@:",long_options
,&long_options_index
); /* -g option is handled in dockapp_imlib2 */
865 Prefs
.xprefs
.flags
|= DOCKPREF_DISPLAY
; Prefs
.xprefs
.display
= strdup(optarg
);
868 Prefs
.xprefs
.flags
|= DOCKPREF_GEOMETRY
; if (optarg
) Prefs
.xprefs
.geometry
= strdup(optarg
);
876 printf("wmhdplop %s\n",VERSION
); exit(0);
879 Prefs
.enable_hddtemp
= 1;
880 if (optarg
) Prefs
.hddtemp_port
= atoi(optarg
);
883 Prefs.enable_power_status = 1;
886 Prefs
.enable_hddtemp
= 1;
887 Prefs
.temperatures_unit
= 'F';
890 Prefs
.disable_io_matrix
= 1;
893 Prefs
.disable_swap_matrix
= 1;
896 Prefs
.disable_hd_leds
= 1;
899 printf("add font path: %s\n", optarg
);
900 imlib_add_path_to_font_path(optarg
);
903 Prefs
.smallfontname
= strdup(optarg
);
906 Prefs
.bigfontname
= strdup(optarg
);
909 Prefs
.hdlist_pos
= getpos(optarg
);
912 Prefs
.iomatrix_colormap
= atoi(optarg
);
913 if (Prefs
.iomatrix_colormap
> 4) { fprintf(stderr
,"invalid colormap number\n"); exit(1); }
917 Prefs
.popup_throughput_threshold
= atof(optarg
);
918 if (strchr(optarg
,',')) Prefs
.popup_throughput_pos
= getpos(strchr(optarg
,',')+1);
921 Prefs
.xprefs
.dockapp_size
= 56;
924 Prefs
.xprefs
.dockapp_size
= 48;
927 Prefs
.xprefs
.dockapp_size
= 32;
931 char *p
= strchr(optarg
, ':');
934 BLAHBLAH(1,printf("adding device %s to monitored disc list\n",optarg
));
935 if (add_device_by_name(optarg
, p
) != 0)
936 fprintf(stderr
, "Warning: device %s not found or not recognized -- try option -v to get additionnal information\n", optarg
);
940 sscanf(optarg
,"%d,%d,%d",&Prefs
.debug_swapio
,&Prefs
.debug_disk_rd
,&Prefs
.debug_disk_wr
);
946 if (optind
!= argc
) {
947 fprintf(stderr
, "unknown option: %s\n", argv
[optind
]); exit(1);
949 if (!d_opt_used
) scan_all_hd(1);
953 char *xstrdup(const char *s
) {
954 if (s
) return strdup(s
);
958 void init_fonts(App
*app
) {
959 char *bigfontlist
[] = {"Arial_Black/10", "luxisb/11", "VeraMoBd/9", "arialbd/12", "Vera/9", "Verdana_Bold/10", "VerdanaBd/10", "Verdana/10", "FreeSansBold/11", NULL
};
960 char *smallfontlist
[] = {"Vera/7","Trebuchet_MS/7", "luxisr/7", "Verdana/7","Arial/7","FreeSans/7", NULL
};
962 imlib_context_set_font(app
->bigfont
); imlib_free_font(); app
->bigfont
= NULL
;
964 if (app
->smallfont
) {
965 imlib_context_set_font(app
->smallfont
); imlib_free_font(); app
->smallfont
= NULL
;
967 app
->bigfont
= load_font(Prefs
.bigfontname
, bigfontlist
);
969 app
->current_bigfont_name
= strdup(dockimlib2_last_loaded_font());
970 app
->smallfont
= load_font(Prefs
.smallfontname
, smallfontlist
);
972 app
->current_smallfont_name
= strdup(dockimlib2_last_loaded_font());
976 int main(int argc
, char**argv
)
978 int hdplop_main(int width
, int height
, GdkDrawable
*gkdrawable
)
983 euid
= geteuid(); uid
= getuid();
986 fprintf(stderr
, "seteuid(uid) failed : %s\n", strerror(errno
));
989 /* Initialize options */
991 parse_options(argc
,argv
);
996 /* Initialize imlib2 */
998 app
->dock
= dockimlib2_setup(2, 2, Prefs
.xprefs
.dockapp_size
-5, Prefs
.xprefs
.dockapp_size
-5, &Prefs
.xprefs
);
1000 app
->dock
= dockimlib2_gkrellm_setup(0, 0, width
, height
, &Prefs
.xprefs
, gkdrawable
);
1002 app
->bigfont
= app
->smallfont
= NULL
;
1003 app
->current_bigfont_name
= app
->current_smallfont_name
= NULL
;
1004 app
->reshape_cnt
= 0;
1005 if (find_id(-1,0) == 0) {
1006 app
->filter_hd
= -1; app
->filter_part
= -1; /* only partitions */
1008 app
->filter_hd
= -1; app
->filter_part
= 0;
1010 app
->displayed_hd_changed
= 1;
1011 if (nb_dev_in_list() == 0) {
1013 fprintf(stderr
, "No common hard-drives found in /etc/mtab and /proc/partitions..\n"
1014 "Please use option -d to add devices (i.e. %s -d /dev/hda -d /dev/hdb ...)\n", argv
[0]);
1017 fprintf(stderr
, "No hard drive found...\n");
1018 /* Euh, on fait quoi maintenant ? exit ? */
1022 app
->update_display_delay_ms
= 50;
1023 app
->update_stats_mult
= 2;
1025 app
->swap_matrix_lighting
= (int)(300/app
->update_display_delay_ms
);
1026 app
->swap_matrix_luminosity
= 255;
1028 app
->nb_hd
= nb_hd_in_list();
1029 app
->nb_dev
= nb_dev_in_list();
1030 ALLOC_VEC(app
->disk_power_mode
, app
->nb_hd
); SET_VEC(app
->disk_power_mode
, HD_ACTIVE
,0,app
->nb_hd
);
1031 ALLOC_VEC(app
->disk_temperature
, app
->nb_hd
); SET_VEC(app
->disk_temperature
, -1, 0, app
->nb_hd
);
1033 init_stats(app
->update_display_delay_ms
*1e-3*app
->update_stats_mult
);
1035 DiskList
*dl
= first_dev_in_list();
1036 for ( ; dl
; dl
=dl
->next
) {
1037 printf("Monitored: %s (%s) major=%d, minor=%d is_partition=%d\n",
1038 dl
->dev_path
, dl
->name
, dl
->major
, dl
->minor
, is_partition(dl
->major
,dl
->minor
));
1042 reshape(app
->dock
->w
,app
->dock
->h
);
1043 app
->iom
.ops
= NULL
;
1044 setup_cmap(&app
->iom
.cm
);
1052 void gkrellm_hdplop_update(int update_options
) {
1053 static int tic_cnt
= 0;
1054 if (update_options
) {
1055 setup_cmap(&app
->iom
.cm
);
1056 if (!Prefs
.enable_hddtemp
)
1057 SET_VEC(app
->disk_temperature
, -1, 0, app
->nb_hd
);
1061 if (tic_cnt
% app
->update_stats_mult
== 0) {
1063 if (!Prefs
.disable_io_matrix
)
1064 update_io_matrix(app
);
1065 if (!Prefs
.disable_swap_matrix
)
1066 update_swap_matrix(app
);
1068 if (tic_cnt
% 100 == 5 && Prefs
.enable_hddtemp
) {
1072 // draw the Imlib2 pixmap:
1074 dockimlib2_render(app
->dock
);