]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/sound-file-stream.c
pdispatch: add missing commands to command table
[pulseaudio] / src / pulsecore / sound-file-stream.c
index e209676f63ab5bb8e1a528a37d4e27dbb6bf2788..f41c53f3c8f86f7bc463ae24ba3874af034f674d 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id$ */
-
 /***
   This file is part of PulseAudio.
 
 /***
   This file is part of PulseAudio.
 
@@ -7,7 +5,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
@@ -35,6 +33,7 @@
 #include <sndfile.h>
 
 #include <pulse/xmalloc.h>
 #include <sndfile.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/util.h>
 
 #include <pulsecore/core-error.h>
 #include <pulsecore/sink-input.h>
 
 #include <pulsecore/core-error.h>
 #include <pulsecore/sink-input.h>
@@ -42,6 +41,7 @@
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/sample-util.h>
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/sample-util.h>
+#include <pulsecore/sndfile-util.h>
 
 #include "sound-file-stream.h"
 
 
 #include "sound-file-stream.h"
 
@@ -64,9 +64,8 @@ enum {
     FILE_STREAM_MESSAGE_UNLINK
 };
 
     FILE_STREAM_MESSAGE_UNLINK
 };
 
-PA_DECLARE_CLASS(file_stream);
+PA_DEFINE_PRIVATE_CLASS(file_stream, pa_msgobject);
 #define FILE_STREAM(o) (file_stream_cast(o))
 #define FILE_STREAM(o) (file_stream_cast(o))
-static PA_DEFINE_CHECK_TYPE(file_stream, pa_msgobject);
 
 /* Called from main context */
 static void file_stream_unlink(file_stream *u) {
 
 /* Called from main context */
 static void file_stream_unlink(file_stream *u) {
@@ -134,7 +133,7 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s
      * we are heard right-away. */
     if (PA_SINK_INPUT_IS_LINKED(state) &&
         i->thread_info.state == PA_SINK_INPUT_INIT)
      * we are heard right-away. */
     if (PA_SINK_INPUT_IS_LINKED(state) &&
         i->thread_info.state == PA_SINK_INPUT_INIT)
-        pa_sink_input_request_rewind(i, 0, FALSE, TRUE);
+        pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
 }
 
 /* Called from IO thread context */
 }
 
 /* Called from IO thread context */
@@ -149,8 +148,6 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
     if (!u->memblockq)
         return -1;
 
     if (!u->memblockq)
         return -1;
 
-    pa_log_debug("pop: %lu", (unsigned long) length);
-
     for (;;) {
         pa_memchunk tchunk;
         size_t fs;
     for (;;) {
         pa_memchunk tchunk;
         size_t fs;
@@ -158,6 +155,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
         sf_count_t n;
 
         if (pa_memblockq_peek(u->memblockq, chunk) >= 0) {
         sf_count_t n;
 
         if (pa_memblockq_peek(u->memblockq, chunk) >= 0) {
+            chunk->length = PA_MIN(chunk->length, length);
             pa_memblockq_drop(u->memblockq, chunk->length);
             return 0;
         }
             pa_memblockq_drop(u->memblockq, chunk->length);
             return 0;
         }
@@ -172,10 +170,10 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
 
         if (u->readf_function) {
             fs = pa_frame_size(&i->sample_spec);
 
         if (u->readf_function) {
             fs = pa_frame_size(&i->sample_spec);
-            n = u->readf_function(u->sndfile, p, length/fs);
+            n = u->readf_function(u->sndfile, p, (sf_count_t) (length/fs));
         } else {
             fs = 1;
         } else {
             fs = 1;
-            n = sf_read_raw(u->sndfile, p, length);
+            n = sf_read_raw(u->sndfile, p, (sf_count_t) length);
         }
 
         pa_memblock_release(tchunk.memblock);
         }
 
         pa_memblock_release(tchunk.memblock);
@@ -188,17 +186,13 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
             break;
         }
 
             break;
         }
 
-        tchunk.length = n * fs;
+        tchunk.length = (size_t) n * fs;
 
         pa_memblockq_push(u->memblockq, &tchunk);
         pa_memblock_unref(tchunk.memblock);
     }
 
 
         pa_memblockq_push(u->memblockq, &tchunk);
         pa_memblock_unref(tchunk.memblock);
     }
 
