#include "fmrxproxy.h" #include #include #include // Cannot really use QtDbus because lack of support for FD passing, pity. #define BUS_NAME "com.javispedro.fmrxd" #define BUS_PATH "/com/javispedro/fmrxd" #define BUS_INTERFACE BUS_NAME #define BUS_MATCH_RULE "type='signal',sender='" BUS_NAME "',interface='" BUS_INTERFACE "'" FmRxProxy::FmRxProxy(QObject *parent) : QObject(parent) { GError *gerr = NULL; DBusGConnection *gconn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &gerr); if (!gconn) { qWarning("Failed to connect to D-Bus: %s", gerr->message); g_error_free(gerr); } // From dbus-glib all we want is main loop integration, // the rest we use plain D-Bus. m_conn = dbus_g_connection_get_connection(gconn); dbus_bus_add_match(m_conn, BUS_MATCH_RULE, NULL); dbus_connection_add_filter(m_conn, bus_message_filter, this, NULL); } FmRxProxy::~FmRxProxy() { dbus_bus_remove_match(m_conn, BUS_MATCH_RULE, NULL); dbus_connection_remove_filter(m_conn, bus_message_filter, this); } int FmRxProxy::Connect() { DBusError err; dbus_bool_t ret; int fd; DBusMessage *reply; DBusMessage *msg = dbus_message_new_method_call(BUS_NAME, BUS_PATH, BUS_INTERFACE, "Connect"); Q_ASSERT(msg != NULL); dbus_error_init(&err); reply = dbus_connection_send_with_reply_and_block(m_conn, msg, -1, &err); dbus_message_unref(msg); if (!reply) { qWarning("Failed to Connect(): %s", err.message); dbus_error_free(&err); return -1; } ret = dbus_message_get_args(reply, &err, DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_INVALID); dbus_message_unref(reply); if (!ret) { qWarning("Failed to parse Connect() reply: %s", err.message); dbus_error_free(&err); return -1; } return fd; } void FmRxProxy::Tune(double f) { DBusError err; DBusMessage *reply; DBusMessage *msg = dbus_message_new_method_call(BUS_NAME, BUS_PATH, BUS_INTERFACE, "Tune"); Q_ASSERT(msg != NULL); dbus_error_init(&err); dbus_message_append_args(msg, DBUS_TYPE_DOUBLE, &f, DBUS_TYPE_INVALID); reply = dbus_connection_send_with_reply_and_block(m_conn, msg, -1, &err); dbus_message_unref(msg); if (!reply) { qWarning("Failed to Tune(): %s", err.message); dbus_error_free(&err); return; } dbus_message_unref(reply); } void FmRxProxy::SearchForward() { DBusMessage *msg = dbus_message_new_method_call(BUS_NAME, BUS_PATH, BUS_INTERFACE, "SearchForward"); Q_ASSERT(msg != NULL); dbus_connection_send(m_conn, msg, NULL); dbus_message_unref(msg); } void FmRxProxy::SearchBackward() { DBusMessage *msg = dbus_message_new_method_call(BUS_NAME, BUS_PATH, BUS_INTERFACE, "SearchBackward"); Q_ASSERT(msg != NULL); dbus_connection_send(m_conn, msg, NULL); dbus_message_unref(msg); } DBusHandlerResult FmRxProxy::bus_message_filter(DBusConnection *, DBusMessage *m, void *user_data) { FmRxProxy *self = reinterpret_cast(user_data); if (dbus_message_has_interface(m, BUS_INTERFACE)) { if (dbus_message_is_signal(m, BUS_INTERFACE, "Tuned")) { double freq; if (dbus_message_get_args(m, NULL, DBUS_TYPE_DOUBLE, &freq, DBUS_TYPE_INVALID)) { emit self->Tuned(freq); } } else if (dbus_message_is_signal(m, BUS_INTERFACE, "Stopped")) { emit self->Stopped(); } else if (dbus_message_is_signal(m, BUS_INTERFACE, "SignalLevelChanged")) { quint16 level; if (dbus_message_get_args(m, NULL, DBUS_TYPE_UINT16, &level, DBUS_TYPE_INVALID)) { emit self->SignalLevelChanged(level); } } else if (dbus_message_is_signal(m, BUS_INTERFACE, "PiReceived")) { quint16 pi; if (dbus_message_get_args(m, NULL, DBUS_TYPE_UINT16, &pi, DBUS_TYPE_INVALID)) { emit self->PiReceived(pi); } } else if (dbus_message_is_signal(m, BUS_INTERFACE, "PsReceived")) { char * s; if (dbus_message_get_args(m, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID)) { emit self->PsReceived(QString::fromUtf8(s)); } } else if (dbus_message_is_signal(m, BUS_INTERFACE, "RtReceived")) { char * s; if (dbus_message_get_args(m, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID)) { emit self->RtReceived(QString::fromUtf8(s)); } } } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; }