-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathdbus-signal.c
186 lines (154 loc) · 5.67 KB
/
dbus-signal.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*
* Signals with DBus / DBus GLib API
*
* A program to illustrate how to connect a signal to an event using DBus
* and the DBus GLib API
*
* Author: Akarsh Simha <[email protected]>
*
* This code is licensed under The GNU General Public License (GPL)
* Anyone is free to distribute, copy, modify and redistribute this code
*/
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <stdlib.h>
#define false 0
/*
* This program subscribes to the 'NameLost' signal from the DBus daemon,
* registers for a name and then loses it, to check if the method mapped
* to the signal is called.
*/
GMainLoop *mainloop;
DBusConnection *con;
/*
* The onNameLost function is to be connected to the 'NameLost' signal
* from the DBus daemon (org.freedesktop.DBus), so that it is called
* when we release a name we may have acquired.
*
* The function prints the message "!!! We lost our Name !!!" and causes
* the program to exit from the GLib Main Loop
*/
void onNameLost() {
g_print("!!! We lost our Name !!!\n");
g_main_loop_quit(mainloop);
}
/*
* The releaseName function is to be called 1000 ms after the program enters
* the GLib Main Loop. It releases the name that we obtain in main() through
* a dbus_bus_request_name() call, so that we trigger the DBus 'NameLost'
* signal.
*
* The pointer my_data is a pointer to the DBusGConnection object that
* represents our connection to the DBus daemon, and is not used, because
* we've made the corresponding DBusConnection object global.
* (Not a good idea)
*/
gboolean releaseName(gpointer my_data) {
DBusError *error;
int retval;
error = NULL;
/* Release the name we got earlier (That is, if we got one) */
retval = dbus_bus_release_name (con, "org.DBusTest.SignalTest", error);
switch(retval) {
case DBUS_RELEASE_NAME_REPLY_RELEASED:
g_printerr("releaseName(): Name org.DBusTest.SignalTest was released successfully\n");
break;
case DBUS_RELEASE_NAME_REPLY_NOT_OWNER:
g_printerr("releaseName(): Name org.DBusTest.SignalTest is not owned by this app!\n");
break;
case DBUS_RELEASE_NAME_REPLY_NON_EXISTENT:
g_printerr("releaseName(): Name org.DBusTest.SignalTest does not exist!\n");
break;
default:
g_printerr("releaseName(): Unknown exit status %d\n", retval);
}
if( retval == -1) {
if( error == NULL ) {
g_printerr("releaseName(): Something fishy. We got an exit status of -1 but error == NULL!\n");
}
else {
g_printerr("Could not release name org.DBusTest.SignalTest: %s\n", error -> message);
g_printerr("This program may not terminate...\n");
dbus_error_free(error);
}
}
/* Return false, so that releaseName() will not be called again by the main loop */
return false;
}
/* The main() function handles the following:
* 1. Getting the connection to the DBus daemon using dbus_g_bus_get()
* 2. Requests the DBus daemon for the name org.DBusTest.SignalTest
* 3. Registers signal handler for the DBus signal 'NameLost' using the
* dbus_g_proxy_connect_signal() method
* 4. Requests that the releaseName() function be called 1s after entering
* the GLib Main Loop.
* 5. Enters the GLib Main Loop
*
*
* It returns 0 on success and 1 on failure
*
*/
int main() {
DBusGProxy *proxy;
DBusGConnection *sigcon;
GError *error;
DBusError *dbuserror;
int retval;
g_type_init();
error = NULL;
/* Obtain a connection to the Session Bus */
sigcon = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
if(!sigcon) {
g_printerr("Failed to connect to Session bus: %s\n", error -> message);
g_error_free(error);
exit(1);
}
con = dbus_g_connection_get_connection(sigcon);
dbuserror = NULL;
/* Request the DBus daemon for the name org.DBusTest.SignalTest */
/* WARNING: Note that the function does not do an exit(1) even
* when it doesn't get the name. This may lead to the program
* not terminating, because the releaseName method will fail
* subsequently and onNameLost will not be called. Thus the program
* will not exit the main loop
*/
retval = dbus_bus_request_name(con, "org.DBusTest.SignalTest", DBUS_NAME_FLAG_ALLOW_REPLACEMENT, dbuserror);
switch(retval) {
case -1: {
g_printerr("Couldn't acquire name org.DBusTest.SignalTest for our connection: %s\n", dbuserror -> message);
g_printerr("This program may not terminate as a result of this error!\n");
dbus_error_free(dbuserror);
break;
}
case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
g_printerr("dbus_bus_request_name(): We now own the name org.DBusTest.SignalTest!\n");
break;
case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
g_printerr("dbus_bus_request_name(): We are standing in queue for our name!\n");
break;
case DBUS_REQUEST_NAME_REPLY_EXISTS:
g_printerr("dbus_bus_request_name(): :-( The name we asked for already exists!\n");
break;
case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
g_printerr("dbus_bus_request_name(): Eh? We already own this name!\n");
break;
default:
g_printerr("dbus_bus_request_name(): Unknown result = %d\n", retval);
}
/* Prepare a main loop */
mainloop = g_main_loop_new(NULL, false);
/* Create a proxy object for the DBus daemon and register the signal handler
* onNameLost() with the signal 'NameLost' from the DBus daemon */
proxy = dbus_g_proxy_new_for_name(sigcon, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus");
dbus_g_proxy_add_signal(proxy, "NameLost", G_TYPE_STRING, G_TYPE_INVALID);
dbus_g_proxy_connect_signal(proxy, "NameLost", onNameLost, NULL, NULL);
/* Set a timeout of 1s to call releaseName() */
g_timeout_add(1000, releaseName, (gpointer) sigcon);
/* Enter the Main Loop */
g_main_loop_run(mainloop);
/* Cleanup code */
g_object_unref(proxy);
return 0;
}