9 #include <spice/macros.h>
10 #include "basic_event_loop.h"
14 #define DPRINTF(x, format, ...) { \
16 printf("%s: " format "\n" , __FUNCTION__, ## __VA_ARGS__); \
20 static GMainLoop
*main_loop
;
22 static SpiceCoreInterface core
;
24 typedef struct SpiceTimer
{
31 static SpiceTimer
* timer_add(SpiceTimerFunc func
, void *opaque
)
33 g_return_val_if_fail(func
!= NULL
, NULL
);
35 SpiceTimer
*timer
= g_new0(SpiceTimer
, 1);
38 timer
->opaque
= opaque
;
43 static gboolean
timer_callback(gpointer data
)
45 SpiceTimer
*timer
= (SpiceTimer
*)data
;
46 g_assert(timer
!= NULL
);
47 g_assert(timer
->func
!= NULL
);
49 timer
->func(timer
->opaque
);
54 static void timer_start(SpiceTimer
*timer
, uint32_t ms
)
56 g_return_if_fail(timer
!= NULL
);
57 g_return_if_fail(ms
!= 0);
59 if (timer
->source
!= NULL
) {
60 g_source_destroy(timer
->source
);
63 timer
->source
= g_timeout_source_new(ms
);
64 g_assert(timer
->source
!= NULL
);
66 g_source_set_callback(timer
->source
, timer_callback
, timer
, NULL
);
68 g_source_attach(timer
->source
, NULL
);
71 static void timer_cancel(SpiceTimer
*timer
)
73 g_return_if_fail(timer
!= NULL
);
75 if (timer
->source
!= NULL
) {
76 g_source_destroy(timer
->source
);
83 static void timer_remove(SpiceTimer
*timer
)
85 g_return_if_fail(timer
!= NULL
);
100 static gboolean
watch_callback(GIOChannel
*source
, GIOCondition condition
, gpointer data
)
102 SpiceWatch
*watch
= (SpiceWatch
*)data
;
104 g_assert(watch
!= NULL
);
105 g_assert(watch
->func
!= NULL
);
107 if (condition
& G_IO_OUT
) {
108 watch
->func(watch
->fd
, SPICE_WATCH_EVENT_WRITE
, watch
->opaque
);
111 if (condition
& G_IO_IN
) {
112 watch
->func(watch
->fd
, SPICE_WATCH_EVENT_READ
, watch
->opaque
);
118 static GIOCondition
event_mask_to_condition(int event_mask
)
120 GIOCondition condition
= 0;
122 if (event_mask
& SPICE_WATCH_EVENT_READ
) {
123 condition
|= G_IO_IN
;
126 if (event_mask
& SPICE_WATCH_EVENT_WRITE
) {
127 condition
|= G_IO_OUT
;
133 static SpiceWatch
*watch_add(int fd
, int event_mask
, SpiceWatchFunc func
, void *opaque
)
135 SpiceWatch
*watch
= g_new0(SpiceWatch
, 1);
137 DPRINTF(0, "adding %p, fd=%d", watch
, fd
);
140 watch
->event_mask
= event_mask
;
142 watch
->opaque
= opaque
;
143 watch
->channel
= g_io_channel_unix_new(fd
);
145 g_assert(watch
->channel
!= NULL
);
146 g_io_channel_set_encoding(watch
->channel
, NULL
, NULL
);
148 GIOCondition condition
= event_mask_to_condition(event_mask
);
149 watch
->evid
= g_io_add_watch(watch
->channel
, condition
, watch_callback
, watch
);
154 static void watch_update_mask(SpiceWatch
*watch
, int event_mask
)
156 g_assert(watch
!= NULL
);
158 DPRINTF(0, "fd %d to %d", watch
->fd
, event_mask
);
160 watch
->event_mask
= event_mask
;
162 g_source_remove(watch
->evid
);
164 GIOCondition condition
= event_mask_to_condition(event_mask
);
165 watch
->evid
= g_io_add_watch(watch
->channel
, condition
, watch_callback
, watch
);
168 static void watch_remove(SpiceWatch
*watch
)
170 g_assert(watch
!= NULL
);
172 DPRINTF(0, "remove %p (fd %d)", watch
, watch
->fd
);
174 g_source_remove(watch
->evid
);
175 g_io_channel_unref(watch
->channel
);
180 static void channel_event(int event
, SpiceChannelEventInfo
*info
)
182 DPRINTF(0, "channel event con, type, id, event: %d, %d, %d, %d",
183 info
->connection_id
, info
->type
, info
->id
, event
);
186 void basic_event_loop_mainloop(void)
188 g_main_loop_run(main_loop
);
191 static void ignore_sigpipe(void)
193 struct sigaction act
;
195 memset(&act
, 0, sizeof(act
));
196 sigfillset(&act
.sa_mask
);
197 act
.sa_handler
= SIG_IGN
;
198 sigaction(SIGPIPE
, &act
, NULL
);
201 SpiceCoreInterface
*basic_event_loop_init(void)
203 main_loop
= g_main_loop_new(NULL
, FALSE
);
205 memset(&core
, 0, sizeof(core
));
206 core
.base
.major_version
= SPICE_INTERFACE_CORE_MAJOR
;
207 core
.base
.minor_version
= SPICE_INTERFACE_CORE_MINOR
;
208 core
.timer_add
= timer_add
;
209 core
.timer_start
= timer_start
;
210 core
.timer_cancel
= timer_cancel
;
211 core
.timer_remove
= timer_remove
;
212 core
.watch_add
= watch_add
;
213 core
.watch_update_mask
= watch_update_mask
;
214 core
.watch_remove
= watch_remove
;
215 core
.channel_event
= channel_event
;