]> code.delx.au - pulseaudio/blobdiff - src/modules/module-suspend-on-idle.c
Remove unnecessary #includes
[pulseaudio] / src / modules / module-suspend-on-idle.c
index 70a7b0492dd64ca496b1976e80195385a81cc28f..e7242628edab9a80dd1e47e543c686297a10d8b6 100644 (file)
@@ -33,7 +33,6 @@
 #include <pulsecore/source-output.h>
 #include <pulsecore/modargs.h>
 #include <pulsecore/log.h>
-#include <pulsecore/namereg.h>
 
 #include "module-suspend-on-idle-symdef.h"
 
@@ -41,9 +40,13 @@ PA_MODULE_AUTHOR("Lennart Poettering");
 PA_MODULE_DESCRIPTION("When a sink/source is idle for too long, suspend it");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(TRUE);
+PA_MODULE_USAGE(
+        "timeout=<timeout> "
+        "mempool_vacuum=<vacuum memory if all sinks and sources are suspended?>");
 
 static const char* const valid_modargs[] = {
     "timeout",
+    "mempool_vacuum",
     NULL,
 };
 
@@ -70,6 +73,8 @@ struct userdata {
         *source_output_move_finish_slot,
         *sink_input_state_changed_slot,
         *source_output_state_changed_slot;
+
+    pa_bool_t mempool_vacuum:1;
 };
 
 struct device_info {
@@ -80,6 +85,29 @@ struct device_info {
     pa_time_event *time_event;
 };
 
+static void check_meempool_vacuum(struct device_info *d) {
+    pa_sink *si;
+    pa_source *so;
+    uint32_t idx;
+
+    pa_assert(d);
+    pa_assert(d->userdata);
+    pa_assert(d->userdata->core);
+
+    idx = 0;
+    PA_IDXSET_FOREACH(si, d->userdata->core->sinks, idx)
+        if (pa_sink_get_state(si) != PA_SINK_SUSPENDED)
+            return;
+
+    idx = 0;
+    PA_IDXSET_FOREACH(so, d->userdata->core->sources, idx)
+        if (pa_source_get_state(so) != PA_SOURCE_SUSPENDED)
+            return;
+
+    pa_log_info("All sinks and sources are suspended, vacuuming memory");
+    pa_mempool_vacuum(d->userdata->core->mempool);
+}
+
 static void timeout_cb(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
     struct device_info *d = userdata;
 
@@ -90,11 +118,15 @@ static void timeout_cb(pa_mainloop_api*a, pa_time_event* e, const struct timeval
     if (d->sink && pa_sink_check_suspend(d->sink) <= 0 && !(d->sink->suspend_cause & PA_SUSPEND_IDLE)) {
         pa_log_info("Sink %s idle for too long, suspending ...", d->sink->name);
         pa_sink_suspend(d->sink, TRUE, PA_SUSPEND_IDLE);
+        if (d->userdata->mempool_vacuum)
+            check_meempool_vacuum(d);
     }
 
     if (d->source && pa_source_check_suspend(d->source) <= 0 && !(d->source->suspend_cause & PA_SUSPEND_IDLE)) {
         pa_log_info("Source %s idle for too long, suspending ...", d->source->name);
         pa_source_suspend(d->source, TRUE, PA_SUSPEND_IDLE);
+        if (d->userdata->mempool_vacuum)
+            check_meempool_vacuum(d);
     }
 }
 
@@ -145,6 +177,10 @@ static pa_hook_result_t sink_input_fixate_hook_cb(pa_core *c, pa_sink_input_new_
     pa_assert(data);
     pa_assert(u);
 
+    /* We need to resume the audio device here even for
+     * PA_SINK_INPUT_START_CORKED, since we need the device parameters
+     * to be fully available while the stream is set up. */
+
     if ((d = pa_hashmap_get(u->device_infos, data->sink)))
         resume(d);
 
@@ -226,11 +262,16 @@ static pa_hook_result_t sink_input_move_start_hook_cb(pa_core *c, pa_sink_input
 
 static pa_hook_result_t sink_input_move_finish_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) {
     struct device_info *d;
+    pa_sink_input_state_t state;
 
     pa_assert(c);
     pa_sink_input_assert_ref(s);
     pa_assert(u);
 
+    state = pa_sink_input_get_state(s);
+    if (state != PA_SINK_INPUT_RUNNING && state != PA_SINK_INPUT_DRAINED)
+        return PA_HOOK_OK;
+
     if ((d = pa_hashmap_get(u->device_infos, s->sink)))
         resume(d);
 
@@ -265,6 +306,9 @@ static pa_hook_result_t source_output_move_finish_hook_cb(pa_core *c, pa_source_
     pa_source_output_assert_ref(s);
     pa_assert(u);
 
+    if (pa_source_output_get_state(s) != PA_SOURCE_OUTPUT_RUNNING)
+        return PA_HOOK_OK;
+
     if (s->source->monitor_of)
         d = pa_hashmap_get(u->device_infos, s->source->monitor_of);
     else
@@ -279,6 +323,7 @@ static pa_hook_result_t source_output_move_finish_hook_cb(pa_core *c, pa_source_
 static pa_hook_result_t sink_input_state_changed_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) {
     struct device_info *d;
     pa_sink_input_state_t state;
+
     pa_assert(c);
     pa_sink_input_assert_ref(s);
     pa_assert(u);
@@ -292,15 +337,11 @@ static pa_hook_result_t sink_input_state_changed_hook_cb(pa_core *c, pa_sink_inp
 }
 
 static pa_hook_result_t source_output_state_changed_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) {
-    pa_source_output_state_t state;
-
     pa_assert(c);
     pa_source_output_assert_ref(s);
     pa_assert(u);
 
-    state = pa_source_output_get_state(s);
-
-    if (state == PA_SOURCE_OUTPUT_RUNNING) {
+    if (pa_source_output_get_state(s) == PA_SOURCE_OUTPUT_RUNNING) {
         struct device_info *d;
 
         if (s->source->monitor_of)
@@ -387,22 +428,17 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s
         pa_sink *s = PA_SINK(o);
         pa_sink_state_t state = pa_sink_get_state(s);
 
-        if (pa_sink_check_suspend(s) <= 0) {
-
+        if (pa_sink_check_suspend(s) <= 0)
             if (PA_SINK_IS_OPENED(state))
                 restart(d);
 
-        }
-
     } else if (pa_source_isinstance(o)) {
         pa_source *s = PA_SOURCE(o);
         pa_source_state_t state = pa_source_get_state(s);
 
-        if (pa_source_check_suspend(s) <= 0) {
-
+        if (pa_source_check_suspend(s) <= 0)
             if (PA_SOURCE_IS_OPENED(state))
                 restart(d);
-        }
     }
 
     return PA_HOOK_OK;
@@ -412,6 +448,7 @@ int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     struct userdata *u;
     uint32_t timeout = 5;
+    pa_bool_t mempool_vacuum = FALSE;
     uint32_t idx;
     pa_sink *sink;
     pa_source *source;
@@ -428,10 +465,16 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
+    if (pa_modargs_get_value_boolean(ma, "mempool_vacuum", &mempool_vacuum) < 0) {
+        pa_log("Failed to parse mempool_vacuum boolean parameter.");
+        goto fail;
+    }
+
     m->userdata = u = pa_xnew(struct userdata, 1);
     u->core = m->core;
     u->timeout = timeout;
     u->device_infos = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+    u->mempool_vacuum = mempool_vacuum;
 
     for (sink = pa_idxset_first(m->core->sinks, &idx); sink; sink = pa_idxset_next(m->core->sinks, &idx))
         device_new_hook_cb(m->core, PA_OBJECT(sink), u);