bluez5 support - a new module with gadget etc.

Summary:
bluez4 support is now basically dead. nothing ships it anymore. bluez5
is a new api that is rather different so new code. also a new gui with
more complete features etc.

not everything is done as i'd like. need:

1. many more icons for device types (60-70 maybe?)
2. a few specific custom icons for some action buttons (like
pair/unpair)
3. icons for group headers
4. gadget status - the gagdte itself displays zero status. it's a
button to display a popup. that's all.

Reviewers: zmike!

Subscribers: devilhorns, cedric

Tags: #enlightenment-git

Differential Revision: https://phab.enlightenment.org/D6148
This commit is contained in:
Carsten Haitzler 2018-05-10 13:52:06 +09:00
parent 05d3f2d393
commit 2e5be79c45
17 changed files with 3008 additions and 1 deletions

View File

@ -111,6 +111,10 @@ option('bluez4',
type: 'boolean', type: 'boolean',
value: true, value: true,
description: 'enable bluez4 module: (default=true)') description: 'enable bluez4 module: (default=true)')
option('bluez5',
type: 'boolean',
value: true,
description: 'enable bluez5 module: (default=true)')
option('clock', option('clock',
type: 'boolean', type: 'boolean',
value: true, value: true,

View File

@ -1525,6 +1525,44 @@ e_config_load(void)
CONFIG_VERSION_UPDATE_INFO(25); CONFIG_VERSION_UPDATE_INFO(25);
e_config_save_queue(); e_config_save_queue();
} }
CONFIG_VERSION_CHECK(26)
{
// move from bluez4 to bluez5 automatically. you can manually
// move back if that works better for you...
Eina_List *l, *ll;
E_Config_Module *em;
E_Config_Gadcon *gc;
E_Config_Gadcon_Client *gcc;
EINA_LIST_FOREACH(e_config->modules, l, em)
{
if (!em->enabled) continue;
if (!em->name) continue;
if (eina_streq(em->name, "bluez4"))
{
eina_stringshare_replace(&(em->name), "bluez5");
}
}
EINA_LIST_FOREACH(e_config->gadcons, l, gc)
{
EINA_LIST_FOREACH(gc->clients, ll, gcc)
{
if (!gcc->name) continue;
if (!strncmp(gcc->name, "bluez4", 6))
{
char *tmp = strdup(gcc->name);
if (tmp)
{
tmp[5] = '5';
eina_stringshare_replace(&(gcc->name), tmp);
free(tmp);
}
}
}
}
CONFIG_VERSION_UPDATE_INFO(26);
e_config_save_queue();
}
} }
elm_config_profile_set(_e_config_profile); elm_config_profile_set(_e_config_profile);
if (!e_config->remember_internal_fm_windows) if (!e_config->remember_internal_fm_windows)

View File

@ -46,7 +46,7 @@ typedef enum
/* increment this whenever a new set of config values are added but the users /* increment this whenever a new set of config values are added but the users
* config doesn't need to be wiped - simply new values need to be put in * config doesn't need to be wiped - simply new values need to be put in
*/ */
#define E_CONFIG_FILE_GENERATION 25 #define E_CONFIG_FILE_GENERATION 26
#define E_CONFIG_FILE_VERSION ((E_CONFIG_FILE_EPOCH * 1000000) + E_CONFIG_FILE_GENERATION) #define E_CONFIG_FILE_VERSION ((E_CONFIG_FILE_EPOCH * 1000000) + E_CONFIG_FILE_GENERATION)
#define E_CONFIG_BINDINGS_VERSION 0 // DO NOT INCREMENT UNLESS YOU WANT TO WIPE ALL BINDINGS!!!!! #define E_CONFIG_BINDINGS_VERSION 0 // DO NOT INCREMENT UNLESS YOU WANT TO WIPE ALL BINDINGS!!!!!

View File

@ -997,6 +997,7 @@ _e_module_whitelist_check(void)
"backlight", "backlight",
"battery", "battery",
"bluez4", "bluez4",
"bluez5",
"clock", "clock",
"conf", "conf",
"conf_applications", "conf_applications",

109
src/modules/bluez5/bz.c Normal file
View File

@ -0,0 +1,109 @@
#include "e_mod_main.h"
Eldbus_Connection *bz_conn = NULL;
static Ecore_Timer *owner_gain_timer = NULL;
/////////////////////////////////////////////////////////////////////////////
static Eina_Bool
cb_name_owner_new(void *data EINA_UNUSED)
{
owner_gain_timer = NULL;
bz_obj_init();
bz_agent_init();
return EINA_FALSE;
}
static void
cb_name_owner_changed(void *data EINA_UNUSED,
const char *bus EINA_UNUSED,
const char *from EINA_UNUSED,
const char *to)
{
static Eina_Bool first = EINA_TRUE;
if (to[0])
{
if (owner_gain_timer) ecore_timer_del(owner_gain_timer);
// on first start try and re-init quickly because we get a name
// owner change even if all is good when we register to listen for it,
// so start fast
if (first)
owner_gain_timer = ecore_timer_add(0.1, cb_name_owner_new, NULL);
// but if we gegt a name owner change later it's probably because
// bluez was restarted or crashed. a new bz daemon will (or should)
// come up. so re-init more slowly here giving the daemon some time
// to come up before pestering it.
else
owner_gain_timer = ecore_timer_add(1.0, cb_name_owner_new, NULL);
first = EINA_FALSE;
}
else
{
if (owner_gain_timer) ecore_timer_del(owner_gain_timer);
owner_gain_timer = NULL;
ebluze5_popup_clear();
bz_agent_shutdown();
bz_obj_shutdown();
}
}
static void
cb_obj_add(Obj *o)
{
if (o->type == BZ_OBJ_ADAPTER)
{
o->fn_change = ebluez5_popup_adapter_change;
o->fn_del = ebluez5_popup_adapter_del;
ebluez5_popup_adapter_add(o);
return;
}
if (o->type == BZ_OBJ_DEVICE)
{
o->fn_change = ebluez5_popup_device_change;
o->fn_del = ebluez5_popup_device_del;
ebluez5_popup_device_add(o);
return;
}
}
void
bz_init(void)
{
bz_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
bz_obj_add_func_set(cb_obj_add);
bz_agent_release_func_set(ebluez5_agent_agent_release);
bz_agent_cancel_func_set(ebluez5_agent_agent_cancel);
bz_agent_req_pin_func_set(ebluez5_agent_agent_req_pin);
bz_agent_disp_pin_func_set(ebluez5_agent_agent_disp_pin);
bz_agent_req_pass_func_set(ebluez5_agent_req_pass);
bz_agent_disp_pass_func_set(ebluez5_agent_disp_pass);
bz_agent_req_confirm_func_set(ebluez5_agent_req_confirm);
bz_agent_req_auth_func_set(ebluez5_agent_req_auth);
bz_agent_auth_service_func_set(ebluez5_agent_auth_service);
eldbus_name_owner_changed_callback_add(bz_conn, "org.bluez",
cb_name_owner_changed,
NULL, EINA_TRUE);
}
void
bz_shutdown(void)
{
eldbus_name_owner_changed_callback_del(bz_conn, "org.bluez",
cb_name_owner_changed, NULL);
bz_agent_release_func_set(NULL);
bz_agent_cancel_func_set(NULL);
bz_agent_req_pin_func_set(NULL);
bz_agent_disp_pin_func_set(NULL);
bz_agent_req_pass_func_set(NULL);
bz_agent_disp_pass_func_set(NULL);
bz_agent_req_confirm_func_set(NULL);
bz_agent_req_auth_func_set(NULL);
bz_agent_auth_service_func_set(NULL);
bz_obj_add_func_set(NULL);
ebluze5_popup_clear();
bz_agent_shutdown();
bz_obj_shutdown();
eldbus_connection_unref(bz_conn);
bz_conn = NULL;
}

234
src/modules/bluez5/bz.h Normal file
View File

