mirror of
https://github.com/netfun2000/lcd4linux.git
synced 2026-02-27 09:44:34 +08:00
event plugin and dbus interface by Ed Martin (forgot to add new files)
git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@1054 3ae390bd-cb1e-0410-b409-cd5a39f66f1f
This commit is contained in:
298
event.c
Normal file
298
event.c
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
/* $Id: event.c 1040 2009-09-23 04:14:17Z michael $
|
||||||
|
* $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/event.c $
|
||||||
|
*
|
||||||
|
* generic timer handling
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Ed Martin <edman007@edman007.com>
|
||||||
|
* Copyright (C) 2004, 2009 The LCD4Linux Team <lcd4linux-devel@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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* exported functions:
|
||||||
|
*
|
||||||
|
* int event_add(void (*callback) (void *data), void *data, const int fd, const int read, const int write);
|
||||||
|
* Adds a file description to watch
|
||||||
|
*
|
||||||
|
* int event_del(const int fd);
|
||||||
|
* Remove an event
|
||||||
|
*
|
||||||
|
* int event_modify(const int fd, const int read, const int write, const int active);
|
||||||
|
* Modify an event
|
||||||
|
*
|
||||||
|
* int named_event_add(char *event, void (*callback) (void *data), void *data);
|
||||||
|
* Add an event identified by a string
|
||||||
|
*
|
||||||
|
* int named_event_del(char *event, void (*callback) (void *data), void *data);
|
||||||
|
* delete the event identified by this string/callback/data
|
||||||
|
*
|
||||||
|
* int named_event_trigger(char *event); //call all calbacks for this event
|
||||||
|
* call the callbacks of all events that have identified as this string
|
||||||
|
*
|
||||||
|
* int event_process(const struct timespec *delay);
|
||||||
|
* process the event list
|
||||||
|
*
|
||||||
|
* void event_exit();
|
||||||
|
* releases all events
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
#include "cfg.h"
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
|
#ifdef WITH_DMALLOC
|
||||||
|
#include <dmalloc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void (*callback) (event_flags_t flags, void *data);
|
||||||
|
void *data;
|
||||||
|
int fd;
|
||||||
|
int read;
|
||||||
|
int write;
|
||||||
|
int active;
|
||||||
|
int fds_id;
|
||||||
|
} event_t;
|
||||||
|
|
||||||
|
|
||||||
|
//our set of FDs
|
||||||
|
static event_t *events = NULL;
|
||||||
|
static int event_count = 0;
|
||||||
|
static void free_events(void);
|
||||||
|
|
||||||
|
int event_add(void (*callback) (event_flags_t flags, void *data), void *data, const int fd, const int read,
|
||||||
|
const int write, const int active)
|
||||||
|
{
|
||||||
|
event_count++;
|
||||||
|
events = realloc(events, sizeof(event_t) * event_count);
|
||||||
|
|
||||||
|
int i = event_count - 1;
|
||||||
|
events[i].callback = callback;
|
||||||
|
events[i].data = data;
|
||||||
|
events[i].fd = fd;
|
||||||
|
events[i].read = read;
|
||||||
|
events[i].write = write;
|
||||||
|
events[i].active = active;
|
||||||
|
events[i].fds_id = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int event_process(const struct timespec *timeout)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
struct pollfd *fds = malloc(sizeof(struct pollfd) * event_count);
|
||||||
|
for (i = 0, j = 0; i < event_count; i++) {
|
||||||
|
events[i].fds_id = -1;
|
||||||
|
if (events[i].active) {
|
||||||
|
events[i].fds_id = j;
|
||||||
|
fds[j].events = 0;
|
||||||
|
fds[j].fd = events[i].fd;
|
||||||
|
if (events[i].read) {
|
||||||
|
fds[j].events |= POLLIN;
|
||||||
|
}
|
||||||
|
if (events[i].write) {
|
||||||
|
fds[j].events |= POLLOUT;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int ready = ppoll(fds, j, timeout, NULL);
|
||||||
|
|
||||||
|
if (ready > 0) {
|
||||||
|
//search the file descriptors, call all relavant callbacks
|
||||||
|
for (i = 0, j = 0; i < event_count; i++) {
|
||||||
|
if (events[i].fds_id != j) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (fds[j].revents) {
|
||||||
|
int flags = 0;
|
||||||
|
if (fds[j].revents & POLLIN) {
|
||||||
|
flags |= EVENT_READ;
|
||||||
|
}
|
||||||
|
if (fds[j].revents & POLLOUT) {
|
||||||
|
flags |= EVENT_WRITE;
|
||||||
|
}
|
||||||
|
if (fds[j].revents & POLLHUP) {
|
||||||
|
flags |= EVENT_HUP;
|
||||||
|
}
|
||||||
|
if (fds[j].revents & POLLERR) {
|
||||||
|
flags |= EVENT_ERR;
|
||||||
|
}
|
||||||
|
events[i].callback(flags, events[i].data);
|
||||||
|
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int event_del(const int fd)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < event_count; i++) {
|
||||||
|
if (events[i].fd == fd) {
|
||||||
|
events[i] = events[event_count - 1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
event_count--;
|
||||||
|
events = realloc(events, sizeof(event_t) * event_count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int event_modify(const int fd, const int read, const int write, const int active)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < event_count; i++) {
|
||||||
|
if (events[i].fd == fd) {
|
||||||
|
events[i].read = read;
|
||||||
|
events[i].write = write;
|
||||||
|
events[i].active = active;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
event_count--;
|
||||||
|
events = realloc(events, sizeof(event_t) * event_count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_events(void)
|
||||||
|
{
|
||||||
|
if (events != NULL) {
|
||||||
|
free(events);
|
||||||
|
}
|
||||||
|
event_count = 0;
|
||||||
|
events = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void event_exit(void)
|
||||||
|
{
|
||||||
|
free_events();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Named events are the user facing side of the event subsystem
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//we rely on "=" working for copying these structs (no pointers except the callers)
|
||||||
|
typedef struct {
|
||||||
|
void (*callback) (void *data);
|
||||||
|
void *data;
|
||||||
|
} event_callback_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
event_callback_t *c;
|
||||||
|
int callback_count;
|
||||||
|
} named_event_list_t;
|
||||||
|
|
||||||
|
|
||||||
|
static named_event_list_t *ev_names = NULL;
|
||||||
|
static int ev_count = 0;
|
||||||
|
|
||||||
|
int named_event_add(char *event, void (*callback) (void *data), void *data)
|
||||||
|
{
|
||||||
|
if (event == NULL || strlen(event) == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (callback == NULL) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < ev_count; i++) {
|
||||||
|
if (0 == strcmp(event, ev_names[i].name)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i >= ev_count) {
|
||||||
|
//create the entry
|
||||||
|
ev_count++;
|
||||||
|
ev_names = realloc(ev_names, sizeof(named_event_list_t) * ev_count);
|
||||||
|
ev_names[i].name = strdup(event);
|
||||||
|
ev_names[i].callback_count = 0;
|
||||||
|
ev_names[i].c = NULL;
|
||||||
|
}
|
||||||
|
int j = ev_names[i].callback_count;
|
||||||
|
ev_names[i].callback_count++;
|
||||||
|
ev_names[i].c = realloc(ev_names[i].c, sizeof(event_callback_t) * ev_names[i].callback_count);
|
||||||
|
|
||||||
|
ev_names[i].c[j].callback = callback;
|
||||||
|
ev_names[i].c[j].data = data;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int named_event_del(char *event, void (*callback) (void *data), void *data)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
for (i = 0; i < ev_count; i++) {
|
||||||
|
if (0 == strcmp(event, ev_names[i].name)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i >= ev_count) {
|
||||||
|
return 1; //nothing removed
|
||||||
|
}
|
||||||
|
for (j = 0; j < ev_names[i].callback_count; j++) {
|
||||||
|
if (ev_names[i].c[j].callback == callback && ev_names[i].c[j].data == data) {
|
||||||
|
ev_names[i].callback_count--;
|
||||||
|
ev_names[i].c[j] = ev_names[i].c[ev_names[i].callback_count];
|
||||||
|
ev_names[i].c = realloc(ev_names[i].c, sizeof(event_callback_t) * ev_names[i].callback_count);
|
||||||
|
if (ev_names[i].callback_count == 0) {
|
||||||
|
//drop this event
|
||||||
|
free(ev_names[i].name);
|
||||||
|
ev_count--;
|
||||||
|
ev_names[i] = ev_names[ev_count];
|
||||||
|
ev_names = realloc(ev_names, sizeof(named_event_list_t) * ev_count);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int named_event_trigger(char *event)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
for (i = 0; i < ev_count; i++) {
|
||||||
|
if (0 == strcmp(event, ev_names[i].name)) {
|
||||||
|
for (j = 0; j < ev_names[i].callback_count; j++) {
|
||||||
|
ev_names[i].c[j].callback(ev_names[i].c[j].data);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
66
event.h
Normal file
66
event.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/* $Id: event.h 840 2007-09-09 12:17:42Z michael $
|
||||||
|
* $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/event.h $
|
||||||
|
*
|
||||||
|
* generic timer handling
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Ed Martin <edman007@edman007.com>
|
||||||
|
* Copyright (C) 2009 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* This file is part of LCD4Linux.
|
||||||
|
*
|
||||||
|
* LCD4Linux 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.
|
||||||
|
*
|
||||||
|
* LCD4Linux 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _EVENT_H_
|
||||||
|
#define _EVENT_H_
|
||||||
|
|
||||||
|
//events are identified by their file descriptor only
|
||||||
|
|
||||||
|
/*
|
||||||
|
* these functions allow plugins to add event hooks
|
||||||
|
* (and thus break out of the main loop when sleeping)
|
||||||
|
* these callbacks than then trigger named events to propagate
|
||||||
|
* the event to the screen
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
EVENT_READ = 1,
|
||||||
|
EVENT_WRITE = 2,
|
||||||
|
EVENT_HUP = 4,
|
||||||
|
EVENT_ERR = 8
|
||||||
|
} event_flags_t;
|
||||||
|
|
||||||
|
|
||||||
|
int event_add(void (*callback) (event_flags_t flags, void *data), void *data, const int fd, const int read,
|
||||||
|
const int write, const int active);
|
||||||
|
int event_del(const int fd);
|
||||||
|
int event_modify(const int fd, const int read, const int write, const int active);
|
||||||
|
int event_process(const struct timespec *timeout);
|
||||||
|
void event_exit(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These fuctions keep a list of the events to trigger on allowing multiple
|
||||||
|
* things to trigger an event and multiple things to receive the event
|
||||||
|
*/
|
||||||
|
|
||||||
|
//add an event to be triggered
|
||||||
|
int named_event_add(char *event, void (*callback) (void *data), void *data);
|
||||||
|
//remove an event from the list of events
|
||||||
|
int named_event_del(char *event, void (*callback) (void *data), void *data);
|
||||||
|
int named_event_trigger(char *event); //call all calbacks for this event
|
||||||
|
|
||||||
|
#endif
|
||||||
803
plugin_dbus.c
Normal file
803
plugin_dbus.c
Normal file
@@ -0,0 +1,803 @@
|
|||||||
|
/* $Id: plugin_dbus.c -1 $
|
||||||
|
* $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/plugin_dbus.c $
|
||||||
|
*
|
||||||
|
* plugin template
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Edward Martin <edman007@edman007.com>
|
||||||
|
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* This file is part of LCD4Linux.
|
||||||
|
*
|
||||||
|
* LCD4Linux 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.
|
||||||
|
*
|
||||||
|
* LCD4Linux 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* exported functions:
|
||||||
|
*
|
||||||
|
* int plugin_init_dbus (void)
|
||||||
|
* adds various functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* define the include files you need */
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/* these should always be included */
|
||||||
|
#include "debug.h"
|
||||||
|
#include "plugin.h"
|
||||||
|
#include "cfg.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
#ifdef WITH_DMALLOC
|
||||||
|
#include <dmalloc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "event.h"
|
||||||
|
#include <dbus/dbus.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
/*
|
||||||
|
* Internal Text Storage (to catch the events)
|
||||||
|
*/
|
||||||
|
|
||||||
|
//a buffer of the most recent results (store the strings you see on the screen)
|
||||||
|
typedef struct {
|
||||||
|
int argc;
|
||||||
|
char **arguments;
|
||||||
|
} dbus_signal_t;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
int signals;
|
||||||
|
dbus_signal_t *a;
|
||||||
|
} dbus_results = {
|
||||||
|
0, NULL};
|
||||||
|
|
||||||
|
//free all resources for the text of a signal
|
||||||
|
static int clear_signal_txt(const int sig);
|
||||||
|
|
||||||
|
//return a pointer to the struct of text for the signal
|
||||||
|
static dbus_signal_t *get_signal_txt(const int sig);
|
||||||
|
|
||||||
|
//set the struct of text for the signal
|
||||||
|
static int set_signal_txt(const int sig, const dbus_signal_t * data);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DBus Functions/types
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//the max that a message may be in characters (if you have a screen that fits more go crazy)
|
||||||
|
static const int LCD_MAX_MSG_LEN = 255;
|
||||||
|
#define DBUS_MAX_SIGNALS 64
|
||||||
|
static const char *DBUS_PLUGIN_SECTION = "Plugin:DBus";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This connects to dbus and gets relavant things for the LCD
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct lcd_sig_t lcd_sig_t;
|
||||||
|
//do not look inside, its private!
|
||||||
|
struct lcd_sig_t {
|
||||||
|
void *user_data;
|
||||||
|
void (*callback) (void *user_data, int argc, char **argv);
|
||||||
|
void (*user_free) (void *);
|
||||||
|
char *sender;
|
||||||
|
char *path;
|
||||||
|
char *interface;
|
||||||
|
char *member;
|
||||||
|
char *rule;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int id;
|
||||||
|
char *event_name;
|
||||||
|
} handle_signal_t;
|
||||||
|
|
||||||
|
static DBusConnection *sessconn;
|
||||||
|
static DBusConnection *sysconn;
|
||||||
|
static DBusError err;
|
||||||
|
|
||||||
|
static lcd_sig_t *lcd_registered_signals[DBUS_MAX_SIGNALS]; //used mostly for freeing resources
|
||||||
|
static int registered_sig_count = 0;
|
||||||
|
|
||||||
|
//takes the signal, matches it against a rule, and sends the correct agrument, as a string, to the screen
|
||||||
|
static DBusHandlerResult lcd_sig_received(DBusConnection * connection, DBusMessage * message, void *sigv);
|
||||||
|
|
||||||
|
//frees all resources for a signal (use lcd_unregister_signal instead)
|
||||||
|
static void free_signal(lcd_sig_t * sig);
|
||||||
|
//unregisters a signal and frees its resources
|
||||||
|
static void lcd_unregister_signal(lcd_sig_t * sig);
|
||||||
|
|
||||||
|
//these copy data in/out of dbus
|
||||||
|
static void fill_args(DBusMessage * message, int *argcount, char ***argv);
|
||||||
|
static void free_args(int argc, char **argv);
|
||||||
|
|
||||||
|
//returns 0 on error (no connection opened)
|
||||||
|
// 1 when only the system connection was opened
|
||||||
|
// 2 when only the session connection was opened
|
||||||
|
// 3 both connections were opened
|
||||||
|
static int lcd_dbus_init(void);
|
||||||
|
|
||||||
|
static void handle_inbound_signal(void *signal, int argc, char **argv);
|
||||||
|
|
||||||
|
//given a signal, will add a hook so when the signal appears your callback is called
|
||||||
|
static lcd_sig_t *lcd_register_signal(const char *sender, const char *path,
|
||||||
|
const char *interface, const char *member,
|
||||||
|
void (*callback) (void *user_data, int argc, char **argv), void *user_data,
|
||||||
|
void (*user_free) (void *));
|
||||||
|
|
||||||
|
static void setup_dbus_events(DBusConnection * conn);
|
||||||
|
|
||||||
|
//to handle watches through the main loop
|
||||||
|
static dbus_bool_t add_watch(DBusWatch * w, void *data);
|
||||||
|
static void remove_watch(DBusWatch * w, void *data);
|
||||||
|
static void toggle_watch(DBusWatch * w, void *data);
|
||||||
|
static void watch_handle(event_flags_t f, void *data);
|
||||||
|
|
||||||
|
static void dispatch_dbus(void); //tell dbus to read something
|
||||||
|
|
||||||
|
|
||||||
|
//to handle timers through the main loop
|
||||||
|
static void timeout_dbus_handle(void *data);
|
||||||
|
static dbus_bool_t add_dbus_timeout(DBusTimeout * t, void *data);
|
||||||
|
static void remove_dbus_timeout(DBusTimeout * t, void *data);
|
||||||
|
static void toggle_dbus_timeout(DBusTimeout * t, void *data);
|
||||||
|
|
||||||
|
static lcd_sig_t *create_signal(const char *sender, const char *path,
|
||||||
|
const char *interface, const char *member,
|
||||||
|
void (*callback) (void *user_data, int argc, char **argv), void *user_data,
|
||||||
|
void (*user_free) (void *));
|
||||||
|
|
||||||
|
static int clear_signal_txt(const int sig)
|
||||||
|
{
|
||||||
|
dbus_signal_t *s = get_signal_txt(sig);
|
||||||
|
if (s == NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
s->argc = 0;
|
||||||
|
if (s->arguments != NULL) {
|
||||||
|
free(s->arguments);
|
||||||
|
s->arguments = NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static dbus_signal_t *get_signal_txt(const int sig)
|
||||||
|
{
|
||||||
|
if (sig < 0 || sig >= dbus_results.signals) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return &dbus_results.a[sig];
|
||||||
|
}
|
||||||
|
|
||||||
|
//sets a signal struct for the given data
|
||||||
|
static int set_signal_txt(const int sig, const dbus_signal_t * data)
|
||||||
|
{
|
||||||
|
if (sig < 0 || sig >= dbus_results.signals) {
|
||||||
|
int new_sigs = sig + 1;
|
||||||
|
//allocate it
|
||||||
|
dbus_results.a = realloc(dbus_results.a, sizeof(dbus_signal_t *) * new_sigs);
|
||||||
|
int i;
|
||||||
|
//clear anything just allocated that we are not writing to right now
|
||||||
|
for (i = dbus_results.signals + 1; i < new_sigs; i++) {
|
||||||
|
dbus_results.a[i].argc = 0;
|
||||||
|
dbus_results.a[i].arguments = NULL;
|
||||||
|
}
|
||||||
|
dbus_results.signals = new_sigs;
|
||||||
|
}
|
||||||
|
//free the old version
|
||||||
|
if (dbus_results.a[sig].argc != 0) {
|
||||||
|
clear_signal_txt(sig);
|
||||||
|
}
|
||||||
|
dbus_results.a[sig].argc = data->argc;
|
||||||
|
//need to dup the strings
|
||||||
|
dbus_results.a[sig].arguments = malloc(sizeof(data->arguments) * data->argc);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < data->argc; i++) {
|
||||||
|
dbus_results.a[sig].arguments[i] = strdup(data->arguments[i]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lcd4linux interface fucntions
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static void get_argument(RESULT * result, RESULT * sig, RESULT * arg)
|
||||||
|
{
|
||||||
|
int signal = (int) R2N(sig);
|
||||||
|
int argument = (int) R2N(arg);
|
||||||
|
|
||||||
|
dbus_signal_t *signal_value = get_signal_txt(signal);
|
||||||
|
char *value = "";
|
||||||
|
if (signal_value != NULL && signal_value->argc > argument && signal_value->arguments[argument] != NULL) {
|
||||||
|
value = signal_value->arguments[argument];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store result */
|
||||||
|
SetResult(&result, R_STRING, value);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_arguments(RESULT * result, RESULT * sig)
|
||||||
|
{
|
||||||
|
int signal = (int) R2N(sig);
|
||||||
|
dbus_signal_t *signal_value = get_signal_txt(signal);
|
||||||
|
int i;
|
||||||
|
if (signal_value->arguments != NULL) {
|
||||||
|
for (i = 0; i < signal_value->argc; i++) {
|
||||||
|
if (signal_value->arguments[i] != NULL) {
|
||||||
|
free(signal_value->arguments[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(signal_value->arguments);
|
||||||
|
signal_value->arguments = NULL;
|
||||||
|
}
|
||||||
|
signal_value->argc = 0;
|
||||||
|
|
||||||
|
/* store result */
|
||||||
|
SetResult(&result, R_STRING, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_dbus_cfg(void)
|
||||||
|
{
|
||||||
|
char *sender, *path, *interface, *member, *eventname;
|
||||||
|
int i;
|
||||||
|
const char *sender_fmt = "signal%dsender";
|
||||||
|
const char *path_fmt = "signal%dpath";
|
||||||
|
const char *interface_fmt = "signal%dinterface";
|
||||||
|
const char *member_fmt = "signal%dmember";
|
||||||
|
const char *eventname_fmt = "signal%deventname";
|
||||||
|
const int max_cfg_len = 32;
|
||||||
|
char cfg_name[max_cfg_len];
|
||||||
|
for (i = 0; i < DBUS_MAX_SIGNALS; i++) {
|
||||||
|
snprintf(cfg_name, max_cfg_len - 1, sender_fmt, i);
|
||||||
|
sender = cfg_get(DBUS_PLUGIN_SECTION, cfg_name, "");
|
||||||
|
|
||||||
|
snprintf(cfg_name, max_cfg_len - 1, path_fmt, i);
|
||||||
|
path = cfg_get(DBUS_PLUGIN_SECTION, cfg_name, "");
|
||||||
|
|
||||||
|
snprintf(cfg_name, max_cfg_len - 1, interface_fmt, i);
|
||||||
|
interface = cfg_get(DBUS_PLUGIN_SECTION, cfg_name, "");
|
||||||
|
|
||||||
|
snprintf(cfg_name, max_cfg_len - 1, member_fmt, i);
|
||||||
|
member = cfg_get(DBUS_PLUGIN_SECTION, cfg_name, "");
|
||||||
|
|
||||||
|
snprintf(cfg_name, max_cfg_len - 1, eventname_fmt, i);
|
||||||
|
eventname = cfg_get(DBUS_PLUGIN_SECTION, cfg_name, "");
|
||||||
|
|
||||||
|
if (*path == '\0' && *interface == '\0' && *member == '\0') {
|
||||||
|
continue;
|
||||||
|
} else if (*path == '\0' || *interface == '\0' || *member == '\0') {
|
||||||
|
error("[DBus] Incomplete configuration specified for signal%d", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_signal_t *sig_info = malloc(sizeof(handle_signal_t));
|
||||||
|
sig_info->id = i;
|
||||||
|
if (*eventname == '\0') {
|
||||||
|
sig_info->event_name = NULL;
|
||||||
|
} else {
|
||||||
|
sig_info->event_name = strdup(eventname);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lcd_register_signal(sender, path, interface, member, handle_inbound_signal, sig_info, free)) {
|
||||||
|
error("[DBus] Error Registering signal %d", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* plugin initialization */
|
||||||
|
int plugin_init_dbus(void)
|
||||||
|
{
|
||||||
|
if (!lcd_dbus_init()) {
|
||||||
|
error("[DBus] Could not connect to DBus");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//dbus::argument(<DisplaySignal>, <Argument#>)//displays arg# for signal#
|
||||||
|
AddFunction("dbus::argument", 2, get_argument);
|
||||||
|
//dbus::clear(<signal>)//sets the arguments for signal#
|
||||||
|
AddFunction("dbus::clear", 1, clear_arguments);
|
||||||
|
|
||||||
|
//read out config
|
||||||
|
load_dbus_cfg();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_exit_dbus(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
//remove all known signals
|
||||||
|
for (i = registered_sig_count - 1; i >= 0; i--) {
|
||||||
|
lcd_unregister_signal(lcd_registered_signals[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove all knows signal results
|
||||||
|
for (i = dbus_results.signals - 1; i >= 0; i--) {
|
||||||
|
clear_signal_txt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From here one out it is all dbus specific funtions,
|
||||||
|
* should probably be split into a seperate file, but i
|
||||||
|
* keept it here to make the plugin a single file
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
//watch functions
|
||||||
|
static dbus_bool_t add_watch(DBusWatch * w, void *data)
|
||||||
|
{
|
||||||
|
(void) data; //ignore it
|
||||||
|
int fd = dbus_watch_get_unix_fd(w); //we assume we are using unix
|
||||||
|
int flags = dbus_watch_get_flags(w);
|
||||||
|
event_add(watch_handle, w, fd, flags & DBUS_WATCH_READABLE, flags & DBUS_WATCH_WRITABLE, dbus_watch_get_enabled(w));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_watch(DBusWatch * w, void *data)
|
||||||
|
{
|
||||||
|
(void) data; //ignore it
|
||||||
|
event_del(dbus_watch_get_unix_fd(w));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void toggle_watch(DBusWatch * w, void *data)
|
||||||
|
{
|
||||||
|
int fd = dbus_watch_get_unix_fd(w); //we assume we are using unix
|
||||||
|
int flags = dbus_watch_get_flags(w);
|
||||||
|
event_modify(fd, flags & DBUS_WATCH_READABLE, flags & DBUS_WATCH_WRITABLE, dbus_watch_get_enabled(w));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void watch_handle(event_flags_t f, void *data)
|
||||||
|
{
|
||||||
|
DBusWatch *w = (DBusWatch *) data;
|
||||||
|
|
||||||
|
//convert the flags
|
||||||
|
unsigned int flags = 0;
|
||||||
|
|
||||||
|
flags |= (f & EVENT_READ) ? DBUS_WATCH_READABLE : 0;
|
||||||
|
flags |= (f & EVENT_WRITE) ? DBUS_WATCH_WRITABLE : 0;
|
||||||
|
flags |= (f & EVENT_HUP) ? DBUS_WATCH_HANGUP : 0;
|
||||||
|
flags |= (f & EVENT_ERR) ? DBUS_WATCH_ERROR : 0;
|
||||||
|
|
||||||
|
//tell dbus
|
||||||
|
if (!dbus_watch_handle(w, flags)) {
|
||||||
|
info("[DBus] dbus_watch_handle(): Not enough memory!");
|
||||||
|
}
|
||||||
|
dispatch_dbus();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dispatch_dbus(void)
|
||||||
|
{
|
||||||
|
if (sessconn != NULL && dbus_connection_get_dispatch_status(sessconn) == DBUS_DISPATCH_DATA_REMAINS) {
|
||||||
|
while (DBUS_DISPATCH_DATA_REMAINS == dbus_connection_dispatch(sessconn));
|
||||||
|
}
|
||||||
|
if (sysconn != NULL && dbus_connection_get_dispatch_status(sysconn) == DBUS_DISPATCH_DATA_REMAINS) {
|
||||||
|
while (DBUS_DISPATCH_DATA_REMAINS == dbus_connection_dispatch(sysconn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void timeout_dbus_handle(void *data)
|
||||||
|
{
|
||||||
|
DBusTimeout *t = (DBusTimeout *) data;
|
||||||
|
if (!dbus_timeout_handle(t)) {
|
||||||
|
info("[DBus] Not enough memory to handle timeout!");
|
||||||
|
}
|
||||||
|
dispatch_dbus();
|
||||||
|
}
|
||||||
|
|
||||||
|
static dbus_bool_t add_dbus_timeout(DBusTimeout * t, void *data)
|
||||||
|
{
|
||||||
|
(void) data; //ignore warning
|
||||||
|
if (!timer_add_late(timeout_dbus_handle, t, dbus_timeout_get_interval(t), 0)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void remove_dbus_timeout(DBusTimeout * t, void *data)
|
||||||
|
{
|
||||||
|
(void) data; //ignore warning
|
||||||
|
timer_remove(timeout_dbus_handle, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void toggle_dbus_timeout(DBusTimeout * t, void *data)
|
||||||
|
{
|
||||||
|
remove_dbus_timeout(t, data);
|
||||||
|
add_dbus_timeout(t, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
//add the proper events/callbacks so we get notified about out messages
|
||||||
|
static void setup_dbus_events(DBusConnection * conn)
|
||||||
|
{
|
||||||
|
if (!dbus_connection_set_watch_functions(conn, add_watch, remove_watch, toggle_watch, NULL, NULL)) {
|
||||||
|
error("[DBus] dbus_connection_set_watch_functions(): Not enough memory!");
|
||||||
|
}
|
||||||
|
if (!dbus_connection_set_timeout_functions
|
||||||
|
(conn, add_dbus_timeout, remove_dbus_timeout, toggle_dbus_timeout, NULL, NULL)) {
|
||||||
|
error("[DBus] dbus_connection_set_timeout_functions(): Not enough memory!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lcd_dbus_init(void)
|
||||||
|
{
|
||||||
|
int success = 3;
|
||||||
|
dbus_error_init(&err); //dbus_error_free(&err);
|
||||||
|
sessconn = dbus_bus_get(DBUS_BUS_SESSION, &err);
|
||||||
|
if (sessconn == NULL) {
|
||||||
|
info("[DBus] Error connecting to the dbus session bus: %s\n", err.message);
|
||||||
|
dbus_error_free(&err);
|
||||||
|
success &= 1;
|
||||||
|
} else {
|
||||||
|
setup_dbus_events(sessconn);
|
||||||
|
}
|
||||||
|
|
||||||
|
sysconn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
|
||||||
|
if (sysconn == NULL) {
|
||||||
|
info("[DBus] Error connecting to the dbus system bus: %s\n", err.message);
|
||||||
|
success &= 2;
|
||||||
|
} else {
|
||||||
|
setup_dbus_events(sysconn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lcd_sig_t *create_signal(const char *sender, const char *path,
|
||||||
|
const char *interface, const char *member,
|
||||||
|
void (*callback) (void *user_data, int argc, char **argv), void *user_data,
|
||||||
|
void (*user_free) (void *))
|
||||||
|
{
|
||||||
|
lcd_sig_t *sig = malloc(sizeof(lcd_sig_t));
|
||||||
|
sig->callback = callback;
|
||||||
|
sig->user_data = user_data;
|
||||||
|
sig->user_free = user_free;
|
||||||
|
sig->sender = malloc(sizeof(char) * (1 + strlen(sender)));
|
||||||
|
strcpy(sig->sender, sender);
|
||||||
|
sig->path = malloc(sizeof(char) * (1 + strlen(path)));
|
||||||
|
strcpy(sig->path, path);
|
||||||
|
sig->interface = malloc(sizeof(char) * (1 + strlen(interface)));
|
||||||
|
strcpy(sig->interface, interface);
|
||||||
|
sig->member = malloc(sizeof(char) * (1 + strlen(member)));
|
||||||
|
strcpy(sig->member, member);
|
||||||
|
|
||||||
|
size_t len = strlen(sender) + strlen(path) + strlen(interface) + strlen(member);
|
||||||
|
char *format;
|
||||||
|
if (strlen(sig->sender) == 0) {
|
||||||
|
format = "type='signal',path='%s',interface='%s',member='%s'";
|
||||||
|
} else {
|
||||||
|
format = "type='signal',sender='%s',path='%s',interface='%s',member='%s'";
|
||||||
|
}
|
||||||
|
len += strlen(format);
|
||||||
|
len *= sizeof(char);
|
||||||
|
sig->rule = malloc(len);
|
||||||
|
if (strlen(sig->sender) == 0) {
|
||||||
|
sprintf(sig->rule, format, path, interface, member);
|
||||||
|
} else {
|
||||||
|
sprintf(sig->rule, format, sender, path, interface, member);
|
||||||
|
}
|
||||||
|
assert(strlen(sig->rule) < len);
|
||||||
|
return sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_inbound_signal(void *signal, int argc, char **argv)
|
||||||
|
{
|
||||||
|
handle_signal_t *signal_info = (handle_signal_t *) signal;
|
||||||
|
dbus_signal_t sig;
|
||||||
|
sig.argc = argc;
|
||||||
|
sig.arguments = argv;
|
||||||
|
set_signal_txt(signal_info->id, &sig);
|
||||||
|
debug("[DBUS] Got Signal");
|
||||||
|
if (signal_info->event_name != NULL) {
|
||||||
|
debug("[DBUS] Calling Screen update");
|
||||||
|
named_event_trigger(signal_info->event_name);
|
||||||
|
}
|
||||||
|
free_args(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static lcd_sig_t *lcd_register_signal(const char *sender, const char *path,
|
||||||
|
const char *interface, const char *member,
|
||||||
|
void (*callback) (void *user_data, int argc, char **argv), void *user_data,
|
||||||
|
void (*user_free) (void *))
|
||||||
|
{
|
||||||
|
if (__builtin_expect(registered_sig_count >= DBUS_MAX_SIGNALS, 0)) { //gcc >= 2.96
|
||||||
|
//i don't think anything will allow this to ever be hit..in fact It's impossible in the form i wrote the plugin
|
||||||
|
error
|
||||||
|
("[DBus] Attempted to add more than %d dus signals, if you actually need more than that edit DBUS_MAX_SIGNALS in plugin_dbus.c",
|
||||||
|
DBUS_MAX_SIGNALS);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
//store everything we need in the singal struct
|
||||||
|
lcd_sig_t *sig = create_signal(sender, path, interface, member, callback, user_data, user_free);
|
||||||
|
int success = 3;
|
||||||
|
if (sessconn != NULL) {
|
||||||
|
dbus_bus_add_match(sessconn, sig->rule, &err);
|
||||||
|
if (dbus_error_is_set(&err)) {
|
||||||
|
info("[DBus] Error adding dbus match to the session bus: %s \n", err.message);
|
||||||
|
dbus_error_free(&err);
|
||||||
|
success ^= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!dbus_connection_add_filter(sessconn, lcd_sig_received, sig, NULL) && (success & 1)) {
|
||||||
|
info("[DBus] Dbus signal registration failed to the session bus!\n");
|
||||||
|
dbus_bus_remove_match(sessconn, sig->rule, &err);
|
||||||
|
success ^= 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
success ^= 1;
|
||||||
|
}
|
||||||
|
if (sysconn != NULL) {
|
||||||
|
dbus_bus_add_match(sysconn, sig->rule, &err);
|
||||||
|
if (dbus_error_is_set(&err)) {
|
||||||
|
info("[DBus] Error adding dbus match to the system bus: %s \n", err.message);
|
||||||
|
success ^= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dbus_connection_add_filter(sysconn, lcd_sig_received, sig, NULL) && (success & 2)) {
|
||||||
|
info("[DBus] Dbus signal registration failed to the system bus!\n");
|
||||||
|
dbus_bus_remove_match(sysconn, sig->rule, &err);
|
||||||
|
success ^= 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
success ^= 2;
|
||||||
|
}
|
||||||
|
if (!success) {
|
||||||
|
free_signal(sig);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
lcd_registered_signals[registered_sig_count] = sig;
|
||||||
|
registered_sig_count++;
|
||||||
|
return sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_signal(lcd_sig_t * sig)
|
||||||
|
{
|
||||||
|
if (sig->user_free != NULL) {
|
||||||
|
sig->user_free(sig->user_data);
|
||||||
|
}
|
||||||
|
free(sig->sender);
|
||||||
|
free(sig->path);
|
||||||
|
free(sig->interface);
|
||||||
|
free(sig->member);
|
||||||
|
free(sig->rule);
|
||||||
|
free(sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lcd_unregister_signal(lcd_sig_t * sig)
|
||||||
|
{
|
||||||
|
if (sig == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
info("[DBus] Unregistering signal %p!", sig);
|
||||||
|
//remove filter and match
|
||||||
|
if (sessconn != NULL) {
|
||||||
|
dbus_connection_remove_filter(sessconn, lcd_sig_received, sig);
|
||||||
|
dbus_bus_remove_match(sessconn, sig->rule, NULL);
|
||||||
|
}
|
||||||
|
if (sysconn != NULL) {
|
||||||
|
dbus_connection_remove_filter(sysconn, lcd_sig_received, sig);
|
||||||
|
dbus_bus_remove_match(sysconn, sig->rule, NULL);
|
||||||
|
}
|
||||||
|
//free user data
|
||||||
|
free_signal(sig);
|
||||||
|
|
||||||
|
//drop it off the list
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < registered_sig_count; i++) {
|
||||||
|
if (lcd_registered_signals[i] == sig) {
|
||||||
|
registered_sig_count--;
|
||||||
|
lcd_registered_signals[i] = lcd_registered_signals[registered_sig_count];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void fill_args(DBusMessage * message, int *argcount, char ***argv)
|
||||||
|
{
|
||||||
|
dbus_message_ref(message);
|
||||||
|
int argc = 0;
|
||||||
|
char **args = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
DBusMessageIter iter;
|
||||||
|
int buf_size = 0;
|
||||||
|
dbus_message_iter_init(message, &iter);
|
||||||
|
int current_type;
|
||||||
|
|
||||||
|
//iterate over all arguments, casting all primitaves to strings
|
||||||
|
while ((current_type = dbus_message_iter_get_arg_type(&iter)) != DBUS_TYPE_INVALID) {
|
||||||
|
assert(argc <= buf_size);
|
||||||
|
if (argc >= buf_size) {
|
||||||
|
buf_size = argc * 2;
|
||||||
|
if (buf_size == 0) {
|
||||||
|
buf_size = 1;
|
||||||
|
}
|
||||||
|
args = realloc(args, sizeof(char **) * buf_size);
|
||||||
|
}
|
||||||
|
if (dbus_type_is_basic(current_type)) {
|
||||||
|
args[argc] = malloc(sizeof(char) * (1 + LCD_MAX_MSG_LEN));
|
||||||
|
args[argc][LCD_MAX_MSG_LEN] = '\0';
|
||||||
|
//determine the type
|
||||||
|
switch (current_type) {
|
||||||
|
/* Primitive types */
|
||||||
|
case DBUS_TYPE_BYTE:
|
||||||
|
{
|
||||||
|
char value;
|
||||||
|
dbus_message_iter_get_basic(&iter, &value);
|
||||||
|
snprintf(args[argc], LCD_MAX_MSG_LEN, "%hhx", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case DBUS_TYPE_BOOLEAN:
|
||||||
|
{
|
||||||
|
dbus_bool_t value;
|
||||||
|
dbus_message_iter_get_basic(&iter, &value);
|
||||||
|
if (value) {
|
||||||
|
strcpy(args[argc], "true");
|
||||||
|
} else {
|
||||||
|
strcpy(args[argc], "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DBUS_TYPE_INT16:
|
||||||
|
{
|
||||||
|
dbus_int16_t value;
|
||||||
|
dbus_message_iter_get_basic(&iter, &value);
|
||||||
|
snprintf(args[argc], LCD_MAX_MSG_LEN, "%hd", value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DBUS_TYPE_UINT16:
|
||||||
|
{
|
||||||
|
dbus_uint16_t value;
|
||||||
|
dbus_message_iter_get_basic(&iter, &value);
|
||||||
|
snprintf(args[argc], LCD_MAX_MSG_LEN, "%hu", value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DBUS_TYPE_INT32:
|
||||||
|
{
|
||||||
|
dbus_int32_t value;
|
||||||
|
dbus_message_iter_get_basic(&iter, &value);
|
||||||
|
snprintf(args[argc], LCD_MAX_MSG_LEN, "%d", value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DBUS_TYPE_UINT32:
|
||||||
|
{
|
||||||
|
dbus_uint32_t value;
|
||||||
|
dbus_message_iter_get_basic(&iter, &value);
|
||||||
|
snprintf(args[argc], LCD_MAX_MSG_LEN, "%u", value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DBUS_TYPE_INT64:
|
||||||
|
{
|
||||||
|
dbus_int64_t value;
|
||||||
|
dbus_message_iter_get_basic(&iter, &value);
|
||||||
|
snprintf(args[argc], LCD_MAX_MSG_LEN, "%ld", value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DBUS_TYPE_UINT64:
|
||||||
|
{
|
||||||
|
dbus_uint64_t value;
|
||||||
|
dbus_message_iter_get_basic(&iter, &value);
|
||||||
|
snprintf(args[argc], LCD_MAX_MSG_LEN, "%lu", value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DBUS_TYPE_DOUBLE:
|
||||||
|
{
|
||||||
|
double value;
|
||||||
|
dbus_message_iter_get_basic(&iter, &value);
|
||||||
|
snprintf(args[argc], LCD_MAX_MSG_LEN, "%f", value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DBUS_TYPE_STRING: //all strings
|
||||||
|
case DBUS_TYPE_OBJECT_PATH:
|
||||||
|
case DBUS_TYPE_SIGNATURE:
|
||||||
|
{
|
||||||
|
char *value;
|
||||||
|
dbus_message_iter_get_basic(&iter, &value);
|
||||||
|
snprintf(args[argc], LCD_MAX_MSG_LEN, "%s", value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DBUS_TYPE_INVALID:
|
||||||
|
default:
|
||||||
|
//not supported
|
||||||
|
free(args[argc]);
|
||||||
|
args[argc] = NULL;
|
||||||
|
assert(0); //should never ever happen...
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
args[argc] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc++;
|
||||||
|
dbus_message_iter_next(&iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
*argcount = argc;
|
||||||
|
*argv = args;
|
||||||
|
dbus_message_unref(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static DBusHandlerResult lcd_sig_received(DBusConnection * connection, DBusMessage * msg, void *sigv)
|
||||||
|
{
|
||||||
|
dbus_message_ref(msg);
|
||||||
|
|
||||||
|
lcd_sig_t *sig = sigv;
|
||||||
|
//compare the signal to the one we were assigned
|
||||||
|
if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) {
|
||||||
|
dbus_message_unref(msg);
|
||||||
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||||
|
}
|
||||||
|
//we don't check the sender because we (probably) asked by name, not by sender
|
||||||
|
if (!dbus_message_has_member(msg, sig->member) ||
|
||||||
|
!dbus_message_has_path(msg, sig->path) || !dbus_message_has_interface(msg, sig->interface)) {
|
||||||
|
dbus_message_unref(msg);
|
||||||
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
char **args;
|
||||||
|
int argc;
|
||||||
|
fill_args(msg, &argc, &args);
|
||||||
|
|
||||||
|
//call the users function
|
||||||
|
if (sig->callback != NULL) {
|
||||||
|
sig->callback(sig->user_data, argc, args);
|
||||||
|
}
|
||||||
|
dbus_message_unref(msg);
|
||||||
|
return DBUS_HANDLER_RESULT_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void free_args(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
//free args
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
if (argv[i] != NULL) {
|
||||||
|
free(argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argv != NULL && argc != 0) {
|
||||||
|
free(argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
94
plugin_event.c
Normal file
94
plugin_event.c
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/* $Id: plugin_event.c -1 $
|
||||||
|
* $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/plugin_event.c $
|
||||||
|
*
|
||||||
|
* plugin template
|
||||||
|
*
|
||||||
|
* Copyright (C) 2003 Ed Martin <edman007@edman007.com>
|
||||||
|
* Copyright (C) 2004, 2005, 2006, 2007, 2008 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* This file is part of LCD4Linux.
|
||||||
|
*
|
||||||
|
* LCD4Linux 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.
|
||||||
|
*
|
||||||
|
* LCD4Linux 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* exported functions:
|
||||||
|
*
|
||||||
|
* int plugin_init_event (void)
|
||||||
|
* adds various functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* define the include files you need */
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
/* these should always be included */
|
||||||
|
#include "debug.h"
|
||||||
|
#include "plugin.h"
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
|
#ifdef WITH_DMALLOC
|
||||||
|
#include <dmalloc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* function 'trigger' */
|
||||||
|
/* takes one argument, a string */
|
||||||
|
/* triggers the event */
|
||||||
|
|
||||||
|
static void my_trigger(RESULT * result, RESULT * arg1)
|
||||||
|
{
|
||||||
|
char *param;
|
||||||
|
|
||||||
|
/* Get Parameter */
|
||||||
|
/* R2N stands for 'Result to Number' */
|
||||||
|
param = R2S(arg1);
|
||||||
|
named_event_trigger(param);
|
||||||
|
|
||||||
|
char *value = "";
|
||||||
|
|
||||||
|
/* store result */
|
||||||
|
/* when called with R_NUMBER, it assumes the */
|
||||||
|
/* next parameter to be a pointer to double */
|
||||||
|
SetResult(&result, R_NUMBER, &value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* plugin initialization */
|
||||||
|
/* MUST NOT be declared 'static'! */
|
||||||
|
int plugin_init_event(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* register all our cool functions */
|
||||||
|
/* the second parameter is the number of arguments */
|
||||||
|
/* -1 stands for variable argument list */
|
||||||
|
AddFunction("event::trigger", 1, my_trigger);
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_exit_event(void)
|
||||||
|
{
|
||||||
|
/* free any allocated memory */
|
||||||
|
/* close filedescriptors */
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user