Meter.c 14.3 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1
2
/*
htop - Meter.c
Hisham Muhammad's avatar
Hisham Muhammad committed
3
(C) 2004-2011 Hisham H. Muhammad
Hisham Muhammad's avatar
Hisham Muhammad committed
4
5
6
7
8
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/

#include "Meter.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
9
10

#include "RichString.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
11
12
#include "Object.h"
#include "CRT.h"
David Hunt's avatar
David Hunt committed
13
#include "StringUtils.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
14
#include "ListItem.h"
15
#include "Settings.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
16
17
18
19
20

#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
21
#include <assert.h>
22
#include <sys/time.h>
23

Hisham Muhammad's avatar
Hisham Muhammad committed
24
#define METER_BUFFER_LEN 256
Hisham Muhammad's avatar
Hisham Muhammad committed
25

26
27
#define GRAPH_DELAY (DEFAULT_DELAY/2)

Hisham Muhammad's avatar
Hisham Muhammad committed
28
/*{
Hisham Muhammad's avatar
Hisham Muhammad committed
29
#include "ListItem.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
30
31

#include <sys/time.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
32
33
34

typedef struct Meter_ Meter;

35
36
37
typedef void(*Meter_Init)(Meter*);
typedef void(*Meter_Done)(Meter*);
typedef void(*Meter_UpdateMode)(Meter*, int);
38
typedef void(*Meter_SetValues)(Meter*, char*, int);
Hisham Muhammad's avatar
Hisham Muhammad committed
39
40
typedef void(*Meter_Draw)(Meter*, int, int, int);

41
42
43
44
45
46
47
48
49
50
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;
Hisham Muhammad's avatar
Hisham Muhammad committed
51
52
53
   const char* name;
   const char* uiName;
   const char* caption;
54
   const char* description;
55
56
   const char maxItems;
   char curItems;
57
58
59
60
61
62
63
64
65
66
67
68
} 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
69
70
#define Meter_getItems(this_)          As_Meter(this_)->curItems
#define Meter_setItems(this_, n_)      As_Meter(this_)->curItems = (n_)
71
72
73
#define Meter_attributes(this_)        As_Meter(this_)->attributes
#define Meter_name(this_)              As_Meter(this_)->name
#define Meter_uiName(this_)            As_Meter(this_)->uiName
74
75
76

struct Meter_ {
   Object super;
77
78
   Meter_Draw draw;
   
79
80
81
   char* caption;
   int mode;
   int param;
82
   void* drawData;
83
   int h;
Hisham Muhammad's avatar
Hisham Muhammad committed
84
   struct ProcessList_* pl;
Hisham Muhammad's avatar
Hisham Muhammad committed
85
86
87
88
   double* values;
   double total;
};

89
90
91
92
93
typedef struct MeterMode_ {
   Meter_Draw draw;
   const char* uiName;
   int h;
} MeterMode;
94

95
96
97
98
99
100
101
102
103
typedef enum {
   CUSTOM_METERMODE = 0,
   BAR_METERMODE,
   TEXT_METERMODE,
   GRAPH_METERMODE,
   LED_METERMODE,
   LAST_METERMODE
} MeterModeId;

104
105
106
107
108
typedef struct GraphData_ {
   struct timeval time;
   double values[METER_BUFFER_LEN];
} GraphData;

Hisham Muhammad's avatar
Hisham Muhammad committed
109
110
111
112
113
}*/

#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
Hisham Muhammad's avatar
Hisham Muhammad committed
114
115
116
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
Hisham Muhammad's avatar
Hisham Muhammad committed
117

118
119
120
121
122
MeterClass Meter_class = {
   .super = {
      .extends = Class(Object)
   }
};
Hisham Muhammad's avatar
Hisham Muhammad committed
123

Hisham Muhammad's avatar
Hisham Muhammad committed
124
Meter* Meter_new(struct ProcessList_* pl, int param, MeterClass* type) {
125
   Meter* this = calloc(1, sizeof(Meter));
126
   Object_setClass(this, type);
127
128
129
   this->h = 1;
   this->param = param;
   this->pl = pl;
130
131
132
133
134
135
   char maxItems = type->maxItems;
   if (maxItems == 0) {
      maxItems = 1;
   }
   type->curItems = maxItems;
   this->values = calloc(maxItems, sizeof(double));
136
137
   this->total = type->total;
   this->caption = strdup(type->caption);
138
139
140
   if (Meter_initFn(this))
      Meter_init(this);
   Meter_setMode(this, type->defaultMode);
141
   return this;
Hisham Muhammad's avatar
Hisham Muhammad committed
142
143
}

