grim/guifications3

merging

2011-05-16, Gary Kramlich
8e6f170cb062
merging
/*
* Guifications - The end-all, be-all notification framework
* Copyright (C) 2003-2009 Gary Kramlich <grim@reaperworld.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include "guifications-daemon-connections.h"
/******************************************************************************
* Globals
*****************************************************************************/
static GHashTable *connections = NULL;
static GfFeedManager *feed_manager = NULL;
static GfPreferenceEngine *engine = NULL;
/******************************************************************************
* Local Server Connection Object
*****************************************************************************/
static GfConnection *local_server = NULL;
typedef struct {
GfServerConnection gparent;
} GfdLocalServerConnection;
typedef struct {
GfServerConnectionClass gparent;
} GfdLocalServerConnectionClass;
static gboolean
gfd_local_server_connection_disconnect(GfConnection *connection, GError **e) {
return TRUE;
}
static gboolean
gfd_local_server_connection_listen(GfServerConnection *connection, GError **e) {
return TRUE;
}
static void
gfd_local_server_connection_class_init(GfConnectionClass *klass) {
GfServerConnectionClass *server_class = GF_SERVER_CONNECTION_CLASS(klass);
klass->disconnect = gfd_local_server_connection_disconnect;
server_class->listen = gfd_local_server_connection_listen;
}
static GType
gfd_local_server_connection_get_gtype(void) {
static GType type = 0;
if(G_UNLIKELY(type == 0)) {
static const GTypeInfo info = {
.class_size = sizeof(GfdLocalServerConnectionClass),
.class_init = (GClassInitFunc)gfd_local_server_connection_class_init,
.instance_size = sizeof(GfdLocalServerConnection),
};
type = g_type_register_static(GF_TYPE_SERVER_CONNECTION,
"GfdLocalServerConnection",
&info, 0);
}
return type;
}
/******************************************************************************
* Local Client Connection Object
*****************************************************************************/
static GObjectClass *local_client_parent_class = NULL;
typedef struct {
GfClientConnection gparent;
} GfdLocalClientConnection;
typedef struct {
GfClientConnectionClass gparent;
} GfdLocalClientConnectionClass;
static gboolean
gfd_local_client_connection_disconnect(GfConnection *connection, GError **e) {
/* we set both disconnecting and disconnected so that anyone listening to
* the signals will be notified.
*/
gf_connection_set_state(connection, GF_CONNECTION_STATE_DISCONNECTING);
gf_connection_set_state(connection, GF_CONNECTION_STATE_DISCONNECTED);
return TRUE;
}
static gboolean
gfd_local_client_connection_connect(GfClientConnection *connection,
GError **e)
{
gboolean ret = FALSE;
gf_connection_set_state(GF_CONNECTION(connection),
GF_CONNECTION_STATE_CONNECTING);
if(GF_IS_CONNECTION(local_server)) {
gf_connection_set_feed_manager(GF_CONNECTION(connection),
gf_connection_get_feed_manager(local_server));
gf_connection_set_preference_engine(GF_CONNECTION(connection),
gf_connection_get_preference_engine(local_server));
ret = TRUE;
} else {
ret = FALSE;
}
gf_connection_set_state(GF_CONNECTION(connection),
(ret) ? GF_CONNECTION_STATE_CONNECTED :
GF_CONNECTION_STATE_DISCONNECTED);
return ret;
}
static void
gfd_local_client_connection_finalize(GObject *obj) {
GfConnectionState state = gf_connection_get_state(GF_CONNECTION(obj));
if(state != GF_CONNECTION_STATE_DISCONNECTING ||
state != GF_CONNECTION_STATE_DISCONNECTED)
{
gf_connection_disconnect(GF_CONNECTION(obj), NULL);
}
G_OBJECT_CLASS(local_client_parent_class)->finalize(obj);
}
static void
gfd_local_client_connection_class_init(GfConnectionClass *klass) {
GfClientConnectionClass *client_class = GF_CLIENT_CONNECTION_CLASS(klass);
GfNamedObjectClass *no_class = GF_NAMED_OBJECT_CLASS(klass);
GObjectClass *obj_class = G_OBJECT_CLASS(klass);
local_client_parent_class = g_type_class_peek_parent(klass);
klass->disconnect = gfd_local_client_connection_disconnect;
client_class->connect = gfd_local_client_connection_connect;
no_class->name = "Local Connection";
obj_class->finalize = gfd_local_client_connection_finalize;
}
static GType
gfd_local_client_connection_get_gtype(void) {
static GType type = 0;
if(G_UNLIKELY(type == 0)) {
static const GTypeInfo info = {
.class_size = sizeof(GfdLocalClientConnectionClass),
.class_init = (GClassInitFunc)gfd_local_client_connection_class_init,
.instance_size = sizeof(GfdLocalClientConnection),
};
type = g_type_register_static(GF_TYPE_CLIENT_CONNECTION,
"GfdLocalClientConnection",
&info, 0);
}
return type;
}
/******************************************************************************
* Helpers
*****************************************************************************/
static void
gfd_connections_debug_helper(gpointer k, gpointer v, gpointer d) {
GfConnection *c = NULL;
GfFeedManager *fp = NULL;
GfFeed **feeds = NULL;
guint nf = 0, i = 0;
c = GF_CONNECTION(v);
fp = gf_connection_get_feed_manager(c);
gf_log_info("Guifications-Daemon",
"Found connection %s.\n",
gf_named_object_get_name(GF_NAMED_OBJECT(c)));
if(fp) {
gf_log_info("Guifications-Daemon",
"\tFound a feed manager. Iterating children, if any.\n");
feeds = gf_feed_manager_list_feeds(fp, &nf);
if(feeds && nf >= 1) {
for(; i < nf; i++) {
gf_log_info("Guifications-Daemon",
"\t\tFound feed %s.\n",
gf_named_object_get_name(GF_NAMED_OBJECT(feeds[i])));
}
} else {
gf_log_info("Guifications-Daemon", "\t\tNo feeds in feed manager.\n");
}
} else {
gf_log_info("Guifications-Daemon", "\tNo feed manager found in connection.\n");
}
}
static void
gfd_connections_listen_helper(gpointer k, gpointer v, gpointer d) {
GfServerConnection *c = GF_SERVER_CONNECTION(v);
GError *error = NULL;
const gchar *name = G_OBJECT_TYPE_NAME(c);
gf_server_connection_listen(c, &error);
if(error) {
gf_log_warning("Guifications-Daemon",
"Failed to listen on connection %s: %s\n",
name,
(error->message) ? error->message : "Uknown error");
g_error_free(error);
} else {
gf_log_info("Guifications-Daemon",
"Listening on connection %s\n",
name);
}
}
static void
gfd_connections_disconnect_helper(gpointer k, gpointer v, gpointer d) {
GfConnection *c = GF_CONNECTION(v);
GError *error = NULL;
const gchar *name = G_OBJECT_TYPE_NAME(c);
gf_connection_disconnect(c, &error);
if(error) {
gf_log_warning("Guifications-Daemon",
"Failed to disconnection connection %s: %s\n",
name,
(error->message) ? error->message : "Unknown error");
g_error_free(error);
} else {
gf_log_info("Guifications-Daemon",
"Disconnected connection %s\n",
name);
}
}
/******************************************************************************
* API
*****************************************************************************/
void
gfd_connections_init(GfFeedManager *fp, GfPreferenceEngine *e) {
const gchar *name = NULL;
g_return_if_fail(!connections);
/* register the local client connection since we don't instantiate it */
gfd_local_client_connection_get_gtype();
connections = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_object_unref);
feed_manager = g_object_ref(G_OBJECT(fp));
engine = g_object_ref(G_OBJECT(e));
/* create and manual insert our local server connection */
local_server = g_object_new(gfd_local_server_connection_get_gtype(),
"feed-manager", feed_manager,
"pref-engine", engine,
NULL);
name = gf_named_object_get_name(local_server);
g_hash_table_insert(connections, g_strdup(name), local_server);
/* now look for any other connections which are plugins */
gfd_connections_refresh();
/* set the default client connection */
gf_connection_manager_set_default(gfd_local_client_connection_get_gtype());
}
void
gfd_connections_uninit(void) {
g_hash_table_destroy(connections);
g_object_unref(G_OBJECT(feed_manager));
g_object_unref(G_OBJECT(engine));
}
void
gfd_connections_refresh(void) {
GType *cons = NULL;
guint n = 0, i = 0;
g_return_if_fail(connections != NULL);
cons = gf_type_concrete_children(GF_TYPE_SERVER_CONNECTION, &n);
for(i = 0; i < n; i++) {
GfConnection *server = NULL;
GfNamedObjectClass *named_class = NULL;
const gchar *name = NULL;
named_class = g_type_class_ref(cons[i]);
name = gf_named_object_class_get_name(named_class);
/* we can't unref the class yet since it could invalidate the name */
server = g_hash_table_lookup(connections, name);
if(server) {
g_type_class_unref(named_class);
continue;
}
server = g_object_new(cons[i],
"feed-manager", feed_manager,
"pref-engine", engine,
NULL);
g_hash_table_insert(connections, g_strdup(name), server);
gf_log_info("Guifications-Daemon",
"adding connection %s to our connections.\n",
name);
g_type_class_unref(named_class);
}
g_free(cons);
}
void
gfd_connections_listen(void) {
g_hash_table_foreach(connections,
gfd_connections_listen_helper,
NULL);
}
void
gfd_connections_close(void) {
g_hash_table_foreach(connections,
gfd_connections_disconnect_helper,
NULL);
}
void
gfd_connections_debug(void) {
g_hash_table_foreach(connections,
gfd_connections_debug_helper,
NULL);
}