2 This file is part of PulseAudio.
4 Copyright 2004-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.1 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
31 #include <pulse/rtclock.h>
32 #include <pulse/timeval.h>
33 #include <pulse/xmalloc.h>
35 #include <pulsecore/module.h>
36 #include <pulsecore/core-rtclock.h>
37 #include <pulsecore/core-util.h>
38 #include <pulsecore/core-scache.h>
39 #include <pulsecore/core-subscribe.h>
40 #include <pulsecore/random.h>
41 #include <pulsecore/log.h>
42 #include <pulsecore/macro.h>
46 PA_DEFINE_PUBLIC_CLASS(pa_core, pa_msgobject);
48 static int core_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
49 pa_core *c = PA_CORE(o);
51 pa_core_assert_ref(c);
55 case PA_CORE_MESSAGE_UNLOAD_MODULE:
56 pa_module_unload(c, userdata, true);
64 static void core_free(pa_object *o);
66 pa_core* pa_core_new(pa_mainloop_api *m, bool shared, size_t shm_size) {
74 if (!(pool = pa_mempool_new(shared, shm_size))) {
75 pa_log_warn("failed to allocate shared memory pool. Falling back to a normal memory pool.");
81 if (!(pool = pa_mempool_new(shared, shm_size))) {
82 pa_log("pa_mempool_new() failed.");
87 c = pa_msgobject_new(pa_core);
88 c->parent.parent.free = core_free;
89 c->parent.process_msg = core_process_msg;
91 c->state = PA_CORE_STARTUP;
94 c->clients = pa_idxset_new(NULL, NULL);
95 c->cards = pa_idxset_new(NULL, NULL);
96 c->sinks = pa_idxset_new(NULL, NULL);
97 c->sources = pa_idxset_new(NULL, NULL);
98 c->sink_inputs = pa_idxset_new(NULL, NULL);
99 c->source_outputs = pa_idxset_new(NULL, NULL);
100 c->modules = pa_idxset_new(NULL, NULL);
101 c->scache = pa_idxset_new(NULL, NULL);
103 c->namereg = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
104 c->shared = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
106 c->default_source = NULL;
107 c->default_sink = NULL;
109 c->default_sample_spec.format = PA_SAMPLE_S16NE;
110 c->default_sample_spec.rate = 44100;
111 c->default_sample_spec.channels = 2;
112 pa_channel_map_init_extend(&c->default_channel_map, c->default_sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
113 c->default_n_fragments = 4;
114 c->default_fragment_size_msec = 25;
116 c->deferred_volume_safety_margin_usec = 8000;
117 c->deferred_volume_extra_delay_usec = 0;
119 c->module_defer_unload_event = NULL;
120 c->scache_auto_unload_event = NULL;
122 c->subscription_defer_event = NULL;
123 PA_LLIST_HEAD_INIT(pa_subscription, c->subscriptions);
124 PA_LLIST_HEAD_INIT(pa_subscription_event, c->subscription_event_queue);
125 c->subscription_event_last = NULL;
128 pa_silence_cache_init(&c->silence_cache);
130 c->exit_event = NULL;
132 c->exit_idle_time = -1;
133 c->scache_idle_time = 20;
135 c->flat_volumes = true;
136 c->disallow_module_loading = false;
137 c->disallow_exit = false;
138 c->running_as_daemon = false;
139 c->realtime_scheduling = false;
140 c->realtime_priority = 5;
141 c->disable_remixing = false;
142 c->disable_lfe_remixing = false;
143 c->deferred_volume = true;
144 c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 1;
146 for (j = 0; j < PA_CORE_HOOK_MAX; j++)
147 pa_hook_init(&c->hooks[j], c);
149 pa_random(&c->cookie, sizeof(c->cookie));
152 pa_check_signal_is_blocked(SIGPIPE);
155 pa_core_check_idle(c);
157 c->state = PA_CORE_RUNNING;
162 static void core_free(pa_object *o) {
163 pa_core *c = PA_CORE(o);
167 c->state = PA_CORE_SHUTDOWN;
169 /* Note: All modules and samples in the cache should be unloaded before
172 pa_assert(pa_idxset_isempty(c->scache));
173 pa_idxset_free(c->scache, NULL);
175 pa_assert(pa_idxset_isempty(c->modules));
176 pa_idxset_free(c->modules, NULL);
178 pa_assert(pa_idxset_isempty(c->clients));
179 pa_idxset_free(c->clients, NULL);
181 pa_assert(pa_idxset_isempty(c->cards));
182 pa_idxset_free(c->cards, NULL);
184 pa_assert(pa_idxset_isempty(c->sinks));
185 pa_idxset_free(c->sinks, NULL);
187 pa_assert(pa_idxset_isempty(c->sources));
188 pa_idxset_free(c->sources, NULL);
190 pa_assert(pa_idxset_isempty(c->source_outputs));
191 pa_idxset_free(c->source_outputs, NULL);
193 pa_assert(pa_idxset_isempty(c->sink_inputs));
194 pa_idxset_free(c->sink_inputs, NULL);
196 pa_assert(pa_hashmap_isempty(c->namereg));
197 pa_hashmap_free(c->namereg, NULL);
199 pa_assert(pa_hashmap_isempty(c->shared));
200 pa_hashmap_free(c->shared, NULL);
202 pa_subscription_free_all(c);
205 c->mainloop->time_free(c->exit_event);
207 pa_assert(!c->default_source);
208 pa_assert(!c->default_sink);
210 pa_silence_cache_done(&c->silence_cache);
211 pa_mempool_free(c->mempool);
213 for (j = 0; j < PA_CORE_HOOK_MAX; j++)
214 pa_hook_done(&c->hooks[j]);
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);
223 pa_log_info("We are idle, quitting...");
224 pa_core_exit(c, true, 0);
227 void pa_core_check_idle(pa_core *c) {
230 if (!c->exit_event &&
231 c->exit_idle_time >= 0 &&
232 pa_idxset_size(c->clients) == 0) {
234 c->exit_event = pa_core_rttime_new(c, pa_rtclock_now() + c->exit_idle_time * PA_USEC_PER_SEC, exit_callback, c);
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;
242 int pa_core_exit(pa_core *c, bool force, int retval) {
245 if (c->disallow_exit && !force)
248 c->mainloop->quit(c->mainloop, retval);
252 void pa_core_maybe_vacuum(pa_core *c) {
255 if (pa_idxset_isempty(c->sink_inputs) && pa_idxset_isempty(c->source_outputs)) {
256 pa_log_debug("Hmm, no streams around, trying to vacuum.");
257 pa_mempool_vacuum(c->mempool);
264 PA_IDXSET_FOREACH(si, c->sinks, idx)
265 if (pa_sink_get_state(si) != PA_SINK_SUSPENDED)
269 PA_IDXSET_FOREACH(so, c->sources, idx)
270 if (pa_source_get_state(so) != PA_SOURCE_SUSPENDED)
273 pa_log_info("All sinks and sources are suspended, vacuuming memory");
274 pa_mempool_vacuum(c->mempool);
278 pa_time_event* pa_core_rttime_new(pa_core *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata) {
282 pa_assert(c->mainloop);
284 return c->mainloop->time_new(c->mainloop, pa_timeval_rtstore(&tv, usec, true), cb, userdata);
287 void pa_core_rttime_restart(pa_core *c, pa_time_event *e, pa_usec_t usec) {
291 pa_assert(c->mainloop);
293 c->mainloop->time_restart(e, pa_timeval_rtstore(&tv, usec, true));