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 gtk_table_attach(GTK_TABLE(strip
->strip_table
), title
, 1, 2, row
, row
+ 1, (GtkAttachOptions
)0, (GtkAttachOptions
)0 , 10, 0);
335 gtk_widget_show(title
);
338 GtkWidget
*label
= calf_toggle_button_new("Edit");
339 strip
->button
= label
;
340 gtk_widget_set_size_request(GTK_WIDGET(label
), 80, -1);
341 g_signal_connect(GTK_OBJECT(label
), "toggled", G_CALLBACK(gui_button_pressed
),
342 (plugin_ctl_iface
*)strip
);
343 gtk_widget_show(strip
->button
);
346 GtkWidget
*con
= calf_toggle_button_new("Connect");
348 gtk_widget_set_size_request(GTK_WIDGET(con
), -1, -1);
349 g_signal_connect(GTK_OBJECT(con
), "toggled", G_CALLBACK(connect_button_pressed
),
350 (plugin_ctl_iface
*)strip
);
351 gtk_widget_show(strip
->con
);
354 GtkWidget
*extra
= calf_button_new("Remove");
355 strip
->extra
= extra
;
356 //gtk_widget_set_size_request(GTK_WIDGET(extra), 100, -1);
357 g_signal_connect(GTK_OBJECT(extra
), "clicked", G_CALLBACK(extra_button_pressed
),
358 (plugin_ctl_iface
*)strip
);
359 gtk_widget_show(strip
->extra
);
362 GtkWidget
*buttonBox
= gtk_hbox_new(FALSE
, 5);
363 gtk_box_pack_start(GTK_BOX(buttonBox
), GTK_WIDGET(strip
->button
), FALSE
, FALSE
, 0);
364 gtk_box_pack_start(GTK_BOX(buttonBox
), GTK_WIDGET(strip
->con
), FALSE
, FALSE
, 0);
365 gtk_box_pack_start(GTK_BOX(buttonBox
), GTK_WIDGET(strip
->extra
), FALSE
, FALSE
, 0);
366 gtk_table_attach(GTK_TABLE(strip
->strip_table
), buttonBox
, 1, 2, row
+ 1, row
+ 2, (GtkAttachOptions
)0, (GtkAttachOptions
)0, 10, 10);
367 gtk_widget_show(buttonBox
);
370 if (metadata
->get_midi()) {
371 label
= calf_led_new();
372 GtkWidget
*midiBox
= gtk_vbox_new(FALSE
, 1);
373 gtk_box_pack_start(GTK_BOX(midiBox
), GTK_WIDGET(gtk_label_new("MIDI")), FALSE
, FALSE
, 0);
374 gtk_box_pack_start(GTK_BOX(midiBox
), GTK_WIDGET(label
), FALSE
, FALSE
, 0);
375 gtk_table_attach(GTK_TABLE(strip
->strip_table
), midiBox
, 2, 3, row
, row
+ 1, (GtkAttachOptions
)0, (GtkAttachOptions
)0, 5, 3);
376 gtk_widget_set_size_request(GTK_WIDGET(label
), 25, 25);
377 strip
->midi_in
= label
;
378 gtk_widget_show_all(midiBox
);
380 label
= gtk_label_new("");
381 gtk_table_attach(GTK_TABLE(strip
->strip_table
), label
, 2, 3, row
, row
+ 1, GTK_FILL
, GTK_EXPAND
, 5, 3);
382 gtk_widget_set_size_request(GTK_WIDGET(label
), 25, 25);
383 strip
->midi_in
= label
;
384 gtk_widget_show(strip
->midi_in
);
386 strip
->midi_in
= label
;
389 strip
->outBox
= NULL
;
390 strip
->audio_in
.clear();
391 strip
->audio_out
.clear();
393 if (metadata
->get_input_count()) {
395 GtkWidget
*inBox
= gtk_vbox_new(FALSE
, 1);
397 gtk_box_pack_start(GTK_BOX(inBox
), gtk_label_new("AUDIO IN"),FALSE
, FALSE
, 0);
399 for (int i
= 0; i
< metadata
->get_input_count(); i
++)
401 label
= calf_vumeter_new();
402 calf_vumeter_set_falloff(CALF_VUMETER(label
), 2.5);
403 calf_vumeter_set_hold(CALF_VUMETER(label
), 1.5);
404 calf_vumeter_set_width(CALF_VUMETER(label
), 100);
405 calf_vumeter_set_height(CALF_VUMETER(label
), 12);
406 calf_vumeter_set_position(CALF_VUMETER(label
), 2);
407 gtk_box_pack_start(GTK_BOX(inBox
), label
, TRUE
, TRUE
, 0);
408 strip
->audio_in
.push_back(label
);
411 strip
->inBox
= gtk_alignment_new(0.f
, 0.f
, 1.f
, 0.f
);
412 gtk_container_add(GTK_CONTAINER(strip
->inBox
), inBox
);
414 gtk_table_attach(GTK_TABLE(strip
->strip_table
), strip
->inBox
, 3, 4, row
, row
+ 1, ao
, ao
, 5, 3);
416 if (get_config()->vu_meters
)
417 gtk_widget_show_all(strip
->inBox
);
419 gtk_widget_set_size_request(GTK_WIDGET(strip
->inBox
), 120, -1);
422 if (metadata
->get_output_count()) {
424 GtkWidget
*outBox
= gtk_vbox_new(FALSE
, 1);
426 gtk_box_pack_start(GTK_BOX(outBox
), gtk_label_new("AUDIO OUT"),TRUE
, TRUE
, 0);
428 for (int i
= 0; i
< metadata
->get_output_count(); i
++)
430 label
= calf_vumeter_new();
431 calf_vumeter_set_falloff(CALF_VUMETER(label
), 2.5);
432 calf_vumeter_set_hold(CALF_VUMETER(label
), 1.5);
433 calf_vumeter_set_width(CALF_VUMETER(label
), 100);
434 calf_vumeter_set_height(CALF_VUMETER(label
), 12);
435 calf_vumeter_set_position(CALF_VUMETER(label
), 2);
436 gtk_box_pack_start(GTK_BOX(outBox
), label
,FALSE
, FALSE
, 0);
437 strip
->audio_out
.push_back(label
);
440 strip
->outBox
= gtk_alignment_new(0.f
, 0.f
, 1.f
, 0.f
);
441 gtk_container_add(GTK_CONTAINER(strip
->outBox
), outBox
);
443 gtk_table_attach(GTK_TABLE(strip
->strip_table
), strip
->outBox
, 4, 5, row
, row
+ 1, ao
, ao
, 5, 3);
445 if (get_config()->vu_meters
)
446 gtk_widget_show_all(strip
->outBox
);
448 gtk_widget_set_size_request(GTK_WIDGET(strip
->outBox
), 120, -1);
451 // other stuff bottom right
452 GtkWidget
*paramBox
= gtk_hbox_new(FALSE
, 0);
454 GtkWidget
*logoImg
= gtk_image_new_from_file(PKGLIBDIR
"/logo_button.png");
455 gtk_box_pack_start(GTK_BOX(paramBox
), GTK_WIDGET(logoImg
), TRUE
, TRUE
, 0);
457 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);
458 gtk_widget_show_all(GTK_WIDGET(paramBox
));
463 GtkWidget
*botImg
= gtk_image_new_from_file(PKGLIBDIR
"/light_bottom.png");
464 gtk_widget_set_size_request(GTK_WIDGET(botImg
), 1, 1);
465 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);
466 gtk_widget_show(botImg
);
468 gtk_widget_show(GTK_WIDGET(strip
->strip_table
));
473 void gtk_main_window::sort_strips()
475 if(plugins
.size() <= 0) return;
476 int rack_float
= get_config()->rack_float
; // 0=horiz, 1=vert
477 int float_size
= get_config()->float_size
; // amout of rows/cols before line break
479 gtk_table_resize(GTK_TABLE(strips_table
), (int)(plugins
.size() / float_size
+ 1), float_size
);
480 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
)
482 switch (rack_float
) {
485 posx
= i
->second
->id
% float_size
;
486 posy
= (int)(i
->second
->id
/ float_size
);
489 posy
= i
->second
->id
% float_size
;
490 posx
= (int)(i
->second
->id
/ float_size
);
494 if(i
->second
->strip_table
->parent
!= NULL
) {
496 g_object_ref(i
->second
->strip_table
);
497 gtk_container_remove(GTK_CONTAINER(strips_table
), GTK_WIDGET(i
->second
->strip_table
));
499 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);
500 if(rem
) g_object_unref(i
->second
->strip_table
);
504 void gtk_main_window::update_strip(plugin_ctl_iface
*plugin
)
506 // plugin_strip *strip = plugins[plugin];
511 void gtk_main_window::open_gui(plugin_ctl_iface
*plugin
)
513 plugin_gui_window
*gui_win
= new plugin_gui_window(this, this);
514 std::string title
= "Calf - ";
515 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());
516 gtk_widget_show(GTK_WIDGET(gui_win
->toplevel
));
517 plugins
[plugin
]->gui_win
= gui_win
;
520 static const char *plugin_pre_xml
=
523 " <menu action=\"AddPluginMenuAction\">\n"
524 " <placeholder name=\"plugin\">\n";
526 static const char *plugin_post_xml
=
532 #define countof(X) ( (size_t) ( sizeof(X)/sizeof*(X) ) )
533 void gtk_main_window::register_icons()
535 const char *names
[]={"Allpass", "Amplifier", "Analyser",
536 "Bandpass", "Chorus", "Comb", "Compressor",
537 "Constant", "Converter", "Delay", "Distortion",
538 "Dynamics", "Envelope", "EQ", "Expander",
539 "Filter", "Flanger", "Function", "Gate",
540 "Generator", "Highpass", "Instrument",
541 "Limiter", "Mixer", "Modulator", "MultiEQ",
542 "Oscillator", "ParaEQ", "Phaser", "Pitch",
543 "Reverb", "Simulator", "Spatial", "Spectral",
544 "Utility", "Waveshaper"};
545 factory
= gtk_icon_factory_new ();
546 for (size_t i
= 0; i
< countof(names
); i
++) {
548 strcpy(name
, "LV2-");
549 strcat(name
, names
[i
]);
550 if (!gtk_icon_factory_lookup(factory
, name
)) {
551 std::string iname
= std::string(PKGLIBDIR
) + "icons/LV2/" + names
[i
] + ".svg";
552 GdkPixbuf
*buf
= gdk_pixbuf_new_from_file_at_size(iname
.c_str(), 64, 64, NULL
);
553 GtkIconSet
*icon
= gtk_icon_set_new_from_pixbuf(buf
);
554 gtk_icon_factory_add (factory
, name
, icon
);
555 gtk_icon_set_unref(icon
);
559 gtk_icon_factory_add_default(factory
);
562 void gtk_main_window::add_plugin_action(GtkWidget
*src
, gpointer data
)
564 add_plugin_params
*app
= (add_plugin_params
*)data
;
565 app
->main_win
->new_plugin(app
->name
.c_str());
568 static void action_destroy_notify(gpointer data
)
570 delete (gtk_main_window::add_plugin_params
*)data
;
573 std::string
gtk_main_window::make_plugin_list(GtkActionGroup
*actions
)
575 string s
= plugin_pre_xml
;
576 const plugin_registry::plugin_vector
&plugins
= plugin_registry::instance().get_all();
577 std::string type
= "";
578 std::string tmp
= "";
579 std::string last
= "";
580 unsigned int count
= 0;
581 unsigned int size
= plugins
.size();
583 const plugin_metadata_iface
*p
= plugins
[0];
585 for(unsigned int i
= 0; i
<= size
; i
++)
589 type
= (p
->get_plugin_info()).plugin_type
;
590 type
= type
.substr(0, type
.length() - 6);
592 if (type
!= last
or i
>= size
or !i
) {
596 s
+= "<menu action='" + last
+ "'>" + tmp
+ "</menu>";
597 GtkAction
*a
= gtk_action_new(last
.c_str(), last
.c_str(), NULL
, ("LV2-" + last
).c_str());
598 gtk_action_group_add_action(actions
, a
);
608 std::string action
= "Add" + string(p
->get_id()) + "Action";
609 std::string stock
= "LV2-" + type
;
611 // add lv2 stock icons to plug-ins and not just to menus
612 // GTK_STOCK_OPEN -> ("LV2_" + type).c_str()
613 GtkActionEntry ae
= { action
.c_str(), stock
.c_str(), p
->get_label(), NULL
, NULL
, (GCallback
)add_plugin_action
};
614 gtk_action_group_add_actions_full(actions
, &ae
, 1, (gpointer
)new add_plugin_params(this, p
->get_id()), action_destroy_notify
);
615 tmp
+= string("<menuitem always-show-image=\"true\" action=\"") + action
+ "\" />";
619 return s
+ plugin_post_xml
;
622 static void window_destroy_cb(GtkWindow
*window
, gpointer data
)
624 ((gtk_main_window
*)data
)->owner
->on_main_window_destroy();
627 void gtk_main_window::create()
630 toplevel
= GTK_WINDOW(gtk_window_new (GTK_WINDOW_TOPLEVEL
));
631 std::string title
= "Calf JACK Host";
632 gtk_window_set_title(toplevel
, title
.c_str()); //(owner->get_client_name() + " - Calf JACK Host").c_str());
633 gtk_widget_set_name(GTK_WIDGET(toplevel
), "Calf-Rack");
634 gtk_window_set_icon_name(toplevel
, "calf");
635 gtk_window_set_role(toplevel
, "calf_rack");
638 gtk_window_set_resizable(toplevel
, false);
640 all_vbox
= gtk_vbox_new(0, FALSE
);
642 ui_mgr
= gtk_ui_manager_new();
643 std_actions
= gtk_action_group_new("default");
644 gtk_action_group_add_actions(std_actions
, actions
, sizeof(actions
)/sizeof(actions
[0]), this);
645 GError
*error
= NULL
;
646 gtk_ui_manager_insert_action_group(ui_mgr
, std_actions
, 0);
647 gtk_ui_manager_add_ui_from_string(ui_mgr
, ui_xml
, -1, &error
);
648 gtk_box_pack_start(GTK_BOX(all_vbox
), gtk_ui_manager_get_widget(ui_mgr
, "/ui/menubar"), false, false, 0);
650 gtk_widget_set_size_request(GTK_WIDGET(gtk_ui_manager_get_widget(ui_mgr
, "/ui/menubar")), 640, -1);
652 gtk_widget_set_name(GTK_WIDGET(gtk_ui_manager_get_widget(ui_mgr
, "/ui/menubar")), "Calf-Menu");
654 plugin_actions
= gtk_action_group_new("plugins");
655 string plugin_xml
= make_plugin_list(plugin_actions
);
656 gtk_ui_manager_insert_action_group(ui_mgr
, plugin_actions
, 0);
657 gtk_ui_manager_add_ui_from_string(ui_mgr
, plugin_xml
.c_str(), -1, &error
);
659 strips_table
= gtk_table_new(0, 1, FALSE
);
660 gtk_table_set_col_spacings(GTK_TABLE(strips_table
), 0);
661 gtk_table_set_row_spacings(GTK_TABLE(strips_table
), 0);
663 for(GList
*p
= GTK_TABLE(strips_table
)->children
; p
!= NULL
; p
= p
->next
)
665 GtkTableChild
*c
= (GtkTableChild
*)p
->data
;
666 if (c
->top_attach
== 0) {
667 gtk_misc_set_alignment(GTK_MISC(c
->widget
), 0.5, 0);
670 for (std::vector
<jack_host
*>::iterator i
= plugin_queue
.begin(); i
!= plugin_queue
.end(); ++i
)
672 plugin_strip
*st
= create_strip(*i
);
678 gtk_container_add(GTK_CONTAINER(all_vbox
), strips_table
);
679 gtk_container_add(GTK_CONTAINER(toplevel
), all_vbox
);
681 gtk_widget_set_name(GTK_WIDGET(strips_table
), "Calf-Container");
683 gtk_window_add_accel_group(toplevel
, gtk_ui_manager_get_accel_group(ui_mgr
));
684 gtk_widget_show_all(GTK_WIDGET(toplevel
));
685 source_id
= g_timeout_add_full(G_PRIORITY_DEFAULT
, 1000/30, on_idle
, this, NULL
); // 30 fps should be enough for everybody
687 notifier
= get_config_db()->add_listener(this);
689 g_signal_connect(GTK_OBJECT(toplevel
), "destroy", G_CALLBACK(window_destroy_cb
), this);
692 void gtk_main_window::on_config_change()
694 get_config()->load(get_config_db());
695 show_rack_ears(get_config()->rack_ears
);
696 show_vu_meters(get_config()->vu_meters
);
700 void gtk_main_window::refresh_plugin(plugin_ctl_iface
*plugin
)
702 if (plugins
[plugin
]->gui_win
)
703 plugins
[plugin
]->gui_win
->gui
->refresh();
706 void gtk_main_window::on_closed()
714 g_source_remove(source_id
);
718 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
)
720 if (i
->second
&& i
->second
->gui_win
) {
721 i
->second
->gui_win
->close();
727 static inline float LVL(float value
)
729 return value
; //sqrt(value) * 0.75;
732 gboolean
gtk_main_window::on_idle(void *data
)
734 gtk_main_window
*self
= (gtk_main_window
*)data
;
736 self
->owner
->on_idle();
738 if (!self
->refresh_controller
.check_redraw(GTK_WIDGET(self
->toplevel
)))
741 for (std::map
<plugin_ctl_iface
*, plugin_strip
*>::iterator i
= self
->plugins
.begin(); i
!= self
->plugins
.end(); ++i
)
745 plugin_ctl_iface
*plugin
= i
->first
;
746 plugin_strip
*strip
= i
->second
;
748 if (strip
->inBox
&& gtk_widget_is_drawable (strip
->inBox
)) {
749 for (int i
= 0; i
< (int)strip
->audio_in
.size(); i
++) {
750 calf_vumeter_set_value(CALF_VUMETER(strip
->audio_in
[i
]), LVL(plugin
->get_level(idx
++)));
754 idx
+= strip
->audio_in
.size();
755 if (strip
->outBox
&& gtk_widget_is_drawable (strip
->outBox
)) {
756 for (int i
= 0; i
< (int)strip
->audio_out
.size(); i
++) {
757 calf_vumeter_set_value(CALF_VUMETER(strip
->audio_out
[i
]), LVL(plugin
->get_level(idx
++)));
761 idx
+= strip
->audio_out
.size();
762 if (plugin
->get_metadata_iface()->get_midi()) {
763 calf_led_set_value (CALF_LED (strip
->midi_in
), plugin
->get_level(idx
++));
770 void gtk_main_window::open_file()
773 dialog
= gtk_file_chooser_dialog_new ("Open File",
775 GTK_FILE_CHOOSER_ACTION_OPEN
,
776 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
777 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
,
779 if (gtk_dialog_run (GTK_DIALOG (dialog
)) == GTK_RESPONSE_ACCEPT
)
781 char *filename
= gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog
));
782 char *error
= owner
->open_file(filename
);
784 display_error(error
, filename
);
786 owner
->set_current_filename(filename
);
790 gtk_widget_destroy (dialog
);
793 bool gtk_main_window::save_file()
795 if (owner
->get_current_filename().empty())
796 return save_file_as();
798 const char *error
= owner
->save_file(owner
->get_current_filename().c_str());
801 display_error(error
, owner
->get_current_filename().c_str());
807 bool gtk_main_window::save_file_as()
810 bool success
= false;
811 dialog
= gtk_file_chooser_dialog_new ("Save File",
813 GTK_FILE_CHOOSER_ACTION_SAVE
,
814 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
815 GTK_STOCK_SAVE
, GTK_RESPONSE_ACCEPT
,
817 if (gtk_dialog_run (GTK_DIALOG (dialog
)) == GTK_RESPONSE_ACCEPT
)
819 char *filename
= gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog
));
820 char *error
= owner
->save_file(filename
);
822 display_error(error
, filename
);
825 owner
->set_current_filename(filename
);
831 gtk_widget_destroy (dialog
);
835 void gtk_main_window::display_error(const char *error
, const char *filename
)
838 dialog
= gtk_message_dialog_new_with_markup (toplevel
, GTK_DIALOG_DESTROY_WITH_PARENT
, GTK_MESSAGE_ERROR
, GTK_BUTTONS_CLOSE
, error
, filename
, NULL
);
839 gtk_dialog_run (GTK_DIALOG (dialog
));
840 gtk_widget_destroy (dialog
);
843 GtkWidget
*gtk_main_window::create_progress_window()
845 GtkWidget
*tlw
= gtk_window_new ( GTK_WINDOW_TOPLEVEL
);
846 gtk_window_set_type_hint (GTK_WINDOW (tlw
), GDK_WINDOW_TYPE_HINT_DIALOG
);
847 GtkWidget
*pbar
= gtk_progress_bar_new();
848 gtk_container_add (GTK_CONTAINER(tlw
), pbar
);
849 gtk_widget_show_all (pbar
);
853 void gtk_main_window::report_progress(float percentage
, const std::string
&message
)
855 if (percentage
< 100)
857 if (!progress_window
) {
858 progress_window
= create_progress_window();
859 gtk_window_set_modal (GTK_WINDOW (progress_window
), TRUE
);
861 gtk_window_set_transient_for (GTK_WINDOW (progress_window
), toplevel
);
862 gtk_widget_show(progress_window
);
864 GtkWidget
*pbar
= gtk_bin_get_child (GTK_BIN (progress_window
));
865 if (!message
.empty())
866 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pbar
), message
.c_str());
867 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pbar
), percentage
/ 100.0);
871 if (progress_window
) {
872 gtk_window_set_modal (GTK_WINDOW (progress_window
), FALSE
);
873 gtk_widget_destroy (progress_window
);
874 progress_window
= NULL
;
878 while (gtk_events_pending ())
879 gtk_main_iteration ();
882 void gtk_main_window::add_condition(const std::string
&name
)
884 conditions
.insert(name
);
887 void gtk_main_window::show_error(const std::string
&text
)
889 GtkWidget
*widget
= gtk_message_dialog_new (NULL
, GTK_DIALOG_MODAL
, GTK_MESSAGE_ERROR
, GTK_BUTTONS_OK
, "%s", text
.c_str());
890 gtk_dialog_run (GTK_DIALOG (widget
));
891 gtk_widget_destroy (widget
);