]> git.zarvox.org Git - imoo.git/commitdiff
WIP on ribbon, a Qt libpurple client
authorDrew Fisher <drew.m.fisher@gmail.com>
Sat, 12 Apr 2014 08:35:20 +0000 (01:35 -0700)
committerDrew Fisher <drew.m.fisher@gmail.com>
Sat, 12 Apr 2014 08:35:20 +0000 (01:35 -0700)
ribbon/main.cpp [new file with mode: 0644]
ribbon/ribbon.pro [new file with mode: 0644]
ribbon/ribbonmanager.cpp [new file with mode: 0644]
ribbon/ribbonmanager.h [new file with mode: 0644]

diff --git a/ribbon/main.cpp b/ribbon/main.cpp
new file mode 100644 (file)
index 0000000..ae507c1
--- /dev/null
@@ -0,0 +1,38 @@
+//#include <QtCore/QCoreApplication>
+#include <QtGui/QApplication>
+#include <QDebug>
+
+#include <QObject>
+#include <QPushButton>
+
+#include <signal.h>
+
+#include "ribbonmanager.h"
+
+
+int main(int argc, char** argv)
+{
+       QApplication* app = new QApplication(argc, argv);
+       //GMainLoop *loop = g_main_loop_new(NULL, FALSE);
+
+       /* libpurple's built-in DNS resolution forks processes to perform
+        * blocking lookups without blocking the main process.  It does not
+        * handle SIGCHLD itself.  This is rather unsettling.
+        */
+       signal(SIGCHLD, SIG_IGN);
+
+       QPushButton* b = new QPushButton("Sign in");
+       b->resize(100,50);
+       b->show();
+
+       RibbonManager* purple = new RibbonManager();
+       purple->init_libpurple();
+
+       qDebug() << "libpurple initialized, version" << purple->get_version();
+
+       QObject::connect(b, SIGNAL(clicked()),
+                       purple, SLOT(sign_in_user()));
+
+       return app->exec();
+}
+
diff --git a/ribbon/ribbon.pro b/ribbon/ribbon.pro
new file mode 100644 (file)
index 0000000..03e93f3
--- /dev/null
@@ -0,0 +1,19 @@
+######################################################################
+# Automatically generated by qmake (2.01a) Wed Apr 9 18:55:15 2014
+######################################################################
+
+TEMPLATE = app
+TARGET = ribbon
+DEPENDPATH += .
+INCLUDEPATH += . 
+
+unix {
+       CONFIG += link_pkgconfig
+       PKGCONFIG += glib-2.0 purple
+}
+
+# Input
+HEADERS += ribbonmanager.h
+
+SOURCES += ribbonmanager.cpp \
+           main.cpp
diff --git a/ribbon/ribbonmanager.cpp b/ribbon/ribbonmanager.cpp
new file mode 100644 (file)
index 0000000..304fa03
--- /dev/null
@@ -0,0 +1,257 @@
+#include "ribbonmanager.h"
+
+#include <QDebug>
+#include <QFile>
+#include <libpurple/purple.h>
+#include <cstdio>
+
+/* Eventloop and glib IO stuff copied verbatim from nullclient.c */
+#define PURPLE_GLIB_READ_COND  (G_IO_IN | G_IO_HUP | G_IO_ERR)
+#define PURPLE_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
+
+typedef struct _PurpleGLibIOClosure {
+    PurpleInputFunction function;
+    guint result;
+    gpointer data;
+} PurpleGLibIOClosure;
+
+static void purple_glib_io_destroy(gpointer data)
+{
+    g_free(data);
+}
+
+static gboolean purple_glib_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+    PurpleGLibIOClosure *closure = (PurpleGLibIOClosure*)data;
+    PurpleInputCondition purple_cond = (PurpleInputCondition)0;
+
+    if (condition & PURPLE_GLIB_READ_COND)
+        purple_cond =  (PurpleInputCondition)(purple_cond | PURPLE_INPUT_READ);
+    if (condition & PURPLE_GLIB_WRITE_COND)
+        purple_cond =  (PurpleInputCondition)(purple_cond | PURPLE_INPUT_WRITE);
+
+    closure->function(closure->data, g_io_channel_unix_get_fd(source),
+        purple_cond);
+
+    return TRUE;
+}
+
+static guint glib_input_add(gint fd, PurpleInputCondition condition,
+    PurpleInputFunction function, gpointer data)
+{
+    PurpleGLibIOClosure *closure = g_new0(PurpleGLibIOClosure, 1);
+    GIOChannel *channel;
+    GIOCondition cond = (GIOCondition)0;
+
+    closure->function = function;
+    closure->data = data;
+
+    if (condition & PURPLE_INPUT_READ)
+        cond = (GIOCondition)(cond | PURPLE_GLIB_READ_COND);
+    if (condition & PURPLE_INPUT_WRITE)
+        cond = (GIOCondition)(cond | PURPLE_GLIB_WRITE_COND);
+
+    channel = g_io_channel_unix_new(fd);
+    closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT,
+        cond, purple_glib_io_invoke, closure, purple_glib_io_destroy);
+
+    g_io_channel_unref(channel);
+    return closure->result;
+}
+
+static PurpleEventLoopUiOps glib_eventloops =
+{
+    g_timeout_add, /* guint timeout_add(guint interval, GSourceFunc function, gpointer data) */
+    g_source_remove, /* gboolean timeout_remove(guint handle); */
+    glib_input_add, /* guint input_add(int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer user_data) */
+    g_source_remove, /* gboolean input_remove(guint handle) */
+    NULL, /* int input_get_error(int fd, int* error) */
+    g_timeout_add_seconds, /* guint timeout_add_seconds(guint interval, GSourceFunc function, gpointer data) */
+
+    /* padding */
+    //NULL,
+    NULL,
+    NULL,
+    NULL
+};
+/* End verbatim copied code */
+
+/* noops for now, add features later */
+static PurpleConversationUiOps ribbon_conversation_callbacks = {
+       NULL,                      /* create_conversation  */
+       NULL,                      /* destroy_conversation */
+       NULL,                      /* write_chat           */
+       NULL,                      /* write_im             */
+       NULL,                      /* write_conv           */
+       NULL,                      /* chat_add_users       */
+       NULL,                      /* chat_rename_user     */
+       NULL,                      /* chat_remove_users    */
+       NULL,                      /* chat_update_user     */
+       NULL,                      /* present              */
+       NULL,                      /* has_focus            */
+       NULL,                      /* custom_smiley_add    */
+       NULL,                      /* custom_smiley_write  */
+       NULL,                      /* custom_smiley_close  */
+       NULL,                      /* send_confirm         */
+       NULL,
+       NULL,
+       NULL,
+       NULL
+};
+
+static void connect_progress(PurpleConnection *gc, const char* text, size_t step, size_t step_count)
+{
+       Q_UNUSED(gc);
+       qDebug() << "Connection progress:" << text << step << "of" << step_count;
+}
+
+static void connection_notice(PurpleConnection *gc, const char* text)
+{
+       Q_UNUSED(gc);
+       qDebug() << "Connection notice:" << text;
+}
+
+static void connection_disconnected(PurpleConnection *gc, const char* text)
+{
+       Q_UNUSED(gc);
+       qDebug() << "Connection disconnected:" << text;
+}
+
+static void network_connected(void)
+{
+       printf("Network connection established\n");
+}
+
+static void network_disconnected(void)
+{
+       printf("This machine has been disconnected from the internet\n");
+}
+
+static void report_disconnect_reason(PurpleConnection *gc, PurpleConnectionError reason, const char *text)
+{
+       PurpleAccount *account = purple_connection_get_account(gc);
+       printf("Connection disconnected: \"%s\" (%s)\n  >Error: %d\n  >Reason: %s\n", purple_account_get_username(account), purple_account_get_protocol_id(account), reason, text);
+}
+
+static PurpleConnectionUiOps connection_uiops =
+{
+       connect_progress,          /* connect_progress         */
+       NULL,                      /* connected                */
+       NULL,                      /* disconnected             */
+       connection_notice,         /* notice                   */
+       connection_disconnected,   /* report_disconnect        */
+       network_connected,         /* network_connected        */
+       network_disconnected,      /* network_disconnected     */
+       report_disconnect_reason,  /* report_disconnect_reason */
+       NULL,
+       NULL,
+       NULL
+};
+
+static void ribbon_core_init(void) {
+       printf("core_init called\n");
+       printf("setting connection callbacks\n");
+       purple_connections_set_ui_ops(&connection_uiops);
+}
+
+static PurpleCoreUiOps ribbon_core_callbacks = {
+       NULL, /* ui_prefs_init - called just after preferences subsystem is initialized */
+       NULL, /* debug_ui_init - called just after the debug system is inited, but before other components init */
+       ribbon_core_init, /* ui_init - called after all of libpurple has been initialized */
+       NULL, /* quit - called after most of libpurple has been uninitialized */
+       NULL, /* get_ui_info - called by purple_core_get_ui_info, should return a
+                        GHashTable* with string key/value pairs containing info about the UI, like:
+                        name, version, website, dev_website */
+       /* padding */
+       //NULL,
+       NULL,
+       NULL,
+       NULL
+};
+
+static void signed_on(PurpleConnection *gc)
+{
+       PurpleAccount *account = purple_connection_get_account(gc);
+       printf("Account connected: \"%s\" (%s)\n", purple_account_get_username(account), purple_account_get_protocol_id(account));
+}
+
+static void received_im_msg(PurpleAccount *account, char *sender, char *message,
+                            PurpleConversation *conv, PurpleMessageFlags flags)
+{
+       Q_UNUSED(flags);
+       if (conv==NULL) {
+               conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender);
+       }
+       printf("(%s) %s (%s): %s\n", purple_utf8_strftime("%H:%M:%S", NULL), sender, purple_conversation_get_name(conv), message);
+}
+
+void connect_to_signals(void)
+{
+       static int handle;
+       purple_signal_connect(purple_connections_get_handle(), "signed-on", &handle,
+                       PURPLE_CALLBACK(signed_on), NULL);
+       purple_signal_connect(purple_conversations_get_handle(), "received-im-msg", &handle,
+                       PURPLE_CALLBACK(received_im_msg), NULL);
+}
+
+RibbonManager::RibbonManager(QObject* parent) : QObject(parent)
+{
+}
+
+RibbonManager::~RibbonManager()
+{
+}
+
+void RibbonManager::init_libpurple(void)
+{
+       /* optional:
+       purple_util_set_user_dir(CUSTOM_USER_DIRECTORY);
+       */
+
+       /* Enable debugging messages */
+       purple_debug_set_enabled(FALSE);
+
+       /* configure purple core callbacks */
+       purple_core_set_ui_ops(&ribbon_core_callbacks);
+       /* configure purple eventloop */
+       purple_eventloop_set_ui_ops(&glib_eventloops);
+       /* Init purple core */
+       if (!purple_core_init(UI_ID)) {
+               /* Initializing the core failed. Terminate. */
+               fprintf(stderr,
+                               "libpurple initialization failed. Dumping core.\n"
+                               "Please report this!\n");
+               abort();
+       }
+
+       /* Create and load the buddylist */
+       purple_set_blist(purple_blist_new());
+       purple_blist_load();
+
+       /* Hopefully this is an okay time for this? */
+       connect_to_signals();
+}
+
+const char* RibbonManager::get_version(void)
+{
+       return purple_core_get_version();
+}
+
+void RibbonManager::sign_in_user(void)
+{
+       QFile file("account.txt");
+       if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+               qDebug() << "Couldn't load account information from account.txt!";
+               return;
+       }
+       QByteArray protocol = file.readLine().trimmed();
+       QByteArray username = file.readLine().trimmed();
+       QByteArray password = file.readLine().trimmed();
+       // Allocate and enable an account.
+       // PurpleAccount *account = purple_account_new("YOUR_IM_ACCOUNTS_USERNAME_HERE", "prpl-IM_NETWORK_HERE"); //this could be prpl-aim, prpl-yahoo, prpl-msn, prpl-icq, etc.
+       PurpleAccount *account = purple_account_new(username.data(), protocol.data());
+       // purple_account_set_password(account, "YOUR_IM_ACCOUNTS_PASSWORD_HERE");
+       purple_account_set_password(account, password.data());
+       purple_accounts_add(account);
+       purple_account_set_enabled(account, UI_ID, TRUE);
+}
diff --git a/ribbon/ribbonmanager.h b/ribbon/ribbonmanager.h
new file mode 100644 (file)
index 0000000..a9d15f9
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef RIBBONMANAGER_H
+#define RIBBONMANAGER_H
+
+#include <QObject>
+
+#define UI_ID                  "ribbon"
+
+class RibbonManager : public QObject {
+       Q_OBJECT
+public:
+       RibbonManager(QObject* parent = 0);
+       ~RibbonManager();
+       void init_libpurple(void);
+       //void connect_to_signals(void);
+       const char* get_version(void);
+public slots:
+       void sign_in_user(void);
+private:
+
+};
+
+#endif /* RIBBONMANAGER_H */