]>
code.delx.au - pulseaudio/blob - polyp/x11wrap.c
4 This file is part of polypaudio.
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
33 struct pa_x11_internal
{
34 PA_LLIST_FIELDS(struct pa_x11_internal
);
35 struct pa_x11_wrapper
*wrapper
;
36 struct pa_io_event
* io_event
;
40 struct pa_x11_wrapper
{
47 struct pa_defer_event
* defer_event
;
48 struct pa_io_event
* io_event
;
50 PA_LLIST_HEAD(struct pa_x11_client
, clients
);
51 PA_LLIST_HEAD(struct pa_x11_internal
, internals
);
54 struct pa_x11_client
{
55 PA_LLIST_FIELDS(struct pa_x11_client
);
56 struct pa_x11_wrapper
*wrapper
;
57 int (*callback
)(struct pa_x11_wrapper
*w
, XEvent
*e
, void *userdata
);
61 /* Dispatch all pending X11 events */
62 static void work(struct pa_x11_wrapper
*w
) {
63 assert(w
&& w
->ref
>= 1);
65 while (XPending(w
->display
)) {
66 struct pa_x11_client
*c
;
68 XNextEvent(w
->display
, &e
);
70 for (c
= w
->clients
; c
; c
= c
->next
) {
72 if (c
->callback(w
, &e
, c
->userdata
) != 0)
78 /* IO notification event for the X11 display connection */
79 static void display_io_event(struct pa_mainloop_api
*m
, struct pa_io_event
*e
, int fd
, enum pa_io_event_flags f
, void *userdata
) {
80 struct pa_x11_wrapper
*w
= userdata
;
81 assert(m
&& e
&& fd
>= 0 && w
&& w
->ref
>= 1);
85 /* Deferred notification event. Called once each main loop iteration */
86 static void defer_event(struct pa_mainloop_api
*m
, struct pa_defer_event
*e
, void *userdata
) {
87 struct pa_x11_wrapper
*w
= userdata
;
88 assert(m
&& e
&& w
&& w
->ref
>= 1);
92 /* IO notification event for X11 internal connections */
93 static void internal_io_event(struct pa_mainloop_api
*m
, struct pa_io_event
*e
, int fd
, enum pa_io_event_flags f
, void *userdata
) {
94 struct pa_x11_wrapper
*w
= userdata
;
95 assert(m
&& e
&& fd
>= 0 && w
&& w
->ref
>= 1);
97 XProcessInternalConnection(w
->display
, fd
);
100 /* Add a new IO source for the specified X11 internal connection */
101 static struct pa_x11_internal
* x11_internal_add(struct pa_x11_wrapper
*w
, int fd
) {
102 struct pa_x11_internal
*i
;
103 assert(i
&& fd
>= 0);
105 i
= pa_xmalloc(sizeof(struct pa_x11_internal
));
107 i
->io_event
= w
->core
->mainloop
->io_new(w
->core
->mainloop
, fd
, PA_IO_EVENT_INPUT
, internal_io_event
, w
);
110 PA_LLIST_PREPEND(struct pa_x11_internal
, w
->internals
, i
);
114 /* Remove an IO source for an X11 internal connection */
115 void x11_internal_remove(struct pa_x11_wrapper
*w
, struct pa_x11_internal
*i
) {
118 PA_LLIST_REMOVE(struct pa_x11_internal
, w
->internals
, i
);
119 w
->core
->mainloop
->io_free(i
->io_event
);
123 /* Implementation of XConnectionWatchProc */
124 static void x11_watch(Display
*display
, XPointer userdata
, int fd
, Bool opening
, XPointer
*watch_data
) {
125 struct pa_x11_wrapper
*w
= (struct pa_x11_wrapper
*) userdata
;
126 assert(display
&& w
&& fd
>= 0);
129 *watch_data
= (XPointer
) x11_internal_add(w
, fd
);
131 x11_internal_remove(w
, (struct pa_x11_internal
*) *watch_data
);
134 static struct pa_x11_wrapper
* x11_wrapper_new(struct pa_core
*c
, const char *name
, const char *t
) {
135 struct pa_x11_wrapper
*w
;
139 if (!(d
= XOpenDisplay(name
))) {
140 pa_log(__FILE__
": XOpenDisplay() failed\n");
144 w
= pa_xmalloc(sizeof(struct pa_x11_wrapper
));
147 w
->property_name
= pa_xstrdup(t
);
150 PA_LLIST_HEAD_INIT(struct pa_x11_client
, w
->clients
);
151 PA_LLIST_HEAD_INIT(struct pa_x11_internal
, w
->internals
);
153 w
->defer_event
= c
->mainloop
->defer_new(c
->mainloop
, defer_event
, w
);
154 w
->io_event
= c
->mainloop
->io_new(c
->mainloop
, ConnectionNumber(d
), PA_IO_EVENT_INPUT
, display_io_event
, w
);
156 XAddConnectionWatch(d
, x11_watch
, (XPointer
) w
);
158 r
= pa_property_set(c
, w
->property_name
, w
);
164 static void x11_wrapper_free(struct pa_x11_wrapper
*w
) {
168 r
= pa_property_remove(w
->core
, w
->property_name
);
173 XRemoveConnectionWatch(w
->display
, x11_watch
, (XPointer
) w
);
174 XCloseDisplay(w
->display
);
176 w
->core
->mainloop
->io_free(w
->io_event
);
177 w
->core
->mainloop
->defer_free(w
->defer_event
);
180 x11_internal_remove(w
, w
->internals
);
182 pa_xfree(w
->property_name
);
186 struct pa_x11_wrapper
* pa_x11_wrapper_get(struct pa_core
*c
, const char *name
) {
188 struct pa_x11_wrapper
*w
;
191 snprintf(t
, sizeof(t
), "x11-wrapper%s%s", name
? "-" : "", name
? name
: "");
192 if ((w
= pa_property_get(c
, t
)))
193 return pa_x11_wrapper_ref(w
);
195 return x11_wrapper_new(c
, name
, t
);
198 struct pa_x11_wrapper
* pa_x11_wrapper_ref(struct pa_x11_wrapper
*w
) {
199 assert(w
&& w
->ref
>= 1);
204 void pa_x11_wrapper_unref(struct pa_x11_wrapper
* w
) {
205 assert(w
&& w
->ref
>= 1);
211 Display
*pa_x11_wrapper_get_display(struct pa_x11_wrapper
*w
) {
212 assert(w
&& w
->ref
>= 1);
216 struct pa_x11_client
* pa_x11_client_new(struct pa_x11_wrapper
*w
, int (*cb
)(struct pa_x11_wrapper
*w
, XEvent
*e
, void *userdata
), void *userdata
) {
217 struct pa_x11_client
*c
;
218 assert(w
&& w
->ref
>= 1);
220 c
= pa_xmalloc(sizeof(struct pa_x11_client
));
223 c
->userdata
= userdata
;
225 PA_LLIST_PREPEND(struct pa_x11_client
, w
->clients
, c
);
230 void pa_x11_client_free(struct pa_x11_client
*c
) {
231 assert(c
&& c
->wrapper
&& c
->wrapper
->ref
>= 1);
233 PA_LLIST_REMOVE(struct pa_x11_client
, c
->wrapper
->clients
, c
);