From ddaf39c3008febd7249ac32464143b61521df8a3 Mon Sep 17 00:00:00 2001 From: Jaidyn Ann Date: Wed, 23 Jun 2021 23:57:27 -0500 Subject: [PATCH] Returning libpurple protocol amount and names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The libpurple add-on has been split into two parts― a background process that will actually interface with libpurple, and an add-on that acts as intermediary between Cardie and the process. This helps prevent redundancy, and is giving me a lot less trouble that directly loading libpurple. The protocol amount and names are now returned by the add-on (through protocol_count() and protocol_at() respectively)― you can see them in Preferences' protocol list. --- protocols/purple/Makefile | 6 +- protocols/purple/PurpleApp.cpp | 170 ++++++++++++++++++++++++++++ protocols/purple/PurpleApp.h | 73 ++++++++++++ protocols/purple/PurpleMain.cpp | 65 ----------- protocols/purple/PurpleMessages.h | 43 +++++++ protocols/purple/PurpleProtocol.cpp | 149 ++++++++++++++++++++---- protocols/purple/PurpleProtocol.h | 51 ++++++--- protocols/purple/purple.rdef | 1 + 8 files changed, 450 insertions(+), 108 deletions(-) create mode 100644 protocols/purple/PurpleApp.cpp create mode 100644 protocols/purple/PurpleApp.h delete mode 100644 protocols/purple/PurpleMain.cpp create mode 100644 protocols/purple/PurpleMessages.h diff --git a/protocols/purple/Makefile b/protocols/purple/Makefile index 077c4b1..662bf60 100644 --- a/protocols/purple/Makefile +++ b/protocols/purple/Makefile @@ -15,10 +15,10 @@ NAME = protocols/purple # SHARED: Shared library or add-on # STATIC: Static library archive # DRIVER: Kernel driver -TYPE = SHARED +TYPE = APP # If you plan to use localization, specify the application's MIME signature. -APP_MIME_SIG = +APP_MIME_SIG = application/x-vnd.caya.purple # The following lines tell Pe and Eddie where the SRCS, RDEFS, and RSRCS are # so that Pe and Eddie can fill them in for you. @@ -32,7 +32,7 @@ APP_MIME_SIG = # same name (source.c or source.cpp) are included from different directories. # Also note that spaces in folder names do not work well with this Makefile. SRCS = \ - protocols/purple/PurpleMain.cpp \ + protocols/purple/PurpleApp.cpp \ protocols/purple/PurpleProtocol.cpp \ # Specify the resource definition files to use. Full or relative paths can be diff --git a/protocols/purple/PurpleApp.cpp b/protocols/purple/PurpleApp.cpp new file mode 100644 index 0000000..345710a --- /dev/null +++ b/protocols/purple/PurpleApp.cpp @@ -0,0 +1,170 @@ +/* + * Copyright 2021, Jaidyn Levesque + * Copyright 1998-2021, Pidgin/Finch/libpurple contributors + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "PurpleApp.h" + +#include + +#include +#include + + +int +main(int arc, char** argv) +{ + PurpleApp app; + app.Run(); + return 0; +} + + +PurpleApp::PurpleApp() + : + BApplication("application/x-vnd.cardie.purple") +{ + if (init_libpurple() != B_OK) + std::cerr << "libpurple initialization failed. Please report!\n"; + + _GetProtocolsInfo(); +} + + +void +PurpleApp::MessageReceived(BMessage* msg) +{ + int64 thread_id; + if (msg->FindInt64("thread_id", &thread_id) != B_OK) + return; + + switch (msg->what) + { + case PURPLE_REQUEST_PROTOCOL_COUNT: + { + send_data(thread_id, fProtocols.CountItems(), NULL, 0); + break; + } + case PURPLE_REQUEST_PROTOCOL_INFO: + { + int32 index = msg->FindInt32("index", 0); + ProtocolInfo* info = fProtocols.ItemAt(index); + + const char* nameConst = info->name.String(); + const char* idConst = info->id.String(); + char name[512] = { '\0' }; + char id[512] = { '\0' }; + strncpy(name, nameConst, 512); + strncpy(id, idConst, 512); + + send_data(thread_id, 0, name, sizeof(char) * 512); + send_data(thread_id, 0, id, sizeof(char) * 512); + break; + } + default: + BApplication::MessageReceived(msg); + } +} + + +void +PurpleApp::_GetProtocolsInfo() +{ + GList* listIter = purple_plugins_get_protocols(); + for (int i = 0; listIter; listIter = listIter->next) { + PurplePlugin* plugin = (PurplePlugin*)listIter->data; + PurplePluginInfo* info = (PurplePluginInfo*)plugin->info; + if (info) + _SaveProtocolInfo(info); + } +} + + +void +PurpleApp::_SaveProtocolInfo(PurplePluginInfo* info) +{ + ProtocolInfo* proto = new ProtocolInfo; + proto->id = info->id; + proto->name = info->name; + fProtocols.AddItem(proto); +} + + +static PurpleEventLoopUiOps _glib_eventloops = +{ + g_timeout_add, + g_source_remove, + _purple_glib_input_add, + g_source_remove, + NULL, + NULL, + NULL, + NULL, + NULL +}; + + +status_t +init_libpurple() +{ + purple_eventloop_set_ui_ops(&_glib_eventloops); + + if (!purple_core_init("cardie")) + return B_ERROR; + return B_OK; +} + + +static guint _purple_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 |= PURPLE_GLIB_READ_COND; +// if (condition & PURPLE_INPUT_WRITE) +// 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, g_free); + + g_io_channel_unref(channel); + return closure->result; +} + + +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 |= PURPLE_INPUT_READ; +// if (condition & PURPLE_GLIB_WRITE_COND) +// purple_cond |= PURPLE_INPUT_WRITE; + + closure->function(closure->data, g_io_channel_unix_get_fd(source), + purple_cond); + + return TRUE; +} diff --git a/protocols/purple/PurpleApp.h b/protocols/purple/PurpleApp.h new file mode 100644 index 0000000..edd3597 --- /dev/null +++ b/protocols/purple/PurpleApp.h @@ -0,0 +1,73 @@ +/* + * Copyright 2021, Jaidyn Levesque + * Copyright 1998-2021, Pidgin/Finch/libpurple contributors + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _PURPLE_APP_H +#define _PURPLE_APP_H + +#include + +#include +#include +#include + +#include "PurpleMessages.h" + + +#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; + +typedef struct _ProtocolInfo { + BString name; + BString id; +} ProtocolInfo; + + +int main(int argc, char** argv); + + +class PurpleApp : public BApplication { +public: + PurpleApp(); + virtual void MessageReceived(BMessage* msg); + +private: + void _GetProtocolsInfo(); + void _SaveProtocolInfo(PurplePluginInfo* info); + + + BObjectList fProtocols; +}; + + +status_t init_libpurple(); + +static guint _purple_glib_input_add(gint fd, PurpleInputCondition condition, + PurpleInputFunction function, gpointer data); +static gboolean _purple_glib_io_invoke(GIOChannel *source, + GIOCondition condition, gpointer data); + + +#endif // _PURPLE_APP_H diff --git a/protocols/purple/PurpleMain.cpp b/protocols/purple/PurpleMain.cpp deleted file mode 100644 index 55b7741..0000000 --- a/protocols/purple/PurpleMain.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright 2021, Jaidyn Levesque - - 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 2 - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "PurpleProtocol.h" - - -extern "C" _EXPORT ChatProtocol* protocol_at(int32 i); -extern "C" _EXPORT int32 protocol_count(); -extern "C" _EXPORT const char* signature(); -extern "C" _EXPORT const char* friendly_signature(); -extern "C" _EXPORT uint32 version(); - - -ChatProtocol* -protocol_at(int32 i) -{ - if (i == 0) - return (ChatProtocol*)new PurpleProtocol(); - return NULL; -} - - -int32 -protocol_count() -{ - return 1; -} - - -const char* -signature() -{ - return "purple"; -} - - -const char* -friendly_signature() -{ - return "Purple"; -} - - -uint32 -version() -{ - return APP_VERSION_1_PRE_ALPHA_1; -} - - diff --git a/protocols/purple/PurpleMessages.h b/protocols/purple/PurpleMessages.h new file mode 100644 index 0000000..5ad3bc6 --- /dev/null +++ b/protocols/purple/PurpleMessages.h @@ -0,0 +1,43 @@ +/* + * Copyright 2021, Jaidyn Levesque + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _PURPLE_MESSAGES_H +#define _PURPLE_MESSAGES_H + +#include + +enum purple_message { + /* + * Messages between the Purple add-on and server + */ + + /*! Request a count of protocols. →Server + * Response is sent directly to the requesting thread, + * use receive_data() to catch it. + * Requires: int64 thread_id */ + PURPLE_REQUEST_PROTOCOL_COUNT = 1, + + /*! Request protocol metadata. →Server + * Response is sent directly to the requesting thread, + * use receive_data() to catch it. + * Requires: int32 protocol_index, int64 thread_id */ + PURPLE_REQUEST_PROTOCOL_INFO = 2 +}; + + +#endif // _PURPLE_MESSAGESH diff --git a/protocols/purple/PurpleProtocol.cpp b/protocols/purple/PurpleProtocol.cpp index e5dcda6..862d286 100644 --- a/protocols/purple/PurpleProtocol.cpp +++ b/protocols/purple/PurpleProtocol.cpp @@ -1,31 +1,129 @@ /* - Copyright 2021, Jaidyn Levesque - - 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 2 - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ + * Copyright 2021, Jaidyn Levesque + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ #include "PurpleProtocol.h" -#include - -#include +#include +#include #include +#include "PurpleMessages.h" -PurpleProtocol::PurpleProtocol() + +BMessenger* kAppMessenger = NULL; + + +ChatProtocol* +protocol_at(int32 i) +{ + BMessenger* msgr = ensure_app_messenger(); + + BMessage* msg = new BMessage(PURPLE_REQUEST_PROTOCOL_INFO); + msg->AddInt64("thread_id", find_thread(NULL)); + msg->AddInt32("index", i); + msgr->SendMessage(msg); + + thread_id sender; + + char name[512] = { '\0' }; + char id[512] = { '\0' }; + receive_data(&sender, name, sizeof(char) * 512); + receive_data(&sender, id, sizeof(char) * 512); + + return (ChatProtocol*)new PurpleProtocol(name, id); +} + + +int32 +protocol_count() +{ + BMessage* msg = new BMessage(PURPLE_REQUEST_PROTOCOL_COUNT); + msg->AddInt64("thread_id", find_thread(NULL)); + ensure_app_messenger()->SendMessage(msg); + + thread_id sender; + int32 count = receive_data(&sender, NULL, 0); + return count; +} + + +const char* +signature() +{ + return "purple"; +} + + +const char* +friendly_signature() +{ + return "Purple"; +} + + +uint32 +version() +{ + return APP_VERSION_1_PRE_ALPHA_1; +} + + +BMessenger* +ensure_app_messenger() +{ + if (kAppMessenger == NULL || kAppMessenger->IsValid() == false) { + ensure_app(); + kAppMessenger = new BMessenger("application/x-vnd.cardie.purple"); + } + return kAppMessenger; +} + + +void +ensure_app() +{ + BRoster roster; + if (roster.IsRunning("application/x-vnd.cardie.purple") == true) + return; + + app_info aInfo; + be_app->GetAppInfo(&aInfo); + BPath protoPath(&aInfo.ref); + protoPath.GetParent(&protoPath); + protoPath.Append("protocols/purple"); + + entry_ref protoRef; + BEntry(protoPath.Path()).GetRef(&protoRef); + roster.Launch(&protoRef); +} + + +status_t +connect_thread(void* data) +{ +} + + +PurpleProtocol::PurpleProtocol(char name[512], char id[512]) + : + fSignature(id), + fFriendlySignature(name) { } @@ -55,6 +153,13 @@ PurpleProtocol::Process(BMessage* msg) status_t PurpleProtocol::UpdateSettings(BMessage* msg) { + thread_id thread = spawn_thread(connect_thread, "connect_thread", + B_NORMAL_PRIORITY, (void*)this); + + if (thread < B_OK) + return B_ERROR; + + resume_thread(thread); return B_OK; } @@ -96,14 +201,14 @@ PurpleProtocol::MenuBarItems() const char* PurpleProtocol::Signature() const { - return "purple"; + return fSignature.String(); } const char* PurpleProtocol::FriendlySignature() const { - return "Purple"; + return fFriendlySignature.String(); } diff --git a/protocols/purple/PurpleProtocol.h b/protocols/purple/PurpleProtocol.h index 82940f4..52dc140 100644 --- a/protocols/purple/PurpleProtocol.h +++ b/protocols/purple/PurpleProtocol.h @@ -1,20 +1,20 @@ /* - Copyright 2021, Jaidyn Levesque - - 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 2 - 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ + * Copyright 2021, Jaidyn Levesque + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ #ifndef _PURPLE_PROTOCOL_H #define _PURPLE_PROTOCOL_H @@ -25,9 +25,22 @@ #include +// Required protocol exports +extern "C" _EXPORT ChatProtocol* protocol_at(int32 i); +extern "C" _EXPORT int32 protocol_count(); +extern "C" _EXPORT const char* signature(); +extern "C" _EXPORT const char* friendly_signature(); +extern "C" _EXPORT uint32 version(); + +BMessenger* ensure_app_messenger(); +void ensure_app(); + +status_t connect_thread(void* data); + + class PurpleProtocol : public ChatProtocol { public: - PurpleProtocol(); + PurpleProtocol(char name[512], char id[512]); // ChatProtocol inheritance virtual status_t Init(ChatProtocolMessengerInterface* interface); @@ -61,11 +74,13 @@ public: private: ChatProtocolMessengerInterface* fMessenger; - thread_id fServerThread; BString fName; BPath fAddOnPath; + + BString fSignature; + BString fFriendlySignature; }; diff --git a/protocols/purple/purple.rdef b/protocols/purple/purple.rdef index 3c77956..b4d40a5 100644 --- a/protocols/purple/purple.rdef +++ b/protocols/purple/purple.rdef @@ -11,3 +11,4 @@ resource app_version { long_info = "©2021 Jaidyn Levesque" }; +resource app_flags B_SINGLE_LAUNCH | B_BACKGROUND_APP;