@ -0,0 +1,234 @@
#ifndef BZ_H
# define BZ_H
# include <Elementary.h>
typedef enum {
BZ_OBJ_UNKNOWN,
BZ_OBJ_BLUEZ,
BZ_OBJ_ADAPTER,
BZ_OBJ_DEVICE
} Obj_Type;
typedef struct _Obj Obj;
struct _Obj {
//// internal object data
Eldbus_Proxy *proxy;
Eldbus_Proxy *prop_proxy;
Eldbus_Signal_Handler *prop_sig;
unsigned int ref;
Eina_Bool in_table : 1;
Eina_Bool add_called : 1;
//// public data to read
const char *path;
Obj_Type type;
//// data to be set by users of the obj
void *data; // custom data
void (*fn_change) (Obj *o);
void (*fn_del) (Obj *o);
//// obj properties
Eina_Array *uuids;
const char *address;
const char *address_type;
const char *name;
const char *icon;
const char *alias;
const char *adapter;
const char *modalias;
unsigned int klass;
unsigned short appearance;
unsigned short txpower;
short rssi;
Eina_Bool paired : 1;
Eina_Bool connected : 1;
Eina_Bool trusted : 1;
Eina_Bool blocked : 1;
Eina_Bool legacy_pairing : 1;
Eina_Bool services_resolved : 1;
//// adapter specific properties
unsigned int discoverable_timeout;
unsigned int pairable_timeout;
Eina_Bool discoverable : 1;
Eina_Bool discovering : 1;
Eina_Bool pairable : 1;
Eina_Bool powered : 1;
//// agent data for when devices ask to pair etc.
const char *agent_request;
Eldbus_Message *agent_msg_ok;
Eldbus_Message *agent_msg_err;
void (*agent_entry_fn) (Eldbus_Message *msg, const char *str);
Eina_Bool agent_alert : 1;
};
#define BZ_OBJ_CLASS_SERVICE_LIMITED_DISCOVERABLE (1 << 13)
#define BZ_OBJ_CLASS_SERVICE_POSITIONING_BIT (1 << 16)
#define BZ_OBJ_CLASS_SERVICE_NETWORKING_BIT (1 << 17)
#define BZ_OBJ_CLASS_SERVICE_RENDERING_BIT (1 << 18)
#define BZ_OBJ_CLASS_SERVICE_CAPTURING_BIT (1 << 19)
#define BZ_OBJ_CLASS_SERVICE_OBJECT_TRANSFER_BIT (1 << 20)
#define BZ_OBJ_CLASS_SERVICE_AUDIO_BIT (1 << 21)
#define BZ_OBJ_CLASS_SERVICE_TELEPHONY_BIT (1 << 22)
#define BZ_OBJ_CLASS_SERVICE_INFORMATION_BIT (1 << 23)
#define BZ_OBJ_CLASS_MAJ_MASK (0x1f << 8)
#define BZ_OBJ_CLASS_MAJ_MISC ( 0 << 8)
#define BZ_OBJ_CLASS_MAJ_COMPUTER ( 1 << 8)
#define BZ_OBJ_CLASS_MAJ_PHONE ( 2 << 8)
#define BZ_OBJ_CLASS_MAJ_LAN ( 3 << 8)
#define BZ_OBJ_CLASS_MAJ_AV ( 4 << 8)
#define BZ_OBJ_CLASS_MAJ_PERIPHERAL ( 5 << 8)
#define BZ_OBJ_CLASS_MAJ_IMAGING ( 6 << 8)
#define BZ_OBJ_CLASS_MAJ_WEARABLE ( 7 << 8)
#define BZ_OBJ_CLASS_MAJ_TOY ( 8 << 8)
#define BZ_OBJ_CLASS_MAJ_HEALTH ( 9 << 8)
#define BZ_OBJ_CLASS_MIN_COMPUTER_MASK (0x3f << 2)
#define BZ_OBJ_CLASS_MIN_COMPUTER_DESKTOP ( 1 << 2)
#define BZ_OBJ_CLASS_MIN_COMPUTER_SERVER ( 2 << 2)
#define BZ_OBJ_CLASS_MIN_COMPUTER_LAPTOP ( 3 << 2)
#define BZ_OBJ_CLASS_MIN_COMPUTER_CLAMSHELL ( 4 << 2)
#define BZ_OBJ_CLASS_MIN_COMPUTER_PDA ( 5 << 2)
#define BZ_OBJ_CLASS_MIN_COMPUTER_WEARABLE ( 6 << 2)
#define BZ_OBJ_CLASS_MIN_COMPUTER_TABLET ( 7 << 2)
#define BZ_OBJ_CLASS_MIN_PHONE_MASK (0x3f << 2)
#define BZ_OBJ_CLASS_MIN_PHONE_CELL ( 1 << 2)
#define BZ_OBJ_CLASS_MIN_PHONE_CORDLESS ( 2 << 2)
#define BZ_OBJ_CLASS_MIN_PHONE_SMARTPHONE ( 3 << 2)
#define BZ_OBJ_CLASS_MIN_PHONE_WIRED ( 4 << 2)
#define BZ_OBJ_CLASS_MIN_PHONE_ISDN ( 5 << 2)
#define BZ_OBJ_CLASS_MIN_LAN_MASK (0x07 << 5)
#define BZ_OBJ_CLASS_MIN_LAN_AVAIL_7 ( 0 << 5)
#define BZ_OBJ_CLASS_MIN_LAN_AVAIL_6 ( 1 << 5)
#define BZ_OBJ_CLASS_MIN_LAN_AVAIL_5 ( 2 << 5)
#define BZ_OBJ_CLASS_MIN_LAN_AVAIL_4 ( 3 << 5)
#define BZ_OBJ_CLASS_MIN_LAN_AVAIL_3 ( 4 << 5)
#define BZ_OBJ_CLASS_MIN_LAN_AVAIL_2 ( 5 << 5)
#define BZ_OBJ_CLASS_MIN_LAN_AVAIL_1 ( 6 << 5)
#define BZ_OBJ_CLASS_MIN_LAN_AVAIL_0 ( 7 << 5)
#define BZ_OBJ_CLASS_MIN_AV_MASK (0x3f << 2)
#define BZ_OBJ_CLASS_MIN_AV_WEARABLE_HEADSET ( 1 << 2)
#define BZ_OBJ_CLASS_MIN_AV_HANDS_FREE ( 2 << 2)
#define BZ_OBJ_CLASS_MIN_AV_MIC ( 4 << 2)
#define BZ_OBJ_CLASS_MIN_AV_SPEAKER ( 5 << 2)
#define BZ_OBJ_CLASS_MIN_AV_HEADPHONES ( 6 << 2)
#define BZ_OBJ_CLASS_MIN_AV_PORTABLE_AUDIO ( 7 << 2)
#define BZ_OBJ_CLASS_MIN_AV_CAR_AUDIO ( 8 << 2)
#define BZ_OBJ_CLASS_MIN_AV_SET_TOP_BOX ( 9 << 2)
#define BZ_OBJ_CLASS_MIN_AV_HIFI_AUDIO (10 << 2)
#define BZ_OBJ_CLASS_MIN_AV_VCR (11 << 2)
#define BZ_OBJ_CLASS_MIN_AV_VIDEO_CAMERA (12 << 2)
#define BZ_OBJ_CLASS_MIN_AV_CAMCORDER (13 << 2)
#define BZ_OBJ_CLASS_MIN_AV_VIDEO_MONITOR (14 << 2)
#define BZ_OBJ_CLASS_MIN_AV_VIDEO_DISPLAY_SPEAKER (15 << 2)
#define BZ_OBJ_CLASS_MIN_AV_VIDEO_CONFERENCE (16 << 2)
#define BZ_OBJ_CLASS_MIN_AV_GAMING (18 << 2)
#define BZ_OBJ_CLASS_MIN_PERIPHERAL_KEYBOARD_BIT ( 1 << 6)
#define BZ_OBJ_CLASS_MIN_PERIPHERAL_MOUSE_BIT ( 1 << 7)
#define BZ_OBJ_CLASS_MIN_PERIPHERAL_MASK2 (0x0f << 2)
#define BZ_OBJ_CLASS_MIN_PERIPHERAL_JOYSTICK ( 1 << 2)
#define BZ_OBJ_CLASS_MIN_PERIPHERAL_GAMEPAD ( 2 << 2)
#define BZ_OBJ_CLASS_MIN_PERIPHERAL_REMOTE ( 3 << 2)
#define BZ_OBJ_CLASS_MIN_PERIPHERAL_SENSING ( 4 << 2)
#define BZ_OBJ_CLASS_MIN_PERIPHERAL_DIGITIZER_TAB ( 5 << 2)
#define BZ_OBJ_CLASS_MIN_PERIPHERAL_CARD_READER ( 6 << 2)
#define BZ_OBJ_CLASS_MIN_PERIPHERAL_PEN ( 7 << 2)
#define BZ_OBJ_CLASS_MIN_PERIPHERAL_SCANNER ( 8 << 2)
#define BZ_OBJ_CLASS_MIN_PERIPHERAL_WAND ( 9 << 2)
#define BZ_OBJ_CLASS_MIN_IMAGING_DISPLAY_BIT ( 1 << 4)
#define BZ_OBJ_CLASS_MIN_IMAGING_CAMERA_BIT ( 1 << 5)
#define BZ_OBJ_CLASS_MIN_IMAGING_SCANNER_BIT ( 1 << 6)
#define BZ_OBJ_CLASS_MIN_IMAGING_PRINTER_BIT ( 1 << 7)
#define BZ_OBJ_CLASS_MIN_WEARABLE_MASK (0x3f << 2)
#define BZ_OBJ_CLASS_MIN_WEARABLE_WATCH ( 1 << 2)
#define BZ_OBJ_CLASS_MIN_WEARABLE_PAGER ( 2 << 2)
#define BZ_OBJ_CLASS_MIN_WEARABLE_JACKET ( 3 << 2)
#define BZ_OBJ_CLASS_MIN_WEARABLE_HELMET ( 4 << 2)
#define BZ_OBJ_CLASS_MIN_WEARABLE_GLASSES ( 5 << 2)
#define BZ_OBJ_CLASS_MIN_TOY_MASK (0x3f << 2)
#define BZ_OBJ_CLASS_MIN_TOY_ROBOT ( 1 << 2)
#define BZ_OBJ_CLASS_MIN_TOY_VEHICLE ( 2 << 2)
#define BZ_OBJ_CLASS_MIN_TOY_DOLL ( 3 << 2)
#define BZ_OBJ_CLASS_MIN_TOY_CONTROLLER ( 4 << 2)
#define BZ_OBJ_CLASS_MIN_TOY_GAME ( 5 << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_MASK (0x3f << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_BLOOD_PRESSURE ( 1 << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_THERMOMETER ( 2 << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_SCALES ( 3 << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_GLUCOSE ( 4 << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_PULSE_OXIMITER ( 5 << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_HEART_RATE ( 6 << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_HEALTH_DATA_DISP ( 7 << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_STEP ( 8 << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_BODY_COMPOSITION ( 9 << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_PEAK_FLOW (10 << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_MEDICATION (11 << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_KNEE_PROSTHESIS (12 << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_ANKLE_PROSTHESIS (13 << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_GENERIC_HEALTH (14 << 2)
#define BZ_OBJ_CLASS_MIN_HEALTH_PRESONAL_MOBILITY (15 << 2)
extern Eldbus_Connection *bz_conn;
void bz_init(void);
void bz_shutdown(void);
Obj *bz_obj_add(const char *path);
Obj *bz_obj_find(const char *path);
void bz_obj_power_on(Obj *o);
void bz_obj_power_off(Obj *o);
void bz_obj_discoverable(Obj *o);
void bz_obj_undiscoverable(Obj *o);
void bz_obj_pairable(Obj *o);
void bz_obj_unpairable(Obj *o);
void bz_obj_trust(Obj *o);
void bz_obj_distrust(Obj *o);
void bz_obj_pair(Obj *o);
void bz_obj_pair_cancel(Obj *o);
void bz_obj_connect(Obj *o);
void bz_obj_disconnect(Obj *o);
void bz_obj_remove(Obj *o);
void bz_obj_profile_connect(Obj *o, const char *uuid);
void bz_obj_profile_disconnect(Obj *o, const char *uuid);
void bz_obj_ref(Obj *o);
void bz_obj_unref(Obj *o);
void bz_obj_discover_start(Obj *o);
void bz_obj_discover_stop(Obj *o);
void bz_obj_agent_request(Obj *o, const char *req, void (*fn) (Eldbus_Message *msg, const char *str), Eldbus_Message *ok_msg, Eldbus_Message *err_msg);
void bz_obj_init(void);
void bz_obj_shutdown(void);
void bz_obj_add_func_set(void (*fn) (Obj *o));
void bz_agent_msg_reply(Eldbus_Message *msg);
void bz_agent_msg_drop(Eldbus_Message *msg);
Eldbus_Message *bz_agent_msg_err(Eldbus_Message *msg);
Eldbus_Message *bz_agent_msg_ok(Eldbus_Message *msg);
const char *bz_agent_msg_path(Eldbus_Message *msg);
const char *bz_agent_msg_path_str(Eldbus_Message *msg, const char **str);
const char *bz_agent_msg_path_u32(Eldbus_Message *msg, unsigned int *u32);
const char *bz_agent_msg_path_u32_u16(Eldbus_Message *msg, unsigned int *u32, unsigned short *u16);
void bz_agent_msg_str_add(Eldbus_Message *msg, const char *str);
void bz_agent_msg_u32_add(Eldbus_Message *msg, unsigned int u32);
void bz_agent_init(void);
void bz_agent_shutdown(void);
void bz_agent_release_func_set(void (*fn) (void));
void bz_agent_cancel_func_set(void (*fn) (void));
void bz_agent_req_pin_func_set(void (*fn) (Eldbus_Message *msg));
void bz_agent_disp_pin_func_set(void (*fn) (Eldbus_Message *msg));
void bz_agent_req_pass_func_set(void (*fn) (Eldbus_Message *msg));
void bz_agent_disp_pass_func_set(void (*fn) (Eldbus_Message *msg));
void bz_agent_req_confirm_func_set(void (*fn) (Eldbus_Message *msg));
void bz_agent_req_auth_func_set(void (*fn) (Eldbus_Message *msg));
void bz_agent_auth_service_func_set(void (*fn) (Eldbus_Message *msg));
#endif

View File

