From 14a30c74b00a7981b600c8ca9323a8eb8bf9ecdb Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Wed, 11 Sep 2019 09:50:05 +0100 Subject: [PATCH] blue4 - remove. obsolete now and bluez5 has replaced it --- TODO | 1 - meson_options.txt | 4 - src/bin/e_module.c | 1 - src/modules/bluez4/agent.c | 261 -------- src/modules/bluez4/agent.h | 4 - src/modules/bluez4/e-module-bluez4.edj | Bin 56750 -> 0 bytes src/modules/bluez4/e_mod_main.c | 837 ------------------------ src/modules/bluez4/e_mod_main.h | 38 -- src/modules/bluez4/ebluez4.c | 843 ------------------------- src/modules/bluez4/ebluez4.h | 84 --- src/modules/bluez4/meson.build | 5 - src/modules/bluez4/module.desktop | 13 - src/modules/meson.build | 1 - 13 files changed, 2092 deletions(-) delete mode 100644 src/modules/bluez4/agent.c delete mode 100644 src/modules/bluez4/agent.h delete mode 100644 src/modules/bluez4/e-module-bluez4.edj delete mode 100644 src/modules/bluez4/e_mod_main.c delete mode 100644 src/modules/bluez4/e_mod_main.h delete mode 100644 src/modules/bluez4/ebluez4.c delete mode 100644 src/modules/bluez4/ebluez4.h delete mode 100644 src/modules/bluez4/meson.build delete mode 100644 src/modules/bluez4/module.desktop diff --git a/TODO b/TODO index db5a5e8c3..3290af17f 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,4 @@ TODO: -* bluez4: remove as it's obsolete * scriptlets: stdin/out module that provides gui services to some back-end script or process where e just talks via stdin/out. things to provide: diff --git a/meson_options.txt b/meson_options.txt index 2eda899fc..d3457def8 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -107,10 +107,6 @@ option('battery', type: 'boolean', value: true, description: 'enable battery module: (default=true)') -option('bluez4', - type: 'boolean', - value: true, - description: 'enable bluez4 module: (default=true)') option('bluez5', type: 'boolean', value: true, diff --git a/src/bin/e_module.c b/src/bin/e_module.c index 9a183e3d5..6ccedc0ff 100644 --- a/src/bin/e_module.c +++ b/src/bin/e_module.c @@ -878,7 +878,6 @@ _e_module_whitelist_check(void) { "backlight", "battery", - "bluez4", "bluez5", "clock", "conf", diff --git a/src/modules/bluez4/agent.c b/src/modules/bluez4/agent.c deleted file mode 100644 index 854c15abb..000000000 --- a/src/modules/bluez4/agent.c +++ /dev/null @@ -1,261 +0,0 @@ -#include -#include "e.h" -#include "ebluez4.h" -#include "agent.h" - -#define AGENT_INTERFACE "org.bluez.Agent" -#define BLUEZ_ERROR_FAILED "org.bluez.Error.Failed" -#define GET_ERROR_MSG "eldbus_message_arguments_get() error" -#define BLUEZ_ERROR_REJECTED "org.bluez.Error.Rejected" -#define REJECTED_MSG "Request was rejected" - -static Eldbus_Connection *bluez_conn; -static char buf[1024]; - -/* Local Functions */ -static void -_reply(Eldbus_Message *message, Eldbus_Message *reply) -{ - eldbus_connection_send(bluez_conn, reply, NULL, NULL, -1); - eldbus_message_unref(message); -} - -static void -_pincode_ok(void *data, char *text) -{ - Eldbus_Message *message = data; - Eldbus_Message *reply = eldbus_message_method_return_new(message); - eldbus_message_arguments_append(reply, "s", text); - _reply(message, reply); -} - -static void -_passkey_ok(void *data, char *text) -{ - Eldbus_Message *message = data; - uint32_t passkey = (uint32_t)atoi(text); - Eldbus_Message *reply = eldbus_message_method_return_new(message); - eldbus_message_arguments_append(reply, "u", passkey); - _reply(message, reply); -} - -static void -_cancel(void *data) -{ - Eldbus_Message *message = data; - Eldbus_Message *reply = eldbus_message_error_new(message, - BLUEZ_ERROR_REJECTED, REJECTED_MSG); - _reply(message, reply); -} - -static E_Dialog * -_create_dialog(const char *title, const char *msg, - const char *icon, const char *class) -{ - E_Dialog *dialog; - - dialog = e_dialog_new(NULL, title, class); - e_dialog_title_set(dialog, _(title)); - e_dialog_icon_set(dialog, icon, 64); - e_dialog_text_set(dialog, msg); - return dialog; -} - -static void -_display_msg(const char *title, const char *msg) -{ - E_Dialog *dialog = _create_dialog(title, msg, "view-hidden-files", - "display"); - e_dialog_button_add(dialog, _("OK"), NULL, NULL, NULL); - e_dialog_show(dialog); -} - -static void -_reply_and_del_dialog(Eldbus_Message *reply, E_Dialog *dialog) -{ - Eldbus_Message *message; - - if (!dialog) return; - if (!(message = dialog->data)) return; - _reply(message, reply); - e_object_del(E_OBJECT(dialog)); -} - -static void -_reject(void *data EINA_UNUSED, E_Dialog *dialog) -{ - const Eldbus_Message *msg = dialog->data; - Eldbus_Message *reply = eldbus_message_error_new(msg, BLUEZ_ERROR_REJECTED, - REJECTED_MSG); - _reply_and_del_dialog(reply, dialog); -} - -static void -_close(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) -{ - E_Dialog *dialog = data; - _reject(NULL, dialog); -} - -static void -_ok(void *data EINA_UNUSED, E_Dialog *dialog) -{ - const Eldbus_Message *msg = dialog->data; - Eldbus_Message *reply = eldbus_message_method_return_new(msg); - evas_object_event_callback_del_full(dialog->win, EVAS_CALLBACK_DEL, _close, dialog); - _reply_and_del_dialog(reply, dialog); -} - -static void -_ask(const char *title, const char *ask_msg, const char *ok_label, - Eldbus_Message *eldbus_message) -{ - E_Dialog *dialog = _create_dialog(title, ask_msg, "dialog-ask", "ask"); - dialog->data = eldbus_message; - evas_object_event_callback_add(dialog->win, EVAS_CALLBACK_DEL, _close, dialog); - e_dialog_button_add(dialog, ok_label, NULL, _ok, NULL); - e_dialog_button_add(dialog, _("Reject"), NULL, _reject, NULL); - e_dialog_show(dialog); -} - -/* Implementation of agent API */ -static Eldbus_Message * -_agent_release(const Eldbus_Service_Interface *iface EINA_UNUSED, - const Eldbus_Message *message) -{ - DBG("Agent Released."); - return eldbus_message_method_return_new(message); -} - -static Eldbus_Message * -_agent_request_pin_code(const Eldbus_Service_Interface *iface EINA_UNUSED, - const Eldbus_Message *message) -{ - Eldbus_Message *msg = (Eldbus_Message *)message; - eldbus_message_ref(msg); - e_entry_dialog_show(_("Pin Code Requested"), NULL, - _("Enter the PinCode above. It should have 1-16 " - "characters and can be alphanumeric."), "0000", - _("OK"), _("Cancel"), _pincode_ok, _cancel, msg); - return NULL; -} - -static Eldbus_Message * -_agent_request_passkey(const Eldbus_Service_Interface *iface EINA_UNUSED, - const Eldbus_Message *message) -{ - Eldbus_Message *msg = (Eldbus_Message *)message; - eldbus_message_ref(msg); - e_entry_dialog_show(_("Passkey Requested"), NULL, - _("Enter the Passkey above. " - "It should be a numeric value between 0-999999."), - "0", _("OK"), _("Cancel"), _passkey_ok, _cancel, msg); - return NULL; -} - -static Eldbus_Message * -_agent_display_passkey(const Eldbus_Service_Interface *iface EINA_UNUSED, - const Eldbus_Message *message) -{ - const char *device; - uint32_t passkey; - uint16_t entered; - Device *dev; - - if(!eldbus_message_arguments_get(message, "ouq", &device, &passkey, &entered)) - return eldbus_message_error_new(message, BLUEZ_ERROR_FAILED, GET_ERROR_MSG); - dev = eina_list_search_unsorted(ctxt->devices, ebluez4_dev_path_cmp, device); - snprintf(buf, sizeof(buf), _("%d keys were typed on %s. Passkey is %06d"), - entered, dev->name, passkey); - _display_msg(N_("Display Passkey"), buf); - return eldbus_message_method_return_new(message); -} - -static Eldbus_Message * -_agent_display_pin_code(const Eldbus_Service_Interface *iface EINA_UNUSED, - const Eldbus_Message *message) -{ - const char *device, *pincode; - Device *dev; - - if(!eldbus_message_arguments_get(message, "os", &device, &pincode)) - return eldbus_message_error_new(message, BLUEZ_ERROR_FAILED, GET_ERROR_MSG); - dev = eina_list_search_unsorted(ctxt->devices, ebluez4_dev_path_cmp, device); - snprintf(buf, sizeof(buf), _("Pincode for %s is %s"), dev->name, pincode); - _display_msg(N_("Display Pincode"), buf); - return eldbus_message_method_return_new(message); -} - -static Eldbus_Message * -_agent_request_confirmation(const Eldbus_Service_Interface *iface EINA_UNUSED, - const Eldbus_Message *message) -{ - const char *device; - uint32_t passkey; - Device *dev; - - if(!eldbus_message_arguments_get(message, "ou", &device, &passkey)) - return eldbus_message_error_new(message, BLUEZ_ERROR_FAILED, GET_ERROR_MSG); - dev = eina_list_search_unsorted(ctxt->devices, ebluez4_dev_path_cmp, device); - snprintf(buf, sizeof(buf), _("%06d is the passkey presented in %s?"), - passkey, dev->name); - eldbus_message_ref((Eldbus_Message *)message); - _ask(N_("Confirm Request"), buf, _("Confirm"), (Eldbus_Message *)message); - return NULL; -} - -static Eldbus_Message * -_agent_authorize(const Eldbus_Service_Interface *iface EINA_UNUSED, - const Eldbus_Message *message) -{ - const char *device, *uuid; - Device *dev; - - if(!eldbus_message_arguments_get(message, "os", &device, &uuid)) - return eldbus_message_error_new(message, BLUEZ_ERROR_FAILED, GET_ERROR_MSG); - dev = eina_list_search_unsorted(ctxt->devices, ebluez4_dev_path_cmp, device); - snprintf(buf, sizeof(buf), _("Grant permission for %s to connect?"), - dev->name); - eldbus_message_ref((Eldbus_Message *)message); - _ask(N_("Authorize Connection"), buf, _("Grant"), (Eldbus_Message *)message); - return NULL; -} - -static Eldbus_Message * -_agent_cancel(const Eldbus_Service_Interface *iface EINA_UNUSED, - const Eldbus_Message *message) -{ - DBG("Request canceled."); - return eldbus_message_method_return_new(message); -} - -static const Eldbus_Method agent_methods[] = { - { "Release", NULL, NULL, _agent_release, 0 }, - { "RequestPinCode", ELDBUS_ARGS({"o", "device"}), - ELDBUS_ARGS({"s", "pincode"}), _agent_request_pin_code, 0 }, - { "RequestPasskey", ELDBUS_ARGS({"o", "device"}), - ELDBUS_ARGS({"u", "passkey"}), _agent_request_passkey, 0 }, - { "DisplayPasskey", - ELDBUS_ARGS({"o", "device"},{"u", "passkey"},{"q", "entered"}), - NULL, _agent_display_passkey, 0 }, - { "DisplayPinCode", ELDBUS_ARGS({"o", "device"},{"s", "pincode"}), - NULL, _agent_display_pin_code, 0 }, - { "RequestConfirmation", ELDBUS_ARGS({"o", "device"},{"u", "passkey"}), - NULL, _agent_request_confirmation, 0 }, - { "Authorize", ELDBUS_ARGS({"o", "device"},{"s", "uuid"}), - NULL, _agent_authorize, 0 }, - { "Cancel", NULL, NULL, _agent_cancel, 0 }, - { NULL, NULL, NULL, NULL, 0 } -}; - -static const Eldbus_Service_Interface_Desc agent_iface = { - AGENT_INTERFACE, agent_methods, NULL, NULL, NULL, NULL -}; - -/* Public Functions */ -void ebluez4_register_agent_interfaces(Eldbus_Connection *conn) -{ - bluez_conn = conn; - eldbus_service_interface_register(conn, AGENT_PATH, &agent_iface); - eldbus_service_interface_register(conn, REMOTE_AGENT_PATH, &agent_iface); -} diff --git a/src/modules/bluez4/agent.h b/src/modules/bluez4/agent.h deleted file mode 100644 index daf6c5334..000000000 --- a/src/modules/bluez4/agent.h +++ /dev/null @@ -1,4 +0,0 @@ -#define AGENT_PATH "/org/bluez/Agent" -#define REMOTE_AGENT_PATH "/org/bluez/RemoteAgent" - -void ebluez4_register_agent_interfaces(Eldbus_Connection *conn); diff --git a/src/modules/bluez4/e-module-bluez4.edj b/src/modules/bluez4/e-module-bluez4.edj deleted file mode 100644 index 3655850713a671b3c6f73a26298e0bd3e6b82e65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56750 zcmce-by(ET_rSY=gwlD7o(zS$$38)|{vC<&jy>uuDs3;(@V1XbY(zyZ>q5{(0 z-665CyYD-T@cE*@d;h)rJi|Hj+R1ayoY{hVidGp0gHeF;1qM4B0E0cK|5Ipx07e4} zcz9lc!R{9SDYU%+?C~}t7>ooIMo_1n2AmNT(6*BpNUA@Db_Yl%P{5-Tv?B)P$X6JQ zjurrFP(b@`P9V!+utRcy6Z9i{yc-51`UQiLr2~Enu)XnnKY)2j|IAA#{XY%^^U_@h zbqZ+j0d&xgP7BDx2bd9H`v0^G1I!dKvIFf30J8#&>Hu>9%xVJvQB>!oL1PrwO%T})eQ~!r~0CpcRngery z7^1fT?BEfUyI1 zFg8K}BlzQBj02xB2m^L-AA~u84PoSj^#OStlyiV70eLW<#{jzl*un9@dKt6H4I0ki#wf%s!^-Dg13fU*o2h?&1^0OEjw;NM-l0LcOhIByJK%>NiE z(ER|5-e-IJg9G*wu-*OcF%Y8+N&he(z~27DfWH|s0Xt~FYQPHrVc^^|5MtwC?5Y6P z4A{Zg1?QXr#L*uHBn2q`fGq)euyI~YU6fDvM2mjOw5@BzjHbZgSch7u+R3^{S7chzz&{iUckVe^q2iW z3@{PS^nMHx#sT|hLI8O%PZH)OoZnprqz)+5fcfmRy?HADi`ZvCs)F(gumm6v-aUjh ze*%nguissurvp|4BnyEN9zZ`0SPzi9{@7z_fXxARa6FKk2(J3WfIJJzF;FEy`rX0) zjMoSl!G608NGec3>@kC!@Yi@}K$T#t-8p~+=ZcUknGJzFI39>oX2*R7FhYLe-0OD^=wAVA1@hp%0Ahu?8?b{h6b#tdKMce! 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 diff --git a/src/modules/bluez4/e_mod_main.c b/src/modules/bluez4/e_mod_main.c deleted file mode 100644 index 4b5148634..000000000 --- a/src/modules/bluez4/e_mod_main.c +++ /dev/null @@ -1,837 +0,0 @@ -#include -#include -#include "e_mod_main.h" -#include "ebluez4.h" - -/* Local Variables */ -static Ecore_Exe *autolock_exe = NULL; -static Ecore_Poller *autolock_poller = NULL; -static Ecore_Event_Handler *autolock_die = NULL; -static Ecore_Event_Handler *autolock_out = NULL; -static Ecore_Event_Handler *autolock_desklock = NULL; -static Eina_Bool autolock_initted = EINA_FALSE; -static Eina_Bool autolock_waiting = EINA_TRUE; - -static Eina_List *instances = NULL; -static E_Module *mod = NULL; -static char tmpbuf[1024]; - -/* Local config */ -static E_Config_DD *conf_edd = NULL; -Config *ebluez4_config = NULL; - -E_API E_Module_Api e_modapi = {E_MODULE_API_VERSION, "Bluez4"}; - -/* Local Functions */ -static Eina_Bool -_ebluez_l2ping_poller(void *data EINA_UNUSED) -{ - Eina_Strbuf *buf; - const char *tmp = NULL; - - autolock_poller = NULL; - - buf = eina_strbuf_new(); - if (e_desklock_state_get()) - { - if (!autolock_waiting) - tmp = ebluez4_config->unlock_dev_addr; - else - tmp = ebluez4_config->lock_dev_addr; - } - else - { - if (!autolock_waiting) - tmp = ebluez4_config->lock_dev_addr; - else - tmp = ebluez4_config->unlock_dev_addr; - } - - if (tmp) - { - eina_strbuf_append_printf(buf, "%s/enlightenment/utils/enlightenment_sys l2ping %s", - e_prefix_lib_get(), tmp); - autolock_exe = ecore_exe_run(eina_strbuf_string_get(buf), NULL); - } - - eina_strbuf_free(buf); - - return 0; -} - -static void -_ebluez4_search_dialog_del(Instance *inst) -{ - if (!inst->search_dialog) return; - e_object_del(E_OBJECT(inst->search_dialog)); - inst->search_dialog = NULL; - inst->found_list = NULL; - - if (ctxt->adap_obj) - { - ebluez4_stop_discovery(); - DBG("Stopping discovery..."); - } -} - -static void -_ebluez4_cb_search_dialog_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) -{ - E_Dialog *dialog = data; - _ebluez4_search_dialog_del(dialog->data); -} - -static void -_ebluez4_cb_paired(void *data, Eina_Bool success, const char *err_msg) -{ - Instance *inst = data; - if (success) - _ebluez4_search_dialog_del(inst); - else - ebluez4_show_error(_("Bluez Error"), err_msg); -} - -static void -_ebluez4_cb_pair(void *data) -{ - Instance *inst = data; - const char *addr = e_widget_ilist_selected_value_get(inst->found_list); - - if(!addr) - return; - ebluez4_pair_with_device(addr, _ebluez4_cb_paired, inst); -} - -static void -_ebluez4_cb_search(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) -{ - Instance *inst = data; - E_Dialog *dialog; - Evas *evas; - - if (inst->search_dialog) - _ebluez4_search_dialog_del(inst); - - dialog = e_dialog_new(NULL, "Search Dialog", "search"); - e_dialog_title_set(dialog, _("Searching for Devices...")); - evas_object_event_callback_add(dialog->win, EVAS_CALLBACK_DEL, _ebluez4_cb_search_dialog_del, dialog); - e_dialog_resizable_set(dialog, EINA_TRUE); - - evas = evas_object_evas_get(dialog->win); - - inst->found_list = e_widget_ilist_add(evas, 100, 0, NULL); - - e_dialog_content_set(dialog, inst->found_list, 300, 200); - - e_dialog_show(dialog); - - dialog->data = inst; - inst->search_dialog = dialog; - - ebluez4_start_discovery(); - DBG("Starting discovery..."); -} - -static void -_ebluez4_cb_adap_settings_dialog_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) -{ - E_Dialog *dialog = data; - ebluez4_adapter_settings_del(dialog); -} - -static void -_ebluez4_check_changed(void *data, Evas_Object *obj, const char *prop_name) -{ - Adapter *adap = data; - Eina_Bool value = e_widget_check_checked_get(obj); - ebluez4_adapter_property_set(adap, prop_name, value); -} - -static void -_ebluez4_powered_changed(void *data, Evas_Object *obj, void *info EINA_UNUSED) -{ - _ebluez4_check_changed(data, obj, "Powered"); -} - -static void -_ebluez4_visible_changed(void *data, Evas_Object *obj, void *info EINA_UNUSED) -{ - _ebluez4_check_changed(data, obj, "Discoverable"); -} - -static void -_ebluez4_pairable_changed(void *data, Evas_Object *obj, void *info EINA_UNUSED) -{ - _ebluez4_check_changed(data, obj, "Pairable"); -} - - -static void -_ebluez4_cb_adap_settings(void *data) -{ - Adapter *adap = data; - E_Dialog *dialog; - Evas *evas; - Evas_Object *list; - Evas_Object *ck; - int mw, mh; - Eina_List *ck_list = NULL; - - if (adap->dialog) - ebluez4_adapter_settings_del(adap->dialog); - - dialog = e_dialog_new(NULL, "Adapter Dialog", "adapter"); - e_dialog_title_set(dialog, _("Adapter Settings")); - evas_object_event_callback_add(dialog->win, EVAS_CALLBACK_DEL, _ebluez4_cb_adap_settings_dialog_del, dialog); - e_dialog_resizable_set(dialog, EINA_TRUE); - - evas = evas_object_evas_get(dialog->win); - - list = e_widget_list_add(evas, 0, 0); - - ck = e_widget_check_add(evas, _("Default"), NULL); - e_widget_check_checked_set(ck, adap->is_default); - e_widget_list_object_append(list, ck, 0, 0, 0); - - ck = e_widget_check_add(evas, _("Powered"), &(adap->powered_checked)); - e_widget_check_checked_set(ck, adap->powered); - e_widget_list_object_append(list, ck, 0, 0, 0); - evas_object_smart_callback_add(ck, "changed", _ebluez4_powered_changed, - adap); - ck_list = eina_list_append(ck_list, ck); - - - ck = e_widget_check_add(evas, _("Visible"), &(adap->visible_checked)); - e_widget_check_checked_set(ck, adap->visible); - e_widget_list_object_append(list, ck, 0, 0, 0); - evas_object_smart_callback_add(ck, "changed", - _ebluez4_visible_changed, adap); - ck_list = eina_list_append(ck_list, ck); - - ck = e_widget_check_add(evas, _("Pairable"), &(adap->pairable_checked)); - e_widget_check_checked_set(ck, adap->pairable); - e_widget_list_object_append(list, ck, 0, 0, 0); - evas_object_smart_callback_add(ck, "changed", - _ebluez4_pairable_changed, adap); - ck_list = eina_list_append(ck_list, ck); - - e_dialog_show(dialog); - e_widget_size_min_get(list, &mw, &mh); - if(mw < 150) mw = 150; - e_dialog_content_set(dialog, list, mw, mh); - - dialog->data = adap; - adap->dialog = dialog; - e_object_data_set(E_OBJECT(dialog), ck_list); -} - -static void -_ebluez4_adap_list_dialog_del(Instance *inst) -{ - if (!inst->adapters_dialog) return; - e_object_del(E_OBJECT(inst->adapters_dialog)); - inst->adapters_dialog = NULL; - inst->adap_list = NULL; -} - -static void -_ebluez4_cb_adap_list_dialog_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) -{ - E_Dialog *dialog = data; - _ebluez4_adap_list_dialog_del(dialog->data); -} - -static void -_ebluez4_cb_adap_list(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) -{ - Instance *inst = data; - E_Dialog *dialog; - Evas *evas; - - if (inst->adapters_dialog) - _ebluez4_adap_list_dialog_del(inst); - - dialog = e_dialog_new(NULL, "Adapters Dialog", "adapters"); - e_dialog_title_set(dialog, _("Adapters Available")); - evas_object_event_callback_add(dialog->win, EVAS_CALLBACK_DEL, _ebluez4_cb_adap_list_dialog_del, dialog); - e_dialog_resizable_set(dialog, EINA_TRUE); - - evas = evas_object_evas_get(dialog->win); - - inst->adap_list = e_widget_ilist_add(evas, 0, 0, NULL); - - e_dialog_content_set(dialog, inst->adap_list, 250, 220); - ebluez4_update_instances(ctxt->adapters); - - e_dialog_show(dialog); - - dialog->data = inst; - inst->adapters_dialog = dialog; -} - -static void -_ebluez4_cb_connect(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) -{ - ebluez4_connect_to_device(data); -} - -static void -_ebluez4_cb_disconnect(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) -{ - ebluez4_disconnect_device(data); -} - -static void -_ebluez4_cb_forget(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED) -{ - Device *dev = data; - ebluez4_remove_device(dev->obj); -} - -#ifdef HAVE_BLUETOOTH -static void -_ebluez4_cb_lock(void *data, - E_Menu *m EINA_UNUSED, - E_Menu_Item *mi) -{ - Device *dev = data; - int tog; - - tog = e_menu_item_toggle_get(mi); - eina_stringshare_replace(&ebluez4_config->lock_dev_addr, - tog ? dev->addr : NULL); - e_config_save_queue(); - - if (autolock_exe) - ecore_exe_kill(autolock_exe); - autolock_exe = NULL; - if (!autolock_poller && (ebluez4_config->lock_dev_addr || ebluez4_config->unlock_dev_addr)) - autolock_poller = ecore_poller_add(ECORE_POLLER_CORE, 32, _ebluez_l2ping_poller, NULL); -} - -static void -_ebluez4_cb_unlock(void *data, - E_Menu *m EINA_UNUSED, - E_Menu_Item *mi) -{ - Device *dev = data; - int tog; - - tog = e_menu_item_toggle_get(mi); - eina_stringshare_replace(&ebluez4_config->unlock_dev_addr, - tog ? dev->addr : NULL); - e_config_save_queue(); - - if (autolock_exe) - ecore_exe_kill(autolock_exe); - autolock_exe = NULL; - if (!autolock_poller && (ebluez4_config->lock_dev_addr || ebluez4_config->unlock_dev_addr)) - autolock_poller = ecore_poller_add(ECORE_POLLER_CORE, 32, _ebluez_l2ping_poller, NULL); -} -#endif - -static void -_menu_post_deactivate(void *data EINA_UNUSED, E_Menu *m) -{ - Eina_List *iter; - E_Menu_Item *mi; - Instance *inst = data; - - if (!(m->parent_item) || !(m->parent_item->menu)) - { - e_gadcon_locked_set(inst->gcc->gadcon, 0); - inst->menu = NULL; - } - EINA_LIST_FOREACH(m->items, iter, mi) - if (mi->submenu) e_menu_deactivate(mi->submenu); - e_object_del(E_OBJECT(m)); -} - -static Eina_Bool -_ebluez4_add_devices(Instance *inst) -{ - Device *dev; - Eina_List *iter; - E_Menu *m, *subm; - E_Menu_Item *mi, *submi; - Eina_Bool ret = EINA_FALSE; - - m = inst->menu; - - EINA_LIST_FOREACH(ctxt->devices, iter, dev) - if (dev->paired) - { - mi = e_menu_item_new(m); - e_menu_item_label_set(mi, _("Paired Devices")); - e_menu_item_disabled_set(mi, EINA_TRUE); - ret = EINA_TRUE; - break; - } - - EINA_LIST_FOREACH(ctxt->devices, iter, dev) - if (dev->paired) - { -#ifdef HAVE_BLUETOOTH - Eina_Bool chk; -#endif - - mi = e_menu_item_new(m); - e_menu_item_label_set(mi, dev->name); - e_menu_item_check_set(mi, 1); - subm = e_menu_new(); - e_menu_post_deactivate_callback_set(subm, _menu_post_deactivate, - inst); - e_menu_item_submenu_set(mi, subm); - submi = e_menu_item_new(subm); - if (dev->connected) - { - e_menu_item_toggle_set(mi, 1); - e_menu_item_label_set(submi, _("Disconnect")); - e_menu_item_callback_set(submi, _ebluez4_cb_disconnect, dev); - } - else - { - e_menu_item_toggle_set(mi, 0); - e_menu_item_label_set(submi, _("Connect")); - e_menu_item_callback_set(submi, _ebluez4_cb_connect, dev); - } - submi = e_menu_item_new(subm); - e_menu_item_label_set(submi, _("Forget")); - e_menu_item_callback_set(submi, _ebluez4_cb_forget, dev); - -#ifdef HAVE_BLUETOOTH - if (autolock_initted) - { - /* Auto lock when away */ - submi = e_menu_item_new(subm); - e_menu_item_check_set(submi, 1); - e_menu_item_label_set(submi, _("Lock on disconnect")); - e_menu_item_callback_set(submi, _ebluez4_cb_lock, dev); - chk = ebluez4_config->lock_dev_addr && dev->addr && - !strcmp(dev->addr, ebluez4_config->lock_dev_addr); - e_menu_item_toggle_set(submi, !!chk); - - submi = e_menu_item_new(subm); - e_menu_item_check_set(submi, 1); - e_menu_item_label_set(submi, _("Unlock on disconnect")); - e_menu_item_callback_set(submi, _ebluez4_cb_unlock, dev); - chk = ebluez4_config->unlock_dev_addr && dev->addr && - !strcmp(dev->addr, ebluez4_config->unlock_dev_addr); - e_menu_item_toggle_set(submi, !!chk); - } -#endif - } - - return ret; -} - -static void -_ebluez4_menu_new(Instance *inst) -{ - E_Menu *m; - E_Menu_Item *mi; - - m = e_menu_new(); - e_menu_post_deactivate_callback_set(m, _menu_post_deactivate, inst); - e_menu_title_set(m, _("Bluez4")); - inst->menu = m; - - if (_ebluez4_add_devices(inst)) - { - mi = e_menu_item_new(m); - e_menu_item_separator_set(mi, 1); - } - - mi = e_menu_item_new(m); - e_menu_item_label_set(mi, _("Search New Devices")); - e_menu_item_callback_set(mi, _ebluez4_cb_search, inst); - - mi = e_menu_item_new(m); - e_menu_item_label_set(mi, _("Adapter Settings")); - e_menu_item_callback_set(mi, _ebluez4_cb_adap_list, inst); -} - -static void -_ebluez4_cb_mouse_down(void *data, Evas *evas EINA_UNUSED, - Evas_Object *obj EINA_UNUSED, void *event) -{ - Instance *inst = NULL; - Evas_Event_Mouse_Down *ev = event; - int x, y; - - if (!(inst = data)) return; - if (ev->button != 1) return; - if (!ctxt->adap_obj) return; - - _ebluez4_menu_new(inst); - - e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &x, &y, NULL, NULL); - e_menu_activate_mouse(inst->menu, - e_zone_current_get(), - x + ev->output.x, y + ev->output.y, 1, 1, - E_MENU_POP_DIRECTION_AUTO, ev->timestamp); - evas_event_feed_mouse_up(inst->gcc->gadcon->evas, ev->button, - EVAS_BUTTON_NONE, ev->timestamp, NULL); - - e_gadcon_locked_set(inst->gcc->gadcon, 1); -} - -static void -_ebluez4_set_mod_icon(Evas_Object *base) -{ - char edj_path[4096]; - char *group; - - snprintf(edj_path, sizeof(edj_path), "%s/e-module-bluez4.edj", mod->dir); - if (ctxt->adap_obj) - group = "e/modules/bluez4/main"; - else - group = "e/modules/bluez4/inactive"; - - if (!e_theme_edje_object_set(base, "base/theme/modules/bluez4", group)) - edje_object_file_set(base, edj_path, group); -} - -/* Gadcon */ -static E_Gadcon_Client * -_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style) -{ - Instance *inst = NULL; - - inst = E_NEW(Instance, 1); - - inst->o_bluez4 = edje_object_add(gc->evas); - _ebluez4_set_mod_icon(inst->o_bluez4); - - inst->gcc = e_gadcon_client_new(gc, name, id, style, inst->o_bluez4); - inst->gcc->data = inst; - - e_gadcon_client_util_menu_attach(inst->gcc); - evas_object_event_callback_add(inst->o_bluez4, EVAS_CALLBACK_MOUSE_DOWN, - _ebluez4_cb_mouse_down, inst); - - instances = eina_list_append(instances, inst); - - return inst->gcc; -} - -static void -_gc_shutdown(E_Gadcon_Client *gcc) -{ - Instance *inst = NULL; - - if (!(inst = gcc->data)) return; - instances = eina_list_remove(instances, inst); - - if (inst->o_bluez4) - { - evas_object_event_callback_del(inst->o_bluez4, EVAS_CALLBACK_MOUSE_DOWN, - _ebluez4_cb_mouse_down); - evas_object_del(inst->o_bluez4); - } - - if (inst->menu) e_menu_deactivate(inst->menu); - _ebluez4_search_dialog_del(inst); - _ebluez4_adap_list_dialog_del(inst); - - E_FREE(inst); -} - -static const char * -_gc_id_new(const E_Gadcon_Client_Class *client_class EINA_UNUSED) -{ - snprintf(tmpbuf, sizeof(tmpbuf), "bluez4.%d", eina_list_count(instances)); - return tmpbuf; -} - -static void -_gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient EINA_UNUSED) -{ - e_gadcon_client_aspect_set(gcc, 16, 16); - e_gadcon_client_min_size_set(gcc, 16, 16); -} - -static const char * -_gc_label(const E_Gadcon_Client_Class *client_class EINA_UNUSED) -{ - return _("Bluez4"); -} - -static Evas_Object * -_gc_icon(const E_Gadcon_Client_Class *client_class EINA_UNUSED, Evas *evas) -{ - Evas_Object *o = NULL; - char buf[4096]; - - snprintf(buf, sizeof(buf), "%s/e-module-bluez4.edj", mod->dir); - - o = edje_object_add(evas); - - edje_object_file_set(o, buf, "icon"); - - return o; -} - -static const E_Gadcon_Client_Class _gc_class = -{ - GADCON_CLIENT_CLASS_VERSION, "bluez4", - {_gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, - _gc_id_new, NULL, NULL}, - E_GADCON_CLIENT_STYLE_PLAIN -}; - -static Eina_Bool -_ebluez_exe_die(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event_info) -{ - Ecore_Exe_Event_Del *ev = event_info; - - if (ev->exe != autolock_exe) - return ECORE_CALLBACK_PASS_ON; - - if (!autolock_initted) - { - if (ev->exit_code == 0) - { - autolock_initted = EINA_TRUE; - } - } - else - { - if (e_desklock_state_get()) // Locked state ? - { - if (!autolock_waiting) - { - // Not waiting yet for the auto unlock device to appear before unlock - if (ev->exit_code == 0 && ebluez4_config->unlock_dev_addr) - { - e_desklock_hide(); - } - } - else if (ev->exit_code == 1) - { - // The device just disapeared, now we can wait for it to disapear - autolock_waiting = EINA_FALSE; - } - } - else - { - if (!autolock_waiting) - { - // Not waiting yet for the auto lock device to disappear before locking - if (ev->exit_code == 1 && ebluez4_config->lock_dev_addr) - { - e_desklock_show(EINA_FALSE); - } - } - else if (ev->exit_code == 0) - { - // The device just appeared, now we can wait for it to disapear - autolock_waiting = EINA_FALSE; - } - } - } - - if (autolock_initted) - autolock_poller = ecore_poller_add(ECORE_POLLER_CORE, 32, _ebluez_l2ping_poller, NULL); - - autolock_exe = NULL; - - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_ebluez_exe_out(void *data EINA_UNUSED, int ev_type EINA_UNUSED, - void *ev EINA_UNUSED) -{ - /* FIXME: Need experiment, but we should be able to use latency to somehow estimate distance, right ? */ - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_ebluez_desklock(void *data EINA_UNUSED, int ev_type EINA_UNUSED, - void *ev EINA_UNUSED) -{ - if (autolock_exe) - ecore_exe_kill(autolock_exe); - autolock_exe = NULL; - - if (!autolock_poller && autolock_initted && (ebluez4_config->lock_dev_addr || ebluez4_config->unlock_dev_addr)) - autolock_poller = ecore_poller_add(ECORE_POLLER_CORE, 32, _ebluez_l2ping_poller, NULL); - - autolock_waiting = EINA_TRUE; - - return ECORE_CALLBACK_PASS_ON; -} - -/* Module Functions */ -E_API void * -e_modapi_init(E_Module *m) -{ - Eina_Strbuf *buf; - - mod = m; - - conf_edd = E_CONFIG_DD_NEW("Config", Config); -#undef T -#undef D -#define T Config -#define D conf_edd - E_CONFIG_VAL(D, T, lock_dev_addr, STR); - E_CONFIG_VAL(D, T, unlock_dev_addr, STR); - - ebluez4_config = e_config_domain_load("module.ebluez4", conf_edd); - if (!ebluez4_config) - ebluez4_config = E_NEW(Config, 1); - - ebluez4_eldbus_init(); - - e_gadcon_provider_register(&_gc_class); - - autolock_die = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _ebluez_exe_die, NULL); - autolock_out = ecore_event_handler_add(ECORE_EXE_EVENT_DATA, _ebluez_exe_out, NULL); - autolock_desklock = ecore_event_handler_add(E_EVENT_DESKLOCK, _ebluez_desklock, NULL); - - buf = eina_strbuf_new(); - eina_strbuf_append_printf(buf, "%s/enlightenment/utils/enlightenment_sys -t l2ping", - e_prefix_lib_get()); - autolock_exe = ecore_exe_run(eina_strbuf_string_get(buf), NULL); - eina_strbuf_free(buf); - - return m; -} - -E_API int -e_modapi_shutdown(E_Module *m EINA_UNUSED) -{ - E_CONFIG_DD_FREE(conf_edd); - - if (autolock_exe) ecore_exe_kill(autolock_exe); - autolock_exe = NULL; - E_FREE_FUNC(autolock_poller, ecore_poller_del); - - ecore_event_handler_del(autolock_die); - ecore_event_handler_del(autolock_out); - ecore_event_handler_del(autolock_desklock); - - eina_stringshare_del(ebluez4_config->lock_dev_addr); - eina_stringshare_del(ebluez4_config->unlock_dev_addr); - free(ebluez4_config); - ebluez4_config = NULL; - - ebluez4_eldbus_shutdown(); - e_gadcon_provider_unregister(&_gc_class); - return 1; -} - -E_API int -e_modapi_save(E_Module *m EINA_UNUSED) -{ - e_config_domain_save("module.ebluez4", - conf_edd, ebluez4_config); - return 1; -} - -/* Public Functions */ -void -ebluez4_update_inst(Evas_Object *dest, Eina_List *src, Instance *inst) -{ - Device *dev; - Evas_Object *o_type; - Adapter *adap; - Eina_List *iter; - - e_widget_ilist_freeze(dest); - e_widget_ilist_clear(dest); - - if (src == ctxt->found_devices) - { - EINA_LIST_FOREACH(src, iter, dev) - if (!dev->paired) - { - o_type = e_widget_label_add(evas_object_evas_get(dest), - dev->type); - e_widget_ilist_append_full(dest, NULL, o_type, dev->name, - _ebluez4_cb_pair, inst, dev->addr); - - } - } - else if (src == ctxt->adapters) - { - EINA_LIST_FOREACH(src, iter, adap) - e_widget_ilist_append(dest, NULL, adap->name, - _ebluez4_cb_adap_settings, adap, NULL); - } - - e_widget_ilist_go(dest); - e_widget_ilist_thaw(dest); -} - -void -ebluez4_update_instances(Eina_List *src) -{ - Eina_List *iter; - Instance *inst; - - EINA_LIST_FOREACH(instances, iter, inst) - if (src == ctxt->found_devices && inst->found_list) - ebluez4_update_inst(inst->found_list, src, inst); - else if (src == ctxt->adapters && inst->adap_list) - ebluez4_update_inst(inst->adap_list, src, inst); -} - -void -ebluez4_update_all_gadgets_visibility(void) -{ - Eina_List *iter; - Instance *inst; - - if (ctxt->adap_obj) - EINA_LIST_FOREACH(instances, iter, inst) - _ebluez4_set_mod_icon(inst->o_bluez4); - else - EINA_LIST_FOREACH(instances, iter, inst) - { - _ebluez4_set_mod_icon(inst->o_bluez4); - if (inst->menu) e_menu_deactivate(inst->menu); - _ebluez4_search_dialog_del(inst); - _ebluez4_adap_list_dialog_del(inst); - } -} - -void -ebluez4_show_error(const char *err_name, const char *err_msg) -{ - snprintf(tmpbuf, sizeof(tmpbuf), "%s: %s.", err_name, err_msg); - e_util_dialog_internal(_("An error has ocurred"), tmpbuf); -} - -void -ebluez4_adapter_settings_del(E_Dialog *dialog) -{ - Adapter *adap; - Eina_List *ck_list; - - if (!dialog) return; - adap = dialog->data; - ck_list = e_object_data_get(E_OBJECT(dialog)); - eina_list_free(ck_list); - e_object_del(E_OBJECT(dialog)); - adap->dialog = NULL; -} - -void -ebluez4_adapter_properties_update(void *data) -{ - Eina_List *ck_list; - Evas_Object *ck; - Adapter *adap = data; - - if (!adap->dialog) return; - ck_list = e_object_data_get(E_OBJECT(adap->dialog)); - ck = eina_list_nth(ck_list, 0); - e_widget_check_checked_set(ck, adap->powered); - ck = eina_list_nth(ck_list, 1); - e_widget_check_checked_set(ck, adap->visible); - ck = eina_list_nth(ck_list, 2); - e_widget_check_checked_set(ck, adap->pairable); -} diff --git a/src/modules/bluez4/e_mod_main.h b/src/modules/bluez4/e_mod_main.h deleted file mode 100644 index af7a9bf8e..000000000 --- a/src/modules/bluez4/e_mod_main.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef E_MOD_MAIN_H -#define E_MOD_MAIN_H - -typedef struct _Instance Instance; -struct _Instance -{ - E_Gadcon_Client *gcc; - E_Menu *menu; - Evas_Object *o_bluez4; - Evas_Object *found_list; - E_Dialog *search_dialog; - Evas_Object *adap_list; - E_Dialog *adapters_dialog; -}; - -typedef struct _Config Config; -struct _Config -{ - const char *lock_dev_addr; - const char *unlock_dev_addr; -}; - -extern Config *ebluez4_config; - -E_API extern E_Module_Api e_modapi; - -E_API void *e_modapi_init(E_Module *m); -E_API int e_modapi_shutdown(E_Module *m); -E_API int e_modapi_save(E_Module *m); - -void ebluez4_update_inst(Evas_Object *dest, Eina_List *src, Instance *inst); -void ebluez4_update_instances(Eina_List *src); -void ebluez4_update_all_gadgets_visibility(void); -void ebluez4_show_error(const char *err_name, const char *err_msg); -void ebluez4_adapter_settings_del(E_Dialog *dialog); -void ebluez4_adapter_properties_update(void *data); - -#endif diff --git a/src/modules/bluez4/ebluez4.c b/src/modules/bluez4/ebluez4.c deleted file mode 100644 index 9b8252dba..000000000 --- a/src/modules/bluez4/ebluez4.c +++ /dev/null @@ -1,843 +0,0 @@ -#include -#include "e.h" -#include "agent.h" -#include "e_mod_main.h" -#include "ebluez4.h" - -Context *ctxt = NULL; - -typedef struct _Pair_Cb -{ - void (*cb)(void *, Eina_Bool, const char *); - void *data; -} Pair_Cb; - -Service services[] = { - { HumanInterfaceDevice_UUID, INPUT }, - { AudioSource_UUID, AUDIO_SOURCE }, - { AudioSink_UUID, AUDIO_SINK }, - { NULL, NONE } -}; - -static int -_dev_addr_cmp(const void *d1, const void *d2) -{ - const Device *dev = d1; - const char *addr = d2; - - return strcmp(dev->addr, addr); -} - -int -_adap_path_cmp(const void *d1, const void *d2) -{ - const Adapter *adap = d1; - const char *path = d2; - - return strcmp(eldbus_object_path_get(adap->obj), path); -} - -static struct icon_type -{ - const char *icon; - const char *type; -} icon_type_table[] = { - { "audio-card", "Audio" }, - { "camera-photo", "Photo Camera" }, - { "camera-video", "Video Camera" }, - { "computer", "Computer" }, - { "input-gaming", "Game Controller" }, - { "input-keyboard", "Keyboard" }, - { "input-mouse", "Mouse" }, - { "input-tablet", "Tablet" }, - { "modem", "Modem" }, - { "network-wireless", "Wireless" }, - { "phone", "Phone" }, - { "printer", "Printer" }, - { NULL, NULL } -}; - -static const char * -_icon_to_type(const char *icon) -{ - struct icon_type *it; - - for (it = &icon_type_table[0]; it && it->icon; it++) - { - if (strcmp(icon, it->icon)) - return it->type; - } - return NULL; -} - -static void -_free_dev(Device *dev) -{ - if (dev->proxy.input) eldbus_proxy_unref(dev->proxy.input); - if (dev->proxy.audio_source) eldbus_proxy_unref(dev->proxy.audio_source); - if (dev->proxy.audio_sink) eldbus_proxy_unref(dev->proxy.audio_sink); - - if (dev->obj) - eldbus_object_unref(dev->obj); - eina_stringshare_del(dev->addr); - dev->addr = NULL; - eina_stringshare_del(dev->name); - dev->name = NULL; - free(dev); -} - -static void -_free_adap(Adapter *adap) -{ - eldbus_proxy_unref(adap->proxy); - eldbus_object_unref(adap->obj); - eina_stringshare_del(adap->name); - adap->name = NULL; - ebluez4_adapter_settings_del(adap->dialog); - free(adap); -} - -static void -_free_dev_list(Eina_List **list) -{ - Device *dev; - - EINA_LIST_FREE(*list, dev) - _free_dev(dev); - *list = NULL; -} - -static void -_free_adap_list(void) -{ - Adapter *adap; - - EINA_LIST_FREE(ctxt->adapters, adap) - _free_adap(adap); - ctxt->adapters = NULL; -} - -static Profile -_uuid_to_profile(const char *uuid) -{ - Service *service; - - for (service = (Service *)services; service && service->uuid; service++) - if (!strcmp(service->uuid, uuid)) - return service->profile; - return NONE; -} - -static void -_set_dev_services(Device *dev, Eldbus_Message_Iter *uuids) -{ - const char *uuid; - - while (eldbus_message_iter_get_and_next(uuids, 's', &uuid)) - switch (_uuid_to_profile(uuid)) - { - case INPUT: - if (!dev->proxy.input) - dev->proxy.input = eldbus_proxy_get(dev->obj, INPUT_INTERFACE); - break; - case AUDIO_SOURCE: - if (!dev->proxy.audio_source) - dev->proxy.audio_source = eldbus_proxy_get(dev->obj, - AUDIO_SOURCE_INTERFACE); - break; - case AUDIO_SINK: - if (!dev->proxy.audio_sink) - dev->proxy.audio_sink = eldbus_proxy_get(dev->obj, - AUDIO_SINK_INTERFACE); - break; - default: - break; - } -} - -static void -_retrieve_properties(Eldbus_Message_Iter *dict, const char **addr, - const char **name, const char **icon, Eina_Bool *paired, - Eina_Bool *connected, Eldbus_Message_Iter **uuids) -{ - Eldbus_Message_Iter *entry, *variant; - const char *key; - - *icon = NULL; - - while (eldbus_message_iter_get_and_next(dict, 'e', &entry)) - { - if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &variant)) - return; - - if (!strcmp(key, "Address")) - { - if (!eldbus_message_iter_arguments_get(variant, "s", addr)) - return; - } - else if (!strcmp(key, "Name")) - { - if (!eldbus_message_iter_arguments_get(variant, "s", name)) - return; - } - else if (!strcmp(key, "Icon")) - { - if (!eldbus_message_iter_arguments_get(variant, "s", icon)) - return; - } - else if (!strcmp(key, "Paired")) - { - if (!eldbus_message_iter_arguments_get(variant, "b", paired)) - return; - } - else if (!strcmp(key, "Connected")) - { - if (!eldbus_message_iter_arguments_get(variant, "b", connected)) - return; - } - else if (!strcmp(key, "UUIDs")) - { - if (!eldbus_message_iter_arguments_get(variant, "as", uuids)) - return; - } - } -} - -static void -_on_dev_property_changed(void *context, const Eldbus_Message *msg) -{ - const char *key, *name, *icon; - char err_msg[4096]; - Eina_Bool paired, connected; - Eldbus_Message_Iter *variant, *uuids; - Device *dev = context; - Device *found_dev = eina_list_search_unsorted(ctxt->found_devices, - _dev_addr_cmp, dev->addr); - - if (!eldbus_message_arguments_get(msg, "sv", &key, &variant)) - { - snprintf(err_msg, sizeof(err_msg), - _("Property of %s changed, but could not be read"), - dev->name); - ERR("%s", err_msg); - ebluez4_show_error(_("Bluez Error"), err_msg); - return; - } - - if (!strcmp(key, "Name")) - { - if (!eldbus_message_iter_arguments_get(variant, "s", &name)) - return; - DBG("'%s' property of %s changed to %s", key, dev->name, name); - eina_stringshare_replace(&dev->name, name); - - if (found_dev) - { - eina_stringshare_replace(&found_dev->name, name); - ebluez4_update_instances(ctxt->found_devices); - } - } - else if (!strcmp(key, "Icon")) - { - if (!eldbus_message_iter_arguments_get(variant, "s", &icon)) - return; - if (!found_dev) return; - DBG("'%s' property of %s changed to %s", key, found_dev->name, icon); - found_dev->type = _icon_to_type(icon); - ebluez4_update_instances(ctxt->found_devices); - } - else if (!strcmp(key, "Paired")) - { - if (!eldbus_message_iter_arguments_get(variant, "b", &paired)) - return; - DBG("'%s' property of %s changed to %d", key, dev->name, paired); - dev->paired = paired; - - if (found_dev) - { - found_dev->paired = paired; - ebluez4_update_instances(ctxt->found_devices); - } - } - else if (!strcmp(key, "Connected")) - { - if (!eldbus_message_iter_arguments_get(variant, "b", &connected)) - return; - DBG("'%s' property of %s changed to %d", key, dev->name, connected); - dev->connected = connected; - } - else if (!strcmp(key, "UUIDs")) - { - if (!eldbus_message_iter_arguments_get(variant, "as", &uuids)) - return; - _set_dev_services(dev, uuids); - } -} - -static void -_on_connected(void *data EINA_UNUSED, const Eldbus_Message *msg, - Eldbus_Pending *pending EINA_UNUSED) -{ - const char *err_name, *err_msg; - - if (eldbus_message_error_get(msg, &err_name, &err_msg)) - { - ERR("%s: %s", err_name, err_msg); - ebluez4_show_error(err_name, err_msg); - return; - } -} - -static void -_try_to_connect(Eldbus_Proxy *proxy) -{ - if (proxy) - eldbus_proxy_call(proxy, "Connect", _on_connected, NULL, -1, ""); -} - -static void -_on_disconnected(void *data EINA_UNUSED, const Eldbus_Message *msg, - Eldbus_Pending *pending EINA_UNUSED) -{ - const char *err_name, *err_msg; - - if (eldbus_message_error_get(msg, &err_name, &err_msg)) - { - ERR("%s: %s", err_name, err_msg); - ebluez4_show_error(err_name, err_msg); - return; - } -} - -static void -_try_to_disconnect(Eldbus_Proxy *proxy) -{ - if (proxy) - eldbus_proxy_call(proxy, "Disconnect", _on_disconnected, NULL, -1, ""); -} - -static void -_on_paired(void *data, const Eldbus_Message *msg, - Eldbus_Pending *pending EINA_UNUSED) -{ - const char *err_name, *err_msg; - Pair_Cb *d = data; - Eina_Bool success = EINA_TRUE; - - if (eldbus_message_error_get(msg, &err_name, &err_msg)) - { - ERR("%s: %s", err_name, err_msg); - success = EINA_FALSE; - } - if (d->cb) d->cb(d->data, success, err_msg); - free(d); -} - -static void -_on_dev_properties(void *data, const Eldbus_Message *msg, - Eldbus_Pending *pending EINA_UNUSED) -{ - Eldbus_Message_Iter *dict, *uuids; - const char *addr, *name, *icon; - Eina_Bool paired; - Eina_Bool connected; - Device *dev = data; - - if (!eldbus_message_arguments_get(msg, "a{sv}", &dict)) - return; - - _retrieve_properties(dict, &addr, &name, &icon, &paired, &connected, &uuids); - - dev->addr = eina_stringshare_add(addr); - dev->name = eina_stringshare_add(name); - dev->paired = paired; - dev->connected = connected; - _set_dev_services(dev, uuids); -} - -static void -_unset_dev(Device *dev, Eina_List **list) -{ - if (!dev || !list) - return; - - *list = eina_list_remove(*list, dev); - _free_dev(dev); -} - -static void -_set_dev(const char *path) -{ - Device *dev = calloc(1, sizeof(Device)); - - dev->obj = eldbus_object_get(ctxt->conn, BLUEZ_BUS, path); - dev->proxy.dev = eldbus_proxy_get(dev->obj, DEVICE_INTERFACE); - eldbus_proxy_call(dev->proxy.dev, "GetProperties", _on_dev_properties, dev, - -1, ""); - eldbus_proxy_signal_handler_add(dev->proxy.dev, "PropertyChanged", - _on_dev_property_changed, dev); - ctxt->devices = eina_list_append(ctxt->devices, dev); -} - -static void -_on_removed(void *context EINA_UNUSED, const Eldbus_Message *msg) -{ - const char *path; - Device *dev, *fdev; - - if (!eldbus_message_arguments_get(msg, "o", &path)) - return; - - dev = eina_list_search_unsorted(ctxt->devices, ebluez4_dev_path_cmp, path); - fdev = eina_list_search_unsorted(ctxt->found_devices, _dev_addr_cmp, - dev->addr); - - _unset_dev(dev, &ctxt->devices); - _unset_dev(fdev, &ctxt->found_devices); -} - -static void -_on_created(void *context EINA_UNUSED, const Eldbus_Message *msg) -{ - const char *path; - - if (!eldbus_message_arguments_get(msg, "o", &path)) - return; - - _set_dev(path); -} - -static void -_on_device_found(void *context EINA_UNUSED, const Eldbus_Message *msg) -{ - Eldbus_Message_Iter *dict, *uuids; - const char *addr, *name, *icon; - Eina_Bool paired, connected; - Device *dev; - - if (!eldbus_message_arguments_get(msg, "sa{sv}", &addr, &dict)) - return; - - if (eina_list_search_unsorted(ctxt->found_devices, _dev_addr_cmp, addr)) - return; - - _retrieve_properties(dict, &addr, &name, &icon, &paired, &connected, &uuids); - - dev = calloc(1, sizeof(Device)); - dev->addr = eina_stringshare_add(addr); - dev->name = eina_stringshare_add(name); - if (icon) dev->type = _icon_to_type(icon); - dev->paired = paired; - ctxt->found_devices = eina_list_append(ctxt->found_devices, dev); - - ebluez4_update_instances(ctxt->found_devices); -} - -static void -_on_list_devices(void *data EINA_UNUSED, const Eldbus_Message *msg, - Eldbus_Pending *pending EINA_UNUSED) -{ - Eldbus_Message_Iter *array; - const char *path; - const char *err_msg = _("Error reading list of devices"); - - if (!eldbus_message_arguments_get(msg, "ao", &array)) - { - ERR("%s", err_msg); - ebluez4_show_error(_("Bluez Error"), err_msg); - return; - } - - while (eldbus_message_iter_get_and_next(array, 'o', &path)) - _set_dev(path); -} - -static void -_on_adap_property_changed(void *context, const Eldbus_Message *msg) -{ - const char *key, *name; - char err_msg[1096]; - Eina_Bool visible, pairable, powered; - Eldbus_Message_Iter *variant; - Adapter *adap = context; - - if (!eldbus_message_arguments_get(msg, "sv", &key, &variant)) - { - snprintf(err_msg, sizeof(err_msg), - _("Property of %s changed, but could not be read"), adap->name); - ERR("%s", err_msg); - ebluez4_show_error(_("Bluez Error"), err_msg); - return; - } - - if (!strcmp(key, "Name")) - { - if (!eldbus_message_iter_arguments_get(variant, "s", &name)) - return; - DBG("'%s' property of %s changed to %s", key, adap->name, name); - eina_stringshare_del(adap->name); - adap->name = eina_stringshare_add(name); - ebluez4_update_instances(ctxt->adapters); - return; - } - else if (!strcmp(key, "Discoverable")) - { - if (!eldbus_message_iter_arguments_get(variant, "b", &visible)) - return; - DBG("'%s' property of %s changed to %d", key, adap->name, visible); - adap->visible = visible; - } - else if (!strcmp(key, "Pairable")) - { - if (!eldbus_message_iter_arguments_get(variant, "b", &pairable)) - return; - DBG("'%s' property of %s changed to %d", key, adap->name, pairable); - adap->pairable = pairable; - } - else if (!strcmp(key, "Powered")) - { - if (!eldbus_message_iter_arguments_get(variant, "b", &powered)) - return; - DBG("'%s' property of %s changed to %d", key, adap->name, powered); - adap->powered = powered; - } - - ebluez4_adapter_properties_update(adap); -} - -static void -_on_adap_properties(void *data, const Eldbus_Message *msg, - Eldbus_Pending *pending EINA_UNUSED) -{ - Eldbus_Message_Iter *dict, *entry, *variant; - const char *name, *key; - Eina_Bool visible, pairable, powered; - Adapter *adap = data; - - if (!eldbus_message_arguments_get(msg, "a{sv}", &dict)) - return; - - while (eldbus_message_iter_get_and_next(dict, 'e', &entry)) - { - if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &variant)) - return; - - else if (!strcmp(key, "Name")) - { - if (!eldbus_message_iter_arguments_get(variant, "s", &name)) - return; - } - else if (!strcmp(key, "Discoverable")) - { - if (!eldbus_message_iter_arguments_get(variant, "b", &visible)) - return; - } - else if (!strcmp(key, "Pairable")) - { - if (!eldbus_message_iter_arguments_get(variant, "b", &pairable)) - return; - } - else if (!strcmp(key, "Powered")) - { - if (!eldbus_message_iter_arguments_get(variant, "b", &powered)) - return; - } - } - - adap->name = eina_stringshare_add(name); - adap->visible = visible; - adap->pairable = pairable; - adap->powered = powered; - ebluez4_update_instances(ctxt->adapters); -} - -static void -_unset_default_adapter(void) -{ - DBG("Remove default adapter %s", eldbus_object_path_get(ctxt->adap_obj)); - _free_dev_list(&ctxt->devices); - ctxt->devices = NULL; - _free_dev_list(&ctxt->found_devices); - ctxt->found_devices = NULL; - eldbus_object_unref(ctxt->adap_obj); - ctxt->adap_obj = NULL; - ebluez4_update_all_gadgets_visibility(); -} - -static void -_unset_adapter(const char *path) -{ - Adapter *adap = eina_list_search_unsorted(ctxt->adapters, _adap_path_cmp, - path); - - if (!adap) - return; - - if (!strcmp(eldbus_object_path_get(ctxt->adap_obj), path)) - _unset_default_adapter(); - ctxt->adapters = eina_list_remove(ctxt->adapters, adap); - _free_adap(adap); - ebluez4_update_instances(ctxt->adapters); -} - -static void -_set_adapter(const char *path) -{ - Adapter *adap = calloc(1, sizeof(Adapter)); - - adap->obj = eldbus_object_get(ctxt->conn, BLUEZ_BUS, path); - if (ctxt->adap_obj && adap->obj == ctxt->adap_obj) - adap->is_default = EINA_TRUE; - else - adap->is_default = EINA_FALSE; - adap->proxy = eldbus_proxy_get(adap->obj, ADAPTER_INTERFACE); - eldbus_proxy_call(adap->proxy, "GetProperties", _on_adap_properties, adap, -1, - ""); - eldbus_proxy_signal_handler_add(adap->proxy, "PropertyChanged", - _on_adap_property_changed, adap); - ctxt->adapters = eina_list_append(ctxt->adapters, adap); -} - -static void -_on_list_adapters(void *data EINA_UNUSED, const Eldbus_Message *msg, - Eldbus_Pending *pending EINA_UNUSED) -{ - Eldbus_Message_Iter *array; - const char *path; - const char *err_msg = _("Error reading list of adapters"); - - if (!eldbus_message_arguments_get(msg, "ao", &array)) - { - ERR("%s", err_msg); - ebluez4_show_error(_("Bluez Error"), err_msg); - return; - } - - while (eldbus_message_iter_get_and_next(array, 'o', &path)) - _set_adapter(path); -} - -static void -_set_default_adapter(const Eldbus_Message *msg) -{ - Adapter *adap; - const char *adap_path; - const char *err_msg = _("Error reading path of Default Adapter"); - - if (!eldbus_message_arguments_get(msg, "o", &adap_path)) - { - ERR("%s", err_msg); - ebluez4_show_error(_("Bluez Error"), err_msg); - return; - } - - DBG("Setting default adapter to %s", adap_path); - - if (ctxt->adap_obj) - _unset_default_adapter(); - - adap = eina_list_search_unsorted(ctxt->adapters, _adap_path_cmp, adap_path); - if (adap) - adap->is_default = EINA_TRUE; - - ctxt->adap_obj = eldbus_object_get(ctxt->conn, BLUEZ_BUS, adap_path); - ctxt->adap_proxy = eldbus_proxy_get(ctxt->adap_obj, ADAPTER_INTERFACE); - - eldbus_proxy_signal_handler_add(ctxt->adap_proxy, "DeviceFound", - _on_device_found, NULL); - eldbus_proxy_signal_handler_add(ctxt->adap_proxy, "DeviceCreated", - _on_created, NULL); - eldbus_proxy_signal_handler_add(ctxt->adap_proxy, "DeviceRemoved", - _on_removed, NULL); - eldbus_proxy_call(ctxt->adap_proxy, "ListDevices", _on_list_devices, NULL, -1, - ""); - eldbus_proxy_call(ctxt->adap_proxy, "RegisterAgent", NULL, NULL, -1, "os", - REMOTE_AGENT_PATH, "KeyboardDisplay"); - ebluez4_update_all_gadgets_visibility(); -} - -static void -_default_adapter_get(void *data EINA_UNUSED, const Eldbus_Message *msg, - Eldbus_Pending *pending EINA_UNUSED) -{ - const char *err_name, *err_msg; - - /* - * If bluetoothd is starting up, we can fail here and wait for the - * DefaultAdapterChanged signal later - */ - if (eldbus_message_error_get(msg, &err_name, &err_msg)) - return; - - if (!ctxt->adap_obj) - _set_default_adapter(msg); -} - -static void -_on_default_adapter_changed(void *context EINA_UNUSED, const Eldbus_Message *msg) -{ - _set_default_adapter(msg); -} - -static void -_on_adapter_removed(void *context EINA_UNUSED, const Eldbus_Message *msg) -{ - const char *adap_path; - const char *err_msg = _("Error reading path of Removed Adapter"); - - if (!eldbus_message_arguments_get(msg, "o", &adap_path)) - { - ERR("%s", err_msg); - ebluez4_show_error(_("Bluez Error"), err_msg); - return; - } - - _unset_adapter(adap_path); -} - -static void -_on_adapter_added(void *context EINA_UNUSED, const Eldbus_Message *msg) -{ - const char *adap_path; - const char *err_msg = _("Error reading path of Added Adapter"); - - if (!eldbus_message_arguments_get(msg, "o", &adap_path)) - { - ERR("%s", err_msg); - ebluez4_show_error(_("Bluez Error"), err_msg); - return; - } - - _set_adapter(adap_path); -} - -static void -_bluez_monitor(void *data EINA_UNUSED, const char *bus EINA_UNUSED, - const char *old_id, const char *new_id) -{ - if (!strcmp(old_id,"") && strcmp(new_id,"")) - { - // Bluez up - eldbus_proxy_call(ctxt->man_proxy, "DefaultAdapter", - _default_adapter_get, NULL, -1, ""); - eldbus_proxy_call(ctxt->man_proxy, "ListAdapters", - _on_list_adapters, NULL, -1, ""); - } - else if (strcmp(old_id,"") && !strcmp(new_id,"")) - { - // Bluez down - _unset_default_adapter(); - _free_adap_list(); - } -} - -/* Public Functions */ -void -ebluez4_eldbus_init(void) -{ - Eldbus_Object *obj; - - ctxt = calloc(1, sizeof(Context)); - - ctxt->conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM); - obj = eldbus_object_get(ctxt->conn, BLUEZ_BUS, MANAGER_PATH); - ctxt->man_proxy = eldbus_proxy_get(obj, MANAGER_INTERFACE); - - ebluez4_register_agent_interfaces(ctxt->conn); - - eldbus_proxy_signal_handler_add(ctxt->man_proxy, "DefaultAdapterChanged", - _on_default_adapter_changed, NULL); - eldbus_proxy_signal_handler_add(ctxt->man_proxy, "AdapterRemoved", - _on_adapter_removed, NULL); - eldbus_proxy_signal_handler_add(ctxt->man_proxy, "AdapterAdded", - _on_adapter_added, NULL); - - eldbus_name_owner_changed_callback_add(ctxt->conn, BLUEZ_BUS, _bluez_monitor, - NULL, EINA_TRUE); -} - -void -ebluez4_eldbus_shutdown(void) -{ - if (ctxt->adap_obj) - _unset_default_adapter(); - _free_adap_list(); - eldbus_object_unref(eldbus_proxy_object_get(ctxt->man_proxy)); - eldbus_connection_unref(ctxt->conn); - free(ctxt); - -} - -void -ebluez4_start_discovery(void) -{ - _free_dev_list(&ctxt->found_devices); - ebluez4_update_instances(ctxt->found_devices); - eldbus_proxy_call(ctxt->adap_proxy, "StartDiscovery", NULL, NULL, -1, ""); -} - -void -ebluez4_stop_discovery(void) -{ - eldbus_proxy_call(ctxt->adap_proxy, "StopDiscovery", NULL, NULL, -1, ""); -} - -void -ebluez4_connect_to_device(Device *dev) -{ - _try_to_connect(dev->proxy.input); - _try_to_connect(dev->proxy.audio_source); - _try_to_connect(dev->proxy.audio_sink); -} - -void -ebluez4_disconnect_device(Device *dev) -{ - _try_to_disconnect(dev->proxy.input); - _try_to_disconnect(dev->proxy.audio_source); - _try_to_disconnect(dev->proxy.audio_sink); -} - -void -ebluez4_pair_with_device(const char *addr, void (*cb)(void *, Eina_Bool, const char *), void *data) -{ - Pair_Cb *d = malloc(sizeof(Pair_Cb)); - EINA_SAFETY_ON_NULL_RETURN(d); - d->cb = cb; - d->data = data; - eldbus_proxy_call(ctxt->adap_proxy, "CreatePairedDevice", _on_paired, d, - -1, "sos", addr, AGENT_PATH, "KeyboardDisplay"); -} - -void -ebluez4_remove_device(Eldbus_Object *obj) -{ - eldbus_proxy_call(ctxt->adap_proxy, "RemoveDevice", NULL, NULL, -1, "o", - eldbus_object_path_get(obj)); -} - -int -ebluez4_dev_path_cmp(const void *d1, const void *d2) -{ - const Device *dev = d1; - const char *path = d2; - - return strcmp(eldbus_object_path_get(dev->obj), path); -} - -void -ebluez4_adapter_property_set(Adapter *adap, const char *prop_name, Eina_Bool value) -{ - Eldbus_Message_Iter *variant, *iter; - Eldbus_Message *new_msg; - - if (!adap) return; - if (!adap->obj) return; - new_msg = eldbus_proxy_method_call_new(adap->proxy, "SetProperty"); - iter = eldbus_message_iter_get(new_msg); - eldbus_message_iter_basic_append(iter, 's', prop_name); - variant = eldbus_message_iter_container_new(iter, 'v', "b"); - eldbus_message_iter_basic_append(variant, 'b', value); - eldbus_message_iter_container_close(iter, variant); - eldbus_proxy_send(adap->proxy, new_msg, NULL, NULL, -1); -} diff --git a/src/modules/bluez4/ebluez4.h b/src/modules/bluez4/ebluez4.h deleted file mode 100644 index 9d6147508..000000000 --- a/src/modules/bluez4/ebluez4.h +++ /dev/null @@ -1,84 +0,0 @@ -#include "Eldbus.h" - -#define BLUEZ_BUS "org.bluez" -#define MANAGER_PATH "/" -#define INPUT_INTERFACE "org.bluez.Input" -#define AUDIO_SOURCE_INTERFACE "org.bluez.AudioSource" -#define AUDIO_SINK_INTERFACE "org.bluez.AudioSink" -#define DEVICE_INTERFACE "org.bluez.Device" -#define ADAPTER_INTERFACE "org.bluez.Adapter" -#define MANAGER_INTERFACE "org.bluez.Manager" - -#define HumanInterfaceDevice_UUID "00001124-0000-1000-8000-00805f9b34fb" -#define AudioSource_UUID "0000110a-0000-1000-8000-00805f9b34fb" -#define AudioSink_UUID "0000110b-0000-1000-8000-00805f9b34fb" - -typedef enum _Profile -{ - INPUT, - AUDIO_SOURCE, - AUDIO_SINK, - NONE -} Profile; - -typedef struct _Service -{ - const char *uuid; - Profile profile; -} Service; - -typedef struct _Device -{ - const char *addr; - const char *name; - const char *type; - Eina_Bool paired; - Eina_Bool connected; - Eldbus_Object *obj; - struct - { - Eldbus_Proxy *dev; - Eldbus_Proxy *input; - Eldbus_Proxy *audio_sink; - Eldbus_Proxy *audio_source; - } proxy; -} Device; - -typedef struct _Adapter -{ - const char *name; - Eina_Bool visible; - Eina_Bool pairable; - Eina_Bool powered; - int visible_checked; - int pairable_checked; - int powered_checked; - Eina_Bool is_default; - E_Dialog *dialog; - Eldbus_Object *obj; - Eldbus_Proxy *proxy; -} Adapter; - -typedef struct _Context -{ - Eldbus_Connection *conn; - Eldbus_Object *adap_obj; - Eldbus_Proxy *man_proxy; - Eldbus_Proxy *adap_proxy; - Eina_List *devices; - Eina_List *found_devices; - Eina_List *adapters; -} Context; - -extern Context *ctxt; - -void ebluez4_eldbus_init(void); -void ebluez4_eldbus_shutdown(void); -void ebluez4_start_discovery(void); -void ebluez4_stop_discovery(void); -void ebluez4_connect_to_device(Device *dev); -void ebluez4_disconnect_device(Device *dev); -void ebluez4_pair_with_device(const char *addr, void (*cb)(void *, Eina_Bool, const char *), void *data); -void ebluez4_remove_device(Eldbus_Object *obj); -int ebluez4_dev_path_cmp(const void *d1, const void *d2); -void ebluez4_adapter_property_set(Adapter *adap, const char *prop_name, Eina_Bool value); diff --git a/src/modules/bluez4/meson.build b/src/modules/bluez4/meson.build deleted file mode 100644 index 05262db4e..000000000 --- a/src/modules/bluez4/meson.build +++ /dev/null @@ -1,5 +0,0 @@ -src = files( - 'e_mod_main.c', - 'agent.c', - 'ebluez4.c' -) diff --git a/src/modules/bluez4/module.desktop b/src/modules/bluez4/module.desktop deleted file mode 100644 index e5b900f19..000000000 --- a/src/modules/bluez4/module.desktop +++ /dev/null @@ -1,13 +0,0 @@ -[Desktop Entry] -Type=Link -Name=Bluez4 -Name[ca]=Bluez4 -Name[de]=Bluez4 -Name[fi]=Bluez4 -Name[gl]=Bluez4 -Name[ja]=Bluez4 -Name[ms]=Bluez4 -Name[sr]=Блуез4 -Name[tr]=Bluetooth -Icon=e-module-bluez4 -X-Enlightenment-ModuleType=utils diff --git a/src/modules/meson.build b/src/modules/meson.build index 4150367e7..5ace236b3 100644 --- a/src/modules/meson.build +++ b/src/modules/meson.build @@ -33,7 +33,6 @@ mods = [ 'gadman', 'geolocation', 'connman', - 'bluez4', 'bluez5', 'syscon', 'systray',