]> git.proxmox.com Git - spiceterm.git/blame - event_loop.c
start mouse support
[spiceterm.git] / event_loop.c
CommitLineData
4ef70811
DM
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
cc04455b
DM
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>
64bc7a2f 34#include "event_loop.h"
cc04455b 35
a0579497 36static int debug = 0;
0535e191 37
cc04455b
DM
38#define DPRINTF(x, format, ...) { \
39 if (x <= debug) { \
40 printf("%s: " format "\n" , __FUNCTION__, ## __VA_ARGS__); \
41 } \
42}
43
0535e191 44static GMainLoop *main_loop;
cc04455b
DM
45
46static SpiceCoreInterface core;
47
48typedef struct SpiceTimer {
0535e191 49 GSource *source;
cc04455b 50 SpiceTimerFunc func;
cc04455b
DM
51 int ms;
52 void *opaque;
53} Timer;
54
cc04455b
DM
55static SpiceTimer* timer_add(SpiceTimerFunc func, void *opaque)
56{
0535e191
DM
57 g_return_val_if_fail(func != NULL, NULL);
58
db8e5ef8 59 SpiceTimer *timer = g_new0(SpiceTimer, 1);
cc04455b
DM
60
61 timer->func = func;
62 timer->opaque = opaque;
0535e191 63
cc04455b
DM
64 return timer;
65}
66
0535e191 67static gboolean timer_callback(gpointer data)
cc04455b 68{
0535e191
DM
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;
cc04455b
DM
76}
77
78static void timer_start(SpiceTimer *timer, uint32_t ms)
79{
0535e191
DM
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);
cc04455b
DM
93}
94
95static void timer_cancel(SpiceTimer *timer)
96{
0535e191
DM
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
cc04455b
DM
104 timer->ms = 0;
105}
106
107static void timer_remove(SpiceTimer *timer)
108{
0535e191
DM
109 g_return_if_fail(timer != NULL);
110
111 timer_cancel(timer);
112 g_free(timer);
cc04455b
DM
113}
114
115struct SpiceWatch {
0535e191
DM
116 GIOChannel *channel;
117 guint evid;
cc04455b
DM
118 int fd;
119 int event_mask;
120 SpiceWatchFunc func;
cc04455b
DM
121 void *opaque;
122};
123
0535e191
DM
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 }
cc04455b 153
0535e191
DM
154 return condition;
155}
cc04455b
DM
156
157static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque)
158{
db8e5ef8 159 SpiceWatch *watch = g_new0(SpiceWatch, 1);
cc04455b 160
a0579497 161 DPRINTF(1, "adding %p, fd=%d", watch, fd);
0535e191 162
cc04455b
DM
163 watch->fd = fd;
164 watch->event_mask = event_mask;
165 watch->func = func;
166 watch->opaque = opaque;
0535e191
DM
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
cc04455b
DM
175 return watch;
176}
177
178static void watch_update_mask(SpiceWatch *watch, int event_mask)
179{
0535e191
DM
180 g_assert(watch != NULL);
181
a0579497 182 DPRINTF(1, "fd %d to %d", watch->fd, event_mask);
0535e191 183
cc04455b 184 watch->event_mask = event_mask;
cc04455b 185
0535e191 186 g_source_remove(watch->evid);
cc04455b 187
0535e191
DM
188 GIOCondition condition = event_mask_to_condition(event_mask);
189 watch->evid = g_io_add_watch(watch->channel, condition, watch_callback, watch);
cc04455b
DM
190}
191
0535e191 192static void watch_remove(SpiceWatch *watch)
cc04455b 193{
0535e191 194 g_assert(watch != NULL);
cc04455b 195
a0579497 196 DPRINTF(1, "remove %p (fd %d)", watch, watch->fd);
cc04455b 197
0535e191
DM
198 g_source_remove(watch->evid);
199 g_io_channel_unref(watch->channel);
cc04455b 200
0535e191 201 g_free(watch);
cc04455b
DM
202}
203
0535e191 204static void channel_event(int event, SpiceChannelEventInfo *info)
cc04455b 205{
a0579497 206 DPRINTF(1, "channel event con, type, id, event: %d, %d, %d, %d",
0535e191 207 info->connection_id, info->type, info->id, event);
cc04455b
DM
208}
209
210void basic_event_loop_mainloop(void)
211{
0535e191 212 g_main_loop_run(main_loop);
cc04455b
DM
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{
0535e191
DM
227 main_loop = g_main_loop_new(NULL, FALSE);
228
cc04455b
DM
229 memset(&core, 0, sizeof(core));
230 core.base.major_version = SPICE_INTERFACE_CORE_MAJOR;
0535e191 231 core.base.minor_version = SPICE_INTERFACE_CORE_MINOR;
cc04455b
DM
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;
0535e191 240
cc04455b 241 ignore_sigpipe();
0535e191 242
cc04455b
DM
243 return &core;
244}