2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2011 Krzysztof Foltman
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (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
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "config-api.h"
48 int cmd_quit(struct cbox_menu_item_command
*item
, void *context
)
53 int cmd_load_scene(struct cbox_menu_item_command
*item
, void *context
)
56 struct cbox_scene
*scene
= app
.rt
->scene
;
57 cbox_scene_clear(scene
);
58 if (!cbox_scene_load(scene
, item
->item
.item_context
, &error
))
59 cbox_print_error(error
);
63 int cmd_load_instrument(struct cbox_menu_item_command
*item
, void *context
)
66 struct cbox_scene
*scene
= app
.rt
->scene
;
67 cbox_scene_clear(scene
);
68 struct cbox_layer
*layer
= cbox_layer_new_with_instrument(scene
, (char *)item
->item
.item_context
, &error
);
72 if (!cbox_scene_add_layer(scene
, layer
, &error
))
73 cbox_print_error(error
);
77 cbox_print_error(error
);
82 int cmd_load_layer(struct cbox_menu_item_command
*item
, void *context
)
85 struct cbox_scene
*scene
= app
.rt
->scene
;
86 cbox_scene_clear(scene
);
87 struct cbox_layer
*layer
= cbox_layer_new_from_config(scene
, (char *)item
->item
.item_context
, &error
);
91 if (!cbox_scene_add_layer(scene
, layer
, &error
))
92 cbox_print_error(error
);
96 cbox_print_error(error
);
102 gchar
*scene_format_value(const struct cbox_menu_item_static
*item
, void *context
)
104 return strdup(app
.current_scene_name
);
107 gchar
*transport_format_value(const struct cbox_menu_item_static
*item
, void *context
)
110 // struct cbox_bbt bbt;
111 // cbox_master_to_bbt(app.rt->master, &bbt);
112 if (app
.rt
->scene
->spb
== NULL
)
113 return g_strdup("N/A");
114 if (!strcmp((const char *)item
->item
.item_context
, "pos"))
115 return g_strdup_printf("%d", (int)app
.rt
->scene
->spb
->song_pos_samples
);
117 return g_strdup_printf("%d", (int)app
.rt
->scene
->spb
->song_pos_ppqn
);
120 struct cbox_config_section_cb_data
122 struct cbox_menu
*menu
;
123 cbox_menu_item_execute_func func
;
127 static void config_key_process(void *user_data
, const char *key
)
129 struct cbox_config_section_cb_data
*data
= user_data
;
131 if (!strncmp(key
, data
->prefix
, strlen(data
->prefix
)))
133 char *title
= cbox_config_get_string(key
, "title");
135 cbox_menu_add_item(data
->menu
, cbox_menu_item_new_command(title
, data
->func
, strdup(key
+ strlen(data
->prefix
))));
137 cbox_menu_add_item(data
->menu
, cbox_menu_item_new_command(key
, data
->func
, strdup(key
+ strlen(data
->prefix
))));
141 struct cbox_menu
*create_scene_menu(struct cbox_menu_item_menu
*item
, void *menu_context
)
143 struct cbox_menu
*scene_menu
= cbox_menu_new();
144 struct cbox_config_section_cb_data cb
= { .menu
= scene_menu
};
146 cbox_menu_add_item(scene_menu
, cbox_menu_item_new_static("Scenes", NULL
, NULL
));
147 cb
.prefix
= "scene:";
148 cb
.func
= cmd_load_scene
;
149 cbox_config_foreach_section(config_key_process
, &cb
);
150 cbox_menu_add_item(scene_menu
, cbox_menu_item_new_static("Layers", NULL
, NULL
));
151 cb
.prefix
= "layer:";
152 cb
.func
= cmd_load_layer
;
153 cbox_config_foreach_section(config_key_process
, &cb
);
154 cbox_menu_add_item(scene_menu
, cbox_menu_item_new_static("Instruments", NULL
, NULL
));
155 cb
.prefix
= "instrument:";
156 cb
.func
= cmd_load_instrument
;
157 cbox_config_foreach_section(config_key_process
, &cb
);
159 cbox_menu_add_item(scene_menu
, cbox_menu_item_new_menu("OK", NULL
, NULL
));
164 ///////////////////////////////////////////////////////////////////////////////
166 static struct cbox_command_target
*find_module_target(const char *type
, GError
**error
)
168 struct cbox_scene
*scene
= app
.rt
->scene
;
169 for (int i
= 0; i
< scene
->instrument_count
; i
++)
171 if (!strcmp(scene
->instruments
[i
]->module
->engine_name
, type
))
172 return &scene
->instruments
[i
]->module
->cmd_target
;
174 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "Cannot find a module of type '%s'", type
);
179 int cmd_stream_rewind(struct cbox_menu_item_command
*item
, void *context
)
181 GError
*error
= NULL
;
182 struct cbox_command_target
*target
= find_module_target("stream_player", &error
);
184 cbox_execute_on(target
, NULL
, "/seek", "i", &error
, 0);
185 cbox_print_error_if(error
);
189 int cmd_stream_play(struct cbox_menu_item_command
*item
, void *context
)
191 GError
*error
= NULL
;
192 struct cbox_command_target
*target
= find_module_target("stream_player", &error
);
194 cbox_execute_on(target
, NULL
, "/play", "", &error
);
195 cbox_print_error_if(error
);
199 int cmd_stream_stop(struct cbox_menu_item_command
*item
, void *context
)
201 GError
*error
= NULL
;
202 struct cbox_command_target
*target
= find_module_target("stream_player", &error
);
204 cbox_execute_on(target
, NULL
, "/stop", "", &error
);
205 cbox_print_error_if(error
);
209 int cmd_stream_unload(struct cbox_menu_item_command
*item
, void *context
)
211 GError
*error
= NULL
;
212 struct cbox_command_target
*target
= find_module_target("stream_player", &error
);
214 cbox_execute_on(target
, NULL
, "/unload", "", &error
);
215 cbox_print_error_if(error
);
219 gboolean
result_parser_status(struct cbox_command_target
*ct
, struct cbox_command_target
*fb
, struct cbox_osc_command
*cmd
, GError
**error
)
221 cbox_osc_command_dump(cmd
);
225 int cmd_stream_status(struct cbox_menu_item_command
*item
, void *context
)
227 struct cbox_command_target response
= { NULL
, result_parser_status
};
228 GError
*error
= NULL
;
229 struct cbox_command_target
*target
= find_module_target("stream_player", &error
);
231 cbox_execute_on(target
, &response
, "/status", "", &error
);
232 cbox_print_error_if(error
);
236 int cmd_stream_load(struct cbox_menu_item_command
*item
, void *context
)
238 GError
*error
= NULL
;
239 struct cbox_command_target
*target
= find_module_target("stream_player", &error
);
241 cbox_execute_on(target
, NULL
, "/load", "si", &error
, (gchar
*)item
->item
.item_context
, 0);
242 cbox_print_error_if(error
);
246 struct cbox_menu
*create_stream_menu(struct cbox_menu_item_menu
*item
, void *menu_context
)
248 struct cbox_menu
*menu
= cbox_menu_new();
249 struct cbox_config_section_cb_data cb
= { .menu
= menu
};
251 cbox_menu_add_item(menu
, cbox_menu_item_new_static("Module commands", NULL
, NULL
));
252 cbox_menu_add_item(menu
, cbox_menu_item_new_command("Play stream", cmd_stream_play
, NULL
));
253 cbox_menu_add_item(menu
, cbox_menu_item_new_command("Stop stream", cmd_stream_stop
, NULL
));
254 cbox_menu_add_item(menu
, cbox_menu_item_new_command("Rewind stream", cmd_stream_rewind
, NULL
));
255 cbox_menu_add_item(menu
, cbox_menu_item_new_command("Describe stream", cmd_stream_status
, NULL
));
256 cbox_menu_add_item(menu
, cbox_menu_item_new_command("Unload stream", cmd_stream_unload
, NULL
));
259 if (glob("*.wav", GLOB_TILDE_CHECK
, NULL
, &g
) == 0)
261 for (int i
= 0; i
< g
.gl_pathc
; i
++)
263 cbox_menu_add_item(menu
, cbox_menu_item_new_command(g_strdup_printf("Load: %s", g
.gl_pathv
[i
]), cmd_stream_load
, g_strdup(g
.gl_pathv
[i
])));
269 cbox_menu_add_item(menu
, cbox_menu_item_new_menu("OK", NULL
, NULL
));
274 ///////////////////////////////////////////////////////////////////////////////
276 int cmd_pattern_none(struct cbox_menu_item_command
*item
, void *context
)
278 cbox_song_clear(app
.rt
->master
->song
);
279 cbox_rt_update_song_playback(app
.rt
);
283 int cmd_pattern_simple(struct cbox_menu_item_command
*item
, void *context
)
285 cbox_song_use_looped_pattern(app
.rt
->master
->song
, cbox_midi_pattern_new_metronome(app
.rt
->master
->song
, 1));
289 int cmd_pattern_normal(struct cbox_menu_item_command
*item
, void *context
)
291 cbox_song_use_looped_pattern(app
.rt
->master
->song
, cbox_midi_pattern_new_metronome(app
.rt
->master
->song
, app
.rt
->master
->timesig_nom
));
295 int cmd_load_drumpattern(struct cbox_menu_item_command
*item
, void *context
)
297 cbox_song_use_looped_pattern(app
.rt
->master
->song
, cbox_midi_pattern_load(app
.rt
->master
->song
, item
->item
.item_context
, 1));
301 int cmd_load_drumtrack(struct cbox_menu_item_command
*item
, void *context
)
303 cbox_song_use_looped_pattern(app
.rt
->master
->song
, cbox_midi_pattern_load_track(app
.rt
->master
->song
, item
->item
.item_context
, 1));
307 int cmd_load_pattern(struct cbox_menu_item_command
*item
, void *context
)
309 cbox_song_use_looped_pattern(app
.rt
->master
->song
, cbox_midi_pattern_load(app
.rt
->master
->song
, item
->item
.item_context
, 0));
313 int cmd_load_track(struct cbox_menu_item_command
*item
, void *context
)
315 cbox_song_use_looped_pattern(app
.rt
->master
->song
, cbox_midi_pattern_load_track(app
.rt
->master
->song
, item
->item
.item_context
, 0));
319 struct cbox_menu
*create_pattern_menu(struct cbox_menu_item_menu
*item
, void *menu_context
)
321 struct cbox_menu
*menu
= cbox_menu_new();
322 struct cbox_config_section_cb_data cb
= { .menu
= menu
};
324 cbox_menu_add_item(menu
, cbox_menu_item_new_static("Pattern commands", NULL
, NULL
));
325 cbox_menu_add_item(menu
, cbox_menu_item_new_command("No pattern", cmd_pattern_none
, NULL
));
326 cbox_menu_add_item(menu
, cbox_menu_item_new_command("Simple metronome", cmd_pattern_simple
, NULL
));
327 cbox_menu_add_item(menu
, cbox_menu_item_new_command("Normal metronome", cmd_pattern_normal
, NULL
));
329 cbox_menu_add_item(menu
, cbox_menu_item_new_static("Drum tracks", NULL
, NULL
));
330 cb
.prefix
= "drumtrack:";
331 cb
.func
= cmd_load_drumtrack
;
332 cbox_config_foreach_section(config_key_process
, &cb
);
334 cbox_menu_add_item(menu
, cbox_menu_item_new_static("Melodic tracks", NULL
, NULL
));
335 cb
.prefix
= "track:";
336 cb
.func
= cmd_load_track
;
337 cbox_config_foreach_section(config_key_process
, &cb
);
339 cbox_menu_add_item(menu
, cbox_menu_item_new_static("Drum patterns", NULL
, NULL
));
340 cb
.prefix
= "drumpattern:";
341 cb
.func
= cmd_load_drumpattern
;
342 cbox_config_foreach_section(config_key_process
, &cb
);
344 cbox_menu_add_item(menu
, cbox_menu_item_new_static("Melodic patterns", NULL
, NULL
));
345 cb
.prefix
= "pattern:";
346 cb
.func
= cmd_load_pattern
;
347 cbox_config_foreach_section(config_key_process
, &cb
);
349 cbox_menu_add_item(menu
, cbox_menu_item_new_menu("OK", NULL
, NULL
));
354 struct cbox_menu
*create_main_menu()
356 struct cbox_menu
*main_menu
= cbox_menu_new();
357 cbox_menu_add_item(main_menu
, cbox_menu_item_new_static("Current scene:", scene_format_value
, NULL
));
358 cbox_menu_add_item(main_menu
, cbox_menu_item_new_dynamic_menu("Set scene", create_scene_menu
, NULL
));
359 cbox_menu_add_item(main_menu
, cbox_menu_item_new_dynamic_menu("Module control", create_stream_menu
, NULL
));
360 cbox_menu_add_item(main_menu
, cbox_menu_item_new_dynamic_menu("Pattern control", create_pattern_menu
, NULL
));
362 cbox_menu_add_item(main_menu
, cbox_menu_item_new_static("Variables", NULL
, NULL
));
363 // cbox_menu_add_item(main_menu, cbox_menu_item_new_int("foo:", &var1, 0, 127, NULL));
364 // cbox_menu_add_item(main_menu, "bar:", menu_item_value_double, &mx_double_var2, &var2);
365 cbox_menu_add_item(main_menu
, cbox_menu_item_new_static("pos:", transport_format_value
, "pos"));
366 cbox_menu_add_item(main_menu
, cbox_menu_item_new_static("bbt:", transport_format_value
, "bbt"));
367 cbox_menu_add_item(main_menu
, cbox_menu_item_new_static("Commands", NULL
, NULL
));
368 cbox_menu_add_item(main_menu
, cbox_menu_item_new_command("Quit", cmd_quit
, NULL
));
372 static gboolean
app_process_cmd(struct cbox_command_target
*ct
, struct cbox_command_target
*fb
, struct cbox_osc_command
*cmd
, GError
**error
)
376 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "NULL command");
379 if (cmd
->command
[0] != '/')
381 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "Invalid global command path '%s'", cmd
->command
);
384 const char *obj
= &cmd
->command
[1];
385 const char *pos
= strchr(obj
, '/');
389 if (!strncmp(obj
, "master/", 7))
390 return cbox_execute_sub(&app
.rt
->master
->cmd_target
, fb
, cmd
, pos
, error
);
392 if (!strncmp(obj
, "config/", 7))
393 return cbox_execute_sub(&app
.config_cmd_target
, fb
, cmd
, pos
, error
);
395 if (!strncmp(obj
, "scene/", 6))
396 return cbox_execute_sub(&app
.rt
->scene
->cmd_target
, fb
, cmd
, pos
, error
);
398 if (!strncmp(obj
, "rt/", 3))
399 return cbox_execute_sub(&app
.rt
->cmd_target
, fb
, cmd
, pos
, error
);
401 if (!strncmp(obj
, "song/", 5))
402 return cbox_execute_sub(&app
.rt
->master
->song
->cmd_target
, fb
, cmd
, pos
, error
);
404 if (!strncmp(obj
, "waves/", 6))
405 return cbox_execute_sub(&cbox_waves_cmd_target
, fb
, cmd
, pos
, error
);
407 if (!strncmp(obj
, "doc/", 4))
408 return cbox_execute_sub(cbox_document_get_cmd_target(app
.document
), fb
, cmd
, pos
, error
);
411 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "Unknown combination of target path and argument: '%s', '%s'", cmd
->command
, cmd
->arg_types
);
416 if (!strcmp(obj
, "on_idle") && !strcmp(cmd
->arg_types
, ""))
422 if (!strcmp(obj
, "send_event") && (!strcmp(cmd
->arg_types
, "iii") || !strcmp(cmd
->arg_types
, "ii") || !strcmp(cmd
->arg_types
, "i")))
424 int mcmd
= CBOX_ARG_I(cmd
, 0);
425 int arg1
= 0, arg2
= 0;
426 if (cmd
->arg_types
[1] == 'i')
428 arg1
= CBOX_ARG_I(cmd
, 1);
429 if (cmd
->arg_types
[2] == 'i')
430 arg2
= CBOX_ARG_I(cmd
, 2);
432 struct cbox_midi_buffer buf
;
433 cbox_midi_buffer_init(&buf
);
434 cbox_midi_buffer_write_inline(&buf
, 0, mcmd
, arg1
, arg2
);
435 cbox_rt_send_events(app
.rt
, &buf
);
439 if (!strcmp(obj
, "play_note") && !strcmp(cmd
->arg_types
, "iii"))
441 int channel
= CBOX_ARG_I(cmd
, 0);
442 int note
= CBOX_ARG_I(cmd
, 1);
443 int velocity
= CBOX_ARG_I(cmd
, 2);
444 struct cbox_midi_buffer buf
;
445 cbox_midi_buffer_init(&buf
);
446 cbox_midi_buffer_write_inline(&buf
, 0, 0x90 + ((channel
- 1) & 15), note
& 127, velocity
& 127);
447 cbox_midi_buffer_write_inline(&buf
, 1, 0x80 + ((channel
- 1) & 15), note
& 127, velocity
& 127);
448 cbox_rt_send_events(app
.rt
, &buf
);
452 if (!strcmp(obj
, "update_playback") && !strcmp(cmd
->arg_types
, ""))
454 cbox_rt_update_song_playback(app
.rt
);
458 if (!strcmp(obj
, "get_pattern") && !strcmp(cmd
->arg_types
, ""))
460 if (!cbox_check_fb_channel(fb
, cmd
->command
, error
))
463 if (app
.rt
->master
->song
&& app
.rt
->master
->song
->tracks
)
465 struct cbox_track
*track
= app
.rt
->master
->song
->tracks
->data
;
468 struct cbox_track_item
*item
= track
->items
->data
;
469 struct cbox_midi_pattern
*pattern
= item
->pattern
;
471 struct cbox_blob
*blob
= cbox_midi_pattern_to_blob(pattern
, &length
);
472 gboolean res
= cbox_execute_on(fb
, NULL
, "/pattern", "bi", error
, blob
, length
);
473 cbox_blob_destroy(blob
);
479 if (!strcmp(obj
, "new_meter") && !strcmp(cmd
->arg_types
, ""))
481 if (!cbox_check_fb_channel(fb
, cmd
->command
, error
))
484 struct cbox_meter
*meter
= cbox_meter_new(app
.document
, cbox_rt_get_sample_rate(app
.rt
));
486 return cbox_execute_on(fb
, NULL
, "/uuid", "o", error
, meter
);
489 if (!strcmp(obj
, "new_recorder") && !strcmp(cmd
->arg_types
, "s"))
491 if (!cbox_check_fb_channel(fb
, cmd
->command
, error
))
494 struct cbox_recorder
*rec
= cbox_recorder_new_stream(app
.rt
, CBOX_ARG_S(cmd
, 0));
496 return cbox_execute_on(fb
, NULL
, "/uuid", "o", error
, rec
);
499 if (!strcmp(obj
, "new_scene") && !strcmp(cmd
->arg_types
, "ii"))
501 if (!cbox_check_fb_channel(fb
, cmd
->command
, error
))
504 struct cbox_rt
*rt
= cbox_rt_new(app
.document
);
505 cbox_rt_set_offline(rt
, CBOX_ARG_I(cmd
, 0), CBOX_ARG_I(cmd
, 1));
506 struct cbox_scene
*rec
= cbox_scene_new(app
.document
, rt
, TRUE
);
508 return cbox_execute_on(fb
, NULL
, "/uuid", "o", error
, rec
);
511 if (!strcmp(obj
, "print_s") && !strcmp(cmd
->arg_types
, "s"))
513 g_message("Print: %s", CBOX_ARG_S(cmd
, 0));
517 if (!strcmp(obj
, "print_i") && !strcmp(cmd
->arg_types
, "i"))
519 g_message("Print: %d", CBOX_ARG_I(cmd
, 0));
523 if (!strcmp(obj
, "print_f") && !strcmp(cmd
->arg_types
, "f"))
525 g_message("Print: %f", CBOX_ARG_F(cmd
, 0));
530 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "Unknown combination of target path and argument: '%s', '%s'", cmd
->command
, cmd
->arg_types
);
535 struct config_foreach_data
539 struct cbox_command_target
*fb
;
544 void api_config_cb(void *user_data
, const char *key
)
546 struct config_foreach_data
*cfd
= user_data
;
549 if (cfd
->prefix
&& strncmp(cfd
->prefix
, key
, strlen(cfd
->prefix
)))
552 if (!cbox_execute_on(cfd
->fb
, NULL
, cfd
->command
, "s", cfd
->error
, key
))
554 cfd
->success
= FALSE
;
559 static gboolean
config_process_cmd(struct cbox_command_target
*ct
, struct cbox_command_target
*fb
, struct cbox_osc_command
*cmd
, GError
**error
)
561 if (!strcmp(cmd
->command
, "/sections") && (!strcmp(cmd
->arg_types
, "") || !strcmp(cmd
->arg_types
, "s")))
563 if (!cbox_check_fb_channel(fb
, cmd
->command
, error
))
566 struct config_foreach_data cfd
= {cmd
->arg_types
[0] == 's' ? CBOX_ARG_S(cmd
, 0) : NULL
, "/section", fb
, error
, TRUE
};
567 cbox_config_foreach_section(api_config_cb
, &cfd
);
570 else if (!strcmp(cmd
->command
, "/keys") && (!strcmp(cmd
->arg_types
, "s") || !strcmp(cmd
->arg_types
, "ss")))
572 if (!cbox_check_fb_channel(fb
, cmd
->command
, error
))
575 struct config_foreach_data cfd
= {cmd
->arg_types
[1] == 's' ? CBOX_ARG_S(cmd
, 1) : NULL
, "/key", fb
, error
, TRUE
};
576 cbox_config_foreach_key(api_config_cb
, CBOX_ARG_S(cmd
, 0), &cfd
);
579 else if (!strcmp(cmd
->command
, "/get") && !strcmp(cmd
->arg_types
, "ss"))
581 if (!cbox_check_fb_channel(fb
, cmd
->command
, error
))
584 const char *value
= cbox_config_get_string(CBOX_ARG_S(cmd
, 0), CBOX_ARG_S(cmd
, 1));
587 return cbox_execute_on(fb
, NULL
, "/value", "s", error
, value
);
589 else if (!strcmp(cmd
->command
, "/set") && !strcmp(cmd
->arg_types
, "sss"))
591 cbox_config_set_string(CBOX_ARG_S(cmd
, 0), CBOX_ARG_S(cmd
, 1), CBOX_ARG_S(cmd
, 2));
594 else if (!strcmp(cmd
->command
, "/delete") && !strcmp(cmd
->arg_types
, "ss"))
596 cbox_config_remove_key(CBOX_ARG_S(cmd
, 0), CBOX_ARG_S(cmd
, 1));
599 else if (!strcmp(cmd
->command
, "/delete_section") && !strcmp(cmd
->arg_types
, "s"))
601 cbox_config_remove_section(CBOX_ARG_S(cmd
, 0));
604 else if (!strcmp(cmd
->command
, "/save") && !strcmp(cmd
->arg_types
, ""))
606 return cbox_config_save(NULL
, error
);
608 else if (!strcmp(cmd
->command
, "/save") && !strcmp(cmd
->arg_types
, "s"))
610 return cbox_config_save(CBOX_ARG_S(cmd
, 0), error
);
614 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "Unknown combination of target path and argument: '%s', '%s'", cmd
->command
, cmd
->arg_types
);
619 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
621 void cbox_app_on_idle()
625 GError
*error
= NULL
;
626 if (cbox_io_get_disconnect_status(&app
.io
, &error
))
627 cbox_io_poll_ports(&app
.io
);
632 int auto_reconnect
= cbox_config_get_int("io", "auto_reconnect", 0);
633 if (auto_reconnect
> 0)
635 sleep(auto_reconnect
);
636 GError
*error
= NULL
;
637 if (!cbox_io_cycle(&app
.io
, &error
))
638 g_warning("Cannot cycle the I/O: %s", (error
&& error
->message
) ? error
->message
: "Unknown error");
643 cbox_rt_handle_cmd_queue(app
.rt
);
646 struct cbox_app app
=
649 .current_scene_name
= NULL
,
652 .process_cmd
= app_process_cmd
,
657 .process_cmd
= config_process_cmd
,