1 // -----------------------------------------------------------------------------
2 //
3 // Copyright (C) 2006-2018 Fons Adriaensen <fons@linuxaudio.org>
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // -----------------------------------------------------------------------------
19
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include "png2img.h"
25 #include "kmeter.h"
26
27
28 unsigned long Kmeter::_peakcol = 0;
29 XImage *Kmeter::_k20_meterH0 = 0;
30 XImage *Kmeter::_k20_meterH1 = 0;
31 XImage *Kmeter::_k20_meterV0 = 0;
32 XImage *Kmeter::_k20_meterV1 = 0;
33 XImage *Kmeter::_k20_scaleH = 0;
34 XImage *Kmeter::_k20_scaleV = 0;
35 XImage *Kmeter::_k14_meterH0 = 0;
36 XImage *Kmeter::_k14_meterH1 = 0;
37 XImage *Kmeter::_k14_meterV0 = 0;
38 XImage *Kmeter::_k14_meterV1 = 0;
39 XImage *Kmeter::_k14_scaleH = 0;
40 XImage *Kmeter::_k14_scaleV = 0;
41
42
Kmeter(X_window * parent,int xpos,int ypos,int geom,int kval)43 Kmeter::Kmeter (X_window *parent, int xpos, int ypos, int geom, int kval) :
44 X_window (parent, xpos, ypos, LINEW, LINEW, 0),
45 _geom (geom),
46 _kval (kval),
47 _xs (0),
48 _ys (0),
49 _kr (-1),
50 _kp (-1),
51 _dp (0),
52 _pixm (0),
53 _imag0 (0),
54 _imag1 (0)
55 {
56 switch (kval)
57 {
58 case K20:
59 _imag0 = (geom == HOR) ? _k20_meterH0 : _k20_meterV0;
60 _imag1 = (geom == HOR) ? _k20_meterH1 : _k20_meterV1;
61 break;
62 case K14:
63 _imag0 = (geom == HOR) ? _k14_meterH0 : _k14_meterV0;
64 _imag1 = (geom == HOR) ? _k14_meterH1 : _k14_meterV1;
65 break;
66 default:
67 return;
68 }
69 if (!_imag0 || !_imag1) return;
70
71 _xs = _ys = LINEW;
72 switch (geom)
73 {
74 case HOR:
75 _xs = _imag0->width;
76 break;
77 case VER:
78 _ys = _imag0->height;
79 break;
80 default:
81 return;
82 }
83
84 _pixm = XCreatePixmap (dpy (), win (), _xs, _ys, disp ()->depth ());
85 if (! _pixm) return;
86 XPutImage (dpy (), _pixm, dgc (), _imag0, 0, 0, 0, 0, _xs, _ys);
87 XSetWindowBackgroundPixmap (dpy (), win (), _pixm);
88 x_resize (_xs, _ys);
89 }
90
91
~Kmeter(void)92 Kmeter::~Kmeter (void)
93 {
94 if (_pixm) XFreePixmap (dpy (), _pixm);
95 }
96
97
update(float r,float p)98 void Kmeter::update (float r, float p)
99 {
100 int x, y, kr, kp, dp;
101
102 kr = (_kval == K20) ? mapk20 (r) : mapk14 (r);
103 kp = (_kval == K20) ? mapk20 (p) : mapk14 (p);
104 dp = kp - kr;
105 if (dp > 3) dp = 3;
106 if (kp < 24) dp = 0;
107 XSetForeground (dpy (), dgc (), _peakcol);
108 if (_geom == HOR)
109 {
110 if (_dp > 0)
111 {
112 x = _kp + 11;
113 XPutImage (dpy (), _pixm, dgc (), _imag0, x - _dp, 0, x - _dp, 0, _dp, LINEW);
114 }
115 if (kr > _kr)
116 {
117 x = _kr + 11;
118 XPutImage (dpy (), _pixm, dgc (), _imag1, x, 0, x, 0, kr - _kr, LINEW);
119 }
120 else if (kr < _kr)
121 {
122 x = kr + 11;
123 XPutImage (dpy (), _pixm, dgc (), _imag0, x, 0, x, 0, _kr - kr, LINEW);
124 }
125 if (dp > 0)
126 {
127 x = kp + 11;
128 XFillRectangle (dpy (), _pixm, dgc (), x - dp, 0, dp, LINEW);
129 }
130 }
131 else
132 {
133 if (_dp > 0)
134 {
135 y = _ys - 11- _kp;
136 XPutImage (dpy (), _pixm, dgc (), _imag0, 0, y, 0, y, LINEW, _dp);
137 }
138 if (kr > _kr)
139 {
140 y = _ys - 11 - kr;
141 XPutImage (dpy (), _pixm, dgc (), _imag1, 0, y, 0, y, LINEW, kr - _kr);
142 }
143 else if (kr < _kr)
144 {
145 y = _ys - 11 - _kr;
146 XPutImage (dpy (), _pixm, dgc (), _imag0, 0, y, 0, y, LINEW, _kr - kr);
147 }
148 if (dp > 0)
149 {
150 y = _ys - 11 - kp;
151 XFillRectangle (dpy (), _pixm, dgc (), 0, y, LINEW, dp);
152 }
153 }
154 _kr = kr;
155 _kp = kp;
156 _dp = dp;
157 x_clear ();
158 }
159
160
mapk20(float v)161 int Kmeter::mapk20 (float v)
162 {
163 if (v < 1e-3f) return (int)(24e3f * v);
164 v = log10f (v);
165 if (v < -1.25f) return (int)(468.3f + v * (196 + v * 16));
166 if (v > 0) v = 0;
167 return (int)(448.3f + v * 160.0f);
168 }
169
170
mapk14(float v)171 int Kmeter::mapk14 (float v)
172 {
173 if (v < 2e-3f) return (int)(12e3f * v);
174 v = log10f (v) - 0.3;
175 if (v < -1.25f) return (int)(468.3f + v * (196 + v * 16));
176 if (v > 0) v = 0;
177 return (int)(448.3f + v * 160.0f);
178 }
179
180
load_images(X_display * disp,const char * path)181 int Kmeter::load_images (X_display *disp, const char *path)
182 {
183 char s [1024];
184
185 if (_k20_meterH0 && _k20_meterH1 && _k20_scaleH) return 0;
186 _peakcol = disp->whitepixel ();
187 snprintf (s, 1024, "%s/k20-meterH0.png", path);
188 _k20_meterH0 = png2img (s, disp, 0);
189 snprintf (s, 1024, "%s/k20-meterH1.png", path);
190 _k20_meterH1 = png2img (s, disp, 0);
191 snprintf (s, 1024, "%s/k20-scaleH.png", path);
192 _k20_scaleH = png2img (s, disp, 0);
193 if (_k20_meterH0 && _k20_meterH1 && _k20_scaleH) return 0;
194 return 1;
195 }
196