@ -0,0 +1,346 @@
#include "bz.h"
#include "e.h"
static Eldbus_Service_Interface *agent_iface = NULL;
static Eldbus_Proxy *agent_proxy = NULL;
static void (*fn_release) (void) = NULL;
static void (*fn_cancel) (void) = NULL;
static void (*fn_req_pin) (Eldbus_Message *msg) = NULL;
static void (*fn_disp_pin) (Eldbus_Message *msg) = NULL;
static void (*fn_req_pass) (Eldbus_Message *msg) = NULL;
static void (*fn_disp_pass) (Eldbus_Message *msg) = NULL;
static void (*fn_req_confirm) (Eldbus_Message *msg) = NULL;
static void (*fn_req_auth) (Eldbus_Message *msg) = NULL;
static void (*fn_auth_service) (Eldbus_Message *msg) = NULL;
static Eldbus_Message *
cb_agent_release(const Eldbus_Service_Interface *iface EINA_UNUSED,
const Eldbus_Message *msg)
{
Eldbus_Message *reply = eldbus_message_method_return_new(msg);
if (fn_release) fn_release();
return reply;
}
static Eldbus_Message *
cb_agent_cancel(const Eldbus_Service_Interface *iface EINA_UNUSED,
const Eldbus_Message *msg)
{
Eldbus_Message *reply = eldbus_message_method_return_new(msg);
if (fn_cancel) fn_cancel();
return reply;
}
static Eldbus_Message *
cb_agent_request_pin_code(const Eldbus_Service_Interface *iface EINA_UNUSED,
const Eldbus_Message *msg)
{
if (fn_req_pin) fn_req_pin((Eldbus_Message *)msg);
return NULL;
}
static Eldbus_Message *
cb_agent_display_pin_code(const Eldbus_Service_Interface *iface EINA_UNUSED,
const Eldbus_Message *msg)
{
if (fn_disp_pin) fn_disp_pin((Eldbus_Message *)msg);
return NULL;
}
static Eldbus_Message *
cb_agent_request_pass_key(const Eldbus_Service_Interface *iface EINA_UNUSED,
const Eldbus_Message *msg)
{
if (fn_req_pass) fn_req_pass((Eldbus_Message *)msg);
return NULL;
}
static Eldbus_Message *
cb_agent_display_pass_key(const Eldbus_Service_Interface *iface EINA_UNUSED,
const Eldbus_Message *msg)
{
if (fn_disp_pass) fn_disp_pass((Eldbus_Message *)msg);
return NULL;
}
static Eldbus_Message *
cb_agent_request_confirmation(const Eldbus_Service_Interface *iface EINA_UNUSED,
const Eldbus_Message *msg)
{
if (fn_req_confirm) fn_req_confirm((Eldbus_Message *)msg);
return NULL;
}
static Eldbus_Message *
cb_agent_request_authorization(const Eldbus_Service_Interface *iface EINA_UNUSED,
const Eldbus_Message *msg)
{
if (fn_req_auth) fn_req_auth((Eldbus_Message *)msg);
return NULL;
}
static Eldbus_Message *
cb_agent_authorize_service(const Eldbus_Service_Interface *iface EINA_UNUSED,
const Eldbus_Message *msg)
{
if (fn_auth_service) fn_auth_service((Eldbus_Message *)msg);
return NULL;
/* Not done yet... don't even know what services are with bt...
Eldbus_Message *reply = eldbus_message_method_return_new(msg);
const char *path = NULL, *uuid = NULL;
printf("Agent authorize service\n");
if (!eldbus_message_arguments_get(msg, "os", &path, &uuid)) return reply;
printf(" %s %s\n", path, uuid);
// if ok return this reply, or make it an error...
// reply = eldbus_message_error_new(msg, "org.bluez.Error.Rejected", "");
return reply;
// really return NULL and defer above reply with:
// eldbus_connection_send(bz_conn, reply, NULL, NULL, -1);
*/
}
static void
cb_default(void *data EINA_UNUSED, const Eldbus_Message *msg,
Eldbus_Pending *pending EINA_UNUSED)
{
const char *name, *text;
if (eldbus_message_error_get(msg, &name, &text))
{
// XXX: should have a visual e log...
e_util_dialog_show(_("Bluetooth"),
_("Could not register default agent:<br>%s %s"),
name, text);
return;
}
}
static void
cb_register(void *data EINA_UNUSED, const Eldbus_Message *msg,
Eldbus_Pending *pending EINA_UNUSED)
{
const char *name, *text;
if (eldbus_message_error_get(msg, &name, &text))
{
// XXX: should have a visual e log...
e_util_dialog_show(_("Bluetooth"),
_("Could not register agent:<br>%s %s\n"),
name, text);
return;
}
if (!agent_proxy) return;
eldbus_proxy_call(agent_proxy, "RequestDefaultAgent",
cb_default, NULL, -1,
"o", "/org/enlightenment/bluez5/agent");
}
static void
cb_unregister(void *data EINA_UNUSED, const Eldbus_Message *msg,
Eldbus_Pending *pending EINA_UNUSED)
{
const char *name, *text;
if (agent_proxy)
{
eldbus_proxy_unref(agent_proxy);
agent_proxy = NULL;
}
if (agent_iface)
{
eldbus_service_object_unregister(agent_iface);
agent_iface = NULL;
}
if (eldbus_message_error_get(msg, &name, &text))
{
// just debug for developers
printf("Could not unregister agent.\n %s:\n %s\n", name, text);
return;
}
}
static const Eldbus_Method agent_methods[] = {
{ "Release", NULL, NULL, cb_agent_release, 0 },
{ "RequestPinCode", ELDBUS_ARGS({ "o", "device" }), ELDBUS_ARGS({ "s", "pincode" }), cb_agent_request_pin_code, 0 },
{ "DisplayPinCode", ELDBUS_ARGS({ "o", "device" }, { "s", "pincode" }), NULL, cb_agent_display_pin_code, 0 },
{ "RequestPasskey", ELDBUS_ARGS({ "o", "device" }), ELDBUS_ARGS({ "u", "passkey" }), cb_agent_request_pass_key, 0 },
{ "DisplayPasskey", ELDBUS_ARGS({ "o", "device" }, { "u", "passkey" }, { "q", "entered" }), NULL, cb_agent_display_pass_key, 0 },
{ "RequestConfirmation", ELDBUS_ARGS({ "o", "device" }, { "u", "passkey" }), NULL, cb_agent_request_confirmation, 0 },
{ "RequestAuthorization", ELDBUS_ARGS({ "o", "device" }), NULL, cb_agent_request_authorization, 0 },
{ "AuthorizeService", ELDBUS_ARGS({ "o", "device" }, { "s", "uuid" }), NULL, cb_agent_authorize_service, 0 },
{ "Cancel", NULL, NULL, cb_agent_cancel, 0 },
{ NULL, NULL, NULL, NULL, 0 }
};
static const Eldbus_Service_Interface_Desc agent_desc = {
"org.bluez.Agent1", agent_methods, NULL, NULL, NULL, NULL
};
void
bz_agent_msg_reply(Eldbus_Message *msg)
{
if (!bz_conn)
{
eldbus_message_unref(msg);
return;
}
eldbus_connection_send(bz_conn, msg, NULL, NULL, -1);
}
void
bz_agent_msg_drop(Eldbus_Message *msg)
{
eldbus_message_unref(msg);
}
Eldbus_Message *
bz_agent_msg_err(Eldbus_Message *msg)
{
return eldbus_message_error_new(msg, "org.bluez.Error.Rejected", "");
}
Eldbus_Message *
bz_agent_msg_ok(Eldbus_Message *msg)
{
return eldbus_message_method_return_new(msg);
}
const char *
bz_agent_msg_path(Eldbus_Message *msg)
{
const char *s = NULL;
if (!eldbus_message_arguments_get(msg, "o", &s)) return NULL;
return s;
}
const char *
bz_agent_msg_path_str(Eldbus_Message *msg, const char **str)
{
const char *s = NULL, *s2 = NULL;
if (!eldbus_message_arguments_get(msg, "os", &s, &s2)) return NULL;
if (str) *str = s2;
return s;
}
const char *
bz_agent_msg_path_u32(Eldbus_Message *msg, unsigned int *u32)
{
const char *s = NULL;
unsigned int uu32 = 0;
if (!eldbus_message_arguments_get(msg, "ou", &s, &uu32)) return NULL;
if (u32) *u32 = uu32;
return s;
}
const char *
bz_agent_msg_path_u32_u16(Eldbus_Message *msg, unsigned int *u32, unsigned short *u16)
{
const char *s = NULL;
unsigned int uu32 = 0;
unsigned short uu16 = 0;
if (!eldbus_message_arguments_get(msg, "ouq", &s, &uu32, &uu16)) return NULL;
if (u32) *u32 = uu32;
if (u16) *u16 = uu16;
return s;
}
void
bz_agent_msg_str_add(Eldbus_Message *msg, const char *str)
{
eldbus_message_arguments_append(msg, "s", str);
}
void
bz_agent_msg_u32_add(Eldbus_Message *msg, unsigned int u32)
{
eldbus_message_arguments_append(msg, "u", &u32);
}
void
bz_agent_init(void)
{
Eldbus_Object *obj;
obj = eldbus_object_get(bz_conn, "org.bluez", "/org/bluez");
agent_proxy = eldbus_proxy_get(obj, "org.bluez.AgentManager1");
agent_iface = eldbus_service_interface_register
(bz_conn, "/org/enlightenment/bluez5/agent", &agent_desc);
if (agent_proxy)
eldbus_proxy_call(agent_proxy, "RegisterAgent",
cb_register, NULL, -1,
"os", "/org/enlightenment/bluez5/agent",
"KeyboardDisplay");
else
e_util_dialog_show(_("Bluetooth"),
_("Could not call RegisterAgent\n"));
}
void
bz_agent_shutdown(void)
{
if (!agent_proxy) return;
eldbus_proxy_call(agent_proxy, "UnregisterAgent",
cb_unregister, NULL, -1,
"o", "/org/enlightenment/bluez5/agent");
}
void
bz_agent_release_func_set(void (*fn) (void))
{
fn_release = fn;
}
void
bz_agent_cancel_func_set(void (*fn) (void))
{
fn_cancel = fn;
}
void
bz_agent_req_pin_func_set(void (*fn) (Eldbus_Message *msg))
{
fn_req_pin = fn;
}
void
bz_agent_disp_pin_func_set(void (*fn) (Eldbus_Message *msg))
{
fn_disp_pin = fn;
}
void
bz_agent_req_pass_func_set(void (*fn) (Eldbus_Message *msg))
{
fn_req_pass = fn;
}
void
bz_agent_disp_pass_func_set(void (*fn) (Eldbus_Message *msg))
{
fn_disp_pass = fn;
}
void
bz_agent_req_confirm_func_set(void (*fn) (Eldbus_Message *msg))
{
fn_req_confirm = fn;
}
void
bz_agent_req_auth_func_set(void (*fn) (Eldbus_Message *msg))
{
fn_req_auth = fn;
}
void
bz_agent_auth_service_func_set(void (*fn) (Eldbus_Message *msg))
{
fn_auth_service = fn;
}

760
src/modules/bluez5/bz_obj.c Normal file
View File

