]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/sound-file.c
Revert "core: Transparently handle non-blocking sockets on Windows"
[pulseaudio] / src / pulsecore / sound-file.c
index 284bbdda0629f8e656924ea909e039ceb62f0150..3db0981fa07bfbd00bcc18be80439d7b7ae069a7 100644 (file)
@@ -1,11 +1,11 @@
-/* $Id$ */
-
 /***
   This file is part of PulseAudio.
 
 /***
   This file is part of PulseAudio.
 
+  Copyright 2004-2006 Lennart Poettering
+
   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
 #include <config.h>
 #endif
 
 #include <config.h>
 #endif
 
-#include <string.h>
-#include <assert.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
 
 #include <sndfile.h>
 
 #include <pulse/sample.h>
 #include <pulsecore/log.h>
 
 #include <sndfile.h>
 
 #include <pulse/sample.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/core-error.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/core-scache.h>
+#include <pulsecore/sndfile-util.h>
 
 #include "sound-file.h"
 
 #include "sound-file.h"
-#include "core-scache.h"
 
 
-int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, pa_channel_map *map, pa_memchunk *chunk) {
-    SNDFILE*sf = NULL;
-    SF_INFO sfinfo;
+int pa_sound_file_load(
+        pa_mempool *pool,
+        const char *fname,
+        pa_sample_spec *ss,
+        pa_channel_map *map,
+        pa_memchunk *chunk,
+        pa_proplist *p) {
+
+    SNDFILE *sf = NULL;
+    SF_INFO sfi;
     int ret = -1;
     size_t l;
     sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames) = NULL;
     int ret = -1;
     size_t l;
     sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames) = NULL;
-    assert(fname && ss && chunk);
+    void *ptr = NULL;
+    int fd;
 
 
-    chunk->memblock = NULL;
-    chunk->index = chunk->length = 0;
+    pa_assert(fname);
+    pa_assert(ss);
+    pa_assert(chunk);
 
 
-    memset(&sfinfo, 0, sizeof(sfinfo));
+    pa_memchunk_reset(chunk);
 
 
-    if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) {
-        pa_log("Failed to open file %s", fname);
+    if ((fd = pa_open_cloexec(fname, O_RDONLY, 0)) < 0) {
+        pa_log("Failed to open file %s: %s", fname, pa_cstrerror(errno));
         goto finish;
     }
 
         goto finish;
     }
 
-    switch (sfinfo.format & SF_FORMAT_SUBMASK) {
-        case SF_FORMAT_PCM_16:
-        case SF_FORMAT_PCM_U8:
-        case SF_FORMAT_PCM_S8:
-            ss->format = PA_SAMPLE_S16NE;
-            readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_short;
-            break;
-
-        case SF_FORMAT_ULAW:
-            ss->format = PA_SAMPLE_ULAW;
-            break;
-
-        case SF_FORMAT_ALAW:
-            ss->format = PA_SAMPLE_ALAW;
-            break;
-
-        case SF_FORMAT_FLOAT:
-        case SF_FORMAT_DOUBLE:
-        default:
-            ss->format = PA_SAMPLE_FLOAT32NE;
-            readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_float;
-            break;
+#ifdef HAVE_POSIX_FADVISE
+    if (posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL) < 0) {
+        pa_log_warn("POSIX_FADV_SEQUENTIAL failed: %s", pa_cstrerror(errno));
+        goto finish;
+    } else
+        pa_log_debug("POSIX_FADV_SEQUENTIAL succeeded.");
+#endif
+
+    pa_zero(sfi);
+    if (!(sf = sf_open_fd(fd, SFM_READ, &sfi, 1))) {
+        pa_log("Failed to open file %s", fname);
+        goto finish;
     }
 
     }
 
-    ss->rate = sfinfo.samplerate;
-    ss->channels = sfinfo.channels;
+    fd = -1;
 
 
-    if (!pa_sample_spec_valid(ss)) {
-        pa_log("Unsupported sample format in file %s", fname);
+    if (pa_sndfile_read_sample_spec(sf, ss) < 0) {
+        pa_log("Failed to determine file sample format.");
         goto finish;
     }
 
         goto finish;
     }
 
-    if (map)
-        pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_DEFAULT);
+    if ((map && pa_sndfile_read_channel_map(sf, map) < 0)) {
+        if (ss->channels > 2)
+            pa_log("Failed to determine file channel map, synthesizing one.");
+        pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_DEFAULT);
+    }
+
+    if (p)
+        pa_sndfile_init_proplist(sf, p);
 
 
-    if ((l = pa_frame_size(ss)*sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
+    if ((l = pa_frame_size(ss) * (size_t) sfi.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
         pa_log("File too large");
         goto finish;
     }
 
     chunk->memblock = pa_memblock_new(pool, l);
         pa_log("File too large");
         goto finish;
     }
 
     chunk->memblock = pa_memblock_new(pool, l);
-    assert(chunk->memblock);
     chunk->index = 0;
     chunk->length = l;
 
     chunk->index = 0;
     chunk->length = l;
 
-    if ((readf_function && readf_function(sf, chunk->memblock->data, sfinfo.frames) != sfinfo.frames) ||
-        (!readf_function && sf_read_raw(sf, chunk->memblock->data, l) != l)) {
+    readf_function = pa_sndfile_readf_function(ss);
+
+    ptr = pa_memblock_acquire(chunk->memblock);
+
+    if ((readf_function && readf_function(sf, ptr, sfi.frames) != sfi.frames) ||
+        (!readf_function && sf_read_raw(sf, ptr, (sf_count_t) l) != (sf_count_t) l)) {
         pa_log("Premature file end");
         goto finish;
     }
         pa_log("Premature file end");
         goto finish;
     }
@@ -110,52 +122,42 @@ finish:
     if (sf)
         sf_close(sf);
 
     if (sf)
         sf_close(sf);
 
+    if (ptr)
+        pa_memblock_release(chunk->memblock);
+
     if (ret != 0 && chunk->memblock)
         pa_memblock_unref(chunk->memblock);
 
     if (ret != 0 && chunk->memblock)
         pa_memblock_unref(chunk->memblock);
 
-    return ret;
+    if (fd >= 0)
+        pa_close(fd);
 
 
+    return ret;
 }
 
 int pa_sound_file_too_big_to_cache(const char *fname) {
 }
 
 int pa_sound_file_too_big_to_cache(const char *fname) {
+
     SNDFILE*sf = NULL;
     SNDFILE*sf = NULL;
-    SF_INFO sfinfo;
+    SF_INFO sfi;
     pa_sample_spec ss;
 
     pa_sample_spec ss;
 
-    if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) {
+    pa_assert(fname);
+
+    pa_zero(sfi);
+    if (!(sf = sf_open(fname, SFM_READ, &sfi))) {
         pa_log("Failed to open file %s", fname);
         pa_log("Failed to open file %s", fname);
-        return 0;
+        return -1;
     }
 
     }
 
-    sf_close(sf);
-
-    switch (sfinfo.format & SF_FORMAT_SUBMASK) {
-        case SF_FORMAT_PCM_16:
-        case SF_FORMAT_PCM_U8:
-        case SF_FORMAT_PCM_S8:
-            ss.format = PA_SAMPLE_S16NE;
-            break;
-
-        case SF_FORMAT_ULAW:
-            ss.format = PA_SAMPLE_ULAW;
-            break;
-
-        case SF_FORMAT_ALAW:
-            ss.format = PA_SAMPLE_ALAW;
-            break;
-
-        case SF_FORMAT_DOUBLE:
-        case SF_FORMAT_FLOAT:
-        default:
-            ss.format = PA_SAMPLE_FLOAT32NE;
-            break;
+    if (pa_sndfile_read_sample_spec(sf, &ss) < 0) {
+        pa_log("Failed to determine file sample format.");
+        sf_close(sf);
+        return -1;
     }
 
     }
 
-    ss.rate = sfinfo.samplerate;
-    ss.channels = sfinfo.channels;
+    sf_close(sf);
 
 
-    if ((pa_frame_size(&ss) * sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
-        pa_log("File too large %s", fname);
+    if ((pa_frame_size(&ss) * (size_t) sfi.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
+        pa_log("File too large: %s", fname);
         return 1;
     }
 
         return 1;
     }