2006-03-04 18:16:49 +00:00
|
|
|
|
/*
|
|
|
|
|
htop - Meter.c
|
2011-05-26 16:35:07 +00:00
|
|
|
|
(C) 2004-2011 Hisham H. Muhammad
|
2006-03-04 18:16:49 +00:00
|
|
|
|
Released under the GNU GPL, see the COPYING file
|
|
|
|
|
in the source distribution for its full text.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "Meter.h"
|
2011-12-26 21:35:57 +00:00
|
|
|
|
|
|
|
|
|
#include "RichString.h"
|
2006-03-04 18:16:49 +00:00
|
|
|
|
#include "Object.h"
|
|
|
|
|
#include "CRT.h"
|
|
|
|
|
#include "String.h"
|
2011-12-26 21:35:57 +00:00
|
|
|
|
#include "ListItem.h"
|
2012-12-05 15:12:20 +00:00
|
|
|
|
#include "Settings.h"
|
2009-06-02 04:51:23 +00:00
|
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdarg.h>
|
2006-03-04 18:16:49 +00:00
|
|
|
|
#include <assert.h>
|
2012-12-05 15:12:20 +00:00
|
|
|
|
#include <sys/time.h>
|
2006-04-10 20:40:38 +00:00
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
|
#define METER_BUFFER_LEN 256
|
2006-03-04 18:16:49 +00:00
|
|
|
|
|
2015-01-23 05:08:21 +00:00
|
|
|
|
#define GRAPH_DELAY (DEFAULT_DELAY/2)
|
|
|
|
|
|
2006-03-04 18:16:49 +00:00
|
|
|
|
/*{
|
2011-12-26 21:35:57 +00:00
|
|
|
|
#include "ListItem.h"
|
2015-01-22 01:27:31 +00:00
|
|
|
|
|
|
|
|
|
#include <sys/time.h>
|
2006-03-04 18:16:49 +00:00
|
|
|
|
|
|
|
|
|
typedef struct Meter_ Meter;
|
|
|
|
|
|
2012-12-05 15:12:20 +00:00
|
|
|
|
typedef void(*Meter_Init)(Meter*);
|
|
|
|
|
typedef void(*Meter_Done)(Meter*);
|
|
|
|
|
typedef void(*Meter_UpdateMode)(Meter*, int);
|
2006-04-10 20:40:38 +00:00
|
|
|
|
typedef void(*Meter_SetValues)(Meter*, char*, int);
|
2006-03-04 18:16:49 +00:00
|
|
|
|
typedef void(*Meter_Draw)(Meter*, int, int, int);
|
|
|
|
|
|
2012-12-05 15:12:20 +00:00
|
|
|
|
typedef struct MeterClass_ {
|
|
|
|
|
ObjectClass super;
|
|
|
|
|
const Meter_Init init;
|
|
|
|
|
const Meter_Done done;
|
|
|
|
|
const Meter_UpdateMode updateMode;
|
|
|
|
|
const Meter_Draw draw;
|
|
|
|
|
const Meter_SetValues setValues;
|
|
|
|
|
const int defaultMode;
|
|
|
|
|
const double total;
|
|
|
|
|
const int* attributes;
|
2010-02-25 01:43:18 +00:00
|
|
|
|
const char* name;
|
|
|
|
|
const char* uiName;
|
|
|
|
|
const char* caption;
|
2014-01-16 03:40:47 +00:00
|
|
|
|
const char maxItems;
|
|
|
|
|
char curItems;
|
2012-12-05 15:12:20 +00:00
|
|
|
|
} MeterClass;
|
|
|
|
|
|
|
|
|
|
#define As_Meter(this_) ((MeterClass*)((this_)->super.klass))
|
|
|
|
|
#define Meter_initFn(this_) As_Meter(this_)->init
|
|
|
|
|
#define Meter_init(this_) As_Meter(this_)->init((Meter*)(this_))
|
|
|
|
|
#define Meter_done(this_) As_Meter(this_)->done((Meter*)(this_))
|
|
|
|
|
#define Meter_updateModeFn(this_) As_Meter(this_)->updateMode
|
|
|
|
|
#define Meter_updateMode(this_, m_) As_Meter(this_)->updateMode((Meter*)(this_), m_)
|
|
|
|
|
#define Meter_drawFn(this_) As_Meter(this_)->draw
|
|
|
|
|
#define Meter_doneFn(this_) As_Meter(this_)->done
|
|
|
|
|
#define Meter_setValues(this_, c_, i_) As_Meter(this_)->setValues((Meter*)(this_), c_, i_)
|
|
|
|
|
#define Meter_defaultMode(this_) As_Meter(this_)->defaultMode
|
2014-01-16 03:40:47 +00:00
|
|
|
|
#define Meter_getItems(this_) As_Meter(this_)->curItems
|
|
|
|
|
#define Meter_setItems(this_, n_) As_Meter(this_)->curItems = (n_)
|
2012-12-05 15:12:20 +00:00
|
|
|
|
#define Meter_attributes(this_) As_Meter(this_)->attributes
|
|
|
|
|
#define Meter_name(this_) As_Meter(this_)->name
|
|
|
|
|
#define Meter_uiName(this_) As_Meter(this_)->uiName
|
2006-04-10 20:40:38 +00:00
|
|
|
|
|
|
|
|
|
struct Meter_ {
|
|
|
|
|
Object super;
|
2012-12-05 15:12:20 +00:00
|
|
|
|
Meter_Draw draw;
|
|
|
|
|
|
2006-04-10 20:40:38 +00:00
|
|
|
|
char* caption;
|
|
|
|
|
int mode;
|
|
|
|
|
int param;
|
2011-03-22 20:37:08 +00:00
|
|
|
|
void* drawData;
|
2006-04-10 20:40:38 +00:00
|
|
|
|
int h;
|
2015-01-22 01:27:31 +00:00
|
|
|
|
struct ProcessList_* pl;
|
2006-03-04 18:16:49 +00:00
|
|
|
|
double* values;
|
|
|
|
|
double total;
|
|
|
|
|
};
|
|
|
|
|
|
2012-12-05 15:12:20 +00:00
|
|
|
|
typedef struct MeterMode_ {
|
|
|
|
|
Meter_Draw draw;
|
|
|
|
|
const char* uiName;
|
|
|
|
|
int h;
|
|
|
|
|
} MeterMode;
|
2011-03-22 20:37:08 +00:00
|
|
|
|
|
2006-04-10 20:40:38 +00:00
|
|
|
|
typedef enum {
|
|
|
|
|
CUSTOM_METERMODE = 0,
|
|
|
|
|
BAR_METERMODE,
|
|
|
|
|
TEXT_METERMODE,
|
|
|
|
|
GRAPH_METERMODE,
|
|
|
|
|
LED_METERMODE,
|
|
|
|
|
LAST_METERMODE
|
|
|
|
|
} MeterModeId;
|
|
|
|
|
|
2012-12-05 15:12:20 +00:00
|
|
|
|
typedef struct GraphData_ {
|
|
|
|
|
struct timeval time;
|
|
|
|
|
double values[METER_BUFFER_LEN];
|
|
|
|
|
} GraphData;
|
|
|
|
|
|
2006-03-04 18:16:49 +00:00
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
#ifndef MIN
|
|
|
|
|
#define MIN(a,b) ((a)<(b)?(a):(b))
|
|
|
|
|
#endif
|
2006-03-23 18:55:29 +00:00
|
|
|
|
#ifndef MAX
|
|
|
|
|
#define MAX(a,b) ((a)>(b)?(a):(b))
|
|
|
|
|
#endif
|
2006-03-04 18:16:49 +00:00
|
|
|
|
|
2012-12-05 15:12:20 +00:00
|
|
|
|
MeterClass Meter_class = {
|
|
|
|
|
.super = {
|
|
|
|
|
.extends = Class(Object)
|
|
|
|
|
}
|
|
|
|
|
};
|
2006-03-04 18:16:49 +00:00
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
|
Meter* Meter_new(struct ProcessList_* pl, int param, MeterClass* type) {
|
2014-01-16 03:40:47 +00:00
|
|
|
|
Meter* this = calloc(1, sizeof(Meter));
|
2012-12-05 15:12:20 +00:00
|
|
|
|
Object_setClass(this, type);
|
2006-04-10 20:40:38 +00:00
|
|
|
|
this->h = 1;
|
|
|
|
|
this->param = param;
|
|
|
|
|
this->pl = pl;
|
2014-01-16 03:40:47 +00:00
|
|
|
|
char maxItems = type->maxItems;
|
|
|
|
|
if (maxItems == 0) {
|
|
|
|
|
maxItems = 1;
|
|
|
|
|
}
|
|
|
|
|
type->curItems = maxItems;
|
|
|
|
|
this->values = calloc(maxItems, sizeof(double));
|
2006-04-10 20:40:38 +00:00
|
|
|
|
this->total = type->total;
|
|
|
|
|
this->caption = strdup(type->caption);
|
2012-12-05 15:12:20 +00:00
|
|
|
|
if (Meter_initFn(this))
|
|
|
|
|
Meter_init(this);
|
|
|
|
|
Meter_setMode(this, type->defaultMode);
|
2006-04-10 20:40:38 +00:00
|
|
|
|
return this;
|
2006-03-04 18:16:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Meter_delete(Object* cast) {
|
2011-03-31 20:24:59 +00:00
|
|
|
|
if (!cast)
|
|
|
|
|
return;
|
2006-03-04 18:16:49 +00:00
|
|
|
|
Meter* this = (Meter*) cast;
|
2012-12-05 15:12:20 +00:00
|
|
|
|
if (Meter_doneFn(this)) {
|
|
|
|
|
Meter_done(this);
|
2006-04-10 20:40:38 +00:00
|
|
|
|
}
|
2011-03-22 20:37:08 +00:00
|
|
|
|
if (this->drawData)
|
|
|
|
|
free(this->drawData);
|
2006-04-10 20:40:38 +00:00
|
|
|
|
free(this->caption);
|
|
|
|
|
free(this->values);
|
2006-03-04 18:16:49 +00:00
|
|
|
|
free(this);
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-25 01:43:18 +00:00
|
|
|
|
void Meter_setCaption(Meter* this, const char* caption) {
|
2006-04-10 20:40:38 +00:00
|
|
|
|
free(this->caption);
|
|
|
|
|
this->caption = strdup(caption);
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-22 12:40:20 +00:00
|
|
|
|
static inline void Meter_displayBuffer(Meter* this, char* buffer, RichString* out) {
|
2012-12-05 15:12:20 +00:00
|
|
|
|
if (Object_displayFn(this)) {
|
|
|
|
|
Object_display(this, out);
|
2006-04-10 20:40:38 +00:00
|
|
|
|
} else {
|
2012-12-05 15:12:20 +00:00
|
|
|
|
RichString_write(out, CRT_colors[Meter_attributes(this)[0]], buffer);
|
2006-03-04 18:16:49 +00:00
|
|
|
|
}
|
2006-04-10 20:40:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Meter_setMode(Meter* this, int modeIndex) {
|
2006-05-09 18:18:08 +00:00
|
|
|
|
if (modeIndex > 0 && modeIndex == this->mode)
|
2006-04-10 20:40:38 +00:00
|
|
|
|
return;
|
|
|
|
|
if (!modeIndex)
|
|
|
|
|
modeIndex = 1;
|
|
|
|
|
assert(modeIndex < LAST_METERMODE);
|
2012-12-05 15:12:20 +00:00
|
|
|
|
if (Meter_defaultMode(this) == CUSTOM_METERMODE) {
|
|
|
|
|
this->draw = Meter_drawFn(this);
|
|
|
|
|
if (Meter_updateModeFn(this))
|
|
|
|
|
Meter_updateMode(this, modeIndex);
|
2006-04-10 20:40:38 +00:00
|
|
|
|
} else {
|
2006-05-09 18:18:08 +00:00
|
|
|
|
assert(modeIndex >= 1);
|
2011-03-22 20:37:08 +00:00
|
|
|
|
if (this->drawData)
|
|
|
|
|
free(this->drawData);
|
|
|
|
|
this->drawData = NULL;
|
2006-05-09 18:18:08 +00:00
|
|
|
|
|
|
|
|
|
MeterMode* mode = Meter_modes[modeIndex];
|
|
|
|
|
this->draw = mode->draw;
|
|
|
|
|
this->h = mode->h;
|
2006-03-04 18:16:49 +00:00
|
|
|
|
}
|
2006-04-10 20:40:38 +00:00
|
|
|
|
this->mode = modeIndex;
|
2006-03-04 18:16:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-04-10 20:40:38 +00:00
|
|
|
|
ListItem* Meter_toListItem(Meter* this) {
|
|
|
|
|
char mode[21];
|
|
|
|
|
if (this->mode)
|
|
|
|
|
snprintf(mode, 20, " [%s]", Meter_modes[this->mode]->uiName);
|
|
|
|
|
else
|
|
|
|
|
mode[0] = '\0';
|
|
|
|
|
char number[11];
|
|
|
|
|
if (this->param > 0)
|
|
|
|
|
snprintf(number, 10, " %d", this->param);
|
|
|
|
|
else
|
|
|
|
|
number[0] = '\0';
|
|
|
|
|
char buffer[51];
|
2012-12-05 15:12:20 +00:00
|
|
|
|
snprintf(buffer, 50, "%s%s%s", Meter_uiName(this), number, mode);
|
2006-04-10 20:40:38 +00:00
|
|
|
|
return ListItem_new(buffer, 0);
|
2006-03-04 18:16:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-04-10 20:40:38 +00:00
|
|
|
|
/* ---------- TextMeterMode ---------- */
|
|
|
|
|
|
2008-03-09 08:58:38 +00:00
|
|
|
|
static void TextMeterMode_draw(Meter* this, int x, int y, int w) {
|
2006-04-10 20:40:38 +00:00
|
|
|
|
char buffer[METER_BUFFER_LEN];
|
2012-12-05 15:12:20 +00:00
|
|
|
|
Meter_setValues(this, buffer, METER_BUFFER_LEN - 1);
|
2014-04-21 21:59:52 +00:00
|
|
|
|
(void) w;
|
2006-04-10 20:40:38 +00:00
|
|
|
|
|
|
|
|
|
attrset(CRT_colors[METER_TEXT]);
|
|
|
|
|
mvaddstr(y, x, this->caption);
|
|
|
|
|
int captionLen = strlen(this->caption);
|
|
|
|
|
x += captionLen;
|
|
|
|
|
mvhline(y, x, ' ', CRT_colors[DEFAULT_COLOR]);
|
|
|
|
|
attrset(CRT_colors[RESET_COLOR]);
|
2010-11-22 12:40:20 +00:00
|
|
|
|
RichString_begin(out);
|
|
|
|
|
Meter_displayBuffer(this, buffer, &out);
|
|
|
|
|
RichString_printVal(out, y, x);
|
|
|
|
|
RichString_end(out);
|
2006-04-10 20:40:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------- BarMeterMode ---------- */
|
|
|
|
|
|
2006-06-06 20:41:01 +00:00
|
|
|
|
static char BarMeterMode_characters[] = "|#*@$%&";
|
2006-04-10 20:40:38 +00:00
|
|
|
|
|
2008-03-09 08:58:38 +00:00
|
|
|
|
static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
|
2006-04-10 20:40:38 +00:00
|
|
|
|
char buffer[METER_BUFFER_LEN];
|
2012-12-05 15:12:20 +00:00
|
|
|
|
Meter_setValues(this, buffer, METER_BUFFER_LEN - 1);
|
2006-04-10 20:40:38 +00:00
|
|
|
|
|
2006-03-04 18:16:49 +00:00
|
|
|
|
w -= 2;
|
|
|
|
|
attrset(CRT_colors[METER_TEXT]);
|
2008-09-23 06:21:28 +00:00
|
|
|
|
int captionLen = 3;
|
|
|
|
|
mvaddnstr(y, x, this->caption, captionLen);
|
2006-03-04 18:16:49 +00:00
|
|
|
|
x += captionLen;
|
|
|
|
|
w -= captionLen;
|
|
|
|
|
attrset(CRT_colors[BAR_BORDER]);
|
|
|
|
|
mvaddch(y, x, '[');
|
|
|
|
|
mvaddch(y, x + w, ']');
|
|
|
|
|
|
|
|
|
|
w--;
|
|
|
|
|
x++;
|
2011-08-26 20:55:09 +00:00
|
|
|
|
|
|
|
|
|
if (w < 1) {
|
|
|
|
|
attrset(CRT_colors[RESET_COLOR]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
char bar[w + 1];
|
2006-03-04 18:16:49 +00:00
|
|
|
|
|
|
|
|
|
int blockSizes[10];
|
|
|
|
|
for (int i = 0; i < w; i++)
|
|
|
|
|
bar[i] = ' ';
|
|
|
|
|
|
2011-10-25 00:05:46 +00:00
|
|
|
|
const size_t barOffset = w - MIN((int)strlen(buffer), w);
|
2011-08-26 20:55:09 +00:00
|
|
|
|
snprintf(bar + barOffset, w - barOffset + 1, "%s", buffer);
|
2006-03-04 18:16:49 +00:00
|
|
|
|
|
|
|
|
|
// First draw in the bar[] buffer...
|
|
|
|
|
int offset = 0;
|
2012-12-05 15:12:20 +00:00
|
|
|
|
int items = Meter_getItems(this);
|
|
|
|
|
for (int i = 0; i < items; i++) {
|
2006-03-04 18:16:49 +00:00
|
|
|
|
double value = this->values[i];
|
2006-04-10 20:40:38 +00:00
|
|
|
|
value = MAX(value, 0);
|
|
|
|
|
value = MIN(value, this->total);
|
2006-03-04 18:16:49 +00:00
|
|
|
|
if (value > 0) {
|
|
|
|
|
blockSizes[i] = ceil((value/this->total) * w);
|
|
|
|
|
} else {
|
|
|
|
|
blockSizes[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
int nextOffset = offset + blockSizes[i];
|
|
|
|
|
// (Control against invalid values)
|
2006-04-10 20:40:38 +00:00
|
|
|
|
nextOffset = MIN(MAX(nextOffset, 0), w);
|
2006-03-04 18:16:49 +00:00
|
|
|
|
for (int j = offset; j < nextOffset; j++)
|
|
|
|
|
if (bar[j] == ' ') {
|
|
|
|
|
if (CRT_colorScheme == COLORSCHEME_MONOCHROME) {
|
2006-04-10 20:40:38 +00:00
|
|
|
|
bar[j] = BarMeterMode_characters[i];
|
2006-03-04 18:16:49 +00:00
|
|
|
|
} else {
|
|
|
|
|
bar[j] = '|';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
offset = nextOffset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ...then print the buffer.
|
|
|
|
|
offset = 0;
|
2012-12-05 15:12:20 +00:00
|
|
|
|
for (int i = 0; i < items; i++) {
|
|
|
|
|
attrset(CRT_colors[Meter_attributes(this)[i]]);
|
2006-03-04 18:16:49 +00:00
|
|
|
|
mvaddnstr(y, x + offset, bar + offset, blockSizes[i]);
|
|
|
|
|
offset += blockSizes[i];
|
|
|
|
|
offset = MAX(offset, 0);
|
|
|
|
|
offset = MIN(offset, w);
|
|
|
|
|
}
|
|
|
|
|
if (offset < w) {
|
|
|
|
|
attrset(CRT_colors[BAR_SHADOW]);
|
|
|
|
|
mvaddnstr(y, x + offset, bar + offset, w - offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
move(y, x + w + 1);
|
|
|
|
|
attrset(CRT_colors[RESET_COLOR]);
|
|
|
|
|
}
|
|
|
|
|
|
2006-04-10 20:40:38 +00:00
|
|
|
|
/* ---------- GraphMeterMode ---------- */
|
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
|
static const char* GraphMeterMode_dotsUtf8[5][5] = {
|
|
|
|
|
{ /*00*/"⠀", /*01*/"⢀", /*02*/"⢠", /*03*/"⢰", /*04*/ "⢸" },
|
|
|
|
|
{ /*10*/"⡀", /*11*/"⣀", /*12*/"⣠", /*13*/"⣰", /*14*/ "⣸" },
|
|
|
|
|
{ /*20*/"⡄", /*21*/"⣄", /*22*/"⣤", /*23*/"⣴", /*24*/ "⣼" },
|
|
|
|
|
{ /*30*/"⡆", /*31*/"⣆", /*32*/"⣦", /*33*/"⣶", /*34*/ "⣾" },
|
|
|
|
|
{ /*40*/"⡇", /*41*/"⣇", /*42*/"⣧", /*43*/"⣷", /*44*/ "⣿" },
|
|
|
|
|
};
|
2006-04-10 20:40:38 +00:00
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
|
static const char* GraphMeterMode_dotsAscii[5][5] = {
|
|
|
|
|
{ /*00*/" ", /*01*/".", /*02*/".", /*03*/":", /*04*/ ":" },
|
|
|
|
|
{ /*10*/"⡀", /*11*/".", /*12*/".", /*13*/":", /*14*/ ":" },
|
|
|
|
|
{ /*20*/".", /*21*/".", /*22*/".", /*23*/":", /*24*/ ":" },
|
|
|
|
|
{ /*30*/":", /*31*/":", /*32*/":", /*33*/":", /*34*/ ":" },
|
|
|
|
|
{ /*40*/":", /*41*/":", /*42*/":", /*43*/":", /*44*/ ":" },
|
2006-04-10 20:40:38 +00:00
|
|
|
|
};
|
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
|
static const char* (*GraphMeterMode_dots)[5];
|
2006-04-10 20:40:38 +00:00
|
|
|
|
|
2008-03-09 08:58:38 +00:00
|
|
|
|
static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
|
2006-04-10 20:40:38 +00:00
|
|
|
|
|
2014-01-16 20:51:16 +00:00
|
|
|
|
if (!this->drawData) this->drawData = calloc(1, sizeof(GraphData));
|
2015-01-22 01:27:31 +00:00
|
|
|
|
GraphData* data = (GraphData*) this->drawData;
|
2011-03-22 20:37:08 +00:00
|
|
|
|
const int nValues = METER_BUFFER_LEN;
|
2015-01-22 01:27:31 +00:00
|
|
|
|
|
|
|
|
|
if (CRT_utf8) {
|
|
|
|
|
GraphMeterMode_dots = GraphMeterMode_dotsUtf8;
|
|
|
|
|
} else {
|
|
|
|
|
GraphMeterMode_dots = GraphMeterMode_dotsAscii;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
attrset(CRT_colors[METER_TEXT]);
|
|
|
|
|
int captionLen = 3;
|
|
|
|
|
mvaddnstr(y, x, this->caption, captionLen);
|
|
|
|
|
x += captionLen;
|
|
|
|
|
w -= captionLen;
|
2011-03-22 20:37:08 +00:00
|
|
|
|
|
2012-12-05 15:12:20 +00:00
|
|
|
|
struct timeval now;
|
|
|
|
|
gettimeofday(&now, NULL);
|
|
|
|
|
if (!timercmp(&now, &(data->time), <)) {
|
2015-01-23 05:08:21 +00:00
|
|
|
|
struct timeval delay = { .tv_sec = (int)(GRAPH_DELAY/10), .tv_usec = (GRAPH_DELAY-((int)(GRAPH_DELAY/10)*10)) * 100000 };
|
2012-12-05 15:12:20 +00:00
|
|
|
|
timeradd(&now, &delay, &(data->time));
|
2006-04-10 20:40:38 +00:00
|
|
|
|
|
2011-03-22 20:37:08 +00:00
|
|
|
|
for (int i = 0; i < nValues - 1; i++)
|
|
|
|
|
data->values[i] = data->values[i+1];
|
|
|
|
|
|
|
|
|
|
char buffer[nValues];
|
2012-12-05 15:12:20 +00:00
|
|
|
|
Meter_setValues(this, buffer, nValues - 1);
|
2011-03-22 20:37:08 +00:00
|
|
|
|
|
|
|
|
|
double value = 0.0;
|
2012-12-05 15:12:20 +00:00
|
|
|
|
int items = Meter_getItems(this);
|
|
|
|
|
for (int i = 0; i < items; i++)
|
2011-03-22 20:37:08 +00:00
|
|
|
|
value += this->values[i];
|
|
|
|
|
value /= this->total;
|
|
|
|
|
data->values[nValues - 1] = value;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
|
for (int i = nValues - (w*2) + 2, k = 0; i < nValues; i+=2, k++) {
|
|
|
|
|
const double dot = (1.0 / 16);
|
|
|
|
|
int v1 = data->values[i] / dot;
|
|
|
|
|
int v2 = data->values[i+1] / dot;
|
2006-04-10 20:40:38 +00:00
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
|
if (v1 == 0) v1 = 1;
|
|
|
|
|
if (v2 == 0) v2 = 1;
|
|
|
|
|
|
|
|
|
|
int level = 12;
|
|
|
|
|
int colorIdx = GRAPH_1;
|
|
|
|
|
for (int line = 0; line < 4; line++) {
|
|
|
|
|
|
|
|
|
|
int line1 = MIN(4, MAX(0, v1 - level));
|
|
|
|
|
int line2 = MIN(4, MAX(0, v2 - level));
|
|
|
|
|
|
|
|
|
|
attrset(CRT_colors[colorIdx]);
|
|
|
|
|
mvaddstr(y+line, x+k, GraphMeterMode_dots[line1][line2]);
|
|
|
|
|
colorIdx = GRAPH_2;
|
|
|
|
|
level -= 4;
|
|
|
|
|
}
|
2006-04-10 20:40:38 +00:00
|
|
|
|
}
|
2006-03-04 18:16:49 +00:00
|
|
|
|
attrset(CRT_colors[RESET_COLOR]);
|
|
|
|
|
}
|
|
|
|
|
|
2006-04-10 20:40:38 +00:00
|
|
|
|
/* ---------- LEDMeterMode ---------- */
|
|
|
|
|
|
2012-12-05 15:12:20 +00:00
|
|
|
|
static const char* LEDMeterMode_digitsAscii[3][10] = {
|
2006-04-10 20:40:38 +00:00
|
|
|
|
{ " __ "," "," __ "," __ "," "," __ "," __ "," __ "," __ "," __ "},
|
|
|
|
|
{ "| |"," |"," __|"," __|","|__|","|__ ","|__ "," |","|__|","|__|"},
|
|
|
|
|
{ "|__|"," |","|__ "," __|"," |"," __|","|__|"," |","|__|"," __|"},
|
|
|
|
|
};
|
2006-03-04 18:16:49 +00:00
|
|
|
|
|
2012-12-05 15:12:20 +00:00
|
|
|
|
static const char* LEDMeterMode_digitsUtf8[3][10] = {
|
|
|
|
|
{ "┌──┐"," ┐ ","╶──┐","╶──┐","╷ ╷","┌──╴","┌──╴","╶──┐","┌──┐","┌──┐"},
|
|
|
|
|
{ "│ │"," │ ","┌──┘"," ──┤","└──┤","└──┐","├──┐"," │","├──┤","└──┤"},
|
|
|
|
|
{ "└──┘"," ╵ ","└──╴","╶──┘"," ╵","╶──┘","└──┘"," ╵","└──┘"," ──┘"},
|
|
|
|
|
};
|
|
|
|
|
|
2015-01-22 01:27:31 +00:00
|
|
|
|
static const char* (*LEDMeterMode_digits)[10];
|
|
|
|
|
|
2006-04-10 20:40:38 +00:00
|
|
|
|
static void LEDMeterMode_drawDigit(int x, int y, int n) {
|
2015-01-22 01:27:31 +00:00
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
mvaddstr(y+i, x, LEDMeterMode_digits[i][n]);
|
2006-04-10 20:40:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-03-09 08:58:38 +00:00
|
|
|
|
static void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
|
2010-02-25 01:43:18 +00:00
|
|
|
|
(void) w;
|
2015-01-22 01:27:31 +00:00
|
|
|
|
|
|
|
|
|
if (CRT_utf8) {
|
|
|
|
|
LEDMeterMode_digits = LEDMeterMode_digitsUtf8;
|
|
|
|
|
} else {
|
|
|
|
|
LEDMeterMode_digits = LEDMeterMode_digitsAscii;
|
|
|
|
|
}
|
|
|
|
|
|
2006-04-10 20:40:38 +00:00
|
|
|
|
char buffer[METER_BUFFER_LEN];
|
2012-12-05 15:12:20 +00:00
|
|
|
|
Meter_setValues(this, buffer, METER_BUFFER_LEN - 1);
|
2010-11-22 12:40:20 +00:00
|
|
|
|
|
|
|
|
|
RichString_begin(out);
|
|
|
|
|
Meter_displayBuffer(this, buffer, &out);
|
2006-04-10 20:40:38 +00:00
|
|
|
|
|
2012-12-05 15:12:20 +00:00
|
|
|
|
int yText = CRT_utf8 ? y+1 : y+2;
|
2006-03-04 18:16:49 +00:00
|
|
|
|
attrset(CRT_colors[LED_COLOR]);
|
2012-12-05 15:12:20 +00:00
|
|
|
|
mvaddstr(yText, x, this->caption);
|
2006-03-04 18:16:49 +00:00
|
|
|
|
int xx = x + strlen(this->caption);
|
2010-11-22 12:40:20 +00:00
|
|
|
|
int len = RichString_sizeVal(out);
|
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
|
char c = RichString_getCharVal(out, i);
|
2006-03-04 18:16:49 +00:00
|
|
|
|
if (c >= '0' && c <= '9') {
|
2006-04-10 20:40:38 +00:00
|
|
|
|
LEDMeterMode_drawDigit(xx, y, c-48);
|
|
|
|
|
xx += 4;
|
2006-03-04 18:16:49 +00:00
|
|
|
|
} else {
|
2012-12-05 15:12:20 +00:00
|
|
|
|
mvaddch(yText, xx, c);
|
2006-03-04 18:16:49 +00:00
|
|
|
|
xx += 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
attrset(CRT_colors[RESET_COLOR]);
|
2010-11-22 12:40:20 +00:00
|
|
|
|
RichString_end(out);
|
2006-03-04 18:16:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-03-09 08:58:38 +00:00
|
|
|
|
static MeterMode BarMeterMode = {
|
|
|
|
|
.uiName = "Bar",
|
|
|
|
|
.h = 1,
|
|
|
|
|
.draw = BarMeterMode_draw,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static MeterMode TextMeterMode = {
|
|
|
|
|
.uiName = "Text",
|
|
|
|
|
.h = 1,
|
|
|
|
|
.draw = TextMeterMode_draw,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static MeterMode GraphMeterMode = {
|
|
|
|
|
.uiName = "Graph",
|
2015-01-22 01:27:31 +00:00
|
|
|
|
.h = 4,
|
2008-03-09 08:58:38 +00:00
|
|
|
|
.draw = GraphMeterMode_draw,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static MeterMode LEDMeterMode = {
|
|
|
|
|
.uiName = "LED",
|
|
|
|
|
.h = 3,
|
|
|
|
|
.draw = LEDMeterMode_draw,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
MeterMode* Meter_modes[] = {
|
|
|
|
|
NULL,
|
|
|
|
|
&BarMeterMode,
|
|
|
|
|
&TextMeterMode,
|
|
|
|
|
&GraphMeterMode,
|
|
|
|
|
&LEDMeterMode,
|
|
|
|
|
NULL
|
|
|
|
|
};
|
2014-02-27 19:35:22 +00:00
|
|
|
|
|
|
|
|
|
/* Blank meter */
|
|
|
|
|
|
|
|
|
|
static void BlankMeter_setValues(Meter* this, char* buffer, int size) {
|
|
|
|
|
(void) this; (void) buffer; (void) size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void BlankMeter_display(Object* cast, RichString* out) {
|
|
|
|
|
(void) cast;
|
|
|
|
|
RichString_prune(out);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int BlankMeter_attributes[] = {
|
|
|
|
|
DEFAULT_COLOR
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
MeterClass BlankMeter_class = {
|
|
|
|
|
.super = {
|
|
|
|
|
.extends = Class(Meter),
|
|
|
|
|
.delete = Meter_delete,
|
|
|
|
|
.display = BlankMeter_display,
|
|
|
|
|
},
|
|
|
|
|
.setValues = BlankMeter_setValues,
|
|
|
|
|
.defaultMode = TEXT_METERMODE,
|
|
|
|
|
.total = 100.0,
|
|
|
|
|
.attributes = BlankMeter_attributes,
|
|
|
|
|
.name = "Blank",
|
|
|
|
|
.uiName = "Blank",
|
|
|
|
|
.caption = ""
|
|
|
|
|
};
|