d011ee0d24451ba2b195c79e5ac6b195df07774e
[framework/uifw/edbus.git] / src / lib / dbus / e_dbus_message.c
1 #include <stdlib.h>
2 #include "E_DBus.h"
3 #include "e_dbus_private.h"
4
5 typedef struct E_DBus_Pending_Call_Data E_DBus_Pending_Call_Data;
6 struct E_DBus_Pending_Call_Data
7 {
8   E_DBus_Method_Return_Cb cb_return;
9   void                   *data;
10 };
11
12 static void
13 cb_pending(DBusPendingCall *pending, void *user_data)
14 {
15   DBusMessage *msg;
16   DBusError err;
17   E_DBus_Pending_Call_Data *data = user_data;
18
19   if (!dbus_pending_call_get_completed(pending))
20   {
21     INFO("E-dbus: NOT COMPLETED");
22     free(data);
23     dbus_message_unref(msg);
24     dbus_pending_call_unref(pending);
25     return;
26   }
27
28   dbus_error_init(&err);
29   msg = dbus_pending_call_steal_reply(pending);
30   if (!msg)
31   {
32     if (data->cb_return)
33     {
34       dbus_set_error(&err, "org.enlightenment.DBus.NoReply", "There was no reply to this method call.");
35       data->cb_return(data->data, NULL, &err);
36       dbus_error_free(&err);
37     }
38     return;
39   }
40
41   if (dbus_set_error_from_message(&err, msg))
42   {
43     if (data->cb_return)
44       data->cb_return(data->data, NULL, &err);
45     dbus_error_free(&err);
46   }
47   else
48   {
49     if (data->cb_return)
50       data->cb_return(data->data, msg, &err);
51   }
52
53   dbus_message_unref(msg);
54   dbus_pending_call_unref(pending);
55 }
56
57
58 /**
59  * @brief Send a DBus message with callbacks
60  * @param conn The DBus connection
61  * @param msg  The message to send
62  * @param cb_return A callback function for returns (only used if @a msg is a method-call)
63  * @param timeout   A timeout in milliseconds, after which a synthetic error will be generated
64  * @return a DBusPendingCall that can be used to cancel the current call
65  */
66 EAPI DBusPendingCall *
67 e_dbus_message_send(E_DBus_Connection *conn, DBusMessage *msg, E_DBus_Method_Return_Cb cb_return, int timeout, void *data)
68 {
69   DBusPendingCall *pending;
70
71   if (!dbus_connection_send_with_reply(conn->conn, msg, &pending, timeout))
72     return NULL;
73
74   if (cb_return && pending)
75   {
76     E_DBus_Pending_Call_Data *pdata;
77
78     pdata = malloc(sizeof(E_DBus_Pending_Call_Data));
79     pdata->cb_return = cb_return;
80     pdata->data = data;
81
82     if (!dbus_pending_call_set_notify(pending, cb_pending, pdata, free))
83     {
84       free(pdata);
85       dbus_message_unref(msg);
86       dbus_pending_call_cancel(pending);
87       return NULL;
88     }
89   }
90
91   return pending;
92 }
93
94 static void
95 cb_method_call(void *data, DBusMessage *msg, DBusError *err)
96 {
97   E_DBus_Callback *cb = data;
98   void *method_return = NULL;
99   DBusError new_err;
100   if (!cb) return;
101
102   dbus_error_init(&new_err);
103   if (!dbus_error_is_set(err))
104     method_return = e_dbus_callback_unmarshal(cb, msg, &new_err);
105   else
106     dbus_move_error(err, &new_err);
107
108   e_dbus_callback_call(cb, method_return, &new_err);
109   e_dbus_callback_return_free(cb, method_return);
110
111   if (dbus_error_is_set(&new_err))
112     dbus_error_free(&new_err);
113
114   e_dbus_callback_free(cb);
115 }
116
117 EAPI DBusPendingCall *
118 e_dbus_method_call_send(E_DBus_Connection *conn, DBusMessage *msg, E_DBus_Unmarshal_Func unmarshal_func, E_DBus_Callback_Func cb_func, E_DBus_Free_Func free_func, int timeout, void *data)
119 {
120   E_DBus_Callback *cb;
121   cb = e_dbus_callback_new(cb_func, unmarshal_func, free_func, data);
122   return e_dbus_message_send(conn, msg, cb_method_call, timeout, cb);
123 }