059dc246ae403f39c0c64a88bf3ef197155091e8
[ardour.git] / gtk2_ardour / ui_config.cc
1 /*
2     Copyright (C) 1999-2014 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <unistd.h>
21 #include <cstdlib>
22 #include <cstdio> /* for snprintf, grrr */
23
24 #include <glibmm/miscutils.h>
25
26 #include "pbd/failed_constructor.h"
27 #include "pbd/xml++.h"
28 #include "pbd/file_utils.h"
29 #include "pbd/error.h"
30
31 #include "gtkmm2ext/rgb_macros.h"
32
33 #include "ardour/filesystem_paths.h"
34
35 #include "ardour_ui.h"
36 #include "global_signals.h"
37 #include "ui_config.h"
38
39 #include "i18n.h"
40
41 using namespace std;
42 using namespace PBD;
43 using namespace ARDOUR;
44 using namespace ArdourCanvas;
45
46 static const char* ui_config_file_name = "ui_config";
47 static const char* default_ui_config_file_name = "default_ui_config";
48 UIConfiguration* UIConfiguration::_instance = 0;
49
50 static const double hue_width = 18.0;
51
52 UIConfiguration::UIConfiguration ()
53         :
54 #undef  UI_CONFIG_VARIABLE
55 #define UI_CONFIG_VARIABLE(Type,var,name,val) var (name,val),
56 #define CANVAS_STRING_VARIABLE(var,name) var (name),
57 #define CANVAS_FONT_VARIABLE(var,name) var (name),
58 #include "ui_config_vars.h"
59 #include "canvas_vars.h"
60 #undef  UI_CONFIG_VARIABLE
61 #undef  CANVAS_STRING_VARIABLE
62 #undef  CANVAS_FONT_VARIABLE
63
64         /* initialize all the base colors using default
65            colors for now. these will be reset when/if
66            we load the UI config file.
67         */
68
69 #undef CANVAS_BASE_COLOR
70 #define CANVAS_BASE_COLOR(var,name,val) var (name,quantized (val)),
71 #include "base_colors.h"
72 #undef CANVAS_BASE_COLOR
73
74 #undef CANVAS_COLOR
75 #define CANVAS_COLOR(var,name,base,modifier) var (base,modifier),
76 #include "colors.h"
77 #undef CANVAS_COLOR
78
79         _dirty (false)
80 {
81         _instance = this;
82
83         /* pack all base colors into the configurable color map so that
84            derived colors can use them.
85         */
86           
87 #undef CANVAS_BASE_COLOR
88 #define CANVAS_BASE_COLOR(var,name,color) configurable_colors.insert (make_pair (name,&var));
89 #include "base_colors.h"
90 #undef CANVAS_BASE_COLOR
91
92 #undef CANVAS_COLOR
93 #define CANVAS_COLOR(var,name,base,modifier) relative_colors.insert (make_pair (name,var));
94 #include "colors.h"
95 #undef CANVAS_COLOR
96
97         load_state();
98
99         // regenerate_relative_definitions ();
100
101         color_compute ();
102
103         ARDOUR_UI_UTILS::ColorsChanged.connect (boost::bind (&UIConfiguration::color_theme_changed, this));
104 }
105
106 UIConfiguration::~UIConfiguration ()
107 {
108 }
109
110 Color
111 UIConfiguration::quantized (Color c)
112 {
113         HSV hsv (c);
114         hsv.h = hue_width * (round (hsv.h/hue_width));
115         return hsv.color ();
116 }
117
118 void
119 UIConfiguration::print_relative_def (string camelcase, string name, Color c)
120 {
121         HSV variable (c);
122         HSV closest;
123         double shortest_distance = DBL_MAX;
124         string closest_name;
125
126         map<string,ColorVariable<Color>*>::iterator f;
127         std::map<std::string,HSV> palette;
128
129         for (f = configurable_colors.begin(); f != configurable_colors.end(); ++f) {
130                 palette.insert (make_pair (f->first, HSV (f->second->get())));
131         }
132
133         for (map<string,HSV>::iterator f = palette.begin(); f != palette.end(); ++f) {
134                 
135                 double d;
136                 HSV fixed (f->second);
137                 
138                 if (fixed.is_gray() || variable.is_gray()) {
139                         /* at least one is achromatic; HSV::distance() will do
140                          * the right thing
141                          */
142                         d = fixed.distance (variable);
143                 } else {
144                         /* chromatic: compare ONLY hue because our task is
145                            to pick the HUE closest and then compute
146                            a modifier. We want to keep the number of 
147                            hues low, and by computing perceptual distance 
148                            we end up finding colors that are to each
149                            other without necessarily be close in hue.
150                         */
151                         d = fabs (variable.h - fixed.h);
152                 }
153
154                 if (d < shortest_distance) {
155                         closest = fixed;
156                         closest_name = f->first;
157                         shortest_distance = d;
158                 }
159         }
160         
161         /* we now know the closest color of the fixed colors to 
162            this variable color. Compute the HSV diff and
163            use it to redefine the variable color in terms of the
164            fixed one.
165         */
166         
167         HSV delta = variable.delta (closest);
168
169         /* quantize hue delta so we don't end up with many subtle hues caused
170          * by original color choices
171          */
172
173         delta.h = hue_width * (round (delta.h/hue_width));
174
175         cerr << "CANVAS_COLOR(" << camelcase << ",\"" << name << "\", \"" << closest_name <<  "\", HSV(" 
176              << delta.h << ',' << delta.s << ',' << delta.v << ',' << variable.a << ")) /*" 
177              << shortest_distance << " */" << endl;
178 }
179
180 void 
181 UIConfiguration::regenerate_relative_definitions ()
182 {
183         /* this takes the color definitions from around ardour 3.5.3600,
184            quantizes their hues, then prints out macros to be used
185            when defining these colors relative to the current
186            base palette. It doesn't need to be called unless
187            we change the base palette defaults.
188         */
189         
190         map<string,HSV> c;
191         c.insert (make_pair ("active crossfade", HSV (0x20b2af2e)));
192         c.insert (make_pair ("arrange base", HSV (0x595959ff)));
193         c.insert (make_pair ("audio bus base", HSV (0x73829968)));
194         c.insert (make_pair ("audio master bus base", HSV (0x00000000)));
195         c.insert (make_pair ("audio track base", HSV (0x9daac468)));
196         c.insert (make_pair ("automation line", HSV (0x44bc59ff)));
197         c.insert (make_pair ("automation track fill", HSV (0xa0a0ce68)));
198         c.insert (make_pair ("automation track outline", HSV (0x282828ff)));
199         c.insert (make_pair ("cd marker bar", HSV (0x9496a3cc)));
200         c.insert (make_pair ("crossfade editor base", HSV (0x282d49ff)));
201         c.insert (make_pair ("crossfade editor line", HSV (0x000000ff)));
202         c.insert (make_pair ("crossfade editor line shading", HSV (0x00a0d154)));
203         c.insert (make_pair ("crossfade editor point fill", HSV (0x00ff00ff)));
204         c.insert (make_pair ("crossfade editor point outline", HSV (0x0000ffff)));
205         c.insert (make_pair ("crossfade editor wave", HSV (0xffffff28)));
206         c.insert (make_pair ("selected crossfade editor wave fill", HSV (0x00000000)));
207         c.insert (make_pair ("crossfade line", HSV (0x000000ff)));
208         c.insert (make_pair ("edit point", HSV (0x0000ffff)));
209         c.insert (make_pair ("entered automation line", HSV (0xdd6363ff)));
210         c.insert (make_pair ("control point fill", HSV (0xffffff66)));
211         c.insert (make_pair ("control point outline", HSV (0xff0000ee)));
212         c.insert (make_pair ("control point selected", HSV (0x55ccccff)));
213         c.insert (make_pair ("entered gain line", HSV (0xdd6363ff)));
214         c.insert (make_pair ("entered marker", HSV (0xdd6363ff)));
215         c.insert (make_pair ("frame handle", HSV (0x7c00ff96)));
216         c.insert (make_pair ("gain line", HSV (0x00bc20ff)));
217         c.insert (make_pair ("gain line inactive", HSV (0x9fbca4c5)));
218         c.insert (make_pair ("ghost track base", HSV (0x603e7cc6)));
219         c.insert (make_pair ("ghost track midi outline", HSV (0x00000000)));
220         c.insert (make_pair ("ghost track wave", HSV (0x202020d9)));
221         c.insert (make_pair ("ghost track wave fill", HSV (0x20202060)));
222         c.insert (make_pair ("ghost track wave clip", HSV (0x202020d9)));
223         c.insert (make_pair ("ghost track zero line", HSV (0xe500e566)));
224         c.insert (make_pair ("image track", HSV (0xddddd8ff)));
225         c.insert (make_pair ("inactive crossfade", HSV (0xe8ed3d77)));
226         c.insert (make_pair ("inactive fade handle", HSV (0xbbbbbbaa)));
227         c.insert (make_pair ("inactive group tab", HSV (0x434343ff)));
228         c.insert (make_pair ("location cd marker", HSV (0x1ee8c4ff)));
229         c.insert (make_pair ("location loop", HSV (0x35964fff)));
230         c.insert (make_pair ("location marker", HSV (0xc4f411ff)));
231         c.insert (make_pair ("location punch", HSV (0x7c3a3aff)));
232         c.insert (make_pair ("location range", HSV (0x497a59ff)));
233         c.insert (make_pair ("marker bar", HSV (0x99a1adcc)));
234         c.insert (make_pair ("marker bar separator", HSV (0x555555ff)));
235         c.insert (make_pair ("marker drag line", HSV (0x004f00f9)));
236         c.insert (make_pair ("marker label", HSV (0x000000ff)));
237         c.insert (make_pair ("marker track", HSV (0xddddd8ff)));
238         c.insert (make_pair ("measure line bar", HSV (0xffffff9c)));
239         c.insert (make_pair ("measure line beat", HSV (0xa29e9e76)));
240         c.insert (make_pair ("meter bar", HSV (0x626470cc)));
241         c.insert (make_pair ("meter fill: 0", HSV (0x008800ff)));
242         c.insert (make_pair ("meter fill: 1", HSV (0x00aa00ff)));
243         c.insert (make_pair ("meter fill: 2", HSV (0x00ff00ff)));
244         c.insert (make_pair ("meter fill: 3", HSV (0x00ff00ff)));
245         c.insert (make_pair ("meter fill: 4", HSV (0xfff000ff)));
246         c.insert (make_pair ("meter fill: 5", HSV (0xfff000ff)));
247         c.insert (make_pair ("meter fill: 6", HSV (0xff8000ff)));
248         c.insert (make_pair ("meter fill: 7", HSV (0xff8000ff)));
249         c.insert (make_pair ("meter fill: 8", HSV (0xff0000ff)));
250         c.insert (make_pair ("meter fill: 9", HSV (0xff0000ff)));
251         c.insert (make_pair ("meter background: bottom", HSV (0x333333ff)));
252         c.insert (make_pair ("meter background: top", HSV (0x444444ff)));
253         c.insert (make_pair ("midi meter fill: 0", HSV (0xeffaa1ff)));
254         c.insert (make_pair ("midi meter fill: 1", HSV (0xf2c97dff)));
255         c.insert (make_pair ("midi meter fill: 2", HSV (0xf2c97dff)));
256         c.insert (make_pair ("midi meter fill: 3", HSV (0xf48f52ff)));
257         c.insert (make_pair ("midi meter fill: 4", HSV (0xf48f52ff)));
258         c.insert (make_pair ("midi meter fill: 5", HSV (0xf83913ff)));
259         c.insert (make_pair ("midi meter fill: 6", HSV (0xf83913ff)));
260         c.insert (make_pair ("midi meter fill: 7", HSV (0x8fc78eff)));
261         c.insert (make_pair ("midi meter fill: 8", HSV (0x8fc78eff)));
262         c.insert (make_pair ("midi meter fill: 9", HSV (0x00f45600)));
263         c.insert (make_pair ("meterbridge peakindicator: fill", HSV (0x444444ff)));
264         c.insert (make_pair ("meterbridge peakindicator: fill active", HSV (0xff0000ff)));
265         c.insert (make_pair ("meterbridge label: fill", HSV (0x444444ff)));
266         c.insert (make_pair ("meterbridge label: fill active", HSV (0x333333ff)));
267         c.insert (make_pair ("meterbridge label: text", HSV (0xc7c7d8ff)));
268         c.insert (make_pair ("meter marker", HSV (0xf2425bff)));
269         c.insert (make_pair ("midi bus base", HSV (0x00000000)));
270         c.insert (make_pair ("midi frame base", HSV (0x393d3766)));
271         c.insert (make_pair ("midi note inactive channel", HSV (0x00000000)));
272         c.insert (make_pair ("midi note color min", HSV (0x3f542aff)));
273         c.insert (make_pair ("midi note color mid", HSV (0x7ea854ff)));
274         c.insert (make_pair ("midi note color max", HSV (0xbfff80ff)));
275         c.insert (make_pair ("selected midi note color min", HSV (0x1e1e33ff)));
276         c.insert (make_pair ("selected midi note color mid", HSV (0x51518aff)));
277         c.insert (make_pair ("selected midi note color max", HSV (0x8383deff)));
278         c.insert (make_pair ("midi note selected", HSV (0xb2b2ffff)));
279         c.insert (make_pair ("midi note velocity text", HSV (0xf4f214bc)));
280         c.insert (make_pair ("midi patch change fill", HSV (0x50555aa0)));
281         c.insert (make_pair ("midi patch change outline", HSV (0xc0c5caff)));
282         c.insert (make_pair ("midi patch change inactive channel fill", HSV (0x50555ac0)));
283         c.insert (make_pair ("midi patch change inactive channel outline", HSV (0x20252ac0)));
284         c.insert (make_pair ("midi sysex fill", HSV (0xf1e139a0)));
285         c.insert (make_pair ("midi sysex outline", HSV (0xa7a7d4ff)));
286         c.insert (make_pair ("midi select rect fill", HSV (0x8888ff88)));
287         c.insert (make_pair ("midi select rect outline", HSV (0x5555ffff)));
288         c.insert (make_pair ("midi track base", HSV (0xb3cca35f)));
289         c.insert (make_pair ("name highlight fill", HSV (0x0000ffff)));
290         c.insert (make_pair ("name highlight outline", HSV (0x7c00ff96)));
291         c.insert (make_pair ("piano roll black outline", HSV (0xf4f4f476)));
292         c.insert (make_pair ("piano roll black", HSV (0x6c6e6a6b)));
293         c.insert (make_pair ("piano roll white", HSV (0x979b9565)));
294         c.insert (make_pair ("play head", HSV (0xff0000ff)));
295         c.insert (make_pair ("processor automation line", HSV (0x7aa3f9ff)));
296         c.insert (make_pair ("punch line", HSV (0xa80000ff)));
297         c.insert (make_pair ("range drag bar rect", HSV (0x969696c6)));
298         c.insert (make_pair ("range drag rect", HSV (0x82c696c6)));
299         c.insert (make_pair ("range marker bar", HSV (0x7d7f8ccc)));
300         c.insert (make_pair ("recording rect", HSV (0xcc2828ff)));
301         c.insert (make_pair ("recorded waveform fill", HSV (0xffffffd9)));
302         c.insert (make_pair ("recorded waveform outline", HSV (0x0f0f1fff)));
303         c.insert (make_pair ("rubber band rect", HSV (0xc6c6c659)));
304         c.insert (make_pair ("ruler base", HSV (0x2c2121ff)));
305         c.insert (make_pair ("ruler text", HSV (0xe5e5e5ff)));
306         c.insert (make_pair ("selected crossfade editor line", HSV (0x00dbdbff)));
307         c.insert (make_pair ("selected crossfade editor wave", HSV (0xf9ea14a0)));
308         c.insert (make_pair ("selected region base", HSV (0x585c61ff)));
309         c.insert (make_pair ("selected waveform fill", HSV (0xffa500d9)));
310         c.insert (make_pair ("selected waveform outline", HSV (0x0f0f0fcc)));
311         c.insert (make_pair ("selection rect", HSV (0xe8f4d377)));
312         c.insert (make_pair ("selection", HSV (0x636363b2)));
313         c.insert (make_pair ("shuttle", HSV (0x6bb620ff)));
314         c.insert (make_pair ("silence", HSV (0x9efffd7a)));
315         c.insert (make_pair ("silence text", HSV (0x0e066cff)));
316         c.insert (make_pair ("mono panner outline", HSV (0x33445eff)));
317         c.insert (make_pair ("mono panner fill", HSV (0x7a9bccc9)));
318         c.insert (make_pair ("mono panner text", HSV (0x000000ff)));
319         c.insert (make_pair ("mono panner bg", HSV (0x2e2929ff)));
320         c.insert (make_pair ("mono panner position fill", HSV (0x7a89b3ff)));
321         c.insert (make_pair ("mono panner position outline", HSV (0x33445eff)));
322         c.insert (make_pair ("stereo panner outline", HSV (0x33445eff)));
323         c.insert (make_pair ("stereo panner fill", HSV (0x7a9accc9)));
324         c.insert (make_pair ("stereo panner text", HSV (0x000000ff)));
325         c.insert (make_pair ("stereo panner bg", HSV (0x2e2929ff)));
326         c.insert (make_pair ("stereo panner rule", HSV (0x455c7fff)));
327         c.insert (make_pair ("stereo panner mono outline", HSV (0xa05600ff)));
328         c.insert (make_pair ("stereo panner mono fill", HSV (0xe99668ca)));
329         c.insert (make_pair ("stereo panner mono text", HSV (0x000000ff)));
330         c.insert (make_pair ("stereo panner mono bg", HSV (0x2e2929ff)));
331         c.insert (make_pair ("stereo panner inverted outline", HSV (0xbf0a00ff)));
332         c.insert (make_pair ("stereo panner inverted fill", HSV (0xe4a19cc9)));
333         c.insert (make_pair ("stereo panner inverted text", HSV (0x000000ff)));
334         c.insert (make_pair ("stereo panner inverted bg", HSV (0x2e2929ff)));
335         c.insert (make_pair ("tempo bar", HSV (0x70727fcc)));
336         c.insert (make_pair ("tempo marker", HSV (0xf2425bff)));
337         c.insert (make_pair ("time axis frame", HSV (0x000000ff)));
338         c.insert (make_pair ("selected time axis frame", HSV (0xee0000ff)));
339         c.insert (make_pair ("time stretch fill", HSV (0xe2b5b596)));
340         c.insert (make_pair ("time stretch outline", HSV (0x63636396)));
341         c.insert (make_pair ("tracknumber label: fill", HSV (0x444444ff)));
342         c.insert (make_pair ("tracknumber label: fill active", HSV (0x333333ff)));
343         c.insert (make_pair ("tracknumber label: text", HSV (0xc7c7d8ff)));
344         c.insert (make_pair ("transport drag rect", HSV (0x969696c6)));
345         c.insert (make_pair ("transport loop rect", HSV (0x1e7728f9)));
346         c.insert (make_pair ("transport marker bar", HSV (0x8c8e98cc)));
347         c.insert (make_pair ("transport punch rect", HSV (0x6d2828e5)));
348         c.insert (make_pair ("trim handle locked", HSV (0xea0f0f28)));
349         c.insert (make_pair ("trim handle", HSV (0x1900ff44)));
350         c.insert (make_pair ("verbose canvas cursor", HSV (0xfffd2ebc)));
351         c.insert (make_pair ("vestigial frame", HSV (0x0000000f)));
352         c.insert (make_pair ("video timeline bar", HSV (0x303030ff)));
353         c.insert (make_pair ("region base", HSV (0x838890ff)));
354         c.insert (make_pair ("region area covered by another region", HSV (0x505050b0)));
355         c.insert (make_pair ("waveform outline", HSV (0x000000ff)));
356         c.insert (make_pair ("clipped waveform", HSV (0xff0000e5)));
357         c.insert (make_pair ("waveform fill", HSV (0xffffffd9)));
358         c.insert (make_pair ("zero line", HSV (0x7f7f7fe0)));
359         c.insert (make_pair ("zoom rect", HSV (0xc6d1b26d)));
360         c.insert (make_pair ("monitor knob", HSV (0x555050ff)));
361         c.insert (make_pair ("monitor knob: arc start", HSV (0x5d90b0ff)));
362         c.insert (make_pair ("monitor knob: arc end", HSV (0x154c6eff)));
363         c.insert (make_pair ("button border", HSV (0x000000f0)));
364         c.insert (make_pair ("border color", HSV (0x00000000)));
365         c.insert (make_pair ("processor prefader: fill", HSV (0x873c3cff)));
366         c.insert (make_pair ("processor prefader: fill active", HSV (0x603535ff)));
367         c.insert (make_pair ("processor prefader: led", HSV (0x26550eff)));
368         c.insert (make_pair ("processor prefader: led active", HSV (0x78cb4eff)));
369         c.insert (make_pair ("processor prefader: text", HSV (0xaaaaa3ff)));
370         c.insert (make_pair ("processor prefader: text active", HSV (0xeeeeecff)));
371         c.insert (make_pair ("processor fader: fill", HSV (0x5d90b0ff)));
372         c.insert (make_pair ("processor fader: fill active", HSV (0x256d8fff)));
373         c.insert (make_pair ("processor fader: led", HSV (0x26550eff)));
374         c.insert (make_pair ("processor fader: led active", HSV (0x78cb4eff)));
375         c.insert (make_pair ("processor fader: text", HSV (0xaaaaa3ff)));
376         c.insert (make_pair ("processor fader: text active", HSV (0xeeeeecff)));
377         c.insert (make_pair ("processor postfader: fill", HSV (0x455a3cff)));
378         c.insert (make_pair ("processor postfader: fill active", HSV (0x254528ff)));
379         c.insert (make_pair ("processor postfader: led", HSV (0x26550eff)));
380         c.insert (make_pair ("processor postfader: led active", HSV (0x78cb4eff)));
381         c.insert (make_pair ("processor postfader: text", HSV (0xaaaaa3ff)));
382         c.insert (make_pair ("processor postfader: text active", HSV (0xeeeeecff)));
383         c.insert (make_pair ("processor control button: fill", HSV (0x222222ff)));
384         c.insert (make_pair ("processor control button: fill active", HSV (0x333333ff)));
385         c.insert (make_pair ("processor control button: led", HSV (0x101010ff)));
386         c.insert (make_pair ("processor control button: led active", HSV (0x5d90b0ff)));
387         c.insert (make_pair ("processor control button: text", HSV (0xffffffff)));
388         c.insert (make_pair ("processor control button: text active", HSV (0xffffffff)));
389         c.insert (make_pair ("midi device: fill", HSV (0x54555dff)));
390         c.insert (make_pair ("midi device: fill active", HSV (0x45464cff)));
391         c.insert (make_pair ("midi device: led", HSV (0x006600ff)));
392         c.insert (make_pair ("midi device: led active", HSV (0x00ff00ff)));
393         c.insert (make_pair ("midi device: text", HSV (0xc7c7d8ff)));
394         c.insert (make_pair ("midi device: text active", HSV (0xeeeeecff)));
395         c.insert (make_pair ("monitor button: fill", HSV (0x616268ff)));
396         c.insert (make_pair ("monitor button: fill active", HSV (0xc56505ff)));
397         c.insert (make_pair ("monitor button: led", HSV (0x660000ff)));
398         c.insert (make_pair ("monitor button: led active", HSV (0xff0000ff)));
399         c.insert (make_pair ("monitor button: text", HSV (0xc7c7d8ff)));
400         c.insert (make_pair ("monitor button: text active", HSV (0x1a1a1aff)));
401         c.insert (make_pair ("solo isolate: fill", HSV (0x616268ff)));
402         c.insert (make_pair ("solo isolate: fill active", HSV (0x564d48ff)));
403         c.insert (make_pair ("solo isolate: led", HSV (0x660000ff)));
404         c.insert (make_pair ("solo isolate: led active", HSV (0xff0000ff)));
405         c.insert (make_pair ("solo isolate: text", HSV (0xc7c7d8ff)));
406         c.insert (make_pair ("solo isolate: text active", HSV (0xc8c8d9ff)));
407         c.insert (make_pair ("solo safe: fill", HSV (0x616268ff)));
408         c.insert (make_pair ("solo safe: fill active", HSV (0x564d48ff)));
409         c.insert (make_pair ("solo safe: led", HSV (0x660000ff)));
410         c.insert (make_pair ("solo safe: led active", HSV (0xff0000ff)));
411         c.insert (make_pair ("solo safe: text", HSV (0xc7c7d8ff)));
412         c.insert (make_pair ("solo safe: text active", HSV (0xc8c8d9ff)));
413         c.insert (make_pair ("meterbridge peaklabel", HSV (0xff1111ff)));
414         c.insert (make_pair ("meter color BBC", HSV (0xffa500ff)));
415         c.insert (make_pair ("monitor section cut: fill", HSV (0x5f5a58ff)));
416         c.insert (make_pair ("monitor section cut: fill active", HSV (0xffa500ff)));
417         c.insert (make_pair ("monitor section cut: led", HSV (0x473812ff)));
418         c.insert (make_pair ("monitor section cut: led active", HSV (0x78cb4eff)));
419         c.insert (make_pair ("monitor section cut: text", HSV (0xc7c7d8ff)));
420         c.insert (make_pair ("monitor section cut: text active", HSV (0x000000ff)));
421         c.insert (make_pair ("monitor section dim: fill", HSV (0x5f5a58ff)));
422         c.insert (make_pair ("monitor section dim: fill active", HSV (0xe58505ff)));
423         c.insert (make_pair ("monitor section dim: led", HSV (0x00000000)));
424         c.insert (make_pair ("monitor section dim: led active", HSV (0x78cb4eff)));
425         c.insert (make_pair ("monitor section dim: text", HSV (0xc8c8d9ff)));
426         c.insert (make_pair ("monitor section dim: text active", HSV (0xc8c8d9ff)));
427         c.insert (make_pair ("monitor section solo: fill", HSV (0x5f5a58ff)));
428         c.insert (make_pair ("monitor section solo: fill active", HSV (0x4dbb00ff)));
429         c.insert (make_pair ("monitor section solo: led", HSV (0x473812ff)));
430         c.insert (make_pair ("monitor section solo: led active", HSV (0xffa500ff)));
431         c.insert (make_pair ("monitor section solo: text", HSV (0x00000000)));
432         c.insert (make_pair ("monitor section solo: text active", HSV (0x00000000)));
433         c.insert (make_pair ("monitor section invert: fill", HSV (0x5f5a58ff)));
434         c.insert (make_pair ("monitor section invert: fill active", HSV (0x4242d0ff)));
435         c.insert (make_pair ("monitor section invert: led", HSV (0x473812ff)));
436         c.insert (make_pair ("monitor section invert: led active", HSV (0x78cb4eff)));
437         c.insert (make_pair ("monitor section invert: text", HSV (0x00000000)));
438         c.insert (make_pair ("monitor section invert: text active", HSV (0x00000000)));
439         c.insert (make_pair ("monitor section mono: fill", HSV (0x5f5a58ff)));
440         c.insert (make_pair ("monitor section mono: fill active", HSV (0x3232c0ff)));
441         c.insert (make_pair ("monitor section mono: led", HSV (0x473812ff)));
442         c.insert (make_pair ("monitor section mono: led active", HSV (0x78cb4eff)));
443         c.insert (make_pair ("monitor section mono: text", HSV (0xc7c7d8ff)));
444         c.insert (make_pair ("monitor section mono: text active", HSV (0xc8c8d9ff)));
445         c.insert (make_pair ("monitor section solo model: fill", HSV (0x5d5856ff)));
446         c.insert (make_pair ("monitor section solo model: fill active", HSV (0x564d48ff)));
447         c.insert (make_pair ("monitor section solo model: led", HSV (0x4f3300ff)));
448         c.insert (make_pair ("monitor section solo model: led active", HSV (0xffa500ff)));
449         c.insert (make_pair ("monitor section solo model: text", HSV (0xc7c7d8ff)));
450         c.insert (make_pair ("monitor section solo model: text active", HSV (0xc8c8d9ff)));
451         c.insert (make_pair ("monitor solo override: fill", HSV (0x5d5856ff)));
452         c.insert (make_pair ("monitor solo override: fill active", HSV (0x564d48ff)));
453         c.insert (make_pair ("monitor solo override: led", HSV (0x4f3300ff)));
454         c.insert (make_pair ("monitor solo override: led active", HSV (0xffa500ff)));
455         c.insert (make_pair ("monitor solo override: text", HSV (0xc7c7d8ff)));
456         c.insert (make_pair ("monitor solo override: text active", HSV (0xc8c8d9ff)));
457         c.insert (make_pair ("monitor solo exclusive: fill", HSV (0x5d5856ff)));
458         c.insert (make_pair ("monitor solo exclusive: fill active", HSV (0x564c47ff)));
459         c.insert (make_pair ("monitor solo exclusive: led", HSV (0x4f3300ff)));
460         c.insert (make_pair ("monitor solo exclusive: led active", HSV (0xffa500ff)));
461         c.insert (make_pair ("monitor solo exclusive: text", HSV (0xc7c7d8ff)));
462         c.insert (make_pair ("monitor solo exclusive: text active", HSV (0xc8c8d9ff)));
463         c.insert (make_pair ("rude solo: fill", HSV (0x684d4dff)));
464         c.insert (make_pair ("rude solo: fill active", HSV (0xe21b1bff)));
465         c.insert (make_pair ("rude solo: led", HSV (0x00000000)));
466         c.insert (make_pair ("rude solo: led active", HSV (0x00000000)));
467         c.insert (make_pair ("rude solo: text", HSV (0x969696ff)));
468         c.insert (make_pair ("rude solo: text active", HSV (0xe5e5e5ff)));
469         c.insert (make_pair ("rude isolate: fill", HSV (0x21414fff)));
470         c.insert (make_pair ("rude isolate: fill active", HSV (0xb6e5fdff)));
471         c.insert (make_pair ("rude isolate: led", HSV (0x00000000)));
472         c.insert (make_pair ("rude isolate: led active", HSV (0x000000ff)));
473         c.insert (make_pair ("rude isolate: text", HSV (0x979797ff)));
474         c.insert (make_pair ("rude isolate: text active", HSV (0x000000ff)));
475         c.insert (make_pair ("rude audition: fill", HSV (0x684d4dff)));
476         c.insert (make_pair ("rude audition: fill active", HSV (0xe21b1bff)));
477         c.insert (make_pair ("rude audition: led", HSV (0x00000000)));
478         c.insert (make_pair ("rude audition: led active", HSV (0x00000000)));
479         c.insert (make_pair ("rude audition: text", HSV (0x979797ff)));
480         c.insert (make_pair ("rude audition: text active", HSV (0xffffffff)));
481         c.insert (make_pair ("feedback alert: fill", HSV (0x684d4dff)));
482         c.insert (make_pair ("feedback alert: fill active", HSV (0xe21b1bff)));
483         c.insert (make_pair ("feedback alert: led", HSV (0x00000000)));
484         c.insert (make_pair ("feedback alert: led active", HSV (0x00000000)));
485         c.insert (make_pair ("feedback alert: text", HSV (0x969696ff)));
486         c.insert (make_pair ("feedback alert: text active", HSV (0xe5e5e5ff)));
487         c.insert (make_pair ("mute button: fill", HSV (0x616268ff)));
488         c.insert (make_pair ("mute button: fill active", HSV (0xbbbb00ff)));
489         c.insert (make_pair ("mute button: led", HSV (0x00000000)));
490         c.insert (make_pair ("mute button: led active", HSV (0x00000000)));
491         c.insert (make_pair ("mute button: text", HSV (0xc7c7d8ff)));
492         c.insert (make_pair ("mute button: text active", HSV (0x191919ff)));
493         c.insert (make_pair ("solo button: fill", HSV (0x616268ff)));
494         c.insert (make_pair ("solo button: fill active", HSV (0x4dbb00ff)));
495         c.insert (make_pair ("solo button: led", HSV (0x00000000)));
496         c.insert (make_pair ("solo button: led active", HSV (0x00000000)));
497         c.insert (make_pair ("solo button: text", HSV (0xc7c7d8ff)));
498         c.insert (make_pair ("solo button: text active", HSV (0x191919ff)));
499         c.insert (make_pair ("invert button: fill", HSV (0x616268ff)));
500         c.insert (make_pair ("invert button: fill active", HSV (0x4242d0ff)));
501         c.insert (make_pair ("invert button: led", HSV (0x473812ff)));
502         c.insert (make_pair ("invert button: led active", HSV (0x78cb4eff)));
503         c.insert (make_pair ("invert button: text", HSV (0xd7d7e8ff)));
504         c.insert (make_pair ("invert button: text active", HSV (0xbfbfbfff)));
505         c.insert (make_pair ("record enable button: fill", HSV (0x616268ff)));
506         c.insert (make_pair ("record enable button: fill active", HSV (0xb50e0eff)));
507         c.insert (make_pair ("record enable button: led", HSV (0x7b3541ff)));
508         c.insert (make_pair ("record enable button: led active", HSV (0xffa3b3ff)));
509         c.insert (make_pair ("record enable button: text", HSV (0xa5a5a5ff)));
510         c.insert (make_pair ("record enable button: text active", HSV (0x000000ff)));
511         c.insert (make_pair ("generic button: fill", HSV (0x616268ff)));
512         c.insert (make_pair ("generic button: fill active", HSV (0xfd0000ff)));
513         c.insert (make_pair ("generic button: led", HSV (0x22224fff)));
514         c.insert (make_pair ("generic button: led active", HSV (0x2222ffff)));
515         c.insert (make_pair ("generic button: text", HSV (0xc7c7d8ff)));
516         c.insert (make_pair ("generic button: text active", HSV (0x191919ff)));
517         c.insert (make_pair ("send alert button: fill", HSV (0x4e5647ff)));
518         c.insert (make_pair ("send alert button: fill active", HSV (0x85e524ff)));
519         c.insert (make_pair ("send alert button: led", HSV (0x00000000)));
520         c.insert (make_pair ("send alert button: led active", HSV (0x00000000)));
521         c.insert (make_pair ("send alert button: text", HSV (0xccccccff)));
522         c.insert (make_pair ("send alert button: text active", HSV (0x000000ff)));
523         c.insert (make_pair ("transport button: fill", HSV (0x616268ff)));
524         c.insert (make_pair ("transport button: fill active", HSV (0x00a300ff)));
525         c.insert (make_pair ("transport button: led", HSV (0x00000000)));
526         c.insert (make_pair ("transport button: led active", HSV (0x00000000)));
527         c.insert (make_pair ("transport button: text", HSV (0x00000000)));
528         c.insert (make_pair ("transport button: text active", HSV (0x00000000)));
529         c.insert (make_pair ("transport recenable button: fill", HSV (0x5f3f3fff)));
530         c.insert (make_pair ("transport recenable button: fill active", HSV (0xb50e0eff)));
531         c.insert (make_pair ("transport recenable button: led", HSV (0x00000000)));
532         c.insert (make_pair ("transport recenable button: led active", HSV (0x00000000)));
533         c.insert (make_pair ("transport recenable button: text", HSV (0x00000000)));
534         c.insert (make_pair ("transport recenable button: text active", HSV (0x00000000)));
535         c.insert (make_pair ("transport option button: fill", HSV (0x616268ff)));
536         c.insert (make_pair ("transport option button: fill active", HSV (0x4a4b51ff)));
537         c.insert (make_pair ("transport option button: led", HSV (0x4f3300ff)));
538         c.insert (make_pair ("transport option button: led active", HSV (0xffa500ff)));
539         c.insert (make_pair ("transport option button: text", HSV (0xd7d7e8ff)));
540         c.insert (make_pair ("transport option button: text active", HSV (0xc8c8d9ff)));
541         c.insert (make_pair ("transport active option button: fill", HSV (0x616268ff)));
542         c.insert (make_pair ("transport active option button: fill active", HSV (0x00a300ff)));
543         c.insert (make_pair ("transport active option button: led", HSV (0x4f3300ff)));
544         c.insert (make_pair ("transport active option button: led active", HSV (0xffa500ff)));
545         c.insert (make_pair ("transport active option button: text", HSV (0xd7d7e8ff)));
546         c.insert (make_pair ("transport active option button: text active", HSV (0x000000ff)));
547         c.insert (make_pair ("plugin bypass button: fill", HSV (0x5d5856ff)));
548         c.insert (make_pair ("plugin bypass button: fill active", HSV (0x564d48ff)));
549         c.insert (make_pair ("plugin bypass button: led", HSV (0x660000ff)));
550         c.insert (make_pair ("plugin bypass button: led active", HSV (0xff0000ff)));
551         c.insert (make_pair ("plugin bypass button: text", HSV (0xc7c7d8ff)));
552         c.insert (make_pair ("plugin bypass button: text active", HSV (0xc8c8d9ff)));
553         c.insert (make_pair ("punch button: fill", HSV (0x603f3fff)));
554         c.insert (make_pair ("punch button: fill active", HSV (0xf03020ff)));
555         c.insert (make_pair ("punch button: led", HSV (0x00000000)));
556         c.insert (make_pair ("punch button: led active", HSV (0x00000000)));
557         c.insert (make_pair ("punch button: text", HSV (0xa5a5a5ff)));
558         c.insert (make_pair ("punch button: text active", HSV (0xd8d8d8ff)));
559         c.insert (make_pair ("mouse mode button: fill", HSV (0x616268ff)));
560         c.insert (make_pair ("mouse mode button: fill active", HSV (0x00b200ff)));
561         c.insert (make_pair ("mouse mode button: led", HSV (0x4f3300ff)));
562         c.insert (make_pair ("mouse mode button: led active", HSV (0xffa500ff)));
563         c.insert (make_pair ("mouse mode button: text", HSV (0xd7d7e8ff)));
564         c.insert (make_pair ("mouse mode button: text active", HSV (0x000000ff)));
565         c.insert (make_pair ("nudge button: fill", HSV (0x684744ff)));
566         c.insert (make_pair ("nudge button: fill active", HSV (0x404045ff)));
567         c.insert (make_pair ("nudge button: led", HSV (0x4f3300ff)));
568         c.insert (make_pair ("nudge button: led active", HSV (0xffa500ff)));
569         c.insert (make_pair ("nudge button: text", HSV (0xc7c7d8ff)));
570         c.insert (make_pair ("nudge button: text active", HSV (0xc8c8d9ff)));
571         c.insert (make_pair ("zoom menu: fill", HSV (0x99997950)));
572         c.insert (make_pair ("zoom menu: fill active", HSV (0x404045ff)));
573         c.insert (make_pair ("zoom menu: led", HSV (0x4f3300ff)));
574         c.insert (make_pair ("zoom menu: led active", HSV (0xffa500ff)));
575         c.insert (make_pair ("zoom menu: text", HSV (0xd7d7e8ff)));
576         c.insert (make_pair ("zoom menu: text active", HSV (0xc8c8d9ff)));
577         c.insert (make_pair ("zoom button: fill", HSV (0x616268ff)));
578         c.insert (make_pair ("zoom button: fill active", HSV (0x00a300ff)));
579         c.insert (make_pair ("zoom button: led", HSV (0x4f3300ff)));
580         c.insert (make_pair ("zoom button: led active", HSV (0xffa500ff)));
581         c.insert (make_pair ("zoom button: text", HSV (0xd7d7e8ff)));
582         c.insert (make_pair ("zoom button: text active", HSV (0x000000ff)));
583         c.insert (make_pair ("route button: fill", HSV (0x616268ff)));
584         c.insert (make_pair ("route button: fill active", HSV (0x121212ff)));
585         c.insert (make_pair ("route button: led", HSV (0x4f3300ff)));
586         c.insert (make_pair ("route button: led active", HSV (0xffa500ff)));
587         c.insert (make_pair ("route button: text", HSV (0xd7d7e8ff)));
588         c.insert (make_pair ("route button: text active", HSV (0x191919ff)));
589         c.insert (make_pair ("mixer strip button: fill", HSV (0x616268ff)));
590         c.insert (make_pair ("mixer strip button: fill active", HSV (0xffa500ff)));
591         c.insert (make_pair ("mixer strip button: led", HSV (0x4f3300ff)));
592         c.insert (make_pair ("mixer strip button: led active", HSV (0xffa500ff)));
593         c.insert (make_pair ("mixer strip button: text", HSV (0xd7d7e8ff)));
594         c.insert (make_pair ("mixer strip button: text active", HSV (0x000000ff)));
595         c.insert (make_pair ("mixer strip name button: fill", HSV (0x616268ff)));
596         c.insert (make_pair ("mixer strip name button: fill active", HSV (0x121212ff)));
597         c.insert (make_pair ("mixer strip name button: led", HSV (0x4f3300ff)));
598         c.insert (make_pair ("mixer strip name button: led active", HSV (0xffa500ff)));
599         c.insert (make_pair ("mixer strip name button: text", HSV (0xd7d7e8ff)));
600         c.insert (make_pair ("mixer strip name button: text active", HSV (0xc8c8d9ff)));
601         c.insert (make_pair ("midi input button: fill", HSV (0x656867ff)));
602         c.insert (make_pair ("midi input button: fill active", HSV (0x00a300ff)));
603         c.insert (make_pair ("midi input button: led", HSV (0x00000000)));
604         c.insert (make_pair ("midi input button: led active", HSV (0x00000000)));
605         c.insert (make_pair ("midi input button: text", HSV (0x00000000)));
606         c.insert (make_pair ("midi input button: text active", HSV (0x00000000)));
607         c.insert (make_pair ("transport clock: background", HSV (0x262626ff)));
608         c.insert (make_pair ("transport clock: text", HSV (0x8df823ff)));
609         c.insert (make_pair ("transport clock: edited text", HSV (0xffa500ff)));
610         c.insert (make_pair ("transport clock: cursor", HSV (0xffa500ff)));
611         c.insert (make_pair ("secondary clock: background", HSV (0x262626ff)));
612         c.insert (make_pair ("secondary clock: text", HSV (0x8df823ff)));
613         c.insert (make_pair ("secondary clock: edited text", HSV (0xffa500ff)));
614         c.insert (make_pair ("secondary clock: cursor", HSV (0xffa500ff)));
615         c.insert (make_pair ("transport delta clock: background", HSV (0x000000ff)));
616         c.insert (make_pair ("transport delta clock: edited text", HSV (0xff0000ff)));
617         c.insert (make_pair ("transport delta clock: cursor", HSV (0xf11000ff)));
618         c.insert (make_pair ("transport delta clock: text", HSV (0x8ce1f8ff)));
619         c.insert (make_pair ("secondary delta clock: edited text", HSV (0xff0000ff)));
620         c.insert (make_pair ("secondary delta clock: cursor", HSV (0xf11000ff)));
621         c.insert (make_pair ("secondary delta clock: background", HSV (0x000000ff)));
622         c.insert (make_pair ("secondary delta clock: text", HSV (0x8ce1f8ff)));
623         c.insert (make_pair ("big clock: background", HSV (0x020202ff)));
624         c.insert (make_pair ("big clock: text", HSV (0xf0f0f0ff)));
625         c.insert (make_pair ("big clock: edited text", HSV (0xffa500ff)));
626         c.insert (make_pair ("big clock: cursor", HSV (0xffa500ff)));
627         c.insert (make_pair ("big clock active: background", HSV (0x020202ff)));
628         c.insert (make_pair ("big clock active: text", HSV (0xf11000ff)));
629         c.insert (make_pair ("big clock active: edited text", HSV (0xffa500ff)));
630         c.insert (make_pair ("big clock active: cursor", HSV (0xffa500ff)));
631         c.insert (make_pair ("punch clock: background", HSV (0x000000ff)));
632         c.insert (make_pair ("punch clock: text", HSV (0x6bb620ff)));
633         c.insert (make_pair ("punch clock: edited text", HSV (0xff0000ff)));
634         c.insert (make_pair ("punch clock: cursor", HSV (0xf11000ff)));
635         c.insert (make_pair ("selection clock: background", HSV (0x000000ff)));
636         c.insert (make_pair ("selection clock: text", HSV (0x6bb620ff)));
637         c.insert (make_pair ("selection clock: edited text", HSV (0xff0000ff)));
638         c.insert (make_pair ("selection clock: cursor", HSV (0xf11000ff)));
639         c.insert (make_pair ("nudge clock: background", HSV (0x262626ff)));
640         c.insert (make_pair ("nudge clock: text", HSV (0x6bb620ff)));
641         c.insert (make_pair ("nudge clock: edited text", HSV (0xffa500ff)));
642         c.insert (make_pair ("nudge clock: cursor", HSV (0xffa500ff)));
643         c.insert (make_pair ("clock: background", HSV (0x000000ff)));
644         c.insert (make_pair ("clock: text", HSV (0x6bb620ff)));
645         c.insert (make_pair ("clock: edited text", HSV (0xffa500ff)));
646         c.insert (make_pair ("clock: cursor", HSV (0xffa500ff)));
647         c.insert (make_pair ("lock button: fill", HSV (0x616268ff)));
648         c.insert (make_pair ("lock button: fill active", HSV (0x404045ff)));
649         c.insert (make_pair ("lock button: led", HSV (0x00000000)));
650         c.insert (make_pair ("lock button: led active", HSV (0x00000000)));
651         c.insert (make_pair ("lock button: text", HSV (0x000024ff)));
652         c.insert (make_pair ("lock button: text active", HSV (0xc8c8d9ff)));
653
654         for (map<string,HSV>::iterator fp = c.begin(); fp != c.end(); ++fp) {
655                 fp->second.h = hue_width * (round (fp->second.h/hue_width));
656         }
657
658 #undef CANVAS_COLOR
659 #define CANVAS_COLOR(var,name,base,modifier) print_relative_def (#var,name,c[name]);
660 #include "colors.h"
661 #undef CANVAS_COLOR     
662 }
663
664 void
665 UIConfiguration::color_theme_changed ()
666 {
667         map<std::string,RelativeHSV>::iterator current_color;
668
669         /* we need to reset the quantized hues before we start, because
670          * otherwise when we call RelativeHSV::get() in color_compute()
671          * we don't get an answer based on the new base colors, but instead
672          * based on any existing hue quantization.
673          */
674
675         for (current_color = relative_colors.begin(); current_color != relative_colors.end(); ++current_color) {
676                 current_color->second.quantized_hue = -1;
677         }
678
679         color_compute ();
680 }
681
682 void
683 UIConfiguration::map_parameters (boost::function<void (std::string)>& functor)
684 {
685 #undef  UI_CONFIG_VARIABLE
686 #define UI_CONFIG_VARIABLE(Type,var,Name,value) functor (Name);
687 #include "ui_config_vars.h"
688 #undef  UI_CONFIG_VARIABLE
689 }
690
691 int
692 UIConfiguration::load_defaults ()
693 {
694         int found = 0;
695         std::string rcfile;
696
697         if (find_file (ardour_config_search_path(), default_ui_config_file_name, rcfile) ) {
698                 XMLTree tree;
699                 found = 1;
700
701                 info << string_compose (_("Loading default ui configuration file %1"), rcfile) << endl;
702
703                 if (!tree.read (rcfile.c_str())) {
704                         error << string_compose(_("cannot read default ui configuration file \"%1\""), rcfile) << endmsg;
705                         return -1;
706                 }
707
708                 if (set_state (*tree.root(), Stateful::loading_state_version)) {
709                         error << string_compose(_("default ui configuration file \"%1\" not loaded successfully."), rcfile) << endmsg;
710                         return -1;
711                 }
712
713                 _dirty = false;
714         }
715
716         return found;
717 }
718
719 int
720 UIConfiguration::load_state ()
721 {
722         bool found = false;
723
724         std::string rcfile;
725
726         if ( find_file (ardour_config_search_path(), default_ui_config_file_name, rcfile)) {
727                 XMLTree tree;
728                 found = true;
729
730                 info << string_compose (_("Loading default ui configuration file %1"), rcfile) << endl;
731
732                 if (!tree.read (rcfile.c_str())) {
733                         error << string_compose(_("cannot read default ui configuration file \"%1\""), rcfile) << endmsg;
734                         return -1;
735                 }
736
737                 if (set_state (*tree.root(), Stateful::loading_state_version)) {
738                         error << string_compose(_("default ui configuration file \"%1\" not loaded successfully."), rcfile) << endmsg;
739                         return -1;
740                 }
741         }
742
743         if (find_file (ardour_config_search_path(), ui_config_file_name, rcfile)) {
744                 XMLTree tree;
745                 found = true;
746
747                 info << string_compose (_("Loading user ui configuration file %1"), rcfile) << endmsg;
748
749                 if (!tree.read (rcfile)) {
750                         error << string_compose(_("cannot read ui configuration file \"%1\""), rcfile) << endmsg;
751                         return -1;
752                 }
753
754                 if (set_state (*tree.root(), Stateful::loading_state_version)) {
755                         error << string_compose(_("user ui configuration file \"%1\" not loaded successfully."), rcfile) << endmsg;
756                         return -1;
757                 }
758
759                 _dirty = false;
760         }
761
762         if (!found) {
763                 error << _("could not find any ui configuration file, canvas will look broken.") << endmsg;
764         }
765
766         return 0;
767 }
768
769 int
770 UIConfiguration::save_state()
771 {
772         XMLTree tree;
773
774         std::string rcfile(user_config_directory());
775         rcfile = Glib::build_filename (rcfile, ui_config_file_name);
776
777         // this test seems bogus?
778         if (rcfile.length()) {
779                 tree.set_root (&get_state());
780                 if (!tree.write (rcfile.c_str())){
781                         error << string_compose (_("Config file %1 not saved"), rcfile) << endmsg;
782                         return -1;
783                 }
784         }
785
786         _dirty = false;
787
788         return 0;
789 }
790
791 XMLNode&
792 UIConfiguration::get_state ()
793 {
794         XMLNode* root;
795         LocaleGuard lg (X_("POSIX"));
796
797         root = new XMLNode("Ardour");
798
799         root->add_child_nocopy (get_variables ("UI"));
800         root->add_child_nocopy (get_variables ("Canvas"));
801
802         if (_extra_xml) {
803                 root->add_child_copy (*_extra_xml);
804         }
805
806         return *root;
807 }
808
809 XMLNode&
810 UIConfiguration::get_variables (std::string which_node)
811 {
812         XMLNode* node;
813         LocaleGuard lg (X_("POSIX"));
814
815         node = new XMLNode (which_node);
816
817 #undef  UI_CONFIG_VARIABLE
818 #undef  CANVAS_STRING_VARIABLE
819 #undef  CANVAS_FONT_VARIABLE
820 #undef  CANVAS_BASE_COLOR
821 #define UI_CONFIG_VARIABLE(Type,var,Name,value) if (node->name() == "UI") { var.add_to_node (*node); }
822 #define CANVAS_STRING_VARIABLE(var,Name) if (node->name() == "Canvas") { var.add_to_node (*node); }
823 #define CANVAS_FONT_VARIABLE(var,Name) if (node->name() == "Canvas") { var.add_to_node (*node); }
824 #define CANVAS_BASE_COLOR(var,Name,val) if (node->name() == "Canvas") { var.add_to_node (*node); }
825 #include "ui_config_vars.h"
826 #include "canvas_vars.h"
827 #include "base_colors.h"
828 #undef  UI_CONFIG_VARIABLE
829 #undef  CANVAS_STRING_VARIABLE
830 #undef  CANVAS_FONT_VARIABLE
831 #undef  CANVAS_BASE_COLOR
832
833         return *node;
834 }
835
836 int
837 UIConfiguration::set_state (const XMLNode& root, int /*version*/)
838 {
839         if (root.name() != "Ardour") {
840                 return -1;
841         }
842
843         Stateful::save_extra_xml (root);
844
845         XMLNodeList nlist = root.children();
846         XMLNodeConstIterator niter;
847         XMLNode *node;
848
849         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
850
851                 node = *niter;
852
853                 if (node->name() == "Canvas" ||  node->name() == "UI") {
854                         set_variables (*node);
855
856                 }
857         }
858
859         return 0;
860 }
861
862
863 void
864 UIConfiguration::set_variables (const XMLNode& node)
865 {
866 #undef  UI_CONFIG_VARIABLE
867 #define UI_CONFIG_VARIABLE(Type,var,name,val) \
868          if (var.set_from_node (node)) { \
869                  ParameterChanged (name); \
870                  }
871 #define CANVAS_STRING_VARIABLE(var,name)        \
872          if (var.set_from_node (node)) { \
873                  ParameterChanged (name); \
874                  }
875 #define CANVAS_FONT_VARIABLE(var,name)  \
876          if (var.set_from_node (node)) { \
877                  ParameterChanged (name); \
878                  }
879 #include "ui_config_vars.h"
880 #include "canvas_vars.h"
881 #undef  UI_CONFIG_VARIABLE
882 #undef  CANVAS_STRING_VARIABLE
883 #undef  CANVAS_FONT_VARIABLE
884
885         /* Reset base colors */
886
887 #undef  CANVAS_BASE_COLOR
888 #define CANVAS_BASE_COLOR(var,name,val) \
889         var.set_from_node (node);
890 #include "base_colors.h"
891 #undef CANVAS_BASE_COLOR        
892
893 }
894
895 void
896 UIConfiguration::set_dirty ()
897 {
898         _dirty = true;
899 }
900
901 bool
902 UIConfiguration::dirty () const
903 {
904         return _dirty;
905 }
906
907 ArdourCanvas::Color
908 UIConfiguration::base_color_by_name (const std::string& name) const
909 {
910         map<std::string,ColorVariable<Color>* >::const_iterator i = configurable_colors.find (name);
911
912         if (i != configurable_colors.end()) {
913                 return i->second->get();
914         }
915
916 #if 0 // yet unsed experimental style postfix
917         /* Idea: use identical colors but different font/sizes
918          * for variants of the same 'widget'.
919          *
920          * example:
921          *  set_name("mute button");  // in route_ui.cc
922          *  set_name("mute button small"); // in mixer_strip.cc
923          *
924          * ardour3_widget_list.rc:
925          *  widget "*mute button" style:highest "small_button"
926          *  widget "*mute button small" style:highest "very_small_text"
927          *
928          * both use color-schema of defined in
929          *   BUTTON_VARS(MuteButton, "mute button")
930          *
931          * (in this particular example the widgets should be packed
932          * vertically shinking the mixer strip ones are currently not)
933          */
934         const size_t name_len = name.size();
935         const size_t name_sep = name.find(':');
936         for (i = configurable_colors.begin(); i != configurable_colors.end(), name_sep != string::npos; ++i) {
937                 const size_t cmp_len = i->first.size();
938                 const size_t cmp_sep = i->first.find(':');
939                 if (cmp_len >= name_len || cmp_sep == string::npos) continue;
940                 if (name.substr(name_sep) != i->first.substr(cmp_sep)) continue;
941                 if (name.substr(0, cmp_sep) != i->first.substr(0, cmp_sep)) continue;
942                 return i->second->get();
943         }
944 #endif
945
946         cerr << string_compose (_("Color %1 not found"), name) << endl;
947         return RGBA_TO_UINT (g_random_int()%256,g_random_int()%256,g_random_int()%256,0xff);
948 }
949
950 ArdourCanvas::Color
951 UIConfiguration::color (const std::string& name) const
952 {
953         map<string,string>::const_iterator e = color_aliases.find (name);
954
955         if (e != color_aliases.end ()) {
956                 map<string,HSV>::const_iterator ac = actual_colors.find (e->second);
957                 if (ac != actual_colors.end()) {
958                         return ac->second;
959                 }
960         } 
961
962         cerr << string_compose (_("Color %1 not found"), name) << endl;
963
964         return rgba_to_color ((g_random_int()%256)/255.0,
965                               (g_random_int()%256)/255.0,
966                               (g_random_int()%256)/255.0,
967                               0xff);
968 }
969
970 ArdourCanvas::HSV
971 UIConfiguration::RelativeHSV::get() const
972 {
973         HSV base (UIConfiguration::instance()->base_color_by_name (base_color));
974         
975         /* this operation is a little wierd. because of the way we originally
976          * computed the alpha specification for the modifiers used here
977          * we need to reset base's alpha to zero before adding the modifier.
978          */
979
980         base.a = 0.0;
981
982         HSV self (base + modifier);
983         
984         if (quantized_hue >= 0.0) {
985                 self.h = quantized_hue;
986         }
987         
988         return self;
989 }
990
991 void
992 UIConfiguration::color_compute ()
993 {
994         using namespace ArdourCanvas;
995
996         map<std::string,ColorVariable<Color>* >::iterator f;
997         map<std::string,HSV*>::iterator v;
998
999         /* now compute distances */
1000
1001         cerr << "Attempt to reduce " << relative_colors.size() << endl;
1002
1003         map<std::string,RelativeHSV>::iterator current_color;
1004         
1005         color_aliases.clear ();
1006         
1007         actual_colors.clear ();
1008
1009         for (current_color = relative_colors.begin(); current_color != relative_colors.end(); ++current_color) {
1010
1011                 map<std::string,HSV>::iterator possible_match;
1012                 std::string equivalent_name;
1013                 bool matched;
1014
1015                 matched = false;
1016
1017                 for (possible_match = actual_colors.begin(); possible_match != actual_colors.end(); ++possible_match) {
1018
1019                         HSV a (current_color->second.get());
1020                         HSV b (possible_match->second);
1021                 
1022                         /* This uses perceptual distance to find visually
1023                          * similar colors.
1024                          */
1025
1026                         if (a.distance (b) < 6.0) {
1027                                 matched = true;
1028                                 break;
1029                         }
1030                 }
1031
1032                 if (!matched) {
1033
1034                         /* color does not match any other, generate a generic
1035                          * name and store two aliases.
1036                          */
1037
1038                         string alias = string_compose ("color %1", actual_colors.size() + 1);
1039                         //cerr << alias << " == " << current_color->second.base_color 
1040                         // << " [ " << HSV (base_color_by_name (current_color->second.base_color)) << "] + " 
1041                         // << current_color->second.modifier << endl;
1042                         actual_colors.insert (make_pair (alias, current_color->second.get()));
1043                         color_aliases.insert (make_pair (current_color->first, alias));
1044
1045                 } else {
1046
1047                         /* this color was within the JND CIE76 distance of
1048                          * another, so throw it away.
1049                          */
1050                         
1051                         color_aliases.insert (make_pair (current_color->first, possible_match->first));
1052                 }
1053         }
1054
1055         cerr << "Ended with " << actual_colors.size() << " colors" << endl;
1056 }