Returning libpurple protocol amount and names

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.
This commit is contained in:
Jaidyn Ann 2021-06-23 23:57:27 -05:00
parent 6f3b375232
commit ddaf39c300
8 changed files with 450 additions and 108 deletions

View File

@ -15,10 +15,10 @@ NAME = protocols/purple
# SHARED: Shared library or add-on # SHARED: Shared library or add-on
# STATIC: Static library archive # STATIC: Static library archive
# DRIVER: Kernel driver # DRIVER: Kernel driver
TYPE = SHARED TYPE = APP
# If you plan to use localization, specify the application's MIME signature. # 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 # 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. # 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. # 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. # Also note that spaces in folder names do not work well with this Makefile.
SRCS = \ SRCS = \
protocols/purple/PurpleMain.cpp \ protocols/purple/PurpleApp.cpp \
protocols/purple/PurpleProtocol.cpp \ protocols/purple/PurpleProtocol.cpp \
# Specify the resource definition files to use. Full or relative paths can be # Specify the resource definition files to use. Full or relative paths can be

View File

@ -0,0 +1,170 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* 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 <iostream>
#include <glib.h>
#include <libpurple/purple.h>
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;
}

View File

@ -0,0 +1,73 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* 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 <libpurple/purple.h>
#include <Application.h>
#include <ObjectList.h>
#include <StringList.h>
#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<ProtocolInfo> 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

View File

@ -1,65 +0,0 @@
/*
Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
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;
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
*
* 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 <SupportDefs.h>
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

View File

@ -1,31 +1,129 @@
/* /*
Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io> * Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
*
This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
*
This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. * GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#include "PurpleProtocol.h" #include "PurpleProtocol.h"
#include <cstdio> #include <Application.h>
#include <Roster.h>
#include <StringList.h>
#include <ChatProtocolMessages.h> #include <ChatProtocolMessages.h>
#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 status_t
PurpleProtocol::UpdateSettings(BMessage* msg) 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; return B_OK;
} }
@ -96,14 +201,14 @@ PurpleProtocol::MenuBarItems()
const char* const char*
PurpleProtocol::Signature() const PurpleProtocol::Signature() const
{ {
return "purple"; return fSignature.String();
} }
const char* const char*
PurpleProtocol::FriendlySignature() const PurpleProtocol::FriendlySignature() const
{ {
return "Purple"; return fFriendlySignature.String();
} }

View File

@ -1,19 +1,19 @@
/* /*
Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io> * Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
*
This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
*
This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. * GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#ifndef _PURPLE_PROTOCOL_H #ifndef _PURPLE_PROTOCOL_H
@ -25,9 +25,22 @@
#include <ChatProtocol.h> #include <ChatProtocol.h>
// 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 { class PurpleProtocol : public ChatProtocol {
public: public:
PurpleProtocol(); PurpleProtocol(char name[512], char id[512]);
// ChatProtocol inheritance // ChatProtocol inheritance
virtual status_t Init(ChatProtocolMessengerInterface* interface); virtual status_t Init(ChatProtocolMessengerInterface* interface);
@ -61,11 +74,13 @@ public:
private: private:
ChatProtocolMessengerInterface* fMessenger; ChatProtocolMessengerInterface* fMessenger;
thread_id fServerThread; thread_id fServerThread;
BString fName; BString fName;
BPath fAddOnPath; BPath fAddOnPath;
BString fSignature;
BString fFriendlySignature;
}; };

View File

@ -11,3 +11,4 @@ resource app_version {
long_info = "©2021 Jaidyn Levesque" long_info = "©2021 Jaidyn Levesque"
}; };
resource app_flags B_SINGLE_LAUNCH | B_BACKGROUND_APP;