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