diff --git a/src/bin/clouseau_client.c b/src/bin/clouseau_client.c index 62496b2..cdd965b 100644 --- a/src/bin/clouseau_client.c +++ b/src/bin/clouseau_client.c @@ -24,6 +24,8 @@ #define _EET_ENTRY "config" +#define _SNAPSHOT_EET_ENTRY "Clouseau_Snapshot" + static int _cl_stat_reg_op = EINA_DEBUG_OPCODE_INVALID; static Gui_Main_Win_Widgets *_main_widgets = NULL; @@ -74,6 +76,7 @@ struct _Extension_Config const char *lib_path; Eina_Module *module; const char *name; + const char *nickname; Ext_Start_Cb start_fn; Ext_Stop_Cb stop_fn; Eina_Bool ready : 1; @@ -84,13 +87,27 @@ typedef struct Eina_List *extensions_cfgs; } Config; +typedef struct +{ + const char *nickname; + void *data; + int data_count; + int version; +} Extension_Snapshot; + +typedef struct +{ + const char *app_name; + int app_pid; + Eina_List *ext_snapshots; /* List of Extension_Snapshot */ +} Snapshot; + static Connection_Type _conn_type = OFFLINE; static Eina_Debug_Session *_session = NULL; static Eina_List *_apps = NULL; static App_Info *_selected_app = NULL; -static Eina_Stringshare *_offline_filename = NULL; -static Eet_Data_Descriptor *_profile_edd = NULL, *_config_edd = NULL; +static Eet_Data_Descriptor *_profile_edd = NULL, *_config_edd = NULL, *_snapshot_edd = NULL; static Eina_List *_profiles = NULL; static Config *_config = NULL; static Eina_List *_extensions = NULL; @@ -209,6 +226,26 @@ _profile_remove(Profile *p) free(p); } +static void +_snapshot_eet_load() +{ + Eet_Data_Descriptor *ext_edd; + if (_snapshot_edd) return; + Eet_Data_Descriptor_Class eddc; + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Extension_Snapshot); + ext_edd = eet_data_descriptor_stream_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(ext_edd, Extension_Snapshot, "nickname", nickname, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(ext_edd, Extension_Snapshot, "data_count", data_count, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_BASIC(ext_edd, Extension_Snapshot, "version", version, EET_T_INT); + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Snapshot); + _snapshot_edd = eet_data_descriptor_stream_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(_snapshot_edd, Snapshot, "app_name", app_name, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_snapshot_edd, Snapshot, "app_pid", app_pid, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_LIST(_snapshot_edd, Snapshot, "ext_snapshots", ext_snapshots, ext_edd); +} + static Eo * _inwin_create(void) { @@ -235,6 +272,18 @@ _ext_cfg_find_by_path(const char *path) return NULL; } +static Extension_Config * +_ext_cfg_find_by_nickname(const char *nick) +{ + Extension_Config *cfg; + Eina_List *itr; + EINA_LIST_FOREACH(_config->extensions_cfgs, itr, cfg) + { + if (!strcmp(cfg->nickname, nick)) return cfg; + } + return NULL; +} + static void _configs_load() { @@ -304,6 +353,14 @@ _configs_load() continue; } ext_cfg->name = name_fn(); + const char *(*nickname_fn)(void) = eina_module_symbol_get(ext_cfg->module, "extension_nickname_get"); + if (!nickname_fn) + { + printf("Can not find extension_nickname_get function for %s\n", ext_cfg->name); + ext_cfg->nickname = ext_cfg->lib_path; + continue; + } + ext_cfg->nickname = nickname_fn(); Ext_Start_Cb start_fn = eina_module_symbol_get(ext_cfg->module, "extension_start"); if (!start_fn) { @@ -383,6 +440,7 @@ _app_populate() ext->app_changed_cb(ext); } } + elm_object_item_disabled_set(_main_widgets->save_load_bt, !sel_app_id); } static void @@ -565,6 +623,7 @@ _connection_type_change(Connection_Type conn_type) ext->app_id = 0; } eina_debug_session_terminate(_session); + _session = NULL; _apps_free(); _cl_stat_reg_op = EINA_DEBUG_OPCODE_INVALID; elm_object_item_text_set(_main_widgets->apps_selector, "Select App"); @@ -597,6 +656,18 @@ _connection_type_change(Connection_Type conn_type) elm_object_item_text_set(_main_widgets->conn_selector, _conn_strs[conn_type]); _conn_type = conn_type; _session_populate(); + if (_session) + { + elm_object_item_text_set(_main_widgets->save_load_bt, "Save"); + elm_toolbar_item_icon_set(_main_widgets->save_load_bt, "document-import"); + elm_object_item_disabled_set(_main_widgets->save_load_bt, EINA_TRUE); + } + else + { + elm_object_item_text_set(_main_widgets->save_load_bt, "Load"); + elm_toolbar_item_icon_set(_main_widgets->save_load_bt, "document-export"); + elm_object_item_disabled_set(_main_widgets->save_load_bt, EINA_FALSE); + } } static void @@ -756,26 +827,29 @@ _file_get(const char *filename, char **buffer_out) } static void -_extension_offline_load(void *data, Evas_Object *obj, +_extension_file_import(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { Extension_Config *cfg = data; Clouseau_Extension *ext = _extension_instantiate(cfg); char *buffer = NULL; - int size = _file_get(_offline_filename, &buffer); - if (size <= 0) return; + int size = 0; + const char *filename = efl_key_data_get(obj, "_filename"); while (obj && strcmp(efl_class_name_get(obj), "Elm.Inwin")) obj = efl_parent_get(obj); if (obj) efl_del(obj); + size = _file_get(filename, &buffer); + if (size <= 0) return; + _ui_freeze(ext, EINA_TRUE); - if (ext->import_data_cb) ext->import_data_cb(ext, buffer, size); + if (ext->import_data_cb) ext->import_data_cb(ext, buffer, size, -1); _ui_freeze(ext, EINA_FALSE); } static void -_extensions_cfgs_inwin_create() +_extensions_cfgs_inwin_create(const char *filename) { Eina_List *itr; Extension_Config *ext_cfg; @@ -798,10 +872,14 @@ _extensions_cfgs_inwin_create() elm_list_mode_set(list, ELM_LIST_EXPAND); evas_object_size_hint_weight_set(list, 1, 1); evas_object_size_hint_align_set(list, -1, -1); + efl_key_data_set(list, "_filename", filename); EINA_LIST_FOREACH(_config->extensions_cfgs, itr, ext_cfg) { if (ext_cfg->ready) - elm_list_item_append(list, ext_cfg->name, NULL, NULL, _extension_offline_load, ext_cfg); + { + elm_list_item_append(list, ext_cfg->name, NULL, NULL, + _extension_file_import, ext_cfg); + } } evas_object_show(list); elm_box_pack_end(box, list); @@ -809,12 +887,136 @@ _extensions_cfgs_inwin_create() elm_win_inwin_activate(inwin); } +static void +_export_to_file(void *_data EINA_UNUSED, Evas_Object *fs EINA_UNUSED, void *ev) +{ + const char *filename = ev; + _snapshot_eet_load(); + FILE *fp = fopen(filename, "w"); + if (fp) + { + Snapshot s; + Extension_Snapshot *e_s; + Clouseau_Extension *e; + Eina_List *itr; + char *eet_buf; + int eet_size = 0; + + s.app_name = _selected_app->name; + s.app_pid = _selected_app->pid; + s.ext_snapshots = NULL; + EINA_LIST_FOREACH(_extensions, itr, e) + { + if (e->export_data_cb) + { + int data_count = 0; + int version = 1; + void *data = e->export_data_cb(e, &data_count, &version); + if (!data) continue; + e_s = alloca(sizeof(*e_s)); + e_s->nickname = e->ext_cfg->nickname; + e_s->data = data; + e_s->data_count = data_count; + e_s->version = version; + s.ext_snapshots = eina_list_append(s.ext_snapshots, e_s); + } + } + + eet_buf = eet_data_descriptor_encode(_snapshot_edd, &s, &eet_size); + fwrite(&eet_size, sizeof(int), 1, fp); + fwrite(eet_buf, 1, eet_size, fp); + + EINA_LIST_FREE(s.ext_snapshots, e_s) + { + fwrite(e_s->data, 1, e_s->data_count, fp); + free(e_s->data); + } + fclose(fp); + } +} + +static void +_file_import(void *_data EINA_UNUSED, Evas_Object *fs EINA_UNUSED, void *ev) +{ + const char *filename = ev; + FILE *fp = fopen(filename, "r"); + void *eet_buf; + Snapshot *s; + int eet_size; + if (!fp) return; + _snapshot_eet_load(); + fread(&eet_size, sizeof(int), 1, fp); + eet_buf = malloc(eet_size); + fread(eet_buf, 1, eet_size, fp); + s = eet_data_descriptor_decode(_snapshot_edd, eet_buf, eet_size); + if (s) + { + Extension_Snapshot *e_s; + char name[100]; + EINA_LIST_FREE(s->ext_snapshots, e_s) + { + void *data = malloc(e_s->data_count); + fread(data, 1, e_s->data_count, fp); + Extension_Config *e_cfg = _ext_cfg_find_by_nickname(e_s->nickname); + if (e_cfg) + { + Clouseau_Extension *e = _extension_instantiate(e_cfg); + if (e->import_data_cb) + e->import_data_cb(e, data, e_s->data_count, e_s->version); + } + free(data); + free(e_s); + } + snprintf(name, sizeof(name) - 1, "%s [%d]", s->app_name, s->app_pid); + elm_object_item_text_set(_main_widgets->apps_selector, name); + free(s); + } + else + _extensions_cfgs_inwin_create(eina_stringshare_add(filename)); + if (fp) fclose(fp); +} + +static void +_inwin_del(void *data, Evas_Object *obj EINA_UNUSED, void *ev EINA_UNUSED) +{ + Eo *inwin = data; + efl_del(inwin); +} + +static void +_fs_activate(Eina_Bool is_save) +{ + Eo *inwin = _inwin_create(); + Eo *fs = elm_fileselector_add(inwin); + + elm_fileselector_is_save_set(fs, is_save); + elm_fileselector_path_set(fs, getenv("HOME")); + evas_object_size_hint_weight_set + (fs, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(fs, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_smart_callback_add(fs, "done", _inwin_del, inwin); + evas_object_smart_callback_add(fs, "done", + is_save?_export_to_file:_file_import, NULL); + evas_object_show(fs); + + elm_win_inwin_content_set(inwin, fs); + elm_win_inwin_activate(inwin); +} + +void +save_load_perform(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + if (_session) _fs_activate(EINA_TRUE); + else _fs_activate(EINA_FALSE); +} + EAPI_MAIN int elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED) { Connection_Type conn_type = OFFLINE; Eina_List *itr; Extension_Config *ext_cfg; + Eina_Stringshare *offline_filename = NULL; int i, long_index = 0, opt; Eina_Bool help = EINA_FALSE; @@ -833,7 +1035,7 @@ elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED) }; while ((opt = getopt_long(argc, argv,"hlr:f:", long_options, &long_index )) != -1) { - if (conn_type != OFFLINE || _offline_filename) + if (conn_type != OFFLINE || offline_filename) { printf("You cannot use more than one option at a time\n"); help = EINA_TRUE; @@ -859,7 +1061,7 @@ elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED) case 'f': { conn_type = OFFLINE; - _offline_filename = eina_stringshare_add(optarg); + offline_filename = eina_stringshare_add(optarg); break; } case 'h': help = EINA_TRUE; break; @@ -906,14 +1108,11 @@ elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED) _connection_type_change(conn_type); - if (conn_type == OFFLINE && _offline_filename) - { - _extensions_cfgs_inwin_create(); - } + if (conn_type == OFFLINE && offline_filename) + _file_import(NULL, NULL, (void *)offline_filename); elm_run(); - _connection_type_change(OFFLINE); eina_shutdown(); return 0; } diff --git a/src/bin/gui.c b/src/bin/gui.c index d7fdb25..0279a5a 100644 --- a/src/bin/gui.c +++ b/src/bin/gui.c @@ -18,6 +18,8 @@ extern void gui_new_profile_win_create_done(Gui_New_Profile_Win_Widgets *wdgs); extern void conn_menu_show(void *data, Evas_Object *obj, void *event_info); +extern void +save_load_perform(void *data, Evas_Object *obj, void *event_info); static void _pubs_free_cb(void *data, const Efl_Event *event EINA_UNUSED) @@ -70,6 +72,8 @@ gui_main_win_create(Eo *__main_parent) pub_widgets->apps_selector_menu = elm_toolbar_item_menu_get(pub_widgets->apps_selector); + pub_widgets->save_load_bt = elm_toolbar_item_append(tb, "document-export", "Save", save_load_perform, NULL); + ext_selector = elm_toolbar_item_append(tb, "system-reboot", "Extensions", NULL, NULL); elm_toolbar_item_menu_set(ext_selector, EINA_TRUE); diff --git a/src/bin/gui.h b/src/bin/gui.h index 25fd373..d7ff97d 100644 --- a/src/bin/gui.h +++ b/src/bin/gui.h @@ -11,6 +11,7 @@ typedef struct Eo *conn_selector_menu; Eo *apps_selector; Eo *apps_selector_menu; + Eo *save_load_bt; Eo *ext_selector_menu; Eo *freeze_pulse; Eo *freeze_inwin; diff --git a/src/lib/Clouseau.h b/src/lib/Clouseau.h index ec69d7c..71bd450 100644 --- a/src/lib/Clouseau.h +++ b/src/lib/Clouseau.h @@ -35,7 +35,8 @@ typedef struct _Clouseau_Extension Clouseau_Extension; typedef Eo *(*Ui_Get_Cb)(Clouseau_Extension *ext, Eo *parent); typedef void (*Session_Changed_Cb)(Clouseau_Extension *ext); typedef void (*App_Changed_Cb)(Clouseau_Extension *ext); -typedef void (*Import_Data_Cb)(Clouseau_Extension *ext, char *buffer, int size); +typedef void (*Import_Data_Cb)(Clouseau_Extension *ext, void *buffer, int size, int version); +typedef void *(*Export_Data_Cb)(Clouseau_Extension *ext, int *size, int *version); typedef Eo *(*Inwin_Create_Cb)(); typedef void (*Ui_Freeze_Cb)(Clouseau_Extension *ext, Eina_Bool freeze); @@ -50,6 +51,7 @@ struct _Clouseau_Extension Session_Changed_Cb session_changed_cb; /* Function called when the session changed */ App_Changed_Cb app_changed_cb; /* Function called when the app changed */ Import_Data_Cb import_data_cb; /* Function called when data has to be imported */ + Export_Data_Cb export_data_cb; /* Function called when data has to be exported */ Inwin_Create_Cb inwin_create_cb; /* Function to call to create a Inwin */ Ui_Freeze_Cb ui_freeze_cb; /* Function to call to freeze/thaw the UI */ void *data; /* Data allocated and managed by the extension */ diff --git a/src/lib/clouseau_debug.c b/src/lib/clouseau_debug.c index d699855..c0be8c9 100644 --- a/src/lib/clouseau_debug.c +++ b/src/lib/clouseau_debug.c @@ -36,11 +36,45 @@ static int _eoids_get_op = EINA_DEBUG_OPCODE_INVALID; static int _obj_info_op = EINA_DEBUG_OPCODE_INVALID; static int _snapshot_objs_get_op = EINA_DEBUG_OPCODE_INVALID; +typedef struct +{ + Eina_List *kls_strs; + uint64_t *kls; + int nb_kls; +} _KlIds_Walk_Data; + +static Eina_Bool +_klids_walk_cb(void *_data, Efl_Class *kl) +{ + _KlIds_Walk_Data *data = _data; + const char *kl_name = efl_class_name_get(kl), *kls_str; + Eina_List *itr; + + EINA_LIST_FOREACH(data->kls_strs, itr, kls_str) + { + if (!strcmp(kl_name, kls_str)) + { + int i; + for (i = 0; i < data->nb_kls; i++) + { + if (!data->kls[i]) + { + data->kls[i] = (uint64_t)kl; + return EINA_TRUE; + } + } + } + } + return EINA_TRUE; +} + static Eina_Debug_Error _snapshot_do_cb(Eina_Debug_Session *session, int srcid, void *buffer, int size) { + static Eina_Bool (*foo)(Eo_Debug_Class_Iterator_Cb, void *) = NULL; char *buf = alloca(sizeof(Eina_Debug_Packet_Header) + size); Eina_Debug_Packet_Header *hdr = (Eina_Debug_Packet_Header *)buf; + char *tmp; hdr->size = sizeof(Eina_Debug_Packet_Header); hdr->cid = srcid; @@ -48,8 +82,27 @@ _snapshot_do_cb(Eina_Debug_Session *session, int srcid, void *buffer, int size) hdr->opcode = _klids_get_op; eina_debug_dispatch(session, buf); + _KlIds_Walk_Data data; + data.kls_strs = NULL; + tmp = buffer; + while (size > 0) + { + data.kls_strs = eina_list_append(data.kls_strs, tmp); + size -= strlen(tmp) + 1; + tmp += strlen(tmp) + 1; + } + data.nb_kls = eina_list_count(data.kls_strs); + size = data.nb_kls * sizeof(uint64_t); + if (data.nb_kls) + { + data.kls = alloca(size); + memset(data.kls, 0, size); + if (!foo) foo = dlsym(RTLD_DEFAULT, "eo_debug_classes_iterate"); + foo(_klids_walk_cb, &data); + } + hdr->size = sizeof(Eina_Debug_Packet_Header) + size; - if (size) memcpy(buf + sizeof(Eina_Debug_Packet_Header), buffer, size); + if (size) memcpy(buf + sizeof(Eina_Debug_Packet_Header), data.kls, size); hdr->thread_id = 0xFFFFFFFF; hdr->opcode = _snapshot_objs_get_op; eina_debug_dispatch(session, buf); diff --git a/src/lib/extensions/evlog/main.c b/src/lib/extensions/evlog/main.c index 29339ba..8f05624 100644 --- a/src/lib/extensions/evlog/main.c +++ b/src/lib/extensions/evlog/main.c @@ -1404,7 +1404,7 @@ _evlog_view_add(Inf *inf) } static void -_evlog_import(Clouseau_Extension *ext, char *buffer, int size) +_evlog_import(Clouseau_Extension *ext, void *buffer, int size, int version EINA_UNUSED) { Evlog *evlog = calloc(1, sizeof(Evlog)); Inf *inf = ext->data; @@ -1468,6 +1468,12 @@ extension_name_get() return "Event log"; } +EAPI const char * +extension_nickname_get() +{ + return "evlog"; +} + EAPI Eina_Bool extension_start(Clouseau_Extension *ext, Eo *parent) { diff --git a/src/lib/extensions/objects_introspection/gui.c b/src/lib/extensions/objects_introspection/gui.c index 8690c5d..5f83493 100644 --- a/src/lib/extensions/objects_introspection/gui.c +++ b/src/lib/extensions/objects_introspection/gui.c @@ -33,8 +33,6 @@ screenshot_req_cb(void *data, const Efl_Event *event); extern void reload_perform(void *data, Evas_Object *obj, void *event_info); extern void -save_load_perform(void *data, Evas_Object *obj, void *event_info); -extern void take_screenshot_button_clicked(void *data, const Efl_Event *event); extern void show_screenshot_button_clicked(void *data, const Efl_Event *event); @@ -108,8 +106,6 @@ gui_win_create(Eo *__main_parent) pub_widgets->highlight_ck = ck; } - pub_widgets->save_load_bt = elm_toolbar_item_append(tb, "document-export", "Save", save_load_perform, NULL); - panes = efl_add(ELM_PANES_CLASS, box); elm_obj_panes_content_right_size_set(panes, 0.600000); evas_object_size_hint_weight_set(panes, 1.000000, 1.000000); diff --git a/src/lib/extensions/objects_introspection/gui.h b/src/lib/extensions/objects_introspection/gui.h index 25c9fb5..72eca3f 100644 --- a/src/lib/extensions/objects_introspection/gui.h +++ b/src/lib/extensions/objects_introspection/gui.h @@ -10,7 +10,6 @@ typedef struct Eo *reload_button; Eo *objs_type_radio; Eo *highlight_ck; - Eo *save_load_bt; Eo *object_infos_list; Eo *objects_list; } Gui_Win_Widgets; diff --git a/src/lib/extensions/objects_introspection/main.c b/src/lib/extensions/objects_introspection/main.c index 005e381..2418863 100644 --- a/src/lib/extensions/objects_introspection/main.c +++ b/src/lib/extensions/objects_introspection/main.c @@ -40,17 +40,17 @@ typedef struct typedef struct { - Eina_Stringshare *out_file; + void *buffer; + int cur_len; + int max_len; +} Snapshot_Buffer; - Eina_List *screenshots; - - char *buffer; - unsigned int max_len; - unsigned int cur_len; - - int klids_op; - int eoids_op; - int obj_info_op; +typedef struct +{ + Snapshot_Buffer klids_buf; + Snapshot_Buffer eoids_buf; + Snapshot_Buffer obj_infos_buf; + Snapshot_Buffer screenshots_buf; } Snapshot; typedef struct @@ -62,7 +62,7 @@ typedef struct typedef struct { Gui_Win_Widgets *wdgs; - Snapshot *snapshot; + Snapshot snapshot; Obj_Info *selected_obj; Eina_Hash *classes_hash_by_id; Eina_Hash *classes_hash_by_name; @@ -76,7 +76,6 @@ typedef struct Eina_Bool clouseau_init_done; } Instance; -static Eet_Data_Descriptor *_snapshot_edd = NULL; static Eet_Data_Descriptor *_config_edd = NULL; static Config *_config = NULL; @@ -185,6 +184,10 @@ _app_changed(Clouseau_Extension *ext) { static int app_id = -1; Instance *inst = ext->data; + Snapshot *s = &(inst->snapshot); + + elm_genlist_clear(inst->wdgs->objects_list); + elm_genlist_clear(inst->wdgs->object_infos_list); if (inst->objs_list_tree) { _objs_tree_free(inst->objs_list_tree); @@ -194,58 +197,41 @@ _app_changed(Clouseau_Extension *ext) eina_hash_free_buckets(inst->classes_hash_by_id); eina_hash_free_buckets(inst->classes_hash_by_name); - elm_genlist_clear(inst->wdgs->objects_list); - elm_genlist_clear(inst->wdgs->object_infos_list); eina_hash_free_buckets(inst->objs_hash); + s->klids_buf.cur_len = 0; + s->eoids_buf.cur_len = 0; + s->obj_infos_buf.cur_len = 0; + s->screenshots_buf.cur_len = 0; if (app_id != ext->app_id) { inst->eo_init_done = EINA_FALSE; inst->eolian_init_done = EINA_FALSE; inst->evas_init_done = EINA_FALSE; inst->clouseau_init_done = EINA_FALSE; - if (ext->app_id) - eina_debug_session_send(ext->session, ext->app_id, _module_init_op, "eo", 3); - } - else - { - if (ext->app_id) - eina_debug_session_send(ext->session, ext->app_id, _klids_get_op, NULL, 0); } + if (ext->app_id) + eina_debug_session_send(ext->session, ext->app_id, _module_init_op, "eo", 3); app_id = ext->app_id; if (app_id) { elm_object_item_disabled_set(inst->wdgs->reload_button, EINA_FALSE); - elm_object_item_disabled_set(inst->wdgs->save_load_bt, EINA_FALSE); } } static void -_snapshot_buffer_append(Clouseau_Extension *ext, void *buffer) +_snapshot_buffer_append(Snapshot_Buffer *sb, void *buffer) { - Instance *inst = ext->data; - Snapshot *s = inst->snapshot; Eina_Debug_Packet_Header *hdr = (Eina_Debug_Packet_Header *)buffer; - unsigned int size = hdr->size; - if (s->max_len < s->cur_len + size) + int size = hdr->size; + if (sb->max_len < sb->cur_len + size) { /* Realloc with addition of 1MB+size */ - s->max_len += size + 1000000; - s->buffer = realloc(s->buffer, s->max_len); + sb->max_len += size + 1000000; + sb->buffer = realloc(sb->buffer, sb->max_len); } - memcpy(s->buffer + s->cur_len, buffer, size); - s->cur_len += size; -} - -static Eina_Bool -_snapshot_is_candidate(void *buffer) -{ - Eina_Debug_Packet_Header *hdr = (Eina_Debug_Packet_Header *)buffer; - if (hdr->opcode == _eoids_get_op || - hdr->opcode == _klids_get_op || - hdr->opcode == _obj_info_op || - hdr->opcode == _win_screenshot_op) return EINA_TRUE; - else return EINA_FALSE; + memcpy((char *)sb->buffer + sb->cur_len, buffer, size); + sb->cur_len += size; } Eina_Debug_Error @@ -254,15 +240,18 @@ _disp_cb(Eina_Debug_Session *session, void *buffer) Clouseau_Extension *ext = eina_debug_session_data_get(session); if (!ext) return EINA_DEBUG_OK; Instance *inst = ext->data; - if (inst->snapshot && _snapshot_is_candidate(buffer)) + if (inst) { - _snapshot_buffer_append(ext, buffer); + Snapshot *s = &inst->snapshot; + Eina_Debug_Packet_Header *hdr = (Eina_Debug_Packet_Header *)buffer; + Snapshot_Buffer *sb = NULL; + if (hdr->opcode == _eoids_get_op) sb = &(s->eoids_buf); + else if (hdr->opcode == _klids_get_op) sb = &(s->klids_buf); + else if (hdr->opcode == _obj_info_op) sb = &(s->obj_infos_buf); + else if (hdr->opcode == _win_screenshot_op) sb = &(s->screenshots_buf); + if (sb) _snapshot_buffer_append(sb, buffer); } - else - { - return inst->old_disp_cb(session, buffer); - } - return EINA_DEBUG_OK; + return inst->old_disp_cb(session, buffer); } static void @@ -291,205 +280,48 @@ _session_changed(Clouseau_Extension *ext) inst->old_disp_cb = eina_debug_session_dispatch_get(ext->session); eina_debug_session_dispatch_override(ext->session, _disp_cb); eina_debug_opcodes_register(ext->session, _ops, _post_register_handle, ext); - - elm_object_item_text_set(inst->wdgs->save_load_bt, "Save"); - elm_toolbar_item_icon_set(inst->wdgs->save_load_bt, "document-import"); - elm_object_item_disabled_set(inst->wdgs->save_load_bt, EINA_TRUE); - } - else - { - elm_object_item_text_set(inst->wdgs->save_load_bt, "Load"); - elm_toolbar_item_icon_set(inst->wdgs->save_load_bt, "document-export"); - elm_object_item_disabled_set(inst->wdgs->save_load_bt, EINA_FALSE); } elm_object_item_disabled_set(inst->wdgs->reload_button, EINA_TRUE); } -static void -_snapshot_eet_load() -{ - if (_snapshot_edd) return; - Eet_Data_Descriptor_Class eddc; - Evas_Debug_Screenshot s; - - EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Evas_Debug_Screenshot); - Eet_Data_Descriptor *evas_shot_edd = eet_data_descriptor_stream_new(&eddc); - -#define SHOT_ADD_BASIC(member, eet_type)\ - EET_DATA_DESCRIPTOR_ADD_BASIC\ - (evas_shot_edd, Evas_Debug_Screenshot, # member, member, eet_type) - - SHOT_ADD_BASIC(obj, EET_T_ULONG_LONG); - SHOT_ADD_BASIC(w, EET_T_INT); - SHOT_ADD_BASIC(h, EET_T_INT); - eet_data_descriptor_element_add(evas_shot_edd, - "img", EET_T_CHAR, EET_G_VAR_ARRAY, - (char *)(&(s.img)) - (char *)(&s), - (char *)(&(s.img_size)) - (char *)(&s), - NULL, NULL); - SHOT_ADD_BASIC(tm_sec, EET_T_INT); - SHOT_ADD_BASIC(tm_min, EET_T_INT); - SHOT_ADD_BASIC(tm_hour, EET_T_INT); - -#undef SHOT_ADD_BASIC - - EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Snapshot); - _snapshot_edd = eet_data_descriptor_stream_new(&eddc); - -#define SNP_ADD_BASIC(member, eet_type)\ - EET_DATA_DESCRIPTOR_ADD_BASIC\ - (_snapshot_edd, Snapshot, # member, member, eet_type) - - SNP_ADD_BASIC(cur_len, EET_T_INT); - SNP_ADD_BASIC(eoids_op, EET_T_INT); - SNP_ADD_BASIC(klids_op, EET_T_INT); - SNP_ADD_BASIC(obj_info_op, EET_T_INT); - EET_DATA_DESCRIPTOR_ADD_LIST(_snapshot_edd, Snapshot, - "screenshots", screenshots, evas_shot_edd); - -#undef SNP_ADD_BASIC -} - -static Eina_Bool -_snapshot_save(Clouseau_Extension *ext) -{ - Instance *inst = ext->data; - Snapshot *s = inst->snapshot; - FILE *fp = fopen(s->out_file, "w"); - void *out_buf = NULL; - int out_size = 0; - Eina_Bool ret = EINA_FALSE; - - if (!fp) - { - printf("Can not open file: \"%s\".\n", s->out_file); - return EINA_FALSE; - } - if (!ext->app_id) goto end; - _snapshot_eet_load(); - s->eoids_op = _eoids_get_op; - s->klids_op = _klids_get_op; - s->obj_info_op = _obj_info_op; - s->screenshots = inst->screenshots; - out_buf = eet_data_descriptor_encode(_snapshot_edd, s, &out_size); - fwrite(&out_size, sizeof(int), 1, fp); - fwrite(out_buf, 1, out_size, fp); - printf("Snapshot buffer size %d max %d\n", s->cur_len, s->max_len); - fwrite(s->buffer, 1, s->cur_len, fp); - ret = EINA_TRUE; -end: - fclose(fp); - return ret; -} - -static Snapshot * -_snapshot_buffer_parse(char *buffer, int size) -{ - Snapshot *s = NULL; - int eet_size = 0; - - if (size < eet_size) return NULL; - - memcpy(&eet_size, buffer, sizeof(int)); - buffer += sizeof(int); - - _snapshot_eet_load(); - - s = eet_data_descriptor_decode(_snapshot_edd, buffer, eet_size); - buffer += eet_size; - - if (s->cur_len) s->buffer = buffer; - - return s; -} static void -_snapshot_load(Clouseau_Extension *ext, char *buffer, int size) +_snapshot_load(Clouseau_Extension *ext, void *buffer, int size, int version EINA_UNUSED) { - Evas_Debug_Screenshot *shot; - unsigned int idx = 0; - + char *buf = buffer; + int klids_op, eoids_op, obj_info_op, screenshot_op; if (!ext) return; - Instance *inst = ext->data; - Snapshot *s = _snapshot_buffer_parse(buffer, size); - if (!s) return; +#define EXTRACT(_buf, pval, sz) \ + { \ + memcpy(pval, _buf, sz); \ + _buf += sz; \ + } + EXTRACT(buf, &klids_op, sizeof(int)); + EXTRACT(buf, &eoids_op, sizeof(int)); + EXTRACT(buf, &obj_info_op, sizeof(int)); + EXTRACT(buf, &screenshot_op, sizeof(int)); +#undef EXTRACT _session_changed(ext); - _eoids_get_op = s->eoids_op; - _klids_get_op = s->klids_op; - _obj_info_op = s->obj_info_op; - - /* Prevent free of the buffer */ - while (idx < s->cur_len) + while (size > 0) { - Eina_Debug_Packet_Header *hdr = (Eina_Debug_Packet_Header *)(s->buffer + idx); - void *payload = (s->buffer + idx) + sizeof(*hdr); - size = hdr->size - sizeof(*hdr); - if (hdr->opcode == _eoids_get_op) _eoids_get((Eina_Debug_Session *)ext, -1, payload, size); - else if (hdr->opcode == _klids_get_op) _klids_get((Eina_Debug_Session *)ext, -1, payload, size); - else if (hdr->opcode == _obj_info_op) _obj_info_get((Eina_Debug_Session *)ext, -1, payload, size); - idx += hdr->size; + Eina_Debug_Packet_Header *hdr = (Eina_Debug_Packet_Header *)buf; + void *payload = buf + sizeof(*hdr); + int psize = hdr->size - sizeof(*hdr); + if (hdr->opcode == eoids_op) + _eoids_get((Eina_Debug_Session *)ext, -1, payload, psize); + else if (hdr->opcode == klids_op) + _klids_get((Eina_Debug_Session *)ext, -1, payload, psize); + else if (hdr->opcode == obj_info_op) + _obj_info_get((Eina_Debug_Session *)ext, -1, payload, psize); + else if (hdr->opcode == screenshot_op) + _win_screenshot_get((Eina_Debug_Session *)ext, -1, payload, psize); + else return; + buf += hdr->size; + size -= hdr->size; } - EINA_LIST_FREE(s->screenshots, shot) - { - Obj_Info *info = eina_hash_find(inst->objs_hash, &(shot->obj)); - if (!info) continue; - info->screenshots = eina_list_append(info->screenshots, shot); - if (info->glitem) elm_genlist_item_update(info->glitem); - } - free(s); - free(buffer); -} - -static int -_file_get(const char *filename, char **buffer_out) -{ - char *file_data = NULL; - int file_size; - FILE *fp = fopen(filename, "r"); - if (!fp) - { - printf("Can not open file: \"%s\".\n", filename); - return -1; - } - - fseek(fp, 0, SEEK_END); - file_size = ftell(fp); - if (file_size <= 0) - { - fclose(fp); - if (file_size < 0) printf("Can not ftell file: \"%s\".\n", filename); - return -1; - } - rewind(fp); - file_data = (char *) calloc(1, file_size); - if (!file_data) - { - fclose(fp); - printf("Calloc failed\n"); - return -1; - } - int res = fread(file_data, 1, file_size, fp); - if (!res) - { - free(file_data); - file_data = NULL; - if (!feof(fp)) printf("fread failed\n"); - } - fclose(fp); - if (file_data && buffer_out) *buffer_out = file_data; - return file_size; -} - -static void -_snapshot_load_from_fs(void *data, Evas_Object *fs EINA_UNUSED, void *ev) -{ - char *buffer = NULL; - int size = _file_get(ev, &buffer); - if (size <= 0) return; - _snapshot_load(data, buffer, size); } static void @@ -761,8 +593,6 @@ _objs_sel_cb(void *data EINA_UNUSED, Evas_Object *obj, void *event_info) eina_debug_session_send_to_thread(ext->session, ext->app_id, info->thread_id, _obj_highlight_op, &(info->obj), sizeof(uint64_t)); } - eina_debug_session_send_to_thread(ext->session, ext->app_id, info->thread_id, - _obj_info_op, &(info->obj), sizeof(uint64_t)); if (info->eolian_info) _obj_info_realize(ext, info->eolian_info); } @@ -809,8 +639,18 @@ static Eina_Debug_Error _win_screenshot_get(Eina_Debug_Session *session EINA_UNUSED, int src EINA_UNUSED, void *buffer, int size) { - Clouseau_Extension *ext = eina_debug_session_data_get(session); - Instance *inst = ext->data; + Clouseau_Extension *ext = NULL; + Instance *inst = NULL; + if (src == -1) + { + ext = (Clouseau_Extension *)session; + session = NULL; + } + else + { + ext = eina_debug_session_data_get(session); + } + inst = ext->data; Evas_Debug_Screenshot *s = evas_debug_screenshot_decode(buffer, size); if (!s) return EINA_DEBUG_ERROR; Obj_Info *info = eina_hash_find(inst->objs_hash, &(s->obj)); @@ -895,49 +735,43 @@ show_screenshot_button_clicked(void *data EINA_UNUSED, const Efl_Event *event) } } -static void * -_eoids_request_prepare(Clouseau_Extension *ext, int *size) -{ - uint64_t obj_kl = 0, canvas_kl = 0; - Instance *inst = ext->data; - Class_Info *info = eina_hash_find(inst->classes_hash_by_name, - _config->wdgs_show_type == 0 ? "Efl.Canvas.Object" : "Elm.Widget"); - if (info) obj_kl = info->id; - info = eina_hash_find(inst->classes_hash_by_name, "Efl.Canvas"); - if (info) canvas_kl = info->id; - return eo_debug_eoids_request_prepare(size, obj_kl, canvas_kl, NULL); -} - static Eina_Debug_Error _snapshot_done_cb(Eina_Debug_Session *session, int src EINA_UNUSED, void *buffer EINA_UNUSED, int size EINA_UNUSED) { Clouseau_Extension *ext = eina_debug_session_data_get(session); - Instance *inst = ext->data; - Snapshot *s = inst->snapshot; - if (!s) return EINA_DEBUG_OK; - _snapshot_save(ext); - free(s->buffer); - free(s); - inst->snapshot = NULL; ext->ui_freeze_cb(ext, EINA_FALSE); return EINA_DEBUG_OK; } -static void -_snapshot_do(void *data, Evas_Object *fs EINA_UNUSED, void *ev) +static void * +_snapshot_save(Clouseau_Extension *ext, int *size, int *version) { - void *buf; - Clouseau_Extension *ext = data; - int size; - if (!ext || !ext->app_id) return; Instance *inst = ext->data; - ext->ui_freeze_cb(ext, EINA_TRUE); - inst->snapshot = calloc(1, sizeof(Snapshot)); - inst->snapshot->out_file = eina_stringshare_add(ev); - buf = _eoids_request_prepare(ext, &size); - eina_debug_session_send(ext->session, ext->app_id, _snapshot_do_op, buf, size); - free(buf); + Snapshot *s = &(inst->snapshot); + void *buffer = malloc(4 * sizeof(int) + + s->klids_buf.cur_len + s->eoids_buf.cur_len + + s->obj_infos_buf.cur_len + s->screenshots_buf.cur_len); + char *tmp = buffer; + +#define STORE(_buf, pval, sz) \ +{ \ + memcpy(_buf, pval, sz); \ + _buf += sz; \ +} + STORE(tmp, &_klids_get_op, sizeof(int)); + STORE(tmp, &_eoids_get_op, sizeof(int)); + STORE(tmp, &_obj_info_op, sizeof(int)); + STORE(tmp, &_win_screenshot_op, sizeof(int)); + STORE(tmp, s->klids_buf.buffer, s->klids_buf.cur_len); + STORE(tmp, s->eoids_buf.buffer, s->eoids_buf.cur_len); + STORE(tmp, s->obj_infos_buf.buffer, s->obj_infos_buf.cur_len); + STORE(tmp, s->screenshots_buf.buffer, s->screenshots_buf.cur_len); +#undef STORE + + *version = 1; + *size = tmp - (char *)buffer; + return buffer; } void @@ -1014,10 +848,12 @@ _objs_item_content_get(void *data, Evas_Object *obj, const char *part) static Eina_Debug_Error _module_initted_cb(Eina_Debug_Session *session, int src, void *buffer, int size) { + const char *obj_kl_name = NULL, *canvas_kl_name = NULL; Clouseau_Extension *ext = eina_debug_session_data_get(session); if (size <= 0) return EINA_DEBUG_ERROR; if (!ext) return EINA_DEBUG_OK; Instance *inst = ext->data; + char *buf; Eina_Bool ret = !!((char *)buffer)[size - 1]; if (!ret) @@ -1049,7 +885,15 @@ _module_initted_cb(Eina_Debug_Session *session, int src, void *buffer, int size) eina_debug_session_send(session, src, _module_init_op, "clouseau", 9); return EINA_DEBUG_OK; } - eina_debug_session_send(session, src, _klids_get_op, NULL, 0); + ext->ui_freeze_cb(ext, EINA_TRUE); + + obj_kl_name = _config->wdgs_show_type == 0 ? "Efl.Canvas.Object" : "Elm.Widget"; + canvas_kl_name = "Efl.Canvas"; + size = strlen(obj_kl_name) + 1 + strlen(canvas_kl_name) + 1; + buf = alloca(size); + memcpy(buf, obj_kl_name, strlen(obj_kl_name) + 1); + memcpy(buf + strlen(obj_kl_name) + 1, canvas_kl_name, strlen(canvas_kl_name) + 1); + eina_debug_session_send(session, src, _snapshot_do_op, buf, size); return EINA_DEBUG_OK; } @@ -1067,8 +911,6 @@ _klid_walk(void *data, uint64_t kl, char *name) static Eina_Debug_Error _klids_get(Eina_Debug_Session *session, int src, void *buffer, int size) { - uint64_t obj_kl = 0, canvas_kl = 0; - void *buf; Clouseau_Extension *ext = NULL; Instance *inst = NULL; if (src == -1) @@ -1082,14 +924,7 @@ _klids_get(Eina_Debug_Session *session, int src, void *buffer, int size) } inst = ext->data; eo_debug_klids_extract(buffer, size, _klid_walk, inst); - Class_Info *info = eina_hash_find(inst->classes_hash_by_name, - _config->wdgs_show_type == 0 ? "Efl.Canvas.Object" : "Elm.Widget"); - if (info) obj_kl = info->id; - info = eina_hash_find(inst->classes_hash_by_name, "Efl.Canvas"); - if (info) canvas_kl = info->id; - buf = eo_debug_eoids_request_prepare(&size, obj_kl, canvas_kl, NULL); - eina_debug_session_send_to_thread(session, src, 0xFFFFFFFF, _eoids_get_op, buf, size); - free(buf); + return EINA_DEBUG_OK; } @@ -1223,33 +1058,6 @@ jump_to_ptr_inwin_show(void *data EINA_UNUSED, Evas_Object *obj, void *event_inf elm_win_inwin_activate(inwin); } -static void -_inwin_del(void *data, Evas_Object *obj EINA_UNUSED, void *ev EINA_UNUSED) -{ - Eo *inwin = data; - efl_del(inwin); -} - -static void -_fs_activate(Clouseau_Extension *ext, Eina_Bool is_save) -{ - Eo *inwin = ext->inwin_create_cb(); - Eo *fs = elm_fileselector_add(inwin); - - elm_fileselector_is_save_set(fs, is_save); - elm_fileselector_path_set(fs, getenv("HOME")); - evas_object_size_hint_weight_set - (fs, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_size_hint_align_set(fs, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_smart_callback_add(fs, "done", _inwin_del, inwin); - evas_object_smart_callback_add(fs, "done", - is_save?_snapshot_do:_snapshot_load_from_fs, ext); - evas_object_show(fs); - - elm_win_inwin_content_set(inwin, fs); - elm_win_inwin_activate(inwin); -} - void reload_perform(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) { @@ -1262,14 +1070,6 @@ reload_perform(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_U } } -void -save_load_perform(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) -{ - Clouseau_Extension *ext = _ext_get(obj); - if (ext->session) _fs_activate(ext, EINA_TRUE); - else _fs_activate(ext, EINA_FALSE); -} - static Eo * _ui_get(Clouseau_Extension *ext, Eo *parent) { @@ -1321,6 +1121,12 @@ extension_name_get() return "Objects introspection"; } +EAPI const char * +extension_nickname_get() +{ + return "objs_intro"; +} + EAPI Eina_Bool extension_start(Clouseau_Extension *ext, Eo *parent) { @@ -1333,12 +1139,15 @@ extension_start(Clouseau_Extension *ext, Eo *parent) ext->session_changed_cb = _session_changed; ext->app_changed_cb = _app_changed; ext->import_data_cb = _snapshot_load; + ext->export_data_cb = _snapshot_save; inst->classes_hash_by_id = eina_hash_pointer_new(NULL); inst->classes_hash_by_name = eina_hash_string_small_new(NULL); inst->objs_hash = eina_hash_pointer_new(NULL); + memset(&(inst->snapshot), 0, sizeof(inst->snapshot)); + eolian_directory_scan(EOLIAN_EO_DIR); _config_load(ext);