Christian Hesse's avatar
Christian Hesse committed
144
int Meter_humanUnit(char* buffer, unsigned long int value, int size) {
Hisham Muhammad's avatar
Hisham Muhammad committed
145
146
147
   const char * prefix = "KMGTPEZY";
   unsigned long int powi = 1;
   unsigned int written, powj = 1, precision = 2;
Christian Hesse's avatar
Christian Hesse committed
148

Hisham Muhammad's avatar
Hisham Muhammad committed
149
150
151
   for(;;) {
      if (value / 1024 < powi)
         break;
Christian Hesse's avatar
Christian Hesse committed
152

Hisham Muhammad's avatar
Hisham Muhammad committed
153
154
      if (prefix[1] == 0)
         break;
Christian Hesse's avatar
Christian Hesse committed
155

Hisham Muhammad's avatar
Hisham Muhammad committed
156
157
158
      powi *= 1024;
      ++prefix;
   }
Christian Hesse's avatar
Christian Hesse committed
159

160
161
162
   if (*prefix == 'K')
      precision = 0;

Hisham Muhammad's avatar
Hisham Muhammad committed
163
164
165
166
167
   for (; precision > 0; precision--) {
      powj *= 10;
      if (value / powi < powj)
         break;
   }
Christian Hesse's avatar
Christian Hesse committed
168

Hisham Muhammad's avatar
Hisham Muhammad committed
169
170
   written = snprintf(buffer, size, "%.*f%c",
      precision, (double) value / powi, *prefix);
Christian Hesse's avatar
Christian Hesse committed
171

Hisham Muhammad's avatar
Hisham Muhammad committed
172
   return written;
Christian Hesse's avatar
Christian Hesse committed
173
174
}

Hisham Muhammad's avatar
Hisham Muhammad committed
175
void Meter_delete(Object* cast) {
176
177
   if (!cast)
      return;
Hisham Muhammad's avatar
Hisham Muhammad committed
178
   Meter* this = (Meter*) cast;
179
180
   if (Meter_doneFn(this)) {
      Meter_done(this);
181
   }
182
183
   if (this->drawData)
      free(this->drawData);
184
185
   free(this->caption);
   free(this->values);
Hisham Muhammad's avatar
Hisham Muhammad committed
186
187
188
   free(this);
}

Hisham Muhammad's avatar
Hisham Muhammad committed
189
void Meter_setCaption(Meter* this, const char* caption) {
190
191
192
193
   free(this->caption);
   this->caption = strdup(caption);
}

194
static inline void Meter_displayBuffer(Meter* this, char* buffer, RichString* out) {
195
196
   if (Object_displayFn(this)) {
      Object_display(this, out);
197
   } else {
198
      RichString_write(out, CRT_colors[Meter_attributes(this)[0]], buffer);
Hisham Muhammad's avatar
Hisham Muhammad committed
199
   }
200
201
202
}

void Meter_setMode(Meter* this, int modeIndex) {
Hisham Muhammad's avatar
Hisham Muhammad committed
203
   if (modeIndex > 0 && modeIndex == this->mode)
204
205
206
207
      return;
   if (!modeIndex)
      modeIndex = 1;
   assert(modeIndex < LAST_METERMODE);
208
209
210
211
   if (Meter_defaultMode(this) == CUSTOM_METERMODE) {
      this->draw = Meter_drawFn(this);
      if (Meter_updateModeFn(this))
         Meter_updateMode(this, modeIndex);
212
   } else {
Hisham Muhammad's avatar
Hisham Muhammad committed
213
      assert(modeIndex >= 1);
214
215
216
      if (this->drawData)
         free(this->drawData);
      this->drawData = NULL;
Hisham Muhammad's avatar
Hisham Muhammad committed
217
218
219
220

      MeterMode* mode = Meter_modes[modeIndex];
      this->draw = mode->draw;
      this->h = mode->h;
Hisham Muhammad's avatar
Hisham Muhammad committed
221
   }
222
   this->mode = modeIndex;
Hisham Muhammad's avatar
Hisham Muhammad committed
223
224
}

225
ListItem* Meter_toListItem(Meter* this, bool moving) {
226
227
228
229
230
231
232
233
234
235
236
   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];
237
   snprintf(buffer, 50, "%s%s%s", Meter_uiName(this), number, mode);
238
239
240
   ListItem* li = ListItem_new(buffer, 0);
   li->moving = moving;
   return li;
Hisham Muhammad's avatar
Hisham Muhammad committed
241
242
}

243
244
/* ---------- TextMeterMode ---------- */

