3 * Copyright (C) 2007-2011 Krzysztof Foltman
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
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 GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 USA
21 #include <calf/ctl_led.h>
22 #include <calf/ctl_vumeter.h>
23 #include <calf/giface.h>
25 #include <calf/custom_ctl.h>
26 #include <calf/preset.h>
27 #include <calf/gtk_main_win.h>
28 #include <calf/jackhost.h>
30 using namespace calf_plugins
;
33 gtk_main_window::gtk_main_window()
39 progress_window
= NULL
;
42 static const char *ui_xml
=
45 " <menu action=\"FileMenuAction\">\n"
46 " <menuitem action=\"FileOpen\"/>\n"
47 " <menuitem action=\"FileSave\"/>\n"
48 " <menuitem action=\"FileSaveAs\"/>\n"
50 " <menuitem action=\"FileReorder\"/>\n"
52 " <menuitem action=\"FilePreferences\"/>\n"
54 " <menuitem action=\"FileQuit\"/>\n"
56 " <menu action=\"AddPluginMenuAction\" />\n"
61 const GtkActionEntry
gtk_main_window::actions
[] = {
62 { "FileMenuAction", NULL
, "_File", NULL
, "File-related operations", NULL
},
63 { "FileOpen", GTK_STOCK_OPEN
, "_Open", "<Ctrl>O", "Open a rack file", (GCallback
)on_open_action
},
64 { "FileSave", GTK_STOCK_SAVE
, "_Save", "<Ctrl>S", "Save a rack file", (GCallback
)on_save_action
},
65 { "FileSaveAs", GTK_STOCK_SAVE_AS
, "Save _as...", NULL
, "Save a rack file as", (GCallback
)on_save_as_action
},
66 { "HostMenuAction", NULL
, "_Host", NULL
, "Host-related operations", NULL
},
67 { "AddPluginMenuAction", NULL
, "_Add plugin", NULL
, "Add a plugin to the rack", NULL
},
68 { "FileReorder", NULL
, "_Reorder plugins", NULL
, "Reorder plugins to minimize latency (experimental)", (GCallback
)on_reorder_action
},
69 { "FilePreferences", GTK_STOCK_PREFERENCES
, "_Preferences...", NULL
, "Adjust preferences", (GCallback
)on_preferences_action
},
70 { "FileQuit", GTK_STOCK_QUIT
, "_Quit", "<Ctrl>Q", "Exit application", (GCallback
)on_exit_action
},
73 void gtk_main_window::on_open_action(GtkWidget
*widget
, gtk_main_window
*main
)
78 void gtk_main_window::on_save_action(GtkWidget
*widget
, gtk_main_window
*main
)
83 void gtk_main_window::on_save_as_action(GtkWidget
*widget
, gtk_main_window
*main
)
88 void gtk_main_window::on_reorder_action(GtkWidget
*widget
, gtk_main_window
*main
)
90 main
->owner
->reorder_plugins();
93 void gtk_main_window::on_preferences_action(GtkWidget
*widget
, gtk_main_window
*main
)
95 GtkBuilder
*prefs_builder
= gtk_builder_new();
97 const gchar
*objects
[] = { "preferences", NULL
};
98 if (!gtk_builder_add_objects_from_file(prefs_builder
, PKGLIBDIR
"/calf-gui.xml", (gchar
**)objects
, &error
))
100 g_warning("Cannot load preferences dialog: %s", error
->message
);
102 g_object_unref(G_OBJECT(prefs_builder
));
105 GtkWidget
*preferences_dlg
= GTK_WIDGET(gtk_builder_get_object(prefs_builder
, "preferences"));
106 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(prefs_builder
, "show-rack-ears")), main
->get_config()->rack_ears
);
107 gtk_spin_button_set_range(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "rack-float")), 0, 1);
108 gtk_spin_button_set_range(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "float-size")), 1, 32);
109 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "rack-float")), 1, 1);
110 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "float-size")), 1, 1);
111 gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "rack-float")), main
->get_config()->rack_float
);
112 gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "float-size")), main
->get_config()->float_size
);
113 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(prefs_builder
, "show-vu-meters")), main
->get_config()->vu_meters
);
114 int response
= gtk_dialog_run(GTK_DIALOG(preferences_dlg
));
115 if (response
== GTK_RESPONSE_OK
)
117 main
->get_config()->rack_ears
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(prefs_builder
, "show-rack-ears")));
118 main
->get_config()->rack_float
= gtk_spin_button_get_value(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "rack-float")));
119 main
->get_config()->float_size
= gtk_spin_button_get_value(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "float-size")));
120 main
->get_config()->vu_meters
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(prefs_builder
, "show-vu-meters")));
121 main
->get_config()->save(main
->get_config_db());
123 gtk_widget_destroy(preferences_dlg
);
124 g_object_unref(G_OBJECT(prefs_builder
));
127 void gtk_main_window::on_exit_action(GtkWidget
*widget
, gtk_main_window
*main
)
129 gtk_widget_destroy(GTK_WIDGET(main
->toplevel
));
132 void gtk_main_window::add_plugin(jack_host
*plugin
)
136 plugin_strip
*strip
= create_strip(plugin
);
137 plugins
[plugin
] = strip
;
138 update_strip(plugin
);
142 plugin_queue
.push_back(plugin
);
143 //plugins[plugin] = NULL;
147 void gtk_main_window::del_plugin(plugin_ctl_iface
*plugin
)
149 if (!plugins
.count(plugin
))
151 plugin_strip
*strip
= plugins
[plugin
];
153 strip
->gui_win
->close();
154 vector
<GtkWidget
*> to_destroy
;
155 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
)
157 if (i
->second
== strip
)
158 to_destroy
.push_back(i
->second
->strip_table
);
159 else if(i
->second
->id
> strip
->id
)
162 for (unsigned int i
= 0; i
< to_destroy
.size(); i
++)
163 gtk_container_remove(GTK_CONTAINER(strips_table
), to_destroy
[i
]);
164 plugins
.erase(plugin
);
168 void gtk_main_window::set_window(plugin_ctl_iface
*plugin
, plugin_gui_window
*gui_win
)
170 if (!plugins
.count(plugin
))
172 plugin_strip
*strip
= plugins
[plugin
];
175 strip
->gui_win
= gui_win
;
177 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(strip
->button
), gui_win
!= NULL
);
180 void gtk_main_window::refresh_all_presets(bool builtin_too
)
182 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
)
184 if (i
->second
&& i
->second
->gui_win
) {
186 i
->second
->gui_win
->fill_gui_presets(true, ch
);
187 i
->second
->gui_win
->fill_gui_presets(false, ch
);
193 gui_button_pressed(GtkWidget
*button
, plugin_strip
*strip
)
195 GtkToggleButton
*tb
= GTK_TOGGLE_BUTTON(button
);
196 if ((gtk_toggle_button_get_active(tb
) != 0) == (strip
->gui_win
!= NULL
))
198 if (strip
->gui_win
) {
199 strip
->gui_win
->close();
200 strip
->gui_win
= NULL
;
202 strip
->main_win
->open_gui(strip
->plugin
);
207 connect_button_pressed(GtkWidget
*button
, plugin_strip
*strip
)
209 //GtkToggleButton *tb = GTK_TOGGLE_BUTTON(button);
210 if (strip
->connector
) {
211 strip
->connector
->close();
212 strip
->connector
= NULL
;
214 strip
->connector
= new calf_connector(strip
);
219 extra_button_pressed(GtkWidget
*button
, plugin_strip
*strip
)
221 if (strip
->connector
)
222 strip
->connector
->close();
223 strip
->main_win
->owner
->remove_plugin(strip
->plugin
);
227 void gtk_main_window::show_rack_ears(bool show
)
229 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
)
233 gtk_widget_show(i
->second
->leftBox
);
234 gtk_widget_show(i
->second
->rightBox
);
238 gtk_widget_hide(i
->second
->leftBox
);
239 gtk_widget_hide(i
->second
->rightBox
);
244 void gtk_main_window::show_vu_meters(bool show
)
246 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
)
250 if (i
->second
->inBox
)
251 gtk_widget_show(i
->second
->inBox
);
252 if (i
->second
->outBox
)
253 gtk_widget_show(i
->second
->outBox
);
257 if (i
->second
->inBox
)
258 gtk_widget_hide(i
->second
->inBox
);
259 if (i
->second
->outBox
)
260 gtk_widget_hide(i
->second
->outBox
);
265 plugin_strip
*gtk_main_window::create_strip(jack_host
*plugin
)
267 plugin_strip
*strip
= new plugin_strip
;
268 strip
->main_win
= this;
269 strip
->plugin
= plugin
;
270 strip
->gui_win
= NULL
;
271 strip
->connector
= NULL
;
272 strip
->id
= plugins
.size();
274 GtkAttachOptions ao
= (GtkAttachOptions
)(GTK_EXPAND
| GTK_FILL
);
276 strip
->strip_table
= gtk_table_new(6, 4, FALSE
);
277 gtk_table_set_col_spacings(GTK_TABLE(strip
->strip_table
), 0);
278 gtk_table_set_row_spacings(GTK_TABLE(strip
->strip_table
), 0);
281 // g_object_get(G_OBJECT(strips_table), "n-rows", &row, "n-columns", &cols, NULL);
282 // gtk_table_resize(GTK_TABLE(strips_table), row + 4, cols);
283 // printf("%03d %03d", row, cols);
284 // images for left side
285 GtkWidget
*nwImg
= gtk_image_new_from_file(PKGLIBDIR
"/side_d_nw.png");
286 GtkWidget
*swImg
= gtk_image_new_from_file(PKGLIBDIR
"/side_d_sw.png");
287 GtkWidget
*wImg
= gtk_image_new_from_file(PKGLIBDIR
"/side_d_w.png");
288 gtk_widget_set_size_request(GTK_WIDGET(wImg
), 56, 1);
290 // images for right side
291 GtkWidget
*neImg
= gtk_image_new_from_file(PKGLIBDIR
"/side_d_ne.png");
292 GtkWidget
*seImg
= gtk_image_new_from_file(PKGLIBDIR
"/side_d_se.png");
293 GtkWidget
*eImg
= gtk_image_new_from_file(PKGLIBDIR
"/side_d_e.png");
294 gtk_widget_set_size_request(GTK_WIDGET(eImg
), 56, 1);
297 GtkWidget
*leftBox
= gtk_vbox_new(FALSE
, 0);
298 gtk_box_pack_start(GTK_BOX(leftBox
), GTK_WIDGET(nwImg
), FALSE
, FALSE
, 0);
299 gtk_box_pack_start(GTK_BOX(leftBox
), GTK_WIDGET(wImg
), TRUE
, TRUE
, 0);
300 gtk_box_pack_end(GTK_BOX(leftBox
), GTK_WIDGET(swImg
), FALSE
, FALSE
, 0);
301 gtk_widget_show_all(GTK_WIDGET(leftBox
));
302 if (!get_config()->rack_ears
)
303 gtk_widget_hide(GTK_WIDGET(leftBox
));
304 gtk_table_attach(GTK_TABLE(strip
->strip_table
), leftBox
, 0, 1, row
, row
+ 4, (GtkAttachOptions
)(0), (GtkAttachOptions
)(GTK_EXPAND
| GTK_FILL
), 0, 0);
307 GtkWidget
*rightBox
= gtk_vbox_new(FALSE
, 0);
308 gtk_box_pack_start(GTK_BOX(rightBox
), GTK_WIDGET(neImg
), FALSE
, FALSE
, 0);
309 gtk_box_pack_start(GTK_BOX(rightBox
), GTK_WIDGET(eImg
), TRUE
, TRUE
, 0);
310 gtk_box_pack_end(GTK_BOX(rightBox
), GTK_WIDGET(seImg
), FALSE
, FALSE
, 0);
311 gtk_widget_show_all(GTK_WIDGET(rightBox
));
312 if (!get_config()->rack_ears
)
313 gtk_widget_hide(GTK_WIDGET(rightBox
));
314 gtk_table_attach(GTK_TABLE(strip
->strip_table
), rightBox
, 5, 6, row
, row
+ 4, (GtkAttachOptions
)(0), (GtkAttachOptions
)(GTK_EXPAND
| GTK_FILL
), 0, 0);
316 strip
->leftBox
= leftBox
;
317 strip
->rightBox
= rightBox
;
321 GtkWidget
*topImg
= gtk_image_new_from_file(PKGLIBDIR
"/light_top.png");
322 gtk_widget_set_size_request(GTK_WIDGET(topImg
), 1, 1);
323 gtk_table_attach(GTK_TABLE(strip
->strip_table
), topImg
, 1, 5, row
, row
+ 1, (GtkAttachOptions
)(GTK_EXPAND
| GTK_FILL
| GTK_SHRINK
), (GtkAttachOptions
)(0), 0, 0);
324 gtk_widget_show(topImg
);
325 strip
->name
= topImg
;
329 const plugin_metadata_iface
*metadata
= plugin
->get_metadata_iface();
330 GtkWidget
*title
= gtk_label_new(NULL
);
331 gtk_widget_set_name(GTK_WIDGET(title
), "Calf-Rack-Title");
332 gtk_label_set_markup(GTK_LABEL(title
), metadata
->get_label());
333 gtk_label_set_justify(GTK_LABEL(title
), GTK_JUSTIFY_RIGHT
);
334 GtkWidget
* align
= gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
335 gtk_container_add(GTK_CONTAINER(align
), title
);
336 gtk_table_attach(GTK_TABLE(strip
->strip_table
), align
, 1, 2, row
, row
+ 1, (GtkAttachOptions
)(GTK_FILL
), (GtkAttachOptions
)(GTK_FILL
) , 10, 0);
337 gtk_widget_show_all(align
);
340 GtkWidget
*label
= calf_toggle_button_new("Edit");
341 strip
->button
= label
;
342 gtk_widget_set_size_request(GTK_WIDGET(label
), 80, -1);
343 g_signal_connect(GTK_OBJECT(label
), "toggled", G_CALLBACK(gui_button_pressed
),
344 (plugin_ctl_iface
*)strip
);
345 gtk_widget_show(strip
->button
);
348 GtkWidget
*con
= calf_toggle_button_new("Connect");
350 gtk_widget_set_size_request(GTK_WIDGET(con
), -1, -1);
351 g_signal_connect(GTK_OBJECT(con
), "toggled", G_CALLBACK(connect_button_pressed
),
352 (plugin_ctl_iface
*)strip
);
353 gtk_widget_show(strip
->con
);
356 GtkWidget
*extra
= calf_button_new("Remove");
357 strip
->extra
= extra
;
358 //gtk_widget_set_size_request(GTK_WIDGET(extra), 100, -1);
359 g_signal_connect(GTK_OBJECT(extra
), "clicked", G_CALLBACK(extra_button_pressed
),
360 (plugin_ctl_iface
*)strip
);
361 gtk_widget_show(strip
->extra
);
364 GtkWidget
*buttonBox
= gtk_hbox_new(FALSE
, 5);
365 gtk_box_pack_start(GTK_BOX(buttonBox
), GTK_WIDGET(strip
->button
), FALSE
, FALSE
, 0);
366 gtk_box_pack_start(GTK_BOX(buttonBox
), GTK_WIDGET(strip
->con
), FALSE
, FALSE
, 0);
367 gtk_box_pack_start(GTK_BOX(buttonBox
), GTK_WIDGET(strip
->extra
), FALSE
, FALSE
, 0);
368 gtk_table_attach(GTK_TABLE(strip
->strip_table
), buttonBox
, 1, 2, row
+ 1, row
+ 2, (GtkAttachOptions
)0, (GtkAttachOptions
)0, 10, 10);
369 gtk_widget_show(buttonBox
);
372 if (metadata
->get_midi()) {
373 label
= calf_led_new();
374 GtkWidget
*midiBox
= gtk_vbox_new(FALSE
, 1);
375 gtk_box_pack_start(GTK_BOX(midiBox
), GTK_WIDGET(gtk_label_new("Midi")), FALSE
, FALSE
, 0);
376 gtk_box_pack_start(GTK_BOX(midiBox
), GTK_WIDGET(label
), FALSE
, FALSE
, 0);
377 gtk_table_attach(GTK_TABLE(strip
->strip_table
), midiBox
, 2, 3, row
, row
+ 1, (GtkAttachOptions
)0, (GtkAttachOptions
)0, 5, 3);
378 gtk_widget_set_size_request(GTK_WIDGET(label
), 25, 25);
379 strip
->midi_in
= label
;
380 gtk_widget_show_all(midiBox
);
382 label
= gtk_label_new("");
383 gtk_table_attach(GTK_TABLE(strip
->strip_table
), label
, 2, 3, row
, row
+ 1, GTK_FILL
, GTK_EXPAND
, 5, 3);
384 gtk_widget_set_size_request(GTK_WIDGET(label
), 25, 25);
385 strip
->midi_in
= label
;
386 gtk_widget_show(strip
->midi_in
);
388 strip
->midi_in
= label
;
391 strip
->outBox
= NULL
;
392 strip
->audio_in
.clear();
393 strip
->audio_out
.clear();
395 if (metadata
->get_input_count()) {
397 GtkWidget
*inBox
= gtk_vbox_new(FALSE
, 1);
399 gtk_box_pack_start(GTK_BOX(inBox
), gtk_label_new("Audio In"),FALSE
, FALSE
, 0);
401 for (int i
= 0; i
< metadata
->get_input_count(); i
++)
403 label
= calf_vumeter_new();
404 calf_vumeter_set_falloff(CALF_VUMETER(label
), 2.5);
405 calf_vumeter_set_hold(CALF_VUMETER(label
), 1.5);
406 calf_vumeter_set_width(CALF_VUMETER(label
), 100);
407 calf_vumeter_set_height(CALF_VUMETER(label
), 12);
408 calf_vumeter_set_position(CALF_VUMETER(label
), 2);
409 gtk_box_pack_start(GTK_BOX(inBox
), label
, TRUE
, TRUE
, 0);
410 strip
->audio_in
.push_back(label
);
413 strip
->inBox
= gtk_alignment_new(0.f
, 0.f
, 1.f
, 0.f
);
414 gtk_container_add(GTK_CONTAINER(strip
->inBox
), inBox
);
416 gtk_table_attach(GTK_TABLE(strip
->strip_table
), strip
->inBox
, 3, 4, row
, row
+ 1, ao
, ao
, 5, 3);
418 if (get_config()->vu_meters
)
419 gtk_widget_show_all(strip
->inBox
);
421 gtk_widget_set_size_request(GTK_WIDGET(strip
->inBox
), 120, -1);
424 if (metadata
->get_output_count()) {
426 GtkWidget
*outBox
= gtk_vbox_new(FALSE
, 1);
428 gtk_box_pack_start(GTK_BOX(outBox
), gtk_label_new("Audio Out"),TRUE
, TRUE
, 0);
430 for (int i
= 0; i
< metadata
->get_output_count(); i
++)
432 label
= calf_vumeter_new();
433 calf_vumeter_set_falloff(CALF_VUMETER(label
), 2.5);
434 calf_vumeter_set_hold(CALF_VUMETER(label
), 1.5);
435 calf_vumeter_set_width(CALF_VUMETER(label
), 100);
436 calf_vumeter_set_height(CALF_VUMETER(label
), 12);
437 calf_vumeter_set_position(CALF_VUMETER(label
), 2);
438 gtk_box_pack_start(GTK_BOX(outBox
), label
,FALSE
, FALSE
, 0);
439 strip
->audio_out
.push_back(label
);
442 strip
->outBox
= gtk_alignment_new(0.f
, 0.f
, 1.f
, 0.f
);
443 gtk_container_add(GTK_CONTAINER(strip
->outBox
), outBox
);
445 gtk_table_attach(GTK_TABLE(strip
->strip_table
), strip
->outBox
, 4, 5, row
, row
+ 1, ao
, ao
, 5, 3);
447 if (get_config()->vu_meters
)
448 gtk_widget_show_all(strip
->outBox
);
450 gtk_widget_set_size_request(GTK_WIDGET(strip
->outBox
), 120, -1);
453 // other stuff bottom right
454 GtkWidget
*paramBox
= gtk_hbox_new(FALSE
, 0);
456 GtkWidget
*logoImg
= gtk_image_new_from_file(PKGLIBDIR
"/logo_button.png");
457 gtk_box_pack_end(GTK_BOX(paramBox
), GTK_WIDGET(logoImg
), TRUE
, TRUE
, 0);
459 gtk_table_attach(GTK_TABLE(strip
->strip_table
), paramBox
, 3, 5, row
+ 1, row
+ 2, (GtkAttachOptions
)(GTK_EXPAND
| GTK_FILL
), (GtkAttachOptions
)(GTK_EXPAND
| GTK_FILL
), 10, 0);
460 gtk_widget_show_all(GTK_WIDGET(paramBox
));
465 GtkWidget
*botImg
= gtk_image_new_from_file(PKGLIBDIR
"/light_bottom.png");
466 gtk_widget_set_size_request(GTK_WIDGET(botImg
), 1, 1);
467 gtk_table_attach(GTK_TABLE(strip
->strip_table
), botImg
, 1, 5, row
, row
+ 1, (GtkAttachOptions
)(GTK_EXPAND
| GTK_FILL
| GTK_SHRINK
), (GtkAttachOptions
)(0), 0, 0);
468 gtk_widget_show(botImg
);
470 gtk_widget_show(GTK_WIDGET(strip
->strip_table
));
475 void gtk_main_window::sort_strips()
477 if(plugins
.size() <= 0) return;
478 int rack_float
= get_config()->rack_float
; // 0=horiz, 1=vert
479 int float_size
= get_config()->float_size
; // amout of rows/cols before line break
481 gtk_table_resize(GTK_TABLE(strips_table
), (int)(plugins
.size() / float_size
+ 1), float_size
);
482 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
)
484 switch (rack_float
) {
487 posx
= i
->second
->id
% float_size
;
488 posy
= (int)(i
->second
->id
/ float_size
);
491 posy
= i
->second
->id
% float_size
;
492 posx
= (int)(i
->second
->id
/ float_size
);
496 if(i
->second
->strip_table
->parent
!= NULL
) {
498 g_object_ref(i
->second
->strip_table
);
499 gtk_container_remove(GTK_CONTAINER(strips_table
), GTK_WIDGET(i
->second
->strip_table
));
501 gtk_table_attach(GTK_TABLE(strips_table
), i
->second
->strip_table
, posx
, posx
+ 1, posy
, posy
+ 1, (GtkAttachOptions
)(GTK_EXPAND
| GTK_FILL
| GTK_SHRINK
), (GtkAttachOptions
)(GTK_EXPAND
| GTK_FILL
| GTK_SHRINK
), 0, 0);
502 if(rem
) g_object_unref(i
->second
->strip_table
);
506 void gtk_main_window::update_strip(plugin_ctl_iface
*plugin
)
508 // plugin_strip *strip = plugins[plugin];
513 void gtk_main_window::open_gui(plugin_ctl_iface
*plugin
)
515 plugin_gui_window
*gui_win
= new plugin_gui_window(this, this);
516 std::string title
= "Calf - ";
517 gui_win
->create(plugin
, (title
+ plugin
->get_metadata_iface()->get_label()).c_str(), plugin
->get_metadata_iface()->get_id()); //(owner->get_client_name() + " - " + plugin->get_metadata_iface()->get_label()).c_str(), plugin->get_metadata_iface()->get_id());
518 gtk_widget_show(GTK_WIDGET(gui_win
->toplevel
));
519 plugins
[plugin
]->gui_win
= gui_win
;
522 static const char *plugin_pre_xml
=
525 " <menu action=\"AddPluginMenuAction\">\n"
526 " <placeholder name=\"plugin\">\n";
528 static const char *plugin_post_xml
=
534 #define countof(X) ( (size_t) ( sizeof(X)/sizeof*(X) ) )
535 void gtk_main_window::register_icons()
537 const char *names
[]={"Allpass", "Amplifier", "Analyser",
538 "Bandpass", "Chorus", "Comb", "Compressor",
539 "Constant", "Converter", "Delay", "Distortion",
540 "Dynamics", "Envelope", "EQ", "Expander",
541 "Filter", "Flanger", "Function", "Gate",
542 "Generator", "Highpass", "Instrument",
543 "Limiter", "Mixer", "Modulator", "MultiEQ",
544 "Oscillator", "ParaEQ", "Phaser", "Pitch",
545 "Reverb", "Simulator", "Spatial", "Spectral",
546 "Utility", "Waveshaper"};
547 factory
= gtk_icon_factory_new ();
548 for (size_t i
= 0; i
< countof(names
); i
++) {
550 strcpy(name
, "LV2-");
551 strcat(name
, names
[i
]);
552 if (!gtk_icon_factory_lookup(factory
, name
)) {
553 std::string iname
= std::string(PKGLIBDIR
) + "icons/LV2/" + names
[i
] + ".svg";
554 GdkPixbuf
*buf
= gdk_pixbuf_new_from_file_at_size(iname
.c_str(), 64, 64, NULL
);
555 GtkIconSet
*icon
= gtk_icon_set_new_from_pixbuf(buf
);
556 gtk_icon_factory_add (factory
, name
, icon
);
557 gtk_icon_set_unref(icon
);
561 gtk_icon_factory_add_default(factory
);
564 void gtk_main_window::add_plugin_action(GtkWidget
*src
, gpointer data
)
566 add_plugin_params
*app
= (add_plugin_params
*)data
;
567 app
->main_win
->new_plugin(app
->name
.c_str());
570 static void action_destroy_notify(gpointer data
)
572 delete (gtk_main_window::add_plugin_params
*)data
;
575 std::string
gtk_main_window::make_plugin_list(GtkActionGroup
*actions
)
577 string s
= plugin_pre_xml
;
578 const plugin_registry::plugin_vector
&plugins
= plugin_registry::instance().get_all();
579 std::string type
= "";
580 std::string tmp
= "";
581 std::string last
= "";
582 unsigned int count
= 0;
583 unsigned int size
= plugins
.size();
585 const plugin_metadata_iface
*p
= plugins
[0];
587 for(unsigned int i
= 0; i
<= size
; i
++)
591 type
= (p
->get_plugin_info()).plugin_type
;
592 type
= type
.substr(0, type
.length() - 6);
594 if (type
!= last
or i
>= size
or !i
) {
598 s
+= "<menu action='" + last
+ "'>" + tmp
+ "</menu>";
599 GtkAction
*a
= gtk_action_new(last
.c_str(), last
.c_str(), NULL
, ("LV2-" + last
).c_str());
600 gtk_action_group_add_action(actions
, a
);
610 std::string action
= "Add" + string(p
->get_id()) + "Action";
611 std::string stock
= "LV2-" + type
;
613 // add lv2 stock icons to plug-ins and not just to menus
614 // GTK_STOCK_OPEN -> ("LV2_" + type).c_str()
615 GtkActionEntry ae
= { action
.c_str(), stock
.c_str(), p
->get_label(), NULL
, NULL
, (GCallback
)add_plugin_action
};
616 gtk_action_group_add_actions_full(actions
, &ae
, 1, (gpointer
)new add_plugin_params(this, p
->get_id()), action_destroy_notify
);
617 tmp
+= string("<menuitem always-show-image=\"true\" action=\"") + action
+ "\" />";
621 return s
+ plugin_post_xml
;
624 static void window_destroy_cb(GtkWindow
*window
, gpointer data
)
626 ((gtk_main_window
*)data
)->owner
->on_main_window_destroy();
629 void gtk_main_window::create()
632 toplevel
= GTK_WINDOW(gtk_window_new (GTK_WINDOW_TOPLEVEL
));
633 std::string title
= "Calf JACK Host";
634 gtk_window_set_title(toplevel
, title
.c_str()); //(owner->get_client_name() + " - Calf JACK Host").c_str());
635 gtk_widget_set_name(GTK_WIDGET(toplevel
), "Calf-Rack");
636 gtk_window_set_icon_name(toplevel
, "calf");
637 gtk_window_set_role(toplevel
, "calf_rack");
640 gtk_window_set_resizable(toplevel
, false);
642 all_vbox
= gtk_vbox_new(0, FALSE
);
644 ui_mgr
= gtk_ui_manager_new();
645 std_actions
= gtk_action_group_new("default");
646 gtk_action_group_add_actions(std_actions
, actions
, sizeof(actions
)/sizeof(actions
[0]), this);
647 GError
*error
= NULL
;
648 gtk_ui_manager_insert_action_group(ui_mgr
, std_actions
, 0);
649 gtk_ui_manager_add_ui_from_string(ui_mgr
, ui_xml
, -1, &error
);
650 gtk_box_pack_start(GTK_BOX(all_vbox
), gtk_ui_manager_get_widget(ui_mgr
, "/ui/menubar"), false, false, 0);
652 gtk_widget_set_size_request(GTK_WIDGET(gtk_ui_manager_get_widget(ui_mgr
, "/ui/menubar")), 640, -1);
654 gtk_widget_set_name(GTK_WIDGET(gtk_ui_manager_get_widget(ui_mgr
, "/ui/menubar")), "Calf-Menu");
656 plugin_actions
= gtk_action_group_new("plugins");
657 string plugin_xml
= make_plugin_list(plugin_actions
);
658 gtk_ui_manager_insert_action_group(ui_mgr
, plugin_actions
, 0);
659 gtk_ui_manager_add_ui_from_string(ui_mgr
, plugin_xml
.c_str(), -1, &error
);
661 strips_table
= gtk_table_new(0, 1, FALSE
);
662 gtk_table_set_col_spacings(GTK_TABLE(strips_table
), 0);
663 gtk_table_set_row_spacings(GTK_TABLE(strips_table
), 0);
665 for(GList
*p
= GTK_TABLE(strips_table
)->children
; p
!= NULL
; p
= p
->next
)
667 GtkTableChild
*c
= (GtkTableChild
*)p
->data
;
668 if (c
->top_attach
== 0) {
669 gtk_misc_set_alignment(GTK_MISC(c
->widget
), 0.5, 0);
672 for (std::vector
<jack_host
*>::iterator i
= plugin_queue
.begin(); i
!= plugin_queue
.end(); ++i
)
674 plugin_strip
*st
= create_strip(*i
);
680 gtk_container_add(GTK_CONTAINER(all_vbox
), strips_table
);
681 gtk_container_add(GTK_CONTAINER(toplevel
), all_vbox
);
683 gtk_widget_set_name(GTK_WIDGET(strips_table
), "Calf-Container");
685 gtk_window_add_accel_group(toplevel
, gtk_ui_manager_get_accel_group(ui_mgr
));
686 gtk_widget_show_all(GTK_WIDGET(toplevel
));
687 source_id
= g_timeout_add_full(G_PRIORITY_DEFAULT
, 1000/30, on_idle
, this, NULL
); // 30 fps should be enough for everybody
689 notifier
= get_config_db()->add_listener(this);
691 g_signal_connect(GTK_OBJECT(toplevel
), "destroy", G_CALLBACK(window_destroy_cb
), this);
694 void gtk_main_window::on_config_change()
696 get_config()->load(get_config_db());
697 show_rack_ears(get_config()->rack_ears
);
698 show_vu_meters(get_config()->vu_meters
);
702 void gtk_main_window::refresh_plugin(plugin_ctl_iface
*plugin
)
704 if (plugins
[plugin
]->gui_win
)
705 plugins
[plugin
]->gui_win
->gui
->refresh();
708 void gtk_main_window::on_closed()
716 g_source_remove(source_id
);
720 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
)
722 if (i
->second
&& i
->second
->gui_win
) {
723 i
->second
->gui_win
->close();
729 static inline float LVL(float value
)
731 return value
; //sqrt(value) * 0.75;
734 gboolean
gtk_main_window::on_idle(void *data
)
736 gtk_main_window
*self
= (gtk_main_window
*)data
;
738 self
->owner
->on_idle();
740 if (!self
->refresh_controller
.check_redraw(GTK_WIDGET(self
->toplevel
)))
743 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= self
->plugins
.begin(); i
!= self
->plugins
.end(); ++i
)
747 plugin_ctl_iface
*plugin
= i
->first
;
748 plugin_strip
*strip
= i
->second
;
750 if (strip
->inBox
&& gtk_widget_is_drawable (strip
->inBox
)) {
751 for (int i
= 0; i
< (int)strip
->audio_in
.size(); i
++) {
752 calf_vumeter_set_value(CALF_VUMETER(strip
->audio_in
[i
]), LVL(plugin
->get_level(idx
++)));
756 idx
+= strip
->audio_in
.size();
757 if (strip
->outBox
&& gtk_widget_is_drawable (strip
->outBox
)) {
758 for (int i
= 0; i
< (int)strip
->audio_out
.size(); i
++) {
759 calf_vumeter_set_value(CALF_VUMETER(strip
->audio_out
[i
]), LVL(plugin
->get_level(idx
++)));
763 idx
+= strip
->audio_out
.size();
764 if (plugin
->get_metadata_iface()->get_midi()) {
765 calf_led_set_value (CALF_LED (strip
->midi_in
), plugin
->get_level(idx
++));
772 void gtk_main_window::open_file()
775 dialog
= gtk_file_chooser_dialog_new ("Open File",
777 GTK_FILE_CHOOSER_ACTION_OPEN
,
778 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
779 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
,
781 if (gtk_dialog_run (GTK_DIALOG (dialog
)) == GTK_RESPONSE_ACCEPT
)
783 char *filename
= gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog
));
784 char *error
= owner
->open_file(filename
);
786 display_error(error
, filename
);
788 owner
->set_current_filename(filename
);
792 gtk_widget_destroy (dialog
);
795 bool gtk_main_window::save_file()
797 if (owner
->get_current_filename().empty())
798 return save_file_as();
800 const char *error
= owner
->save_file(owner
->get_current_filename().c_str());
803 display_error(error
, owner
->get_current_filename().c_str());
809 bool gtk_main_window::save_file_as()
812 bool success
= false;
813 dialog
= gtk_file_chooser_dialog_new ("Save File",
815 GTK_FILE_CHOOSER_ACTION_SAVE
,
816 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
817 GTK_STOCK_SAVE
, GTK_RESPONSE_ACCEPT
,
819 if (gtk_dialog_run (GTK_DIALOG (dialog
)) == GTK_RESPONSE_ACCEPT
)
821 char *filename
= gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog
));
822 char *error
= owner
->save_file(filename
);
824 display_error(error
, filename
);
827 owner
->set_current_filename(filename
);
833 gtk_widget_destroy (dialog
);
837 void gtk_main_window::display_error(const char *error
, const char *filename
)
840 dialog
= gtk_message_dialog_new_with_markup (toplevel
, GTK_DIALOG_DESTROY_WITH_PARENT
, GTK_MESSAGE_ERROR
, GTK_BUTTONS_CLOSE
, error
, filename
, NULL
);
841 gtk_dialog_run (GTK_DIALOG (dialog
));
842 gtk_widget_destroy (dialog
);
845 GtkWidget
*gtk_main_window::create_progress_window()
847 GtkWidget
*tlw
= gtk_window_new ( GTK_WINDOW_TOPLEVEL
);
848 gtk_window_set_type_hint (GTK_WINDOW (tlw
), GDK_WINDOW_TYPE_HINT_DIALOG
);
849 GtkWidget
*pbar
= gtk_progress_bar_new();
850 gtk_container_add (GTK_CONTAINER(tlw
), pbar
);
851 gtk_widget_show_all (pbar
);
855 void gtk_main_window::report_progress(float percentage
, const std::string
&message
)
857 if (percentage
< 100)
859 if (!progress_window
) {
860 progress_window
= create_progress_window();
861 gtk_window_set_modal (GTK_WINDOW (progress_window
), TRUE
);
863 gtk_window_set_transient_for (GTK_WINDOW (progress_window
), toplevel
);
864 gtk_widget_show(progress_window
);
866 GtkWidget
*pbar
= gtk_bin_get_child (GTK_BIN (progress_window
));
867 if (!message
.empty())
868 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pbar
), message
.c_str());
869 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pbar
), percentage
/ 100.0);
873 if (progress_window
) {
874 gtk_window_set_modal (GTK_WINDOW (progress_window
), FALSE
);
875 gtk_widget_destroy (progress_window
);
876 progress_window
= NULL
;
880 while (gtk_events_pending ())
881 gtk_main_iteration ();
884 void gtk_main_window::add_condition(const std::string
&name
)
886 conditions
.insert(name
);
889 void gtk_main_window::show_error(const std::string
&text
)
891 GtkWidget
*widget
= gtk_message_dialog_new (NULL
, GTK_DIALOG_MODAL
, GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "%s", text
.c_str());
892 gtk_dialog_run (GTK_DIALOG (widget
));
893 gtk_widget_destroy (widget
);