]> code.delx.au - pulseaudio/blob - src/pulsecore/core.c
Merge commit 'wtay/optimize'
[pulseaudio] / src / pulsecore / core.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
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.1 of the License,
10 or (at your option) any later version.
11
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.
16
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 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <signal.h>
30
31 #include <pulse/rtclock.h>
32 #include <pulse/timeval.h>
33 #include <pulse/xmalloc.h>
34
35 #include <pulsecore/module.h>
36 #include <pulsecore/sink.h>
37 #include <pulsecore/source.h>
38 #include <pulsecore/namereg.h>
39 #include <pulsecore/core-rtclock.h>
40 #include <pulsecore/core-util.h>
41 #include <pulsecore/core-scache.h>
42 #include <pulsecore/core-subscribe.h>
43 #include <pulsecore/shared.h>
44 #include <pulsecore/random.h>
45 #include <pulsecore/log.h>
46 #include <pulsecore/macro.h>
47
48 #include "core.h"
49
50 PA_DEFINE_PUBLIC_CLASS(pa_core, pa_msgobject);
51
52 static int core_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
53 pa_core *c = PA_CORE(o);
54
55 pa_core_assert_ref(c);
56
57 switch (code) {
58
59 case PA_CORE_MESSAGE_UNLOAD_MODULE:
60 pa_module_unload(c, userdata, TRUE);
61 return 0;
62
63 default:
64 return -1;
65 }
66 }
67
68 static void core_free(pa_object *o);
69
70 pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size) {
71 pa_core* c;
72 pa_mempool *pool;
73 int j;
74
75 pa_assert(m);
76
77 if (shared) {
78 if (!(pool = pa_mempool_new(shared, shm_size))) {
79 pa_log_warn("failed to allocate shared memory pool. Falling back to a normal memory pool.");
80 shared = FALSE;
81 }
82 }
83
84 if (!shared) {
85 if (!(pool = pa_mempool_new(shared, shm_size))) {
86 pa_log("pa_mempool_new() failed.");
87 return NULL;
88 }
89 }
90
91 c = pa_msgobject_new(pa_core);
92 c->parent.parent.free = core_free;
93 c->parent.process_msg = core_process_msg;
94
95 c->state = PA_CORE_STARTUP;
96 c->mainloop = m;
97
98 c->clients = pa_idxset_new(NULL, NULL);
99 c->cards = pa_idxset_new(NULL, NULL);
100 c->sinks = pa_idxset_new(NULL, NULL);
101 c->sources = pa_idxset_new(NULL, NULL);
102 c->sink_inputs = pa_idxset_new(NULL, NULL);
103 c->source_outputs = pa_idxset_new(NULL, NULL);
104 c->modules = pa_idxset_new(NULL, NULL);
105 c->scache = pa_idxset_new(NULL, NULL);
106
107 c->namereg = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
108 c->shared = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
109
110 c->default_source = NULL;
111 c->default_sink = NULL;
112
113 c->default_sample_spec.format = PA_SAMPLE_S16NE;
114 c->default_sample_spec.rate = 44100;
115 c->default_sample_spec.channels = 2;
116 pa_channel_map_init_extend(&c->default_channel_map, c->default_sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
117 c->default_n_fragments = 4;
118 c->default_fragment_size_msec = 25;
119
120 c->module_defer_unload_event = NULL;
121 c->scache_auto_unload_event = NULL;
122
123 c->subscription_defer_event = NULL;
124 PA_LLIST_HEAD_INIT(pa_subscription, c->subscriptions);
125 PA_LLIST_HEAD_INIT(pa_subscription_event, c->subscription_event_queue);
126 c->subscription_event_last = NULL;
127
128 c->mempool = pool;
129 pa_silence_cache_init(&c->silence_cache);
130
131 c->exit_event = NULL;
132
133 c->exit_idle_time = -1;
134 c->scache_idle_time = 20;
135
136 c->flat_volumes = TRUE;
137 c->disallow_module_loading = FALSE;
138 c->disallow_exit = FALSE;
139 c->running_as_daemon = FALSE;
140 c->realtime_scheduling = FALSE;
141 c->realtime_priority = 5;
142 c->disable_remixing = FALSE;
143 c->disable_lfe_remixing = FALSE;
144 c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 3;
145
146 for (j = 0; j < PA_CORE_HOOK_MAX; j++)
147 pa_hook_init(&c->hooks[j], c);
148
149 pa_random(&c->cookie, sizeof(c->cookie));
150
151 #ifdef SIGPIPE
152 pa_check_signal_is_blocked(SIGPIPE);
153 #endif
154
155 pa_core_check_idle(c);
156
157 c->state = PA_CORE_RUNNING;
158
159 return c;
160 }
161
162 static void core_free(pa_object *o) {
163 pa_core *c = PA_CORE(o);
164 int j;
165 pa_assert(c);
166
167 c->state = PA_CORE_SHUTDOWN;
168
169 pa_module_unload_all(c);
170 pa_scache_free_all(c);
171
172 pa_assert(pa_idxset_isempty(c->scache));
173 pa_idxset_free(c->scache, NULL, NULL);
174
175 pa_assert(pa_idxset_isempty(c->modules));
176 pa_idxset_free(c->modules, NULL, NULL);
177
178 pa_assert(pa_idxset_isempty(c->clients));
179 pa_idxset_free(c->clients, NULL, NULL);
180
181 pa_assert(pa_idxset_isempty(c->cards));
182 pa_idxset_free(c->cards, NULL, NULL);
183
184 pa_assert(pa_idxset_isempty(c->sinks));
185 pa_idxset_free(c->sinks, NULL, NULL);
186
187 pa_assert(pa_idxset_isempty(c->sources));
188 pa_idxset_free(c->sources, NULL, NULL);
189
190 pa_assert(pa_idxset_isempty(c->source_outputs));
191 pa_idxset_free(c->source_outputs, NULL, NULL);
192
193 pa_assert(pa_idxset_isempty(c->sink_inputs));
194 pa_idxset_free(c->sink_inputs, NULL, NULL);
195
196 pa_assert(pa_hashmap_isempty(c->namereg));
197 pa_hashmap_free(c->namereg, NULL, NULL);
198
199 pa_assert(pa_hashmap_isempty(c->shared));
200 pa_hashmap_free(c->shared, NULL, NULL);
201
202 pa_subscription_free_all(c);
203
204 if (c->exit_event)
205 c->mainloop->time_free(c->exit_event);
206
207 pa_assert(!c->default_source);
208 pa_assert(!c->default_sink);
209
210 pa_silence_cache_done(&c->silence_cache);
211 pa_mempool_free(c->mempool);
212
213 for (j = 0; j < PA_CORE_HOOK_MAX; j++)
214 pa_hook_done(&c->hooks[j]);
215
216 pa_xfree(c);
217 }
218
219 static void exit_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {
220 pa_core *c = userdata;
221 pa_assert(c->exit_event == e);
222
223 pa_log_info("We are idle, quitting...");
224 pa_core_exit(c, TRUE, 0);
225 }
226
227 void pa_core_check_idle(pa_core *c) {
228 pa_assert(c);
229
230 if (!c->exit_event &&
231 c->exit_idle_time >= 0 &&
232 pa_idxset_size(c->clients) == 0) {
233
234 c->exit_event = pa_core_rttime_new(c, pa_rtclock_now() + c->exit_idle_time * PA_USEC_PER_SEC, exit_callback, c);
235
236 } else if (c->exit_event && pa_idxset_size(c->clients) > 0) {
237 c->mainloop->time_free(c->exit_event);
238 c->exit_event = NULL;
239 }
240 }
241
242 int pa_core_exit(pa_core *c, pa_bool_t force, int retval) {
243 pa_assert(c);
244
245 if (c->disallow_exit && !force)
246 return -1;
247
248 c->mainloop->quit(c->mainloop, retval);
249 return 0;
250 }
251
252 void pa_core_maybe_vacuum(pa_core *c) {
253 pa_assert(c);
254
255 if (!pa_idxset_isempty(c->sink_inputs) ||
256 !pa_idxset_isempty(c->source_outputs))
257 return;
258
259 pa_log_debug("Hmm, no streams around, trying to vacuum.");
260 pa_mempool_vacuum(c->mempool);
261 }
262
263 pa_time_event* pa_core_rttime_new(pa_core *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata) {
264 struct timeval tv;
265
266 pa_assert(c);
267 pa_assert(c->mainloop);
268
269 return c->mainloop->time_new(c->mainloop, pa_timeval_rtstore(&tv, usec, TRUE), cb, userdata);
270 }
271
272 void pa_core_rttime_restart(pa_core *c, pa_time_event *e, pa_usec_t usec) {
273 struct timeval tv;
274
275 pa_assert(c);
276 pa_assert(c->mainloop);
277
278 c->mainloop->time_restart(e, pa_timeval_rtstore(&tv, usec, TRUE));
279 }