3 Copyright (C) 2013 Proxmox Server Solutions GmbH
5 Copyright: spiceterm is under GNU GPL, the GNU General Public License.
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.
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.
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
21 Author: Dietmar Maurer <dietmar@proxmox.com>
33 #include <spice/macros.h>
34 #include "event_loop.h"
38 #define DPRINTF(x, format, ...) { \
40 printf("%s: " format "\n" , __FUNCTION__, ## __VA_ARGS__); \
44 static GMainLoop
*main_loop
;
46 static SpiceCoreInterface core
;
48 typedef struct SpiceTimer
{
55 static SpiceTimer
* timer_add(SpiceTimerFunc func
, void *opaque
)
57 g_return_val_if_fail(func
!= NULL
, NULL
);
59 SpiceTimer
*timer
= g_new0(SpiceTimer
, 1);
62 timer
->opaque
= opaque
;
67 static gboolean
timer_callback(gpointer data
)
69 SpiceTimer
*timer
= (SpiceTimer
*)data
;
70 g_assert(timer
!= NULL
);
71 g_assert(timer
->func
!= NULL
);
73 timer
->func(timer
->opaque
);
78 static void timer_start(SpiceTimer
*timer
, uint32_t ms
)
80 g_return_if_fail(timer
!= NULL
);
81 g_return_if_fail(ms
!= 0);
83 if (timer
->source
!= NULL
) {
84 g_source_destroy(timer
->source
);
87 timer
->source
= g_timeout_source_new(ms
);
88 g_assert(timer
->source
!= NULL
);
90 g_source_set_callback(timer
->source
, timer_callback
, timer
, NULL
);
92 g_source_attach(timer
->source
, NULL
);
95 static void timer_cancel(SpiceTimer
*timer
)
97 g_return_if_fail(timer
!= NULL
);
99 if (timer
->source
!= NULL
) {
100 g_source_destroy(timer
->source
);
101 timer
->source
= NULL
;
107 static void timer_remove(SpiceTimer
*timer
)
109 g_return_if_fail(timer
!= NULL
);
124 static gboolean
watch_callback(GIOChannel
*source
, GIOCondition condition
, gpointer data
)
126 SpiceWatch
*watch
= (SpiceWatch
*)data
;
128 g_assert(watch
!= NULL
);
129 g_assert(watch
->func
!= NULL
);
131 if (condition
& G_IO_OUT
) {
132 watch
->func(watch
->fd
, SPICE_WATCH_EVENT_WRITE
, watch
->opaque
);
135 if (condition
& G_IO_IN
) {
136 watch
->func(watch
->fd
, SPICE_WATCH_EVENT_READ
, watch
->opaque
);
142 static GIOCondition
event_mask_to_condition(int event_mask
)
144 GIOCondition condition
= 0;
146 if (event_mask
& SPICE_WATCH_EVENT_READ
) {
147 condition
|= G_IO_IN
;
150 if (event_mask
& SPICE_WATCH_EVENT_WRITE
) {
151 condition
|= G_IO_OUT
;
157 static SpiceWatch
*watch_add(int fd
, int event_mask
, SpiceWatchFunc func
, void *opaque
)
159 SpiceWatch
*watch
= g_new0(SpiceWatch
, 1);
161 DPRINTF(1, "adding %p, fd=%d", watch
, fd
);
164 watch
->event_mask
= event_mask
;
166 watch
->opaque
= opaque
;
167 watch
->channel
= g_io_channel_unix_new(fd
);
169 g_assert(watch
->channel
!= NULL
);
170 g_io_channel_set_encoding(watch
->channel
, NULL
, NULL
);
172 GIOCondition condition
= event_mask_to_condition(event_mask
);
173 watch
->evid
= g_io_add_watch(watch
->channel
, condition
, watch_callback
, watch
);
178 static void watch_update_mask(SpiceWatch
*watch
, int event_mask
)
180 g_assert(watch
!= NULL
);
182 DPRINTF(1, "fd %d to %d", watch
->fd
, event_mask
);
184 watch
->event_mask
= event_mask
;
186 g_source_remove(watch
->evid
);
188 GIOCondition condition
= event_mask_to_condition(event_mask
);
189 watch
->evid
= g_io_add_watch(watch
->channel
, condition
, watch_callback
, watch
);
192 static void watch_remove(SpiceWatch
*watch
)
194 g_assert(watch
!= NULL
);
196 DPRINTF(1, "remove %p (fd %d)", watch
, watch
->fd
);
198 g_source_remove(watch
->evid
);
199 g_io_channel_unref(watch
->channel
);
204 static void channel_event(int event
, SpiceChannelEventInfo
*info
)
206 DPRINTF(1, "channel event con, type, id, event: %d, %d, %d, %d",
207 info
->connection_id
, info
->type
, info
->id
, event
);
210 void basic_event_loop_mainloop(void)
212 g_main_loop_run(main_loop
);
215 static void ignore_sigpipe(void)
217 struct sigaction act
;
219 memset(&act
, 0, sizeof(act
));
220 sigfillset(&act
.sa_mask
);
221 act
.sa_handler
= SIG_IGN
;
222 sigaction(SIGPIPE
, &act
, NULL
);
225 SpiceCoreInterface
*basic_event_loop_init(void)
227 main_loop
= g_main_loop_new(NULL
, FALSE
);
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
;