libroot/posix/stdio: Remove unused portions.
[haiku.git] / src / apps / patchbay / MidiEventMeter.cpp
blob893f27dd8c8dd25c02eaa7feec68cd3029314d8b
1 /* MidiEventMeter.cpp
2 * ------------------
3 * Implements the MidiEventMeter class.
5 * Copyright 2013, Haiku, Inc. All rights reserved.
6 * Distributed under the terms of the MIT License.
8 * Revisions by Pete Goodeve
10 * Copyright 1999, Be Incorporated. All Rights Reserved.
11 * This file may be used under the terms of the Be Sample Code License.
14 #include "MidiEventMeter.h"
16 #include <stdio.h>
17 #include <MidiRoster.h>
18 #include <MidiProducer.h>
19 #include <MidiConsumer.h>
20 #include <View.h>
22 #include "CountEventConsumer.h"
24 static const BRect METER_BOUNDS(0, 0, 7, 31);
26 // If we get this number of events per pulse or greater, we will
27 // max out the event meter.
28 // Value was determined empirically based on my banging on a MIDI
29 // keyboard controller with a pulse of 200ms.
30 static const int32 METER_SCALE = 10;
33 MidiEventMeter::MidiEventMeter(int32 producerID)
35 fCounter(NULL),
36 fMeterLevel(0)
38 BMidiRoster* roster = BMidiRoster::MidiRoster();
39 if (roster != NULL) {
40 BMidiProducer* producer = roster->FindProducer(producerID);
41 if (producer != NULL) {
42 BString name;
43 name << producer->Name() << " Event Meter";
44 fCounter = new CountEventConsumer(name.String());
45 producer->Connect(fCounter);
46 producer->Release();
52 MidiEventMeter::~MidiEventMeter()
54 if (fCounter != NULL)
55 fCounter->Release();
59 void
60 MidiEventMeter::Pulse(BView* view)
62 int32 newLevel = fMeterLevel;
63 if (fCounter != NULL) {
64 newLevel = CalcMeterLevel(fCounter->CountEvents());
65 fCounter->Reset();
67 if (newLevel != fMeterLevel) {
68 fMeterLevel = newLevel;
69 view->Invalidate(BRect(METER_BOUNDS).InsetBySelf(1, 1));
74 BRect
75 MidiEventMeter::Bounds() const
77 return METER_BOUNDS;
81 void
82 MidiEventMeter::Draw(BView* view)
84 const rgb_color METER_BLACK = { 0, 0, 0, 255 };
85 const rgb_color METER_GREY = { 180, 180, 180, 255 };
86 const rgb_color METER_GREEN = { 0, 255, 0, 255 };
88 view->PushState();
90 // draw the frame
91 BPoint lt = METER_BOUNDS.LeftTop();
92 BPoint rb = METER_BOUNDS.RightBottom();
93 view->BeginLineArray(4);
94 view->AddLine(BPoint(lt.x, lt.y), BPoint(rb.x - 1, lt.y), METER_BLACK);
95 view->AddLine(BPoint(rb.x, lt.y), BPoint(rb.x, rb.y - 1), METER_BLACK);
96 view->AddLine(BPoint(rb.x, rb.y), BPoint(lt.x + 1, rb.y), METER_BLACK);
97 view->AddLine(BPoint(lt.x, rb.y), BPoint(lt.x, lt.y + 1), METER_BLACK);
98 view->EndLineArray();
100 // draw the cells
101 BRect cell = METER_BOUNDS;
102 cell.InsetBy(1, 1);
103 cell.bottom = cell.top + (cell.Height() + 1) / 5;
104 cell.bottom--;
106 const float kTintArray[] =
107 {B_DARKEN_4_TINT,
108 B_DARKEN_3_TINT,
109 B_DARKEN_2_TINT,
110 B_DARKEN_1_TINT,
111 B_NO_TINT};
113 for (int32 i = 4; i >= 0; i--) {
114 rgb_color color;
115 if (fMeterLevel > i) {
116 color = tint_color(METER_GREEN, kTintArray[i]);
117 } else {
118 color = METER_GREY;
120 view->SetHighColor(color);
121 view->FillRect(cell);
122 cell.OffsetBy(0, cell.Height() + 1);
125 view->PopState();
129 int32
130 MidiEventMeter::CalcMeterLevel(int32 eventCount) const
132 // we use an approximately logarithmic scale for determing the actual
133 // drawn meter level, so that low-density event streams show up well.
134 if (eventCount == 0)
135 return 0;
136 else if (eventCount < (int32)(0.5 * METER_SCALE))
137 return 1;
138 else if (eventCount < (int32)(0.75 * METER_SCALE))
139 return 2;
140 else if (eventCount < (int32)(0.9 * METER_SCALE))
141 return 3;
142 else if (eventCount < METER_SCALE)
143 return 4;
144 return 5;