summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c266
1 files changed, 265 insertions, 1 deletions
diff --git a/src/main.c b/src/main.c
index 3dd9704..525aa38 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,11 +1,14 @@
#include "common.h"
#include <gtk/gtk.h>
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/client.h>
+#include <string.h>
+
#include "customcellrendererstate.h"
#include "customcellrendererprogress.h"
#include "customcellrendererrate.h"
#include "customcellrendererleft.h"
-#include <string.h>
typedef enum
{
@@ -33,6 +36,66 @@ typedef struct
static void torrent_update(torrent_t* torrent,
GtkListStore* store, GtkTreeIter* iter);
+typedef struct
+{
+ GAsyncQueue* queue;
+} worker_data_t;
+
+typedef enum
+{
+ MSG_CONNECT, /* main -> worker */
+ MSG_CONNECTRESULT, /* worker -> main */
+ MSG_DISCONNECT, /* main -> worker */
+ MSG_QUIT, /* main -> worker */
+ MSG_ERROR, /* worker -> main */
+} msg_type_t;
+
+typedef struct
+{
+ msg_type_t type;
+} msg_t;
+
+typedef struct
+{
+ msg_t base;
+ gchar* url;
+ gchar* auth_username, * auth_password;
+} msg_connect_t;
+
+typedef struct
+{
+ msg_t base;
+ gboolean success;
+ gchar* errmsg;
+} msg_connectresult_t;
+
+typedef struct
+{
+ msg_t base;
+ gchar* msg;
+} msg_error_t;
+
+typedef struct
+{
+ msg_t base;
+} msg_quit_t;
+
+typedef struct
+{
+ msg_t base;
+} msg_disconnect_t;
+
+static void msg_free(msg_t* msg);
+
+static msg_t* msg_connect(const gchar* url, const gchar* username,
+ const gchar* password);
+static msg_t* msg_connectresult(gboolean success, const gchar* errfmt, ...);
+static msg_t* msg_error(const gchar* format, ...);
+static msg_t* msg_disconnect(void);
+static msg_t* msg_quit(void);
+
+static gpointer worker_main(gpointer data);
+
int main(int argc, char** argv)
{
const gchar* gladefile;
@@ -45,11 +108,21 @@ int main(int argc, char** argv)
GtkTreeIter iter;
GtkCellRenderer* cell;
GtkTreeViewColumn* column;
+ GThread* worker;
+ worker_data_t worker_data;
g_thread_init(NULL);
gtk_init(&argc, &argv);
+ worker_data.queue = g_async_queue_new();
+ worker = g_thread_create(worker_main, &worker_data, TRUE, NULL);
+ if (worker == NULL)
+ {
+ fprintf(stderr, "Unable to create thread\n");
+ return EXIT_FAILURE;
+ }
+
builder = gtk_builder_new();
gladefile = DATAROOTDIR "viewtorrents/viewtorrents.glade";
ret = gtk_builder_add_from_file(builder, gladefile, &error);
@@ -146,6 +219,9 @@ int main(int argc, char** argv)
gtk_main();
+ g_async_queue_push(worker_data.queue, msg_quit());
+ g_async_queue_unref(worker_data.queue);
+
return EXIT_SUCCESS;
}
@@ -164,3 +240,191 @@ void torrent_update(torrent_t* torrent, GtkListStore* store, GtkTreeIter* iter)
torrent->seeded + 1000.0f,
-1);
}
+
+gpointer worker_main(gpointer _data)
+{
+ worker_data_t* data = _data;
+ xmlrpc_env env;
+ xmlrpc_client* client;
+ xmlrpc_server_info* server = NULL;
+ gboolean quit = FALSE;
+
+ data->queue = g_async_queue_ref(data->queue);
+
+ xmlrpc_env_init(&env);
+ xmlrpc_client_setup_global_const(&env);
+ xmlrpc_client_create(&env, XMLRPC_CLIENT_NO_FLAGS, "viewtorrents", "0.1",
+ NULL, 0, &client);
+ if (env.fault_occurred)
+ {
+ g_async_queue_push(data->queue,
+ msg_error("Unable to create XMLRPC-C client (%d): %s",
+ env.fault_code, env.fault_string));
+ quit = TRUE;
+ }
+
+ while (!quit)
+ {
+ msg_t* msg = g_async_queue_pop(data->queue);
+ switch (msg->type)
+ {
+ case MSG_CONNECT:
+ {
+ const gchar* tmp;
+ xmlrpc_value* params, * result;
+ msg_connect_t* m = (msg_connect_t*)msg;
+
+ server = xmlrpc_server_info_new(&env, m->url);
+ if (m->auth_username != NULL)
+ {
+ xmlrpc_server_info_set_user(&env, server,
+ m->auth_username,
+ m->auth_password);
+ xmlrpc_server_info_allow_auth_basic(&env, server);
+ }
+
+ params = xmlrpc_array_new(&env);
+ xmlrpc_client_call2(&env, client, server, "system.client_version",
+ params, &result);
+ if (env.fault_occurred)
+ {
+ xmlrpc_DECREF(params);
+ xmlrpc_server_info_free(server);
+ msg_free(msg);
+ server = NULL;
+ g_async_queue_push(data->queue,
+ msg_connectresult(FALSE,
+ "Unable to get client version (%d): %s",
+ env.fault_code, env.fault_string));
+ continue;
+ }
+ xmlrpc_DECREF(params);
+ xmlrpc_read_string(&env, result, &tmp);
+ if (env.fault_occurred)
+ {
+ xmlrpc_DECREF(result);
+ xmlrpc_server_info_free(server);
+ msg_free(msg);
+ server = NULL;
+ g_async_queue_push(data->queue,
+ msg_connectresult(FALSE,
+ "Unable to get client version (%d): %s",
+ env.fault_code, env.fault_string));
+ continue;
+ }
+ printf("result: %s\n", tmp);
+ xmlrpc_DECREF(result);
+ g_async_queue_push(data->queue, msg_connectresult(TRUE, NULL));
+ msg_free(msg);
+ break;
+ }
+ case MSG_DISCONNECT:
+ {
+ xmlrpc_server_info_free(server);
+ server = NULL;
+ break;
+ }
+ case MSG_QUIT:
+ break;
+ case MSG_CONNECTRESULT:
+ case MSG_ERROR:
+ g_assert(FALSE);
+ break;
+ }
+ }
+
+ if (server != NULL)
+ {
+ xmlrpc_server_info_free(server);
+ }
+ xmlrpc_client_destroy(client);
+ xmlrpc_client_teardown_global_const();
+ g_async_queue_unref(data->queue);
+ return NULL;
+}
+
+void msg_free(msg_t* msg)
+{
+ switch (msg->type)
+ {
+ case MSG_CONNECT:
+ {
+ msg_connect_t* m = (msg_connect_t*)msg;
+ g_free(m->url);
+ g_free(m->auth_username);
+ g_free(m->auth_password);
+ break;
+ }
+ case MSG_CONNECTRESULT:
+ {
+ msg_connectresult_t* m = (msg_connectresult_t*)msg;
+ g_free(m->errmsg);
+ break;
+ }
+ case MSG_ERROR:
+ {
+ msg_error_t* m = (msg_error_t*)msg;
+ g_free(m->msg);
+ break;
+ }
+ case MSG_DISCONNECT:
+ case MSG_QUIT:
+ break;
+ }
+ g_free(msg);
+}
+
+msg_t* msg_connect(const gchar* url, const gchar* username,
+ const gchar* password)
+{
+ msg_connect_t* msg = g_new0(msg_connect_t, 1);
+ msg->base.type = MSG_CONNECT;
+ msg->url = strdup(url);
+ msg->auth_username = g_strdup(username);
+ msg->auth_password = g_strdup(password);
+ return &msg->base;
+}
+
+msg_t* msg_connectresult(gboolean success, const gchar* errfmt, ...)
+{
+ msg_connectresult_t* msg = g_new0(msg_connectresult_t, 1);
+ msg->base.type = MSG_CONNECTRESULT;
+ if (success)
+ {
+ msg->success = TRUE;
+ }
+ else
+ {
+ va_list args;
+ msg->success = FALSE;
+ va_start(args, errfmt);
+ msg->errmsg = g_strdup_vprintf(errfmt, args);
+ va_end(args);
+ }
+ return &msg->base;
+}
+
+msg_t* msg_error(const gchar* format, ...)
+{
+ msg_error_t* msg = g_new0(msg_error_t, 1);
+ va_list args;
+ msg->base.type = MSG_ERROR;
+ va_start(args, format);
+ msg->msg = g_strdup_vprintf(format, args);
+ va_end(args);
+ return &msg->base;
+}
+
+msg_t* msg_disconnect(void)
+{
+ msg_disconnect_t* msg = g_new0(msg_disconnect_t, 1);
+ msg->base.type = MSG_DISCONNECT;
+ return &msg->base;
+}
+
+msg_t* msg_quit(void)
+{
+ msg_quit_t* msg = g_new0(msg_quit_t, 1);
+ msg->base.type = MSG_QUIT;
+ return &msg->base;
+}