1 /* Calf DSP Library Utility Application - calfjackhost
2 * Standalone application module wrapper example.
4 * Copyright (C) 2007 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 #include <glade/glade.h>
27 #include <jack/jack.h>
29 #include <lash/lash.h>
31 #include <calf/giface.h>
32 #include <calf/jackhost.h>
33 #include <calf/modules.h>
34 #include <calf/modules_dev.h>
36 #include <calf/preset.h>
37 #include <calf/preset_gui.h>
38 #include <calf/main_win.h>
39 #include <calf/utils.h>
42 using namespace calf_utils
;
43 using namespace calf_plugins
;
45 // I don't need anyone to tell me this is stupid. I already know that :)
46 plugin_gui_window
*gui_win
;
48 const char *client_name
= "calfhost";
51 static bool save_data_set_cb(lash_config_handle_t
*handle
, void *user_data
);
52 static bool load_data_set_cb(lash_config_handle_t
*handle
, void *user_data
);
53 static bool quit_cb(void *user_data
);
56 jack_host_base
*calf_plugins::create_jack_host(const char *effect_name
, const std::string
&instance_name
, calf_plugins::progress_report_iface
*priface
)
58 #define PER_MODULE_ITEM(name, isSynth, jackname) if (!strcasecmp(effect_name, jackname)) return new jack_host<name##_audio_module>(effect_name, instance_name, priface);
59 #include <calf/modulelist.h>
63 void jack_host_base::open(jack_client
*_client
)
65 client
= _client
; //jack_client_open(client_name, JackNullOption, &status);
75 void jack_host_base::create_ports() {
78 string prefix
= client
->name
+ ":";
79 static const char *suffixes
[] = { "l", "r", "2l", "2r" };
80 port
*inputs
= get_inputs();
81 port
*outputs
= get_outputs();
82 int in_count
= get_input_count(), out_count
= get_output_count();
83 for (int i
=0; i
<in_count
; i
++) {
84 sprintf(buf
, "%s_in_%s", instance_name
.c_str(), suffixes
[i
]);
85 sprintf(buf2
, client
->input_name
.c_str(), client
->input_nr
++);
86 inputs
[i
].name
= buf2
;
87 inputs
[i
].handle
= jack_port_register(client
->client
, buf
, JACK_DEFAULT_AUDIO_TYPE
, JackPortIsInput
, 0);
88 inputs
[i
].data
= NULL
;
89 if (!inputs
[i
].handle
)
90 throw text_exception("Could not create JACK input port");
91 jack_port_set_alias(inputs
[i
].handle
, (prefix
+ buf2
).c_str());
94 sprintf(buf
, "%s_midi_in", instance_name
.c_str());
95 sprintf(buf2
, client
->midi_name
.c_str(), client
->midi_nr
++);
96 midi_port
.name
= buf2
;
97 midi_port
.handle
= jack_port_register(client
->client
, buf
, JACK_DEFAULT_MIDI_TYPE
, JackPortIsInput
, 0);
98 if (!midi_port
.handle
)
99 throw text_exception("Could not create JACK MIDI port");
100 jack_port_set_alias(midi_port
.handle
, (prefix
+ buf2
).c_str());
102 for (int i
=0; i
<out_count
; i
++) {
103 sprintf(buf
, "%s_out_%s", instance_name
.c_str(), suffixes
[i
]);
104 sprintf(buf2
, client
->output_name
.c_str(), client
->output_nr
++);
105 outputs
[i
].name
= buf2
;
106 outputs
[i
].handle
= jack_port_register(client
->client
, buf
, JACK_DEFAULT_AUDIO_TYPE
, JackPortIsOutput
, 0);
107 outputs
[i
].data
= NULL
;
108 if (!outputs
[i
].handle
)
109 throw text_exception("Could not create JACK output port");
110 jack_port_set_alias(outputs
[i
].handle
, (prefix
+ buf2
).c_str());
114 void jack_host_base::close() {
115 port
*inputs
= get_inputs(), *outputs
= get_outputs();
116 int input_count
= get_input_count(), output_count
= get_output_count();
117 for (int i
= 0; i
< input_count
; i
++) {
118 jack_port_unregister(client
->client
, inputs
[i
].handle
);
119 inputs
[i
].data
= NULL
;
121 for (int i
= 0; i
< output_count
; i
++) {
122 jack_port_unregister(client
->client
, outputs
[i
].handle
);
123 outputs
[i
].data
= NULL
;
126 jack_port_unregister(client
->client
, midi_port
.handle
);
130 void destroy(GtkWindow
*window
, gpointer data
)
135 void gui_win_destroy(GtkWindow
*window
, gpointer data
)
139 static struct option long_options
[] = {
141 {"version", 0, 0, 'v'},
142 {"client", 1, 0, 'c'},
143 {"effect", 0, 0, 'e'},
144 {"input", 1, 0, 'i'},
145 {"output", 1, 0, 'o'},
146 {"connect-midi", 1, 0, 'M'},
150 void print_help(char *argv
[])
152 printf("JACK host for Calf effects\n"
153 "Syntax: %s [--client <name>] [--input <name>] [--output <name>] [--midi <name>]\n"
154 " [--connect-midi <name|capture-index>] [--help] [--version] [!] pluginname[:<preset>] [!] ...\n",
158 int jack_client::do_jack_process(jack_nframes_t nframes
, void *p
)
160 jack_client
*self
= (jack_client
*)p
;
161 ptlock
lock(self
->mutex
);
162 for(unsigned int i
= 0; i
< self
->plugins
.size(); i
++)
163 self
->plugins
[i
]->process(nframes
);
167 int jack_client::do_jack_bufsize(jack_nframes_t numsamples
, void *p
)
169 jack_client
*self
= (jack_client
*)p
;
170 ptlock
lock(self
->mutex
);
171 for(unsigned int i
= 0; i
< self
->plugins
.size(); i
++)
172 self
->plugins
[i
]->cache_ports();
176 void jack_client::delete_plugins()
179 for (unsigned int i
= 0; i
< plugins
.size(); i
++) {
180 // plugins[i]->close();
186 struct host_session
: public main_window_owner_iface
, public calf_plugins::progress_report_iface
188 string client_name
, input_name
, output_name
, midi_name
;
189 vector
<string
> plugin_names
;
190 map
<int, string
> presets
;
193 lash_client_t
*lash_client
;
195 lash_args_t
*lash_args
;
199 // these are not saved
201 string autoconnect_midi
;
202 int autoconnect_midi_index
;
204 vector
<jack_host_base
*> plugins
;
205 main_window
*main_win
;
206 bool restoring_session
;
207 std::set
<std::string
> instances
;
208 GtkWidget
*progress_window
;
212 void add_plugin(string name
, string preset
, string instance_name
= string());
213 void create_plugins_from_list();
216 bool activate_preset(int plugin
, const std::string
&preset
, bool builtin
);
218 static gboolean
update_lash(void *self
) { ((host_session
*)self
)->update_lash(); return TRUE
; }
221 void send_lash(LASH_Event_Type type
, const std::string
&data
) {
222 lash_send_event(lash_client
, lash_event_new_with_all(type
, data
.c_str()));
226 virtual void new_plugin(const char *name
);
227 virtual void remove_plugin(plugin_ctl_iface
*plugin
);
228 void remove_all_plugins();
229 std::string
get_next_instance_name(const std::string
&effect_name
);
231 /// Create a toplevel window with progress bar
232 GtkWidget
*create_progress_window();
233 /// Implementation of progress_report_iface function
234 void report_progress(float percentage
, const std::string
&message
);
236 /// Implementation of open file functionality (TODO)
237 virtual char *open_file(const char *name
);
238 /// Implementation of save file functionality
239 virtual char *save_file(const char *name
);
242 host_session::host_session()
244 client_name
= "calf";
252 restoring_session
= false;
253 main_win
= new main_window
;
254 main_win
->set_owner(this);
255 progress_window
= NULL
;
256 autoconnect_midi_index
= -1;
259 std::string
host_session::get_next_instance_name(const std::string
&effect_name
)
261 if (!instances
.count(effect_name
))
263 for (int i
= 2; ; i
++)
265 string tmp
= string(effect_name
) + i2s(i
);
266 if (!instances
.count(tmp
))
273 void host_session::add_plugin(string name
, string preset
, string instance_name
)
275 if (instance_name
.empty())
276 instance_name
= get_next_instance_name(name
);
277 jack_host_base
*jh
= create_jack_host(name
.c_str(), instance_name
, this);
280 #define PER_MODULE_ITEM(name, isSynth, jackname) jackname ", "
281 #include <calf/modulelist.h>
284 s
= s
.substr(0, s
.length() - 2);
285 throw text_exception("Unknown plugin name; allowed are: " + s
);
287 instances
.insert(jh
->instance_name
);
290 plugins
.push_back(jh
);
292 main_win
->add_plugin(jh
);
293 if (!preset
.empty()) {
294 if (!activate_preset(plugins
.size() - 1, preset
, false))
296 if (!activate_preset(plugins
.size() - 1, preset
, true))
298 fprintf(stderr
, "Unknown preset: %s\n", preset
.c_str());
304 void host_session::report_progress(float percentage
, const std::string
&message
)
306 if (percentage
< 100)
308 if (!progress_window
) {
309 progress_window
= create_progress_window();
310 gtk_window_set_modal (GTK_WINDOW (progress_window
), TRUE
);
311 if (main_win
->toplevel
)
312 gtk_window_set_transient_for (GTK_WINDOW (progress_window
), main_win
->toplevel
);
314 gtk_widget_show(progress_window
);
315 GtkWidget
*pbar
= gtk_bin_get_child (GTK_BIN (progress_window
));
316 if (!message
.empty())
317 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pbar
), message
.c_str());
318 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pbar
), percentage
/ 100.0);
322 if (progress_window
) {
323 gtk_window_set_modal (GTK_WINDOW (progress_window
), FALSE
);
324 gtk_widget_destroy (progress_window
);
325 progress_window
= NULL
;
329 while (gtk_events_pending ())
330 gtk_main_iteration ();
334 void host_session::create_plugins_from_list()
336 for (unsigned int i
= 0; i
< plugin_names
.size(); i
++) {
337 add_plugin(plugin_names
[i
], presets
.count(i
) ? presets
[i
] : string());
341 GtkWidget
*host_session::create_progress_window()
343 GtkWidget
*tlw
= gtk_window_new ( GTK_WINDOW_TOPLEVEL
);
344 gtk_window_set_type_hint (GTK_WINDOW (tlw
), GDK_WINDOW_TYPE_HINT_DIALOG
);
345 GtkWidget
*pbar
= gtk_progress_bar_new();
346 gtk_container_add (GTK_CONTAINER(tlw
), pbar
);
347 gtk_widget_show_all (pbar
);
351 void host_session::open()
353 if (!input_name
.empty()) client
.input_name
= input_name
;
354 if (!output_name
.empty()) client
.output_name
= output_name
;
355 if (!midi_name
.empty()) client
.midi_name
= midi_name
;
357 gtk_rc_parse(PKGLIBDIR
"calf.rc");
358 client
.open(client_name
.c_str());
359 main_win
->prefix
= client_name
+ " - ";
360 main_win
->conditions
.insert("jackhost");
361 main_win
->conditions
.insert("directlink");
362 if (!restoring_session
)
363 create_plugins_from_list();
365 gtk_signal_connect(GTK_OBJECT(main_win
->toplevel
), "destroy", G_CALLBACK(destroy
), NULL
);
368 void host_session::new_plugin(const char *name
)
370 jack_host_base
*jh
= create_jack_host(name
, get_next_instance_name(name
), this);
373 instances
.insert(jh
->instance_name
);
376 plugins
.push_back(jh
);
378 main_win
->add_plugin(jh
);
381 void host_session::remove_plugin(plugin_ctl_iface
*plugin
)
383 for (unsigned int i
= 0; i
< plugins
.size(); i
++)
385 if (plugins
[i
] == plugin
)
388 plugins
.erase(plugins
.begin() + i
);
389 main_win
->del_plugin(plugin
);
396 void host_session::remove_all_plugins()
398 while(!plugins
.empty())
400 plugin_ctl_iface
*plugin
= plugins
[0];
402 plugins
.erase(plugins
.begin());
403 main_win
->del_plugin(plugin
);
408 bool host_session::activate_preset(int plugin_no
, const std::string
&preset
, bool builtin
)
410 string cur_plugin
= plugins
[plugin_no
]->get_id();
411 preset_vector
&pvec
= (builtin
? get_builtin_presets() : get_user_presets()).presets
;
412 for (unsigned int i
= 0; i
< pvec
.size(); i
++) {
413 if (pvec
[i
].name
== preset
&& pvec
[i
].plugin
== cur_plugin
)
415 pvec
[i
].activate(plugins
[plugin_no
]);
416 if (gui_win
&& gui_win
->gui
)
417 gui_win
->gui
->refresh();
424 void host_session::connect()
427 #if USE_LASH && !USE_LASH_0_6
429 lash_jack_client_name(lash_client
, client
.get_name().c_str());
431 if (!restoring_session
)
433 string cnp
= client
.get_name() + ":";
434 for (unsigned int i
= 0; i
< plugins
.size(); i
++) {
435 if (chains
.count(i
)) {
438 if (plugins
[0]->get_output_count() < 2)
440 fprintf(stderr
, "Cannot connect input to plugin %s - incompatible ports\n", plugins
[0]->name
.c_str());
442 client
.connect("system:capture_1", cnp
+ plugins
[0]->get_inputs()[0].name
);
443 client
.connect("system:capture_2", cnp
+ plugins
[0]->get_inputs()[1].name
);
448 if (plugins
[i
- 1]->get_output_count() < 2 || plugins
[i
]->get_input_count() < 2)
450 fprintf(stderr
, "Cannot connect plugins %s and %s - incompatible ports\n", plugins
[i
- 1]->name
.c_str(), plugins
[i
]->name
.c_str());
453 client
.connect(cnp
+ plugins
[i
- 1]->get_outputs()[0].name
, cnp
+ plugins
[i
]->get_inputs()[0].name
);
454 client
.connect(cnp
+ plugins
[i
- 1]->get_outputs()[1].name
, cnp
+ plugins
[i
]->get_inputs()[1].name
);
459 if (chains
.count(plugins
.size()) && plugins
.size())
461 int last
= plugins
.size() - 1;
462 if (plugins
[last
]->get_output_count() < 2)
464 fprintf(stderr
, "Cannot connect plugin %s to output - incompatible ports\n", plugins
[last
]->name
.c_str());
466 client
.connect(cnp
+ plugins
[last
]->get_outputs()[0].name
, "system:playback_1");
467 client
.connect(cnp
+ plugins
[last
]->get_outputs()[1].name
, "system:playback_2");
470 if (autoconnect_midi
!= "") {
471 for (unsigned int i
= 0; i
< plugins
.size(); i
++)
473 if (plugins
[i
]->get_midi())
474 client
.connect(autoconnect_midi
, cnp
+ plugins
[i
]->get_midi_port()->name
);
478 if (autoconnect_midi_index
!= -1) {
479 const char **ports
= client
.get_ports("(system|alsa_pcm):.*", JACK_DEFAULT_MIDI_TYPE
, JackPortIsOutput
);
480 for (int j
= 0; ports
&& ports
[j
]; j
++)
482 if (j
+ 1 == autoconnect_midi_index
) {
483 for (unsigned int i
= 0; i
< plugins
.size(); i
++)
485 if (plugins
[i
]->get_midi())
486 client
.connect(ports
[j
], cnp
+ plugins
[i
]->get_midi_port()->name
);
497 send_lash(LASH_Client_Name
, "calf-"+client_name
);
499 lash_source_id
= g_timeout_add_full(G_PRIORITY_LOW
, 250, update_lash
, this, NULL
); // 4 LASH reads per second... should be enough?
504 void host_session::close()
508 g_source_remove(lash_source_id
);
510 main_win
->on_closed();
511 main_win
->close_guis();
513 client
.delete_plugins();
517 static string
stripfmt(string x
)
521 if (x
.substr(x
.length() - 2) != "%d")
523 return x
.substr(0, x
.length() - 2);
526 char *host_session::open_file(const char *name
)
530 remove_all_plugins();
532 printf("Size %d\n", (int)pl
.plugins
.size());
533 for (unsigned int i
= 0; i
< pl
.plugins
.size(); i
++)
535 preset_list::plugin_snapshot
&ps
= pl
.plugins
[i
];
536 client
.input_nr
= ps
.input_index
;
537 client
.output_nr
= ps
.output_index
;
538 client
.midi_nr
= ps
.midi_index
;
539 printf("Loading %s\n", ps
.type
.c_str());
540 if (ps
.preset_offset
< (int)pl
.presets
.size())
542 add_plugin(ps
.type
, "", ps
.instance_name
);
543 pl
.presets
[ps
.preset_offset
].activate(plugins
[i
]);
544 main_win
->refresh_plugin(plugins
[i
]);
548 catch(preset_exception
&e
)
550 // XXXKF this will leak
551 char *data
= strdup(e
.what());
558 char *host_session::save_file(const char *name
)
560 string i_name
= stripfmt(client
.input_name
);
561 string o_name
= stripfmt(client
.output_name
);
562 string m_name
= stripfmt(client
.midi_name
);
564 data
= "<?xml version=\"1.1\" encoding=\"utf-8\">\n";
566 for (unsigned int i
= 0; i
< plugins
.size(); i
++) {
567 jack_host_base
*p
= plugins
[i
];
568 plugin_preset preset
;
569 preset
.plugin
= p
->get_id();
572 data
+= to_xml_attr("type", preset
.plugin
);
573 data
+= to_xml_attr("instance-name", p
->instance_name
);
574 if (p
->get_input_count())
575 data
+= to_xml_attr("input-index", p
->get_inputs()[0].name
.substr(i_name
.length()));
576 if (p
->get_output_count())
577 data
+= to_xml_attr("output-index", p
->get_outputs()[0].name
.substr(o_name
.length()));
578 if (p
->get_midi_port())
579 data
+= to_xml_attr("midi-index", p
->get_midi_port()->name
.substr(m_name
.length()));
581 data
+= preset
.to_xml();
582 data
+= "</plugin>\n";
585 FILE *f
= fopen(name
, "w");
586 if (!f
|| 1 != fwrite(data
.c_str(), data
.length(), 1, f
))
590 return strdup(strerror(e
));
593 return strdup(strerror(errno
));
602 void host_session::update_lash()
605 lash_event_t
*event
= lash_get_event(lash_client
);
609 // printf("type = %d\n", lash_event_get_type(event));
611 switch(lash_event_get_type(event
)) {
612 case LASH_Save_Data_Set
:
614 lash_config_t
*cfg
= lash_config_new_with_key("global");
617 string i_name
= stripfmt(client
.input_name
);
618 string o_name
= stripfmt(client
.output_name
);
619 string m_name
= stripfmt(client
.midi_name
);
620 tmp
["input_prefix"] = i_name
;
621 tmp
["output_prefix"] = stripfmt(client
.output_name
);
622 tmp
["midi_prefix"] = stripfmt(client
.midi_name
);
623 pstr
= encode_map(tmp
);
624 lash_config_set_value(cfg
, pstr
.c_str(), pstr
.length());
625 lash_send_config(lash_client
, cfg
);
627 for (unsigned int i
= 0; i
< plugins
.size(); i
++) {
628 jack_host_base
*p
= plugins
[i
];
630 plugin_preset preset
;
631 preset
.plugin
= p
->get_id();
633 sprintf(ss
, "Plugin%d", i
);
634 pstr
= preset
.to_xml();
636 tmp
["instance_name"] = p
->instance_name
;
637 if (p
->get_input_count())
638 tmp
["input_name"] = p
->get_inputs()[0].name
.substr(i_name
.length());
639 if (p
->get_output_count())
640 tmp
["output_name"] = p
->get_outputs()[0].name
.substr(o_name
.length());
641 if (p
->get_midi_port())
642 tmp
["midi_name"] = p
->get_midi_port()->name
.substr(m_name
.length());
643 tmp
["preset"] = pstr
;
644 pstr
= encode_map(tmp
);
645 lash_config_t
*cfg
= lash_config_new_with_key(ss
);
646 lash_config_set_value(cfg
, pstr
.c_str(), pstr
.length());
647 lash_send_config(lash_client
, cfg
);
649 send_lash(LASH_Save_Data_Set
, "");
653 case LASH_Restore_Data_Set
:
655 // printf("!!!Restore data set!!!\n");
656 remove_all_plugins();
657 while(lash_config_t
*cfg
= lash_get_config(lash_client
)) {
658 const char *key
= lash_config_get_key(cfg
);
659 // printf("key = %s\n", lash_config_get_key(cfg));
660 string data
= string((const char *)lash_config_get_value(cfg
), lash_config_get_value_size(cfg
));
661 if (!strcmp(key
, "global"))
664 decode_map(dict
, data
);
665 if (dict
.count("input_prefix")) client
.input_name
= dict
["input_prefix"]+"%d";
666 if (dict
.count("output_prefix")) client
.output_name
= dict
["output_prefix"]+"%d";
667 if (dict
.count("midi_prefix")) client
.midi_name
= dict
["midi_prefix"]+"%d";
669 if (!strncmp(key
, "Plugin", 6))
671 unsigned int nplugin
= atoi(key
+ 6);
673 decode_map(dict
, data
);
674 data
= dict
["preset"];
675 string instance_name
;
676 if (dict
.count("instance_name")) instance_name
= dict
["instance_name"];
677 if (dict
.count("input_name")) client
.input_nr
= atoi(dict
["input_name"].c_str());
678 if (dict
.count("output_name")) client
.output_nr
= atoi(dict
["output_name"].c_str());
679 if (dict
.count("midi_name")) client
.midi_nr
= atoi(dict
["midi_name"].c_str());
681 tmp
.parse("<presets>"+data
+"</presets>", false);
682 if (tmp
.presets
.size())
684 printf("Load plugin %s\n", tmp
.presets
[0].plugin
.c_str());
685 add_plugin(tmp
.presets
[0].plugin
, "", instance_name
);
686 tmp
.presets
[0].activate(plugins
[nplugin
]);
687 main_win
->refresh_plugin(plugins
[nplugin
]);
690 lash_config_destroy(cfg
);
692 send_lash(LASH_Restore_Data_Set
, "");
701 g_warning("Unhandled LASH event %d (%s)", lash_event_get_type(event
), lash_event_get_string(event
));
709 void host_session::update_lash()
711 lash_dispatch(lash_client
);
714 bool save_data_set_cb(lash_config_handle_t
*handle
, void *user_data
)
716 host_session
*sess
= static_cast<host_session
*>(user_data
);
719 string i_name
= stripfmt(sess
->client
.input_name
);
720 string o_name
= stripfmt(sess
->client
.output_name
);
721 string m_name
= stripfmt(sess
->client
.midi_name
);
722 tmp
["input_prefix"] = i_name
;
723 tmp
["output_prefix"] = stripfmt(sess
->client
.output_name
);
724 tmp
["midi_prefix"] = stripfmt(sess
->client
.midi_name
);
725 pstr
= encode_map(tmp
);
726 lash_config_write_raw(handle
, "global", pstr
.c_str(), pstr
.length());
727 for (unsigned int i
= 0; i
< sess
->plugins
.size(); i
++) {
728 jack_host_base
*p
= sess
->plugins
[i
];
730 plugin_preset preset
;
731 preset
.plugin
= p
->get_id();
733 sprintf(ss
, "Plugin%d", i
);
734 pstr
= preset
.to_xml();
736 tmp
["instance_name"] = p
->instance_name
;
737 if (p
->get_input_count())
738 tmp
["input_name"] = p
->get_inputs()[0].name
.substr(i_name
.length());
739 if (p
->get_output_count())
740 tmp
["output_name"] = p
->get_outputs()[0].name
.substr(o_name
.length());
741 if (p
->get_midi_port())
742 tmp
["midi_name"] = p
->get_midi_port()->name
.substr(m_name
.length());
743 tmp
["preset"] = pstr
;
744 pstr
= encode_map(tmp
);
745 lash_config_write_raw(handle
, ss
, pstr
.c_str(), pstr
.length());
750 bool load_data_set_cb(lash_config_handle_t
*handle
, void *user_data
)
752 host_session
*sess
= static_cast<host_session
*>(user_data
);
756 sess
->remove_all_plugins();
757 while((size
= lash_config_read(handle
, &key
, (void *)&value
, &type
))) {
758 if (size
== -1 || type
!= LASH_TYPE_RAW
)
760 string data
= string(value
, size
);
761 if (!strcmp(key
, "global"))
764 decode_map(dict
, data
);
765 if (dict
.count("input_prefix")) sess
->client
.input_name
= dict
["input_prefix"]+"%d";
766 if (dict
.count("output_prefix")) sess
->client
.output_name
= dict
["output_prefix"]+"%d";
767 if (dict
.count("midi_prefix")) sess
->client
.midi_name
= dict
["midi_prefix"]+"%d";
768 } else if (!strncmp(key
, "Plugin", 6)) {
769 unsigned int nplugin
= atoi(key
+ 6);
771 decode_map(dict
, data
);
772 data
= dict
["preset"];
773 string instance_name
;
774 if (dict
.count("instance_name")) instance_name
= dict
["instance_name"];
775 if (dict
.count("input_name")) sess
->client
.input_nr
= atoi(dict
["input_name"].c_str());
776 if (dict
.count("output_name")) sess
->client
.output_nr
= atoi(dict
["output_name"].c_str());
777 if (dict
.count("midi_name")) sess
->client
.midi_nr
= atoi(dict
["midi_name"].c_str());
779 tmp
.parse("<presets>"+data
+"</presets>", false);
780 if (tmp
.presets
.size())
782 printf("Load plugin %s\n", tmp
.presets
[0].plugin
.c_str());
783 sess
->add_plugin(tmp
.presets
[0].plugin
, "", instance_name
);
784 tmp
.presets
[0].activate(sess
->plugins
[nplugin
]);
785 sess
->main_win
->refresh_plugin(sess
->plugins
[nplugin
]);
792 bool quit_cb(void *user_data
)
801 host_session current_session
;
803 int main(int argc
, char *argv
[])
805 host_session
&sess
= current_session
;
806 gtk_rc_add_default_file(PKGLIBDIR
"calf.rc");
807 gtk_init(&argc
, &argv
);
811 for (int i
= 1; i
< argc
; i
++)
813 if (!strncmp(argv
[i
], "--lash-project=", 14)) {
814 sess
.restoring_session
= true;
818 sess
.lash_args
= lash_extract_args(&argc
, &argv
);
819 sess
.lash_client
= lash_init(sess
.lash_args
, PACKAGE_NAME
, LASH_Config_Data_Set
, LASH_PROTOCOL(2, 0));
821 sess
.lash_client
= lash_client_open(PACKAGE_NAME
, LASH_Config_Data_Set
, argc
, argv
);
822 sess
.restoring_session
= lash_client_is_being_restored(sess
.lash_client
);
823 lash_set_save_data_set_callback(sess
.lash_client
, save_data_set_cb
, &sess
);
824 lash_set_load_data_set_callback(sess
.lash_client
, load_data_set_cb
, &sess
);
825 lash_set_quit_callback(sess
.lash_client
, quit_cb
, NULL
);
827 if (!sess
.lash_client
) {
828 g_warning("Warning: failed to create a LASH connection");
834 int c
= getopt_long(argc
, argv
, "c:i:o:m:M:ehv", long_options
, &option_index
);
843 printf("%s\n", PACKAGE_STRING
);
846 fprintf(stderr
, "Warning: switch -%c is deprecated!\n", c
);
849 sess
.client_name
= optarg
;
852 sess
.input_name
= string(optarg
) + "_%d";
855 sess
.output_name
= string(optarg
) + "_%d";
858 sess
.midi_name
= string(optarg
) + "_%d";
862 sess
.autoconnect_midi_index
= atoi(optarg
);
865 sess
.autoconnect_midi
= string(optarg
);
869 while(optind
< argc
) {
870 if (!strcmp(argv
[optind
], "!")) {
871 sess
.chains
.insert(sess
.plugin_names
.size());
874 string plugname
= argv
[optind
++];
875 size_t pos
= plugname
.find(":");
876 if (pos
!= string::npos
) {
877 sess
.presets
[sess
.plugin_names
.size()] = plugname
.substr(pos
+ 1);
878 plugname
= plugname
.substr(0, pos
);
880 sess
.plugin_names
.push_back(plugname
);
884 get_builtin_presets().load_defaults(true);
885 get_user_presets().load_defaults(false);
887 catch(calf_plugins::preset_exception
&e
)
889 // XXXKF this exception is already handled by load_defaults, so this is redundant
890 fprintf(stderr
, "Error while loading presets: %s\n", e
.what());
896 sess
.client
.activate();
900 #if USE_LASH && !USE_LASH_0_6
902 lash_args_destroy(sess
.lash_args
);
904 // this is now done on preset add
905 // save_presets(get_preset_filename().c_str());
907 catch(std::exception
&e
)
909 fprintf(stderr
, "%s\n", e
.what());