#ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include "eulogium.h" #include "eulogium_item_list.h" #include "eulogium_private.h" #include "gettext.h" #include "procedures.h" #include "dbus_handlers.h" #include "widget_data.h" #define COPYRIGHT "Copyright © 2015 Olliver Schinagl and various contributors (see AUTHORS)." #define SECOND 1UL #define MINUTE (60UL * SECOND) #define HOUR (60UL * MINUTE) #define DAY (24UL * HOUR) #define WEEK (7UL * DAY) #define MONTH (4UL * WEEK) #define YEAR (52UL * WEEK) /* TODO this LUT can be much improved */ char *griffin_print_status[] = { gettext_noop("Unknown"), gettext_noop("Disconnected"), gettext_noop("Error"), gettext_noop("First Run Wizard"), gettext_noop("IDLE"), gettext_noop("Slicing"), gettext_noop("Heating"), gettext_noop("Printing"), gettext_noop("Cooling down"), gettext_noop("Wait for Removal"), gettext_noop("Paused"), }; /* TODO Create def for a menu/screen to house all the buttons */ static void _on_print_abort_ret(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED); static void _cb_content_prev_set(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _print_abort_confirm_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _print_abort_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _print_ignore_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _set_ethernet_power_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _set_wifi_power_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _set_hotspot_power_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _network_wifi_manage_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_material_change_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_material_settings_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_system_maintenance_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_system_settings_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_main_system_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _cb_button_main_print(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_print_local_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_print_usb_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_main_mathot_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_mathot_material_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_mathot_hotend_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_settings_material_1_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_settings_material_2_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_change_material_1_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_change_material_2_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_hotend_change_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_hotend_settings_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_settings_hotend_1_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_settings_hotend_2_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_change_hotend_1_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_change_hotend_2_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_network_info_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_settings_network_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_settings_language_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_settings_hotend_1_offset_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_settings_hotend_2_offset_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_material_customize_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _but_print_tune_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); /* Buttons */ static struct button_def but_return = { .text = gettext_noop("RETURN"), .cb = { .func = _cb_content_prev_set, .data = NULL, .info = "return button pressed", }, .data = NULL, }; static struct button_def but_print_abort_confirm = { .text = "ABORT", .cb = { .func = _print_abort_confirm_cb, .data = NULL, .info = "print abort confirm button pressed", }, .data = NULL, }; static struct button_def but_print_abort = { .text = "Yes", .cb = { .func = _print_abort_cb, .data = NULL, .info = "print abort button pressed", }, .data = NULL, }; static struct button_def but_print_tune = { .text = "TUNE", .cb = { .func = _but_print_tune_cb, .data = NULL, .info = "tune progress button pressed", }, .data = NULL, }; static struct button_def but_main_print = { .text = "PRINT", .cb = { .func = _cb_button_main_print, .data = NULL, .info = "print button pressed", }, .data = NULL, }; static struct button_def but_print_ignore = { .text = "IGNORE THIS JOB", .cb = { .func = _print_ignore_cb, .data = NULL, .info = "print ignore button pressed", }, .data = NULL, }; static struct button_def but_print_local = { .text = "LOCAL", .cb = { .func = _but_print_local_cb, .data = NULL, .info = "local storage button pressed", }, .data = NULL, }; static struct button_def but_print_mmc = { .text = "SD", .cb = { .func = _but_print_usb_cb, .data = NULL, .info = "usb storage button pressed", }, .data = NULL, }; static struct button_def but_print_usb = { .text = "USB", .cb = { .func = _but_print_usb_cb, .data = NULL, .info = "usb storage button pressed", }, .data = NULL, }; static struct button_def but_main_mathot = { .text = "MATERIAL
/HOT END", .cb = { .func = _but_main_mathot_cb, .data = NULL, .info = "material / hot-end button pressed", }, .data = NULL, }; static struct button_def but_mathot_material = { .text = "MATERIAL", .cb = { .func = _but_mathot_material_cb, .data = NULL, .info = "material button pressed", }, .data = NULL, }; static struct button_def but_mathot_hotend = { .text = "HOT END", .cb = { .func = _but_mathot_hotend_cb, .data = NULL, .info = "hot-end button pressed", }, .data = NULL, }; static struct button_def but_main_system = { .text = "SYSTEM", .cb = { .func = _but_main_system_cb, .data = NULL, .info = "system button pressed", }, .data = NULL, }; static struct button_def but_system_maintenance = { .text = "MAINTE-
NANCE", .cb = { .func = _but_system_maintenance_cb, .data = NULL, .info = "maintenance button pressed", }, .data = NULL, }; static struct button_def but_system_settings = { .text = "SETTINGS", .cb = { .func = _but_system_settings_cb, .data = NULL, }, .data = NULL, }; static struct button_def but_material_change = { .text = "CHANGE", .cb = { .func = _but_material_change_cb, .data = NULL, }, .data = NULL, }; static struct button_def but_material_settings = { .text = "SETTINGS", .cb = { .func = _but_material_settings_cb, .data = NULL, }, .data = NULL, }; static struct button_def but_settings_material_1 = { .text = "MATERIAL 1", .cb = { .func = _but_settings_material_1_cb, /* XXX we should make 1/2 a var */ .data = NULL, }, .data = NULL, }; static struct button_def but_settings_material_2 = { .text = "MATERIAL 2", .cb = { .func = _but_settings_material_2_cb, /* XXX we should make 1/2 a var */ .data = NULL, }, .data = NULL, }; static struct button_def but_change_material_1 = { .text = "MATERIAL 1", .cb = { .func = _but_change_material_1_cb, /* XXX we should make 1/2 a var */ .data = NULL, }, .data = NULL, }; static struct button_def but_change_material_2 = { .text = "MATERIAL 2", .cb = { .func = _but_change_material_2_cb, /* XXX we should make 1/2 a var */ .data = NULL, }, .data = NULL, }; static struct button_def but_hotend_change = { .text = "CHANGE", .cb = { .func = _but_hotend_change_cb, .data = NULL, }, .data = NULL, }; static struct button_def but_hotend_settings = { .text = "SETTINGS", .cb = { .func = _but_hotend_settings_cb, .data = NULL, }, .data = NULL, }; static struct button_def but_settings_hotend_1 = { .text = "HOT END 1", .cb = { .func = _but_settings_hotend_1_cb, /* XXX we should make 1/2 a var */ .data = NULL, }, .data = NULL, }; static struct button_def but_settings_hotend_2 = { .text = "HOT END 2", .cb = { .func = _but_settings_hotend_2_cb, /* XXX we should make 1/2 a var */ .data = NULL, }, .data = NULL, }; static struct button_def but_change_hotend_1 = { .text = "HOT END 1", .cb = { .func = _but_change_hotend_1_cb, /* XXX we should make 1/2 a var */ .data = NULL, }, .data = NULL, }; static struct button_def but_change_hotend_2 = { .text = "HOT END 2", .cb = { .func = _but_change_hotend_2_cb, /* XXX we should make 1/2 a var */ .data = NULL, }, .data = NULL, }; static struct menu_def menu_system_settings = { .title = "SETTINGS", .type = LIST_MENU, .entry = { { .icon = "user-home", .label = gettext_noop("Return"), .item = {.type = LIST_ITEM_BUTTON}, .footer = gettext_noop("Return to Main menu"), .footer_alt = NULL, .func = _cb_content_prev_set, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Language", .item = {.type = LIST_ITEM_BUTTON}, .footer = "Change language", .footer_alt = NULL, .func = _but_settings_language_cb, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Network", .item = {.type = LIST_ITEM_BUTTON}, .footer = "Manage connectivity", .footer_alt = "WiFi & Ethernet", .func = _but_settings_network_cb, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Hot end 1 offset", .item = {.type = LIST_ITEM_BUTTON}, .footer = "Adjust offset", .footer_alt = NULL, .func = _but_settings_hotend_1_offset_cb, .toggle_timer = NULL, .data = NULL, /* hot end 1 pointer? */ }, { .icon = NULL, .label = "Hot end 2 offset", .end = NULL, .footer = "Adjust offset", .footer_alt = NULL, .func = _but_settings_hotend_2_offset_cb, .toggle_timer = NULL, .data = NULL, /* hot end 2 pointer? */ }, { .icon = NULL, .label = "Feeder power", .end = NULL, .footer = "Adjust power ", .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Filament detection", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Camera", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Internal storage", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "LED settings", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Retraction", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Motion", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .data = NULL, }, { .icon = NULL, .label = "Software version", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Factory reset", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { NULL }, /* sentinel */ }, .data = NULL, }; static struct menu_def menu_settings_network = { .title = "NETWORK", .type = LIST_MENU, .entry = { { .icon = "user-home", .label = "Return", .item = {.type = LIST_ITEM_BUTTON}, .footer = "Return to Main menu", .footer_alt = NULL, .func = _cb_content_prev_set, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Network info", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = _but_network_info_cb, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Manage WiFi", .end = NULL, .footer = "Connect or forget", .footer_alt = NULL, .func = _network_wifi_manage_cb, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Ethernet", .item = { .type = LIST_ITEM_CHECK, .state = EINA_FALSE, ._widget = NULL, }, .dbus = { /* .proxy = NULL; TODO keep a link to the proxy that is responsible for this item. */ .signal = "EthernetPowerChanged", .sig_cb = on_signal_network_power_changed_ret, .get = "isEthernetPowered", .get_cb = on_method_is_network_powered_ret, .set = "setEthernetPower", .set_cb = on_method_generic_ret, }, .end = NULL, .footer = NULL, .footer_alt = NULL, .func = _set_ethernet_power_cb, /* TODO _set_network_power can be possible */ .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "WiFi", .item = { .type = LIST_ITEM_CHECK, .state = EINA_FALSE, ._widget = NULL, }, .dbus = { .signal = "WifiPowerChanged", .sig_cb = on_signal_network_power_changed_ret, .get = "isWifiPowered", .get_cb = on_method_is_network_powered_ret, .set = "setWifiPower", .set_cb = on_method_generic_ret, }, .end = NULL, .footer = NULL, .footer_alt = NULL, .func = _set_wifi_power_cb, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Hotspot", .item = { .type = LIST_ITEM_CHECK, .state = EINA_FALSE, ._widget = NULL, }, .dbus = { .signal = "HotspotPowerChanged", .sig_cb = on_signal_network_power_changed_ret, .get = "isHotspotPowered", .get_cb = on_method_is_network_powered_ret, .set = "setHotspotPower", .set_cb = on_method_generic_ret, }, .footer = NULL, .footer_alt = NULL, .end = NULL, .func = _set_hotspot_power_cb, .toggle_timer = NULL, .data = NULL, }, { NULL }, /* sentinel */ }, .data = NULL, }; /* TODO: generate this table based on available/installed PO's */ static struct menu_def menu_settings_language = { .title = "LANGUAGE", .type = LIST_MENU, .entry = { { .icon = "user-home", .label = "Return", .end = NULL, .footer = "Return to Main menu", .footer_alt = NULL, .func = _cb_content_prev_set, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "English", .end = NULL, .footer = "Welcome", .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { NULL }, /* sentinel */ }, .data = NULL, }; static struct menu_def menu_settings_hotend_1_offset = { .title = "HOTEND 1 OFFSET", .type = LIST_MENU, .entry = { { .icon = "user-home", .label = "Return", .end = NULL, .footer = "Return to Main menu", .footer_alt = NULL, .func = _cb_content_prev_set, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Calibrate", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "X Offset - 0.02", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Y Offset - 0.02", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Z Offset - 0.02", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Load from Hotend", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Reset", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { NULL }, /* sentinel */ }, .data = NULL, }; static struct menu_def menu_settings_hotend_2_offset = { .title = "HOTEND 2 OFFSET", .type = LIST_MENU, .entry = { { .icon = "user-home", .label = "Return", .end = NULL, .footer = "Return to Main menu", .footer_alt = NULL, .func = _cb_content_prev_set, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Calibrate", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "X Offset - 0.02", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Y Offset - 0.02", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Z Offset - 0.02", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Load from Hotend", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Reset", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { NULL }, /* sentinel */ }, .data = NULL, }; static struct menu_def menu_system_maintenance = { .title = "MAINTENANCE", .type = LIST_MENU, .entry = { { .icon = "user-home", .label = "Return", .end = NULL, .footer = "Return to Main menu", .footer_alt = NULL, .func = _cb_content_prev_set, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Run network wizard", .end = NULL, .footer = "Connect to WiFi", .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Level buildplate", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Heatup buildplate", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Lower buildplate", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Raise buildplate", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Home head", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Printhead tray", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Heatup hotend 1", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Heatup hotend 2", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Set fan speed", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Move material", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Runtime stats", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Factory reset", .end = NULL, .footer = "Reset all settings", .footer_alt = "to their defaults", .func = NULL, .toggle_timer = NULL, .data = NULL, }, { NULL }, /* sentinel */ }, .data = NULL, }; /* TODO this menu probably will be way more dynamic and will likely get replaced */ static struct menu_def menu_material_1 = { .title = "MATERIAL 1", .type = LIST_MENU, .entry = { { .icon = "user-home", .label = "Return", .end = NULL, .footer = "Return to Main menu", .footer_alt = NULL, .func = _cb_content_prev_set, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "PLA", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "ABS", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "UPET", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "CUSTOM", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "CUSTOM3", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "CUSTOMIZE", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = _but_material_customize_cb, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "EXPORT", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "IMPORT", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { NULL }, /* sentinel */ }, .data = NULL, }; static struct menu_def menu_material_2 = { .title = "MATERIAL 2", .type = LIST_MENU, .entry = { { .icon = "user-home", .label = "Return", .end = NULL, .footer = "Return to Main menu", .footer_alt = NULL, .func = _cb_content_prev_set, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "PLA", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "ABS", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "UPET", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "CUSTOM", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "CUSTOM3", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "CUSTOMIZE", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "EXPORT", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "IMPORT", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { NULL }, /* sentinel */ }, .data = NULL, }; static struct menu_def menu_material_customize = { .title = "CUSTOM MATERIALS", .type = LIST_MENU, .entry = { { .icon = "user-home", .label = "Return", .end = NULL, .footer = "Return to Main menu", .footer_alt = NULL, .func = _cb_content_prev_set, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Temperature", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Heated buildplate", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Diameter", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Cooling fan", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Flow rate", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Color", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Brand", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Save as preset", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { NULL }, /* sentinel */ }, .data = NULL, }; static struct menu_def menu_print_tune = { .title = "TUNE", .type = LIST_MENU, .entry = { { .icon = "user-home", .label = "Return", .end = NULL, .footer = "Return to print", .footer_alt = NULL, .func = _cb_content_prev_set, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Networking", .end = NULL, .footer = "IP: ", .footer_alt = NULL, .func = _but_settings_network_cb, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Speed", .end = NULL, .footer = "100 %", .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Hotend temperature", .end = NULL, .footer = "210 °C", .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Buildplate temperature", .end = NULL, .footer = "60 °C", .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Fan speed", .end = NULL, .footer = "100 %", .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Material flow", .end = NULL, .footer = "100 %", .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Retraction hotend", .end = NULL, .footer = "Up", .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "LED Brightness", .end = NULL, .footer = "100 %", .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "Material/Nozzle", .end = NULL, .footer = "PLA | PVA", .footer_alt = "RVS | Bronze", .func = NULL, .toggle_timer = NULL, .data = NULL, }, { NULL }, /* sentinel */ }, .data = NULL, }; #if 0 menu template; TODO make nice macro for entries static struct menu_def menu_ = { .title = "", .type = LIST_MENU, .entry = { { .icon = "user-home", .label = "Return", .end = NULL, .footer = "Return to Main menu", .footer_alt = NULL, .func = _cb_content_prev_set, .toggle_timer = NULL, .data = NULL, }, { .icon = NULL, .label = "", .end = NULL, .footer = NULL, .footer_alt = NULL, .func = NULL, .toggle_timer = NULL, .data = NULL, }, { NULL }, /* sentinel */ }, .data = NULL, }; #endif static void eulogium_print_data_clear(struct eulogium_data *eulogium) { if (eulogium->progress_data_refresh) ecore_timer_del(eulogium->progress_data_refresh); eulogium->progress_data_refresh = NULL; eulogium->progress = NULL; /* XXX memleak here? when or how is this freed by efl */ eulogium->status = NULL; /* XXX memleak here too? how does efl do it */ eulogium->time = NULL; /* XXX memleak here too? how does efl do it */ eulogium->name = NULL; /* XXX memleak here too? how does efl do it */ // if (eulogium->print.name) // free(eulogium->print.name); eulogium->print.name = NULL; eulogium->print.name_changed = EINA_FALSE; // if (eulogium->print.file) // free(eulogium->print.file); eulogium->print.url = NULL; eulogium->print.time = 0; eulogium->print.material = 0; eulogium->print.progress = 0; eulogium->print.flags = ""; } static void _on_print_abort_ret(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) { struct eulogium_data *eulogium = data; const char *errname, *errmsg; Eina_Bool print_abort = EINA_FALSE; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "b", &print_abort)) { EINA_LOG_ERR("Failed to abort print."); return; } if (print_abort == EINA_TRUE) { EINA_LOG_INFO("Successfully aborted print."); eulogium_print_data_clear(eulogium); } else { EINA_LOG_WARN("Unable to abort print."); } } static void _cb_content_prev_set(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; uint_fast8_t list_size; printf("prev ret\n"); list_size = eina_list_count(elm_naviframe_items_get(eulogium->navi)); if (list_size < 2) printf("Not popping last item cowboy\n"); /* TODO, use proper debug construct */ else elm_naviframe_item_pop(eulogium->navi); } static void _print_abort_confirm_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; content = eulogium_menu_confirm(eulogium->navi, gettext_noop("
Abort the print?"), "No", &but_print_abort); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _print_abort_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; //eldbus_proxy_call(eulogium->dbus.proxy[PRINTER], "abortPrint", _on_print_abort_ret, eulogium, -1, ""); } static void _print_ignore_cb(void *data, Evas_Object *obj, void *event_info) { struct eulogium_data *eulogium = data; eulogium->print.block = EINA_FALSE; eulogium->print.block_active = EINA_FALSE; _print_abort_cb(data, obj, event_info); } static void _but_system_maintenance_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("But sys maint\n"); content = menu_widget_list(eulogium, eulogium->navi, &menu_system_maintenance); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_material_change_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("But material change\n"); content = eulogium_tripple_button_menu(eulogium->navi, &but_change_material_1, &but_change_material_2, &but_return); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_material_settings_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("But material settings\n"); content = eulogium_tripple_button_menu(eulogium->navi, &but_settings_material_1, &but_settings_material_2, &but_return); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_hotend_change_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("But hotend change\n"); content = eulogium_tripple_button_menu(eulogium->navi, &but_change_hotend_1, &but_change_hotend_2, &but_return); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_hotend_settings_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("But hotend settings\n"); content = eulogium_tripple_button_menu(eulogium->navi, &but_settings_hotend_1, &but_settings_hotend_2, &but_return); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_main_system_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("Button system pressed\n"); content = eulogium_tripple_button_menu(eulogium->navi, &but_system_settings, &but_system_maintenance, &but_return); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void menu_widget_list_push(struct eulogium_data *eulogium, struct menu_def *file) { Evas_Object *content; content = menu_widget_list(eulogium, eulogium->navi, file); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void menu_wifi_list(struct eulogium_data *eulogium) { struct menu_def *wifi_list; wifi_list = malloc(sizeof(struct menu_def)); /* XXX memleak here. free on pop */ wifi_list->title = _("Wifi Networks"); wifi_list->type = LIST_WIFI; menu_widget_list_push(eulogium, wifi_list); } static void menu_internal_storage(struct eulogium_data *eulogium) { struct menu_def *menu_internal_storage; menu_internal_storage = malloc(sizeof(struct menu_def)); /* XXX meamleak here. This needs to be free-ed when we pop this screen */ menu_internal_storage->title = "Internal storage"; menu_internal_storage->type = LIST_FILE; menu_internal_storage->dir.path = "/home"; /* TODO, use variable for internal storage */ menu_widget_list_push(eulogium, menu_internal_storage); } static void menu_usb_storage(struct eulogium_data *eulogium) { struct menu_def *menu_usb_storage; struct mount_data *mount; char *mount_point; uint_fast16_t mount_len; /* Only care about last entry. Yes this is wrong as we need a UI element to handle this properly first. XXX */ mount = eina_list_data_get(eina_list_last(eulogium->mounts)); /* XXX double check if we don't need ** here */ if (!mount) return; mount_point = (char *)eeze_disk_mount_point_get(mount->disk); if (!mount_point) return; mount_len = strlen(mount_point) + 1; menu_usb_storage = malloc(sizeof(struct menu_def)); /* XXX meamleak here. This needs to be free-ed when we pop this screen */ menu_usb_storage->title = "USB storage"; menu_usb_storage->type = LIST_FILE; menu_usb_storage->dir.path = malloc(mount_len); strncpy(menu_usb_storage->dir.path, mount_point, mount_len); menu_widget_list_push(eulogium, menu_usb_storage); } static void _network_wifi_manage_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { menu_wifi_list((struct eulogium_data *)data); } static void _but_print_local_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { menu_internal_storage((struct eulogium_data *)data); } static void _but_print_usb_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { menu_usb_storage((struct eulogium_data *)data); } static void _cb_button_main_print(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; /* TODO: Right now we just implement 1 or 2 buttons horizontally, ideally this should be something scrollable where more storage locations are usable */ if (eina_list_count(eulogium->mounts) < 1) { menu_internal_storage(eulogium); } else { Evas_Object *content = NULL; struct mount_data *mount; mount = eina_list_data_get(eina_list_last(eulogium->mounts)); if (!mount) return; if (eeze_disk_type_get(mount->disk) == EEZE_DISK_TYPE_FLASH) content = eulogium_tripple_button_menu(eulogium->navi, &but_print_local, &but_print_mmc, &but_return); if (eeze_disk_type_get(mount->disk) == EEZE_DISK_TYPE_USB) content = eulogium_tripple_button_menu(eulogium->navi, &but_print_local, &but_print_usb, &but_return); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } } /* TODO Make macro for all the simple entries */ static void _but_settings_network_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content = NULL; printf("But settings network settings\n"); content = menu_widget_list(eulogium, eulogium->navi, &menu_settings_network); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_system_settings_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content = NULL; printf("But system settings settings\n"); content = menu_widget_list(eulogium, eulogium->navi, &menu_system_settings); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_settings_hotend_1_offset_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content = NULL; printf("But settings hotend 1 offset settings\n"); content = menu_widget_list(eulogium, eulogium->navi, &menu_settings_hotend_1_offset); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_settings_hotend_2_offset_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content = NULL; printf("But settings hotend 2 offset settings\n"); content = menu_widget_list(eulogium, eulogium->navi, &menu_settings_hotend_2_offset); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_settings_language_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content = NULL; printf("But menu language settings\n"); content = menu_widget_list(eulogium, eulogium->navi, &menu_settings_language); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static char *parse_networks_for_display(struct network_data *networks) { char *buf = NULL; uint_fast16_t i; uint_fast32_t pos = 0; if (!networks) return NULL; for (i = 0; networks[i].obj_path; i++) { buf = realloc(buf, pos + 34 * sizeof(char *)); pos += sprintf(buf + pos, "%s%s IP: %s", i == 0 ? "": "
", (networks[i].tech == TECH_ETHERNET) ? "Ethernet" : (networks[i].tech == TECH_WIFI) ? "WiFi" : "", networks[i].ipv4); } return buf; } static void _but_network_info_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content, *_top, *_bottom; char *buf; /* XXX Quick hack to make the adv feature a little more useful, this needs to be made much better! */ _top = elm_box_add(eulogium->navi); evas_object_show(_top); _top = elm_label_add(eulogium->navi); /* TODO, dynamically update IPs */ buf = parse_networks_for_display(eulogium->networks); elm_object_text_set(_top, buf); free(buf); evas_object_show(_top); _bottom = elm_button_add(eulogium->navi); elm_object_text_set(_bottom, _(but_return.text)); /* not pretty using the global XXX */ evas_object_smart_callback_add(_bottom, "clicked", but_return.cb.func, but_return.cb.data); evas_object_show(_bottom); // elm_naviframe_item_simple_push(eulogium->navi, box); content = eulogium_split_screen(eulogium->navi, _top, _bottom); if (content) elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_main_mathot_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("Button matts pressed\n"); content = eulogium_tripple_button_menu(eulogium->navi, &but_mathot_material, &but_mathot_hotend, &but_return); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_settings_material_1_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("Button matts settings 1 pressed\n"); content = menu_widget_list(eulogium, eulogium->navi, &menu_material_1); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_settings_material_2_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("Button matts settings 2 pressed\n"); content = menu_widget_list(eulogium, eulogium->navi, &menu_material_2); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_material_customize_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("Button matts customize pressed\n"); content = menu_widget_list(eulogium, eulogium->navi, &menu_material_customize); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_print_tune_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("Button print tune pressed\n"); content = menu_widget_list(eulogium, eulogium->navi, &menu_print_tune); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_change_material_1_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("Button matts change 1 pressed\n"); content = eulogium_tripple_button_menu(eulogium->navi, &but_return, &but_return, &but_return); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_change_material_2_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("Button matts change 2 pressed\n"); content = eulogium_tripple_button_menu(eulogium->navi, &but_return, &but_return, &but_return); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_mathot_material_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("Button mathot material pressed\n"); content = eulogium_tripple_button_menu(eulogium->navi, &but_material_change, &but_material_settings, &but_return); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_mathot_hotend_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("Button mathot hotend pressed\n"); content = eulogium_tripple_button_menu(eulogium->navi, &but_hotend_change, &but_hotend_settings, &but_return); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_settings_hotend_1_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("Button hotend settings 1 pressed\n"); content = menu_widget_list(eulogium, eulogium->navi, &menu_settings_hotend_1_offset); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_settings_hotend_2_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("Button hotend settings 2 pressed\n"); content = menu_widget_list(eulogium, eulogium->navi, &menu_settings_hotend_1_offset); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_change_hotend_1_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("Button hotend change 1 pressed\n"); content = eulogium_tripple_button_menu(eulogium->navi, &but_return, &but_return, &but_return); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } static void _but_change_hotend_2_cb(void *data, Evas_Object *object EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; Evas_Object *content; printf("Button matts change 2 pressed\n"); content = eulogium_tripple_button_menu(eulogium->navi, &but_return, &but_return, &but_return); if (!content) return; elm_naviframe_item_simple_push(eulogium->navi, content); } void eulogium_button_cb_set(struct button_def *button, struct button_cb *cb) { if (cb && button) button->cb = *cb; } void eulogium_button_cb_data_set(struct button_def *button, void *data) { if (data && button) button->cb.data = data; } void eulogium_button_data_set(struct button_def *button, void *data) { if (data && button) button->data = data; } void eulogium_print_data_set(struct eulogium_data *eulogium, char *filepath) { char *buf; size_t buf_size; if (!filepath) EINA_LOG_CRIT("Incorrect filename passed %s", filepath); buf_size = strlen("file://") + strlen(filepath) + 1; buf = malloc(buf_size); /* TODO: remember to free this later! */ snprintf(buf, buf_size, "file://%s", filepath); eulogium->print.url = buf; eulogium->print.name = ecore_file_strip_ext(ecore_file_file_get(filepath)); eulogium->print.flags = ""; eulogium->print.material = 100.23; /* TODO */ eulogium->print.time = 12; } /* Function to make the Z-axis of any wheel focus the next/previous focusable widget */ static void _cb_eulogium_input_wheel(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) { Evas_Event_Mouse_Wheel *ev = event_info; if (ev->z > 0) elm_object_focus_next((Evas_Object *)data, ELM_FOCUS_NEXT); else elm_object_focus_next((Evas_Object *)data, ELM_FOCUS_PREVIOUS); } static void _cb_eulogium_exit(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { elm_exit(); } Evas_Object *eulogium_split_screen(Evas_Object *parent, Evas_Object *top, Evas_Object *bottom) { Evas_Object *table; Evas_Object *sep; table = elm_table_add(parent); evas_object_size_hint_weight_set(table, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(table, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(top, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(top, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_table_pack(table, top, 0, 0, 1, 4); sep = elm_separator_add(table); elm_separator_horizontal_set(sep, EINA_TRUE); evas_object_size_hint_weight_set(sep, EVAS_HINT_EXPAND, 0); evas_object_show(sep); elm_table_pack(table, sep, 0, 4, 1, 1); elm_table_pack(table, bottom, 0, 5, 1, 1); evas_object_size_hint_weight_set(bottom, EVAS_HINT_EXPAND, 0); evas_object_size_hint_align_set(bottom, EVAS_HINT_FILL, 0); evas_object_show(table); return table; } struct _status_msg { enum printer_status i; char *s; }; static void eulogium_printer_status_set(struct eulogium_data *eulogium, struct _status_msg *status); static void _on_get_status_ret(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) { const char *errname, *errmsg; struct eulogium_data *eulogium = data; char *state; struct _status_msg status; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); status.i = ERROR; status.s = griffin_print_status[ERROR]; } else if (!eldbus_message_arguments_get(msg, "s", &state)) { EINA_LOG_ERR("Message content does not match expected \"s\" signature."); status.i = ERROR; status.s = griffin_print_status[ERROR]; } else if (!strncmp(state, "DISCONNECTED", 12)) { /* XXX replace this with something better and maintainable, function, LUT etc */ status.i = DISCONNECTED; status.s = griffin_print_status[DISCONNECTED]; } else if (!strncmp(state, "ERROR", 5)) { status.i = ERROR; status.s = griffin_print_status[ERROR]; } else if (!strncmp(state, "FIRST_RUN_WIZZARD", 17)) { status.i = FIRST_RUN_WIZZARD; status.s = griffin_print_status[FIRST_RUN_WIZZARD]; } else if (!strncmp(state, "IDLE", 4)) { status.i = IDLE; status.s = griffin_print_status[IDLE]; } else if (!strncmp(state, "SLICING", 7)) { status.i = SLICING; status.s = griffin_print_status[SLICING]; } else if (!strncmp(state, "HEATING", 7)) { status.i = HEATING; status.s = griffin_print_status[HEATING]; } else if (!strncmp(state, "PRINTING", 8)) { status.i = PRINTING; status.s = griffin_print_status[PRINTING]; } else if (!strncmp(state, "COOLING", 7)) { status.i = COOLING; status.s = griffin_print_status[COOLING]; } else if (!strncmp(state, "WAIT_FOR_REMOVAL", 16)) { status.i = WAIT_FOR_REMOVAL; status.s = griffin_print_status[WAIT_FOR_REMOVAL]; } else if (!strncmp(state, "PAUSED", 6)) { status.i = PAUSED; status.s = griffin_print_status[PAUSED]; } else { status.i = UNKNOWN; status.s = griffin_print_status[UNKNOWN]; } eulogium_printer_status_set(eulogium, &status); } static void _on_get_progress_ret(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) { const char *errname, *errmsg; double *progress = data; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "d", progress)) { EINA_LOG_ERR("Failed to get print progress."); return; } } static void _on_get_time_ret(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) { const char *errname, *errmsg; uint_fast32_t *time = data; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "u", time)) { EINA_LOG_ERR("Failed to get remaining print time."); return; } } static Eina_Bool _timer_progress_data_update_cb(void *data) { struct eulogium_data *eulogium = data; static enum printer_status status = -1; static double progress = 0; static double time = -1; //eldbus_proxy_call(eulogium->dbus.proxy[PRINTER], "getProgress", _on_get_progress_ret, &eulogium->print.progress, 2, ""); //eldbus_proxy_call(eulogium->dbus.proxy[PRINTER], "getTime", _on_get_time_ret, &eulogium->print.time, 2, ""); if (eulogium->printer.status != status) { elm_object_text_set(eulogium->status, _(griffin_print_status[eulogium->printer.status])); if (eulogium->printer.status == COOLING) elm_progressbar_inverted_set(eulogium->progress, EINA_TRUE); status = eulogium->printer.status; } if (eulogium->print.progress != progress) { elm_progressbar_value_set(eulogium->progress, eulogium->print.progress); progress = eulogium->print.progress; } if (eulogium->print.name_changed == EINA_TRUE) { elm_object_text_set(eulogium->name, _(eulogium->print.name)); eulogium->print.name_changed = EINA_FALSE; } if (eulogium->print.time != time) { char buf[255], *str; uint_fast32_t time = 0; if (eulogium->print.time < 1) { str = "Print time unknown"; time = 0; } if (eulogium->print.time > 0) { str = "Time left: %d second%s"; time = eulogium->print.time; } if (eulogium->print.time > MINUTE) { str = "Time left: %d minute%s"; time = eulogium->print.time / MINUTE; } if (eulogium->print.time > HOUR) { str = "Time left: %d hour%s"; time = eulogium->print.time / HOUR; } if (eulogium->print.time > DAY) { str = "Time left: %d day%s"; time = eulogium->print.time / DAY; } if (eulogium->print.time > WEEK) { str = "Time left: %d week%s"; time = eulogium->print.time / WEEK; } if (eulogium->print.time > MONTH) { str = "Time left: %d month%s"; time = eulogium->print.time / MONTH; } if (eulogium->print.time > YEAR) { str = "Time left: %d year%s"; time = eulogium->print.time / YEAR; } snprintf(buf, sizeof(buf), str, (int)eulogium->print.time, (time > 1) ? "s" : ""); /* TODO: This won't work with in10 */ elm_object_text_set(eulogium->time, _(buf)); eulogium->print.time = time; } return ECORE_CALLBACK_RENEW; } /* FIXME: bug here. If the user hits 'abort print' button, an abort is sent to the backend. This timer however * still keeps going and requests the backend status afterwards. Because of this, the status change gets * triggered in the menu state machine and if we're not idle, we jump to a progress screen. * The issue seems minor however, but might not be. Slicing may take longer then 10 seconds and thus * slicing can quickly be aborted, however we are then in the 'cooling' state, thus popping up the cooling * window. */ static Eina_Bool _timer_print_unblock_cb(void *data) { static uint_fast8_t timeout = 10; /* TODO, make it a configurable maybe in eulogium_data */ struct eulogium_data *eulogium = data; timeout--; elm_progressbar_value_set(eulogium->progress, timeout / 100.0); if (timeout > 0) { return ECORE_CALLBACK_RENEW; } else { eulogium->print.block_active = EINA_FALSE; eulogium->print.block = EINA_FALSE; /* XXX: Cleanup eulogium structures? Right now they get overwritten. */ timeout = 10; /* TODO, use same configurable as above */ //eldbus_proxy_call(eulogium->dbus.proxy[PRINTER], "getStatus", _on_get_status_ret, eulogium, -1, ""); eulogium->progress_data_refresh = NULL; return ECORE_CALLBACK_CANCEL; } } Evas_Object *eulogium_print_ignore(struct eulogium_data *eulogium) { Evas_Object *_top, *_bottom; eulogium->progress_data_refresh = ecore_timer_add(1.0, _timer_print_unblock_cb, eulogium); if (!eulogium->progress_data_refresh) { /* TODO: define here is probably nicer */ EINA_LOG_CRIT("Unable to create progress update timer"); return NULL; } _top = elm_box_add(eulogium->navi); evas_object_size_hint_weight_set(_top, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(_top, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_homogeneous_set(_top, EINA_FALSE); evas_object_show(_top); eulogium->time = elm_label_add(_top); elm_object_text_set(eulogium->time, _("Receiving print file
10 seconds to
ignore this job.")); elm_label_slide_mode_set(eulogium->time, ELM_LABEL_SLIDE_MODE_NONE); evas_object_size_hint_align_set(eulogium->time, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(eulogium->time); elm_box_pack_end(_top, eulogium->time); eulogium->progress = elm_progressbar_add(_top); /* TODO: depending on i18n sig, change inverted */ elm_progressbar_horizontal_set(eulogium->progress, EINA_TRUE); elm_progressbar_pulse_set(eulogium->progress, EINA_FALSE); elm_progressbar_pulse(eulogium->progress, EINA_FALSE); elm_progressbar_value_set(eulogium->progress, 10 / 100.0); /* TODO, use timeout from above as define/configurabe */ elm_progressbar_unit_format_set(eulogium->progress, "%1.0f"); /* Remove text alltogether? */ evas_object_size_hint_align_set(eulogium->progress, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(eulogium->progress); elm_box_pack_end(_top, eulogium->progress); _bottom = elm_button_add(eulogium->navi); evas_object_size_hint_align_set(_bottom, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(_bottom, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_smart_callback_add(_bottom, "clicked", but_print_ignore.cb.func, but_print_ignore.cb.data); elm_object_text_set(_bottom, _(but_print_ignore.text)); evas_object_show(_bottom); return eulogium_split_screen(eulogium->navi, _top, _bottom); } Evas_Object *eulogium_print_progress(struct eulogium_data *eulogium) { Evas_Object *_top, *_bottom; eulogium->progress_data_refresh = ecore_timer_add(0.5, _timer_progress_data_update_cb, eulogium); if (!eulogium->progress_data_refresh) { /* TODO make define for the timeout */ EINA_LOG_CRIT("Unable to create progress update timer"); return NULL; } _top = elm_box_add(eulogium->navi); evas_object_size_hint_weight_set(_top, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(_top, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_homogeneous_set(_top, EINA_FALSE); evas_object_show(_top); eulogium->time = elm_label_add(_top); elm_object_text_set(eulogium->time, _("Calculating time ...")); elm_label_slide_mode_set(eulogium->time, ELM_LABEL_SLIDE_MODE_NONE); evas_object_size_hint_align_set(eulogium->time, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(eulogium->time); elm_box_pack_end(_top, eulogium->time); eulogium->status = elm_label_add(_top); elm_object_text_set(eulogium->status, _("Unknown print status")); elm_label_slide_mode_set(eulogium->status, ELM_LABEL_SLIDE_MODE_NONE); evas_object_size_hint_align_set(eulogium->status, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(eulogium->status); elm_box_pack_end(_top, eulogium->status); eulogium->name = elm_label_add(_top); elm_object_text_set(eulogium->name, eulogium->print.name); elm_label_slide_mode_set(eulogium->name, ELM_LABEL_SLIDE_MODE_AUTO); //elm_label_slide_speed_set(object, 2); elm_label_slide_go(eulogium->name); elm_object_style_set(eulogium->name, "slide_bounce"); evas_object_size_hint_align_set(eulogium->name, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(eulogium->name); elm_box_pack_end(_top, eulogium->name); eulogium->progress = elm_progressbar_add(_top); /* TODO: depending on i18n sig, change inverted */ elm_progressbar_horizontal_set(eulogium->progress, EINA_TRUE); elm_progressbar_pulse_set(eulogium->progress, EINA_FALSE); /* TODO: pulse = time-unknown/pause */ elm_progressbar_pulse(eulogium->progress, EINA_FALSE); elm_progressbar_value_set(eulogium->progress, eulogium->print.progress); elm_progressbar_unit_format_set(eulogium->progress, "%1.1f %%"); evas_object_size_hint_align_set(eulogium->progress, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(eulogium->progress); elm_box_pack_end(_top, eulogium->progress); _bottom = eulogium_dual_button_add(eulogium->navi, &but_print_tune, &but_print_abort_confirm); evas_object_show(_bottom); return eulogium_split_screen(eulogium->navi, _top, _bottom); } Evas_Object *eulogium_generic_error(struct eulogium_data *eulogium, uint8_t eulogium_error) { Evas_Object *box, *object; char buf[] = "Printer error -255.
Please contact support via
http://ultimaker.com/support."; /* TODO, replace with define of strings to collect all strings centrally */ box = elm_box_add(eulogium->navi); evas_object_show(box); object = elm_label_add(eulogium->navi); snprintf(buf, sizeof(buf), "Printer error %d.
Please contact support via
http://ultimaker.com/support.", eulogium_error); elm_object_text_set(object, _(buf)); evas_object_show(object); elm_box_pack_end(box, object); #if 0 /* XXX what to do here, reboot? make support notice via wget? */ object = elm_button_add(eulogium->navi); elm_object_text_set(object, _("ABORT")); /* TODO create abort button */ evas_object_size_hint_align_set(object, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(object, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_smart_callback_add(object, "clicked", _print_abort_cb, eulogium); /* TODO what button to use here? */ evas_object_show(object); elm_box_pack_end(box, object); #endif return box; } static void _on_cleared_printer_ret(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) { const char *errname, *errmsg; Eina_Bool cleared_bed = EINA_FALSE; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "b", &cleared_bed)) { EINA_LOG_ERR("Failed to get bed clear status."); return; } if (cleared_bed == EINA_TRUE) EINA_LOG_INFO("Bed has been successfully Cleared"); else EINA_LOG_WARN("Unable to clear printer bed"); } static void _cleared_bed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; //eldbus_proxy_call(eulogium->dbus.proxy[PRINTER], "clearedPrinter", _on_cleared_printer_ret, eulogium, -1, ""); } Evas_Object *eulogium_clear_print_bed(struct eulogium_data *eulogium) { Evas_Object *_top, *_bottom, *obj; _top = elm_box_add(eulogium->navi); evas_object_show(_top); obj = elm_label_add(_top); elm_object_text_set(obj, _("Print finished!
Remove the print
for next
print job.")); evas_object_show(obj); elm_box_pack_end(_top, obj); _bottom = elm_button_add(eulogium->navi); elm_object_text_set(_bottom, _("Print removed")); evas_object_smart_callback_add(_bottom, "clicked", _cleared_bed_cb, eulogium); evas_object_show(_bottom); return eulogium_split_screen(eulogium->navi, _top, _bottom); } struct _filelist_data { struct eulogium_data *eulogium; struct dir_entry_def *dir; Evas_Object *list; }; struct _filelist_entry_data { struct _filelist_data *filelist; char *filepath; }; static void _cb_select_file(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = ((struct _filelist_entry_data *)data)->filelist->eulogium; char *filepath = ((struct _filelist_entry_data *)data)->filepath; if (filepath) { if (ecore_file_is_dir(filepath)) { struct menu_def *new_dir; uint_fast16_t new_dir_len; new_dir_len = strlen(filepath) + 1; new_dir = malloc(sizeof(struct menu_def)); /* XXX memleak, free on pop */ new_dir->title = "TODO!"; /* TODO */ new_dir->type = LIST_FILE; new_dir->dir.path = malloc(new_dir_len); /* XXX memleak, but by copying we can free _filelist_data without worry */ strncpy(new_dir->dir.path, filepath, new_dir_len); menu_widget_list_push(eulogium, new_dir); } else { eulogium_print_data_set(eulogium, filepath); procedure_start_print(eulogium->dbus.proxy[PRINTER], &eulogium->print); } } } static int _cb_dirfile_sort(const void *data1, const void *data2) { const char *filepath1 = ((struct _filelist_entry_data *)evas_object_data_get(data1, "sort_data"))->filepath; const char *filepath2 = ((struct _filelist_entry_data *)evas_object_data_get(data2, "sort_data"))->filepath; if (!filepath1) return 1; if (!filepath2) return -1; if (ecore_file_is_dir(filepath1) != (ecore_file_is_dir(filepath2))) { return (ecore_file_is_dir(filepath1) ? -1 : 1); } return strcoll(filepath1, filepath2); } char *ecore_file_ext_get(const char *path) { char *p, *file = NULL; p = strrchr(path, '.'); if ((!path) || (!p)) return NULL; else if (p != path) { size_t l = strlen(p); if (l < 2) return NULL; file = malloc(strlen(p) * sizeof(char)); if (file) { memcpy(file, &p[1], l); } } return file; } static void _cb_populate_filelist(const char *name, const char *path, void *data) { struct _filelist_data *filelist = data; char *filepath; struct _filelist_entry_data *filelist_entry; Evas_Object *icon; char *ext; size_t dir_len; uint_fast8_t hidden_visible = 1; if (hidden_visible && (name[0] == '.')) return; dir_len = strlen(name) + strlen(path) + sizeof('/') + 1; filepath = malloc(dir_len); snprintf(filepath, dir_len, "%s/%s", path, name); if (!ecore_file_is_dir(filepath)) { int i, valid_ext = 0; ext = ecore_file_ext_get(name); if (!ext) return; if (!filelist->eulogium->printer.file_handlers) return; for (i = 0; filelist->eulogium->printer.file_handlers[i] != NULL; i++) if (strncmp(ext, filelist->eulogium->printer.file_handlers[i], strlen(ext)) == 0) valid_ext++; if (!valid_ext) return; } icon = elm_icon_add(filelist->list); if (ecore_file_is_dir(filepath)) { elm_icon_standard_set(icon, "folder"); } else { elm_icon_standard_set(icon, "file"); } elm_image_resizable_set(icon, EINA_FALSE, EINA_FALSE); evas_object_show(icon); filelist_entry = malloc(sizeof(struct _filelist_entry_data)); filelist_entry->filelist = filelist; filelist_entry->filepath = filepath; eulogium_item_list_sorted_insert(filelist->list, icon, name, NULL, _cb_select_file, filelist_entry, _cb_dirfile_sort); // evas_object_smart_callback_add(item, "focused", _update_footer_focus_cb, &menu->entry[i]); // evas_object_smart_callback_add(item, "unfocused", _update_footer_unfocus_cb, &menu->entry[i]); // evas_object_smart_callback_add(list, "longpressed", _cb_filelist_filedetails, NULL); /* TODO, popup? */ // free(filepath); /* TODO is this required?, yes! / } static void _update_menu_footer_unfocus_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct menu_entry_def *entry = data; if (entry->toggle_timer) { ecore_timer_del(entry->toggle_timer); entry->toggle_timer = NULL; } } static Eina_Bool _timer_footer_toggle_cb(void *data) { struct menu_entry_def *entry = data; Evas_Object *footer = entry->data; static uint_fast8_t toggle = 0; if (toggle) elm_object_text_set(footer, _(entry->footer)); else elm_object_text_set(footer, _(entry->footer_alt)); toggle = !toggle; return ECORE_CALLBACK_RENEW; } static void _update_menu_footer_focus_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { struct menu_entry_def *entry = data; Evas_Object *footer = entry->data; if (!entry->footer) { elm_object_text_set(footer, _(entry->label)); return; } elm_object_text_set(footer, _(entry->footer)); if (entry->footer_alt) { entry->toggle_timer = ecore_timer_add(1.5, _timer_footer_toggle_cb, entry); /* XXX magic value!! */ if (!entry->toggle_timer) EINA_LOG_ERR("Unable to create toggle timer for entry %s", entry->label); } } static void _set_ethernet_power_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; eldbus_proxy_call(eulogium->dbus.proxy[NETWORK], "setEthernetPower", on_method_generic_ret, NULL, -1, "b", elm_check_state_get(obj)); } static void _set_wifi_power_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; eldbus_proxy_call(eulogium->dbus.proxy[NETWORK], "setWifiPower", on_method_generic_ret, NULL, -1, "b", elm_check_state_get(obj)); } static void _set_hotspot_power_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { struct eulogium_data *eulogium = data; eldbus_proxy_call(eulogium->dbus.proxy[NETWORK], "setHotspotPower", on_method_generic_ret, NULL, -1, "b", elm_check_state_get(obj)); } static void _menu_generate_wifilist(struct eulogium_data *eulogium, Evas_Object *list, struct wifi_def *wifi) { Evas_Object *icon; icon = elm_icon_add(list); elm_icon_standard_set(icon, "user-home"); evas_object_show(icon); eulogium_item_list_prepend(list, icon, "Return", NULL, _cb_content_prev_set, eulogium); /* XXX TODO: when we pop the filelist from the stack, who calls elm_list_free();? */ } static void _menu_generate_filelist(struct eulogium_data *eulogium, Evas_Object *list, struct dir_entry_def *dir) { Evas_Object *icon; struct _filelist_data *filelist_data; filelist_data = malloc(sizeof(struct _filelist_data)); /* XXX memleak, free on pop */ filelist_data->eulogium = eulogium; filelist_data->list = list; filelist_data->dir = dir; eina_file_dir_list(dir->path, EINA_FALSE, _cb_populate_filelist, filelist_data); icon = elm_icon_add(list); elm_icon_standard_set(icon, "user-home"); evas_object_show(icon); eulogium_item_list_prepend(list, icon, "Return", NULL, _cb_content_prev_set, eulogium); /* XXX TODO: when we pop the filelist from the stack, who calls elm_list_free();? */ } static void _menu_generate_menulist(struct eulogium_data *eulogium, Evas_Object *list, struct menu_entry_def *entry) { int i; Evas_Object *item, *icon; for (i = 0; entry[i].label != NULL; i++) { if (entry[i].icon) { icon = elm_icon_add(list); elm_icon_standard_set(icon, entry[i].icon); evas_object_show(icon); } else { icon = NULL; } item = eulogium_item_list_append(list, icon, entry[i].label, &entry[i].item, entry[i].func, eulogium); entry[i].data = eulogium->footer; /* XXX ugly-ness keeps adding. The footer widget should not be passed like this :( */ evas_object_smart_callback_add(item, "focused", _update_menu_footer_focus_cb, &entry[i]); evas_object_smart_callback_add(item, "unfocused", _update_menu_footer_unfocus_cb, &entry[i]); // evas_object_smart_callback_add(list, "longpressed", _cb_filelist_filedetails, NULL); /* TODO, popup? */ } } Evas_Object *menu_widget_list(struct eulogium_data *eulogium, Evas_Object *parent, struct menu_def *menu) { Evas_Object *obj; Evas_Object *box; Evas_Object *list; box = elm_box_add(parent); eulogium->footer = elm_label_add(box); elm_object_text_set(eulogium->footer, NULL); obj = elm_label_add(box); elm_object_text_set(obj, _(menu->title)); /* XXX THIS IS NOT ALWAYS IN DATA! */ evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(obj); elm_box_pack_start(box, obj); list = eulogium_item_list_add(box); elm_scroller_bounce_set(list, EINA_FALSE, EINA_FALSE); elm_scroller_policy_set(list, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(list, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_scroller_movement_block_set(list, ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL | ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL); evas_object_show(list); if (menu->type == LIST_MENU) _menu_generate_menulist(eulogium, list, menu->entry); if (menu->type == LIST_FILE) _menu_generate_filelist(eulogium, list, &menu->dir); if (menu->type == LIST_WIFI) _menu_generate_wifilist(eulogium, list, NULL); eulogium_item_list_go(list); evas_object_show(list); elm_box_pack_end(box, list); obj = elm_separator_add(box); elm_separator_horizontal_set(obj, EINA_TRUE); evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, 0); evas_object_show(obj); elm_box_pack_end(box, obj); /* Footer is initialized at the start of the function, so that the for loop can work with it. */ evas_object_size_hint_align_set(eulogium->footer, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(eulogium->footer); elm_box_pack_end(box, eulogium->footer); evas_object_show(box); return box; } struct _multi_screen_next_cb_data { struct eulogium_data *eulogium; struct multi_screen_data *screen_data; uint_fast8_t pagenum; Eina_Bool pageindex; }; static void _eulogium_multi_screen_next_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Evas_Object *content; struct eulogium_data *eulogium = ((struct _multi_screen_next_cb_data *)data)->eulogium; uint_fast8_t pagenum = ((struct _multi_screen_next_cb_data *)data)->pagenum; Eina_Bool pageindex = ((struct _multi_screen_next_cb_data *)data)->pageindex; struct multi_screen_data *screen_data = ((struct _multi_screen_next_cb_data *)data)->screen_data; if (pagenum >= screen_data->count) { Elm_Object_Item *item; item = elm_naviframe_bottom_item_get(eulogium->navi); if (item) elm_naviframe_item_pop_to(item); /* XXX what else? */ } else { content = eulogium_multi_screen_menu(eulogium, eulogium->navi, screen_data, pagenum, pageindex); if (content) elm_naviframe_item_simple_push(eulogium->navi, content); /* XXX what else? */ } free(data); } static void _cb_material_set(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { printf("Material: %s selected\n", (char *)data); } Evas_Object *eulogium_multi_screen_menu(struct eulogium_data *eulogium, Evas_Object *parent, struct multi_screen_data *screen_data, uint_fast8_t pagenum, Eina_Bool pageindex) /* TODO swap parent/eulogium */ { Evas_Object *object; Evas_Object *_top, *_bottom; struct _multi_screen_next_cb_data *multi_screen_next_cb_data; char buf[6]; _top = elm_box_add(parent); evas_object_show(_top); if (screen_data->count == 0) { EINA_LOG_WARN("Tut tut, we can't have a count of 0!\n"); return NULL; } if (pagenum >= screen_data->count) pagenum = screen_data->count - 1; if (pageindex) { object = elm_label_add(_top); snprintf(buf, sizeof(buf), "%d/%d", pagenum + 1, screen_data->count); elm_object_text_set(object, _(buf)); evas_object_show(object); evas_object_size_hint_weight_set(object, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(object, 1.0, 0); elm_box_pack_end(_top, object); } if (screen_data->screen[pagenum].text) { object = elm_label_add(_top); elm_object_text_set(object, _(screen_data->screen[pagenum].text)); evas_object_size_hint_align_set(object, 0.5, 0.5); evas_object_show(object); elm_box_pack_end(_top, object); } switch (screen_data->screen[pagenum].type) { Evas_Object *box; /* TODO rename to 'type' or something */ case MATERIAL: box = elm_box_add(_top); elm_box_horizontal_set(box, EINA_TRUE); evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_show(box); object = elm_button_add(box); evas_object_size_hint_align_set(object, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(object, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_text_set(object, "PLA"); /* Materials need to be handled differently */ evas_object_smart_callback_add(object, "clicked", _cb_material_set, "PLA"); evas_object_show(object); elm_box_pack_end(box, object); object = elm_button_add(box); evas_object_size_hint_align_set(object, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(object, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_text_set(object, "ABS"); evas_object_smart_callback_add(object, "clicked", _cb_material_set, "ABS"); evas_object_show(object); elm_box_pack_end(box, object); elm_box_pack_end(_top, box); break; case PROGRESS: box = elm_progressbar_add(_top); elm_progressbar_horizontal_set(box, EINA_TRUE); elm_progressbar_pulse_set(box, EINA_FALSE); /* TODO: pulse = time-unknown/pause */ elm_progressbar_pulse(box, EINA_FALSE); elm_progressbar_value_set(box, 0.5); elm_progressbar_unit_format_set(box, "%1.0f%%"); evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(box); elm_box_pack_end(_top, box); break; case FUNC: /* call function pointer from screen_data.func */ break; case END: /* fall through */ default: break; } _bottom = elm_box_add(parent); elm_box_horizontal_set(_bottom, EINA_TRUE); evas_object_show(_bottom); multi_screen_next_cb_data = malloc(sizeof(struct _multi_screen_next_cb_data)); multi_screen_next_cb_data->eulogium = eulogium; multi_screen_next_cb_data->screen_data = screen_data; multi_screen_next_cb_data->pagenum = pagenum + 1; multi_screen_next_cb_data->pageindex = EINA_TRUE; if (screen_data->screen[pagenum].prev_button) { object = elm_button_add(parent); evas_object_size_hint_align_set(object, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(object, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_text_set(object, _(screen_data->screen[pagenum].prev_button)); evas_object_smart_callback_add(object, "clicked", _cb_content_prev_set, eulogium); evas_object_show(object); elm_box_pack_end(_bottom, object); } if (screen_data->screen[pagenum].next_button) { object = elm_button_add(parent); evas_object_size_hint_align_set(object, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(object, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_text_set(object, _(screen_data->screen[pagenum].next_button)); evas_object_smart_callback_add(object, "clicked", _eulogium_multi_screen_next_cb, multi_screen_next_cb_data); evas_object_show(object); elm_box_pack_end(_bottom, object); } return eulogium_split_screen(parent, _top, _bottom); } Evas_Object *eulogium_menu_confirm(Evas_Object *parent, const char *msg, const char *prev, const struct button_def *next) { Evas_Object *_top, *_bottom, *obj; _top = elm_label_add(parent); elm_object_text_set(_top, _(msg)); evas_object_show(_top); _bottom = elm_box_add(parent); elm_box_horizontal_set(_bottom, EINA_TRUE); evas_object_show(_bottom); obj = elm_button_add(_bottom); evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_smart_callback_add(obj, "clicked", next->cb.func, next->cb.data); elm_object_text_set(obj, _(next->text)); evas_object_show(obj); elm_box_pack_start(_bottom, obj); obj = elm_button_add(_bottom); evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_smart_callback_add(obj, "clicked", but_return.cb.func, but_return.cb.data); elm_object_text_set(obj, _(prev)); evas_object_show(obj); elm_box_pack_end(_bottom, obj); return eulogium_split_screen(parent, _top, _bottom); } Evas_Object *eulogium_dual_button_add(Evas_Object *parent, const struct button_def *left, const struct button_def *right) { Evas_Object *box; Evas_Object *obj, *butbox; box = elm_box_add(parent); elm_box_homogeneous_set(box, EINA_TRUE); evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_horizontal_set(box, EINA_TRUE); butbox = elm_box_add(box); evas_object_size_hint_weight_set(butbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(butbox, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(butbox); elm_box_horizontal_set(butbox, EINA_TRUE); elm_box_pack_end(box, butbox); /* Dummy separator that is not visible to make both buttons identical in size */ obj = elm_separator_add(box); elm_separator_horizontal_set(obj, EINA_FALSE); evas_object_size_hint_weight_set(obj, 0, 0); elm_box_pack_end(butbox, obj); obj = elm_button_add(box); evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_text_set(obj, _(left->text)); evas_object_smart_callback_add(obj, "clicked", left->cb.func, left->cb.data); evas_object_show(obj); elm_box_pack_end(butbox, obj); butbox = elm_box_add(box); evas_object_size_hint_weight_set(butbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(butbox, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(butbox); elm_box_horizontal_set(butbox, EINA_TRUE); elm_box_pack_end(box, butbox); obj = elm_separator_add(box); elm_separator_horizontal_set(obj, EINA_FALSE); evas_object_size_hint_weight_set(obj, 0, 0); evas_object_show(obj); elm_box_pack_end(butbox, obj); obj = elm_button_add(box); evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_text_set(obj, _(right->text)); evas_object_smart_callback_add(obj, "clicked", right->cb.func, right->cb.data); evas_object_show(obj); elm_box_pack_end(butbox, obj); return box; } Evas_Object *eulogium_tripple_button_menu(Evas_Object *parent, const struct button_def *left, const struct button_def *right, const struct button_def *bottom) { Evas_Object *_top, *_bottom; _top = eulogium_dual_button_add(parent, left, right); evas_object_show(_top); _bottom = elm_button_add(parent); elm_object_text_set(_bottom, _(bottom->text)); evas_object_smart_callback_add(_bottom, "clicked", bottom->cb.func, bottom->cb.data); evas_object_show(_bottom); return eulogium_split_screen(parent, _top, _bottom); } static struct multi_screen screen[] = { { .type = NONE, .text = "Welcome
to your new Ultimaker", .func = NULL, .data = NULL, .prev_button = "Skip Wizzard!", .next_button = "Continue", }, { .type = MATERIAL, .text = "Choose material", .func = NULL, .data = NULL, .prev_button = "Skip Wizzard!", .next_button = "Continue", }, { .type = FUNC, .text = "Level bed", .func = NULL, .data = "Bed leveling call", .prev_button = "Skip Wizzard!", .next_button = "Continue", }, { .type = PROGRESS, .text = "Heating ...", .func = NULL, .data = "progress object", .prev_button = "Skip Wizzard!", .next_button = "Continue", }, { .type = NONE, .text = "Lets print!", .func = NULL, .data = NULL, .prev_button = NULL, .next_button = "Let's Print!", }, { .type = END, /* sentinel */ }, }; static struct multi_screen_data screen_data = { .screen = &screen[0], }; Evas_Object *eulogium_main_menu(Evas_Object *window, struct eulogium_data *eulogium) { Evas_Object *content; eulogium->navi = elm_naviframe_add(window); if (!eulogium->navi) return NULL; elm_naviframe_prev_btn_auto_pushed_set(eulogium->navi, EINA_FALSE); /* We removed this from the theme, enabling it causes errors */ content = eulogium_tripple_button_menu(eulogium->navi, &but_main_print, &but_main_mathot, &but_main_system); if (!content) return NULL; elm_naviframe_item_simple_push(eulogium->navi, content); return eulogium->navi; } static void eulogium_setup(struct eulogium_data *eulogium) { while (screen_data.screen[screen_data.count].type != END) screen_data.count++; /* This is silly, barding redonkylous and will get fixed in the refactoring */ eulogium->procedures = procedures_init(); eulogium_button_cb_data_set(&but_return, eulogium); eulogium_button_cb_data_set(&but_print_abort_confirm, eulogium); eulogium_button_cb_data_set(&but_print_abort, eulogium); eulogium_button_cb_data_set(&but_print_tune, eulogium); eulogium_button_cb_data_set(&but_main_print, eulogium); eulogium_button_cb_data_set(&but_print_ignore, eulogium); eulogium_button_cb_data_set(&but_print_local, eulogium); eulogium_button_cb_data_set(&but_print_usb, eulogium); eulogium_button_cb_data_set(&but_main_mathot, eulogium); eulogium_button_cb_data_set(&but_main_system, eulogium); eulogium_button_cb_data_set(&but_system_maintenance, eulogium); eulogium_button_cb_data_set(&but_system_settings, eulogium); eulogium_button_cb_data_set(&but_material_change, eulogium); eulogium_button_cb_data_set(&but_material_settings, eulogium); eulogium_button_cb_data_set(&but_settings_material_1, eulogium); eulogium_button_cb_data_set(&but_settings_material_2, eulogium); eulogium_button_cb_data_set(&but_change_material_1, eulogium); eulogium_button_cb_data_set(&but_change_material_2, eulogium); eulogium_button_cb_data_set(&but_mathot_material, eulogium); eulogium_button_cb_data_set(&but_mathot_hotend, eulogium); eulogium_button_cb_data_set(&but_hotend_change, eulogium); eulogium_button_cb_data_set(&but_hotend_settings, eulogium); eulogium_button_cb_data_set(&but_settings_hotend_1, eulogium); eulogium_button_cb_data_set(&but_settings_hotend_2, eulogium); eulogium_button_cb_data_set(&but_change_hotend_1, eulogium); eulogium_button_cb_data_set(&but_change_hotend_2, eulogium); } static void _on_get_print_name_ret(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) { struct eulogium_data *eulogium = data; const char *errname, *errmsg; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "s", &eulogium->print.name)) { EINA_LOG_ERR("Failed to get printName message."); return; } eulogium->print.name_changed = EINA_TRUE; EINA_LOG_INFO("Printer name updated"); /* TODO Call generic error screen in case of trouble here? */ } static void eulogium_printer_status_set(struct eulogium_data *eulogium, struct _status_msg *status) { Evas_Object *content = NULL; EINA_LOG_WARN("Printer status: %s", status->s); if (eulogium->printer.status != status->i) { switch (status->i) { Elm_Object_Item *item; /* Cases missing: First run wizard, heating, cooling */ #if 0 case (FIRST_RUN_WIZARD): content = eulogium_multi_screen_menu(eulogium, eulogium->navi, &screen_data, 0, EINA_TRUE); if (content) elm_naviframe_item_simple_push(eulogium->navi, content); break; #endif case (PAUSED): /* fall through TODO: make pause screen with resume/other button */ case (HEATING): /* fall through */ case (SLICING): /* fall through */ case (PRINTING): /* fall through */ case (COOLING): /* Check if the previous state was already one of the printing states. * If the state was one of the various printing states, do nothing. */ if (!((eulogium->printer.status == PAUSED) || (eulogium->printer.status == HEATING) || (eulogium->printer.status == SLICING) || (eulogium->printer.status == PRINTING) || (eulogium->printer.status == COOLING))) { //eldbus_proxy_call(eulogium->dbus.proxy[PRINTER], "getPrintName", _on_get_print_name_ret, eulogium, -1, ""); /* For griffin-0.1 this is technically a 'race' condition, as we may not have the name yet */ if (!eulogium->print.block_active) { if (eulogium->print.block) { eulogium->print.block_active = EINA_TRUE; content = eulogium_print_ignore(eulogium); } else { content = eulogium_print_progress(eulogium); } } } break; case (WAIT_FOR_REMOVAL): if (eulogium->printer.status != status->i) { eulogium_print_data_clear(eulogium); content = eulogium_clear_print_bed(eulogium); } break; case (DISCONNECTED): /* fall through */ case (ERROR): //eldbus_proxy_call(eulogium->dbus.proxy[PRINTER], "getError", _on_get_error_ret, eulogium, -1, ""); content = eulogium_generic_error(eulogium, 4); break; case (IDLE): /* XXX BUG, when we abort a print, we may not want to pop to the IDLE screen!! */ /* Pop to the bottom of the stack. TODO: evaluate if a) we want this in a seperate function, b) popping to the bottom may not be the right frame to pop too? */ eulogium_print_data_clear(eulogium); item = elm_naviframe_bottom_item_get(eulogium->navi); if (item) elm_naviframe_item_pop_to(item); /* XXX what to do else? | XXX stack corrupted after this? (see error log) */ else EINA_LOG_CRIT("There is no bottom of the stack!"); break; default: break; } if (content) elm_naviframe_item_simple_push(eulogium->navi, content); //elm_naviframe_item_push(eulogium->navi, NULL, NULL, NULL, content, NULL); /* TODO: When status is printing for example, or waiting_for_Removal, pop to those screens immediatly? */ if (!eulogium->print.block_active) eulogium->printer.status = status->i; } } static void _on_get_file_handlers_ret(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) { const char *errname, *errmsg; Eldbus_Message_Iter *array; uint_fast8_t i; char *file_handler; char **file_handlers = NULL; struct eulogium_data *eulogium = data; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "as", &array)) { EINA_LOG_ERR("Message content does not match expected \"as\" signature."); return; } for (i = 0; (eldbus_message_iter_get_and_next(array, 's', &file_handler)); i++) { size_t fhandler_size = strlen(file_handler) + 1; file_handlers = realloc(file_handlers, (i + 1) * sizeof(char *)); if (!file_handlers) EINA_LOG_ERR("Unable to allocate memory."); else file_handlers[i] = malloc(fhandler_size); if (!file_handlers[i]) EINA_LOG_ERR("Unable to allocate memory."); else strncpy(file_handlers[i], file_handler, fhandler_size); } file_handlers[i] = NULL; /* sentinel */ eulogium->printer.file_handlers = file_handlers; } static void _on_status_changed_ret(void *data, const Eldbus_Message *msg) { _on_get_status_ret(data, msg, NULL); } static void eulogium_disk_free(struct mount_data *mount) { eeze_disk_free(mount->disk); if (mount->id) free(mount->id); eldbus_proxy_unref(mount->proxy); free(mount); mount = NULL; } static void _on_where_ret(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) { struct mount_data *mount = data; const char *errname, *errmsg; Eldbus_Message_Iter *var = NULL; char *where; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "v", &var)) { EINA_LOG_ERR("Message content does not match expected \"v\" signature. (%s)", eldbus_message_signature_get(msg)); return; } if (!eldbus_message_iter_arguments_get(var, "s", &where)) { EINA_LOG_ERR("Message content does not match expected \"s\" signature. (%s)", eldbus_message_iter_signature_get(var)); return; } if (!where) return; /* Never use a medium that is mounted under dev, proc, run or sys. */ if (!(strncmp(where, "/dev/", 5) && strncmp(where, "/proc/", 6) && strncmp(where, "/run/", 5) && strncmp(where, "/sys/", 5))) return; mount->disk = eeze_disk_new_from_mount(where); eeze_disk_scan(mount->disk); EINA_LOG_ERR("Medium mounted at %s of type %d", where, eeze_disk_type_get(mount->disk)); if (eeze_disk_type_get(mount->disk) == EEZE_DISK_TYPE_USB) *mount->mounts = eina_list_append(*mount->mounts, mount); if ((eeze_disk_type_get(mount->disk) == EEZE_DISK_TYPE_FLASH) && (!strstr(eeze_disk_devpath_get(mount->disk), "mmcblk0"))) /* XXX skip using mmcblk0 as that is our root fs for now. This may be handled by udev making it invisible. */ *mount->mounts = eina_list_append(*mount->mounts, mount); else eulogium_disk_free(mount); /* TODO: UI Stuffs/signals */ } static void _on_result_ret(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) { struct mount_data *mount = data; const char *errname, *errmsg; Eldbus_Message_Iter *var = NULL; char *result; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "v", &var)) { EINA_LOG_ERR("Message content does not match expected \"v\" signature. (%s)", eldbus_message_signature_get(msg)); return; } if (!eldbus_message_iter_arguments_get(var, "s", &result)) { EINA_LOG_ERR("Message content does not match expected \"s\" signature. (%s)", eldbus_message_iter_signature_get(var)); return; } if (strncmp(result, "success", 7)) { return; } eldbus_proxy_property_get(mount->proxy, "Where", _on_where_ret, mount); } static void _on_unit_new_ret(void *data, const Eldbus_Message *msg) { const char *errname, *errmsg; struct eulogium_data *eulogium = data; char *id, *unit, *ext; size_t id_len; Eldbus_Object *obj; struct mount_data *mount; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "so", &id, &unit)) { EINA_LOG_ERR("Message content does not match expected \"so\" signature."); return; } ext = ecore_file_ext_get(id); if (strncmp(ext, "mount", 5)) return; obj = eldbus_object_get(eulogium->dbus.conn, "org.freedesktop.systemd1", unit); if (!obj) { EINA_LOG_WARN("Could not get org.freedesktop.systemd1-mount object. (%s)", unit); return; } mount = calloc(1, sizeof(struct mount_data)); if (!mount) { EINA_LOG_ERR("Unable to allocate memory for mountpoint %s", id); return; } id_len = strlen(id); mount->id = malloc(id_len + 1); if (!mount->id) { EINA_LOG_ERR("Unable to allocate memory for id %s", id); free(mount); return; } strncpy(mount->id, id, id_len); mount->proxy = eldbus_proxy_get(obj, "org.freedesktop.systemd1.Mount"); mount->mounts = &eulogium->mounts; if (!mount->proxy) { EINA_LOG_WARN("Could not get dbus proxy for (%s).", id); free(mount->id); free(mount); return; } EINA_LOG_ERR("Medium inserted (%s)", id); eldbus_proxy_property_get(mount->proxy, "Result", _on_result_ret, mount); } static void _on_list_units_ret(void *data, const Eldbus_Message *msg, Eldbus_Pending *Pending EINA_UNUSED) { const char *errname, *errmsg; struct eulogium_data *eulogium = data; Eldbus_Message_Iter *array, *units_struct; char *id, *unit; char *dummy; uint_fast32_t dummy_int; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "a(ssssssouso)", &array)) { EINA_LOG_ERR("Message content does not match expected \"a(ssssssouso)\" signature. (%s)", eldbus_message_signature_get(msg)); return; } while (eldbus_message_iter_get_and_next(array, 'r', &units_struct)) { if (eldbus_message_iter_arguments_get(units_struct, "ssssssouso", &id, &dummy, &dummy, &dummy, &dummy, &dummy, &unit, &dummy_int, &dummy, &dummy)) { Eldbus_Object *obj; struct mount_data *mount; size_t id_len; obj = eldbus_object_get(eulogium->dbus.conn, "org.freedesktop.systemd1", unit); if (!obj) { EINA_LOG_WARN("Could not get org.freedesktop.systemd1-mount object. (%s)", unit); return; } mount = calloc(1, sizeof(struct mount_data)); if (!mount) { EINA_LOG_ERR("Unable to allocate memory for mountpoint %s", id); break; } id_len = strlen(id); mount->id = malloc(id_len + 1); if (!mount->id) { EINA_LOG_ERR("Unable to allocate memory for id %s", id); free(mount); break; } strncpy(mount->id, id, id_len); mount->proxy = eldbus_proxy_get(obj, "org.freedesktop.systemd1.Mount"); if (!mount->proxy) { EINA_LOG_WARN("Could not get dbus proxy for (%s).", id); free(mount->id); free(mount); break; } mount->mounts = &eulogium->mounts; EINA_LOG_ERR("Medium detected (%s)", id); eldbus_proxy_property_get(mount->proxy, "Result", _on_result_ret, mount); } else { EINA_LOG_ERR("Unable to decode dbus-struct\n"); } } } static int _mount_find_cb(const void *haystack, const void *needle) { const struct mount_data *mount = haystack; const char *id = needle; return strncmp(id, mount->id, strlen(id)); } static void _on_unit_removed_ret(void *data, const Eldbus_Message *msg) { const char *errname, *errmsg; struct eulogium_data *eulogium = data; char *id, *unit, *ext; Eldbus_Object *obj; struct mount_data *mount; Eina_List *list; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "so", &id, &unit)) { EINA_LOG_ERR("Message content does not match expected \"so\" signature."); return; } ext = ecore_file_ext_get(id); if (strncmp(ext, "mount", 5)) return; obj = eldbus_object_get(eulogium->dbus.conn, "org.freedesktop.systemd1", unit); if (!obj) { EINA_LOG_WARN("Could not get org.freedesktop.systemd1-mount object (%s).", unit); return; } EINA_LOG_ERR("Medium remove request (%s)", id); list = eina_list_search_unsorted_list(eulogium->mounts, _mount_find_cb, id); /* XXX verify if we don't need a pointer pointer for mounts */ mount = eina_list_data_get(list); if (!mount) { EINA_LOG_CRIT("Mount %s is NULL, this should not happen!", id); } else { eulogium_disk_free(mount); eulogium->mounts = eina_list_remove_list(eulogium->mounts, list); } /* TODO: UI Stuff/signals */ } static void _on_get_available_procedures_ret(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) { const char *errname, *errmsg; struct eulogium_data *eulogium = data; Eldbus_Message_Iter *array, *avail_proc_struct; char *key; Eina_Bool executable; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "a(sb)", &array)) { EINA_LOG_ERR("Message content does not match expected \"a(sb)\" signature."); return; } while (eldbus_message_iter_get_and_next(array, 'r', &avail_proc_struct)) { if (eldbus_message_iter_arguments_get(avail_proc_struct, "sb", &key, &executable)) { uint_fast16_t i; for (i = 0; eulogium->procedures[i].key ; i++) { if (strncmp(key, eulogium->procedures[i].key, eulogium->procedures[i].keylen)) { eulogium->procedures[i].executable = executable; eulogium->procedures[i].available = EINA_TRUE; } else { EINA_LOG_WARN("Procedure not found: '%s'", key); } } } } } static void _on_get_active_procedures_ret(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) { const char *errname, *errmsg; struct eulogium_data *eulogium = data; Eldbus_Message_Iter *array, *act_proc_struct; char *key, *step; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "a(ss)", &array)) { EINA_LOG_ERR("Message content does not match expected \"a(ss)\" signature."); return; } while (eldbus_message_iter_get_and_next(array, 'r', &act_proc_struct)) { if (eldbus_message_iter_arguments_get(act_proc_struct, "ss", &key, &step)) { uint_fast16_t i; for (i = 0; eulogium->procedures[i].key ; i++) { if (strncmp(key, eulogium->procedures[i].key, eulogium->procedures[i].keylen)) { printf("Step: %s\n", step); } else { EINA_LOG_WARN("Procedure not found: '%s'", key); } } } } } static void _on_procedure_start_ret(void *data EINA_UNUSED, const Eldbus_Message *msg) { const char *errname, *errmsg; const char *key, *step; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "ss", &key, &step)) { EINA_LOG_ERR("Message content does not match expected \"ss\" signature. (%s)", eldbus_message_signature_get(msg)); return; } EINA_LOG_ERR("Key '%s' step %s", key, step); } static void _on_procedure_next_step_ret(void *data EINA_UNUSED, const Eldbus_Message *msg) { const char *errname, *errmsg; const char *key, *step; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "ss", &key, &step)) { EINA_LOG_ERR("Message content does not match expected \"ss\" signature. (%s)", eldbus_message_signature_get(msg)); return; } EINA_LOG_ERR("next: Key '%s' step %s", key, step); } static void _on_procedure_finished_ret(void *data EINA_UNUSED, const Eldbus_Message *msg) { const char *errname, *errmsg; const char *key; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "s", &key)) { EINA_LOG_ERR("Message content does not match expected \"s\" signature. (%s)", eldbus_message_signature_get(msg)); return; } EINA_LOG_ERR("finshed Key '%s'", key); } static void _on_get_error_ret(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) { const char *errname, *errmsg, *errormsg; if (eldbus_message_error_get(msg, &errname, &errmsg)) { EINA_LOG_ERR("%s %s", errname, errmsg); return; } if (!eldbus_message_arguments_get(msg, "s", &errormsg)) { EINA_LOG_ERR("Message content does not match expected \"s\" signature. (%s)", eldbus_message_signature_get(msg)); return; } if (strlen(errormsg) > 0) EINA_LOG_ERR("Printer Error '%s' received", errormsg); /* TODO Call generic error screen in case of trouble here? */ } static void _on_error_ret(void *data, const Eldbus_Message *msg) { _on_get_error_ret(data, msg, NULL); } static uint_fast16_t _dbus_members_map(Eldbus_Proxy *proxy, struct menu_entry_def *entry) { uint_fast16_t i; for (i = 0; entry[i].label; i++) { if (entry[i].dbus.signal && entry[i].dbus.sig_cb) eldbus_proxy_signal_handler_add(proxy, entry[i].dbus.signal, entry[i].dbus.sig_cb, &entry[i].item); if (entry[i].dbus.get && entry[i].dbus.get_cb) eldbus_proxy_call(proxy, entry[i].dbus.get, entry[i].dbus.get_cb, &entry[i].item, -1, ""); } return i; } static int eulogium_dbus_init(struct eulogium_data *eulogium) { Eldbus_Object *obj; Eldbus_Proxy *proxy; Eldbus_Message_Iter *iter, *array; Eldbus_Message *msg; eulogium->dbus.conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM); if (!eulogium->dbus.conn) { EINA_LOG_CRIT("Could not get system dbus."); return -ECONNREFUSED; } obj = eldbus_object_get(eulogium->dbus.conn, "org.freedesktop.systemd1", "/org/freedesktop/systemd1"); if (!obj) { EINA_LOG_WARN("Could not get org.freedesktop.systemd1 object."); return -EFAULT; } /* XXX We currently monitor systemd for new mounts. This functionality should really be handled by eeze and once it may does, this has to be re-written. */ proxy = eldbus_proxy_get(obj, "org.freedesktop.systemd1.Manager"); if (!proxy) { EINA_LOG_WARN("Could not get dbus systemd-manager proxy."); return -EFAULT; } /* TODO: Make nice loop that gets BUS/PATH from a predefined array? */ obj = eldbus_object_get(eulogium->dbus.conn, "nl.ultimaker.led", "/nl/ultimaker/led"); if (!obj) { return -EFAULT; EINA_LOG_WARN("Could not get nl.ultimaker.led object."); } eulogium->dbus.proxy[LED] = eldbus_proxy_get(obj, "nl.ultimaker"); if (!eulogium->dbus.proxy[LED]) { EINA_LOG_WARN("Could not get dbus led proxy."); return -EFAULT; } obj = eldbus_object_get(eulogium->dbus.conn, "nl.ultimaker.printer", "/nl/ultimaker/printer"); if (!obj) { EINA_LOG_WARN("Could not get nl.ultimaker.printer object."); return -EFAULT; } eulogium->dbus.proxy[PRINTER] = eldbus_proxy_get(obj, "nl.ultimaker"); if (!eulogium->dbus.proxy[PRINTER]) { EINA_LOG_WARN("Could not get dbus printer proxy."); return -EFAULT; } obj = eldbus_object_get(eulogium->dbus.conn, "nl.ultimaker.network", "/nl/ultimaker/network"); if (!obj) { EINA_LOG_WARN("Could not get nl.ultimaker.network object."); return -EFAULT; } eulogium->dbus.proxy[NETWORK] = eldbus_proxy_get(obj, "nl.ultimaker"); if (!eulogium->dbus.proxy[NETWORK]) { EINA_LOG_WARN("Could not get dbus network proxy."); return -EFAULT; } _dbus_members_map(eulogium->dbus.proxy[NETWORK], menu_settings_network.entry); /* TODO: put signal/method name strings in macro/LUT */ eldbus_proxy_call(eulogium->dbus.proxy[NETWORK], "getNetworkInfo", on_method_get_network_info_ret, eulogium, -1, ""); eldbus_proxy_signal_handler_add(eulogium->dbus.proxy[NETWORK], "NetworkInfoChanged", on_signal_network_info_changed_ret, eulogium); eldbus_proxy_call(eulogium->dbus.proxy[PRINTER], "getError", _on_get_error_ret, eulogium, -1, ""); eldbus_proxy_signal_handler_add(eulogium->dbus.proxy[PRINTER], "onError", _on_error_ret, eulogium); eldbus_proxy_call(eulogium->dbus.proxy[PRINTER], "getAvailableProcedures", _on_get_available_procedures_ret, eulogium, -1, ""); eldbus_proxy_call(eulogium->dbus.proxy[PRINTER], "getActiveProcedures", _on_get_active_procedures_ret, eulogium, -1, ""); eldbus_proxy_signal_handler_add(eulogium->dbus.proxy[PRINTER], "onProcedureStart", _on_procedure_start_ret, eulogium); eldbus_proxy_signal_handler_add(eulogium->dbus.proxy[PRINTER], "onProcedureNextStep", _on_procedure_next_step_ret, eulogium); eldbus_proxy_signal_handler_add(eulogium->dbus.proxy[PRINTER], "onProcedureFinished", _on_procedure_finished_ret, eulogium); //eldbus_proxy_call(eulogium->dbus.proxy[PRINTER], "getFileHandlers", _on_get_file_handlers_ret, eulogium, -1, ""); //eldbus_proxy_call(eulogium->dbus.proxy[PRINTER], "getStatus", _on_get_status_ret, eulogium, -1, ""); //eldbus_proxy_call(eulogium->dbus.proxy[PRINTER], "getPrintName", _on_get_print_name_ret, eulogium, -1, ""); //eldbus_proxy_signal_handler_add(eulogium->dbus.proxy[PRINTER], "statusChanged", _on_status_changed_ret, eulogium); eldbus_proxy_signal_handler_add(proxy, "UnitNew", _on_unit_new_ret, eulogium); eldbus_proxy_signal_handler_add(proxy, "UnitRemoved", _on_unit_removed_ret, eulogium); msg = eldbus_proxy_method_call_new(proxy, "ListUnitsFiltered"); iter = eldbus_message_iter_get(msg); array = eldbus_message_iter_container_new(iter, 'a', "s"); if (!array) EINA_LOG_ERR("Empty container"); eldbus_message_iter_basic_append(array, 's', "mounted"); eldbus_message_iter_container_close(iter, array); eldbus_proxy_send(proxy, msg, _on_list_units_ret, eulogium, -1); /* eldbus_proxy_call(proxy, "ListUnitsFiltered", _on_list_units_ret, eulogium, -1, "as", "{mounted}"); */ return 0; } EAPI_MAIN int elm_main(int argc, char **argv) { Eina_Bool quit_option = EINA_FALSE; static const Ecore_Getopt optdesc = { PACKAGE_NAME, "%prog [options]", PACKAGE_VERSION, COPYRIGHT, "Affero GPLv3", "eulogium program", 0, { ECORE_GETOPT_LICENSE('L', "license"), ECORE_GETOPT_COPYRIGHT('C', "copyright"), ECORE_GETOPT_VERSION('V', "version"), ECORE_GETOPT_HELP('h', "help"), ECORE_GETOPT_SENTINEL } }; Ecore_Getopt_Value values[] = { ECORE_GETOPT_VALUE_BOOL(quit_option), ECORE_GETOPT_VALUE_BOOL(quit_option), ECORE_GETOPT_VALUE_BOOL(quit_option), ECORE_GETOPT_VALUE_BOOL(quit_option), ECORE_GETOPT_VALUE_NONE }; int args; uint_fast8_t i; struct eulogium_data eulogium = { .mounts = NULL, .progress_data_refresh = NULL, .print = { .name = NULL, .url = NULL, .block = EINA_TRUE, .block_active = EINA_FALSE, }, .printer = { .status = DISCONNECTED, .file_handlers = NULL, }, .footer = NULL, }; Evas_Object *window, *object; // Evas_Object *splash_window; // Eina_List *engines, *l; eeze_init(); eeze_disk_function(); if (!(eeze_disk_can_mount() && eeze_disk_can_unmount())) EINA_LOG_ERR("No disk (u)mount support available"); elm_need_eldbus(); args = ecore_getopt_parse(&optdesc, values, argc, argv); if (args < 0) { EINA_LOG_CRIT("Could not parse arguments."); return EXIT_FAILURE; } // elm_prefs_data_new(); /* TODO */ elm_policy_set(ELM_POLICY_QUIT, /* ELM_POLICY_QUIT_NONE */ ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); elm_app_compile_bin_dir_set(PACKAGE_BIN_DIR); elm_app_compile_lib_dir_set(PACKAGE_LIB_DIR); elm_app_compile_data_dir_set(PACKAGE_DATA_DIR); #if HAVE_GETTEXT && ENABLE_NLS elm_app_compile_locale_set(LOCALE_DIR); #endif #if ENABLE_NLS /* TODO Check for removal, elm_app_compile may solve this allready */ setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALE_DIR); bind_textdomain_codeset(PACKAGE, "UTF-8"); textdomain(PACKAGE); #endif elm_app_info_set(NULL, PACKAGE, NULL); /* TODO */ #if (ELM_VERSION_MAJOR > 1) || (ELM_VERSION_MINOR >= 10) elm_config_accel_preference_set("accel"); #endif elm_theme_overlay_add(NULL, "./default.edj"); #if 0 /* TODO make icon */ icon = evas_object_image_add(evas_object_evas_get(win)); snprintf(buf, sizeof(buf), "%s/images/rage.png", elm_app_data_dir_get()); evas_object_image_file_set(o, buf, NULL); elm_win_icon_object_set(win, o); #endif elm_config_focus_highlight_enabled_set(EINA_FALSE); elm_config_focus_highlight_animate_set(EINA_FALSE); elm_config_softcursor_mode_set(ELM_SOFTCURSOR_MODE_OFF); if (eulogium_dbus_init(&eulogium)) EINA_LOG_CRIT("Griffin D-Bus initialization failed!"); /* TODO: move into its own init */ window = elm_win_add(NULL, PACKAGE_NAME, ELM_WIN_BASIC); if (!window) return EXIT_FAILURE; evas_object_resize(window, 128, 64); elm_win_title_set(window, PACKAGE_NAME); evas_object_repeat_events_set(window, EINA_TRUE); elm_win_autodel_set(window, EINA_TRUE); evas_object_smart_callback_add(window, "delete,request", _cb_eulogium_exit, NULL); object = elm_bg_add(window); if (!object) return EXIT_FAILURE; evas_object_size_hint_weight_set(object, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(object, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_win_resize_object_add(window, object); evas_object_show(object); eulogium_setup(&eulogium); eulogium_print_data_clear(&eulogium); object = eulogium_main_menu(window, &eulogium); if (!object) return EXIT_FAILURE; evas_object_size_hint_weight_set(object, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(object, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_win_resize_object_add(window, object); evas_object_show(object); #if 0 /* Ideally we want to add the callbacks to the window. This currently does not work */ evas_object_event_callback_add(window, EVAS_CALLBACK_MOUSE_WHEEL, _cb_eulogium_input_wheel, NULL); #else /* HACK: draw a transparent rectangle over the entire window and capture events we are interested in */ object = evas_object_rectangle_add(evas_object_evas_get(window)); if (!object) return EXIT_FAILURE; evas_object_size_hint_weight_set(object, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_color_set(object, 0, 0, 0, 0); evas_object_repeat_events_set(object, EINA_TRUE); evas_object_event_callback_add(object, EVAS_CALLBACK_MOUSE_WHEEL, _cb_eulogium_input_wheel, window); /* TODO: don't these two input events repeat/fall through, everything else, may/should. */ evas_object_show(object); elm_win_resize_object_add(window, object); #endif evas_object_show(window); elm_run(); eldbus_connection_unref(eulogium.dbus.conn); if (eulogium.printer.file_handlers != NULL) for (i = 0; eulogium.printer.file_handlers[i] != NULL; i++) free(eulogium.printer.file_handlers[i]); free(eulogium.printer.file_handlers); /* TODO: Cleanup function? */ elm_shutdown(); eeze_shutdown(); return EXIT_SUCCESS; } ELM_MAIN();