245
static void TextMeterMode_draw(Meter* this, int x, int y, int w) {
246
   char buffer[METER_BUFFER_LEN];
247
   Meter_setValues(this, buffer, METER_BUFFER_LEN - 1);
Hisham Muhammad's avatar
Hisham Muhammad committed
248
   (void) w;
249
250
251
252
253
254

   attrset(CRT_colors[METER_TEXT]);
   mvaddstr(y, x, this->caption);
   int captionLen = strlen(this->caption);
   x += captionLen;
   attrset(CRT_colors[RESET_COLOR]);
255
256
257
258
   RichString_begin(out);
   Meter_displayBuffer(this, buffer, &out);
   RichString_printVal(out, y, x);
   RichString_end(out);
259
260
261
262
}

/* ---------- BarMeterMode ---------- */

263
static char BarMeterMode_characters[] = "|#*@$%&.";
264

265
static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
266
   char buffer[METER_BUFFER_LEN];
267
   Meter_setValues(this, buffer, METER_BUFFER_LEN - 1);
268

Hisham Muhammad's avatar
Hisham Muhammad committed
269
270
   w -= 2;
   attrset(CRT_colors[METER_TEXT]);
Hisham Muhammad's avatar
Hisham Muhammad committed
271
272
   int captionLen = 3;
   mvaddnstr(y, x, this->caption, captionLen);
Hisham Muhammad's avatar
Hisham Muhammad committed
273
274
275
276
277
278
279
280
   x += captionLen;
   w -= captionLen;
   attrset(CRT_colors[BAR_BORDER]);
   mvaddch(y, x, '[');
   mvaddch(y, x + w, ']');
   
   w--;
   x++;
281
282
283
284
285
286

   if (w < 1) {
      attrset(CRT_colors[RESET_COLOR]);
      return;
   }
   char bar[w + 1];
Hisham Muhammad's avatar
Hisham Muhammad committed
287
288
289
290
291
   
   int blockSizes[10];
   for (int i = 0; i < w; i++)
      bar[i] = ' ';

292
   const size_t barOffset = w - MIN((int)strlen(buffer), w);
293
   snprintf(bar + barOffset, w - barOffset + 1, "%s", buffer);
Hisham Muhammad's avatar
Hisham Muhammad committed
294
295
296

   // First draw in the bar[] buffer...
   int offset = 0;
297
298
   int items = Meter_getItems(this);
   for (int i = 0; i < items; i++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
299
      double value = this->values[i];
300
301
      value = MAX(value, 0);
      value = MIN(value, this->total);
Hisham Muhammad's avatar
Hisham Muhammad committed
302
303
304
305
306
307
308
      if (value > 0) {
         blockSizes[i] = ceil((value/this->total) * w);
      } else {
         blockSizes[i] = 0;
      }
      int nextOffset = offset + blockSizes[i];
      // (Control against invalid values)
309
      nextOffset = MIN(MAX(nextOffset, 0), w);
Hisham Muhammad's avatar
Hisham Muhammad committed
310
311
312
      for (int j = offset; j < nextOffset; j++)
         if (bar[j] == ' ') {
            if (CRT_colorScheme == COLORSCHEME_MONOCHROME) {
313
               bar[j] = BarMeterMode_characters[i];
Hisham Muhammad's avatar
Hisham Muhammad committed
314
315
316
317
318
319
320
321
322
            } else {
               bar[j] = '|';
            }
         }
      offset = nextOffset;
   }

   // ...then print the buffer.
   offset = 0;
323
324
   for (int i = 0; i < items; i++) {
      attrset(CRT_colors[Meter_attributes(this)[i]]);
Hisham Muhammad's avatar
Hisham Muhammad committed
325
326
327
328
329
330
331
332
333
334
335
336
337
338
      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]);
}

339
340
/* ---------- GraphMeterMode ---------- */

341
342
#ifdef HAVE_LIBNCURSESW

Christian Hesse's avatar
Christian Hesse committed
343
344
#define PIXPERROW_UTF8 4
static const char* GraphMeterMode_dotsUtf8[] = {
345
   /*00*/" ", /*01*/"⢀", /*02*/"⢠", /*03*/"⢰", /*04*/ "⢸",
Christian Hesse's avatar
Christian Hesse committed
346
347
348
349
   /*10*/"⡀", /*11*/"⣀", /*12*/"⣠", /*13*/"⣰", /*14*/ "⣸",
   /*20*/"⡄", /*21*/"⣄", /*22*/"⣤", /*23*/"⣴", /*24*/ "⣼",
   /*30*/"⡆", /*31*/"⣆", /*32*/"⣦", /*33*/"⣶", /*34*/ "⣾",
   /*40*/"⡇", /*41*/"⣇", /*42*/"⣧", /*43*/"⣷", /*44*/ "⣿"
Hisham Muhammad's avatar
Hisham Muhammad committed
350
};
351