-    pa_log_debug("peek fail");
-
     if (pa_sink_input_safe_to_remove(i)) {
     if (pa_sink_input_safe_to_remove(i)) {
-        pa_log_debug("completed to play");
-
         pa_memblockq_free(u->memblockq);
         u->memblockq = NULL;
 
         pa_memblockq_free(u->memblockq);
         u->memblockq = NULL;
 
@@ -212,7 +206,6 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
     file_stream *u;
 
     pa_sink_input_assert_ref(i);
     file_stream *u;
 
     pa_sink_input_assert_ref(i);
-    pa_assert(nbytes > 0);
     u = FILE_STREAM(i->userdata);
     file_stream_assert_ref(u);
 
     u = FILE_STREAM(i->userdata);
     file_stream_assert_ref(u);
 
@@ -241,10 +234,11 @@ int pa_play_file(
         const pa_cvolume *volume) {
 
     file_stream *u = NULL;
         const pa_cvolume *volume) {
 
     file_stream *u = NULL;
-    SF_INFO sfinfo;
     pa_sample_spec ss;
     pa_sample_spec ss;
+    pa_channel_map cm;
     pa_sink_input_new_data data;
     int fd;
     pa_sink_input_new_data data;
     int fd;
+    SF_INFO sfi;
 
     pa_assert(sink);
     pa_assert(fname);
 
     pa_assert(sink);
     pa_assert(fname);
@@ -258,8 +252,6 @@ int pa_play_file(
     u->readf_function = NULL;
     u->memblockq = NULL;
 
     u->readf_function = NULL;
     u->memblockq = NULL;
 
-    memset(&sfinfo, 0, sizeof(sfinfo));
-
     if ((fd = open(fname, O_RDONLY
 #ifdef O_NOCTTY
                    |O_NOCTTY
     if ((fd = open(fname, O_RDONLY
 #ifdef O_NOCTTY
                    |O_NOCTTY
@@ -288,52 +280,38 @@ int pa_play_file(
         pa_log_debug("POSIX_FADV_WILLNEED succeeded.");
 #endif
 
         pa_log_debug("POSIX_FADV_WILLNEED succeeded.");
 #endif
 
-    if (!(u->sndfile = sf_open_fd(fd, SFM_READ, &sfinfo, 1))) {
+    pa_zero(sfi);
+    if (!(u->sndfile = sf_open_fd(fd, SFM_READ, &sfi, 1))) {
         pa_log("Failed to open file %s", fname);
         pa_log("Failed to open file %s", fname);
-        pa_close(fd);
         goto fail;
     }
 
         goto fail;
     }
 
-    switch (sfinfo.format & 0xFF) {
-        case SF_FORMAT_PCM_16:
-        case SF_FORMAT_PCM_U8:
-        case SF_FORMAT_PCM_S8:
-            ss.format = PA_SAMPLE_S16NE;
-            u->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;
+    fd = -1;
 
 
-        case SF_FORMAT_FLOAT:
-        default:
-            ss.format = PA_SAMPLE_FLOAT32NE;
-            u->readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_float;
-            break;
+    if (pa_sndfile_read_sample_spec(u->sndfile, &ss) < 0) {
+        pa_log("Failed to determine file sample format.");
+        goto fail;
     }
 
     }
 
-    ss.rate = sfinfo.samplerate;
-    ss.channels = sfinfo.channels;
-
-    if (!pa_sample_spec_valid(&ss)) {
-        pa_log("Unsupported sample format in file %s", fname);
-        goto fail;
+    if (pa_sndfile_read_channel_map(u->sndfile, &cm) < 0) {
+        if (ss.channels > 2)
+            pa_log_info("Failed to determine file channel map, synthesizing one.");
+        pa_channel_map_init_extend(&cm, ss.channels, PA_CHANNEL_MAP_DEFAULT);
     }
 
     }
 
+    u->readf_function = pa_sndfile_readf_function(&ss);
+
     pa_sink_input_new_data_init(&data);
     data.sink = sink;
     data.driver = __FILE__;
     pa_sink_input_new_data_set_sample_spec(&data, &ss);
     pa_sink_input_new_data_init(&data);
     data.sink = sink;
     data.driver = __FILE__;
     pa_sink_input_new_data_set_sample_spec(&data, &ss);
+    pa_sink_input_new_data_set_channel_map(&data, &cm);
     pa_sink_input_new_data_set_volume(&data, volume);
     pa_sink_input_new_data_set_volume(&data, volume);
-    pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, fname);
+    pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, pa_path_get_filename(fname));
     pa_proplist_sets(data.proplist, PA_PROP_MEDIA_FILENAME, fname);
     pa_proplist_sets(data.proplist, PA_PROP_MEDIA_FILENAME, fname);
+    pa_sndfile_init_proplist(u->sndfile, data.proplist);
 
 
-    u->sink_input = pa_sink_input_new(sink->core, &data, 0);
+    pa_sink_input_new(&u->sink_input, sink->core, &data, 0);
     pa_sink_input_new_data_done(&data);
 
     if (!u->sink_input)
     pa_sink_input_new_data_done(&data);
 
     if (!u->sink_input)
@@ -359,5 +337,8 @@ fail:
     if (u)
         file_stream_unref(u);
 
     if (u)
         file_stream_unref(u);
 
+    if (fd >= 0)
+        pa_close(fd);
+
     return -1;
 }
     return -1;
 }