]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/core-scache.c
core: Add name to flist struct for more informative log messages
[pulseaudio] / src / pulsecore / core-scache.c
index 0f34c9d1b0e25b1d7a7348317a713c8c5e3a6ebb..5ec6159d67f9d9681c92aceda3b60e48e8019ff6 100644 (file)
@@ -6,7 +6,7 @@
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
-  by the Free Software Foundation; either version 2 of the License,
+  by the Free Software Foundation; either version 2.1 of the License,
   or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
   or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
@@ -47,6 +47,7 @@
 #include <pulse/util.h>
 #include <pulse/volume.h>
 #include <pulse/xmalloc.h>
 #include <pulse/util.h>
 #include <pulse/volume.h>
 #include <pulse/xmalloc.h>
+#include <pulse/rtclock.h>
 
 #include <pulsecore/sink-input.h>
 #include <pulsecore/sample-util.h>
 
 #include <pulsecore/sink-input.h>
 #include <pulsecore/sample-util.h>
@@ -54,6 +55,7 @@
 #include <pulsecore/core-subscribe.h>
 #include <pulsecore/namereg.h>
 #include <pulsecore/sound-file.h>
 #include <pulsecore/core-subscribe.h>
 #include <pulsecore/namereg.h>
 #include <pulsecore/sound-file.h>
+#include <pulsecore/core-rtclock.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
 #include <pulsecore/core-error.h>
 
 #include "core-scache.h"
 
 
 #include "core-scache.h"
 
-#define UNLOAD_POLL_TIME 60
+#define UNLOAD_POLL_TIME (60 * PA_USEC_PER_SEC)
 
 
-static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, const struct timeval *tv, void *userdata) {
+static void timeout_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {
     pa_core *c = userdata;
     pa_core *c = userdata;
-    struct timeval ntv;
 
     pa_assert(c);
     pa_assert(c->mainloop == m);
 
     pa_assert(c);
     pa_assert(c->mainloop == m);
@@ -73,9 +74,7 @@ static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, const struct t
 
     pa_scache_unload_unused(c);
 
 
     pa_scache_unload_unused(c);
 
-    pa_gettimeofday(&ntv);
-    ntv.tv_sec += UNLOAD_POLL_TIME;
-    m->time_restart(e, &ntv);
+    pa_core_rttime_restart(c, e, pa_rtclock_now() + UNLOAD_POLL_TIME);
 }
 
 static void free_entry(pa_scache_entry *e) {
 }
 
 static void free_entry(pa_scache_entry *e) {
@@ -120,9 +119,6 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
         e->core = c;
         e->proplist = pa_proplist_new();
 
         e->core = c;
         e->proplist = pa_proplist_new();
 
-        if (!c->scache)
-            c->scache = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
-
         pa_idxset_put(c->scache, e, &e->index);
 
         pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_NEW, e->index);
         pa_idxset_put(c->scache, e, &e->index);
 
         pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_NEW, e->index);
@@ -137,6 +133,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
     pa_sample_spec_init(&e->sample_spec);
     pa_channel_map_init(&e->channel_map);
     pa_cvolume_init(&e->volume);
     pa_sample_spec_init(&e->sample_spec);
     pa_channel_map_init(&e->channel_map);
     pa_cvolume_init(&e->volume);
+    e->volume_is_set = FALSE;
 
     pa_proplist_sets(e->proplist, PA_PROP_MEDIA_ROLE, "event");
 
 
     pa_proplist_sets(e->proplist, PA_PROP_MEDIA_ROLE, "event");
 
