+ Knob: test implementation of drawing using pixmaps and not pixbufs
[calf.git] / src / giface.cpp
blob1945326d0cd539dbc2861998acd4b7058ac6df93
1 /* Calf DSP Library
2 * Module wrapper methods.
4 * Copyright (C) 2001-2007 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307, USA.
21 #include <config.h>
22 #include <assert.h>
23 #include <memory.h>
24 #include <calf/giface.h>
25 #include <calf/osctlnet.h>
27 using namespace std;
28 using namespace calf_utils;
29 using namespace calf_plugins;
31 float parameter_properties::from_01(double value01) const
33 double value = dsp::clip(value01, 0., 1.);
34 switch(flags & PF_SCALEMASK)
36 case PF_SCALE_DEFAULT:
37 case PF_SCALE_LINEAR:
38 case PF_SCALE_PERC:
39 default:
40 value = min + (max - min) * value01;
41 break;
42 case PF_SCALE_QUAD:
43 value = min + (max - min) * value01 * value01;
44 break;
45 case PF_SCALE_LOG:
46 value = min * pow(double(max / min), value01);
47 break;
48 case PF_SCALE_GAIN:
49 if (value01 < 0.00001)
50 value = min;
51 else {
52 float rmin = std::max(1.0f / 1024.0f, min);
53 value = rmin * pow(double(max / rmin), value01);
55 break;
56 case PF_SCALE_LOG_INF:
57 assert(step);
58 if (value01 > (step - 1.0) / step)
59 value = FAKE_INFINITY;
60 else
61 value = min * pow(double(max / min), value01 * step / (step - 1.0));
62 break;
64 switch(flags & PF_TYPEMASK)
66 case PF_INT:
67 case PF_BOOL:
68 case PF_ENUM:
69 case PF_ENUM_MULTI:
70 if (value > 0)
71 value = (int)(value + 0.5);
72 else
73 value = (int)(value - 0.5);
74 break;
76 return value;
79 double parameter_properties::to_01(float value) const
81 switch(flags & PF_SCALEMASK)
83 case PF_SCALE_DEFAULT:
84 case PF_SCALE_LINEAR:
85 case PF_SCALE_PERC:
86 default:
87 return double(value - min) / (max - min);
88 case PF_SCALE_QUAD:
89 return sqrt(double(value - min) / (max - min));
90 case PF_SCALE_LOG:
91 value /= min;
92 return log((double)value) / log((double)max / min);
93 case PF_SCALE_LOG_INF:
94 if (IS_FAKE_INFINITY(value))
95 return max;
96 value /= min;
97 assert(step);
98 return (step - 1.0) * log((double)value) / (step * log((double)max / min));
99 case PF_SCALE_GAIN:
100 if (value < 1.0 / 1024.0) // new bottom limit - 60 dB
101 return 0;
102 double rmin = std::max(1.0f / 1024.0f, min);
103 value /= rmin;
104 return log((double)value) / log(max / rmin);
108 float parameter_properties::get_increment() const
110 float increment = 0.01;
111 if (step > 1)
112 increment = 1.0 / (step - 1);
113 else
114 if (step > 0 && step < 1)
115 increment = step;
116 else
117 if ((flags & PF_TYPEMASK) != PF_FLOAT)
118 increment = 1.0 / (max - min);
119 return increment;
122 int parameter_properties::get_char_count() const
124 if ((flags & PF_SCALEMASK) == PF_SCALE_PERC)
125 return 6;
126 if ((flags & PF_SCALEMASK) == PF_SCALE_GAIN) {
127 char buf[256];
128 size_t len = 0;
129 sprintf(buf, "%0.0f dB", 6.0 * log(min) / log(2));
130 len = strlen(buf);
131 sprintf(buf, "%0.0f dB", 6.0 * log(max) / log(2));
132 len = std::max(len, strlen(buf)) + 2;
133 return (int)len;
135 return std::max(to_string(min).length(), std::max(to_string(max).length(), to_string(min + (max-min) * 0.987654).length()));
138 std::string parameter_properties::to_string(float value) const
140 char buf[32];
141 if ((flags & PF_SCALEMASK) == PF_SCALE_PERC) {
142 sprintf(buf, "%0.f%%", 100.0 * value);
143 return string(buf);
145 if ((flags & PF_SCALEMASK) == PF_SCALE_GAIN) {
146 if (value < 1.0 / 1024.0) // new bottom limit - 60 dB
147 return "-inf dB"; // XXXKF change to utf-8 infinity
148 sprintf(buf, "%0.1f dB", 6.0 * log(value) / log(2));
149 return string(buf);
151 switch(flags & PF_TYPEMASK)
153 case PF_STRING:
154 return "N/A";
155 case PF_INT:
156 case PF_BOOL:
157 case PF_ENUM:
158 case PF_ENUM_MULTI:
159 value = (int)value;
160 break;
163 if ((flags & PF_SCALEMASK) == PF_SCALE_LOG_INF && IS_FAKE_INFINITY(value))
164 sprintf(buf, "+inf"); // XXXKF change to utf-8 infinity
165 else
166 sprintf(buf, "%g", value);
168 switch(flags & PF_UNITMASK) {
169 case PF_UNIT_DB: return string(buf) + " dB";
170 case PF_UNIT_HZ: return string(buf) + " Hz";
171 case PF_UNIT_SEC: return string(buf) + " s";
172 case PF_UNIT_MSEC: return string(buf) + " ms";
173 case PF_UNIT_CENTS: return string(buf) + " ct";
174 case PF_UNIT_SEMITONES: return string(buf) + "#";
175 case PF_UNIT_BPM: return string(buf) + " bpm";
176 case PF_UNIT_RPM: return string(buf) + " rpm";
177 case PF_UNIT_DEG: return string(buf) + " deg";
178 case PF_UNIT_NOTE:
180 static const char *notes = "C C#D D#E F F#G G#A A#B ";
181 int note = (int)value;
182 if (note < 0 || note > 127)
183 return "---";
184 return string(notes + 2 * (note % 12), 2) + i2s(note / 12 - 2);
188 return string(buf);
191 void calf_plugins::plugin_ctl_iface::clear_preset() {
192 int param_count = get_param_count();
193 for (int i=0; i < param_count; i++)
195 parameter_properties &pp = *get_param_props(i);
196 if ((pp.flags & PF_TYPEMASK) == PF_STRING)
198 configure(pp.short_name, pp.choices ? pp.choices[0] : "");
200 else
201 set_param_value(i, pp.def_value);
205 const char *calf_plugins::load_gui_xml(const std::string &plugin_id)
207 try {
208 return strdup(calf_utils::load_file((std::string(PKGLIBDIR) + "/gui-" + plugin_id + ".xml").c_str()).c_str());
210 catch(file_exception e)
212 return NULL;
216 bool calf_plugins::check_for_message_context_ports(parameter_properties *parameters, int count)
218 for (int i = count - 1; i >= 0; i--)
220 if (parameters[i].flags & PF_PROP_MSGCONTEXT)
221 return true;
223 return false;
226 bool calf_plugins::check_for_string_ports(parameter_properties *parameters, int count)
228 for (int i = count - 1; i >= 0; i--)
230 if ((parameters[i].flags & PF_TYPEMASK) == PF_STRING)
231 return true;
232 if ((parameters[i].flags & PF_TYPEMASK) < PF_STRING)
233 return false;
235 return false;
238 #if USE_DSSI
239 struct osc_cairo_control: public cairo_iface
241 osctl::osc_inline_typed_strstream &os;
243 osc_cairo_control(osctl::osc_inline_typed_strstream &_os) : os(_os) {}
244 virtual void set_source_rgba(float r, float g, float b, float a = 1.f)
246 os << (uint32_t)LGI_SET_RGBA << r << g << b << a;
248 virtual void set_line_width(float width)
250 os << (uint32_t)LGI_SET_WIDTH << width;
254 static void send_graph_via_osc(osctl::osc_client &client, const std::string &address, line_graph_iface *graph, std::vector<int> &params)
256 osctl::osc_inline_typed_strstream os;
257 osc_cairo_control cairoctl(os);
258 for (size_t i = 0; i < params.size(); i++)
260 int index = params[i];
261 os << (uint32_t)LGI_GRAPH;
262 os << (uint32_t)index;
263 for (int j = 0; ; j++)
265 float data[128];
266 if (graph->get_graph(index, j, data, 128, &cairoctl))
268 os << (uint32_t)LGI_SUBGRAPH;
269 os << (uint32_t)128;
270 for (int p = 0; p < 128; p++)
271 os << data[p];
273 else
274 break;
276 for (int j = 0; ; j++)
278 float x, y;
279 int size = 3;
280 if (graph->get_dot(index, j, x, y, size, &cairoctl))
281 os << (uint32_t)LGI_DOT << x << y << (uint32_t)size;
282 else
283 break;
285 for (int j = 0; ; j++)
287 float pos = 0;
288 bool vertical = false;
289 string legend;
290 if (graph->get_gridline(index, j, pos, vertical, legend, &cairoctl))
291 os << (uint32_t)LGI_LEGEND << pos << (uint32_t)(vertical ? 1 : 0) << legend;
292 else
293 break;
295 os << (uint32_t)LGI_END_ITEM;
297 os << (uint32_t)LGI_END;
298 client.send(address, os);
301 calf_plugins::dssi_feedback_sender::dssi_feedback_sender(const char *URI, line_graph_iface *_graph, calf_plugins::parameter_properties *props, int num_params)
303 graph = _graph;
304 client = new osctl::osc_client;
305 client->bind("0.0.0.0", 0);
306 client->set_url(URI);
307 for (int i = 0; i < num_params; i++)
309 if (props[i].flags & PF_PROP_GRAPH)
310 indices.push_back(i);
314 void calf_plugins::dssi_feedback_sender::update()
316 send_graph_via_osc(*client, "/lineGraph", graph, indices);
319 calf_plugins::dssi_feedback_sender::~dssi_feedback_sender()
321 // this would not be received by GUI's main loop because it's already been terminated
322 // client->send("/iQuit");
323 delete client;
325 #endif