322 lines
7.9 KiB
C
322 lines
7.9 KiB
C
/***************************************************************************
|
|
|
|
c_dbusobserver.c
|
|
|
|
(c) 2000-2017 Benoît Minisini <gambas@users.sourceforge.net>
|
|
|
|
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, 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.
|
|
|
|
***************************************************************************/
|
|
|
|
#define __C_DBUSOBSERVER_C
|
|
|
|
#include "helper.h"
|
|
#include "c_dbusconnection.h"
|
|
#include "c_dbusobserver.h"
|
|
|
|
DECLARE_EVENT(EVENT_MESSAGE);
|
|
|
|
CDBUSOBSERVER *DBUS_observers = NULL;
|
|
|
|
void DBUS_raise_observer(CDBUSOBSERVER *_object)
|
|
{
|
|
GB.Raise(THIS, EVENT_MESSAGE, 0);
|
|
}
|
|
|
|
static char *add_rule(char *match, const char *name, const char *rule)
|
|
{
|
|
if (!rule)
|
|
return match;
|
|
|
|
if (rule[0] == '*' && rule[1] == 0)
|
|
return match;
|
|
|
|
if (match)
|
|
match = GB.AddChar(match, ',');
|
|
|
|
match = GB.AddString(match, name, 0);
|
|
match = GB.AddString(match, "='", 2);
|
|
match = GB.AddString(match, rule, 0);
|
|
match = GB.AddChar(match, '\'');
|
|
return match;
|
|
}
|
|
|
|
static void set_filter(char **property, const char *str, int len)
|
|
{
|
|
if (!str)
|
|
return;
|
|
|
|
if (len < 0)
|
|
len = strlen(str);
|
|
|
|
if (len == 0) // || (len == 1 && *str == '*'))
|
|
return;
|
|
|
|
*property = GB.NewString(str, len);
|
|
}
|
|
|
|
static void update_match(CDBUSOBSERVER *_object, bool noerr)
|
|
{
|
|
//static char *type[] = { "method_call", "method_return", "signal", "error" };
|
|
char *match = NULL;
|
|
DBusError error;
|
|
|
|
switch(THIS->type)
|
|
{
|
|
case DBUS_MESSAGE_TYPE_METHOD_CALL:
|
|
match = add_rule(match, "type", "method_call");
|
|
break;
|
|
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
|
|
match = add_rule(match, "type", "method_return");
|
|
break;
|
|
case DBUS_MESSAGE_TYPE_SIGNAL:
|
|
match = add_rule(match, "type", "signal");
|
|
break;
|
|
case DBUS_MESSAGE_TYPE_ERROR:
|
|
match = add_rule(match, "type", "error");
|
|
break;
|
|
default:
|
|
GB.Error("Invalid message type");
|
|
return;
|
|
}
|
|
|
|
match = add_rule(match, "path", THIS->object);
|
|
match = add_rule(match, "member", THIS->member);
|
|
match = add_rule(match, "interface", THIS->interface);
|
|
|
|
if (THIS->destination && *(THIS->destination))
|
|
match = add_rule(match, "destination", THIS->destination);
|
|
else
|
|
match = add_rule(match, "destination", dbus_bus_get_unique_name(THIS->connection));
|
|
|
|
dbus_error_init(&error);
|
|
|
|
DBUS_watch(THIS->connection, THIS->enabled);
|
|
|
|
if (THIS->enabled)
|
|
{
|
|
if (DBUS_Debug)
|
|
fprintf(stderr, "gb.dbus: add match: %s\n", match);
|
|
dbus_bus_add_match(THIS->connection, match, &error);
|
|
if (dbus_error_is_set(&error))
|
|
{
|
|
if (!noerr)
|
|
GB.Error("Cannot enable observer");
|
|
dbus_error_free(&error);
|
|
THIS->enabled = FALSE;
|
|
DBUS_watch(THIS->connection, FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (DBUS_Debug)
|
|
fprintf(stderr, "gb.dbus: remove match: %s\n", match);
|
|
dbus_bus_remove_match(THIS->connection, match, &error);
|
|
if (dbus_error_is_set(&error))
|
|
{
|
|
if (!noerr)
|
|
GB.Error("Cannot disable observer");
|
|
dbus_error_free(&error);
|
|
THIS->enabled = TRUE;
|
|
DBUS_watch(THIS->connection, TRUE);
|
|
}
|
|
}
|
|
|
|
dbus_connection_flush(THIS->connection);
|
|
|
|
GB.FreeString(&match);
|
|
}
|
|
|
|
BEGIN_METHOD(DBusObserver_new, GB_OBJECT connection; GB_INTEGER type; GB_STRING object; GB_STRING member; GB_STRING interface; GB_STRING destination)
|
|
|
|
CDBUSCONNECTION *connection = VARG(connection);
|
|
|
|
if (GB.CheckObject(connection))
|
|
return;
|
|
|
|
THIS->connection = connection->connection;
|
|
|
|
THIS->type = VARG(type);
|
|
if (!MISSING(object)) set_filter(&THIS->object, STRING(object), LENGTH(object));
|
|
if (!MISSING(member)) set_filter(&THIS->member, STRING(member), LENGTH(member));
|
|
if (!MISSING(interface)) set_filter(&THIS->interface, STRING(interface), LENGTH(interface));
|
|
if (!MISSING(destination)) set_filter(&THIS->destination, STRING(destination), LENGTH(destination));
|
|
|
|
THIS->next = DBUS_observers;
|
|
|
|
if (DBUS_observers)
|
|
DBUS_observers->prev = THIS;
|
|
|
|
DBUS_observers = THIS;
|
|
|
|
THIS->enabled = TRUE;
|
|
update_match(THIS, FALSE);
|
|
|
|
END_METHOD
|
|
|
|
BEGIN_METHOD_VOID(DBusObserver_free)
|
|
|
|
if (THIS->enabled)
|
|
{
|
|
THIS->enabled = FALSE;
|
|
update_match(THIS, TRUE);
|
|
}
|
|
|
|
if (THIS == DBUS_observers)
|
|
DBUS_observers = THIS->next;
|
|
|
|
if (THIS->prev)
|
|
THIS->prev->next = THIS->next;
|
|
|
|
if (THIS->next)
|
|
THIS->next->prev = THIS->prev;
|
|
|
|
GB.FreeString(&THIS->object);
|
|
GB.FreeString(&THIS->member);
|
|
GB.FreeString(&THIS->interface);
|
|
GB.FreeString(&THIS->destination);
|
|
|
|
END_METHOD
|
|
|
|
BEGIN_PROPERTY(DBusObserver_Enabled)
|
|
|
|
if (READ_PROPERTY)
|
|
GB.ReturnBoolean(THIS->enabled);
|
|
else
|
|
{
|
|
bool e = VPROP(GB_BOOLEAN);
|
|
if (e == THIS->enabled)
|
|
return;
|
|
THIS->enabled = e;
|
|
update_match(THIS, FALSE);
|
|
}
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
BEGIN_PROPERTY(DBusObserver_Message)
|
|
|
|
if (THIS->message)
|
|
RETURN_SELF();
|
|
else
|
|
GB.ReturnNull();
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
BEGIN_PROPERTY(DBusObserverMessage_Type)
|
|
|
|
GB.ReturnInteger(dbus_message_get_type(THIS->message));
|
|
|
|
END_PROPERTY
|
|
|
|
BEGIN_PROPERTY(DBusObserverMessage_Serial)
|
|
|
|
GB.ReturnInteger(dbus_message_get_serial(THIS->message));
|
|
|
|
END_PROPERTY
|
|
|
|
BEGIN_PROPERTY(DBusObserverMessage_Sender)
|
|
|
|
GB.ReturnConstZeroString(dbus_message_get_sender(THIS->message));
|
|
|
|
END_PROPERTY
|
|
|
|
BEGIN_PROPERTY(DBusObserverMessage_Destination)
|
|
|
|
GB.ReturnConstZeroString(dbus_message_get_destination(THIS->message));
|
|
|
|
END_PROPERTY
|
|
|
|
BEGIN_PROPERTY(DBusObserverMessage_Object)
|
|
|
|
GB.ReturnConstZeroString(dbus_message_get_path(THIS->message));
|
|
|
|
END_PROPERTY
|
|
|
|
BEGIN_PROPERTY(DBusObserverMessage_Interface)
|
|
|
|
GB.ReturnConstZeroString(dbus_message_get_interface(THIS->message));
|
|
|
|
END_PROPERTY
|
|
|
|
BEGIN_PROPERTY(DBusObserverMessage_Member)
|
|
|
|
GB.ReturnConstZeroString(dbus_message_get_member(THIS->message));
|
|
|
|
END_PROPERTY
|
|
|
|
BEGIN_PROPERTY(DBusObserverMessage_Arguments)
|
|
|
|
DBUS_retrieve_message_arguments(THIS->message);
|
|
|
|
END_PROPERTY
|
|
|
|
BEGIN_METHOD(DBusObserver_Reply, GB_STRING signature; GB_OBJECT args)
|
|
|
|
if (THIS->message)
|
|
{
|
|
if (!DBUS_reply(THIS->connection, THIS->message, MISSING(signature) ? NULL : GB.ToZeroString(ARG(signature)), VARGOPT(args, NULL)))
|
|
THIS->reply = TRUE;
|
|
}
|
|
|
|
END_METHOD
|
|
|
|
BEGIN_METHOD(DBusObserver_Error, GB_STRING type; GB_STRING error)
|
|
|
|
if (THIS->message)
|
|
{
|
|
if (!DBUS_error(THIS->connection, THIS->message, MISSING(error) ? NULL : GB.ToZeroString(ARG(error)), MISSING(type) ? NULL : GB.ToZeroString(ARG(type))))
|
|
THIS->reply = TRUE;
|
|
}
|
|
|
|
END_METHOD
|
|
|
|
GB_DESC CDBusObserverMessageDesc[] =
|
|
{
|
|
GB_DECLARE(".DBusObserver.Message", 0), GB_VIRTUAL_CLASS(),
|
|
|
|
GB_PROPERTY_READ("Type", "i", DBusObserverMessage_Type),
|
|
GB_PROPERTY_READ("Serial", "i", DBusObserverMessage_Serial),
|
|
GB_PROPERTY_READ("Sender", "s", DBusObserverMessage_Sender),
|
|
GB_PROPERTY_READ("Destination", "s", DBusObserverMessage_Destination),
|
|
GB_PROPERTY_READ("Object", "s", DBusObserverMessage_Object),
|
|
GB_PROPERTY_READ("Interface", "s", DBusObserverMessage_Interface),
|
|
GB_PROPERTY_READ("Member", "s", DBusObserverMessage_Member),
|
|
GB_PROPERTY_READ("Arguments", "Variant[]", DBusObserverMessage_Arguments),
|
|
|
|
GB_END_DECLARE
|
|
};
|
|
|
|
|
|
GB_DESC CDBusObserverDesc[] =
|
|
{
|
|
GB_DECLARE("DBusObserver", sizeof(CDBUSOBSERVER)),
|
|
|
|
GB_METHOD("_new", NULL, DBusObserver_new, "(Connection)DBusConnection;(Type)i[(Object)s(Member)s(Interface)s(Destination)s]"),
|
|
GB_METHOD("_free", NULL, DBusObserver_free, NULL),
|
|
|
|
//GB_PROPERTY("Tag", "v", DBusObserver_Tag),
|
|
GB_PROPERTY("Enabled", "b", DBusObserver_Enabled),
|
|
GB_PROPERTY_READ("Message", ".DBusObserver.Message", DBusObserver_Message),
|
|
GB_METHOD("Reply", NULL, DBusObserver_Reply, "[(Signature)s(Arguments)Array;]"),
|
|
GB_METHOD("Error", NULL, DBusObserver_Error, "[(Error)s(Type)s]"),
|
|
|
|
GB_EVENT("Message", NULL, NULL, &EVENT_MESSAGE),
|
|
|
|
GB_END_DECLARE
|
|
};
|
|
|