]> git.proxmox.com Git - spiceterm.git/blame_incremental - event_loop.c
start mouse support
[spiceterm.git] / event_loop.c
... / ...
CommitLineData
1/*
2
3 Copyright (C) 2013 Proxmox Server Solutions GmbH
4
5 Copyright: spiceterm is under GNU GPL, the GNU General Public License.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; version 2 dated June, 1991.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA.
20
21 Author: Dietmar Maurer <dietmar@proxmox.com>
22
23*/
24
25#include <stdlib.h>
26#include <stdio.h>
27#include <sys/time.h>
28#include <signal.h>
29#include <string.h>
30
31#include <glib.h>
32
33#include <spice/macros.h>
34#include "event_loop.h"
35
36static int debug = 0;
37
38#define DPRINTF(x, format, ...) { \
39 if (x <= debug) { \
40 printf("%s: " format "\n" , __FUNCTION__, ## __VA_ARGS__); \
41 } \
42}
43
44static GMainLoop *main_loop;
45
46static SpiceCoreInterface core;
47
48typedef struct SpiceTimer {
49 GSource *source;
50 SpiceTimerFunc func;
51 int ms;
52 void *opaque;
53} Timer;
54
55static SpiceTimer* timer_add(SpiceTimerFunc func, void *opaque)
56{
57 g_return_val_if_fail(func != NULL, NULL);
58
59 SpiceTimer *timer = g_new0(SpiceTimer, 1);
60
61 timer->func = func;
62 timer->opaque = opaque;
63
64 return timer;
65}
66
67static gboolean timer_callback(gpointer data)
68{
69 SpiceTimer *timer = (SpiceTimer *)data;
70 g_assert(timer != NULL);
71 g_assert(timer->func != NULL);
72
73 timer->func(timer->opaque);
74
75 return FALSE;
76}
77
78static void timer_start(SpiceTimer *timer, uint32_t ms)
79{
80 g_return_if_fail(timer != NULL);
81 g_return_if_fail(ms != 0);
82
83 if (timer->source != NULL) {
84 g_source_destroy(timer->source);
85 }
86
87 timer->source = g_timeout_source_new(ms);
88 g_assert(timer->source != NULL);
89
90 g_source_set_callback(timer->source, timer_callback, timer, NULL);
91
92 g_source_attach(timer->source, NULL);
93}
94
95static void timer_cancel(SpiceTimer *timer)
96{
97 g_return_if_fail(timer != NULL);
98
99 if (timer->source != NULL) {
100 g_source_destroy(timer->source);
101 timer->source = NULL;
102 }
103
104 timer->ms = 0;
105}
106
107static void timer_remove(SpiceTimer *timer)
108{
109 g_return_if_fail(timer != NULL);
110
111 timer_cancel(timer);
112 g_free(timer);
113}
114
115struct SpiceWatch {
116 GIOChannel *channel;
117 guint evid;
118 int fd;
119 int event_mask;
120 SpiceWatchFunc func;
121 void *opaque;
122};
123
124static gboolean watch_callback(GIOChannel *source, GIOCondition condition, gpointer data)
125{
126 SpiceWatch *watch = (SpiceWatch *)data;
127
128 g_assert(watch != NULL);
129 g_assert(watch->func != NULL);
130
131 if (condition & G_IO_OUT) {
132 watch->func(watch->fd, SPICE_WATCH_EVENT_WRITE, watch->opaque);
133 }
134
135 if (condition & G_IO_IN) {
136 watch->func(watch->fd, SPICE_WATCH_EVENT_READ, watch->opaque);
137 }
138
139 return TRUE;
140}
141
142static GIOCondition event_mask_to_condition(int event_mask)
143{
144 GIOCondition condition = 0;
145
146 if (event_mask & SPICE_WATCH_EVENT_READ) {
147 condition |= G_IO_IN;
148 }
149
150 if (event_mask & SPICE_WATCH_EVENT_WRITE) {
151 condition |= G_IO_OUT;
152 }
153
154 return condition;
155}
156
157static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque)
158{
159 SpiceWatch *watch = g_new0(SpiceWatch, 1);
160
161 DPRINTF(1, "adding %p, fd=%d", watch, fd);
162
163 watch->fd = fd;
164 watch->event_mask = event_mask;
165 watch->func = func;
166 watch->opaque = opaque;
167 watch->channel = g_io_channel_unix_new(fd);
168
169 g_assert(watch->channel != NULL);
170 g_io_channel_set_encoding(watch->channel, NULL, NULL);
171
172 GIOCondition condition = event_mask_to_condition(event_mask);
173 watch->evid = g_io_add_watch(watch->channel, condition, watch_callback, watch);
174
175 return watch;
176}
177
178static void watch_update_mask(SpiceWatch *watch, int event_mask)
179{
180 g_assert(watch != NULL);
181
182 DPRINTF(1, "fd %d to %d", watch->fd, event_mask);
183
184 watch->event_mask = event_mask;
185
186 g_source_remove(watch->evid);
187
188 GIOCondition condition = event_mask_to_condition(event_mask);
189 watch->evid = g_io_add_watch(watch->channel, condition, watch_callback, watch);
190}
191
192static void watch_remove(SpiceWatch *watch)
193{
194 g_assert(watch != NULL);
195
196 DPRINTF(1, "remove %p (fd %d)", watch, watch->fd);
197
198 g_source_remove(watch->evid);
199 g_io_channel_unref(watch->channel);
200
201 g_free(watch);
202}
203
204static void channel_event(int event, SpiceChannelEventInfo *info)
205{
206 DPRINTF(1, "channel event con, type, id, event: %d, %d, %d, %d",
207 info->connection_id, info->type, info->id, event);
208}
209
210void basic_event_loop_mainloop(void)
211{
212 g_main_loop_run(main_loop);
213}
214
215static void ignore_sigpipe(void)
216{
217 struct sigaction act;
218
219 memset(&act, 0, sizeof(act));
220 sigfillset(&act.sa_mask);
221 act.sa_handler = SIG_IGN;
222 sigaction(SIGPIPE, &act, NULL);
223}
224
225SpiceCoreInterface *basic_event_loop_init(void)
226{
227 main_loop = g_main_loop_new(NULL, FALSE);
228
229 memset(&core, 0, sizeof(core));
230 core.base.major_version = SPICE_INTERFACE_CORE_MAJOR;
231 core.base.minor_version = SPICE_INTERFACE_CORE_MINOR;
232 core.timer_add = timer_add;
233 core.timer_start = timer_start;
234 core.timer_cancel = timer_cancel;
235 core.timer_remove = timer_remove;
236 core.watch_add = watch_add;
237 core.watch_update_mask = watch_update_mask;
238 core.watch_remove = watch_remove;
239 core.channel_event = channel_event;
240
241 ignore_sigpipe();
242
243 return &core;
244}