2002-12-24 Havoc Pennington <hp@pobox.com>
[platform/upstream/dbus.git] / glib / dbus-gmain.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-gmain.c GLib main loop integration
3  *
4  * Copyright (C) 2002  CodeFactory AB
5  *
6  * Licensed under the Academic Free License version 1.2
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "dbus-glib.h"
25 #include <glib.h>
26
27 typedef struct _DBusGSource DBusGSource;
28
29 struct _DBusGSource
30 {
31   GSource source;
32
33   DBusConnection *connection;
34
35   GList *poll_fds;
36   GHashTable *watches;
37 };
38
39 static gboolean gdbus_connection_prepare  (GSource     *source,
40                                            gint        *timeout);
41 static gboolean gdbus_connection_check    (GSource     *source);
42 static gboolean gdbus_connection_dispatch (GSource     *source,
43                                            GSourceFunc  callback,
44                                            gpointer     user_data);
45
46 static GSourceFuncs dbus_funcs = {
47   gdbus_connection_prepare,
48   gdbus_connection_check,
49   gdbus_connection_dispatch,
50   NULL
51 };
52
53 static gboolean
54 gdbus_connection_prepare (GSource     *source,
55                           gint        *timeout)
56 {
57   DBusConnection *connection = ((DBusGSource *)source)->connection;
58   
59   *timeout = -1;
60
61   return (dbus_connection_peek_message (connection) != NULL);
62 }
63
64 static gboolean
65 gdbus_connection_check (GSource *source)
66 {
67   DBusGSource *dbus_source = (DBusGSource *)source;
68   GList *list;
69
70   list = dbus_source->poll_fds;
71
72   while (list)
73     {
74       GPollFD *poll_fd = list->data;
75
76       if (poll_fd->revents != 0)
77         return TRUE;
78
79       list = list->next;
80     }
81
82   return FALSE;
83 }
84
85 static gboolean
86 gdbus_connection_dispatch (GSource     *source,
87                            GSourceFunc  callback,
88                            gpointer     user_data)
89 {
90    DBusGSource *dbus_source = (DBusGSource *)source;
91    DBusMessageFunction handler = (DBusMessageFunction)callback;
92    DBusMessage *message;
93    
94    GList *list;
95
96    list = dbus_source->poll_fds;
97
98    while (list)
99      {
100        GPollFD *poll_fd = list->data;
101
102        g_print ("poll_fd is: %p\n", poll_fd);
103        if (poll_fd->revents != 0)
104          {
105            DBusWatch *watch = g_hash_table_lookup (dbus_source->watches, poll_fd);
106            guint condition = 0;
107
108            if (poll_fd->revents & G_IO_IN)
109              condition |= DBUS_WATCH_READABLE;
110            if (poll_fd->revents & G_IO_OUT)
111              condition |= DBUS_WATCH_WRITABLE;
112            if (poll_fd->revents & G_IO_ERR)
113              condition |= DBUS_WATCH_ERROR;
114            if (poll_fd->revents & G_IO_HUP)
115              condition |= DBUS_WATCH_HANGUP;
116            
117            dbus_connection_handle_watch (dbus_source->connection, watch, condition);
118          }
119        
120        list = list->next;
121      }
122
123    while ((message = dbus_connection_pop_message (dbus_source->connection)))
124      {
125        handler (dbus_source->connection, message, user_data);
126
127        dbus_message_unref (message);
128      }
129    
130    return TRUE;
131 }
132
133 static void
134 gdbus_add_connection_watch (DBusWatch      *watch,
135                             DBusGSource    *source)
136 {
137   GPollFD *poll_fd;
138   guint flags;
139   
140   poll_fd = g_new (GPollFD, 1);
141   poll_fd->fd = dbus_watch_get_fd (watch);
142
143   poll_fd->events = 0;
144   flags = dbus_watch_get_flags (watch);
145   dbus_watch_set_data (watch, poll_fd, NULL);
146   
147   if (flags & DBUS_WATCH_READABLE)
148     poll_fd->events |= G_IO_IN;
149
150   if (flags & DBUS_WATCH_WRITABLE)
151     poll_fd->events |= G_IO_OUT;
152
153   g_source_add_poll ((GSource *)source, poll_fd);
154   
155   g_print ("Add connection watch: %p!\n", watch);
156
157   source->poll_fds = g_list_prepend (source->poll_fds, poll_fd);
158   g_hash_table_insert (source->watches, poll_fd, watch);
159 }
160
161 static void
162 gdbus_remove_connection_watch (DBusWatch      *watch,
163                                DBusGSource    *source)
164 {
165   GPollFD *poll_fd;
166
167   poll_fd = dbus_watch_get_data (watch);
168
169   source->poll_fds = g_list_remove (source->poll_fds, poll_fd);
170   g_hash_table_remove (source->watches, poll_fd);
171   g_source_remove_poll ((GSource *)source, poll_fd);
172   
173   g_free (poll_fd);
174 }
175
176 GSource *
177 dbus_connection_gsource_new (DBusConnection *connection)
178 {
179   GSource *source = g_source_new (&dbus_funcs, sizeof (DBusGSource));
180   DBusGSource *dbus_source = (DBusGSource *)source;
181
182   dbus_source->watches = g_hash_table_new (NULL, NULL);
183   dbus_source->connection = connection;
184   dbus_connection_ref (dbus_source->connection);
185   
186   dbus_connection_set_watch_functions (connection,
187                                        (DBusAddWatchFunction) gdbus_add_connection_watch,
188                                        (DBusRemoveWatchFunction) gdbus_remove_connection_watch,
189                                        dbus_source,
190                                        NULL);
191
192
193   return source;
194 }