@@ -175,6 +172,7 @@ int pa_scache_add_item(
     pa_sample_spec_init(&e->sample_spec);
     pa_channel_map_init(&e->channel_map);
     pa_cvolume_init(&e->volume);
     pa_sample_spec_init(&e->sample_spec);
     pa_channel_map_init(&e->channel_map);
     pa_cvolume_init(&e->volume);
+    e->volume_is_set = FALSE;
 
     if (ss) {
         e->sample_spec = *ss;
 
     if (ss) {
         e->sample_spec = *ss;
@@ -220,11 +218,14 @@ int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint3
     pa_assert(name);
     pa_assert(filename);
 
     pa_assert(name);
     pa_assert(filename);
 
-    if (pa_sound_file_load(c->mempool, filename, &ss, &map, &chunk) < 0)
-        return -1;
-
     p = pa_proplist_new();
     pa_proplist_sets(p, PA_PROP_MEDIA_FILENAME, filename);
     p = pa_proplist_new();
     pa_proplist_sets(p, PA_PROP_MEDIA_FILENAME, filename);
+
+    if (pa_sound_file_load(c->mempool, filename, &ss, &map, &chunk, p) < 0) {
+        pa_proplist_free(p);
+        return -1;
+    }
+
     r = pa_scache_add_item(c, name, &ss, &map, &chunk, p, idx);
     pa_memblock_unref(chunk.memblock);
     pa_proplist_free(p);
     r = pa_scache_add_item(c, name, &ss, &map, &chunk, p, idx);
     pa_memblock_unref(chunk.memblock);
     pa_proplist_free(p);
@@ -254,12 +255,8 @@ int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename,
 
     pa_proplist_sets(e->proplist, PA_PROP_MEDIA_FILENAME, filename);
 
 
     pa_proplist_sets(e->proplist, PA_PROP_MEDIA_FILENAME, filename);
 
-    if (!c->scache_auto_unload_event) {
-        struct timeval ntv;
-        pa_gettimeofday(&ntv);
-        ntv.tv_sec += UNLOAD_POLL_TIME;
-        c->scache_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c);
-    }
+    if (!c->scache_auto_unload_event)
+        c->scache_auto_unload_event = pa_core_rttime_new(c, pa_rtclock_now() + UNLOAD_POLL_TIME, timeout_callback, c);
 
     if (idx)
         *idx = e->index;
 
     if (idx)
         *idx = e->index;
@@ -285,29 +282,25 @@ int pa_scache_remove_item(pa_core *c, const char *name) {
     return 0;
 }
 
     return 0;
 }
 
-static void free_cb(void *p, void *userdata) {
-    pa_scache_entry *e = p;
-    pa_assert(e);
-
-    free_entry(e);
-}
+void pa_scache_free_all(pa_core *c) {
+    pa_scache_entry *e;
 
 
-void pa_scache_free(pa_core *c) {
     pa_assert(c);
 
     pa_assert(c);
 
-    if (c->scache) {
-        pa_idxset_free(c->scache, free_cb, NULL);
-        c->scache = NULL;
-    }
+    while ((e = pa_idxset_steal_first(c->scache, NULL)))
+        free_entry(e);
 
 
-    if (c->scache_auto_unload_event)
+    if (c->scache_auto_unload_event) {
         c->mainloop->time_free(c->scache_auto_unload_event);
         c->mainloop->time_free(c->scache_auto_unload_event);
+        c->scache_auto_unload_event = NULL;
+    }
 }
 
 int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t volume, pa_proplist *p, uint32_t *sink_input_idx) {
     pa_scache_entry *e;
     pa_cvolume r;
     pa_proplist *merged;
 }
 
 int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t volume, pa_proplist *p, uint32_t *sink_input_idx) {
     pa_scache_entry *e;
     pa_cvolume r;
     pa_proplist *merged;
+    pa_bool_t pass_volume;
 
     pa_assert(c);
     pa_assert(name);
 
     pa_assert(c);
     pa_assert(name);
@@ -316,41 +309,55 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t
     if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE)))
         return -1;
 
     if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE)))
         return -1;
 
+    merged = pa_proplist_new();
+    pa_proplist_sets(merged, PA_PROP_MEDIA_NAME, name);
+    pa_proplist_sets(merged, PA_PROP_EVENT_ID, name);
+
     if (e->lazy && !e->memchunk.memblock) {
         pa_channel_map old_channel_map = e->channel_map;
 
     if (e->lazy && !e->memchunk.memblock) {
         pa_channel_map old_channel_map = e->channel_map;
 
-        if (pa_sound_file_load(c->mempool, e->filename, &e->sample_spec, &e->channel_map, &e->memchunk) < 0)
-            return -1;
+        if (pa_sound_file_load(c->mempool, e->filename, &e->sample_spec, &e->channel_map, &e->memchunk, merged) < 0)
+            goto fail;
 
         pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index);
 
 
         pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index);
 
