This repository has been archived on 2020-04-11. You can view files and clone it, but cannot push or open issues or pull requests.
gnoemoe/gnoemoe/mcp/gm-mcp-icecrew-userlist.c

1262 lines
34 KiB
C

#include <glib.h>
#include <string.h>
#include <glob.h>
#include <unistd.h>
#include <errno.h>
#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 *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(path);
}
}
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;
GnomeVFSResult result;
GnomeVFSFileInfo *finfo;
/* 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)) {
finfo = gnome_vfs_file_info_new();
result = gnome_vfs_get_file_info(map->value, finfo,
GNOME_VFS_FILE_INFO_DEFAULT);
gnome_vfs_file_info_unref(finfo);
if (result != GNOME_VFS_OK) {
gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist."
"FetchNextAlternatives: removing %s because it's "
"invalid: %s", map->value,
gnome_vfs_result_to_string(result));
item = item->next;
*alter = g_list_remove(*alter, map);
gm_mcp_icecrew_userlist_pair_free(map);
} else {
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;
}
}
item = item->next;
}
} else {
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!");
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");
path = gnome_vfs_get_local_path_from_uri(g->cur_file_name);
gm_mcp_icecrew_userlist_remove_alternatives(package, path, 1, rank);
g_free(path);
}
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, *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) {
ptr = subst;
}
}
if (!substituted) {
result = g_string_append_unichar(result, ch);
}
if (*ptr == '\0') {
break;
}
ptr = g_utf8_next_char(ptr);
}
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 NULL;
}
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);
}