]> 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 cb2727845dff287e003bc42f74ef6ff8fd268165..5ec6159d67f9d9681c92aceda3b60e48e8019ff6 100644 (file)
@@ -1,14 +1,12 @@
-/* $Id$ */
-
 /***
   This file is part of PulseAudio.
 
 /***
   This file is part of PulseAudio.
 
-  Copyright 2004-2006 Lennart Poettering
+  Copyright 2004-2008 Lennart Poettering
   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
 
   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
@@ -26,7 +24,6 @@
 #include <config.h>
 #endif
 
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -50,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>
 #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 <pulsecore/macro.h>
 
 #include "core-scache.h"
 
 
 #include "core-scache.h"
 
-#define UNLOAD_POLL_TIME 2
+#define UNLOAD_POLL_TIME (60 * PA_USEC_PER_SEC)
 
 
-static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED 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;
-    assert(c && c->mainloop == m && c->scache_auto_unload_event == e);
+
+    pa_assert(c);
+    pa_assert(c->mainloop == m);
+    pa_assert(c->scache_auto_unload_event == e);
 
     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) {
-    assert(e);
+    pa_assert(e);
+
     pa_namereg_unregister(e->core, e->name);
     pa_subscription_post(e->core, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_REMOVE, e->index);
     pa_xfree(e->name);
     pa_xfree(e->filename);
     if (e->memchunk.memblock)
         pa_memblock_unref(e->memchunk.memblock);
     pa_namereg_unregister(e->core, e->name);
     pa_subscription_post(e->core, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_REMOVE, e->index);
     pa_xfree(e->name);
     pa_xfree(e->filename);
     if (e->memchunk.memblock)
         pa_memblock_unref(e->memchunk.memblock);
+    if (e->proplist)
+        pa_proplist_free(e->proplist);
     pa_xfree(e);
 }
 
 static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
     pa_scache_entry *e;
     pa_xfree(e);
 }
 
 static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
     pa_scache_entry *e;
-    assert(c && name);
 
 
-    if ((e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) {
+    pa_assert(c);
+    pa_assert(name);
+
+    if ((e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE))) {
         if (e->memchunk.memblock)
             pa_memblock_unref(e->memchunk.memblock);
 
         pa_xfree(e->filename);
         if (e->memchunk.memblock)
             pa_memblock_unref(e->memchunk.memblock);
 
         pa_xfree(e->filename);
+        pa_proplist_clear(e->proplist);
 
 
-        assert(e->core == c);
+        pa_assert(e->core == c);
 
         pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index);
     } else {
 
         pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index);
     } else {
-        e = pa_xmalloc(sizeof(pa_scache_entry));
+        e = pa_xnew(pa_scache_entry, 1);
 
 
-        if (!pa_namereg_register(c, name, PA_NAMEREG_SAMPLE, e, 1)) {
+        if (!pa_namereg_register(c, name, PA_NAMEREG_SAMPLE, e, TRUE)) {
             pa_xfree(e);
             return NULL;
         }
 
         e->name = pa_xstrdup(name);
         e->core = c;
             pa_xfree(e);
             return NULL;
         }
 
         e->name = pa_xstrdup(name);
         e->core = c;
-
-        if (!c->scache) {
-            c->scache = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
-            assert(c->scache);
-        }
+        e->proplist = pa_proplist_new();
 
         pa_idxset_put(c->scache, e, &e->index);
 
 
         pa_idxset_put(c->scache, e, &e->index);
 
@@ -123,23 +125,43 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
     }
 
     e->last_used_time = 0;
     }
 
     e->last_used_time = 0;
-    e->memchunk.memblock = NULL;
-    e->memchunk.index = e->memchunk.length = 0;
+    pa_memchunk_reset(&e->memchunk);
     e->filename = NULL;
     e->filename = NULL;
-    e->lazy = 0;
+    e->lazy = FALSE;
     e->last_used_time = 0;
 
     e->last_used_time = 0;
 
-    memset(&e->sample_spec, 0, sizeof(e->sample_spec));
+    pa_sample_spec_init(&e->sample_spec);
     pa_channel_map_init(&e->channel_map);
     pa_channel_map_init(&e->channel_map);
-    pa_cvolume_reset(&e->volume, PA_CHANNELS_MAX);
+    pa_cvolume_init(&e->volume);
+    e->volume_is_set = FALSE;
+
+    pa_proplist_sets(e->proplist, PA_PROP_MEDIA_ROLE, "event");
 
     return e;
 }
 
 
     return e;
 }
 
-int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map, const pa_memchunk *chunk, uint32_t *idx) {
+int pa_scache_add_item(
+        pa_core *c,
+        const char *name,
+        const pa_sample_spec *ss,
+        const pa_channel_map *map,
+        const pa_memchunk *chunk,
+        pa_proplist *p,
+        uint32_t *idx) {
+
     pa_scache_entry *e;
     char st[PA_SAMPLE_SPEC_SNPRINT_MAX];
     pa_scache_entry *e;
     char st[PA_SAMPLE_SPEC_SNPRINT_MAX];
-    assert(c && name);
+    pa_channel_map tmap;
+
+    pa_assert(c);
+    pa_assert(name);
+    pa_assert(!ss || pa_sample_spec_valid(ss));
+    pa_assert(!map || (pa_channel_map_valid(map) && ss && pa_channel_map_compatible(map, ss)));
+
+    if (ss && !map) {
+        pa_channel_map_init_extend(&tmap, ss->channels, PA_CHANNEL_MAP_DEFAULT);
+        map = &tmap;
+    }
 
     if (chunk && chunk->length > PA_SCACHE_ENTRY_SIZE_MAX)
         return -1;
 
     if (chunk && chunk->length > PA_SCACHE_ENTRY_SIZE_MAX)
         return -1;
@@ -147,10 +169,14 @@ int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, c
     if (!(e = scache_add_item(c, name)))
         return -1;
 
     if (!(e = scache_add_item(c, name)))
         return -1;
 
+    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;
-        pa_channel_map_init_auto(&e->channel_map, ss->channels, PA_CHANNEL_MAP_DEFAULT);
-        e->volume.channels = e->sample_spec.channels;
+        pa_cvolume_reset(&e->volume, ss->channels);
     }
 
     if (map)
     }
 
     if (map)
@@ -161,12 +187,15 @@ int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, c
         pa_memblock_ref(e->memchunk.memblock);
     }
 
         pa_memblock_ref(e->memchunk.memblock);
     }
 
+    if (p)
+        pa_proplist_update(e->proplist, PA_UPDATE_REPLACE, p);
+
     if (idx)
         *idx = e->index;
 
     if (idx)
         *idx = e->index;
 
-    pa_log_debug("created sample \"%s\" (#%d), %d bytes with sample spec %s",
-        name, e->index, e->memchunk.length,
-        pa_sample_spec_snprint(st, sizeof(st), &e->sample_spec));
+    pa_log_debug("Created sample \"%s\" (#%d), %lu bytes with sample spec %s",
+                 name, e->index, (unsigned long) e->memchunk.length,
+                 pa_sample_spec_snprint(st, sizeof(st), &e->sample_spec));
 
     return 0;
 }
 
     return 0;
 }
@@ -176,6 +205,7 @@ int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint3
     pa_channel_map map;
     pa_memchunk chunk;
     int r;
     pa_channel_map map;
     pa_memchunk chunk;
     int r;
+    pa_proplist *p;
 
 #ifdef OS_IS_WIN32
     char buf[MAX_PATH];
 
 #ifdef OS_IS_WIN32
     char buf[MAX_PATH];
@@ -184,11 +214,21 @@ int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint3
         filename = buf;
 #endif
 
         filename = buf;
 #endif
 
-    if (pa_sound_file_load(c->mempool, filename, &ss, &map, &chunk) < 0)
+    pa_assert(c);
+    pa_assert(name);
+    pa_assert(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;
         return -1;
+    }
 
 
-    r = pa_scache_add_item(c, name, &ss, &map, &chunk, idx);
+    r = pa_scache_add_item(c, name, &ss, &map, &chunk, p, idx);
     pa_memblock_unref(chunk.memblock);
     pa_memblock_unref(chunk.memblock);
+    pa_proplist_free(p);
 
     return r;
 }
 
     return r;
 }
@@ -203,20 +243,20 @@ int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename,
         filename = buf;
 #endif
 
         filename = buf;
 #endif
 
-    assert(c && name);
+    pa_assert(c);
+    pa_assert(name);
+    pa_assert(filename);
 
     if (!(e = scache_add_item(c, name)))
         return -1;
 
 
     if (!(e = scache_add_item(c, name)))
         return -1;
 
-    e->lazy = 1;
+    e->lazy = TRUE;
     e->filename = pa_xstrdup(filename);
 
     e->filename = pa_xstrdup(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);
-    }
+    pa_proplist_sets(e->proplist, PA_PROP_MEDIA_FILENAME, filename);
+
+    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;
@@ -226,87 +266,128 @@ int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename,
 
 int pa_scache_remove_item(pa_core *c, const char *name) {
     pa_scache_entry *e;
 
 int pa_scache_remove_item(pa_core *c, const char *name) {
     pa_scache_entry *e;
-    assert(c && name);
 
 
-    if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0)))
+    pa_assert(c);
+    pa_assert(name);
+
+    if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE)))
         return -1;
 
         return -1;
 
-    if (pa_idxset_remove_by_data(c->scache, e, NULL) != e)
-        assert(0);
+    pa_assert_se(pa_idxset_remove_by_data(c->scache, e, NULL) == e);
 
 
-    pa_log_debug("removed sample \"%s\"", name);
+    pa_log_debug("Removed sample \"%s\"", name);
 
     free_entry(e);
 
     return 0;
 }
 
 
     free_entry(e);
 
     return 0;
 }
 
-static void free_cb(void *p, PA_GCC_UNUSED void *userdata) {
-    pa_scache_entry *e = p;
-    assert(e);
-    free_entry(e);
-}
+void pa_scache_free_all(pa_core *c) {
+    pa_scache_entry *e;
 
 
-void pa_scache_free(pa_core *c) {
-    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) {
+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_scache_entry *e;
-    char *t;
     pa_cvolume r;
     pa_cvolume r;
+    pa_proplist *merged;
+    pa_bool_t pass_volume;
 
 
-    assert(c);
-    assert(name);
-    assert(sink);
+    pa_assert(c);
+    pa_assert(name);
+    pa_assert(sink);
 
 
-    if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1)))
+    if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE)))
         return -1;
 
         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) {
     if (e->lazy && !e->memchunk.memblock) {
-        if (pa_sound_file_load(c->mempool, e->filename, &e->sample_spec, &e->channel_map, &e->memchunk) < 0)
-            return -1;
+        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, 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 (e->volume.channels > e->sample_spec.channels)
-            e->volume.channels = 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);
 
 
-    t = pa_sprintf_malloc("sample:%s", name);
+    pass_volume = TRUE;
 
 
-    pa_cvolume_set(&r, e->volume.channels, volume);
-    pa_sw_cvolume_multiply(&r, &r, &e->volume);
+    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;
 
 
-    if (pa_play_memchunk(sink, t, &e->sample_spec, &e->channel_map, &e->memchunk, &r) < 0) {
-        pa_xfree(t);
-        return -1;
-    }
+    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,
+                         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_xfree(t);
+    pa_proplist_free(merged);
 
     if (e->lazy)
         time(&e->last_used_time);
 
     return 0;
 
     if (e->lazy)
         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) {
+    pa_sink *sink;
+
+    pa_assert(c);
+    pa_assert(name);
+
+    if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK)))
+        return -1;
+
+    return pa_scache_play_item(c, name, sink, volume, p, sink_input_idx);
 }
 
 }
 
-const char * pa_scache_get_name_by_id(pa_core *c, uint32_t id) {
+const char *pa_scache_get_name_by_id(pa_core *c, uint32_t id) {
     pa_scache_entry *e;
     pa_scache_entry *e;
-    assert(c && id != PA_IDXSET_INVALID);
+
+    pa_assert(c);
+    pa_assert(id != PA_IDXSET_INVALID);
 
     if (!c->scache || !(e = pa_idxset_get_by_index(c->scache, id)))
         return NULL;
 
     if (!c->scache || !(e = pa_idxset_get_by_index(c->scache, id)))
         return NULL;
@@ -316,18 +397,22 @@ const char * pa_scache_get_name_by_id(pa_core *c, uint32_t id) {
 
 uint32_t pa_scache_get_id_by_name(pa_core *c, const char *name) {
     pa_scache_entry *e;
 
 uint32_t pa_scache_get_id_by_name(pa_core *c, const char *name) {
     pa_scache_entry *e;
-    assert(c && name);
 
 
-    if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0)))
+    pa_assert(c);
+    pa_assert(name);
+
+    if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE)))
         return PA_IDXSET_INVALID;
 
     return e->index;
 }
 
         return PA_IDXSET_INVALID;
 
     return e->index;
 }
 
-uint32_t pa_scache_total_size(pa_core *c) {
+size_t pa_scache_total_size(pa_core *c) {
     pa_scache_entry *e;
     pa_scache_entry *e;
-    uint32_t idx, sum = 0;
-    assert(c);
+    uint32_t idx;
+    size_t sum = 0;
+
+    pa_assert(c);
 
     if (!c->scache || !pa_idxset_size(c->scache))
         return 0;
 
     if (!c->scache || !pa_idxset_size(c->scache))
         return 0;
@@ -343,7 +428,8 @@ void pa_scache_unload_unused(pa_core *c) {
     pa_scache_entry *e;
     time_t now;
     uint32_t idx;
     pa_scache_entry *e;
     time_t now;
     uint32_t idx;
-    assert(c);
+
+    pa_assert(c);
 
     if (!c->scache || !pa_idxset_size(c->scache))
         return;
 
     if (!c->scache || !pa_idxset_size(c->scache))
         return;
@@ -359,8 +445,7 @@ void pa_scache_unload_unused(pa_core *c) {
             continue;
 
         pa_memblock_unref(e->memchunk.memblock);
             continue;
 
         pa_memblock_unref(e->memchunk.memblock);
-        e->memchunk.memblock = NULL;
-        e->memchunk.index = e->memchunk.length = 0;
+        pa_memchunk_reset(&e->memchunk);
 
         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);
     }
@@ -370,6 +455,9 @@ static void add_file(pa_core *c, const char *pathname) {
     struct stat st;
     const char *e;
 
     struct stat st;
     const char *e;
 
+    pa_core_assert_ref(c);
+    pa_assert(pathname);
+
     e = pa_path_get_filename(pathname);
 
     if (stat(pathname, &st) < 0) {
     e = pa_path_get_filename(pathname);
 
     if (stat(pathname, &st) < 0) {
@@ -385,7 +473,9 @@ static void add_file(pa_core *c, const char *pathname) {
 
 int pa_scache_add_directory_lazy(pa_core *c, const char *pathname) {
     DIR *dir;
 
 int pa_scache_add_directory_lazy(pa_core *c, const char *pathname) {
     DIR *dir;
-    assert(c && pathname);
+
+    pa_core_assert_ref(c);
+    pa_assert(pathname);
 
     /* First try to open this as directory */
     if (!(dir = opendir(pathname))) {
 
     /* First try to open this as directory */
     if (!(dir = opendir(pathname))) {
@@ -410,16 +500,18 @@ 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;
 
-            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);
     return 0;
 }
     return 0;
 }