volume ramp: additions to the low level infra
[platform/upstream/pulseaudio.git] / 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/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>
43
44 #include "core.h"
45
46 PA_DEFINE_PUBLIC_CLASS(pa_core, pa_msgobject);
47
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);
50
51     pa_core_assert_ref(c);
52
53     switch (code) {
54
55         case PA_CORE_MESSAGE_UNLOAD_MODULE:
56             pa_module_unload(c, userdata, true);
57             return 0;
58
59         default:
60             return -1;
61     }
62 }
63
64 static void core_free(pa_object *o);
65
66 pa_core* pa_core_new(pa_mainloop_api *m, bool shared, size_t shm_size) {
67     pa_core* c;
68     pa_mempool *pool;
69     int j;
70
71     pa_assert(m);
72
73     if (shared) {
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.");
76             shared = false;
77         }
78     }
79
80     if (!shared) {
81         if (!(pool = pa_mempool_new(shared, shm_size))) {
82             pa_log("pa_mempool_new() failed.");
83             return NULL;
84         }
85     }
86
87     c = pa_msgobject_new(pa_core);
88     c->parent.parent.free = core_free;
89     c->parent.process_msg = core_process_msg;
90
91     c->state = PA_CORE_STARTUP;
92     c->mainloop = m;
93
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);
102
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);
105
106     c->default_source = NULL;
107     c->default_sink = NULL;
108
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;
115
116     c->deferred_volume_safety_margin_usec = 8000;
117     c->deferred_volume_extra_delay_usec = 0;
118
119     c->module_defer_unload_event = NULL;
120     c->scache_auto_unload_event = NULL;
121
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;
126
127     c->mempool = pool;
128     pa_silence_cache_init(&c->silence_cache);
129
130     c->exit_event = NULL;
131
132     c->exit_idle_time = -1;
133     c->scache_idle_time = 20;
134
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;
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     /* Note: All modules and samples in the cache should be unloaded before
170      * we get here */
171
172     pa_assert(pa_idxset_isempty(c->scache));
173     pa_idxset_free(c->scache, NULL);
174
175     pa_assert(pa_idxset_isempty(c->modules));
176     pa_idxset_free(c->modules, NULL);
177
178     pa_assert(pa_idxset_isempty(c->clients));
179     pa_idxset_free(c->clients, NULL);
180
181     pa_assert(pa_idxset_isempty(c->cards));
182     pa_idxset_free(c->cards, NULL);
183
184     pa_assert(pa_idxset_isempty(c->sinks));
185     pa_idxset_free(c->sinks, NULL);
186
187     pa_assert(pa_idxset_isempty(c->sources));
188     pa_idxset_free(c->sources, NULL);
189
190     pa_assert(pa_idxset_isempty(c->source_outputs));
191     pa_idxset_free(c->source_outputs, NULL);
192
193     pa_assert(pa_idxset_isempty(c->sink_inputs));
194     pa_idxset_free(c->sink_inputs, NULL);
195
196     pa_assert(pa_hashmap_isempty(c->namereg));
197     pa_hashmap_free(c->namereg);
198
199     pa_assert(pa_hashmap_isempty(c->shared));
200     pa_hashmap_free(c->shared);
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, bool 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) && pa_idxset_isempty(c->source_outputs)) {
256         pa_log_debug("Hmm, no streams around, trying to vacuum.");
257         pa_mempool_vacuum(c->mempool);
258     } else {
259         pa_sink *si;
260         pa_source *so;
261         uint32_t idx;
262
263         idx = 0;
264         PA_IDXSET_FOREACH(si, c->sinks, idx)
265             if (pa_sink_get_state(si) != PA_SINK_SUSPENDED)
266                 return;
267
268         idx = 0;
269         PA_IDXSET_FOREACH(so, c->sources, idx)
270             if (pa_source_get_state(so) != PA_SOURCE_SUSPENDED)
271                 return;
272
273         pa_log_info("All sinks and sources are suspended, vacuuming memory");
274         pa_mempool_vacuum(c->mempool);
275     }
276 }
277
278 pa_time_event* pa_core_rttime_new(pa_core *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata) {
279     struct timeval tv;
280
281     pa_assert(c);
282     pa_assert(c->mainloop);
283
284     return c->mainloop->time_new(c->mainloop, pa_timeval_rtstore(&tv, usec, true), cb, userdata);
285 }
286
287 void pa_core_rttime_restart(pa_core *c, pa_time_event *e, pa_usec_t usec) {
288     struct timeval tv;
289
290     pa_assert(c);
291     pa_assert(c->mainloop);
292
293     c->mainloop->time_restart(e, pa_timeval_rtstore(&tv, usec, true));
294 }