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

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

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

Hisham Muhammad's avatar
Hisham Muhammad committed
169
   return written;
Christian Hesse's avatar
Christian Hesse committed
170
171
}

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

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

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

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

      MeterMode* mode = Meter_modes[modeIndex];
      this->draw = mode->draw;
      this->h = mode->h;
Hisham Muhammad's avatar
Hisham Muhammad committed
218
   }
219
   this->mode = modeIndex;
Hisham Muhammad's avatar
Hisham Muhammad committed
220
221
}

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

240
241
/* ---------- TextMeterMode ---------- */

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

   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]);
253
254
255
256
   RichString_begin(out);
   Meter_displayBuffer(this, buffer, &out);
   RichString_printVal(out, y, x);
   RichString_end(out);
257
258
259
260
}

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

261
static char BarMeterMode_characters[] = "|#*@$%&";
262

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

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

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

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

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

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

337
338
/* ---------- GraphMeterMode ---------- */

339
340
#ifdef HAVE_LIBNCURSESW

Christian Hesse's avatar
Christian Hesse committed
341
342
#define PIXPERROW_UTF8 4
static const char* GraphMeterMode_dotsUtf8[] = {
343
   /*00*/" ", /*01*/"⢀", /*02*/"⢠", /*03*/"⢰", /*04*/ "⢸",
Christian Hesse's avatar
Christian Hesse committed
344
345
346
347
   /*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
348
};
349

350
351
#endif

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

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

362
static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
363

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

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

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

391
392
393
394
      for (int i = 0; i < nValues - 1; i++)
         data->values[i] = data->values[i+1];
   
      char buffer[nValues];
395
      Meter_setValues(this, buffer, nValues - 1);
396
397
   
      double value = 0.0;
398
399
      int items = Meter_getItems(this);
      for (int i = 0; i < items; i++)
400
401
402
403
404
         value += this->values[i];
      value /= this->total;
      data->values[nValues - 1] = value;
   }
   
Hisham Muhammad's avatar
Hisham Muhammad committed
405
   for (int i = nValues - (w*2) + 2, k = 0; i < nValues; i+=2, k++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
406
407
408
      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
409

Hisham Muhammad's avatar
Hisham Muhammad committed
410
411
      int colorIdx = GRAPH_1;
      for (int line = 0; line < 4; line++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
412
413
         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
414

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

423
424
/* ---------- LEDMeterMode ---------- */

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

431
432
#ifdef HAVE_LIBNCURSESW

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

439
440
#endif

Christian Hesse's avatar
Christian Hesse committed
441
static const char** LEDMeterMode_digits;
Hisham Muhammad's avatar
Hisham Muhammad committed
442

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

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

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

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

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

487
488
489
490
491
492
493
494
495
496
497
498
499
500
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
501
   .h = 4,
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
   .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
519
520
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

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