352
353
#endif

Christian Hesse's avatar
Christian Hesse committed
354
355
356
357
358
#define PIXPERROW_ASCII 2
static const char* GraphMeterMode_dotsAscii[] = {
   /*00*/" ", /*01*/".", /*02*/":",
   /*10*/".", /*11*/".", /*12*/":",
   /*20*/":", /*21*/":", /*22*/":"
359
360
};

Christian Hesse's avatar
Christian Hesse committed
361
static const char** GraphMeterMode_dots;
Hisham Muhammad's avatar
Hisham Muhammad committed
362
static int GraphMeterMode_pixPerRow;
363

364
static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
365

366
   if (!this->drawData) this->drawData = calloc(1, sizeof(GraphData));
Hisham Muhammad's avatar
Hisham Muhammad committed
367
    GraphData* data = (GraphData*) this->drawData;
368
   const int nValues = METER_BUFFER_LEN;
Hisham Muhammad's avatar
Hisham Muhammad committed
369

370
#ifdef HAVE_LIBNCURSESW
Hisham Muhammad's avatar
Hisham Muhammad committed
371
372
   if (CRT_utf8) {
      GraphMeterMode_dots = GraphMeterMode_dotsUtf8;
Hisham Muhammad's avatar
Hisham Muhammad committed
373
      GraphMeterMode_pixPerRow = PIXPERROW_UTF8;
374
375
376
   } else
#endif
   {
Hisham Muhammad's avatar
Hisham Muhammad committed
377
      GraphMeterMode_dots = GraphMeterMode_dotsAscii;
Hisham Muhammad's avatar
Hisham Muhammad committed
378
      GraphMeterMode_pixPerRow = PIXPERROW_ASCII;
Hisham Muhammad's avatar
Hisham Muhammad committed
379
380
381
382
383
384
385
   }

   attrset(CRT_colors[METER_TEXT]);
   int captionLen = 3;
   mvaddnstr(y, x, this->caption, captionLen);
   x += captionLen;
   w -= captionLen;
386
   
387
388
389
   struct timeval now;
   gettimeofday(&now, NULL);
   if (!timercmp(&now, &(data->time), <)) {
390
      struct timeval delay = { .tv_sec = (int)(CRT_delay/10), .tv_usec = (CRT_delay-((int)(CRT_delay/10)*10)) * 100000 };
391
      timeradd(&now, &delay, &(data->time));
392

393
394
395
396
      for (int i = 0; i < nValues - 1; i++)
         data->values[i] = data->values[i+1];
   
      char buffer[nValues];
397
      Meter_setValues(this, buffer, nValues - 1);
398
399
   
      double value = 0.0;
400
401
      int items = Meter_getItems(this);
      for (int i = 0; i < items; i++)
402
403
404
405
406
         value += this->values[i];
      value /= this->total;
      data->values[nValues - 1] = value;
   }
   
Hisham Muhammad's avatar
Hisham Muhammad committed
407
   for (int i = nValues - (w*2) + 2, k = 0; i < nValues; i+=2, k++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
408
409
410
      const double dot = (1.0 / (GraphMeterMode_pixPerRow * 4));
      int v1 = MIN(GraphMeterMode_pixPerRow * 4, MAX(1, data->values[i] / dot));
      int v2 = MIN(GraphMeterMode_pixPerRow * 4, MAX(1, data->values[i+1] / dot));
Christian Hesse's avatar
Christian Hesse committed
411

Hisham Muhammad's avatar
Hisham Muhammad committed
412
413
      int colorIdx = GRAPH_1;
      for (int line = 0; line < 4; line++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
414
415
         int line1 = MIN(GraphMeterMode_pixPerRow, MAX(0, v1 - (GraphMeterMode_pixPerRow * (3 - line))));
         int line2 = MIN(GraphMeterMode_pixPerRow, MAX(0, v2 - (GraphMeterMode_pixPerRow * (3 - line))));
Christian Hesse's avatar
Christian Hesse committed
416

Hisham Muhammad's avatar
Hisham Muhammad committed
417
         attrset(CRT_colors[colorIdx]);
Hisham Muhammad's avatar
Hisham Muhammad committed
418
         mvaddstr(y+line, x+k, GraphMeterMode_dots[line1 * (GraphMeterMode_pixPerRow + 1) + line2]);
Hisham Muhammad's avatar
Hisham Muhammad committed
419
420
         colorIdx = GRAPH_2;
      }
421
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
422
423
424
   attrset(CRT_colors[RESET_COLOR]);
}

