Add some more device properties to the sink properties list
[pulseaudio-mirror.git] / src / pulse / thread-mainloop.c
blobfb73ff1bee27a603747615d5233eea656b609040
1 /***
2 This file is part of PulseAudio.
4 Copyright 2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <signal.h>
28 #include <stdio.h>
30 #ifdef HAVE_POLL_H
31 #include <poll.h>
32 #else
33 #include <pulsecore/poll.h>
34 #endif
36 #include <pulse/xmalloc.h>
37 #include <pulse/mainloop.h>
38 #include <pulse/i18n.h>
40 #include <pulsecore/log.h>
41 #include <pulsecore/hashmap.h>
42 #include <pulsecore/thread.h>
43 #include <pulsecore/mutex.h>
44 #include <pulsecore/macro.h>
46 #include "thread-mainloop.h"
48 struct pa_threaded_mainloop {
49 pa_mainloop *real_mainloop;
50 int n_waiting;
52 pa_thread* thread;
53 pa_mutex* mutex;
54 pa_cond* cond, *accept_cond;
57 static inline int in_worker(pa_threaded_mainloop *m) {
58 return pa_thread_self() == m->thread;
61 static int poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, void *userdata) {
62 pa_mutex *mutex = userdata;
63 int r;
65 pa_assert(mutex);
67 /* Before entering poll() we unlock the mutex, so that
68 * avahi_simple_poll_quit() can succeed from another thread. */
70 pa_mutex_unlock(mutex);
71 r = poll(ufds, nfds, timeout);
72 pa_mutex_lock(mutex);
74 return r;
77 static void thread(void *userdata) {
78 pa_threaded_mainloop *m = userdata;
80 #ifndef OS_IS_WIN32
81 sigset_t mask;
83 /* Make sure that signals are delivered to the main thread */
84 sigfillset(&mask);
85 pthread_sigmask(SIG_BLOCK, &mask, NULL);
86 #endif
88 pa_mutex_lock(m->mutex);
90 pa_mainloop_run(m->real_mainloop, NULL);
92 pa_mutex_unlock(m->mutex);
95 pa_threaded_mainloop *pa_threaded_mainloop_new(void) {
96 pa_threaded_mainloop *m;
98 pa_init_i18n();
100 m = pa_xnew(pa_threaded_mainloop, 1);
102 if (!(m->real_mainloop = pa_mainloop_new())) {
103 pa_xfree(m);
104 return NULL;
107 m->mutex = pa_mutex_new(TRUE, TRUE);
108 m->cond = pa_cond_new();
109 m->accept_cond = pa_cond_new();
110 m->thread = NULL;
112 pa_mainloop_set_poll_func(m->real_mainloop, poll_func, m->mutex);
114 m->n_waiting = 0;
116 return m;
119 void pa_threaded_mainloop_free(pa_threaded_mainloop* m) {
120 pa_assert(m);
122 /* Make sure that this function is not called from the helper thread */
123 pa_assert((m->thread && !pa_thread_is_running(m->thread)) || !in_worker(m));
125 pa_threaded_mainloop_stop(m);
127 if (m->thread)
128 pa_thread_free(m->thread);
130 pa_mainloop_free(m->real_mainloop);
132 pa_mutex_free(m->mutex);
133 pa_cond_free(m->cond);
134 pa_cond_free(m->accept_cond);
136 pa_xfree(m);
139 int pa_threaded_mainloop_start(pa_threaded_mainloop *m) {
140 pa_assert(m);
142 pa_assert(!m->thread || !pa_thread_is_running(m->thread));
144 if (!(m->thread = pa_thread_new(thread, m)))
145 return -1;
147 return 0;
150 void pa_threaded_mainloop_stop(pa_threaded_mainloop *m) {
151 pa_assert(m);
153 if (!m->thread || !pa_thread_is_running(m->thread))
154 return;
156 /* Make sure that this function is not called from the helper thread */
157 pa_assert(!in_worker(m));
159 pa_mutex_lock(m->mutex);
160 pa_mainloop_quit(m->real_mainloop, 0);
161 pa_mutex_unlock(m->mutex);
163 pa_thread_join(m->thread);
166 void pa_threaded_mainloop_lock(pa_threaded_mainloop *m) {
167 pa_assert(m);
169 /* Make sure that this function is not called from the helper thread */
170 pa_assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
172 pa_mutex_lock(m->mutex);
175 void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) {
176 pa_assert(m);
178 /* Make sure that this function is not called from the helper thread */
179 pa_assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
181 pa_mutex_unlock(m->mutex);
184 void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept) {
185 pa_assert(m);
187 pa_cond_signal(m->cond, 1);
189 if (wait_for_accept && m->n_waiting > 0)
190 pa_cond_wait(m->accept_cond, m->mutex);
193 void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) {
194 pa_assert(m);
196 /* Make sure that this function is not called from the helper thread */
197 pa_assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
199 m->n_waiting ++;
201 pa_cond_wait(m->cond, m->mutex);
203 pa_assert(m->n_waiting > 0);
204 m->n_waiting --;
207 void pa_threaded_mainloop_accept(pa_threaded_mainloop *m) {
208 pa_assert(m);
210 /* Make sure that this function is not called from the helper thread */
211 pa_assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
213 pa_cond_signal(m->accept_cond, 0);
216 int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m) {
217 pa_assert(m);
219 return pa_mainloop_get_retval(m->real_mainloop);
222 pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m) {
223 pa_assert(m);
225 return pa_mainloop_get_api(m->real_mainloop);
228 int pa_threaded_mainloop_in_thread(pa_threaded_mainloop *m) {
229 pa_assert(m);
231 return m->thread && pa_thread_self() == m->thread;