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>
32 using namespace calf_plugins
;
35 gtk_main_window::gtk_main_window()
41 progress_window
= NULL
;
44 static const char *ui_xml
=
47 " <menu action=\"FileMenuAction\">\n"
48 " <menuitem action=\"FileOpen\"/>\n"
49 " <menuitem action=\"FileSave\"/>\n"
50 " <menuitem action=\"FileSaveAs\"/>\n"
52 " <menuitem action=\"FileReorder\"/>\n"
54 " <menuitem action=\"FilePreferences\"/>\n"
56 " <menuitem action=\"FileQuit\"/>\n"
58 " <menu action=\"AddPluginMenuAction\" />\n"
63 const GtkActionEntry
gtk_main_window::actions
[] = {
64 { "FileMenuAction", NULL
, "_File", NULL
, "File-related operations", NULL
},
65 { "FileOpen", GTK_STOCK_OPEN
, "_Open", "<Ctrl>O", "Open a rack file", (GCallback
)on_open_action
},
66 { "FileSave", GTK_STOCK_SAVE
, "_Save", "<Ctrl>S", "Save a rack file", (GCallback
)on_save_action
},
67 { "FileSaveAs", GTK_STOCK_SAVE_AS
, "Save _as...", NULL
, "Save a rack file as", (GCallback
)on_save_as_action
},
68 { "HostMenuAction", NULL
, "_Host", NULL
, "Host-related operations", NULL
},
69 { "AddPluginMenuAction", NULL
, "_Add plugin", NULL
, "Add a plugin to the rack", NULL
},
70 { "FileReorder", NULL
, "_Reorder plugins", NULL
, "Reorder plugins to minimize latency (experimental)", (GCallback
)on_reorder_action
},
71 { "FilePreferences", GTK_STOCK_PREFERENCES
, "_Preferences...", NULL
, "Adjust preferences", (GCallback
)on_preferences_action
},
72 { "FileQuit", GTK_STOCK_QUIT
, "_Quit", "<Ctrl>Q", "Exit application", (GCallback
)on_exit_action
},
75 void gtk_main_window::on_open_action(GtkWidget
*widget
, gtk_main_window
*main
)
80 void gtk_main_window::on_save_action(GtkWidget
*widget
, gtk_main_window
*main
)
85 void gtk_main_window::on_save_as_action(GtkWidget
*widget
, gtk_main_window
*main
)
90 void gtk_main_window::on_reorder_action(GtkWidget
*widget
, gtk_main_window
*main
)
92 main
->owner
->reorder_plugins();
95 void gtk_main_window::on_preferences_action(GtkWidget
*widget
, gtk_main_window
*main
)
97 GtkBuilder
*prefs_builder
= gtk_builder_new();
99 const gchar
*objects
[] = { "preferences", NULL
};
100 if (!gtk_builder_add_objects_from_file(prefs_builder
, PKGLIBDIR
"/calf-gui.xml", (gchar
**)objects
, &error
))
102 g_warning("Cannot load preferences dialog: %s", error
->message
);
104 g_object_unref(G_OBJECT(prefs_builder
));
109 GtkCellRenderer
*cell
;
110 GtkListStore
*store
= main
->get_styles();
111 GtkComboBox
*cb
= GTK_COMBO_BOX(gtk_builder_get_object(prefs_builder
, "rcstyles"));
112 gtk_combo_box_set_model(cb
, GTK_TREE_MODEL(store
));
113 cell
= gtk_cell_renderer_text_new();
114 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(cb
), cell
, TRUE
);
115 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(cb
), cell
, "text", 0, NULL
);
116 //gtk_tree_model_(cb);
118 gboolean valid
= gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store
), &iter
);
121 gtk_tree_model_get_value(GTK_TREE_MODEL(store
), &iter
, 0, &title
);
122 if (main
->get_config()->style
.compare(g_value_get_string(&title
)) == 0) {
123 gtk_combo_box_set_active_iter(cb
, &iter
);
126 valid
= gtk_tree_model_iter_next(GTK_TREE_MODEL(store
), &iter
);
127 g_value_unset(&title
);
131 GtkWidget
*preferences_dlg
= GTK_WIDGET(gtk_builder_get_object(prefs_builder
, "preferences"));
132 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(prefs_builder
, "show-rack-ears")), main
->get_config()->rack_ears
);
133 gtk_spin_button_set_range(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "rack-float")), 0, 1);
134 gtk_spin_button_set_range(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "float-size")), 1, 32);
135 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "rack-float")), 1, 1);
136 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "float-size")), 1, 1);
137 gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "rack-float")), main
->get_config()->rack_float
);
138 gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "float-size")), main
->get_config()->float_size
);
139 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(prefs_builder
, "show-vu-meters")), main
->get_config()->vu_meters
);
140 int response
= gtk_dialog_run(GTK_DIALOG(preferences_dlg
));
141 if (response
== GTK_RESPONSE_OK
)
143 main
->get_config()->rack_ears
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(prefs_builder
, "show-rack-ears")));
144 main
->get_config()->rack_float
= gtk_spin_button_get_value(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "rack-float")));
145 main
->get_config()->float_size
= gtk_spin_button_get_value(GTK_SPIN_BUTTON(gtk_builder_get_object(prefs_builder
, "float-size")));
146 main
->get_config()->vu_meters
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(prefs_builder
, "show-vu-meters")));
147 main
->get_config()->save(main
->get_config_db());
149 gtk_widget_destroy(preferences_dlg
);
150 g_object_unref(G_OBJECT(prefs_builder
));
153 void gtk_main_window::on_exit_action(GtkWidget
*widget
, gtk_main_window
*main
)
155 gtk_widget_destroy(GTK_WIDGET(main
->toplevel
));
158 void gtk_main_window::add_plugin(jack_host
*plugin
)
162 plugin_strip
*strip
= create_strip(plugin
);
163 plugins
[plugin
] = strip
;
164 update_strip(plugin
);
168 plugin_queue
.push_back(plugin
);
169 //plugins[plugin] = NULL;
173 void gtk_main_window::del_plugin(plugin_ctl_iface
*plugin
)
175 if (!plugins
.count(plugin
))
177 plugin_strip
*strip
= plugins
[plugin
];
179 strip
->gui_win
->close();
180 vector
<GtkWidget
*> to_destroy
;
181 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
)
183 if (i
->second
== strip
)
184 to_destroy
.push_back(i
->second
->strip_table
);
185 else if(i
->second
->id
> strip
->id
)
188 for (unsigned int i
= 0; i
< to_destroy
.size(); i
++)
189 gtk_container_remove(GTK_CONTAINER(strips_table
), to_destroy
[i
]);
190 plugins
.erase(plugin
);
194 void gtk_main_window::set_window(plugin_ctl_iface
*plugin
, plugin_gui_window
*gui_win
)
196 if (!plugins
.count(plugin
))
198 plugin_strip
*strip
= plugins
[plugin
];
201 strip
->gui_win
= gui_win
;
203 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(strip
->button
), gui_win
!= NULL
);
206 void gtk_main_window::refresh_all_presets(bool builtin_too
)
208 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
)
210 if (i
->second
&& i
->second
->gui_win
) {
212 i
->second
->gui_win
->fill_gui_presets(true, ch
);
213 i
->second
->gui_win
->fill_gui_presets(false, ch
);
219 gui_button_pressed(GtkWidget
*button
, plugin_strip
*strip
)
221 GtkToggleButton
*tb
= GTK_TOGGLE_BUTTON(button
);
222 if ((gtk_toggle_button_get_active(tb
) != 0) == (strip
->gui_win
!= NULL
))
224 if (strip
->gui_win
) {
225 strip
->gui_win
->close();
226 strip
->gui_win
= NULL
;
228 strip
->main_win
->open_gui(strip
->plugin
);
233 connect_button_pressed(GtkWidget
*button
, plugin_strip
*strip
)
235 //GtkToggleButton *tb = GTK_TOGGLE_BUTTON(button);
236 if (strip
->connector
) {
237 strip
->connector
->close();
238 strip
->connector
= NULL
;
240 strip
->connector
= new calf_connector(strip
);
245 extra_button_pressed(GtkWidget
*button
, plugin_strip
*strip
)
247 if (strip
->connector
)
248 strip
->connector
->close();
249 strip
->main_win
->owner
->remove_plugin(strip
->plugin
);
253 void gtk_main_window::show_rack_ears(bool show
)
255 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
)
259 gtk_widget_show(i
->second
->leftBox
);
260 gtk_widget_show(i
->second
->rightBox
);
264 gtk_widget_hide(i
->second
->leftBox
);
265 gtk_widget_hide(i
->second
->rightBox
);
270 void gtk_main_window::show_vu_meters(bool show
)
272 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
)
276 if (i
->second
->inBox
)
277 gtk_widget_show(i
->second
->inBox
);
278 if (i
->second
->outBox
)
279 gtk_widget_show(i
->second
->outBox
);
283 if (i
->second
->inBox
)
284 gtk_widget_hide(i
->second
->inBox
);
285 if (i
->second
->outBox
)
286 gtk_widget_hide(i
->second
->outBox
);
291 plugin_strip
*gtk_main_window::create_strip(jack_host
*plugin
)
293 plugin_strip
*strip
= new plugin_strip
;
294 strip
->main_win
= this;
295 strip
->plugin
= plugin
;
296 strip
->gui_win
= NULL
;
297 strip
->connector
= NULL
;
298 strip
->id
= plugins
.size();
300 GtkAttachOptions ao
= (GtkAttachOptions
)(GTK_EXPAND
| GTK_FILL
);
302 strip
->strip_table
= gtk_table_new(6, 4, FALSE
);
303 gtk_table_set_col_spacings(GTK_TABLE(strip
->strip_table
), 0);
304 gtk_table_set_row_spacings(GTK_TABLE(strip
->strip_table
), 0);
307 // g_object_get(G_OBJECT(strips_table), "n-rows", &row, "n-columns", &cols, NULL);
308 // gtk_table_resize(GTK_TABLE(strips_table), row + 4, cols);
309 // printf("%03d %03d", row, cols);
310 // images for left side
311 GtkWidget
*nwImg
= gtk_image_new_from_file(PKGLIBDIR
"/side_d_nw.png");
312 GtkWidget
*swImg
= gtk_image_new_from_file(PKGLIBDIR
"/side_d_sw.png");
313 GtkWidget
*wImg
= gtk_image_new_from_file(PKGLIBDIR
"/side_d_w.png");
314 gtk_widget_set_size_request(GTK_WIDGET(wImg
), 56, 1);
316 // images for right side
317 GtkWidget
*neImg
= gtk_image_new_from_file(PKGLIBDIR
"/side_d_ne.png");
318 GtkWidget
*seImg
= gtk_image_new_from_file(PKGLIBDIR
"/side_d_se.png");
319 GtkWidget
*eImg
= gtk_image_new_from_file(PKGLIBDIR
"/side_d_e.png");
320 gtk_widget_set_size_request(GTK_WIDGET(eImg
), 56, 1);
323 GtkWidget
*leftBox
= gtk_vbox_new(FALSE
, 0);
324 gtk_box_pack_start(GTK_BOX(leftBox
), GTK_WIDGET(nwImg
), FALSE
, FALSE
, 0);
325 gtk_box_pack_start(GTK_BOX(leftBox
), GTK_WIDGET(wImg
), TRUE
, TRUE
, 0);
326 gtk_box_pack_end(GTK_BOX(leftBox
), GTK_WIDGET(swImg
), FALSE
, FALSE
, 0);
327 gtk_widget_show_all(GTK_WIDGET(leftBox
));
328 if (!get_config()->rack_ears
)
329 gtk_widget_hide(GTK_WIDGET(leftBox
));
330 gtk_table_attach(GTK_TABLE(strip
->strip_table
), leftBox
, 0, 1, row
, row
+ 4, (GtkAttachOptions
)(0), (GtkAttachOptions
)(GTK_EXPAND
| GTK_FILL
), 0, 0);
333 GtkWidget
*rightBox
= gtk_vbox_new(FALSE
, 0);
334 gtk_box_pack_start(GTK_BOX(rightBox
), GTK_WIDGET(neImg
), FALSE
, FALSE
, 0);
335 gtk_box_pack_start(GTK_BOX(rightBox
), GTK_WIDGET(eImg
), TRUE
, TRUE
, 0);
336 gtk_box_pack_end(GTK_BOX(rightBox
), GTK_WIDGET(seImg
), FALSE
, FALSE
, 0);
337 gtk_widget_show_all(GTK_WIDGET(rightBox
));
338 if (!get_config()->rack_ears
)
339 gtk_widget_hide(GTK_WIDGET(rightBox
));
340 gtk_table_attach(GTK_TABLE(strip
->strip_table
), rightBox
, 5, 6, row
, row
+ 4, (GtkAttachOptions
)(0), (GtkAttachOptions
)(GTK_EXPAND
| GTK_FILL
), 0, 0);
342 strip
->leftBox
= leftBox
;
343 strip
->rightBox
= rightBox
;
347 GtkWidget
*topImg
= gtk_image_new_from_file(PKGLIBDIR
"/light_top.png");
348 gtk_widget_set_size_request(GTK_WIDGET(topImg
), 1, 1);
349 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);
350 gtk_widget_show(topImg
);
351 strip
->name
= topImg
;
355 const plugin_metadata_iface
*metadata
= plugin
->get_metadata_iface();
356 GtkWidget
*title
= gtk_label_new(NULL
);
357 gtk_widget_set_name(GTK_WIDGET(title
), "Calf-Rack-Title");
358 gtk_label_set_markup(GTK_LABEL(title
), metadata
->get_label());
359 gtk_label_set_justify(GTK_LABEL(title
), GTK_JUSTIFY_RIGHT
);
360 GtkWidget
* align
= gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
361 gtk_container_add(GTK_CONTAINER(align
), title
);
362 gtk_table_attach(GTK_TABLE(strip
->strip_table
), align
, 1, 2, row
, row
+ 1, (GtkAttachOptions
)(GTK_FILL
), (GtkAttachOptions
)(GTK_FILL
) , 10, 0);
363 gtk_widget_show_all(align
);
366 GtkWidget
*label
= calf_toggle_button_new("Edit");
367 strip
->button
= label
;
368 gtk_widget_set_size_request(GTK_WIDGET(label
), 80, -1);
369 g_signal_connect(GTK_OBJECT(label
), "toggled", G_CALLBACK(gui_button_pressed
),
370 (plugin_ctl_iface
*)strip
);
371 gtk_widget_show(strip
->button
);
374 GtkWidget
*con
= calf_toggle_button_new("Connect");
376 gtk_widget_set_size_request(GTK_WIDGET(con
), -1, -1);
377 g_signal_connect(GTK_OBJECT(con
), "toggled", G_CALLBACK(connect_button_pressed
),
378 (plugin_ctl_iface
*)strip
);
379 gtk_widget_show(strip
->con
);
382 GtkWidget
*extra
= calf_button_new("Remove");
383 strip
->extra
= extra
;
384 //gtk_widget_set_size_request(GTK_WIDGET(extra), 100, -1);
385 g_signal_connect(GTK_OBJECT(extra
), "clicked", G_CALLBACK(extra_button_pressed
),
386 (plugin_ctl_iface
*)strip
);
387 gtk_widget_show(strip
->extra
);
390 GtkWidget
*buttonBox
= gtk_hbox_new(FALSE
, 5);
391 gtk_box_pack_start(GTK_BOX(buttonBox
), GTK_WIDGET(strip
->button
), FALSE
, FALSE
, 0);
392 gtk_box_pack_start(GTK_BOX(buttonBox
), GTK_WIDGET(strip
->con
), FALSE
, FALSE
, 0);
393 gtk_box_pack_start(GTK_BOX(buttonBox
), GTK_WIDGET(strip
->extra
), FALSE
, FALSE
, 0);
394 gtk_table_attach(GTK_TABLE(strip
->strip_table
), buttonBox
, 1, 2, row
+ 1, row
+ 2, (GtkAttachOptions
)0, (GtkAttachOptions
)0, 10, 10);
395 gtk_widget_show(buttonBox
);
398 if (metadata
->get_midi()) {
399 label
= calf_led_new();
400 GtkWidget
*midiBox
= gtk_vbox_new(FALSE
, 1);
401 gtk_box_pack_start(GTK_BOX(midiBox
), GTK_WIDGET(gtk_label_new("Midi")), FALSE
, FALSE
, 0);
402 gtk_box_pack_start(GTK_BOX(midiBox
), GTK_WIDGET(label
), FALSE
, FALSE
, 0);
403 gtk_table_attach(GTK_TABLE(strip
->strip_table
), midiBox
, 2, 3, row
, row
+ 1, (GtkAttachOptions
)0, (GtkAttachOptions
)0, 5, 3);
404 gtk_widget_set_size_request(GTK_WIDGET(label
), 25, 25);
405 strip
->midi_in
= label
;
406 gtk_widget_show_all(midiBox
);
408 label
= gtk_label_new("");
409 gtk_table_attach(GTK_TABLE(strip
->strip_table
), label
, 2, 3, row
, row
+ 1, GTK_FILL
, GTK_EXPAND
, 5, 3);
410 gtk_widget_set_size_request(GTK_WIDGET(label
), 25, 25);
411 strip
->midi_in
= label
;
412 gtk_widget_show(strip
->midi_in
);
414 strip
->midi_in
= label
;
417 strip
->outBox
= NULL
;
418 strip
->audio_in
.clear();
419 strip
->audio_out
.clear();
421 if (metadata
->get_input_count()) {
423 GtkWidget
*inBox
= gtk_vbox_new(FALSE
, 1);
425 gtk_box_pack_start(GTK_BOX(inBox
), gtk_label_new("Audio In"),FALSE
, FALSE
, 0);
427 for (int i
= 0; i
< metadata
->get_input_count(); i
++)
429 label
= calf_vumeter_new();
430 calf_vumeter_set_falloff(CALF_VUMETER(label
), 2.5);
431 calf_vumeter_set_hold(CALF_VUMETER(label
), 1.5);
432 calf_vumeter_set_width(CALF_VUMETER(label
), 100);
433 calf_vumeter_set_height(CALF_VUMETER(label
), 12);
434 calf_vumeter_set_position(CALF_VUMETER(label
), 2);
435 gtk_box_pack_start(GTK_BOX(inBox
), label
, TRUE
, TRUE
, 0);
436 strip
->audio_in
.push_back(label
);
439 strip
->inBox
= gtk_alignment_new(0.f
, 0.f
, 1.f
, 0.f
);
440 gtk_container_add(GTK_CONTAINER(strip
->inBox
), inBox
);
442 gtk_table_attach(GTK_TABLE(strip
->strip_table
), strip
->inBox
, 3, 4, row
, row
+ 1, ao
, ao
, 5, 3);
444 if (get_config()->vu_meters
)
445 gtk_widget_show_all(strip
->inBox
);
447 gtk_widget_set_size_request(GTK_WIDGET(strip
->inBox
), 120, -1);
450 if (metadata
->get_output_count()) {
452 GtkWidget
*outBox
= gtk_vbox_new(FALSE
, 1);
454 gtk_box_pack_start(GTK_BOX(outBox
), gtk_label_new("Audio Out"),TRUE
, TRUE
, 0);
456 for (int i
= 0; i
< metadata
->get_output_count(); i
++)
458 label
= calf_vumeter_new();
459 calf_vumeter_set_falloff(CALF_VUMETER(label
), 2.5);
460 calf_vumeter_set_hold(CALF_VUMETER(label
), 1.5);
461 calf_vumeter_set_width(CALF_VUMETER(label
), 100);
462 calf_vumeter_set_height(CALF_VUMETER(label
), 12);
463 calf_vumeter_set_position(CALF_VUMETER(label
), 2);
464 gtk_box_pack_start(GTK_BOX(outBox
), label
,FALSE
, FALSE
, 0);
465 strip
->audio_out
.push_back(label
);
468 strip
->outBox
= gtk_alignment_new(0.f
, 0.f
, 1.f
, 0.f
);
469 gtk_container_add(GTK_CONTAINER(strip
->outBox
), outBox
);
471 gtk_table_attach(GTK_TABLE(strip
->strip_table
), strip
->outBox
, 4, 5, row
, row
+ 1, ao
, ao
, 5, 3);
473 if (get_config()->vu_meters
)
474 gtk_widget_show_all(strip
->outBox
);
476 gtk_widget_set_size_request(GTK_WIDGET(strip
->outBox
), 120, -1);
479 // other stuff bottom right
480 GtkWidget
*paramBox
= gtk_hbox_new(FALSE
, 0);
482 GtkWidget
*logoImg
= gtk_image_new_from_file(PKGLIBDIR
"/logo_button.png");
483 gtk_box_pack_end(GTK_BOX(paramBox
), GTK_WIDGET(logoImg
), TRUE
, TRUE
, 0);
485 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);
486 gtk_widget_show_all(GTK_WIDGET(paramBox
));
491 GtkWidget
*botImg
= gtk_image_new_from_file(PKGLIBDIR
"/light_bottom.png");
492 gtk_widget_set_size_request(GTK_WIDGET(botImg
), 1, 1);
493 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);
494 gtk_widget_show(botImg
);
496 gtk_widget_show(GTK_WIDGET(strip
->strip_table
));
501 void gtk_main_window::sort_strips()
503 if(plugins
.size() <= 0) return;
504 int rack_float
= get_config()->rack_float
; // 0=horiz, 1=vert
505 int float_size
= get_config()->float_size
; // amout of rows/cols before line break
507 gtk_table_resize(GTK_TABLE(strips_table
), (int)(plugins
.size() / float_size
+ 1), float_size
);
508 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
)
510 switch (rack_float
) {
513 posx
= i
->second
->id
% float_size
;
514 posy
= (int)(i
->second
->id
/ float_size
);
517 posy
= i
->second
->id
% float_size
;
518 posx
= (int)(i
->second
->id
/ float_size
);
522 if(i
->second
->strip_table
->parent
!= NULL
) {
524 g_object_ref(i
->second
->strip_table
);
525 gtk_container_remove(GTK_CONTAINER(strips_table
), GTK_WIDGET(i
->second
->strip_table
));
527 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);
528 if(rem
) g_object_unref(i
->second
->strip_table
);
532 void gtk_main_window::update_strip(plugin_ctl_iface
*plugin
)
534 // plugin_strip *strip = plugins[plugin];
539 void gtk_main_window::open_gui(plugin_ctl_iface
*plugin
)
541 plugin_gui_window
*gui_win
= new plugin_gui_window(this, this);
542 std::string title
= "Calf - ";
543 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());
544 gtk_widget_show(GTK_WIDGET(gui_win
->toplevel
));
545 plugins
[plugin
]->gui_win
= gui_win
;
548 static const char *plugin_pre_xml
=
551 " <menu action=\"AddPluginMenuAction\">\n"
552 " <placeholder name=\"plugin\">\n";
554 static const char *plugin_post_xml
=
560 #define countof(X) ( (size_t) ( sizeof(X)/sizeof*(X) ) )
561 void gtk_main_window::register_icons()
563 const char *names
[]={"Allpass", "Amplifier", "Analyser",
564 "Bandpass", "Chorus", "Comb", "Compressor",
565 "Constant", "Converter", "Delay", "Distortion",
566 "Dynamics", "Envelope", "EQ", "Expander",
567 "Filter", "Flanger", "Function", "Gate",
568 "Generator", "Highpass", "Instrument",
569 "Limiter", "Mixer", "Modulator", "MultiEQ",
570 "Oscillator", "ParaEQ", "Phaser", "Pitch",
571 "Reverb", "Simulator", "Spatial", "Spectral",
572 "Utility", "Waveshaper"};
573 factory
= gtk_icon_factory_new ();
574 for (size_t i
= 0; i
< countof(names
); i
++) {
576 strcpy(name
, "LV2-");
577 strcat(name
, names
[i
]);
578 if (!gtk_icon_factory_lookup(factory
, name
)) {
579 std::string iname
= std::string(PKGLIBDIR
) + "icons/LV2/" + names
[i
] + ".svg";
580 GdkPixbuf
*buf
= gdk_pixbuf_new_from_file_at_size(iname
.c_str(), 64, 64, NULL
);
581 GtkIconSet
*icon
= gtk_icon_set_new_from_pixbuf(buf
);
582 gtk_icon_factory_add (factory
, name
, icon
);
583 gtk_icon_set_unref(icon
);
587 gtk_icon_factory_add_default(factory
);
590 void gtk_main_window::add_plugin_action(GtkWidget
*src
, gpointer data
)
592 add_plugin_params
*app
= (add_plugin_params
*)data
;
593 app
->main_win
->new_plugin(app
->name
.c_str());
596 static void action_destroy_notify(gpointer data
)
598 delete (gtk_main_window::add_plugin_params
*)data
;
601 std::string
gtk_main_window::make_plugin_list(GtkActionGroup
*actions
)
603 string s
= plugin_pre_xml
;
604 const plugin_registry::plugin_vector
&plugins
= plugin_registry::instance().get_all();
605 std::string type
= "";
606 std::string tmp
= "";
607 std::string last
= "";
608 unsigned int count
= 0;
609 unsigned int size
= plugins
.size();
611 const plugin_metadata_iface
*p
= plugins
[0];
613 for(unsigned int i
= 0; i
<= size
; i
++)
617 type
= (p
->get_plugin_info()).plugin_type
;
618 type
= type
.substr(0, type
.length() - 6);
620 if (type
!= last
or i
>= size
or !i
) {
624 s
+= "<menu action='" + last
+ "'>" + tmp
+ "</menu>";
625 GtkAction
*a
= gtk_action_new(last
.c_str(), last
.c_str(), NULL
, ("LV2-" + last
).c_str());
626 gtk_action_group_add_action(actions
, a
);
636 std::string action
= "Add" + string(p
->get_id()) + "Action";
637 std::string stock
= "LV2-" + type
;
639 // add lv2 stock icons to plug-ins and not just to menus
640 // GTK_STOCK_OPEN -> ("LV2_" + type).c_str()
641 GtkActionEntry ae
= { action
.c_str(), stock
.c_str(), p
->get_label(), NULL
, NULL
, (GCallback
)add_plugin_action
};
642 gtk_action_group_add_actions_full(actions
, &ae
, 1, (gpointer
)new add_plugin_params(this, p
->get_id()), action_destroy_notify
);
643 tmp
+= string("<menuitem always-show-image=\"true\" action=\"") + action
+ "\" />";
647 return s
+ plugin_post_xml
;
650 static void window_destroy_cb(GtkWindow
*window
, gpointer data
)
652 ((gtk_main_window
*)data
)->owner
->on_main_window_destroy();
655 void gtk_main_window::create()
658 toplevel
= GTK_WINDOW(gtk_window_new (GTK_WINDOW_TOPLEVEL
));
659 std::string title
= "Calf JACK Host";
660 gtk_window_set_title(toplevel
, title
.c_str()); //(owner->get_client_name() + " - Calf JACK Host").c_str());
661 gtk_widget_set_name(GTK_WIDGET(toplevel
), "Calf-Rack");
662 gtk_window_set_icon_name(toplevel
, "calf");
663 gtk_window_set_role(toplevel
, "calf_rack");
666 gtk_window_set_resizable(toplevel
, false);
668 all_vbox
= gtk_vbox_new(0, FALSE
);
670 ui_mgr
= gtk_ui_manager_new();
671 std_actions
= gtk_action_group_new("default");
672 gtk_action_group_add_actions(std_actions
, actions
, sizeof(actions
)/sizeof(actions
[0]), this);
673 GError
*error
= NULL
;
674 gtk_ui_manager_insert_action_group(ui_mgr
, std_actions
, 0);
675 gtk_ui_manager_add_ui_from_string(ui_mgr
, ui_xml
, -1, &error
);
676 gtk_box_pack_start(GTK_BOX(all_vbox
), gtk_ui_manager_get_widget(ui_mgr
, "/ui/menubar"), false, false, 0);
678 gtk_widget_set_size_request(GTK_WIDGET(gtk_ui_manager_get_widget(ui_mgr
, "/ui/menubar")), 640, -1);
680 gtk_widget_set_name(GTK_WIDGET(gtk_ui_manager_get_widget(ui_mgr
, "/ui/menubar")), "Calf-Menu");
682 plugin_actions
= gtk_action_group_new("plugins");
683 string plugin_xml
= make_plugin_list(plugin_actions
);
684 gtk_ui_manager_insert_action_group(ui_mgr
, plugin_actions
, 0);
685 gtk_ui_manager_add_ui_from_string(ui_mgr
, plugin_xml
.c_str(), -1, &error
);
687 strips_table
= gtk_table_new(0, 1, FALSE
);
688 gtk_table_set_col_spacings(GTK_TABLE(strips_table
), 0);
689 gtk_table_set_row_spacings(GTK_TABLE(strips_table
), 0);
691 for(GList
*p
= GTK_TABLE(strips_table
)->children
; p
!= NULL
; p
= p
->next
)
693 GtkTableChild
*c
= (GtkTableChild
*)p
->data
;
694 if (c
->top_attach
== 0) {
695 gtk_misc_set_alignment(GTK_MISC(c
->widget
), 0.5, 0);
698 for (std::vector
<jack_host
*>::iterator i
= plugin_queue
.begin(); i
!= plugin_queue
.end(); ++i
)
700 plugin_strip
*st
= create_strip(*i
);
706 gtk_container_add(GTK_CONTAINER(all_vbox
), strips_table
);
707 gtk_container_add(GTK_CONTAINER(toplevel
), all_vbox
);
709 gtk_widget_set_name(GTK_WIDGET(strips_table
), "Calf-Container");
711 gtk_window_add_accel_group(toplevel
, gtk_ui_manager_get_accel_group(ui_mgr
));
712 gtk_widget_show_all(GTK_WIDGET(toplevel
));
713 source_id
= g_timeout_add_full(G_PRIORITY_DEFAULT
, 1000/30, on_idle
, this, NULL
); // 30 fps should be enough for everybody
715 notifier
= get_config_db()->add_listener(this);
717 g_signal_connect(GTK_OBJECT(toplevel
), "destroy", G_CALLBACK(window_destroy_cb
), this);
720 void gtk_main_window::on_config_change()
722 get_config()->load(get_config_db());
723 show_rack_ears(get_config()->rack_ears
);
724 show_vu_meters(get_config()->vu_meters
);
728 void gtk_main_window::refresh_plugin(plugin_ctl_iface
*plugin
)
730 if (plugins
[plugin
]->gui_win
)
731 plugins
[plugin
]->gui_win
->gui
->refresh();
734 void gtk_main_window::on_closed()
742 g_source_remove(source_id
);
746 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
)
748 if (i
->second
&& i
->second
->gui_win
) {
749 i
->second
->gui_win
->close();
755 static inline float LVL(float value
)
757 return value
; //sqrt(value) * 0.75;
760 gboolean
gtk_main_window::on_idle(void *data
)
762 gtk_main_window
*self
= (gtk_main_window
*)data
;
764 self
->owner
->on_idle();
766 if (!self
->refresh_controller
.check_redraw(GTK_WIDGET(self
->toplevel
)))
769 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= self
->plugins
.begin(); i
!= self
->plugins
.end(); ++i
)
773 plugin_ctl_iface
*plugin
= i
->first
;
774 plugin_strip
*strip
= i
->second
;
776 if (strip
->inBox
&& gtk_widget_is_drawable (strip
->inBox
)) {
777 for (int i
= 0; i
< (int)strip
->audio_in
.size(); i
++) {
778 calf_vumeter_set_value(CALF_VUMETER(strip
->audio_in
[i
]), LVL(plugin
->get_level(idx
++)));
782 idx
+= strip
->audio_in
.size();
783 if (strip
->outBox
&& gtk_widget_is_drawable (strip
->outBox
)) {
784 for (int i
= 0; i
< (int)strip
->audio_out
.size(); i
++) {
785 calf_vumeter_set_value(CALF_VUMETER(strip
->audio_out
[i
]), LVL(plugin
->get_level(idx
++)));
789 idx
+= strip
->audio_out
.size();
790 if (plugin
->get_metadata_iface()->get_midi()) {
791 calf_led_set_value (CALF_LED (strip
->midi_in
), plugin
->get_level(idx
++));
798 void gtk_main_window::open_file()
801 dialog
= gtk_file_chooser_dialog_new ("Open File",
803 GTK_FILE_CHOOSER_ACTION_OPEN
,
804 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
805 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
,
807 if (gtk_dialog_run (GTK_DIALOG (dialog
)) == GTK_RESPONSE_ACCEPT
)
809 char *filename
= gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog
));
810 char *error
= owner
->open_file(filename
);
812 display_error(error
, filename
);
814 owner
->set_current_filename(filename
);
818 gtk_widget_destroy (dialog
);
821 bool gtk_main_window::save_file()
823 if (owner
->get_current_filename().empty())
824 return save_file_as();
826 const char *error
= owner
->save_file(owner
->get_current_filename().c_str());
829 display_error(error
, owner
->get_current_filename().c_str());
835 bool gtk_main_window::save_file_as()
838 bool success
= false;
839 dialog
= gtk_file_chooser_dialog_new ("Save File",
841 GTK_FILE_CHOOSER_ACTION_SAVE
,
842 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
843 GTK_STOCK_SAVE
, GTK_RESPONSE_ACCEPT
,
845 if (gtk_dialog_run (GTK_DIALOG (dialog
)) == GTK_RESPONSE_ACCEPT
)
847 char *filename
= gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog
));
848 char *error
= owner
->save_file(filename
);
850 display_error(error
, filename
);
853 owner
->set_current_filename(filename
);
859 gtk_widget_destroy (dialog
);
863 void gtk_main_window::display_error(const char *error
, const char *filename
)
866 dialog
= gtk_message_dialog_new_with_markup (toplevel
, GTK_DIALOG_DESTROY_WITH_PARENT
, GTK_MESSAGE_ERROR
, GTK_BUTTONS_CLOSE
, error
, filename
, NULL
);
867 gtk_dialog_run (GTK_DIALOG (dialog
));
868 gtk_widget_destroy (dialog
);
871 GtkWidget
*gtk_main_window::create_progress_window()
873 GtkWidget
*tlw
= gtk_window_new ( GTK_WINDOW_TOPLEVEL
);
874 gtk_window_set_type_hint (GTK_WINDOW (tlw
), GDK_WINDOW_TYPE_HINT_DIALOG
);
875 GtkWidget
*pbar
= gtk_progress_bar_new();
876 gtk_container_add (GTK_CONTAINER(tlw
), pbar
);
877 gtk_widget_show_all (pbar
);
881 void gtk_main_window::report_progress(float percentage
, const std::string
&message
)
883 if (percentage
< 100)
885 if (!progress_window
) {
886 progress_window
= create_progress_window();
887 gtk_window_set_modal (GTK_WINDOW (progress_window
), TRUE
);
889 gtk_window_set_transient_for (GTK_WINDOW (progress_window
), toplevel
);
890 gtk_widget_show(progress_window
);
892 GtkWidget
*pbar
= gtk_bin_get_child (GTK_BIN (progress_window
));
893 if (!message
.empty())
894 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pbar
), message
.c_str());
895 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pbar
), percentage
/ 100.0);
899 if (progress_window
) {
900 gtk_window_set_modal (GTK_WINDOW (progress_window
), FALSE
);
901 gtk_widget_destroy (progress_window
);
902 progress_window
= NULL
;
906 while (gtk_events_pending ())
907 gtk_main_iteration ();
910 void gtk_main_window::add_condition(const std::string
&name
)
912 conditions
.insert(name
);
915 void gtk_main_window::show_error(const std::string
&text
)
917 GtkWidget
*widget
= gtk_message_dialog_new (NULL
, GTK_DIALOG_MODAL
, GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "%s", text
.c_str());
918 gtk_dialog_run (GTK_DIALOG (widget
));
919 gtk_widget_destroy (widget
);
922 GtkListStore
*gtk_main_window::get_styles()
924 std::vector
<calf_utils::direntry
> list
= calf_utils::list_directory(PKGLIBDIR
);
925 GtkListStore
*store
= gtk_list_store_new(2, G_TYPE_STRING
, G_TYPE_STRING
);
926 for (std::vector
<calf_utils::direntry
>::iterator i
= list
.begin(); i
!= list
.end(); i
++) {
927 if (i
->name
.substr(i
->name
.length() - 3).compare(".rc") == 0) {
928 ifstream
infile(i
->full_path
.c_str());
931 getline(infile
, line
);
932 i
->name
= line
.substr(1);
934 gtk_list_store_insert_with_values(store
, NULL
, -1,
936 1, i
->full_path
.c_str(),