425
426
/* ---------- LEDMeterMode ---------- */

Christian Hesse's avatar
Christian Hesse committed
427
428
429
430
static const char* LEDMeterMode_digitsAscii[] = {
   " __ ","    "," __ "," __ ","    "," __ "," __ "," __ "," __ "," __ ",
   "|  |","   |"," __|"," __|","|__|","|__ ","|__ ","   |","|__|","|__|",
   "|__|","   |","|__ "," __|","   |"," __|","|__|","   |","|__|"," __|"
431
};
Hisham Muhammad's avatar
Hisham Muhammad committed
432

433
434
#ifdef HAVE_LIBNCURSESW

Christian Hesse's avatar
Christian Hesse committed
435
436
437
438
static const char* LEDMeterMode_digitsUtf8[] = {
   "┌──┐","  ┐ ","╶──┐","╶──┐","╷  ╷","┌──╴","┌──╴","╶──┐","┌──┐","┌──┐",
   "│  │","  │ ","┌──┘"," ──┤","└──┤","└──┐","├──┐","   │","├──┤","└──┤",
   "└──┘","  ╵ ","└──╴","╶──┘","   ╵","╶──┘","└──┘","   ╵","└──┘"," ──┘"
439
440
};

441
442
#endif

Christian Hesse's avatar
Christian Hesse committed
443
static const char** LEDMeterMode_digits;
Hisham Muhammad's avatar
Hisham Muhammad committed
444

445
static void LEDMeterMode_drawDigit(int x, int y, int n) {
Hisham Muhammad's avatar
Hisham Muhammad committed
446
   for (int i = 0; i < 3; i++)
Christian Hesse's avatar
Christian Hesse committed
447
      mvaddstr(y+i, x, LEDMeterMode_digits[i * 10 + n]);
448
449
}

450
static void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
Hisham Muhammad's avatar
Hisham Muhammad committed
451
   (void) w;
Hisham Muhammad's avatar
Hisham Muhammad committed
452

453
454
#ifdef HAVE_LIBNCURSESW
   if (CRT_utf8)
Hisham Muhammad's avatar
Hisham Muhammad committed
455
      LEDMeterMode_digits = LEDMeterMode_digitsUtf8;
456
457
   else
#endif
Hisham Muhammad's avatar
Hisham Muhammad committed
458
459
      LEDMeterMode_digits = LEDMeterMode_digitsAscii;

460
   char buffer[METER_BUFFER_LEN];
461
   Meter_setValues(this, buffer, METER_BUFFER_LEN - 1);
462
463
464
   
   RichString_begin(out);
   Meter_displayBuffer(this, buffer, &out);
465

466
467
   int yText =
#ifdef HAVE_LIBNCURSESW
Hisham Muhammad's avatar
Hisham Muhammad committed
468
      CRT_utf8 ? y+1 :
469
#endif
Hisham Muhammad's avatar
Hisham Muhammad committed
470
      y+2;
Hisham Muhammad's avatar
Hisham Muhammad committed
471
   attrset(CRT_colors[LED_COLOR]);
472
   mvaddstr(yText, x, this->caption);
Hisham Muhammad's avatar
Hisham Muhammad committed
473
   int xx = x + strlen(this->caption);
474
475
476
   int len = RichString_sizeVal(out);
   for (int i = 0; i < len; i++) {
      char c = RichString_getCharVal(out, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
477
      if (c >= '0' && c <= '9') {
478
479
         LEDMeterMode_drawDigit(xx, y, c-48);
         xx += 4;
Hisham Muhammad's avatar
Hisham Muhammad committed
480
      } else {
481
         mvaddch(yText, xx, c);
Hisham Muhammad's avatar
Hisham Muhammad committed
482
483
484
485
         xx += 1;
      }
   }
   attrset(CRT_colors[RESET_COLOR]);
486
   RichString_end(out);
Hisham Muhammad's avatar
Hisham Muhammad committed
487
488
}

489
490
491
492
493
494
495
496
497
498
499
500
501
502
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",
Hisham Muhammad's avatar
Hisham Muhammad committed
503
   .h = 4,
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
   .draw = GraphMeterMode_draw,
};

static MeterMode LEDMeterMode = {
   .uiName = "LED",
   .h = 3,
   .draw = LEDMeterMode_draw,
};

MeterMode* Meter_modes[] = {
   NULL,
   &BarMeterMode,
   &TextMeterMode,
   &GraphMeterMode,
   &LEDMeterMode,
   NULL
};
Hisham Muhammad's avatar
Hisham Muhammad committed
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550

/* 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 = ""
};