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