4 Version 0.98 (2000-10-20)
6 Robert Kling (robkli-8@student.luth.se)
7 http://boombox.campus.luth.se/projects.php
10 -n option patch by Thorsten Jens (thodi@et-inf.fho-emden.de) (2000-05-12)
11 Various bugfixes and optimizations by Jakob Borg (2000-05-13)
12 Solaris Port by Dan Price (dp@rampant.org) (2000-07-16)
13 OpenBSD Port by Brian Joseph Czapiga (rys@godsey.net) (2000-07-19)
14 FreeBSD Port by Tai-hwa Liang (avatar@mmlab.cse.yzu.edu.tw) (2000-07-20)
15 NetBSD Port by Jared Smolens <jsmolens+@andrew.cmu.edu> (2000-09-23)
17 This software is licensed through the GNU General Public Licence.
19 See http://www.BenSinclair.com/dockapp/ for more wm dock apps.
21 If you want to port wmcube to another OS the system specific code is
22 sectioned the bottom of this file. See instructions there.
26 #define WMCUBE_VERSION "0.98"
27 #define REV_DATE "2000-10-23"
40 #include <sys/param.h>
41 #include <sys/types.h>
42 #include <sys/ioctl.h>
43 #include <sys/socket.h>
50 #include <X11/extensions/shape.h>
56 #include "../wmgeneral/wmgeneral.h"
57 #include "../wmgeneral/misc.h"
60 char wmcube_mask_bits
[64*64];
61 int wmcube_mask_width
= 64;
62 int wmcube_mask_height
= 64;
66 #define PI 3.1415926535
68 //**** Graphics ***********************************
70 void putpixel(int x
, int y
, int c
);
71 void line(int x1
, int y1
, int x2
, int y2
, int c
);
72 void hline(int x1
, int x2
, int y
, int c
);
73 void triangle(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
, int c
);
74 void BlitString(char *name
, int x
, int y
);
75 void BlitNum(int num
, int x
, int y
);
80 //**** 3d specific ********************************
82 void setupobj(char *filename
) ;
84 void rotate(int xang
, int yang
, int zang
);
85 int normal(float p1
[], float p2
[], float p3
[]);
86 int luminate(float p1
[], float p2
[], float p3
[]);
87 void sortz(int nofelements
);
89 //**** Application Management, I/O etc. ***********
92 int loadobj(char *filename
);
93 void mem_alloc_error(void *block
);
94 int scan4objects(char *dir
);
98 //**** System specific functions ******************
101 int calc_cpu_total();
103 //**** Global variables ***************************
105 int xcenter
, ycenter
, zoff
;
106 double cost
[361], sint
[361];
114 int nofcoords
, noflines
, nofplanes
;
120 int planesORlines
= 1;
123 float lum_vector
[3] = { 0, 0, 100 }; // Lightsource vector
127 static struct nlist nlst
[] = { {"_cp_time"}, {0} };
130 int main(int argc
, char **argv
)
132 int j
, i
= 0, rot_speed
= 0, cpu_usage
= 0, rot_step
= 1;
133 long screen_speed
= 10000; // microseconds between screen updates (approx.)
134 long cpu_update
= 490000; // microseconds between cpu update (approx.)
139 char *rotdiv
= {"25"};
140 char *rotstep
= {"1"};
141 char *obj_filename
= {""};
145 int invert_speed
= 0;
147 pname
= strrchr(argv
[0], '/');
148 if (pname
== NULL
) pname
= argv
[0];
150 srand((unsigned)time(NULL
));
153 while ((c
= getopt (argc
, argv
, "d:nhpbir:o:c:")) != -1) {
157 which_cpu
= atoi(optarg
);
178 obj_filename
= optarg
;
192 * Validate that wmcube can run on this system given the parameters,
193 * then setup the statistics gathering subsystem.
196 if (init_calc_cpu() != 0) die();
199 * Scan directory for .wmc files and choose one randomly. If the user
200 * specified a particular file, load that one.
203 #ifndef SOLARIS // scan4objects doesnt work on Solaris, load object immediatly
204 scan4objects(obj_filename
);
206 if (nof_objects
!= 0)
210 setupobj(obj_filename
);
213 * Various initializion stuff for the 3d-engine etc.
219 if ((rot
>= 1) && (rot
<=100)) ; else rot
= 25;
221 rot_step
= atoi(rotstep
);
222 if (rot_step
< 0) rot_step
= -rot_step
;
224 if (calc_cpu_total() == -1) die();
226 cpu_update
/= screen_speed
;
228 createXBMfromXPM(wmcube_mask_bits
, wmcube_xpm
, wmcube_mask_width
, wmcube_mask_height
);
229 openXwindow(argc
, argv
, wmcube_xpm
, wmcube_mask_bits
, wmcube_mask_width
, wmcube_mask_height
);
233 if (calc_cpu_total() == -1) die();
235 // index, left, top, right, bottom
236 AddMouseRegion(1, 45, 45, 58, 58); // + Zoom In
237 AddMouseRegion(5, 5, 45, 20, 58); // - Zoom Out
238 AddMouseRegion(3, 21, 45, 45, 58); // Show cpu-load
239 AddMouseRegion(2, 5, 5, 55, 45); // Everywhere else (almost) to change object
242 * Main loop begins here
247 i
= (i
+rot_speed
+rot_step
) % 360;
255 BlitNum(cpu_usage
,24,49);
256 BlitString("Z",38,49);
261 if (loop
++ == cpu_update
) {
265 * call calc_cpu_total to update statistics. If some
266 * sort of bad event occurs, calc_cpu_total will return
270 if ((cpu_usage
= calc_cpu_total()) == -1) {
273 rot_speed
= abs( invert_speed
*(100 / rot
) - cpu_usage
/ rot
);
278 while (XPending(display
))
280 XNextEvent(display
, &Event
);
287 XCloseDisplay(display
);
291 j
= CheckMouseRegion(Event
.xbutton
.x
, Event
.xbutton
.y
);
296 j
= CheckMouseRegion(Event
.xbutton
.x
, Event
.xbutton
.y
);
302 BlitString("ö",48,48);
313 if (show_load
== 1) show_load
= 0; else show_load
= 1;
314 ycenter
= 15 - 2*show_load
;
318 BlitString("ä",11,49);
326 usleep(screen_speed
);
330 * Free up memory used by the object (dirty...)
341 //**** Graphics ***********************************
342 //*************************************************
346 char *tmp
= malloc(32);
349 sprintf(tmp
,"V%s",WMCUBE_VERSION
);
352 BlitString("WMCUBE",13,22);
353 BlitString(tmp
,15,31);
361 for (;zoff
< oldzoff
; zoff
+= 35)
363 rotate((zoff
-1200)/8,0,0);
365 BlitString("WMCUBE",13,22);
366 BlitString(tmp
,15,31);
382 for (i
= 0; i
< nofplanes
; i
++) {
383 if (normal(rmatrix
[planes
[zorder
[i
]][0]], rmatrix
[planes
[zorder
[i
]][1]], rmatrix
[planes
[zorder
[i
]][2]]) > 0) {
385 triangle(xcenter
+rmatrix
[planes
[zorder
[i
]][0]][0], ycenter
+rmatrix
[planes
[zorder
[i
]][0]][1],
386 xcenter
+rmatrix
[planes
[zorder
[i
]][1]][0], ycenter
+rmatrix
[planes
[zorder
[i
]][1]][1],
387 xcenter
+rmatrix
[planes
[zorder
[i
]][2]][0], ycenter
+rmatrix
[planes
[zorder
[i
]][2]][1], plane_color
[zorder
[i
]]);
392 for (i
= 0; i
< noflines
; i
+= 2)
393 line(xcenter
+rmatrix
[cline
[i
]-1][0], ycenter
+rmatrix
[cline
[i
]-1][1],
394 xcenter
+rmatrix
[cline
[i
+1]-1][0], ycenter
+rmatrix
[cline
[i
+1]-1][1],color
);
398 void putpixel(int x
, int y
,int c
)
400 if ((x
> 4) && (x
< 59) && (y
> 4) && (y
< 59))
401 copyXPMArea(160-c
,0,1,1,x
,y
);
404 void hline(int x1
, int x2
, int y
, int c
)
406 if ((y
> 4) && (y
< 59)) {
407 if (x1
<= 4) x1
= 5; else if (x1
> 57) return;
408 if (x2
> 57) x2
= 57; else if (x2
<= 4) return;
410 copyXPMArea(105, 56+c
+ 9*(c
/18), x2
-x1
, 1, x1
, y
);
414 void triangle(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
, int c
) // Draws a filled triangle
416 int k
,k2
,x
,x_2
,i
, tmp1
;
450 if (y1
!=y3
) k
=((x1
-x3
) << 6) / (y1
-y3
);
453 if (y1
!=y2
) k2
=((x1
-x2
) << 6) / (y1
-y2
);
454 else k2
=(x1
-x2
) << 6;
467 if ((x1t
= x
>> 6) > (x2t
= x_2
>> 6))
468 hline(x2t
, x1t
, i
, c
);
470 hline(x1t
, x2t
, i
, c
);
476 if (y2
!=y3
) k2
=((x2
-x3
) << 6) / (y2
-y3
);
477 else k2
=((x2
-x3
) << 6);
487 if ((x1t
= x
>> 6) > (x2t
= x_2
>> 6))
488 hline(x2t
, x1t
, i
, c
);
490 hline(x1t
, x2t
, i
, c
);
497 copyXPMArea(78,0,56,56,4,4);
500 // Blits a string at given co-ordinates
501 void BlitString(char *name
, int x
, int y
)
509 copyXPMArea(73,64,1,8,k
-1,y
);
511 for (i
=0; name
[i
]; i
++)
513 c
= toupper(name
[i
]);
516 if (c
>= 'A' && c
<= 'Z')
519 if ( k
> -2) copyXPMArea(c
* 6, 74, 6, 8, k
, y
);
522 if (c
>= '0' && c
<= ':')
523 { // its a number or symbol
525 if ( k
> -2) copyXPMArea(c
* 6, 64, 6, 8, k
, y
);
529 if ( k
> -2) copyXPMArea(0, 84, 6, 9, k
, y
);
533 if ( k
> -2) copyXPMArea(6, 84, 6, 9, k
, y
);
537 if ( k
> -2) copyXPMArea(12, 84, 6, 9, k
, y
);
540 { // its a blank or something else
541 if ( k
> -2) copyXPMArea(73,64,6,8,k
,y
);
546 copyXPMArea(73,64,1,8,k
,y
);
550 // Blits number to given coordinates.. two 0's, right justified
552 void BlitNum(int num
, int x
, int y
)
567 sprintf(buf
, "%02i", num
);
569 BlitString(buf
, newx
, y
);
572 void line(int x1
, int y1
, int x2
, int y2
, int c
)
574 int i
, deltax
, deltay
, numpixels
,
579 deltax
= abs(x2
- x1
);
580 deltay
= abs(y2
- y1
);
581 if (deltax
>= deltay
)
583 numpixels
= deltax
+ 1;
584 d
= (deltay
<< 1) - deltax
;
586 dinc2
= (deltay
- deltax
) << 1;
594 numpixels
= deltay
+ 1;
595 d
= (deltax
<< 1) - deltay
;
597 dinc2
= (deltax
- deltay
) << 1;
615 for (i
=1; i
<numpixels
; i
++)
634 //**** 3d specific ********************************
635 //*************************************************
637 void rotate(int xang
, int yang
, int zang
)
642 for (i
= 0; i
< nofcoords
; i
++)
644 tx
= cost
[yang
]*matrix
[i
][0]-sint
[yang
]*matrix
[i
][2];
645 tz
= sint
[yang
]*matrix
[i
][0]+cost
[yang
]*matrix
[i
][2];
646 ty
= cost
[zang
]*matrix
[i
][1]-sint
[zang
]*tx
;
648 rmatrix
[i
][0] = (cost
[zang
]*tx
+sint
[zang
]*matrix
[i
][1]);
649 rmatrix
[i
][1] = (sint
[xang
]*tz
+cost
[xang
]*ty
);
650 rmatrix
[i
][2] = (cost
[xang
]*tz
-sint
[xang
]*ty
);
654 for (i
= 0; i
< nofplanes
; i
++)
655 if (normal(rmatrix
[planes
[i
][0]], rmatrix
[planes
[i
][1]], rmatrix
[planes
[i
][2]]) > 0)
656 plane_color
[i
] = luminate(rmatrix
[planes
[i
][0]], rmatrix
[planes
[i
][1]], rmatrix
[planes
[i
][2]]);
658 for (i
= 0; i
< nofcoords
; i
++) {
659 // Perspective correcting lines...
660 rmatrix
[i
][0] = (rmatrix
[i
][0] *256) / (2*rmatrix
[i
][2] - zoff
) + xcenter
;
661 rmatrix
[i
][1] = (rmatrix
[i
][1] *256) / (2*rmatrix
[i
][2] - zoff
) + ycenter
;
665 void sortz(int nofelements
) { // Insertion-sort the planes in increasing z-distance
669 float temparr
[nofelements
];
671 for (i
= 0; i
< nofelements
; i
++)
674 temparr
[i
] = rmatrix
[planes
[i
][0]][2]+rmatrix
[planes
[i
][1]][2]+rmatrix
[planes
[i
][2]][2];
677 for (j
= 1; j
< nofelements
; j
++) {
683 while ((i
> -1) && (temparr
[i
] > key
)) {
684 temparr
[i
+1] = temparr
[i
];
685 zorder
[i
+1] = zorder
[i
--];
693 int normal(float p1
[], float p2
[], float p3
[])
695 return ((p1
[0]-p3
[0])*(p2
[1]-p3
[1])-(p2
[0]-p3
[0])*(p1
[1]-p3
[1]));
698 int luminate(float p1
[], float p2
[], float p3
[])
700 double x1
= (float)(p1
[0]-p3
[0]), y1
= (float)(p1
[1]-p3
[1]), z1
= (float)(p1
[2]-p3
[2]);
701 double x2
= (float)(p2
[0]-p3
[0]), y2
= (float)(p2
[1]-p3
[1]), z2
= (float)(p2
[2]-p3
[2]);
702 double nx
= y1
*z2
-y2
*z1
, ny
=-(x1
*z2
-x2
*z1
),nz
= x1
*y2
-y1
*x2
;
704 return (int)(53 * (acost
[(int)(50 + 50*(nx
*lum_vector
[0]+ny
*lum_vector
[1]+nz
*lum_vector
[2])/
705 (sqrt(nx
*nx
+ny
*ny
+nz
*nz
)*
706 sqrt(lum_vector
[0]*lum_vector
[0]+lum_vector
[1]*lum_vector
[1]+
707 lum_vector
[2]*lum_vector
[2])))] / PI
));
709 // Do I smell optimization? :-)
715 for (i
= 0; i
< 361; i
++) {
716 cost
[i
] = cos((double)i
*(2*PI
/(double)360));
717 sint
[i
] = sin((double)i
*(2*PI
/(double)360));
720 for (i
= 0; i
< 100; i
++) acost
[i
] = acos((double)(-50+i
)/50);
723 void setupobj(char *filename
)
730 ycenter
= 15 - 2*show_load
;
732 if (strcmp(filename
,"") != 0)
741 matrix
= (float **)malloc(nofcoords
*sizeof(float *)); mem_alloc_error(matrix
);
742 planes
= (int **)malloc(nofplanes
*sizeof(int *)); mem_alloc_error(planes
);
743 plane_color
= (int *)malloc(nofplanes
*sizeof(int)); mem_alloc_error(plane_color
);
744 zorder
= (int *)malloc(nofplanes
*sizeof(int)); mem_alloc_error(zorder
);
746 for (i
= 0; i
< nofplanes
; i
++) zorder
[i
] = i
;
748 for (i
= 0; i
< nofcoords
; i
++) {
749 matrix
[i
] = (float *)malloc(3*sizeof(float));
750 mem_alloc_error(matrix
[i
]);
753 for (i
= 0; i
< nofplanes
; i
++) {
754 planes
[i
] = (int *)malloc(3*sizeof(int));
755 mem_alloc_error(planes
[i
]);
758 cline
= (int *)malloc((noflines
+1)*sizeof(int)); mem_alloc_error(cline
);
760 matrix
[0][0] = -180; matrix
[0][1] = -180; matrix
[0][2] = 180; // 0
761 matrix
[1][0] = 180; matrix
[1][1] = -180; matrix
[1][2] = 180; // 1
762 matrix
[2][0] = 180; matrix
[2][1] = 180; matrix
[2][2] = 180; // 2
763 matrix
[3][0] = -180; matrix
[3][1] = 180; matrix
[3][2] = 180; // 3
764 matrix
[4][0] = -180; matrix
[4][1] = -180; matrix
[4][2] = -180; // 4
765 matrix
[5][0] = 180; matrix
[5][1] = -180; matrix
[5][2] = -180; // 5
766 matrix
[6][0] = 180; matrix
[6][1] = 180; matrix
[6][2] = -180; // 6
767 matrix
[7][0] = -180; matrix
[7][1] = 180; matrix
[7][2] = -180; // 7
769 cline
[0] = 1; cline
[1] = 2;
770 cline
[2] = 2; cline
[3] = 3;
771 cline
[4] = 3; cline
[5] = 4;
772 cline
[6] = 4; cline
[7] = 1;
773 cline
[8] = 5; cline
[9] = 6;
774 cline
[10] = 6; cline
[11] = 7;
775 cline
[12] = 7; cline
[13] = 8;
776 cline
[14] = 8; cline
[15] = 5;
777 cline
[16] = 1; cline
[17] = 5;
778 cline
[18] = 2; cline
[19] = 6;
779 cline
[20] = 3; cline
[21] = 7;
780 cline
[22] = 4; cline
[23] = 8;
782 planes
[0][0] = 0; planes
[0][1] = 1; planes
[0][2] = 3;
783 planes
[1][0] = 1; planes
[1][1] = 2; planes
[1][2] = 3;
784 planes
[2][0] = 1; planes
[2][1] = 5; planes
[2][2] = 6;
785 planes
[3][0] = 1; planes
[3][1] = 6; planes
[3][2] = 2;
787 planes
[4][0] = 4; planes
[4][1] = 0; planes
[4][2] = 3;
788 planes
[5][0] = 4; planes
[5][1] = 3; planes
[5][2] = 7;
789 planes
[6][0] = 3; planes
[6][1] = 2; planes
[6][2] = 7;
790 planes
[7][0] = 7; planes
[7][1] = 2; planes
[7][2] = 6;
792 planes
[8][0] = 4; planes
[8][1] = 1; planes
[8][2] = 0;
793 planes
[9][0] = 4; planes
[9][1] = 5; planes
[9][2] = 1;
794 planes
[10][0] = 5; planes
[10][1] = 4; planes
[10][2] = 7;
795 planes
[11][0] = 5; planes
[11][1] = 7; planes
[11][2] = 6;
798 rmatrix
= (float **)realloc(rmatrix
,nofcoords
*sizeof(float *)); mem_alloc_error(rmatrix
);
799 for (i
= 0; i
< nofcoords
; i
++) {
800 rmatrix
[i
] = (float *)malloc(3*sizeof(float));
801 mem_alloc_error(rmatrix
[i
]);
805 * Find the longest discance between all coordinates relative to the origin
808 for (i
= 0; i
< nofcoords
; i
++) {
809 j
= (int)sqrt((pow(matrix
[i
][0],2)+pow(matrix
[i
][1],2)+pow(matrix
[i
][2],2)));
810 if (j
> biggest
) biggest
= j
;
814 * Scale every coordinate using the calculated factor
817 scale
= 280 / (float)biggest
;
819 for (i
= 0; i
< nofcoords
; i
++) {
820 matrix
[i
][0] *= scale
;
821 matrix
[i
][1] *= scale
;
822 matrix
[i
][2] *= scale
;
829 //**** Application Management, I/O etc. ***********
830 //*************************************************
833 printf("\nwmCube %s (%s)\n\n", WMCUBE_VERSION
, REV_DATE
);
836 printf(" -o <filename or directory>: load external 3d-object(s).\n\n");
838 printf(" -o <filename>: load external 3d-object.\n\n");
841 printf(" -d x: rotate x degrees/step when the cpu is idle. (default 1)\n");
842 printf(" -r x: rotate 1 degree faster every x percent of cpu-usage. (default 25)\n");
845 printf(" -c x: which cpu (0,1,2..) to monitor. (default average over all)\n");
846 printf(" -n : exclude \"nice\" processes. (default OFF)\n");
850 printf(" -c x: which cpu (0,1,2..) to monitor. (default average over all)\n");
854 printf(" -n : exclude \"nice\" processes. (default OFF)\n");
858 printf(" -n : exclude \"nice\" processes. (default OFF)\n");
861 printf(" -b : draw the cube in a brighter color. (default OFF)\n");
862 printf(" -i : invert cube speed. (default OFF)\n");
863 printf(" -p : do not display cpu-load (default OFF)\n");
864 printf(" -h : display this helptext.\n\n");
869 fprintf(stderr
, "%s: exiting", pname
);
873 #ifndef SOLARIS // scan4objects doesnt work on Solaris because of alphasort
874 int scan4objects(char *dir
)
876 struct dirent
**names
;
879 n
= scandir(dir
,&names
,0,alphasort
);
882 if (strstr(names
[n
]->d_name
,".wmc") != NULL
)
884 objects
[nof_objects
] = (char *)malloc(strlen(dir
)+strlen(names
[n
]->d_name
)+2);
885 strcpy(objects
[nof_objects
],dir
);
886 if (dir
[strlen(dir
)] != '/') strcat(objects
[nof_objects
],"/");
887 strcat(objects
[nof_objects
++],names
[n
]->d_name
);
896 if (nof_objects
== 0) return -1;
897 setupobj(objects
[rand() % (nof_objects
)]);
903 int loadobj(char *filename
) {
907 int i
= 0, counter
= 1;
909 //printf("\nLoading file %s...",filename); fflush(stdout);
911 if ((fp
= fopen(filename
,"rt")) == NULL
) {
912 printf("\nERROR: wmCube object-file not found (%s).\n\n",filename
);
918 if (strcmp(tmp
,"WMCUBE_COORDINATES") != 0) {
919 printf("\nError in objectfile: it must start with WMCUBE_COORDINATES\n\n");
927 while ((strcmp(tmp
,"WMCUBE_LINES") != 0) && (strcmp(tmp
,"WMCUBE_PLANES") != 0)) {
929 matrix
= (float **)realloc(matrix
,(i
+1)*sizeof(float *)); mem_alloc_error(matrix
);
930 matrix
[i
] = (float *)malloc(3*sizeof(float)); mem_alloc_error(matrix
[i
]);
931 fscanf(fp
,"%f %f %f",&matrix
[i
][0],&matrix
[i
][1],&matrix
[i
][2]);
932 //printf("\n%d: %f %f %f",atoi(tmp), matrix[i][0],matrix[i][1],matrix[i][2]);
934 if (atoi(tmp
) != (++i
)) {
936 printf("\nError in objectfile (WMCUBE_COORDINATES section):\n"
937 "the coordinates must be listed in order 1..n\n\n");
944 printf("\nError in objectfile: you must have a section WMCUBE_LINES or WMCUBE_PLANES\n\n");
953 if (strcmp(tmp
,"WMCUBE_LINES") == 0) {
958 cline
= (int *)realloc(cline
,(i
+2)*sizeof(int)); mem_alloc_error(cline
);
959 fscanf(fp
,"%d %d",&cline
[i
++],&cline
[i
++]);
960 //printf("\n%d %d",cline[i-2],cline[i-1]);
963 if (cline
[i
-2] > nofcoords
|| cline
[i
-1] > nofcoords
) {
964 printf("\nError in objectfile (WMCUBE_LINES section):\n"
965 "coordinates %d or/and %d doesnt exist\n\n",cline
[i
-2],cline
[i
-1]);
972 else if (strcmp(tmp
,"WMCUBE_PLANES") == 0) {
976 planes
= (int **)realloc(planes
,(i
+1)*sizeof(int *)); mem_alloc_error(planes
);
977 planes
[i
] = (int *)malloc(3*sizeof(int)); mem_alloc_error(planes
[i
]);
978 fscanf(fp
,"%d %d %d",&planes
[i
][0],&planes
[i
][1],&planes
[i
][2]);
979 //printf("\n%d: %d %d %d",i,planes[i][0],planes[i][1],planes[i][2]);
981 planes
[i
][0]--; planes
[i
][1]--; planes
[i
][2]--;
982 //printf("\n%d: %d %d %d\n",i,planes[i][0],planes[i][1],planes[i][2]);
986 if (planes
[i
][0] > nofcoords
|| planes
[i
][1] > nofcoords
|| planes
[i
][2] > nofcoords
) {
987 printf("\nError in objectfile (WMCUBE_PLANES section):\n"
988 "coordinates %d or/and %d or/and %d doesnt exist\n\n",planes
[i
][0],planes
[i
][1],planes
[i
][2]);
995 plane_color
= (int *)malloc(nofplanes
*sizeof(int)); mem_alloc_error(plane_color
);
996 zorder
= (int *)malloc(nofplanes
*sizeof(int)); mem_alloc_error(zorder
);
997 for (i
= 0; i
< nofplanes
; i
++) zorder
[i
] = i
;
1000 printf("\nError in objectfile: you must have a section WMCUBE_LINES or WMCUBE_PLANES\n\n");
1009 void mem_alloc_error(void *block
) {
1010 if (block
== NULL
) {
1011 printf("\nError allocating memory!\n\n");
1017 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1018 * Begin System Specific Code. If you wish to port wmcube to a new platform,
1019 * you'll need to implement the following operations:
1021 * int init_calc_cpu();
1022 * Perform feature tests to determine whether wmcube can run, and set up
1023 * any files/data structures/etc. to gather statistics.
1025 * int calc_cpu_total();
1026 * return an integer reflecting the current CPU load
1032 * init_calc_cpu doesn't have much to do on Linux, but it can check to see if
1033 * /proc/stat is available; if the user selected to monitor a particular CPU,
1034 * it can check it's existence.
1043 sprintf(check_cpu
, "cpu%d", which_cpu
);
1045 if ((fp
= fopen("/proc/stat","rb")) == NULL
) {
1046 perror("/proc/stat required for this system");
1050 if (which_cpu
== -1)
1053 for (i
= -2; i
< which_cpu
; i
++) {
1054 fscanf(fp
, "%s", cpuid
);
1057 if (strcmp(check_cpu
,cpuid
) != 0) {
1058 fprintf(stderr
, "ERROR: could not read cpu-load on %s. Are you "
1059 "sure you have an SMP system?\n",check_cpu
);
1065 int calc_cpu_total() {
1066 int total
, used
, t
=0, i
;
1067 static int previous_total
= 0, previous_used
= 0;
1069 int cpu
,nice
,system
,idle
;
1072 fp
= fopen("/proc/stat","rt");
1074 for (i
= -2; i
< which_cpu
; i
++) {
1075 fscanf(fp
,"%s %d %d %d %d",cpuid
,&cpu
,&nice
,&system
,&idle
);
1080 used
= cpu
+ system
+ use_nice
*nice
;
1081 total
= used
+ idle
+ (1-use_nice
)*nice
;
1083 t
= 100 * (double)(used
- previous_used
) / (double)(total
- previous_total
);
1084 previous_total
= total
;
1085 previous_used
= used
;
1090 #elif defined SOLARIS
1091 #include <sys/types.h>
1092 #include <sys/sysinfo.h>
1095 static kstat_ctl_t
*kc
;
1096 static kstat_t
**cpu_ksp_list
;
1097 static kstat_t
*the_cpu
;
1101 * The biggest subtlety of the Solaris port is that init_calc_cpu can be called
1102 * after the initial program setup. This occurs when a 'kstat state change'
1103 * occurs. Usually this means that a CPU has been taken on or off-line using
1104 * the psradm command. Another possibility is that on server systems, a new
1105 * CPU might have been hot-added to a running system.
1107 * As a result, init_calc_cpu frees any resources it might have setup if needed,
1108 * and reinitializes everything.
1116 if ((kc
= kstat_open()) == NULL
) {
1117 fprintf(stderr
, "wmcube: can't open /dev/kstat\n");
1122 if (which_cpu
!= -1) {
1124 * User selected to monitor a particlur CPU. find it...
1126 for (ksp
= kc
->kc_chain
; ksp
; ksp
= ksp
->ks_next
) {
1127 if ((strcmp(ksp
->ks_module
, "cpu_stat") == 0) &&
1128 (ksp
->ks_instance
== which_cpu
)) {
1133 if (the_cpu
== NULL
) {
1134 fprintf(stderr
, "CPU %d not found\n", which_cpu
);
1139 * User selected to monitor all CPUs. First, count them.
1141 for (ksp
= kc
->kc_chain
; ksp
; ksp
= ksp
->ks_next
) {
1142 if (strcmp(ksp
->ks_module
, "cpu_stat") == 0)
1149 cpu_ksp_list
= (kstat_t
**) calloc(i
* sizeof (kstat_t
*), 1);
1153 * stash the ksp for each CPU.
1156 for (ksp
= kc
->kc_chain
; ksp
; ksp
= ksp
->ks_next
) {
1157 if (strcmp(ksp
->ks_module
, "cpu_stat") == 0) {
1158 cpu_ksp_list
[i
] = ksp
;
1166 int calc_cpu_total()
1170 static int previous_total
= 0, previous_used
= 0;
1171 int used
, total
, t
, user
= 0, wait
= 0, kern
= 0, idle
= 0;
1174 * Read each cpu's data. If the kstat chain has changed (a state change
1175 * has happened, maybe a new cpu was added to the system or one went
1176 * away), then reinitialize everything with init_calc_cpu(). Finally,
1177 * recursively call calc_cpu_total.
1179 * We'll need to do a little better than this in the future, since we
1180 * could recurse too much in the pathological case here.
1182 if (which_cpu
== -1) {
1183 for (i
= 0; i
< ncpus
; i
++) {
1184 if (kstat_read(kc
, cpu_ksp_list
[i
],
1185 (void *)&stat
) == -1) {
1186 if (init_calc_cpu() != 0) {
1187 fprintf(stderr
, "failed to "
1188 "reinitialize following state "
1192 return (calc_cpu_total());
1194 user
+= stat
.cpu_sysinfo
.cpu
[CPU_USER
]; /* user */
1195 wait
+= stat
.cpu_sysinfo
.cpu
[CPU_WAIT
]; /* io wait */
1196 kern
+= stat
.cpu_sysinfo
.cpu
[CPU_KERNEL
]; /* sys */
1197 idle
+= stat
.cpu_sysinfo
.cpu
[CPU_IDLE
]; /*idle("free")*/
1200 if (kstat_read(kc
, the_cpu
, (void *)&stat
) == -1) {
1201 if (init_calc_cpu() != 0) {
1202 fprintf(stderr
, "failed to reinitialize "
1203 "following state change\n");
1206 return (calc_cpu_total());
1208 user
+= stat
.cpu_sysinfo
.cpu
[CPU_USER
]; /* user */
1209 wait
+= stat
.cpu_sysinfo
.cpu
[CPU_WAIT
]; /* io wait */
1210 kern
+= stat
.cpu_sysinfo
.cpu
[CPU_KERNEL
]; /* sys */
1211 idle
+= stat
.cpu_sysinfo
.cpu
[CPU_IDLE
]; /* idle("free") */
1214 used
= user
+ wait
+ kern
;
1215 total
= used
+ idle
;
1216 t
= 100 * (double)(used
- previous_used
) /
1217 (double)(total
- previous_total
);
1218 previous_total
= total
;
1219 previous_used
= used
;
1223 #elif defined FREEBSD
1226 #include <sys/dkstat.h>
1231 if ((kd
= kvm_open(NULL
, NULL
, NULL
, O_RDONLY
, "kvm_open")) == NULL
)
1233 printf("\nError: unable to open kvm\n\n");
1236 kvm_nlist(kd
, nlst
);
1237 if (nlst
[0].n_type
== 0)
1239 printf("\nError: unable to get nlist\n\n");
1246 int calc_cpu_total() {
1247 int total
, used
, t
=0;
1248 static int previous_total
= 0, previous_used
= 0;
1249 int cpu
,nice
,system
,idle
;
1250 unsigned long int cpu_time
[CPUSTATES
];
1252 if (kvm_read(kd
, nlst
[0].n_value
, &cpu_time
, sizeof(cpu_time
))
1253 != sizeof(cpu_time
))
1255 printf("\nError reading kvm\n\n");
1259 cpu
= cpu_time
[CP_USER
];
1260 nice
= cpu_time
[CP_NICE
];
1261 system
= cpu_time
[CP_SYS
];
1262 idle
= cpu_time
[CP_IDLE
];
1264 used
= cpu
+ system
+ use_nice
*nice
;
1265 total
= used
+ idle
+ (1-use_nice
)*nice
;
1267 t
= 100 * (double)(used
- previous_used
) / (double)(total
- previous_total
);
1268 previous_total
= total
;
1269 previous_used
= used
;
1274 #elif defined OPENBSD
1281 int calc_cpu_total() {
1284 (void) getloadavg(avenrun
, sizeof(avenrun
) / sizeof(avenrun
[0]));
1285 return(((5.0*avenrun
[0] + 0.5) > 50) ? 50 : (5.0*avenrun
[0] + 0.5))*2;
1289 #elif defined NETBSD /* END OPENBSD */
1290 #include <sys/sched.h>
1291 #include <sys/sysctl.h>
1293 int init_calc_cpu ()
1298 int calc_cpu_total ()
1300 static u_int64_t last_cp_time
[CPUSTATES
] = { 0, 0, 0, 0, 0 };
1301 u_int64_t curr_cp_time
[CPUSTATES
];
1302 u_int64_t total_time
= 0, idle_time
= 0;
1306 const int IDLE_TIME
= 4;
1307 const int NICE_TIME
= 1;
1309 ssize
= sizeof ( curr_cp_time
);
1311 mib
[1] = KERN_CP_TIME
;
1312 if ( sysctl ( mib
, 2, curr_cp_time
, &ssize
, NULL
, 0 ) ) {
1313 fprintf ( stderr
, "wmcube: unable to read CP_TIME from sysctl()\n" );
1317 curr_cp_time
[NICE_TIME
] = 0;
1319 /* NetBSD gives 5 CPUSTATES -
1320 * User, Nice, System, Interrupt, Idle
1322 idle_time
= curr_cp_time
[IDLE_TIME
] - last_cp_time
[IDLE_TIME
];
1323 for ( i
= 0; i
< CPUSTATES
; i
++ ) {
1324 total_time
+= ( curr_cp_time
[i
] - last_cp_time
[i
] );
1325 last_cp_time
[i
] = curr_cp_time
[i
];
1328 /* Calculate the % CPU usage as the User+Nice+System+Interrupt/Total
1331 return ( 100 * (int) ( total_time
- idle_time
) / total_time
);
1335 #else /* END NETBSD */
1338 * This is a stub which will compile for platforms other than LINUX or SOLARIS.
1339 * Use these to start your port to a new platform.
1346 int calc_cpu_total()
1351 #endif /* OS SPECIFIC CODE */