/*************************************************************************** c_dbusconnection.c (c) 2000-2017 BenoƮt Minisini 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_DBUSCONNECTION_C #include "helper.h" #include "c_dbusconnection.h" static CDBUSCONNECTION *_system = NULL; static CDBUSCONNECTION *_session = NULL; static DBusConnection *get_bus(DBusBusType type) { DBusConnection *conn; conn = dbus_bus_get(type, NULL); if (!conn) GB.Error("Cannot connect to the &1 bus", type == DBUS_BUS_SYSTEM ? "system" : "session"); else dbus_connection_set_exit_on_disconnect(conn, FALSE); return conn; } CDBUSCONNECTION *CDBUSCONNECTION_get(DBusBusType type) { DBusConnection *conn; if (type == DBUS_BUS_SYSTEM) { if (!_system) { conn = get_bus(type); if (conn) { _system = GB.New(GB.FindClass("DBusConnection"), NULL, NULL); GB.Ref(_system); _system->connection = conn; } } return _system; } else if (type == DBUS_BUS_SESSION) { if (!_session) { conn = get_bus(type); if (conn) { _session = GB.New(GB.FindClass("DBusConnection"), NULL, NULL); GB.Ref(_session); _session->connection = conn; } } return _session; } else return NULL; } BEGIN_METHOD_VOID(DBusConnection_exit) GB.Unref(POINTER(&_session)); GB.Unref(POINTER(&_system)); END_METHOD BEGIN_METHOD_VOID(DBusConnection_free) GB.StoreVariant(NULL, &THIS->tag); dbus_connection_unref(THIS->connection); END_METHOD BEGIN_METHOD(DBusConnection_Introspect, GB_STRING application; GB_STRING object) char *application = GB.ToZeroString(ARG(application)); char *object; if (!MISSING(object)) object = GB.ToZeroString(ARG(object)); else object = "/"; GB.ReturnNewZeroString(DBUS_introspect(THIS->connection, application, object)); END_METHOD BEGIN_METHOD(DBusConnection_CallMethod, GB_STRING application; GB_STRING object; GB_STRING interface; GB_STRING method; GB_STRING input_signature; GB_STRING output_signature; GB_OBJECT arguments) char *application = GB.ToZeroString(ARG(application)); char *object = GB.ToZeroString(ARG(object)); char *interface = GB.ToZeroString(ARG(interface)); char *method = GB.ToZeroString(ARG(method)); char *input_signature = GB.ToZeroString(ARG(input_signature)); char *output_signature = GB.ToZeroString(ARG(output_signature)); if (DBUS_validate_path(object, LENGTH(object))) { GB.Error("Invalid object path"); return; } if (!*interface) interface = NULL; else if (DBUS_validate_interface(interface, LENGTH(interface))) { GB.Error("Invalid interface name"); return; } if (DBUS_validate_method(method, LENGTH(method))) { GB.Error("Invalid method name"); return; } if (DBUS_call_method(THIS->connection, application, object, interface, method, input_signature, output_signature, VARG(arguments))) return; GB.ReturnConvVariant(); END_METHOD BEGIN_METHOD(DBusConnection_SendSignal, GB_STRING object; GB_STRING interface; GB_STRING signal; GB_STRING input_signature; GB_OBJECT arguments) char *object = GB.ToZeroString(ARG(object)); char *interface = GB.ToZeroString(ARG(interface)); char *signal = GB.ToZeroString(ARG(signal)); char *input_signature = GB.ToZeroString(ARG(input_signature)); if (DBUS_validate_path(object, LENGTH(object))) { GB.Error("Invalid object path"); return; } if (!*interface) interface = NULL; else if (DBUS_validate_interface(interface, LENGTH(interface))) { GB.Error("Invalid interface name"); return; } if (DBUS_validate_method(signal, LENGTH(signal))) { GB.Error("Invalid signal name"); return; } if (DBUS_send_signal(THIS->connection, object, interface, signal, input_signature, VARG(arguments))) return; END_METHOD BEGIN_PROPERTY(DBusConnection_Applications) DBUS_call_method(THIS->connection, "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "ListNames", "", "as", NULL); END_PROPERTY BEGIN_METHOD(DBusConnection_RequestName, GB_STRING name; GB_BOOLEAN unique) bool ret = DBUS_register(THIS->connection, GB.ToZeroString(ARG(name)), VARGOPT(unique, FALSE)); GB.ReturnBoolean(ret); END_METHOD BEGIN_METHOD(DBusConnection_ReleaseName, GB_STRING name) bool ret = DBUS_unregister(THIS->connection, GB.ToZeroString(ARG(name))); GB.ReturnBoolean(ret); END_METHOD BEGIN_PROPERTY(DBusConnection_Name) GB.ReturnNewZeroString(dbus_bus_get_unique_name(THIS->connection)); END_PROPERTY BEGIN_METHOD(DBusConnection_Register, GB_OBJECT object; GB_STRING path; GB_OBJECT interfaces) GB_FUNCTION func; void *object = VARG(object); if (GB.CheckObject(object)) return; if (GB.GetFunction(&func, object, "_Register", NULL, NULL)) { GB.Error("Cannot find _Register method"); return; } if (MISSING(interfaces)) { GB.Push(2, GB_T_OBJECT, THIS, GB_T_STRING, STRING(path), LENGTH(path)); GB.Call(&func, 2, TRUE); } else { GB.Push(3, GB_T_OBJECT, THIS, GB_T_STRING, STRING(path), LENGTH(path), GB_T_OBJECT, VARG(interfaces)); GB.Call(&func, 3, TRUE); } END_METHOD BEGIN_METHOD(DBusConnection_Unregister, GB_OBJECT object) GB_FUNCTION func; void *object = VARG(object); if (GB.CheckObject(object)) return; if (GB.GetFunction(&func, object, "_Unregister", NULL, NULL)) { GB.Error("Cannot find _Unregister method"); return; } GB.Push(1, GB_T_OBJECT, THIS); GB.Call(&func, 1, TRUE); END_METHOD BEGIN_PROPERTY(DBusConnection_Tag) if (READ_PROPERTY) GB.ReturnVariant(&THIS->tag); else GB.StoreVariant(PROP(GB_VARIANT), POINTER(&(THIS->tag))); END_METHOD GB_DESC CDBusConnectionDesc[] = { GB_DECLARE("DBusConnection", sizeof(CDBUSCONNECTION)), GB_NOT_CREATABLE(), GB_STATIC_METHOD("_exit", NULL, DBusConnection_exit, NULL), GB_METHOD("_free", NULL, DBusConnection_free, NULL), GB_METHOD("_Introspect", "s", DBusConnection_Introspect, "(Application)s[(Object)s]"), GB_METHOD("_CallMethod", "v", DBusConnection_CallMethod, "(Application)s(Object)s(Interface)s(Method)s(InputSignature)s(OutputSignature)s(Arguments)Array;"), GB_METHOD("_SendSignal", "v", DBusConnection_SendSignal, "(Object)s(Interface)s(Signal)s(InputSignature)s(Arguments)Array;"), //GB_METHOD("_AddMatch", "b", DBusConnection_AddMatch, "(Type)s[(Object)s(Member)s(Interface)s(Destination)s]"), //GB_METHOD("_RemoveMatch", "b", DBusConnection_RemoveMatch, "(Type)s[(Object)s(Member)s(Interface)s(Destination)s]"), GB_PROPERTY_READ("Applications", "String[]", DBusConnection_Applications), GB_METHOD("_RequestName", "b", DBusConnection_RequestName, "(Name)s[(Unique)b]"), GB_METHOD("_ReleaseName", "b", DBusConnection_ReleaseName, "(Name)s"), GB_PROPERTY_READ("_Name", "s", DBusConnection_Name), GB_METHOD("Register", NULL, DBusConnection_Register, "(Object)DBusObject;(Path)s[(Interface)String[];]"), GB_METHOD("Unregister", NULL, DBusConnection_Unregister, "(Object)DBusObject;"), GB_PROPERTY("Tag", "v", DBusConnection_Tag), GB_END_DECLARE };