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

📄 bubblemon.c

📁 A GNOME panel applet that displays the CPU + memory load as a bubbling liquid. 一个Gnome面板程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Bubbling Load Monitoring Applet *  Copyright (C) 1999-2000 Johan Walles - d92-jwa@nada.kth.se *  http://www.nada.kth.se/~d92-jwa/code/#bubblemon * *  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., 59 Temple Street #330, Boston, MA 02111-1307, USA. *//* * This is a platform independent file that drives the program. */#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <sys/time.h>#include <string.h>#include <math.h>#include <time.h>/* Natural language translation stuff */#ifdef ENABLE_NLS#include <libintl.h>#include <locale.h>#ifndef _#define _ gettext#endif#else#define _#endif // ENABLE_NLS#include "bubblemon.h"#include "ui.h"#include "meter.h"#include "mail.h"#include "config.h"#include "netload.h"// Bottle graphics#include "msgInBottle.c"static bubblemon_picture_t bubblePic;static bubblemon_Physics physics;static meter_sysload_t sysload;/* Set the dimensions of the bubble array */void bubblemon_setSize(int width, int height){  if ((width != bubblePic.width) ||      (height != bubblePic.height))  {    bubblePic.width = width;    bubblePic.height = height;        if (bubblePic.airAndWater != NULL)    {      free(bubblePic.airAndWater);      bubblePic.airAndWater = NULL;    }        if (bubblePic.pixels != NULL)    {      free(bubblePic.pixels);      bubblePic.pixels = NULL;    }        if (physics.waterLevels != NULL)    {      free(physics.waterLevels);      physics.waterLevels = NULL;    }        if (physics.weeds != NULL)    {      free(physics.weeds);      physics.weeds = NULL;    }        physics.n_bubbles = 0;    physics.max_bubbles = 0;    if (physics.bubbles != NULL)    {      free(physics.bubbles);      physics.bubbles = NULL;    }  }}static void usage2string(/*@out@*/ char *string,			 u_int64_t used,			 u_int64_t max){  /* Create a string of the form "35/64Mb" */    unsigned int shiftme = 0;  char divisor_char = '\0';  if ((max >> 30) > 7000)    {      shiftme = 40;      divisor_char = 'T';    }  else if ((max >> 20) > 7000)    {      shiftme = 30;      divisor_char = 'G';    }  else if ((max >> 10) > 7000)    {      shiftme = 20;      divisor_char = 'M';    }  else if ((max >> 0) > 7000)    {      shiftme = 10;      divisor_char = 'k';    }  if (divisor_char == '\0')    {      sprintf(string, "%llu/%llu bytes",	      used >> shiftme,	      max >> shiftme);    }  else    {      sprintf(string, "%llu/%llu%cb",	      used >> shiftme,	      max >> shiftme,	      divisor_char);    }}const char *bubblemon_getTooltip(void){  char memstring[20], swapstring[20], loadstring[50];  static char *tooltipstring = 0;  int cpu_number;  if (!tooltipstring)  {    /* Prevent the tooltipstring buffer from overflowing on a system       with lots of CPUs */    tooltipstring =      malloc(sizeof(char) * (sysload.nCpus * 50 + 100));    assert(tooltipstring != NULL);  }  usage2string(memstring, sysload.memoryUsed, sysload.memorySize);  snprintf(tooltipstring, 90,           _("Memory used: %s"),           memstring);  if (sysload.swapSize > 0)  {    usage2string(swapstring, sysload.swapUsed, sysload.swapSize);    snprintf(loadstring, 90,	     _("\nSwap used: %s"),	     swapstring);    strcat(tooltipstring, loadstring);  }  if (sysload.nCpus == 1)    {      snprintf(loadstring, 45,               _("\nCPU load: %d%%"),               bubblemon_getCpuLoadPercentage(0));      strcat(tooltipstring, loadstring);    }  else    {      for (cpu_number = 0;           cpu_number < sysload.nCpus;           cpu_number++)        {          snprintf(loadstring, 45,                   _("\nCPU #%d load: %d%%"),                   cpu_number,                   bubblemon_getCpuLoadPercentage(cpu_number));          strcat(tooltipstring, loadstring);        }    }    return tooltipstring;}static int bubblemon_getMsecsSinceLastCall(){  /* Return the number of milliseconds that have passed since the last     time this function was called, or -1 if this is the first call.  If     a long time has passed since last time, the result is undefined. */  static long last_sec = 0L;  static long last_usec = 0L;  int returnMe = -1;  struct timeval currentTime;  /* What time is it now? */  gettimeofday(&currentTime, NULL);  if ((last_sec != 0L) || (last_usec != 0L))  {    returnMe = 1000 * (int)(currentTime.tv_sec - last_sec);    returnMe += ((int)(currentTime.tv_usec - last_usec)) / 1000L;  }  last_sec = currentTime.tv_sec;  last_usec = currentTime.tv_usec;  return returnMe;}static void bubblemon_updateWaterlevels(int msecsSinceLastCall){  float dt = msecsSinceLastCall / 30.0;  /* Typing fingers savers */  int w = bubblePic.width;  int h = bubblePic.height;    int x;    /* Where is the surface heading? */  float waterLevels_goal;  /* How high can the surface be? */  float waterLevels_max = (h - 0.55);    /* Move the water level with the current memory usage.  The water   * level goes from 0.0 to h so that you can get an integer height by   * just chopping off the decimals. */  waterLevels_goal =    ((float)sysload.memoryUsed / (float)sysload.memorySize) * waterLevels_max;    physics.waterLevels[0].y = waterLevels_goal;  physics.waterLevels[w - 1].y = waterLevels_goal;    for (x = 1; x < (w - 1); x++)  {    /* Accelerate the current waterlevel towards its correct value */    float current_waterlevel_goal = (physics.waterLevels[x - 1].y +				     physics.waterLevels[x + 1].y) / 2.0;        physics.waterLevels[x].dy +=      (current_waterlevel_goal - physics.waterLevels[x].y) * dt * VOLATILITY;    physics.waterLevels[x].dy *= VISCOSITY;    if (physics.waterLevels[x].dy > SPEED_LIMIT)      physics.waterLevels[x].dy = SPEED_LIMIT;    else if (physics.waterLevels[x].dy < -SPEED_LIMIT)      physics.waterLevels[x].dy = -SPEED_LIMIT;  }    for (x = 1; x < (w - 1); x++)  {    /* Move the current water level */    physics.waterLevels[x].y += physics.waterLevels[x].dy * dt;        if (physics.waterLevels[x].y > waterLevels_max)    {      /* Stop the wave if it hits the ceiling... */      physics.waterLevels[x].y = waterLevels_max;      physics.waterLevels[x].dy = 0.0;    }    else if (physics.waterLevels[x].y < 0.0)    {      /* ... or the floor. */      physics.waterLevels[x].y = 0.0;      physics.waterLevels[x].dy = 0.0;    }  }}static void bubblemon_addNourishment(bubblemon_Weed *weed, int percentage){  float heightLimit = (bubblePic.height * WEED_HEIGHT) / 100.0;    weed->nourishment += (heightLimit * percentage) / 100.0;    if (weed->nourishment + weed->height > heightLimit)  {    weed->nourishment = heightLimit - weed->height;  }}static void bubblemon_updateWeeds(int msecsSinceLastCall){  static int timeToNextUpdate = 0;  static int lastUpdatedWeed = 0;  int w = bubblePic.width;  int x;  // If enough time has elapsed...  timeToNextUpdate -= msecsSinceLastCall;  while (timeToNextUpdate <= 0)  {    // ... update the nourishment level of our next weed    lastUpdatedWeed--;    if ((lastUpdatedWeed <= 0) ||	(lastUpdatedWeed >= bubblePic.width))    {      lastUpdatedWeed = bubblePic.width - 1;    }        // Distribute the nourishment over several weeds    if (lastUpdatedWeed > 0)    {      bubblemon_addNourishment(&(physics.weeds[lastUpdatedWeed - 1]), (netload_getLoadPercentage() * 8) / 10);    }    bubblemon_addNourishment(&(physics.weeds[lastUpdatedWeed]), netload_getLoadPercentage());    if (lastUpdatedWeed < (bubblePic.width - 1))    {      bubblemon_addNourishment(&(physics.weeds[lastUpdatedWeed + 1]), (netload_getLoadPercentage() * 8) / 10);    }        timeToNextUpdate += NETLOAD_INTERVAL;  }    // For all weeds...  for (x = 0; x < w; x++)  {    // ... grow / shrink them according to their nourishment level    float speed;    float delta;        if (physics.weeds[x].nourishment <= 0.0)    {      speed = -WEED_MINSPEED;    }    else    {      speed = physics.weeds[x].nourishment * WEED_SPEEDFACTOR;      if (speed > WEED_MAXSPEED)      {	speed = WEED_MAXSPEED;      }      else if (speed < WEED_MINSPEED)      {	speed = WEED_MINSPEED;      }    }        delta = (speed * msecsSinceLastCall) / 1000.0;    if (delta > physics.weeds[x].nourishment)    {      delta = physics.weeds[x].nourishment;    }        if (delta > 0.0)    {      physics.weeds[x].nourishment -= delta;    }    physics.weeds[x].height += delta;    if (physics.weeds[x].height < 0.0)    {      physics.weeds[x].height = 0.0;    }  }}/* Update the bubbles (and possibly create new ones) */static void bubblemon_updateBubbles(int msecsSinceLastCall){  int i;  static float createNNewBubbles;  static bubblemon_layer_t lastNewBubbleLayer = BACKGROUND;  float dt = msecsSinceLastCall / 30.0;  /* Typing fingers saver */  int w = bubblePic.width;    /* Create new bubble(s) if the planets are correctly aligned... */  createNNewBubbles += ((float)bubblemon_getAverageLoadPercentage() *			(float)bubblePic.width *			dt) / 2000.0;    for (i = 0; i < createNNewBubbles; i++)  {    if (physics.n_bubbles < physics.max_bubbles)    {      lastNewBubbleLayer = (lastNewBubbleLayer == BACKGROUND) ? FOREGROUND : BACKGROUND;            /* We don't allow bubbles on the edges 'cause we'd have to clip them */      physics.bubbles[physics.n_bubbles].x = (random() % (w - 2)) + 1;      physics.bubbles[physics.n_bubbles].y = 0.0;      physics.bubbles[physics.n_bubbles].dy = 0.0;      /* Create alternately foreground and background bubbles */      physics.bubbles[physics.n_bubbles].layer = lastNewBubbleLayer;            if (RIPPLES != 0.0)      {	/* Raise the water level above where the bubble is created */	if ((physics.bubbles[physics.n_bubbles].x - 2) >= 0)	  physics.waterLevels[physics.bubbles[physics.n_bubbles].x - 2].y += RIPPLES;	physics.waterLevels[physics.bubbles[physics.n_bubbles].x - 1].y   += RIPPLES;	physics.waterLevels[physics.bubbles[physics.n_bubbles].x].y       += RIPPLES;	physics.waterLevels[physics.bubbles[physics.n_bubbles].x + 1].y   += RIPPLES;	if ((physics.bubbles[physics.n_bubbles].x + 2) < w)	  physics.waterLevels[physics.bubbles[physics.n_bubbles].x + 2].y += RIPPLES;      }          /* Count the new bubble */      physics.n_bubbles++;      createNNewBubbles--;    }  }    /* Move the bubbles */  for (i = 0; i < physics.n_bubbles; i++)  {    /* Accelerate the bubble upwards */    physics.bubbles[i].dy -= GRAVITY * dt;        /* Move the bubble vertically */    physics.bubbles[i].y +=      physics.bubbles[i].dy * dt *      ((physics.bubbles[i].layer == BACKGROUND) ? BGBUBBLE_SPEED : 1.0);        /* Did we lose it? */    if (physics.bubbles[i].y > physics.waterLevels[physics.bubbles[i].x].y)    {      if (RIPPLES != 0.0)      {        /* Lower the water level around where the bubble is           about to vanish */        physics.waterLevels[physics.bubbles[i].x - 1].y -= RIPPLES;        physics.waterLevels[physics.bubbles[i].x].y     -= 3 * RIPPLES;        physics.waterLevels[physics.bubbles[i].x + 1].y -= RIPPLES;      }            /* We just lost it, so let's nuke it */      physics.bubbles[i].x  = physics.bubbles[physics.n_bubbles - 1].x;      physics.bubbles[i].y  = physics.bubbles[physics.n_bubbles - 1].y;      physics.bubbles[i].dy = physics.bubbles[physics.n_bubbles - 1].dy;      physics.n_bubbles--;            /* We must check the previously last bubble, which is        now the current bubble, also. */      i--;      continue;    }  }}#define MIN(a,b) (((a) < (b)) ? (a) : (b))/* Update the bottle */static void bubblemon_updateBottle(int msecsSinceLastCall, int youveGotMail){  float dt = msecsSinceLastCall / 30.0;  float gravityDdy;  float dragDdy;  int isInWater;  // The MIN stuff prevents the bottle from floating above the visible  // area even when the water surface is at the top of the display  isInWater =    physics.bottle_y < MIN(physics.waterLevels[bubblePic.width / 2].y,			   bubblePic.height - msgInBottle.height / 2);  if (youveGotMail) {    if (physics.bottle_state == GONE) {      // Drop a new bottle      physics.bottle_y = bubblePic.height + msgInBottle.height;      physics.bottle_dy = 0.0;      physics.bottle_state = FALLING;    } else if (physics.bottle_state == SINKING) {      physics.bottle_state = FLOATING;    }  } else {    /* No unread mail */    if ((physics.bottle_state == FALLING) ||	(physics.bottle_state == FLOATING))    {      physics.bottle_state = SINKING;    }  }  if (physics.bottle_state == GONE) {    return;  }  /* Accelerate the bottle */  if ((physics.bottle_state == FALLING) ||      (physics.bottle_state == SINKING) ||      !isInWater)  {    // Gravity pulls the bottle down    gravityDdy = 2.0 * GRAVITY * dt;  } else {    // Gravity floats the bottle up    gravityDdy = 2.0 * -(GRAVITY * dt);  }  if (isInWater) {    dragDdy = (physics.bottle_dy * physics.bottle_dy) * BOTTLE_DRAG;    // If the speed is positive...    if (physics.bottle_dy > 0.0) {      // ... then the drag should be negative      dragDdy = -dragDdy;    }  } else {    dragDdy = 0.0;  }  physics.bottle_dy += gravityDdy + dragDdy;    /* Move the bottle vertically */  physics.bottle_y += physics.bottle_dy * dt;    // If the bottle has fallen on screen...  if ((physics.bottle_state == FALLING) &&      (physics.bottle_y < bubblePic.height))  {    // ... it should start floating instead of falling    physics.bottle_state = FLOATING;  }    /* Did we lose it? */  if ((physics.bottle_state == SINKING) && (physics.bottle_y + msgInBottle.height < 0.0)) {    physics.bottle_state = GONE;  }}static const bubblemon_color_t bubblemon_constant2color(const unsigned int constant){  bubblemon_color_t returnMe;    returnMe.components.r = (constant >> 24) & 0xff;  returnMe.components.g = (constant >> 16) & 0xff;   returnMe.components.b = (constant >> 8)  & 0xff;   returnMe.components.a = (constant >> 0)  & 0xff;    return returnMe;}/* The amount parameter is 0-255. */static inline bubblemon_color_t bubblemon_interpolateColor(const bubblemon_color_t c1,							   const bubblemon_color_t c2,							   const int amount){  int a, r, g, b;  bubblemon_color_t returnme;  assert(amount >= 0 && amount < 256);

⌨️ 快捷键说明

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