-        if (pa_cvolume_valid(&e->volume))
-            pa_cvolume_remap(&e->volume, &old_channel_map, &e->channel_map);
-        else
-            pa_cvolume_reset(&e->volume, e->sample_spec.channels);
+        if (e->volume_is_set) {
+            if (pa_cvolume_valid(&e->volume))
+                pa_cvolume_remap(&e->volume, &old_channel_map, &e->channel_map);
+            else
+                pa_cvolume_reset(&e->volume, e->sample_spec.channels);
+        }
     }
 
     if (!e->memchunk.memblock)
     }
 
     if (!e->memchunk.memblock)
-        return -1;
+        goto fail;
 
     pa_log_debug("Playing sample \"%s\" on \"%s\"", name, sink->name);
 
 
     pa_log_debug("Playing sample \"%s\" on \"%s\"", name, sink->name);
 
-    pa_cvolume_set(&r, e->volume.channels, volume);
-    pa_sw_cvolume_multiply(&r, &r, &e->volume);
+    pass_volume = TRUE;
 
 
-    merged = pa_proplist_new();
-
-    pa_proplist_setf(merged, PA_PROP_MEDIA_NAME, "Sample %s", name);
+    if (e->volume_is_set && PA_VOLUME_IS_VALID(volume)) {
+        pa_cvolume_set(&r, e->sample_spec.channels, volume);
+        pa_sw_cvolume_multiply(&r, &r, &e->volume);
+    } else if (e->volume_is_set)
+        r = e->volume;
+    else if (PA_VOLUME_IS_VALID(volume))
+        pa_cvolume_set(&r, e->sample_spec.channels, volume);
+    else
+        pass_volume = FALSE;
 
     pa_proplist_update(merged, PA_UPDATE_REPLACE, e->proplist);
 
     if (p)
         pa_proplist_update(merged, PA_UPDATE_REPLACE, p);
 
 
     pa_proplist_update(merged, PA_UPDATE_REPLACE, e->proplist);
 
     if (p)
         pa_proplist_update(merged, PA_UPDATE_REPLACE, p);
 
-    if (pa_play_memchunk(sink, &e->sample_spec, &e->channel_map, &e->memchunk, &r, merged, sink_input_idx) < 0) {
-        pa_proplist_free(merged);
-        return -1;
-    }
+    if (pa_play_memchunk(sink,
+                         &e->sample_spec, &e->channel_map,
+                         &e->memchunk,
+                         pass_volume ? &r : NULL,
+                         merged,
+                         PA_SINK_INPUT_NO_CREATE_ON_SUSPEND|PA_SINK_INPUT_KILL_ON_SUSPEND, sink_input_idx) < 0)
+        goto fail;
 
     pa_proplist_free(merged);
 
 
     pa_proplist_free(merged);
 
@@ -358,6 +365,10 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t
         time(&e->last_used_time);
 
     return 0;
         time(&e->last_used_time);
 
     return 0;
+
+fail:
+    pa_proplist_free(merged);
+    return -1;
 }
 
 int pa_scache_play_item_by_name(pa_core *c, const char *name, const char*sink_name, pa_volume_t volume, pa_proplist *p, uint32_t *sink_input_idx) {
 }
 
 int pa_scache_play_item_by_name(pa_core *c, const char *name, const char*sink_name, pa_volume_t volume, pa_proplist *p, uint32_t *sink_input_idx) {
@@ -489,13 +500,14 @@ int pa_scache_add_directory_lazy(pa_core *c, const char *pathname) {
         struct dirent *e;
 
         while ((e = readdir(dir))) {
         struct dirent *e;
 
         while ((e = readdir(dir))) {
-            char p[PATH_MAX];
+            char *p;
 
             if (e->d_name[0] == '.')
                 continue;
 
 
             if (e->d_name[0] == '.')
                 continue;
 
-            pa_snprintf(p, sizeof(p), "%s/%s", pathname, e->d_name);
+            p = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", pathname, e->d_name);
             add_file(c, p);
             add_file(c, p);
+            pa_xfree(p);
         }
 
         closedir(dir);
         }
 
         closedir(dir);