#include #include #include #include #include #include "gm-mcp-icecrew-userlist.h" #include "gm-iuserlist.h" #include "gm-mcp-userlist-view.h" #include "gm-mcp-icecrew-playerdb.h" #include "gm-mcp-session.h" #include "gm-mcp.h" #include "gm-support.h" #include "gm-marshal.h" #include "gm-debug.h" #include "gm-world.h" #include "gm-triggers.h" #define GM_MCP_ICECREW_USERLIST_GET_PRIVATE(object)( \ G_TYPE_INSTANCE_GET_PRIVATE((object), \ GM_TYPE_MCP_ICECREW_USERLIST, GmMcpIcecrewUserlistPrivate)) #define USERLIST_ICON_SIZE 22 static GmKeyValuePair default_states[] = { {"away+idle", "ice-userlist/away+idle.svg"}, {"busy+idle", "ice-userlist/busy+idle.svg"}, {"avail+idle", "ice-userlist/avail+idle.svg"}, {"away", "ice-userlist/away.svg"}, {"busy", "ice-userlist/busy.svg"}, {NULL, NULL} }; static GmKeyValuePair default_ranks[] = { {"inhabitant", "ice-userlist/inhabitant.svg"}, {"programmer", "ice-userlist/programmer.svg"}, {"wizard", "ice-userlist/wizard.svg"}, {NULL, NULL} }; struct _GmMcpIcecrewUserlistPrivate { GList *state_icons; GList *rank_icons; GList *state_alternatives; GList *rank_alternatives; GList *key_datatags; GmFetchHandle *rank_fetch; GmFetchHandle *state_fetch; gchar *rank_dir; gchar *state_dir; gchar **property_names; GList *menu; gboolean initializing; }; static gchar *gm_mcp_icecrew_userlist_depends[] = { "dns-nl-icecrew-playerdb", NULL }; static gchar *gm_mcp_icecrew_userlist_overrides[] = { "dns-com-vmoo-userlist", NULL }; enum { P_NAME, P_RANK, P_STATE, P_STATE_MSG }; static gchar *gm_mcp_icecrew_userlist_property_names0[] = { "P_NAME", "P_RANK", "P_STATE", "P_STATE_MSG" }; static gchar *gm_mcp_icecrew_userlist_property_names1[] = { "name", "rank", "state", "state_msg" }; /* Signals enum { NUM_SIGNALS }; */ //static guint gm_mcp_icecrew_userlist_signals[NUM_SIGNALS] = {0}; static void gm_mcp_icecrew_userlist_iface_init(GmIUserlistInterface *iface); G_DEFINE_TYPE_EXTENDED(GmMcpIcecrewUserlist, gm_mcp_icecrew_userlist, \ GM_TYPE_MCP_PACKAGE, 0, G_IMPLEMENT_INTERFACE(GM_TYPE_IUSERLIST, \ gm_mcp_icecrew_userlist_iface_init)) void on_gm_mcp_icecrew_userlist_add(GmMcpIcecrewPlayerdb *playerdb, GmPlayerdbPlayerInfo *ppi, GmMcpIcecrewUserlist *userlist); void on_gm_mcp_icecrew_userlist_set(GmMcpIcecrewPlayerdb *playerdb, GmPlayerdbPlayerInfo *ppi, gchar const *key, gchar const *value, gchar const *old, GmMcpIcecrewUserlist *userlist); void on_gm_mcp_icecrew_userlist_delete(GmMcpIcecrewPlayerdb *playerdb, GmPlayerdbPlayerInfo *ppi, GmMcpIcecrewUserlist *userlist); void on_gm_mcp_icecrew_userlist_fetch_progress(GmFetchHandle *g, GmMcpIcecrewUserlist *package); gboolean gm_mcp_icecrew_userlist_handle_multi(GmMcpPackage *package, gchar const *data_tag, gchar const *key, gchar const *value, GList *all_values); void gm_mcp_icecrew_userlist_set_session(GmMcpPackage *package, GObject *session); void gm_mcp_icecrew_userlist_create_view(GmMcpPackage *package, GObject *parent); void gm_mcp_icecrew_userlist_fetch_progress(GmFetchHandle *g, GmMcpIcecrewUserlist *package); GList *gm_mcp_icecrew_userlist_get_menu(GmIUserlist *userlist, gint id); gboolean gm_mcp_icecrew_userlist_supports_status(GmIUserlist *userlist); gchar *gm_mcp_icecrew_userlist_get_status(GmIUserlist *userlist, gint id); gchar const *gm_mcp_icecrew_userlist_get_name(GmIUserlist *userlist, gint id); gchar const *gm_mcp_icecrew_userlist_get_icon(GmIUserlist *userlist, gint id, gboolean use_state); gint gm_mcp_icecrew_userlist_get_rank_priority(GmIUserlist *userlist, gint id); gint gm_mcp_icecrew_userlist_get_state_priority(GmIUserlist *userlist, gint id); static void gm_mcp_icecrew_userlist_iface_init( GmIUserlistInterface *iface) { iface->get_menu = gm_mcp_icecrew_userlist_get_menu; iface->get_status = gm_mcp_icecrew_userlist_get_status; iface->get_name = gm_mcp_icecrew_userlist_get_name; iface->get_icon = gm_mcp_icecrew_userlist_get_icon; iface->get_rank_priority = gm_mcp_icecrew_userlist_get_rank_priority; iface->get_state_priority = gm_mcp_icecrew_userlist_get_state_priority; } void gm_mcp_icecrew_userlist_pair_free(GmKeyValuePair *pair) { g_free(pair->key); g_free(pair->value); g_free(pair); } void gm_mcp_icecrew_userlist_free_list(GList *rs) { GList *item; for (item = rs; item; item = item->next) { gm_mcp_icecrew_userlist_pair_free((GmKeyValuePair *)(item->data)); } g_list_free(rs); } static void gm_mcp_icecrew_userlist_free_menu(GmMcpIcecrewUserlist *obj) { gm_mcp_icecrew_userlist_free_list(obj->priv->menu); obj->priv->menu = NULL; } static void gm_mcp_icecrew_userlist_finalize(GObject *object) { GmMcpIcecrewUserlist *obj = GM_MCP_ICECREW_USERLIST(object); GmMcpPackage *playerdb = gm_mcp_session_find_package( GM_MCP_PACKAGE_SESSION(obj), "dns-nl-icecrew-playerdb"); if (playerdb) { g_signal_handlers_disconnect_by_func(playerdb, on_gm_mcp_icecrew_userlist_add, obj); g_signal_handlers_disconnect_by_func(playerdb, on_gm_mcp_icecrew_userlist_set, obj); g_signal_handlers_disconnect_by_func(playerdb, on_gm_mcp_icecrew_userlist_delete, obj); } if (obj->priv->rank_fetch) { obj->priv->rank_fetch->aborted = TRUE; } if (obj->priv->state_fetch) { obj->priv->state_fetch->aborted = TRUE; } gm_mcp_icecrew_userlist_free_list(obj->priv->state_icons); gm_mcp_icecrew_userlist_free_list(obj->priv->rank_icons); gm_mcp_icecrew_userlist_free_list(obj->priv->key_datatags); gm_mcp_icecrew_userlist_free_menu(obj); gm_mcp_icecrew_userlist_free_list(obj->priv->rank_alternatives); gm_mcp_icecrew_userlist_free_list(obj->priv->state_alternatives); g_free(obj->priv->rank_dir); g_free(obj->priv->state_dir); G_OBJECT_CLASS(gm_mcp_icecrew_userlist_parent_class)->finalize(object); } static void gm_mcp_icecrew_userlist_class_init(GmMcpIcecrewUserlistClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); GmMcpPackageClass *pklass = GM_MCP_PACKAGE_CLASS(klass); object_class->finalize = gm_mcp_icecrew_userlist_finalize; pklass->name = "dns-nl-icecrew-userlist"; pklass->depends = gm_mcp_icecrew_userlist_depends; pklass->overrides = gm_mcp_icecrew_userlist_overrides; pklass->min_version = 1.0; pklass->max_version = 1.1; pklass->set_session = &gm_mcp_icecrew_userlist_set_session; pklass->handle_multi = &gm_mcp_icecrew_userlist_handle_multi; pklass->create_view = &gm_mcp_icecrew_userlist_create_view; g_type_class_add_private(object_class, sizeof(GmMcpIcecrewUserlistPrivate)); } GmKeyValuePair * gm_mcp_icecrew_userlist_url_map_new(gchar const *name, gchar const *filename) { GmKeyValuePair *r = g_new(GmKeyValuePair, 1); r->key = g_strdup(name); r->value = g_strdup(filename); return r; } GList * gm_mcp_icecrew_userlist_find_icon_names(GList *icons, gchar const *path) { GList *item, *res = NULL; GmKeyValuePair *map; if (path == NULL || icons == NULL) { return NULL; } for (item = icons; item; item = item->next) { map = (GmKeyValuePair *)(item->data); if (map->value != NULL && strcmp(map->value, path) == 0) { res = g_list_append(res, map->key); } } return res; } guint gm_mcp_icecrew_userlist_find_path(GList *icons, gchar const *name, gchar const **path) { GList *item; GmKeyValuePair *map; guint position = 0; if (name == NULL) { if (path != NULL) { *path = NULL; } return 0; } for (item = icons; item; item = item->next) { map = (GmKeyValuePair *)(item->data); if (map->key != NULL && strcmp(map->key, name) == 0) { if (path != NULL) { *path = map->value; } return position; } ++position; } if (path != NULL) { *path = NULL; } return position + 1; } void gm_mcp_icecrew_userlist_remove_datatag(GmMcpIcecrewUserlist *package, gchar const *datatag) { GList *item; GmKeyValuePair *map; if (datatag == NULL) { return; } for (item = package->priv->key_datatags; item; item = item->next) { map = (GmKeyValuePair *)(item->data); if (strcmp(map->value, datatag) == 0) { gm_mcp_icecrew_userlist_pair_free(map); package->priv->key_datatags = g_list_remove_link( package->priv->key_datatags, item); g_list_free_1(item); return; } } } gchar const * gm_mcp_icecrew_userlist_find_key(GmMcpIcecrewUserlist *package, gchar const *datatag) { GList *item; GmKeyValuePair *map; if (datatag == NULL) { return NULL; } for (item = package->priv->key_datatags; item; item = item->next) { map = (GmKeyValuePair *)(item->data); if (map->value != NULL && strcmp(map->value, datatag) == 0) { return map->key; } } return NULL; } gchar const * gm_mcp_icecrew_userlist_find_name(gchar const *name, GmKeyValuePair def[]) { GmKeyValuePair *pair = def; if (name == NULL) { return NULL; } while (!(pair->key == NULL && pair->value == NULL)) { if (pair->key != NULL && strcmp(pair->key, name) == 0) { return pair->value; } ++pair; } return NULL; } void gm_mcp_icecrew_userlist_init_states(GmMcpIcecrewUserlist *package) { GmKeyValuePair *pair = default_states; package->priv->state_icons = NULL; while (!(pair->key == NULL && pair->value == NULL)) { package->priv->state_icons = g_list_append(package->priv->state_icons, gm_mcp_icecrew_userlist_url_map_new(pair->key, pair->value)); ++pair; } } void gm_mcp_icecrew_userlist_init_ranks(GmMcpIcecrewUserlist *package) { GmKeyValuePair *pair = default_ranks; package->priv->rank_icons = NULL; while (!(pair->key == NULL && pair->value == NULL)) { package->priv->rank_icons = g_list_append(package->priv->rank_icons, gm_mcp_icecrew_userlist_url_map_new(pair->key, pair->value)); ++pair; } } static void gm_mcp_icecrew_userlist_init(GmMcpIcecrewUserlist *obj) { obj->priv = GM_MCP_ICECREW_USERLIST_GET_PRIVATE(obj); obj->priv->rank_alternatives = NULL; obj->priv->state_alternatives = NULL; obj->priv->key_datatags = NULL; obj->priv->rank_dir = NULL; obj->priv->state_dir = NULL; obj->priv->rank_fetch = NULL; obj->priv->state_fetch = NULL; gm_mcp_icecrew_userlist_init_states(obj); gm_mcp_icecrew_userlist_init_ranks(obj); } GmMcpIcecrewUserlist * gm_mcp_icecrew_userlist_new() { GmMcpIcecrewUserlist *obj = GM_MCP_ICECREW_USERLIST(g_object_new( GM_TYPE_MCP_ICECREW_USERLIST, NULL)); return obj; } gchar * gm_mcp_icecrew_userlist_remote_to_local_path(gchar const *url, gchar const *dirname) { gchar *base = g_path_get_basename(url); gchar *result; result = g_strconcat(dirname, G_DIR_SEPARATOR_S, base, NULL); g_free(base); return result; } void gm_mcp_icecrew_userlist_remove_alternatives(GmMcpIcecrewUserlist *package, gchar const *path, gint n, gboolean rank) { GList *item, **alter; gint i; GmKeyValuePair *map; gchar *name, *pathd, *dir; if (path == NULL) { return; } alter = rank ? &(package->priv->rank_alternatives) : &(package->priv->state_alternatives); dir = rank ? package->priv->rank_dir : package->priv->state_dir; for (item = *alter; item; item = item->next) { map = (GmKeyValuePair *)(item->data); pathd = gm_mcp_icecrew_userlist_remote_to_local_path(map->value, dir); if (pathd != NULL && strcmp(pathd, path) == 0) { name = g_strdup(map->key); i = 0; if (name != NULL) { while (item && (n == 0 || i < n)) { map = (GmKeyValuePair *)(item->data); ++i; if (map->key != NULL && strcmp(map->key, name) == 0) { item = item->next; *alter = g_list_remove(*alter, map); gm_mcp_icecrew_userlist_pair_free(map); } else { break; } } } g_free(name); break; } g_free(pathd); } } gchar const * gm_mcp_icecrew_userlist_icon_path(GmMcpIcecrewUserlist *package, GmPlayerdbPlayerInfo *ppi, gboolean use_state) { gchar const *state; gchar const *icon_path = NULL; state = gm_playerdb_player_info_get_prop(ppi, package->priv->property_names[P_STATE]); if (!use_state || (state != NULL && strcmp(state, "avail") == 0)) { gm_mcp_icecrew_userlist_find_path(package->priv->rank_icons, gm_playerdb_player_info_get_prop(ppi, package->priv->property_names[P_RANK]), &icon_path); } else { gm_mcp_icecrew_userlist_find_path(package->priv->state_icons, state, &icon_path); } return icon_path; } void gm_mcp_icecrew_userlist_update_rank_icon(GmPlayerdbPlayerInfo *ppi, gpointer user_data) { g_signal_emit_by_name(user_data, "rank-changed", ppi->id); } void gm_mcp_icecrew_userlist_update_state_icon(GmPlayerdbPlayerInfo *ppi, gpointer user_data) { g_signal_emit_by_name(user_data, "state-changed", ppi->id); } void gm_mcp_icecrew_userlist_new_rank_state_icon(GmMcpIcecrewUserlist *package, gchar *path, gboolean rank) { GList *names; GList *tmp; GmMcpPackage *playerdb; playerdb = gm_mcp_session_find_package(GM_MCP_PACKAGE_SESSION(package), "dns-nl-icecrew-playerdb"); g_return_if_fail(playerdb != NULL); if (rank) { names = gm_mcp_icecrew_userlist_find_icon_names( package->priv->rank_icons, path); } else { names = gm_mcp_icecrew_userlist_find_icon_names( package->priv->state_icons, path); } if (names == NULL) { return; } for (tmp = names; tmp; tmp = tmp->next) { if (rank) { gm_mcp_icecrew_playerdb_find_players_with( GM_MCP_ICECREW_PLAYERDB(playerdb), package->priv->property_names[P_RANK], (gchar *)(tmp->data), gm_mcp_icecrew_userlist_update_rank_icon, package); } else { gm_mcp_icecrew_playerdb_find_players_with( GM_MCP_ICECREW_PLAYERDB(playerdb), package->priv->property_names[P_STATE], (gchar *)(tmp->data), gm_mcp_icecrew_userlist_update_state_icon, package); } } g_list_free(names); } void gm_mcp_icecrew_userlist_remove_not_used_icons(GList *icons, gchar *dir) { glob_t gl; guint i; GList *names; gchar *g = g_strconcat(dir, G_DIR_SEPARATOR_S, "*", NULL); glob(g, 0, NULL, &gl); for (i = 0; i < gl.gl_pathc; ++i) { names = gm_mcp_icecrew_userlist_find_icon_names(icons, gl.gl_pathv[i]); if (!names) { gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.RemoveNotUsedIcons: " "removing %s", gl.gl_pathv[i]); if (unlink(gl.gl_pathv[i]) == -1) { gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.RemoveNotUsedIcons: " "error %s", strerror(errno)); } } else { g_list_free(names); } } g_free(g); globfree(&gl); } void gm_mcp_icecrew_userlist_fetch_next_alternatives(GmMcpIcecrewUserlist *package, gboolean rank) { GList *source_uri = NULL, *dest_uri = NULL; gchar *prev_name = NULL, *path; GList *item, **alter, *iter; GmKeyValuePair *map, *itermap; /* Select unique name alternatives */ alter = rank ? &(package->priv->rank_alternatives) : &(package->priv->state_alternatives); item = *alter; while (item) { map = (GmKeyValuePair *)(item->data); gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.FetchNextAlternatives: " "checking: %s", map->value); /* Skip alternatives with names we've already stored to be fetched */ if (prev_name == NULL || (map->key != NULL && strcmp(map->key, prev_name) != 0)) { prev_name = map->key; path = gm_mcp_icecrew_userlist_remote_to_local_path(map->value, rank ? package->priv->rank_dir : package->priv->state_dir); gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist." "FetchNextAlternatives: adding to be fetched: %s => %s", map->key, map->value); source_uri = g_list_append(source_uri, map->value); dest_uri = g_list_append(dest_uri, path); unlink(path); for (iter = rank ? package->priv->rank_icons : package->priv->state_icons; iter; iter = iter->next) { itermap = (GmKeyValuePair *)(iter->data); if (itermap->key != NULL && strcmp(itermap->key, map->key) == 0) { g_free(itermap->value); itermap->value = g_strdup(path); break; } } } if (source_uri != NULL) break; item = item->next; } if (source_uri != NULL) { if (rank) { package->priv->rank_fetch = gm_fetch(source_uri, dest_uri, (GFunc)gm_mcp_icecrew_userlist_fetch_progress, package); } else { package->priv->state_fetch = gm_fetch(source_uri, dest_uri, (GFunc)gm_mcp_icecrew_userlist_fetch_progress, package); } gm_g_list_free_simple(dest_uri); } else { if (rank) { gm_mcp_icecrew_userlist_remove_not_used_icons( package->priv->rank_icons, package->priv->rank_dir); } else { gm_mcp_icecrew_userlist_remove_not_used_icons( package->priv->state_icons, package->priv->state_dir); } } } void gm_mcp_icecrew_userlist_fetch_progress(GmFetchHandle *g, GmMcpIcecrewUserlist *package) { gchar *path; gboolean rank; GdkPixbuf *pixtest; GError *err = NULL; if (g->aborted) { gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.FetchProgress: " "fetch aborted!"); return; } rank = (package->priv->rank_fetch == g); if (g->done) { gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.FetchProgress: " "fetch done!"); /* Remove this one from the alternatives */ gm_mcp_icecrew_userlist_remove_alternatives(package, gnome_vfs_uri_get_path((GnomeVFSURI *)(g->dest_uri->data)), 1, rank); if (rank) { package->priv->rank_fetch = NULL; gm_mcp_icecrew_userlist_fetch_next_alternatives(package, TRUE); } else { package->priv->state_fetch = NULL; gm_mcp_icecrew_userlist_fetch_next_alternatives(package, FALSE); } return; } if (g->status == GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR) { /* Skip to the next alternative (in the next run, see on done */ gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.FetchProgress: error"); } if (g->cur_phase == GNOME_VFS_XFER_PHASE_FILECOMPLETED) { path = gnome_vfs_get_local_path_from_uri(g->cur_file_name); gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.FetchProgress: " "%s fetched!", path); pixtest = gdk_pixbuf_new_from_file(path, &err); if (pixtest) { /* Remove alternatives which don't need to be fetched anymore */ g_object_unref(pixtest); gm_mcp_icecrew_userlist_remove_alternatives(package, path, 0, rank); if (rank) { gm_mcp_icecrew_userlist_new_rank_state_icon(package, path, TRUE); } else { gm_mcp_icecrew_userlist_new_rank_state_icon(package, path, FALSE); } } else { /* This failed! */ gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.FetchProgress: " "error, couldn't load file: %s", err->message); g_error_free(err); gm_mcp_icecrew_userlist_remove_alternatives(package, path, 1, rank); } g_free(path); } } #define MAX_MATCHES 10 void gm_mcp_icecrew_userlist_process_triggers(GmMcpIcecrewUserlist *package, gchar const *username, GmTriggerConditionType condition) { GmWorld *world; GmTriggers *triggers; GList const *item; GmTrigger *trigger; regmatch_t matches[MAX_MATCHES]; gint num; GmMcpPackage *playerdb = gm_mcp_session_find_package( GM_MCP_PACKAGE_SESSION(package), "dns-nl-icecrew-playerdb"); if (gm_mcp_icecrew_playerdb_initializing( GM_MCP_ICECREW_PLAYERDB(playerdb))) { return; } world = GM_MCP_SESSION_WORLD(GM_MCP_PACKAGE_SESSION(package)); triggers = gm_world_triggers(world); for (item = gm_triggers_list(triggers); item; item = item->next) { trigger = (GmTrigger *)(item->data); if (trigger->event == TT_USERS) { if ((num = gm_trigger_match_user(trigger, username, condition, matches, MAX_MATCHES))) { gm_world_apply_trigger(world, trigger, username, matches, num); } } } } gchar * gm_mcp_icecrew_userlist_menu_item_subst(GmMcpIcecrewUserlist *package, gchar *str, GmPlayerdbPlayerInfo *info) { GString *result; gchar *ptr = str, *subst = NULL, *tmp, *prop; gchar const *value; gunichar ch, cnum; gboolean substituted; if (str == NULL) { return NULL; } result = g_string_sized_new(strlen(str)); while ((ch = g_utf8_get_char(ptr)) != '\0') { substituted = FALSE; if (ch == '$') { tmp = subst = g_utf8_next_char(ptr); while ((cnum = g_utf8_get_char(subst)) && (cnum == '_' || g_unichar_isalpha(cnum))) { subst = g_utf8_next_char(subst); } prop = g_strndup(tmp, subst - tmp); if (strcmp(prop, "ID") == 0 || strcmp(prop, "id") == 0) { tmp = g_strdup_printf("#%d", info->id); result = g_string_append(result, tmp); g_free(tmp); substituted = TRUE; } else { value = gm_playerdb_player_info_get_prop(info, prop); if (value) { for (; *value != '\0'; value = g_utf8_next_char(value)) { ch = g_utf8_get_char(value); if (ch == '_') { result = g_string_append_c(result, '_'); } result = g_string_append_unichar(result, ch); } substituted = TRUE; } } } if (!substituted) { result = g_string_append_unichar(result, ch); } if (*ptr == '\0') { break; } if (!substituted) { ptr = g_utf8_next_char(ptr); } else { ptr = subst; } } ptr = result->str; g_string_free(result, FALSE); return ptr; } GmKeyValuePair * gm_mcp_icecrew_userlist_get_menu_item(GmMcpIcecrewUserlist *package, GmKeyValuePair *menuitem, GmPlayerdbPlayerInfo *info) { GmKeyValuePair *result = g_new0(GmKeyValuePair, 1); if (!menuitem) { return result; } result->key = gm_mcp_icecrew_userlist_menu_item_subst(package, menuitem->key, info); result->value = gm_mcp_icecrew_userlist_menu_item_subst(package, menuitem->value, info); return result; } /* Interface */ GList * gm_mcp_icecrew_userlist_get_menu(GmIUserlist *userlist, gint id) { GmMcpIcecrewUserlist *object = GM_MCP_ICECREW_USERLIST(userlist); GmMcpIcecrewPlayerdb *playerdb = GM_MCP_ICECREW_PLAYERDB( gm_mcp_session_find_package(GM_MCP_PACKAGE_SESSION(userlist), "dns-nl-icecrew-playerdb")); GmPlayerdbPlayerInfo *info = gm_mcp_icecrew_playerdb_find(playerdb, id); GList *item, *result = NULL; for (item = object->priv->menu; item; item = item->next) { result = g_list_append(result, gm_mcp_icecrew_userlist_get_menu_item( object, (GmKeyValuePair *)(item->data), info)); } return result; } gchar const * gm_mcp_icecrew_userlist_get_name(GmIUserlist *userlist, gint id) { GmMcpIcecrewPlayerdb *playerdb = GM_MCP_ICECREW_PLAYERDB( gm_mcp_session_find_package(GM_MCP_PACKAGE_SESSION(userlist), "dns-nl-icecrew-playerdb")); GmPlayerdbPlayerInfo *info = gm_mcp_icecrew_playerdb_find(playerdb, id); return gm_playerdb_player_info_get_prop(info, GM_MCP_ICECREW_USERLIST(userlist)->priv->property_names[P_NAME]); } gchar const * gm_mcp_icecrew_userlist_get_icon(GmIUserlist *userlist, gint id, gboolean use_state) { GmMcpIcecrewUserlist *package = GM_MCP_ICECREW_USERLIST(userlist); GmMcpIcecrewPlayerdb *playerdb = GM_MCP_ICECREW_PLAYERDB( gm_mcp_session_find_package(GM_MCP_PACKAGE_SESSION(package), "dns-nl-icecrew-playerdb")); GmPlayerdbPlayerInfo *info = gm_mcp_icecrew_playerdb_find(playerdb, id); return gm_mcp_icecrew_userlist_icon_path(package, info, use_state); } gint gm_mcp_icecrew_userlist_get_rank_priority(GmIUserlist *userlist, gint id) { GmMcpIcecrewUserlist *package = GM_MCP_ICECREW_USERLIST(userlist); GmMcpIcecrewPlayerdb *playerdb = GM_MCP_ICECREW_PLAYERDB( gm_mcp_session_find_package(GM_MCP_PACKAGE_SESSION(userlist), "dns-nl-icecrew-playerdb")); GmPlayerdbPlayerInfo *info = gm_mcp_icecrew_playerdb_find(playerdb, id); gchar const *rank = gm_playerdb_player_info_get_prop(info, package->priv->property_names[P_RANK]); return g_list_length(package->priv->rank_icons) - gm_mcp_icecrew_userlist_find_path(package->priv->rank_icons, rank, NULL) - 1; } gint gm_mcp_icecrew_userlist_get_state_priority(GmIUserlist *userlist, gint id) { GmMcpIcecrewUserlist *package = GM_MCP_ICECREW_USERLIST(userlist); GmMcpIcecrewPlayerdb *playerdb = GM_MCP_ICECREW_PLAYERDB( gm_mcp_session_find_package(GM_MCP_PACKAGE_SESSION(userlist), "dns-nl-icecrew-playerdb")); GmPlayerdbPlayerInfo *info = gm_mcp_icecrew_playerdb_find(playerdb, id); gchar const *state = gm_playerdb_player_info_get_prop(info, package->priv->property_names[P_STATE]); return g_list_length(package->priv->state_icons) - gm_mcp_icecrew_userlist_find_path(package->priv->state_icons, state, NULL) + 1; } gchar * gm_mcp_icecrew_userlist_get_status(GmIUserlist *userlist, gint id) { GmMcpIcecrewPlayerdb *playerdb = GM_MCP_ICECREW_PLAYERDB( gm_mcp_session_find_package(GM_MCP_PACKAGE_SESSION(userlist), "dns-nl-icecrew-playerdb")); GmPlayerdbPlayerInfo *info = gm_mcp_icecrew_playerdb_find(playerdb, id); GmMcpIcecrewUserlist *package = GM_MCP_ICECREW_USERLIST(userlist); gchar const *state = gm_playerdb_player_info_get_prop(info, package->priv->property_names[P_STATE]); gchar const *msg = gm_playerdb_player_info_get_prop(info, package->priv->property_names[P_STATE_MSG]); gchar const *caption; if (state == NULL || strcmp(state, "avail") == 0) { return strdup(_("Available")); } if (strstr(state, "away") != NULL) { caption = _("Away"); } else if (strstr(state, "busy") != NULL) { caption = _("Busy"); } else if (strstr(state, "idle") != NULL) { caption = _("Idle"); } else { return NULL; } if (msg == NULL || *msg == '\0') { return strdup(caption); } else { return g_strconcat(caption, ": ", msg, NULL); } } void gm_mcp_icecrew_userlist_handle_menu(GmMcpIcecrewUserlist *package, GList *values) { GmKeyValuePair *pair; GList *item, *data; gm_mcp_icecrew_userlist_free_menu(package); for (item = values; item; item = item->next) { data = (GList *)(item->data); pair = g_new0(GmKeyValuePair, 1); if (g_list_length(data) == 2) { pair->key = g_strdup(data->data); pair->value = g_strdup(data->next->data); } package->priv->menu = g_list_append(package->priv->menu, pair); } } void gm_mcp_icecrew_userlist_handle_ranks_states(GmMcpIcecrewUserlist *package, GList *values, gboolean rank) { GList *tmp, *data, *new_list = NULL; gchar *name, **alternatives, *path, **ptr; gchar const *cpath; /* Abort a previous fetch if needed */ if (rank && package->priv->rank_fetch) { package->priv->rank_fetch = NULL; gm_mcp_icecrew_userlist_free_list(package->priv->rank_alternatives); package->priv->rank_alternatives = NULL; package->priv->rank_fetch->aborted = TRUE; } else if (!rank && package->priv->state_fetch) { package->priv->state_fetch = NULL; gm_mcp_icecrew_userlist_free_list(package->priv->state_alternatives); package->priv->state_alternatives = NULL; package->priv->state_fetch->aborted = TRUE; } for (tmp = values; tmp; tmp = tmp->next) { data = (GList *)(tmp->data); if (data == NULL ) { continue; } name = (gchar *)(data->data); gm_mcp_icecrew_userlist_find_path(new_list, name, &cpath); if (cpath) { gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.HandleRanksStates: " "duplicate %s, ignored!", name); continue; } if (data->next == NULL) { if (rank) { cpath = gm_mcp_icecrew_userlist_find_name(name, default_ranks); } else { cpath = gm_mcp_icecrew_userlist_find_name(name, default_states); } if (cpath) { new_list = g_list_append(new_list, gm_mcp_icecrew_userlist_url_map_new(name, cpath)); } else { gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist." "HandleRanksStates: couldn't find %s, ignored!", name); } } else { alternatives = g_strsplit(g_list_nth_data(data, 1), ";", 0); ptr = alternatives; while (*ptr) { /* Initialize to first alternative */ if (ptr == alternatives) { path = gm_mcp_icecrew_userlist_remote_to_local_path( *ptr, rank ? package->priv->rank_dir : package->priv->state_dir); new_list = g_list_append(new_list, gm_mcp_icecrew_userlist_url_map_new(name, path)); g_free(path); } gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.HandleRanksStates: " "adding alternative: %s => %s", name, *ptr); if (rank) { package->priv->rank_alternatives = g_list_append( package->priv->rank_alternatives, gm_mcp_icecrew_userlist_url_map_new(name, *ptr)); } else { package->priv->state_alternatives = g_list_append( package->priv->state_alternatives, gm_mcp_icecrew_userlist_url_map_new(name, *ptr)); } ++ptr; } g_strfreev(alternatives); } } if (rank) { gm_mcp_icecrew_userlist_free_list(package->priv->rank_icons); package->priv->rank_icons = new_list; } else { gm_mcp_icecrew_userlist_free_list(package->priv->state_icons); package->priv->state_icons = new_list; } if (rank && package->priv->rank_alternatives) { gm_mcp_icecrew_userlist_fetch_next_alternatives(package, rank); } else if (!rank && package->priv->state_alternatives) { gm_mcp_icecrew_userlist_fetch_next_alternatives(package, rank); } } gboolean gm_mcp_icecrew_userlist_handle_multi(GmMcpPackage *package, gchar const *data_tag, gchar const *key, gchar const *value, GList *all_values) { GmMcpIcecrewUserlist *userlist = GM_MCP_ICECREW_USERLIST(package); GList *tmp, *l, *vals = NULL; GmKeyValuePair *m; if (key) { if (!gm_mcp_icecrew_userlist_find_key(userlist, data_tag)) { m = g_new(GmKeyValuePair, 1); m->key = g_strdup(key); m->value = g_strdup(data_tag); userlist->priv->key_datatags = g_list_append( userlist->priv->key_datatags, m); } } else if ((key = gm_mcp_icecrew_userlist_find_key(userlist, data_tag)) != NULL) { for (tmp = all_values; tmp; tmp = tmp->next) { l = gm_mcp_parse_list((gchar *)(tmp->data)); vals = g_list_append(vals, l); } if (strcmp(key, "rank") == 0) { gm_mcp_icecrew_userlist_handle_ranks_states(userlist, vals, TRUE); } else if (strcmp(key, "state") == 0) { gm_mcp_icecrew_userlist_handle_ranks_states(userlist, vals, FALSE); } else if (strcmp(key, "menu") == 0) { gm_mcp_icecrew_userlist_handle_menu(userlist, vals); } gm_mcp_icecrew_userlist_remove_datatag(userlist, data_tag); } else { gm_debug_msg(DEBUG_ALWAYS, "Datatag %s not found", data_tag); } for (tmp = vals; tmp; tmp = tmp->next) { gm_mcp_list_free((GList *)(tmp->data)); } g_list_free(vals); return FALSE; } void gm_mcp_icecrew_userlist_set_session(GmMcpPackage *package, GObject *session) { GmMcpPackageClass *parent_class = g_type_class_peek_parent( GM_MCP_ICECREW_USERLIST_GET_CLASS(package)); gchar *icons_dir; GmMcpPackage *playerdb; GmMcpIcecrewUserlist *userlist = GM_MCP_ICECREW_USERLIST(package); GmMcpSession *ses; gdouble version; parent_class->set_session(package, session); ses = GM_MCP_SESSION(session); playerdb = gm_mcp_session_find_package(ses, "dns-nl-icecrew-playerdb"); g_return_if_fail(playerdb != NULL); version = gm_mcp_package_get_version(GM_MCP_PACKAGE(playerdb)); if (version == 1.1) { userlist->priv->property_names = gm_mcp_icecrew_userlist_property_names1; } else { userlist->priv->property_names = gm_mcp_icecrew_userlist_property_names0; } icons_dir = g_strconcat(gm_world_path(GM_MCP_SESSION_WORLD(ses)), G_DIR_SEPARATOR_S, "icons", NULL); userlist->priv->rank_dir = g_strconcat(icons_dir, G_DIR_SEPARATOR_S, "ranks", NULL); userlist->priv->state_dir = g_strconcat(icons_dir, G_DIR_SEPARATOR_S, "states", NULL); if (!g_file_test(icons_dir, G_FILE_TEST_EXISTS)) mkdir(icons_dir, 0755); if (!g_file_test(userlist->priv->rank_dir, G_FILE_TEST_EXISTS)) mkdir(userlist->priv->rank_dir, 0755); if (!g_file_test(userlist->priv->state_dir, G_FILE_TEST_EXISTS)) mkdir(userlist->priv->state_dir, 0755); g_free(icons_dir); g_signal_connect(playerdb, "add", G_CALLBACK(on_gm_mcp_icecrew_userlist_add), package); g_signal_connect(playerdb, "set", G_CALLBACK(on_gm_mcp_icecrew_userlist_set), package); g_signal_connect(playerdb, "delete", G_CALLBACK(on_gm_mcp_icecrew_userlist_delete), package); } void gm_mcp_icecrew_userlist_create_view(GmMcpPackage *package, GObject *parent) { gm_mcp_userlist_view_new(package, parent); } void gm_mcp_icecrew_userlist_process_state_changed(GmMcpIcecrewUserlist *userlist, GmPlayerdbPlayerInfo *ppi, gchar const *value, gchar const *old) { gboolean was_away, was_idle; gboolean is_away, is_idle; gchar const *name = gm_playerdb_player_info_get_prop(ppi, userlist->priv->property_names[P_NAME]); was_away = (strstr(old, "away") != NULL || strstr(old, "busy") != NULL); was_idle = (strstr(old, "idle") != NULL); is_away = (strstr(value, "away") != NULL || strstr(value, "busy") != NULL); is_idle = (strstr(value, "idle") != NULL); if (was_away && !is_away) { gm_mcp_icecrew_userlist_process_triggers(userlist, name, TCT_USER_AWAY_OFF); } else if (!was_away && is_away) { gm_mcp_icecrew_userlist_process_triggers(userlist, name, TCT_USER_AWAY); } if (was_idle && !is_idle) { gm_mcp_icecrew_userlist_process_triggers(userlist, name, TCT_USER_IDLE_OFF); } else if (!was_idle && is_idle) { gm_mcp_icecrew_userlist_process_triggers(userlist, name, TCT_USER_IDLE); } } /* Callbacks */ void on_gm_mcp_icecrew_userlist_add(GmMcpIcecrewPlayerdb *playerdb, GmPlayerdbPlayerInfo *ppi, GmMcpIcecrewUserlist *userlist) { gchar const *name = gm_playerdb_player_info_get_prop(ppi, userlist->priv->property_names[P_NAME]); g_signal_emit_by_name(userlist, "player-added", ppi->id); gm_mcp_icecrew_userlist_process_triggers(userlist, name, TCT_USER_ONLINE); } void on_gm_mcp_icecrew_userlist_set(GmMcpIcecrewPlayerdb *playerdb, GmPlayerdbPlayerInfo *ppi, gchar const *key, gchar const *value, gchar const *old, GmMcpIcecrewUserlist *userlist) { if (strcmp(key, userlist->priv->property_names[P_STATE]) == 0) { g_signal_emit_by_name(userlist, "state-changed", ppi->id); gm_mcp_icecrew_userlist_process_state_changed(userlist, ppi, value, old); } else if (strcmp(key, userlist->priv->property_names[P_RANK]) == 0) { g_signal_emit_by_name(userlist, "rank-changed", ppi->id); } else if (strcmp(key, userlist->priv->property_names[P_NAME]) == 0) { g_signal_emit_by_name(userlist, "name-changed", ppi->id); } else if (strcmp(key, userlist->priv->property_names[P_STATE_MSG]) == 0) { g_signal_emit_by_name(userlist, "state-changed", ppi->id); } } void on_gm_mcp_icecrew_userlist_delete(GmMcpIcecrewPlayerdb *playerdb, GmPlayerdbPlayerInfo *ppi, GmMcpIcecrewUserlist *userlist) { gchar const *name = gm_playerdb_player_info_get_prop(ppi, userlist->priv->property_names[P_NAME]); g_signal_emit_by_name(userlist, "player-removed", ppi->id); gm_mcp_icecrew_userlist_process_triggers(userlist, name, TCT_USER_OFFLINE); }