]> code.delx.au - pulseaudio/blob - src/pulsecore/core.c
Fix up some double spaces
[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->sync_volume_safety_margin_usec = 8000;
121 c->sync_volume_extra_delay_usec = 0;
122
123 c->module_defer_unload_event = NULL;
124 c->scache_auto_unload_event = NULL;
125
126 c->subscription_defer_event = NULL;
127 PA_LLIST_HEAD_INIT(pa_subscription, c->subscriptions);
128 PA_LLIST_HEAD_INIT(pa_subscription_event, c->subscription_event_queue);
129 c->subscription_event_last = NULL;
130
131 c->mempool = pool;
132 pa_silence_cache_init(&c->silence_cache);
133
134 c->exit_event = NULL;
135
136 c->exit_idle_time = -1;
137 c->scache_idle_time = 20;
138
139 c->flat_volumes = TRUE;
140 c->disallow_module_loading = FALSE;
141 c->disallow_exit = FALSE;
142 c->running_as_daemon = FALSE;
143 c->realtime_scheduling = FALSE;
144 c->realtime_priority = 5;
145 c->disable_remixing = FALSE;
146 c->disable_lfe_remixing = FALSE;
147 c->sync_volume = TRUE;
148 c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 3;
149
150 for (j = 0; j < PA_CORE_HOOK_MAX; j++)
151 pa_hook_init(&c->hooks[j], c);
152
153 pa_random(&c->cookie, sizeof(c->cookie));
154
155 #ifdef SIGPIPE
156 pa_check_signal_is_blocked(SIGPIPE);
157 #endif
158
159 pa_core_check_idle(c);
160
161 c->state = PA_CORE_RUNNING;
162
163 return c;
164 }
165
166 static void core_free(pa_object *o) {
167 pa_core *c = PA_CORE(o);
168 int j;
169 pa_assert(c);
170
171 c->state = PA_CORE_SHUTDOWN;
172
173 pa_module_unload_all(c);
174 pa_scache_free_all(c);
175
176 pa_assert(pa_idxset_isempty(c->scache));
177 pa_idxset_free(c->scache, NULL, NULL);
178
179 pa_assert(pa_idxset_isempty(c->modules));
180 pa_idxset_free(c->modules, NULL, NULL);
181
182 pa_assert(pa_idxset_isempty(c->clients));
183 pa_idxset_free(c->clients, NULL, NULL);
184
185 pa_assert(pa_idxset_isempty(c->cards));
186 pa_idxset_free(c->cards, NULL, NULL);
187
188 pa_assert(pa_idxset_isempty(c->sinks));
189 pa_idxset_free(c->sinks, NULL, NULL);
190
191 pa_assert(pa_idxset_isempty(c->sources));
192 pa_idxset_free(c->sources, NULL, NULL);
193
194 pa_assert(pa_idxset_isempty(c->source_outputs));
195 pa_idxset_free(c->source_outputs, NULL, NULL);
196
197 pa_assert(pa_idxset_isempty(c->sink_inputs));
198 pa_idxset_free(c->sink_inputs, NULL, NULL);
199
200 pa_assert(pa_hashmap_isempty(c->namereg));
201 pa_hashmap_free(c->namereg, NULL, NULL);
202
203 pa_assert(pa_hashmap_isempty(c->shared));
204 pa_hashmap_free(c->shared, NULL, NULL);
205
206 pa_subscription_free_all(c);
207
208 if (c->exit_event)
209 c->mainloop->time_free(c->exit_event);
210
211 pa_assert(!c->default_source);
212 pa_assert(!c->default_sink);
213
214 pa_silence_cache_done(&c->silence_cache);
215 pa_mempool_free(c->mempool);
216
217 for (j = 0; j < PA_CORE_HOOK_MAX; j++)
218 pa_hook_done(&c->hooks[j]);
219
220 pa_xfree(c);
221 }
222
223 static void exit_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {
224 pa_core *c = userdata;
225 pa_assert(c->exit_event == e);
226
227 pa_log_info("We are idle, quitting...");
228 pa_core_exit(c, TRUE, 0);
229 }
230
231 void pa_core_check_idle(pa_core *c) {
232 pa_assert(c);
233
234 if (!c->exit_event &&
235 c->exit_idle_time >= 0 &&
236 pa_idxset_size(c->clients) == 0) {
237
238 c->exit_event = pa_core_rttime_new(c, pa_rtclock_now() + c->exit_idle_time * PA_USEC_PER_SEC, exit_callback, c);
239
240 } else if (c->exit_event && pa_idxset_size(c->clients) > 0) {
241 c->mainloop->time_free(c->exit_event);
242 c->exit_event = NULL;
243 }
244 }
245
246 int pa_core_exit(pa_core *c, pa_bool_t force, int retval) {
247 pa_assert(c);
248
249 if (c->disallow_exit && !force)
250 return -1;
251
252 c->mainloop->quit(c->mainloop, retval);
253 return 0;
254 }
255
256 void pa_core_maybe_vacuum(pa_core *c) {
257 pa_assert(c);
258
259 if (!pa_idxset_isempty(c->sink_inputs) ||
260 !pa_idxset_isempty(c->source_outputs))
261 return;
262
263 pa_log_debug("Hmm, no streams around, trying to vacuum.");
264 pa_mempool_vacuum(c->mempool);
265 }
266
267 pa_time_event* pa_core_rttime_new(pa_core *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata) {
268 struct timeval tv;
269
270 pa_assert(c);
271 pa_assert(c->mainloop);
272
273 return c->mainloop->time_new(c->mainloop, pa_timeval_rtstore(&tv, usec, TRUE), cb, userdata);
274 }
275
276 void pa_core_rttime_restart(pa_core *c, pa_time_event *e, pa_usec_t usec) {
277 struct timeval tv;
278
279 pa_assert(c);
280 pa_assert(c->mainloop);
281
282 c->mainloop->time_restart(e, pa_timeval_rtstore(&tv, usec, TRUE));
283 }