@ -0,0 +1,760 @@
#include "bz.h"
static Eldbus_Proxy *objman_proxy = NULL;
static Eldbus_Signal_Handler *sig_ifadd = NULL;
static Eldbus_Signal_Handler *sig_ifdel = NULL;
static Eldbus_Pending *pend_getobj = NULL;
static Eina_Hash *obj_table = NULL;
static void (*fn_obj_add) (Obj *o) = NULL;
/*
static void
cb_obj_prop_mandata(void *data, const void *key, Eldbus_Message_Iter *var)
{
Obj *o = data;
unsigned short *skey = key;
printf(" M KEY %x\n", (int)*skey);
}
*/
static void
cb_obj_prop_entry(void *data, const void *key, Eldbus_Message_Iter *var)
{
Obj *o = data;
const char *skey = key;
if (!strcmp(skey, "Paired"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->paired = val;
}
if (!strcmp(skey, "Connected"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->connected = val;
}
if (!strcmp(skey, "Trusted"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->trusted = val;
}
if (!strcmp(skey, "Blocked"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->blocked = val;
}
if (!strcmp(skey, "LegacyPairing"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->legacy_pairing = val;
}
if (!strcmp(skey, "ServicesResolved"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->services_resolved = val;
}
if (!strcmp(skey, "Address"))
{
const char *val = NULL;
if (eldbus_message_iter_arguments_get(var, "s", &val))
o->address = eina_stringshare_add(val);
}
if (!strcmp(skey, "AddressType"))
{
const char *val = NULL;
if (eldbus_message_iter_arguments_get(var, "s", &val))
o->address_type = eina_stringshare_add(val);
}
if (!strcmp(skey, "Name"))
{
const char *val = NULL;
if (eldbus_message_iter_arguments_get(var, "s", &val))
o->name = eina_stringshare_add(val);
}
if (!strcmp(skey, "Icon"))
{
const char *val = NULL;
if (eldbus_message_iter_arguments_get(var, "s", &val))
o->icon = eina_stringshare_add(val);
}
if (!strcmp(skey, "Alias"))
{
const char *val = NULL;
if (eldbus_message_iter_arguments_get(var, "s", &val))
o->alias = eina_stringshare_add(val);
}
if (!strcmp(skey, "Modalias"))
{
const char *val = NULL;
if (eldbus_message_iter_arguments_get(var, "s", &val))
o->modalias = eina_stringshare_add(val);
}
if (!strcmp(skey, "Adapter"))
{
const char *val = NULL;
if (eldbus_message_iter_arguments_get(var, "o", &val))
o->adapter = eina_stringshare_add(val);
}
if (!strcmp(skey, "Class"))
{
unsigned int val = 0;
if (eldbus_message_iter_arguments_get(var, "u", &val))
o->klass = val;
}
if (!strcmp(skey, "Appearance"))
{
unsigned short val = 0;
if (eldbus_message_iter_arguments_get(var, "q", &val))
o->appearance = val;
}
if (!strcmp(skey, "RSSI"))
{
short val = 0;
if (eldbus_message_iter_arguments_get(var, "n", &val))
o->rssi = val;
}
if (!strcmp(skey, "TxPower"))
{
unsigned short val = 0;
if (eldbus_message_iter_arguments_get(var, "n", &val))
o->txpower = val;
}
if (!strcmp(skey, "UUIDs"))
{
Eldbus_Message_Iter *array = NULL;
if (eldbus_message_iter_arguments_get(var, "as", &array))
{
const char *val = NULL;
while (eldbus_message_iter_get_and_next(array, 's', &val))
{
if (!o->uuids) o->uuids = eina_array_new(1);
eina_array_push(o->uuids, eina_stringshare_add(val));
}
}
}
if (!strcmp(skey, "Discoverable"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->discoverable = val;
}
if (!strcmp(skey, "Discovering"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->discovering = val;
}
if (!strcmp(skey, "Pairable"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->pairable = val;
}
if (!strcmp(skey, "Powered"))
{
Eina_Bool val = EINA_FALSE;
if (eldbus_message_iter_arguments_get(var, "b", &val))
o->powered = val;
}
if (!strcmp(skey, "DiscoverableTimeout"))
{
unsigned int val = 0;
if (eldbus_message_iter_arguments_get(var, "u", &val))
o->discoverable_timeout = val;
}
if (!strcmp(skey, "PairableTimeout"))
{
unsigned int val = 0;
if (eldbus_message_iter_arguments_get(var, "u", &val))
o->pairable_timeout = val;
}
// dict ManufacturerData [readonly, optional]
// Manufacturer specific advertisement data. Keys are
// 16 bits Manufacturer ID followed by its byte array
// value.
/*
if (!strcmp(skey, "ManufacturerData"))
{
Eldbus_Message_Iter *array = NULL;
if (eldbus_message_iter_arguments_get(var, "a{qv}", &array))
eldbus_message_iter_dict_iterate(array, "qv", cb_obj_prop_mandata, o);
}
*/
// dict ServiceData [readonly, optional]
// Service advertisement data. Keys are the UUIDs in
// string format followed by its byte array value.
//
// array{byte} AdvertisingFlags [readonly, experimental]
// The Advertising Data Flags of the remote device.
//
// dict AdvertisingData [readonly, experimental]
// The Advertising Data of the remote device. Keys are
// are 8 bits AD Type followed by data as byte array.
}
static void
_obj_clear(Obj *o)
{
o->paired = EINA_FALSE;
o->connected = EINA_FALSE;
o->trusted = EINA_FALSE;
o->blocked = EINA_FALSE;
o->legacy_pairing = EINA_FALSE;
o->services_resolved = EINA_FALSE;
eina_stringshare_del(o->address);
o->address = NULL;
eina_stringshare_del(o->address_type);
o->address_type = NULL;
eina_stringshare_del(o->name);
o->name = NULL;
eina_stringshare_del(o->icon);
o->icon = NULL;
eina_stringshare_del(o->alias);
o->alias = NULL;
eina_stringshare_del(o->adapter);
o->adapter = NULL;
eina_stringshare_del(o->modalias);
o->modalias = NULL;
eina_stringshare_del(o->modalias);
o->modalias = NULL;
o->klass = 0;
o->appearance = 0;
o->txpower = 0;
o->rssi = 0;
if (o->uuids)
{
const char *val;
while ((val = eina_array_pop(o->uuids)))
eina_stringshare_del(val);
eina_array_free(o->uuids);
o->uuids = NULL;
}
}
#define ERR_PRINT(str) \
do { const char *name, *text; \
if (eldbus_message_error_get(msg, &name, &text)) { \
printf("Error: %s.\n %s:\n %s\n", str, name, text); \
return; \
} \
} while(0)
static void
cb_obj_prop(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
{
Obj *o = data;
Eldbus_Message_Iter *array;
if (eldbus_message_error_get(msg, NULL, NULL)) return;
_obj_clear(o);
if (eldbus_message_arguments_get(msg, "a{sv}", &array))
eldbus_message_iter_dict_iterate(array, "sv", cb_obj_prop_entry, o);
bz_obj_ref(o);
if (!o->add_called)
{
o->add_called = EINA_TRUE;
if (fn_obj_add) fn_obj_add(o);
}
if (o->fn_change) o->fn_change(o);
bz_obj_unref(o);
}
static void
cb_obj_prop_changed(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
{
Obj *o = data;
if (!o->proxy) return;
eldbus_proxy_property_get_all(o->proxy, cb_obj_prop, o);
}
Obj *
bz_obj_add(const char *path)
{
Eldbus_Object *obj;
Obj *o = calloc(1, sizeof(Obj));
o->ref = 1;
o->path = eina_stringshare_add(path);
obj = eldbus_object_get(bz_conn, "org.bluez", o->path);
o->type = BZ_OBJ_UNKNOWN;
o->in_table = EINA_TRUE;
eina_hash_add(obj_table, o->path, o);
if (!strcmp(o->path, "/org/bluez"))
{
o->proxy = eldbus_proxy_get(obj, "org.bluez.AgentManager1");
o->type = BZ_OBJ_BLUEZ;
o->add_called = EINA_TRUE;
bz_obj_ref(o);
if (fn_obj_add) fn_obj_add(o);
bz_obj_unref(o);
goto done;
}
// all devices are /org/bluez/XXX/dev_XXX so look for /dev_
else if (strstr(o->path, "/dev_"))
{
o->proxy = eldbus_proxy_get(obj, "org.bluez.Device1");
o->type = BZ_OBJ_DEVICE;
if (o->proxy)
{
eldbus_proxy_property_get_all(o->proxy, cb_obj_prop, o);
o->prop_proxy = eldbus_proxy_get(obj,
"org.freedesktop.DBus.Properties");
if (o->prop_proxy)
o->prop_sig = eldbus_proxy_signal_handler_add(o->prop_proxy,
"PropertiesChanged",
cb_obj_prop_changed, o);
}
goto done;
}
// all dadapters begin with /org/bluez/
else if (!strncmp(o->path, "/org/bluez/", 11))
{
o->proxy = eldbus_proxy_get(obj, "org.bluez.Adapter1");
o->type = BZ_OBJ_ADAPTER;
if (o->proxy)
{
eldbus_proxy_property_get_all(o->proxy, cb_obj_prop, o);
o->prop_proxy = eldbus_proxy_get(obj,
"org.freedesktop.DBus.Properties");
if (o->prop_proxy)
o->prop_sig = eldbus_proxy_signal_handler_add(o->prop_proxy,
"PropertiesChanged",
cb_obj_prop_changed, o);
}
goto done;
}
done:
return o;
}
Obj *
bz_obj_find(const char *path)
{
return eina_hash_find(obj_table, path);
}
static void
cb_power_on(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Power On");
}
void
bz_obj_power_on(Obj *o)
{
Eina_Bool val = EINA_TRUE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Powered", "b", (void *)(uintptr_t)val, cb_power_on, o);
}
static void
cb_power_off(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Power Off");
}
void
bz_obj_power_off(Obj *o)
{
Eina_Bool val = EINA_FALSE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Powered", "b", (void *)(uintptr_t)val, cb_power_off, o);
}
static void
cb_discoverable(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Discoverable");
}
void
bz_obj_discoverable(Obj *o)
{
Eina_Bool val = EINA_TRUE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Discoverable", "b", (void *)(uintptr_t)val, cb_discoverable, o);
}
static void
cb_undiscoverable(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Undiscoverable");
}
void
bz_obj_undiscoverable(Obj *o)
{
Eina_Bool val = EINA_FALSE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Discoverable", "b", (void *)(uintptr_t)val, cb_undiscoverable, o);
}
static void
cb_pairable(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Pairable");
}
void
bz_obj_pairable(Obj *o)
{
Eina_Bool val = EINA_TRUE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Pairable", "b", (void *)(uintptr_t)val, cb_pairable, o);
}
static void
cb_unpairable(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Unpairable");
}
void
bz_obj_unpairable(Obj *o)
{
Eina_Bool val = EINA_FALSE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Pairable", "b", (void *)(uintptr_t)val, cb_unpairable, o);
}
static void
cb_trust(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Trust");
}
void
bz_obj_trust(Obj *o)
{
Eina_Bool val = EINA_TRUE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Trusted", "b", (void *)(uintptr_t)val, cb_trust, o);
}
static void
cb_distrust(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Distrust");
}
void
bz_obj_distrust(Obj *o)
{
Eina_Bool val = EINA_FALSE;
if (!o->proxy) return;
eldbus_proxy_property_set
(o->proxy, "Trusted", "b", (void *)(uintptr_t)val, cb_distrust, o);
}
static void
cb_pair(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Pair");
}
void
bz_obj_pair(Obj *o)
{
if (!o->proxy) return;
eldbus_proxy_call(o->proxy, "Pair", cb_pair, o, -1, "");
}
static void
cb_pair_cancel(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Pair Cancel");
}
void
bz_obj_pair_cancel(Obj *o)
{
if (!o->proxy) return;
eldbus_proxy_call
(o->proxy, "CancelPairing", cb_pair_cancel, o, -1, "");
}
static void
cb_connect(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Connect");
}
void
bz_obj_connect(Obj *o)
{
if (!o->proxy) return;
eldbus_proxy_call
(o->proxy, "Connect", cb_connect, o, -1, "");
}
static void
cb_disconnect(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Disconnect");
}
void
bz_obj_disconnect(Obj *o)
{
if (!o->proxy) return;
eldbus_proxy_call
(o->proxy, "Disconnect", cb_disconnect, o, -1, "");
}
/*
void
bz_obj_profile_connect(Obj *o, const char *uuid)
{
if (!o->proxy) return;
eldbus_proxy_call(o->proxy, "ConnectProfile", NULL, NULL, -1, "s", uuid);
}
void
bz_obj_profile_disconnect(Obj *o, const char *uuid)
{
if (!o->proxy) return;
eldbus_proxy_call(o->proxy, "DisconnectProfile", NULL, NULL, -1, "s", uuid);
}
*/
static void
cb_remove(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Remove");
}
void
bz_obj_remove(Obj *o)
{
if (o->adapter)
{
Obj *adapter = bz_obj_find(o->adapter);
if (adapter)
{
if (!adapter->proxy) return;
eldbus_proxy_call(adapter->proxy, "RemoveDevice",
cb_remove, adapter, -1,
"o", o->path);
}
}
}
void
bz_obj_ref(Obj *o)
{
o->ref++;
}
void
bz_obj_unref(Obj *o)
{
o->ref--;
if (o->ref > 0) return;
if (o->in_table)
{
o->in_table = EINA_FALSE;
eina_hash_del(obj_table, o->path, o);
}
_obj_clear(o);
if (o->prop_sig)
{
eldbus_signal_handler_del(o->prop_sig);
o->prop_sig = NULL;
}
if (o->proxy)
{
eldbus_proxy_unref(o->proxy);
o->proxy = NULL;
}
if (o->prop_proxy)
{
eldbus_proxy_unref(o->prop_proxy);
o->prop_proxy = NULL;
}
if (o->path)
{
eina_stringshare_del(o->path);
o->path = NULL;
}
if (o->agent_request)
{
eina_stringshare_del(o->agent_request);
o->agent_request = NULL;
}
if (o->agent_msg_err)
{
bz_agent_msg_drop(o->agent_msg_err);
o->agent_msg_err = NULL;
}
if (o->agent_msg_ok)
{
bz_agent_msg_drop(o->agent_msg_ok);
o->agent_msg_ok = NULL;
}
free(o);
}
static void
cb_discovery_start(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Discovery Start");
}
void
bz_obj_discover_start(Obj *o)
{
if (!o->proxy) return;
eldbus_proxy_call
(o->proxy, "StartDiscovery", cb_discovery_start, o, -1, "");
}
static void
cb_discovery_stop(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
{
ERR_PRINT("Discovery Stop");
}
void
bz_obj_discover_stop(Obj *o)
{
if (!o->proxy) return;
eldbus_proxy_call
(o->proxy, "StopDiscovery", cb_discovery_stop, o, -1, "");
}
void
bz_obj_agent_request(Obj *o, const char *req, void (*fn) (Eldbus_Message *msg, const char *str), Eldbus_Message *msg_ok, Eldbus_Message *msg_err)
{
if (o->agent_msg_ok) bz_agent_msg_drop(o->agent_msg_ok);
if (o->agent_msg_err) bz_agent_msg_reply(o->agent_msg_err);
o->agent_msg_ok = msg_ok;
o->agent_msg_err = msg_err;
o->agent_entry_fn = fn;
o->agent_alert = EINA_TRUE;
eina_stringshare_replace(&(o->agent_request), req);
bz_obj_ref(o);
if (o->fn_change) o->fn_change(o);
bz_obj_unref(o);
}
static void
cb_obj_add(void *data EINA_UNUSED, const Eldbus_Message *msg)
{
const char *path = NULL;
if (!eldbus_message_arguments_get(msg, "o", &path)) return;
if (bz_obj_find(path)) return;
bz_obj_add(path);
}
static void
cb_obj_del(void *data EINA_UNUSED, const Eldbus_Message *msg)
{
Obj *o;
const char *path = NULL;
if (!eldbus_message_arguments_get(msg, "o", &path)) return;
o = bz_obj_find(path);
if (o)
{
bz_obj_ref(o);
if (o->fn_del) o->fn_del(o);
bz_obj_unref(o);
bz_obj_unref(o);
}
}
static void
cb_getobj(void *data EINA_UNUSED, const Eldbus_Message *msg,
Eldbus_Pending *pending EINA_UNUSED)
{
Eldbus_Message_Iter *prop, *dict;
pend_getobj = NULL;
ERR_PRINT("Get Objects");
if (eldbus_message_arguments_get(msg, "a{oa{sa{sv}}}", &prop))
{
while (eldbus_message_iter_get_and_next(prop, 'e', &dict))
{
const char *path;
path = NULL;
if (!eldbus_message_iter_arguments_get(dict, "o", &path))
{
return;
}
bz_obj_add(path);
}
}
}
static void
_obj_hash_free(Obj *o)
{
o->in_table = 0;
bz_obj_unref(o);
}
void
bz_obj_init(void)
{
Eldbus_Object *obj;
obj_table = eina_hash_string_superfast_new((void *)_obj_hash_free);
obj = eldbus_object_get(bz_conn, "org.bluez", "/");
objman_proxy = eldbus_proxy_get(obj, "org.freedesktop.DBus.ObjectManager");
sig_ifadd = eldbus_proxy_signal_handler_add(objman_proxy, "InterfacesAdded",
cb_obj_add, NULL);
sig_ifdel = eldbus_proxy_signal_handler_add(objman_proxy, "InterfacesRemoved",
cb_obj_del, NULL);
pend_getobj = eldbus_proxy_call(objman_proxy, "GetManagedObjects",
cb_getobj, NULL, -1, "");
}
void
bz_obj_shutdown(void)
{
eina_hash_free(obj_table);
obj_table = NULL;
if (pend_getobj)
{
eldbus_pending_cancel(pend_getobj);
pend_getobj = NULL;
}
if (sig_ifadd)
{
eldbus_signal_handler_del(sig_ifadd);
sig_ifadd = NULL;
}
if (sig_ifdel)
{
eldbus_signal_handler_del(sig_ifdel);
sig_ifdel = NULL;
}
eldbus_proxy_unref(objman_proxy);
objman_proxy = NULL;
}
void
bz_obj_add_func_set(void (*fn) (Obj *o))
{
fn_obj_add = fn;
}

Binary file not shown.

View File

@ -0,0 +1,143 @@
#include "e_mod_main.h"
/////////////////////////////////////////////////////////////////////////////
static void
cb_get_pass(Eldbus_Message *msg, const char *str)
{
if (!str) return;
bz_agent_msg_str_add(msg, str);
}
static void
cb_get_pin(Eldbus_Message *msg, const char *str)
{
unsigned int pin;
if (!str) return;
pin = atoi(str);
bz_agent_msg_u32_add(msg, pin);
}
void
ebluez5_agent_agent_release(void)
{
// just debugging
printf("BZ5 Agent Release\n");
}
void
ebluez5_agent_agent_cancel(void)
{
// just debugging
printf("BZ5 Agent Cancel\n");
}
void
ebluez5_agent_agent_req_pin(Eldbus_Message *msg)
{
const char *path;
Obj *o;
if (!(path = bz_agent_msg_path(msg))) goto error;
if (!(o = bz_obj_find(path))) goto error;
bz_obj_agent_request(o, _("Supply PIN"), cb_get_pass,
bz_agent_msg_ok(msg), bz_agent_msg_err(msg));
return;
error:
bz_agent_msg_reply(bz_agent_msg_err(msg));
}
void
ebluez5_agent_agent_disp_pin(Eldbus_Message *msg)
{
const char *path, *s = "";
Obj *o;
char buf[1024];
if (!(path = bz_agent_msg_path_str(msg, &s))) goto error;
if (!(o = bz_obj_find(path))) goto error;
snprintf(buf, sizeof(buf), _("Pair? PIN: <hilight>%s</hilight>"), s);
bz_obj_agent_request(o, buf, NULL,
bz_agent_msg_ok(msg), bz_agent_msg_err(msg));
return;
error:
bz_agent_msg_reply(bz_agent_msg_err(msg));
}
void
ebluez5_agent_req_pass(Eldbus_Message *msg)
{
const char *path;
Obj *o;
if (!(path = bz_agent_msg_path(msg))) goto error;
if (!(o = bz_obj_find(path))) goto error;
bz_obj_agent_request(o, _("Enter PIN"), cb_get_pin,
bz_agent_msg_ok(msg), bz_agent_msg_err(msg));
return;
error:
bz_agent_msg_reply(bz_agent_msg_err(msg));
}
void
ebluez5_agent_disp_pass(Eldbus_Message *msg)
{
const char *path;
unsigned int pin = 0;
unsigned short entered = 0;
Obj *o;
char buf[1024];
if (!(path = bz_agent_msg_path_u32_u16(msg, &pin, &entered))) goto error;
if (!(o = bz_obj_find(path))) goto error;
snprintf(buf, sizeof(buf), _("Pair? PIN: <hilight>%06u</hilight>"), pin);
bz_obj_agent_request(o, buf, NULL,
bz_agent_msg_ok(msg), bz_agent_msg_err(msg));
return;
error:
bz_agent_msg_reply(bz_agent_msg_err(msg));
}
void
ebluez5_agent_req_confirm(Eldbus_Message *msg)
{
const char *path;
unsigned int pin = 0;
Obj *o;
char buf[1024];
if (!(path = bz_agent_msg_path_u32(msg, &pin))) goto error;
if (!(o = bz_obj_find(path))) goto error;
snprintf(buf, sizeof(buf), _("Pair? PIN: <hilight>%06u</hilight>"), pin);
bz_obj_agent_request(o, buf, NULL,
bz_agent_msg_ok(msg), bz_agent_msg_err(msg));
return;
error:
bz_agent_msg_reply(bz_agent_msg_err(msg));
}
void
ebluez5_agent_req_auth(Eldbus_Message *msg)
{
const char *path;
Obj *o;
if (!(path = bz_agent_msg_path(msg))) goto error;
if (!(o = bz_obj_find(path))) goto error;
bz_obj_agent_request(o, _("Connect?"), NULL,
bz_agent_msg_ok(msg), bz_agent_msg_err(msg));
return;
error:
bz_agent_msg_reply(bz_agent_msg_err(msg));
}
void
ebluez5_agent_auth_service(Eldbus_Message *msg)
{
// if "ask for service" on then ask, otherwise always auth
// always auth:
// if (!(path = bz_agent_msg_path_str(msg, &s))) goto error;
Eldbus_Message *ok;
ok = bz_agent_msg_ok(msg);
bz_agent_msg_reply(ok);
}

View File

@ -0,0 +1,305 @@
#include "e_mod_main.h"
static Eina_List *instances = NULL;
static E_Module *mod = NULL;
/* Local config */
static E_Config_DD *conf_edd = NULL;
Config *ebluez5_config = NULL;
E_API E_Module_Api e_modapi = {E_MODULE_API_VERSION, "Bluez5"};
static void
_mod_icon_set(Evas_Object *base, Eina_Bool gadget)
{
char edj_path[4096], *group;
// XXX: hack for now until we make the icon do things and have it
// in theme in efl
snprintf(edj_path, sizeof(edj_path), "%s/e-module-bluez5.edj", mod->dir);
if (1) group = "e/modules/bluez5/main";
else group = "e/modules/bluez5/inactive";
if (!e_theme_edje_object_set(base, "base/theme/modules/bluez5", group))
{
if (gadget)
elm_layout_file_set(base, edj_path, group);
else
edje_object_file_set(base, edj_path, group);
}
}
/////////////////////////////////////////////////////////////////////////////
static void
_gad_popup_dismiss(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
{
Instance *inst = data;
E_FREE_FUNC(obj, evas_object_del);
inst->pop = NULL;
}
static void
_gad_popup_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Instance *inst = data;
inst->pop = NULL;
}
static void
_gad_popup_do(Instance *inst)
{
Evas_Object *o;
if (inst->pop) return;
inst->pop = o = elm_ctxpopup_add(e_comp->elm);
elm_object_style_set(o, "noblock");
evas_object_smart_callback_add(o, "dismissed", _gad_popup_dismiss, inst);
evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _gad_popup_del, inst);
inst->popcontent = o = ebluez5_popup_content_add(e_comp->elm, inst);
elm_object_content_set(inst->pop, o);
evas_object_show(o);
e_gadget_util_ctxpopup_place(inst->o_bluez5, inst->pop, inst->o_bluez5);
evas_object_show(inst->pop);
}
static void
_gad_mouse_down(void *data, Evas *evas EINA_UNUSED,
Evas_Object *obj EINA_UNUSED, void *event)
{
Instance *inst = data;
Evas_Event_Mouse_Down *ev = event;
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
if (ev->button != 1) return;
if (!inst->pop) _gad_popup_do(inst);
else elm_ctxpopup_dismiss(inst->pop);
}
static void
_gad_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Instance *inst = data;
instances = eina_list_remove(instances, inst);
E_FREE(inst);
}
/* XXX: fill in later when we have gotten this far
static Evas_Object *
_gad_config(Evas_Object *g EINA_UNUSED)
{
if (e_configure_registry_exists("extensions/bluez5"))
e_configure_registry_call("extensions/bluez5", NULL, NULL);
return NULL;
}
*/
static Evas_Object *
_gad_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient)
{
Evas_Object *o;
Instance *inst = E_NEW(Instance, 1);
if (!inst) return NULL;
inst->id = *id;
inst->orient = orient;
inst->o_bluez5 = o = elm_layout_add(parent);
_mod_icon_set(o, EINA_TRUE);
evas_object_size_hint_aspect_set(o, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
// XXX: fill in later when we have gotten this far
// e_gadget_configure_cb_set(o, _gad_config);
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _gad_mouse_down, inst);
if (*id != -1)
evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _gad_del, inst);
instances = eina_list_append(instances, inst);
return o;
}
/////////////////////////////////////////////////////////////////////////////
static void
_popup_del(Instance *inst)
{
E_FREE_FUNC(inst->popup, e_object_del);
}
static void
_popup_del_cb(void *obj)
{
_popup_del(e_object_data_get(obj));
}
static void
_popup_comp_del_cb(void *data, Evas_Object *obj EINA_UNUSED)
{
_popup_del(data);
}
static void
_popup_new(Instance *inst)
{
inst->popup = e_gadcon_popup_new(inst->gcc, 0);
e_gadcon_popup_content_set(inst->popup, ebluez5_popup_content_add(e_comp->elm, inst));
e_comp_object_util_autoclose(inst->popup->comp_object, _popup_comp_del_cb, NULL, inst);
e_gadcon_popup_show(inst->popup);
e_object_data_set(E_OBJECT(inst->popup), inst);
E_OBJECT_DEL_SET(inst->popup, _popup_del_cb);
}
static void
_ebluez5_cb_mouse_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
{
Instance *inst = data;
Evas_Event_Mouse_Down *ev = event;
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
if (ev->button != 1) return;
if (!inst->popup) _popup_new(inst);
else _popup_del(inst);
}
static E_Gadcon_Client *
_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
{
Evas_Object *o;
Instance *inst = E_NEW(Instance, 1);
if (!inst) return NULL;
inst->o_bluez5 = o = edje_object_add(gc->evas);
_mod_icon_set(o, EINA_FALSE);
inst->gcc = e_gadcon_client_new(gc, name, id, style, o);
inst->gcc->data = inst;
e_gadcon_client_util_menu_attach(inst->gcc);
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _ebluez5_cb_mouse_down, inst);
instances = eina_list_append(instances, inst);
return inst->gcc;
}
static void
_gc_shutdown(E_Gadcon_Client *gcc)
{
Instance *inst = gcc->data;;
if (!inst) return;
instances = eina_list_remove(instances, inst);
_popup_del(inst);
E_FREE_FUNC(inst->o_bluez5, evas_object_del);
E_FREE(inst);
}
static const char *
_gc_id_new(const E_Gadcon_Client_Class *client_class EINA_UNUSED)
{
static char tmpbuf[128];
snprintf(tmpbuf, sizeof(tmpbuf), "bluez5.%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 _("Bluez5");
}
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-bluez5.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, "bluez5",
{_gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL, NULL},
E_GADCON_CLIENT_STYLE_PLAIN
};
/////////////////////////////////////////////////////////////////////////////
void
ebluez5_popups_show(void)
{
Eina_List *l;
Instance *inst;
EINA_LIST_FOREACH(instances, l, inst)
{
if (inst->gcc)
{
if (!inst->popup) _popup_new(inst);
}
else
{
if (!inst->pop) _gad_popup_do(inst);
}
}
}
/////////////////////////////////////////////////////////////////////////////
/* Module Functions */
E_API void *
e_modapi_init(E_Module *m)
{
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);
ebluez5_config = e_config_domain_load("module.ebluez5", conf_edd);
if (!ebluez5_config) ebluez5_config = E_NEW(Config, 1);
ebluze5_popup_init();
bz_init();
e_gadcon_provider_register(&_gc_class);
e_gadget_type_add("Bluetooth", _gad_create, NULL);
return m;
}
E_API int
e_modapi_shutdown(E_Module *m EINA_UNUSED)
{
E_CONFIG_DD_FREE(conf_edd);
eina_stringshare_del(ebluez5_config->lock_dev_addr);
eina_stringshare_del(ebluez5_config->unlock_dev_addr);
free(ebluez5_config);
ebluez5_config = NULL;
bz_shutdown();
ebluze5_popup_shutdown();
e_gadget_type_del("Bluetooth");
e_gadcon_provider_unregister(&_gc_class);
return 1;
}
E_API int
e_modapi_save(E_Module *m EINA_UNUSED)
{
e_config_domain_save("module.ebluez5", conf_edd, ebluez5_config);
return 1;
}

View File

@ -0,0 +1,68 @@
#ifndef E_MOD_MAIN_H
#define E_MOD_MAIN_H
#include <e.h>
#include "bz.h"
typedef struct _Instance Instance;
struct _Instance
{
// common info
Evas_Object *o_bluez5;
// e_gadcon info
E_Gadcon_Client *gcc;
E_Gadcon_Popup *popup;
// e_gadget info
Evas_Object *pop;
Evas_Object *popcontent;
int id;
E_Gadget_Site_Orient orient;
};
typedef struct _Config Config;
struct _Config
{
const char *lock_dev_addr;
const char *unlock_dev_addr;
};
extern Config *ebluez5_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 ebluez5_popups_show(void);
void ebluez5_popup_hide(Instance *inst);
Evas_Object *ebluez5_popup_content_add(Evas_Object *base, Instance *inst);
void ebluze5_popup_init(void);
void ebluze5_popup_shutdown(void);
void ebluze5_popup_clear(void);
void ebluez5_popup_adapter_add(Obj *o);
void ebluez5_popup_adapter_del(Obj *o);
void ebluez5_popup_adapter_change(Obj *o);
void ebluez5_popup_device_add(Obj *o);
void ebluez5_popup_device_del(Obj *o);
void ebluez5_popup_device_change(Obj *o);
void ebluez5_agent_agent_release(void);
void ebluez5_agent_agent_cancel(void);
void ebluez5_agent_agent_req_pin(Eldbus_Message *msg);
void ebluez5_agent_agent_disp_pin(Eldbus_Message *msg);
void ebluez5_agent_req_pass(Eldbus_Message *msg);
void ebluez5_agent_disp_pass(Eldbus_Message *msg);
void ebluez5_agent_req_confirm(Eldbus_Message *msg);
void ebluez5_agent_req_auth(Eldbus_Message *msg);
void ebluez5_agent_auth_service(Eldbus_Message *msg);
Evas_Object *util_obj_icon_add(Evas_Object *base, Obj *o, int size);
Evas_Object *util_obj_icon_rssi_add(Evas_Object *base, Obj *o, int size);
Evas_Object *util_check_add(Evas_Object *base, const char *text, const char *tip, Eina_Bool state);
Evas_Object *util_button_icon_add(Evas_Object *base, const char *icon, const char *tip);
const char *util_obj_name_get(Obj *o);
#endif

View File

@ -0,0 +1,714 @@
#include "e_mod_main.h"
static Elm_Genlist_Item_Class *adapt_itc = NULL;
static Elm_Genlist_Item_Class *dev_itc = NULL;
static Elm_Genlist_Item_Class *group_itc = NULL;
static Eina_List *lists = NULL;
static Eina_List *adapters = NULL;
static Eina_List *devices = NULL;
static void
_adapter_add(Evas_Object *gl, Obj *o)
{
Elm_Object_Item *it = evas_object_data_get(gl, "adapters_item");;
elm_genlist_item_append(gl, adapt_itc, o, it, ELM_GENLIST_ITEM_NONE,
NULL, NULL);
}
static int
_cb_insert_cmp(const void *ai, const void *bi)
{
Obj *a = elm_object_item_data_get(ai);
Obj *b = elm_object_item_data_get(bi);
Eina_Bool apub = EINA_FALSE, bpub = EINA_FALSE;
if ((!a) || (!a->address)) return -1;
if ((!b) || (!b->address)) return 1;
// prefer paired at top
if ((a->paired) && (!b->paired)) return -1;
if ((!a->paired) && (b->paired)) return 1;
// prefer public addresses next after being paired
if ((a->address_type) && (!strcmp(a->address_type, "public")))
apub = EINA_TRUE;
if ((b->address_type) && (!strcmp(b->address_type, "public")))
bpub = EINA_TRUE;
if ((apub) && (!bpub)) return -1;
if ((!apub) && (bpub)) return 1;
// and sort by address
return strcmp(a->address, b->address);
}
static void
_device_add(Evas_Object *gl, Obj *o)
{
Elm_Object_Item *it = evas_object_data_get(gl, "devices_item");;
elm_genlist_item_sorted_insert(gl, dev_itc, o, it, ELM_GENLIST_ITEM_NONE,
_cb_insert_cmp, NULL, NULL);
}
static void
_cb_power(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Obj *o = data;
if (elm_check_state_get(obj)) bz_obj_power_on(o);
else bz_obj_power_off(o);
}
static void
_cb_scan(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Obj *o = data;
if (elm_check_state_get(obj)) bz_obj_discover_start(o);
else bz_obj_discover_stop(o);
}
static void
_cb_visible(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Obj *o = data;
if (elm_check_state_get(obj)) bz_obj_discoverable(o);
else bz_obj_undiscoverable(o);
}
static void
_cb_pairable(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Obj *o = data;
if (elm_check_state_get(obj)) bz_obj_pairable(o);
else bz_obj_unpairable(o);
}
static void
_cb_connect(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Obj *o = data;
bz_obj_connect(o);
}
static void
_cb_disconnect(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Obj *o = data;
bz_obj_disconnect(o);
}
static void
_cb_trust(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Obj *o = data;
bz_obj_trust(o);
}
static void
_cb_distrust(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Obj *o = data;
bz_obj_distrust(o);
}
static void
_cb_pair(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Obj *o = data;
bz_obj_pair(o);
}
static void
_cb_unpair(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Obj *o = data;
bz_obj_remove(o);
}
static void
_agent_done(Obj *o)
{
Eina_List *l;
Evas_Object *gl;
Elm_Object_Item *it;
if (o->agent_request)
{
eina_stringshare_del(o->agent_request);
o->agent_request = NULL;
}
EINA_LIST_FOREACH(lists, l, gl)
{
for (it = elm_genlist_first_item_get(gl); it;
it = elm_genlist_item_next_get(it))
{
if (o == elm_object_item_data_get(it))
{
elm_genlist_item_update(it);
break;
}
}
}
}
static void
_cb_agent_ok(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
{
Obj *o = data;
if ((o->agent_entry_fn) && (o->agent_msg_ok))
{
Evas_Object *en = evas_object_data_get(obj, "entry");
if (en)
{
const char *s = elm_object_text_get(en);
if (s) o->agent_entry_fn(o->agent_msg_ok, s);
}
}
if (o->agent_msg_err)
{
bz_agent_msg_drop(o->agent_msg_err);
o->agent_msg_err = NULL;
}
if (o->agent_msg_ok)
{
bz_agent_msg_reply(o->agent_msg_ok);
o->agent_msg_ok = NULL;
}
_agent_done(o);
}
static void
_cb_agent_cancel(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Obj *o = data;
if (o->agent_msg_ok)
{
bz_agent_msg_drop(o->agent_msg_ok);
o->agent_msg_ok = NULL;
}
if (o->agent_msg_err)
{
bz_agent_msg_reply(o->agent_msg_err);
o->agent_msg_err = NULL;
}
_agent_done(o);
}
static char *
_cb_group_text_get(void *data, Evas_Object *obj EINA_UNUSED,
const char *part EINA_UNUSED)
{
if (!data) return strdup(_("Adapters"));
return strdup(_("Devices"));
}
static Evas_Object *
_cb_group_content_get(void *data EINA_UNUSED, Evas_Object *obj,
const char *part EINA_UNUSED)
{
if (!strcmp(part, "elm.swallow.icon"))
{
Evas_Object *ic = elm_icon_add(obj);
if (!data)
elm_icon_standard_set(ic, "computer");
else
elm_icon_standard_set(ic, "system-run");
evas_object_size_hint_min_set(ic,
ELM_SCALE_SIZE(16),
ELM_SCALE_SIZE(16));
return ic;
}
return NULL;
}
static char *
_cb_adapt_text_get(void *data, Evas_Object *obj EINA_UNUSED,
const char *part EINA_UNUSED)
{
Obj *o = data;
if (!strcmp(part, "elm.text"))
{
return strdup(util_obj_name_get(o));
}
else if (!strcmp(part, "elm.text.sub"))
{
if (o->address) return strdup(o->address);
return strdup(_("Unknown Address"));
}
return NULL;
}
static Evas_Object *
_cb_adapt_content_get(void *data EINA_UNUSED, Evas_Object *obj,
const char *part EINA_UNUSED)
{
Obj *o = data;
if (!strcmp(part, "elm.swallow.icon"))
{
return util_obj_icon_add(obj, o, 48);
}
else if (!strcmp(part, "elm.swallow.end"))
{
Evas_Object *tab, *ck;
tab = elm_table_add(obj);
evas_object_size_hint_weight_set(tab, EVAS_HINT_EXPAND, 0);
evas_object_size_hint_align_set(tab, EVAS_HINT_FILL, 0.0);
ck = util_check_add(obj, _("Power"), _("Enable power for this adapter"),
o->powered);
evas_object_smart_callback_add(ck, "changed", _cb_power, o);
elm_table_pack(tab, ck, 0, 0, 1, 1);
evas_object_show(ck);
ck = util_check_add(obj, _("Visible"), _("Make this adapter visible to other devices"),
o->discoverable);
evas_object_smart_callback_add(ck, "changed", _cb_visible, o);
elm_table_pack(tab, ck, 1, 0, 1, 1);
evas_object_show(ck);
ck = util_check_add(obj, _("Scan"), _("Scan for other devices"),
o->discovering);
evas_object_smart_callback_add(ck, "changed", _cb_scan, o);
elm_table_pack(tab, ck, 0, 1, 1, 1);
evas_object_show(ck);
ck = util_check_add(obj, _("Pairable"), _("Allow this adapter to have other devices request to pair with it"),
o->pairable);
evas_object_smart_callback_add(ck, "changed", _cb_pairable, o);
elm_table_pack(tab, ck, 1, 1, 1, 1);
evas_object_show(ck);
return tab;
}
return NULL;
}
static char *
_cb_dev_text_get(void *data, Evas_Object *obj EINA_UNUSED,
const char *part EINA_UNUSED)
{
Obj *o = data;
return strdup(util_obj_name_get(o));
}
static Evas_Object *
_cb_dev_content_get(void *data EINA_UNUSED, Evas_Object *obj,
const char *part EINA_UNUSED)
{
Obj *o = data;
char buf[512];
if (!strcmp(part, "elm.swallow.icon"))
{
Evas_Object *ic, *bx;
bx = elm_box_add(obj);
ic = util_obj_icon_add(obj, o, 24);
snprintf(buf, sizeof(buf),
_("Address: %s (%s)<br>"
"Services: %s%s%s%s%s%s%s%s%s<br>"
"Trusted: %s<br>"
"Blocked: %s<br>"
)
,
(o->address) ? o->address : _("Unknown"),
(o->address_type) ? o->address_type : _("Unknown"),
(o->klass & BZ_OBJ_CLASS_SERVICE_LIMITED_DISCOVERABLE) ? _("Limited-Discoverable ") : "",
(o->klass & BZ_OBJ_CLASS_SERVICE_POSITIONING_BIT) ? _("Positioning ") : "",
(o->klass & BZ_OBJ_CLASS_SERVICE_NETWORKING_BIT) ? _("Networking ") : "",
(o->klass & BZ_OBJ_CLASS_SERVICE_RENDERING_BIT) ? _("Rendering ") : "",
(o->klass & BZ_OBJ_CLASS_SERVICE_CAPTURING_BIT) ? _("Capture ") : "",
(o->klass & BZ_OBJ_CLASS_SERVICE_OBJECT_TRANSFER_BIT) ? _("OBEX ") : "",
(o->klass & BZ_OBJ_CLASS_SERVICE_AUDIO_BIT) ? _("Audio ") : "",
(o->klass & BZ_OBJ_CLASS_SERVICE_TELEPHONY_BIT) ? _("Telephony ") : "",
(o->klass & BZ_OBJ_CLASS_SERVICE_INFORMATION_BIT) ? _("Information ") : "",
(o->trusted) ? _("Yes") : _("No"),
(o->blocked) ? _("Yes") : _("No")
);
elm_object_tooltip_text_set(ic, buf);
elm_box_pack_end(bx, ic);
evas_object_show(ic);
return bx;
}
else if (!strcmp(part, "elm.swallow.end"))
{
Evas_Object *bx, *ic, *bt, *lb, *tb, *en, *rec;
bx = elm_box_add(obj);
elm_box_horizontal_set(bx, EINA_TRUE);
if (o->paired)
{
if (o->connected)
{
bt = util_button_icon_add(obj, "network-offline",
_("Disconnect this device"));
evas_object_smart_callback_add(bt, "clicked", _cb_disconnect, o);
}
else
{
bt = util_button_icon_add(obj, "network-transmit-receive",
_("Connect this device"));
evas_object_smart_callback_add(bt, "clicked", _cb_connect, o);
}
elm_box_pack_end(bx, bt);
evas_object_show(bt);
if (o->trusted)
{
bt = util_button_icon_add(obj, "security-low",
_("Disrust this device"));
evas_object_smart_callback_add(bt, "clicked", _cb_distrust, o);
}
else
{
bt = util_button_icon_add(obj, "security-high",
_("Trust this device"));
evas_object_smart_callback_add(bt, "clicked", _cb_trust, o);
}
elm_box_pack_end(bx, bt);
evas_object_show(bt);
}
if (!o->paired)
{
if (o->agent_request)
{
if (o->agent_entry_fn)
{
tb = elm_table_add(obj);
rec = evas_object_rectangle_add(evas_object_evas_get(obj));
evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(80), ELM_SCALE_SIZE(1));
elm_table_pack(tb, rec, 0, 0, 1, 1);
en = elm_entry_add(obj);
elm_entry_single_line_set(en, EINA_TRUE);
elm_entry_scrollable_set(en, EINA_TRUE);
elm_scroller_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
elm_object_part_text_set(en, "guide", o->agent_request);
// elm_entry_password_set(en, EINA_TRUE);
evas_object_smart_callback_add(en, "activated", _cb_agent_ok, o);
evas_object_smart_callback_add(en, "aborted", _cb_agent_cancel, o);
elm_table_pack(tb, en, 0, 0, 1, 1);
evas_object_show(en);
elm_box_pack_end(bx, tb);
evas_object_show(tb);
bt = util_button_icon_add(obj, "list-add",
_("Pair with this device"));
evas_object_data_set(bt, "entry", en);
evas_object_smart_callback_add(bt, "clicked", _cb_agent_ok, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
bt = util_button_icon_add(obj, "list-remove",
_("Reject pairing"));
evas_object_smart_callback_add(bt, "clicked", _cb_agent_cancel, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
}
else
{
lb = elm_label_add(obj);
elm_layout_text_set(lb, NULL, o->agent_request);
elm_box_pack_end(bx, lb);
evas_object_show(lb);
bt = util_button_icon_add(obj, "list-add",
_("Pair with this device"));
evas_object_smart_callback_add(bt, "clicked", _cb_agent_ok, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
bt = util_button_icon_add(obj, "list-remove",
_("Reject pairing"));
evas_object_smart_callback_add(bt, "clicked", _cb_agent_cancel, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
}
}
else
{
bt = util_button_icon_add(obj, "list-add",
_("Pair with this device"));
evas_object_smart_callback_add(bt, "clicked", _cb_pair, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
}
}
else
{
bt = util_button_icon_add(obj, "list-remove",
_("Unpair with this device"));
evas_object_smart_callback_add(bt, "clicked", _cb_unpair, o);
elm_box_pack_end(bx, bt);
evas_object_show(bt);
}
ic = util_obj_icon_rssi_add(obj, o, 24);
elm_box_pack_end(bx, ic);
evas_object_show(ic);
return bx;
}
return NULL;
}
static void
_cb_list_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
lists = eina_list_remove(lists, obj);
}
/*
static void
_cb_settings(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Instance *inst = data;
ebluez5_popup_hide(inst);
}
*/
Evas_Object *
ebluez5_popup_content_add(Evas_Object *base, Instance *inst)
{
Evas_Object *o, *box, *tab, *gl;
Eina_List *l;
Elm_Object_Item *it;
Obj *oo;
o = box = elm_box_add(base);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
tab = o = elm_table_add(base);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
o = evas_object_rectangle_add(evas_object_evas_get(base));
evas_object_size_hint_min_set(o, ELM_SCALE_SIZE(320), ELM_SCALE_SIZE(240));
evas_object_size_hint_max_set(o, ELM_SCALE_SIZE(560), ELM_SCALE_SIZE(400));
elm_table_pack(tab, o, 0, 0, 1, 1);
o = gl = elm_genlist_add(base);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_genlist_mode_set(o, ELM_LIST_LIMIT);
elm_genlist_select_mode_set(o, ELM_OBJECT_SELECT_MODE_NONE);
lists = eina_list_append(lists, gl);
evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _cb_list_del, inst);
it = elm_genlist_item_append(gl, group_itc, NULL, NULL,
ELM_GENLIST_ITEM_GROUP, NULL, NULL);
evas_object_data_set(gl, "adapters_item", it);
it = elm_genlist_item_append(gl, group_itc, gl, NULL,
ELM_GENLIST_ITEM_GROUP, NULL, NULL);
evas_object_data_set(gl, "devices_item", it);
EINA_LIST_FOREACH(adapters, l, oo)
{
_adapter_add(gl, oo);
}
EINA_LIST_FOREACH(devices, l, oo)
{
_device_add(gl, oo);
}
elm_table_pack(tab, o, 0, 0, 1, 1);
evas_object_show(o);
elm_box_pack_end(box, tab);
evas_object_show(tab);
/*
o = elm_separator_add(base);
elm_separator_horizontal_set(o, EINA_TRUE);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_box_pack_end(box, o);
evas_object_show(o);
o = elm_button_add(base);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_layout_text_set(o, NULL, _("Settings"));
elm_object_tooltip_text_set(o, _("Bring up more detailed Bluetooth settings"));
evas_object_smart_callback_add(o, "clicked", _cb_settings, inst);
elm_box_pack_end(box, o);
evas_object_show(o);
*/
return box;
}
void
ebluze5_popup_init(void)
{
adapt_itc = elm_genlist_item_class_new();
adapt_itc->item_style = "double_label";
adapt_itc->func.text_get = _cb_adapt_text_get;
adapt_itc->func.content_get = _cb_adapt_content_get;
adapt_itc->func.state_get = NULL;
adapt_itc->func.del = NULL;
dev_itc = elm_genlist_item_class_new();
dev_itc->item_style = "default";
dev_itc->func.text_get = _cb_dev_text_get;
dev_itc->func.content_get = _cb_dev_content_get;
dev_itc->func.state_get = NULL;
dev_itc->func.del = NULL;
group_itc = elm_genlist_item_class_new();
group_itc->item_style = "group_index";
group_itc->func.text_get = _cb_group_text_get;
group_itc->func.content_get = _cb_group_content_get;
group_itc->func.state_get = NULL;
group_itc->func.del = NULL;
}
void
ebluze5_popup_shutdown(void)
{
ebluze5_popup_clear();
elm_genlist_item_class_free(group_itc);
elm_genlist_item_class_free(dev_itc);
elm_genlist_item_class_free(adapt_itc);
group_itc = NULL;
dev_itc = NULL;
adapt_itc = NULL;
}
void
ebluze5_popup_clear(void)
{
Eina_List *l;
Evas_Object *gl;
adapters = eina_list_free(adapters);
devices = eina_list_free(devices);
EINA_LIST_FOREACH(lists, l, gl)
{
elm_genlist_clear(gl);
}
}
void
ebluez5_popup_adapter_add(Obj *o)
{
Eina_List *l;
Evas_Object *gl;
adapters = eina_list_append(adapters, o);
EINA_LIST_FOREACH(lists, l, gl)
{
_adapter_add(gl, o);
}
}
void
ebluez5_popup_adapter_del(Obj *o)
{
Eina_List *l;
Evas_Object *gl;
Elm_Object_Item *it;
EINA_LIST_FOREACH(lists, l, gl)
{
for (it = elm_genlist_first_item_get(gl); it;
it = elm_genlist_item_next_get(it))
{
if (o == elm_object_item_data_get(it))
{
elm_object_item_del(it);
break;
}
}
}
adapters = eina_list_remove(adapters, o);
}
void
ebluez5_popup_adapter_change(Obj *o)
{
Eina_List *l;
Evas_Object *gl;
Elm_Object_Item *it;
EINA_LIST_FOREACH(lists, l, gl)
{
for (it = elm_genlist_first_item_get(gl); it;
it = elm_genlist_item_next_get(it))
{
if (o == elm_object_item_data_get(it))
{
elm_genlist_item_update(it);
break;
}
}
}
}
void
ebluez5_popup_device_add(Obj *o)
{
Eina_List *l;
Evas_Object *gl;
devices = eina_list_append(devices, o);
EINA_LIST_FOREACH(lists, l, gl)
{
_device_add(gl, o);
}
}
void
ebluez5_popup_device_del(Obj *o)
{
Eina_List *l;
Evas_Object *gl;
Elm_Object_Item *it;
EINA_LIST_FOREACH(lists, l, gl)
{
for (it = elm_genlist_first_item_get(gl); it;
it = elm_genlist_item_next_get(it))
{
if (o == elm_object_item_data_get(it))
{
elm_object_item_del(it);
break;
}
}
}
devices = eina_list_remove(devices, o);
}
void
ebluez5_popup_device_change(Obj *o)
{
Eina_List *l;
Evas_Object *gl;
Elm_Object_Item *it;
Eina_Bool alert = EINA_FALSE;
if (o->agent_alert)
{
alert = EINA_TRUE;
o->agent_alert = EINA_FALSE;
if (!lists) ebluez5_popups_show();
}
EINA_LIST_FOREACH(lists, l, gl)
{
for (it = elm_genlist_first_item_get(gl); it;
it = elm_genlist_item_next_get(it))
{
if (o == elm_object_item_data_get(it))
{
elm_genlist_item_update(it);
if (alert)
elm_genlist_item_show(it, ELM_GENLIST_ITEM_SCROLLTO_MIDDLE);
break;
}
}
}
}

View File

@ -0,0 +1,262 @@
#include "e_mod_main.h"
Evas_Object *
util_obj_icon_add(Evas_Object *base, Obj *o, int size)
{
Evas_Object *ic = elm_icon_add(base);
unsigned int maj, min;
const char *s ="bluetooth-active";
// XXX: replace this with a much better database...
maj = o->klass & BZ_OBJ_CLASS_MAJ_MASK;
if (maj == BZ_OBJ_CLASS_MAJ_MISC)
{
s ="bluetooth-active";
}
else if (maj == BZ_OBJ_CLASS_MAJ_COMPUTER)
{
min = o->klass & BZ_OBJ_CLASS_MIN_COMPUTER_MASK;
if (min == BZ_OBJ_CLASS_MIN_COMPUTER_DESKTOP)
s = "computer";
else if (min == BZ_OBJ_CLASS_MIN_COMPUTER_SERVER)
s = "computer";
else if (min == BZ_OBJ_CLASS_MIN_COMPUTER_LAPTOP)
s = "computer-laptop";
else if (min == BZ_OBJ_CLASS_MIN_COMPUTER_CLAMSHELL)
s = "computer-laptop";
else if (min == BZ_OBJ_CLASS_MIN_COMPUTER_PDA)
s = "pda";
else if (min == BZ_OBJ_CLASS_MIN_COMPUTER_WEARABLE)
s = "pda";
else if (min == BZ_OBJ_CLASS_MIN_COMPUTER_TABLET)
s = "pda";
}
else if (maj == BZ_OBJ_CLASS_MAJ_PHONE)
{
min = o->klass & BZ_OBJ_CLASS_MIN_PHONE_MASK;
if (min == BZ_OBJ_CLASS_MIN_PHONE_CELL)
s = "phone";
else if (min == BZ_OBJ_CLASS_MIN_PHONE_CORDLESS)
s = "phone";
else if (min == BZ_OBJ_CLASS_MIN_PHONE_SMARTPHONE)
s = "phone";
else if (min == BZ_OBJ_CLASS_MIN_PHONE_WIRED)
s = "modem";
else if (min == BZ_OBJ_CLASS_MIN_PHONE_ISDN)
s = "modem";
}
else if (maj == BZ_OBJ_CLASS_MAJ_LAN)
{
s = "network-wired";
// XXX: handle (top is max availability)
// BZ_OBJ_CLASS_MIN_LAN_AVAIL_7
// BZ_OBJ_CLASS_MIN_LAN_AVAIL_6
// BZ_OBJ_CLASS_MIN_LAN_AVAIL_5
// BZ_OBJ_CLASS_MIN_LAN_AVAIL_4
// BZ_OBJ_CLASS_MIN_LAN_AVAIL_3
// BZ_OBJ_CLASS_MIN_LAN_AVAIL_2
// BZ_OBJ_CLASS_MIN_LAN_AVAIL_1
// BZ_OBJ_CLASS_MIN_LAN_AVAIL_0
}
else if (maj == BZ_OBJ_CLASS_MAJ_AV)
{
min = o->klass & BZ_OBJ_CLASS_MIN_AV_MASK;
if (min == BZ_OBJ_CLASS_MIN_AV_WEARABLE_HEADSET)
s = "audio-input-microphone";
else if (min == BZ_OBJ_CLASS_MIN_AV_HANDS_FREE)
s = "audio-input-microphone";
else if (min == BZ_OBJ_CLASS_MIN_AV_MIC)
s = "audio-input-microphone";
else if (min == BZ_OBJ_CLASS_MIN_AV_SPEAKER)
s = "audio-volume-high";
else if (min == BZ_OBJ_CLASS_MIN_AV_HEADPHONES)
s = "audio-volume-high";
else if (min == BZ_OBJ_CLASS_MIN_AV_PORTABLE_AUDIO)
s = "audio-volume-high";
else if (min == BZ_OBJ_CLASS_MIN_AV_CAR_AUDIO)
s = "audio-volume-high";
else if (min == BZ_OBJ_CLASS_MIN_AV_SET_TOP_BOX)
s = "modem";
else if (min == BZ_OBJ_CLASS_MIN_AV_HIFI_AUDIO)
s = "audio-volume-high";
else if (min == BZ_OBJ_CLASS_MIN_AV_VCR)
s = "media-tape";
else if (min == BZ_OBJ_CLASS_MIN_AV_VIDEO_CAMERA)
s = "camera-photo";
else if (min == BZ_OBJ_CLASS_MIN_AV_CAMCORDER)
s = "camera-photo";
else if (min == BZ_OBJ_CLASS_MIN_AV_VIDEO_MONITOR)
s = "video-display";
else if (min == BZ_OBJ_CLASS_MIN_AV_VIDEO_DISPLAY_SPEAKER)
s = "video-display";
else if (min == BZ_OBJ_CLASS_MIN_AV_VIDEO_CONFERENCE)
s = "video-display";
else if (min == BZ_OBJ_CLASS_MIN_AV_GAMING)
s = "input-gaming";
}
else if (maj == BZ_OBJ_CLASS_MAJ_PERIPHERAL)
{
s = "input-keyboard";
// XXX: handle bits + ide below
if (o->klass & BZ_OBJ_CLASS_MIN_PERIPHERAL_KEYBOARD_BIT)
s = "input-keyboard";
else if (o->klass & BZ_OBJ_CLASS_MIN_PERIPHERAL_MOUSE_BIT)
s = "input-mouse";
min = o->klass & BZ_OBJ_CLASS_MIN_PERIPHERAL_MASK2;
if (min == BZ_OBJ_CLASS_MIN_PERIPHERAL_JOYSTICK)
s = "input-gaming";
else if (min == BZ_OBJ_CLASS_MIN_PERIPHERAL_GAMEPAD)
s = "input-gaming";
else if (min == BZ_OBJ_CLASS_MIN_PERIPHERAL_REMOTE)
s = "input-gaming";
else if (min == BZ_OBJ_CLASS_MIN_PERIPHERAL_SENSING)
s = "input-gaming";
else if (min == BZ_OBJ_CLASS_MIN_PERIPHERAL_DIGITIZER_TAB)
s = "input-tablet";
else if (min == BZ_OBJ_CLASS_MIN_PERIPHERAL_CARD_READER)
s = "media-flash";
else if (min == BZ_OBJ_CLASS_MIN_PERIPHERAL_PEN)
s = "input-mouse";
else if (min == BZ_OBJ_CLASS_MIN_PERIPHERAL_SCANNER)
s = "scanner";
else if (min == BZ_OBJ_CLASS_MIN_PERIPHERAL_WAND)
s = "input-mouse";
}
else if (maj == BZ_OBJ_CLASS_MAJ_IMAGING)
{
// XXX: handle permutations of bits
if (o->klass & BZ_OBJ_CLASS_MIN_IMAGING_CAMERA_BIT)
s = "camera-photo";
else if (o->klass & BZ_OBJ_CLASS_MIN_IMAGING_SCANNER_BIT)
s = "scanner";
else if (o->klass & BZ_OBJ_CLASS_MIN_IMAGING_PRINTER_BIT)
s = "printer";
}
else if (maj == BZ_OBJ_CLASS_MAJ_WEARABLE)
{
min = o->klass & BZ_OBJ_CLASS_MIN_WEARABLE_MASK;
if (min == BZ_OBJ_CLASS_MIN_WEARABLE_WATCH)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_WEARABLE_PAGER)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_WEARABLE_JACKET)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_WEARABLE_HELMET)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_WEARABLE_GLASSES)
s = "cpu";
}
else if (maj == BZ_OBJ_CLASS_MAJ_TOY)
{
min = o->klass & BZ_OBJ_CLASS_MIN_TOY_MASK;
if (min == BZ_OBJ_CLASS_MIN_TOY_ROBOT)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_TOY_VEHICLE)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_TOY_DOLL)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_TOY_CONTROLLER)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_TOY_GAME)
s = "cpu";
}
else if (maj == BZ_OBJ_CLASS_MAJ_HEALTH)
{
min = o->klass & BZ_OBJ_CLASS_MIN_HEALTH_MASK;
if (min == BZ_OBJ_CLASS_MIN_HEALTH_BLOOD_PRESSURE)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_HEALTH_THERMOMETER)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_HEALTH_SCALES)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_HEALTH_GLUCOSE)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_HEALTH_PULSE_OXIMITER)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_HEALTH_HEART_RATE)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_HEALTH_HEALTH_DATA_DISP)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_HEALTH_STEP)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_HEALTH_BODY_COMPOSITION)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_HEALTH_PEAK_FLOW)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_HEALTH_MEDICATION)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_HEALTH_KNEE_PROSTHESIS)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_HEALTH_ANKLE_PROSTHESIS)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_HEALTH_GENERIC_HEALTH)
s = "cpu";
else if (min == BZ_OBJ_CLASS_MIN_HEALTH_PRESONAL_MOBILITY)
s = "cpu";
}
elm_icon_standard_set(ic, s);
evas_object_size_hint_min_set(ic,
ELM_SCALE_SIZE(size),
ELM_SCALE_SIZE(size));
return ic;
}
Evas_Object *
util_obj_icon_rssi_add(Evas_Object *base, Obj *o, int size)
{
Evas_Object *ic = elm_icon_add(base);
char buf[64];
if (o->rssi <= -80)
elm_icon_standard_set(ic, "network-cellular-signal-excellent");
else if (o->rssi <= -72)
elm_icon_standard_set(ic, "network-cellular-signal-good");
else if (o->rssi <= -64)
elm_icon_standard_set(ic, "network-cellular-signal-ok");
else if (o->rssi <= -56)
elm_icon_standard_set(ic, "network-cellular-signal-weak");
else if (o->rssi <= -48)
elm_icon_standard_set(ic, "network-cellular-signal-none");
else
elm_icon_standard_set(ic, "network-cellular-signal-acquiring");
snprintf(buf, sizeof(buf), "RSSI: %i", (int)o->rssi);
elm_object_tooltip_text_set(ic, buf);
evas_object_size_hint_min_set(ic,
ELM_SCALE_SIZE(size),
ELM_SCALE_SIZE(size));
return ic;
}
Evas_Object *
util_check_add(Evas_Object *base, const char *text, const char *tip, Eina_Bool state)
{
Evas_Object *ck = elm_check_add(base);
evas_object_size_hint_align_set(ck, 0.0, EVAS_HINT_FILL);
elm_layout_text_set(ck, NULL, text);
elm_object_tooltip_text_set(ck, tip);
elm_check_state_set(ck, state);
return ck;
}
Evas_Object *
util_button_icon_add(Evas_Object *base, const char *icon, const char *tip)
{
Evas_Object *ic, *bt = elm_button_add(base);
ic = elm_icon_add(base);
evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_icon_standard_set(ic, icon);
elm_object_tooltip_text_set(bt, tip);
elm_object_part_content_set(bt, NULL, ic);
evas_object_show(ic);
return bt;
}
const char *
util_obj_name_get(Obj *o)
{
if (o->name) return o->name;
if (o->alias) return o->alias;
if (o->address) return o->address;
return _("Uknown");
}

View File

@ -0,0 +1,9 @@
src = files(
'e_mod_main.c',
'e_mod_popup.c',
'e_mod_agent.c',
'e_mod_util.c',
'bz.c',
'bz_obj.c',
'bz_agent.c'
)

View File

@ -0,0 +1,13 @@
[Desktop Entry]
Type=Link
Name=Bluez5
Name[ca]=Bluez5
Name[de]=Bluez5
Name[fi]=Bluez5
Name[gl]=Bluez5
Name[ja]=Bluez5
Name[ms]=Bluez5
Name[sr]=Блуез5
Name[tr]=Bluetooth
Icon=e-module-bluez5
X-Enlightenment-ModuleType=utils

View File

@ -34,6 +34,7 @@ mods = [
'geolocation', 'geolocation',
'connman', 'connman',
'bluez4', 'bluez4',
'bluez5',
'syscon', 'syscon',
'systray', 'systray',
'appmenu', 'appmenu',