summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2006-01-27 16:25:31 +0000
committerLennart Poettering <lennart@poettering.net>2006-01-27 16:25:31 +0000
commitdd10c982414dfa8fbb9aeeeae61c68e4a6f081cc (patch)
tree8c05e4a7344570c2f4d40854baddeff7cc353709
parent759721cbbc265cc6ce4c5dd9141e00ca67c8fe2d (diff)
Mega patch:
* implement inner loops using liboil * drop "typeid" stuff * add support for channel maps * add support for seperate volumes per channel * add support for hardware mixer settings (only module-oss implements this for now) * fix a lot of types for _t suffix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@463 fefdeb5f-60dc-0310-8127-8f9354f1896f
-rw-r--r--configure.ac5
-rw-r--r--polyp/Makefile.am26
-rw-r--r--polyp/alsa-util.c2
-rw-r--r--polyp/alsa-util.h2
-rw-r--r--polyp/autoload.c8
-rw-r--r--polyp/autoload.h10
-rw-r--r--polyp/channelmap.c202
-rw-r--r--polyp/channelmap.h94
-rw-r--r--polyp/cli-command.c21
-rw-r--r--polyp/cli-text.c129
-rw-r--r--polyp/cli.c3
-rw-r--r--polyp/client.c6
-rw-r--r--polyp/client.h6
-rw-r--r--polyp/core.h2
-rw-r--r--polyp/daemon-conf.c2
-rw-r--r--polyp/daemon-conf.h8
-rw-r--r--polyp/dllmain.c2
-rw-r--r--polyp/glib-mainloop.c12
-rw-r--r--polyp/glib12-mainloop.c10
-rw-r--r--polyp/inet_ntop.c2
-rw-r--r--polyp/iochannel.c4
-rw-r--r--polyp/log.c26
-rw-r--r--polyp/log.h12
-rw-r--r--polyp/main.c3
-rw-r--r--polyp/mainloop-api.h6
-rw-r--r--polyp/mainloop-signal.c2
-rw-r--r--polyp/mainloop-test.c2
-rw-r--r--polyp/mainloop.c14
-rw-r--r--polyp/memblock.h6
-rw-r--r--polyp/module-alsa-sink.c8
-rw-r--r--polyp/module-alsa-source.c6
-rw-r--r--polyp/module-combine.c6
-rw-r--r--polyp/module-esound-sink.c6
-rw-r--r--polyp/module-lirc.c39
-rw-r--r--polyp/module-match.c6
-rw-r--r--polyp/module-mmkbd-evdev.c25
-rw-r--r--polyp/module-null-sink.c4
-rw-r--r--polyp/module-oss-mmap.c8
-rw-r--r--polyp/module-oss.c54
-rw-r--r--polyp/module-pipe-sink.c4
-rw-r--r--polyp/module-pipe-source.c4
-rw-r--r--polyp/module-protocol-stub.c2
-rw-r--r--polyp/module-sine.c4
-rw-r--r--polyp/module-solaris.c2
-rw-r--r--polyp/module-tunnel.c6
-rw-r--r--polyp/module-waveout.c2
-rw-r--r--polyp/module-x11-bell.c3
-rw-r--r--polyp/namereg.c8
-rw-r--r--polyp/namereg.h8
-rw-r--r--polyp/native-common.h5
-rw-r--r--polyp/pacat-simple.c2
-rw-r--r--polyp/pacat.c13
-rw-r--r--polyp/pactl.c77
-rw-r--r--polyp/paplay.c8
-rw-r--r--polyp/parec-simple.c2
-rw-r--r--polyp/parseaddr.h4
-rw-r--r--polyp/play-memchunk.c26
-rw-r--r--polyp/play-memchunk.h8
-rw-r--r--polyp/poll.c2
-rw-r--r--polyp/poll.h2
-rw-r--r--polyp/polyplib-context.c4
-rw-r--r--polyp/polyplib-context.h2
-rw-r--r--polyp/polyplib-def.h14
-rw-r--r--polyp/polyplib-internal.h15
-rw-r--r--polyp/polyplib-introspect.c28
-rw-r--r--polyp/polyplib-introspect.h46
-rw-r--r--polyp/polyplib-operation.c4
-rw-r--r--polyp/polyplib-operation.h2
-rw-r--r--polyp/polyplib-simple.c13
-rw-r--r--polyp/polyplib-simple.h3
-rw-r--r--polyp/polyplib-stream.c39
-rw-r--r--polyp/polyplib-stream.h19
-rw-r--r--polyp/polyplib-subscribe.c6
-rw-r--r--polyp/polyplib-subscribe.h4
-rw-r--r--polyp/protocol-esound.c40
-rw-r--r--polyp/protocol-native.c108
-rw-r--r--polyp/protocol-simple.c8
-rw-r--r--polyp/resampler.c546
-rw-r--r--polyp/resampler.h18
-rw-r--r--polyp/sample-util.c354
-rw-r--r--polyp/sample-util.h23
-rw-r--r--polyp/sample.c83
-rw-r--r--polyp/sample.h49
-rw-r--r--polyp/scache.c21
-rw-r--r--polyp/scache.h7
-rw-r--r--polyp/sconv-s16be.c8
-rw-r--r--polyp/sconv-s16be.h4
-rw-r--r--polyp/sconv-s16le.c64
-rw-r--r--polyp/sconv-s16le.h4
-rw-r--r--polyp/sconv.c155
-rw-r--r--polyp/sconv.h8
-rw-r--r--polyp/sink-input.c152
-rw-r--r--polyp/sink-input.h37
-rw-r--r--polyp/sink.c226
-rw-r--r--polyp/sink.h41
-rw-r--r--polyp/socket-client.c4
-rw-r--r--polyp/socket-server.c2
-rw-r--r--polyp/sound-file-stream.c11
-rw-r--r--polyp/sound-file-stream.h2
-rw-r--r--polyp/source-output.c74
-rw-r--r--polyp/source-output.h26
-rw-r--r--polyp/source.c65
-rw-r--r--polyp/source.h27
-rw-r--r--polyp/subscribe.c10
-rw-r--r--polyp/subscribe.h4
-rw-r--r--polyp/tagstruct.c91
-rw-r--r--polyp/tagstruct.h6
-rw-r--r--polyp/typeid.c33
-rw-r--r--polyp/typeid.h46
-rw-r--r--polyp/voltest.c17
-rw-r--r--polyp/volume.c176
-rw-r--r--polyp/volume.h107
-rw-r--r--polyp/x11prop.c2
-rw-r--r--polyp/x11wrap.c4
114 files changed, 2549 insertions, 1294 deletions
diff --git a/configure.ac b/configure.ac
index f2de16539..710f205b9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -330,6 +330,11 @@ AC_SUBST(HOWL_LIBS)
AC_SUBST(HAVE_HOWL)
AM_CONDITIONAL([HAVE_HOWL], [test "x$HAVE_HOWL" = x1])
+
+PKG_CHECK_MODULES(LIBOIL, [ liboil-0.3 >= 0.3.0 ])
+AC_SUBST(LIBOIL_CFLAGS)
+AC_SUBST(LIBOIL_LIBS)
+
#### Async DNS support (optional) ####
PKG_CHECK_MODULES(LIBASYNCNS, [ libasyncns >= 0.1 ], HAVE_LIBASYNCNS=1, HAVE_LIBASYNCNS=0)
diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index 0181ae6a9..ad9952a50 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -47,6 +47,7 @@ AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS
AM_CFLAGS += $(LTDLINCL)
AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS)
AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\"
+#AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\"
AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\"
AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(POLYPAUDIO_BINARY)\"
@@ -101,10 +102,10 @@ polypaudio_SOURCES = \
main.c \
pid.c pid.h
-polypaudio_CFLAGS = $(AM_CFLAGS)
-polypaudio_CPPFLAGS = $(AM_CPPFLAGS)
+polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
+polypaudio_CPPFLAGS = $(AM_CPPFLAGS)
polypaudio_LDADD = $(AM_LDADD) libpolypcore.la $(LIBLTDL) \
- $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS)
+ $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS)
polypaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force $(foreach f,$(PREOPEN_LIBS),-dlopen $(f))
if PREOPEN_MODS
@@ -219,7 +220,7 @@ strlist_test_CFLAGS = $(AM_CFLAGS)
strlist_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS)
strlist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
-voltest_SOURCES = voltest.c sample.c
+voltest_SOURCES = voltest.c sample.c volume.c volume.h sample.h
voltest_CFLAGS = $(AM_CFLAGS)
voltest_LDADD = $(AM_LDADD)
voltest_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
@@ -265,8 +266,7 @@ polypinclude_HEADERS = \
polyplib-stream.h \
polyplib-subscribe.h \
polyplib-version.h \
- sample.h \
- typeid.h
+ sample.h
if HAVE_HOWL
polypinclude_HEADERS += \
@@ -333,10 +333,11 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = \
strbuf.c strbuf.h \
strlist.c strlist.h \
tagstruct.c tagstruct.h \
- typeid.c typeid.h \
util.c util.h \
winsock.h \
- xmalloc.c xmalloc.h
+ xmalloc.c xmalloc.h \
+ channelmap.c channelmap.h \
+ volume.c volume.h
if HAVE_X11
libpolyp_@PA_MAJORMINOR@_la_SOURCES += \
@@ -475,14 +476,15 @@ libpolypcore_la_SOURCES = \
strbuf.c strbuf.h \
subscribe.c subscripe.h \
tokenizer.c tokenizer.h \
- typeid.c typeid.h \
util.c util.h \
winsock.h \
- xmalloc.c xmalloc.h
+ xmalloc.c xmalloc.h \
+ volume.c volume.h \
+ channelmap.c channelmap.h
-libpolypcore_la_CPPFLAGS = $(AM_CPPFLAGS)
+libpolypcore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS)
libpolypcore_la_LDFLAGS = -avoid-version
-libpolypcore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS)
+libpolypcore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS)
###################################
# Plug-in support libraries #
diff --git a/polyp/alsa-util.c b/polyp/alsa-util.c
index 73f3be7dd..cc65b8de8 100644
--- a/polyp/alsa-util.c
+++ b/polyp/alsa-util.c
@@ -85,7 +85,7 @@ finish:
* *io_events. Store the length of that array in *n_io_events. Use the
* specified callback function and userdata. The array has to be freed
* with pa_free_io_events(). */
-int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api* m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags events, void *userdata), void *userdata) {
+int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api* m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata), void *userdata) {
unsigned i;
struct pollfd *pfds, *ppfd;
pa_io_event **ios;
diff --git a/polyp/alsa-util.h b/polyp/alsa-util.h
index 787519f74..d180db3ec 100644
--- a/polyp/alsa-util.h
+++ b/polyp/alsa-util.h
@@ -29,7 +29,7 @@
int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size);
-int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api *m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags events, void *userdata), void *userdata);
+int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api *m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata), void *userdata);
void pa_free_io_events(pa_mainloop_api* m, pa_io_event **io_sources, unsigned n_io_sources);
#endif
diff --git a/polyp/autoload.c b/polyp/autoload.c
index 7e05c1689..ff2916cbf 100644
--- a/polyp/autoload.c
+++ b/polyp/autoload.c
@@ -81,7 +81,7 @@ static pa_autoload_entry* entry_new(pa_core *c, const char *name) {
return e;
}
-int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type type, const char*module, const char *argument, uint32_t *idx) {
+int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type_t type, const char*module, const char *argument, uint32_t *idx) {
pa_autoload_entry *e = NULL;
assert(c && name && module && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE));
@@ -98,7 +98,7 @@ int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type type, const cha
return 0;
}
-int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type type) {
+int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type_t type) {
pa_autoload_entry *e;
assert(c && name && type);
@@ -120,7 +120,7 @@ int pa_autoload_remove_by_index(pa_core *c, uint32_t idx) {
return 0;
}
-void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type type) {
+void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type_t type) {
pa_autoload_entry *e;
pa_module *m;
assert(c && name);
@@ -159,7 +159,7 @@ void pa_autoload_free(pa_core *c) {
}
}
-const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type type) {
+const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type_t type) {
pa_autoload_entry *e;
assert(c && name);
diff --git a/polyp/autoload.h b/polyp/autoload.h
index 622a854e5..7350c16a9 100644
--- a/polyp/autoload.h
+++ b/polyp/autoload.h
@@ -34,7 +34,7 @@ typedef struct pa_autoload_entry {
pa_core *core;
uint32_t index;
char *name;
- pa_namereg_type type; /* Type of the autoload entry */
+ pa_namereg_type_t type; /* Type of the autoload entry */
int in_action; /* Currently loaded */
char *module, *argument;
} pa_autoload_entry;
@@ -42,17 +42,17 @@ typedef struct pa_autoload_entry {
/* Add a new autoload entry of the given time, with the speicified
* sink/source name, module name and argument. Return the entry's
* index in *index */
-int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type type, const char*module, const char *argument, uint32_t *idx);
+int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type_t type, const char*module, const char *argument, uint32_t *idx);
/* Free all autoload entries */
void pa_autoload_free(pa_core *c);
-int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type type);
+int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type_t type);
int pa_autoload_remove_by_index(pa_core *c, uint32_t idx);
/* Request an autoload entry by its name, effectively causing a module to be loaded */
-void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type type);
+void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type_t type);
-const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type type);
+const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type_t type);
const pa_autoload_entry* pa_autoload_get_by_index(pa_core *c, uint32_t idx);
#endif
diff --git a/polyp/channelmap.c b/polyp/channelmap.c
new file mode 100644
index 000000000..7bfd21e6e
--- /dev/null
+++ b/polyp/channelmap.c
@@ -0,0 +1,202 @@
+/* $Id$ */
+
+/***
+ This file is part of polypaudio.
+
+ polypaudio 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,
+ or (at your option) any later version.
+
+ polypaudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with polypaudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "channelmap.h"
+
+pa_channel_map* pa_channel_map_init(pa_channel_map *m) {
+ unsigned c;
+ assert(m);
+
+ m->channels = 0;
+
+ for (c = 0; c < PA_CHANNELS_MAX; c++)
+ m->map[c] = PA_CHANNEL_POSITION_INVALID;
+
+ return m;
+}
+
+pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m) {
+ assert(m);
+
+ pa_channel_map_init(m);
+
+ m->channels = 1;
+ m->map[0] = PA_CHANNEL_POSITION_MONO;
+ return m;
+}
+
+pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m) {
+ assert(m);
+
+ pa_channel_map_init(m);
+
+ m->channels = 2;
+ m->map[0] = PA_CHANNEL_POSITION_LEFT;
+ m->map[1] = PA_CHANNEL_POSITION_RIGHT;
+ return m;
+}
+
+pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels) {
+ assert(m);
+ assert(channels > 0);
+ assert(channels <= PA_CHANNELS_MAX);
+
+ pa_channel_map_init(m);
+
+ m->channels = channels;
+
+ switch (channels) {
+ case 1:
+ m->map[0] = PA_CHANNEL_POSITION_MONO;
+ return m;
+
+ case 8:
+ m->map[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
+ m->map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
+ /* Fall through */
+
+ case 6:
+ m->map[5] = PA_CHANNEL_POSITION_LFE;
+ /* Fall through */
+
+ case 5:
+ m->map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
+ /* Fall through */
+
+ case 4:
+ m->map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
+ m->map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
+ /* Fall through */
+
+ case 2:
+ m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
+ m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
+ return m;
+
+ default:
+ return NULL;
+ }
+}
+
+const char* pa_channel_position_to_string(pa_channel_position_t pos) {
+
+ const char *const table[] = {
+ [PA_CHANNEL_POSITION_MONO] = "mono",
+
+ [PA_CHANNEL_POSITION_FRONT_CENTER] = "front-center",
+ [PA_CHANNEL_POSITION_FRONT_LEFT] = "front-left",
+ [PA_CHANNEL_POSITION_FRONT_RIGHT] = "front-right",
+
+ [PA_CHANNEL_POSITION_REAR_CENTER] = "rear-center",
+ [PA_CHANNEL_POSITION_REAR_LEFT] = "rear-left",
+ [PA_CHANNEL_POSITION_REAR_RIGHT] = "rear-right",
+
+ [PA_CHANNEL_POSITION_LFE] = "lfe",
+
+ [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = "front-left-of-center",
+ [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = "front-right-of-center",
+
+ [PA_CHANNEL_POSITION_SIDE_LEFT] = "side-left",
+ [PA_CHANNEL_POSITION_SIDE_RIGHT] = "side-right",
+
+ [PA_CHANNEL_POSITION_AUX1] = "aux1",
+ [PA_CHANNEL_POSITION_AUX2] = "aux2",
+ [PA_CHANNEL_POSITION_AUX3] = "aux3",
+ [PA_CHANNEL_POSITION_AUX4] = "aux4",
+ [PA_CHANNEL_POSITION_AUX5] = "aux5",
+ [PA_CHANNEL_POSITION_AUX6] = "aux6",
+ [PA_CHANNEL_POSITION_AUX7] = "aux7",
+ [PA_CHANNEL_POSITION_AUX8] = "aux8",
+ [PA_CHANNEL_POSITION_AUX9] = "aux9",
+ [PA_CHANNEL_POSITION_AUX10] = "aux10",
+ [PA_CHANNEL_POSITION_AUX11] = "aux11",
+ [PA_CHANNEL_POSITION_AUX12] = "aux12"
+ };
+
+ if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX)
+ return NULL;
+
+ return table[pos];
+}
+
+int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) {
+ unsigned c;
+
+ assert(a);
+ assert(b);
+
+ if (a->channels != b->channels)
+ return 0;
+
+ for (c = 0; c < a->channels; c++)
+ if (a->map[c] != b->map[c])
+ return 0;
+
+ return 1;
+}
+
+char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) {
+ unsigned channel;
+ int first = 1;
+ char *e;
+
+ assert(s);
+ assert(l > 0);
+ assert(map);
+
+ *(e = s) = 0;
+
+ for (channel = 0; channel < map->channels && l > 1; channel++) {
+ l -= snprintf(e, l, "%s%u:%s",
+ first ? "" : " ",
+ channel,
+ pa_channel_position_to_string(map->map[channel]));
+
+ e = strchr(e, 0);
+ first = 0;
+ }
+
+ return s;
+}
+
+int pa_channel_map_valid(const pa_channel_map *map) {
+ unsigned c;
+
+ assert(map);
+
+ if (map->channels <= 0 || map->channels > PA_CHANNELS_MAX)
+ return 0;
+
+ for (c = 0; c < map->channels; c++)
+ if (map->map[c] < 0 ||map->map[c] >= PA_CHANNEL_POSITION_MAX)
+ return 0;
+
+ return 1;
+}
diff --git a/polyp/channelmap.h b/polyp/channelmap.h
new file mode 100644
index 000000000..6466eecfd
--- /dev/null
+++ b/polyp/channelmap.h
@@ -0,0 +1,94 @@
+#ifndef foochannelmaphfoo
+#define foochannelmaphfoo
+
+/* $Id$ */
+
+/***
+ This file is part of polypaudio.
+
+ polypaudio 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,
+ or (at your option) any later version.
+
+ polypaudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with polypaudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include <polyp/sample.h>
+#include <polyp/cdecl.h>
+
+/** \file
+ * Constants and routines for channel mapping handling */
+
+PA_C_DECL_BEGIN
+
+typedef enum {
+ PA_CHANNEL_POSITION_INVALID = -1,
+ PA_CHANNEL_POSITION_MONO = 0,
+
+ PA_CHANNEL_POSITION_LEFT,
+ PA_CHANNEL_POSITION_RIGHT,
+
+ PA_CHANNEL_POSITION_FRONT_CENTER,
+ PA_CHANNEL_POSITION_FRONT_LEFT = PA_CHANNEL_POSITION_LEFT,
+ PA_CHANNEL_POSITION_FRONT_RIGHT = PA_CHANNEL_POSITION_RIGHT,
+
+ PA_CHANNEL_POSITION_REAR_CENTER,
+ PA_CHANNEL_POSITION_REAR_LEFT,
+ PA_CHANNEL_POSITION_REAR_RIGHT,
+
+ PA_CHANNEL_POSITION_LFE,
+ PA_CHANNEL_POSITION_SUBWOOFER = PA_CHANNEL_POSITION_LFE,
+
+ PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
+ PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
+
+ PA_CHANNEL_POSITION_SIDE_LEFT,
+ PA_CHANNEL_POSITION_SIDE_RIGHT,
+
+ PA_CHANNEL_POSITION_AUX1,
+ PA_CHANNEL_POSITION_AUX2,
+ PA_CHANNEL_POSITION_AUX3,
+ PA_CHANNEL_POSITION_AUX4,
+ PA_CHANNEL_POSITION_AUX5,
+ PA_CHANNEL_POSITION_AUX6,
+ PA_CHANNEL_POSITION_AUX7,
+ PA_CHANNEL_POSITION_AUX8,
+ PA_CHANNEL_POSITION_AUX9,
+ PA_CHANNEL_POSITION_AUX10,
+ PA_CHANNEL_POSITION_AUX11,
+ PA_CHANNEL_POSITION_AUX12,
+
+ PA_CHANNEL_POSITION_MAX
+} pa_channel_position_t;
+
+typedef struct pa_channel_map {
+ uint8_t channels;
+ pa_channel_position_t map[PA_CHANNELS_MAX];
+} pa_channel_map;
+
+pa_channel_map* pa_channel_map_init(pa_channel_map *m);
+pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m);
+pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m);
+pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels);
+
+const char* pa_channel_position_to_string(pa_channel_position_t pos);
+
+#define PA_CHANNEL_MAP_SNPRINT_MAX 64
+char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map);
+
+int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b);
+
+int pa_channel_map_valid(const pa_channel_map *map);
+
+PA_C_DECL_END
+
+#endif
diff --git a/polyp/cli-command.c b/polyp/cli-command.c
index 63241a815..f6192bf87 100644
--- a/polyp/cli-command.c
+++ b/polyp/cli-command.c
@@ -311,6 +311,7 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
const char *n, *v;
pa_sink *sink;
uint32_t volume;
+ pa_cvolume cvolume;
if (!(n = pa_tokenizer_get(t, 1))) {
pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
@@ -332,14 +333,16 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
return -1;
}
- pa_sink_set_volume(sink, (uint32_t) volume);
+ pa_cvolume_set(&cvolume, sink->sample_spec.channels, volume);
+ pa_sink_set_volume(sink, PA_MIXER_HARDWARE, &cvolume);
return 0;
}
static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
const char *n, *v;
pa_sink_input *si;
- uint32_t volume;
+ pa_volume_t volume;
+ pa_cvolume cvolume;
uint32_t idx;
if (!(n = pa_tokenizer_get(t, 1))) {
@@ -367,7 +370,8 @@ static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strb
return -1;
}
- pa_sink_input_set_volume(si, (uint32_t) volume);
+ pa_cvolume_set(&cvolume, si->sample_spec.channels, volume);
+ pa_sink_input_set_volume(si, &cvolume);
return 0;
}
@@ -497,7 +501,7 @@ static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
return -1;
}
- if (pa_scache_play_item(c, n, sink, PA_VOLUME_NORM) < 0) {
+ if (pa_scache_play_item(c, n, sink, NULL) < 0) {
pa_strbuf_puts(buf, "Failed to play sample.\n");
return -1;
}
@@ -576,7 +580,7 @@ static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf,
}
- return pa_play_file(sink, fname, PA_VOLUME_NORM);
+ return pa_play_file(sink, fname, NULL);
}
static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
@@ -663,9 +667,6 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G
nl = 0;
for (s = pa_idxset_first(c->sinks, &idx); s; s = pa_idxset_next(c->sinks, &idx)) {
- if (s->volume == PA_VOLUME_NORM)
- continue;
-
if (s->owner && s->owner->auto_unload)
continue;
@@ -673,8 +674,8 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G
pa_strbuf_puts(buf, "\n");
nl = 1;
}
-
- pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", s->name, s->volume);
+
+ pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", s->name, pa_cvolume_avg(pa_sink_get_volume(s, PA_MIXER_HARDWARE)));
}
diff --git a/polyp/cli-text.c b/polyp/cli-text.c
index a19bfc971..328aca4cf 100644
--- a/polyp/cli-text.c
+++ b/polyp/cli-text.c
@@ -38,6 +38,7 @@
#include "scache.h"
#include "autoload.h"
#include "xmalloc.h"
+#include "volume.h"
char *pa_module_list_to_string(pa_core *c) {
pa_strbuf *s;
@@ -60,7 +61,6 @@ char *pa_client_list_to_string(pa_core *c) {
pa_strbuf *s;
pa_client *client;
uint32_t idx = PA_IDXSET_INVALID;
- char tid[5];
assert(c);
s = pa_strbuf_new();
@@ -69,7 +69,7 @@ char *pa_client_list_to_string(pa_core *c) {
pa_strbuf_printf(s, "%u client(s) logged in.\n", pa_idxset_size(c->clients));
for (client = pa_idxset_first(c->clients, &idx); client; client = pa_idxset_next(c->clients, &idx)) {
- pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\ttype: <%s>\n", client->index, client->name, pa_typeid_to_string(client->typeid, tid, sizeof(tid)));
+ pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\tdriver: <%s>\n", client->index, client->name, client->driver);
if (client->owner)
pa_strbuf_printf(s, "\towner module: <%u>\n", client->owner->index);
@@ -82,7 +82,6 @@ char *pa_sink_list_to_string(pa_core *c) {
pa_strbuf *s;
pa_sink *sink;
uint32_t idx = PA_IDXSET_INVALID;
- char tid[5];
assert(c);
s = pa_strbuf_new();
@@ -91,20 +90,26 @@ char *pa_sink_list_to_string(pa_core *c) {
pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_size(c->sinks));
for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) {
- char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
- pa_sample_spec_snprint(ss, sizeof(ss), &sink->sample_spec);
- assert(sink->monitor_source);
+ char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+
pa_strbuf_printf(
s,
- " %c index: %u\n\tname: <%s>\n\ttype: <%s>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n",
+ " %c index: %u\n"
+ "\tname: <%s>\n"
+ "\tdriver: <%s>\n"
+ "\tvolume: <%s>\n"
+ "\tlatency: <%0.0f usec>\n"
+ "\tmonitor_source: <%u>\n"
+ "\tsample spec: <%s>\n"
+ "\tchannel map: <%s>\n",
c->default_sink_name && !strcmp(sink->name, c->default_sink_name) ? '*' : ' ',
sink->index, sink->name,
- pa_typeid_to_string(sink->typeid, tid, sizeof(tid)),
- (unsigned) sink->volume,
- pa_volume_to_dB(sink->volume),
+ sink->driver,
+ pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, PA_MIXER_HARDWARE)),
(double) pa_sink_get_latency(sink),
sink->monitor_source->index,
- ss);
+ pa_sample_spec_snprint(ss, sizeof(ss), &sink->sample_spec),
+ pa_channel_map_snprint(cm, sizeof(cm), &sink->channel_map));
if (sink->owner)
pa_strbuf_printf(s, "\towner module: <%u>\n", sink->owner->index);
@@ -119,7 +124,6 @@ char *pa_source_list_to_string(pa_core *c) {
pa_strbuf *s;
pa_source *source;
uint32_t idx = PA_IDXSET_INVALID;
- char tid[5];
assert(c);
s = pa_strbuf_new();
@@ -128,15 +132,24 @@ char *pa_source_list_to_string(pa_core *c) {
pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_size(c->sources));
for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) {
- char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
- pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec);
- pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\ttype: <%s>\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n",
- c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ',
- source->index,
- source->name,
- pa_typeid_to_string(source->typeid, tid, sizeof(tid)),
- (double) pa_source_get_latency(source),
- ss);
+ char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+
+
+ pa_strbuf_printf(
+ s,
+ " %c index: %u\n"
+ "\tname: <%s>\n"
+ "\tdriver: <%s>\n"
+ "\tlatency: <%0.0f usec>\n"
+ "\tsample spec: <%s>\n"
+ "\tchannel map: <%s>\n",
+ c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ',
+ source->index,
+ source->name,
+ source->driver,
+ (double) pa_source_get_latency(source),
+ pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec),
+ pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map));
if (source->monitor_of)
pa_strbuf_printf(s, "\tmonitor_of: <%u>\n", source->monitor_of->index);
@@ -154,7 +167,6 @@ char *pa_source_output_list_to_string(pa_core *c) {
pa_strbuf *s;
pa_source_output *o;
uint32_t idx = PA_IDXSET_INVALID;
- char tid[5];
static const char* const state_table[] = {
"RUNNING",
"CORKED",
@@ -168,23 +180,28 @@ char *pa_source_output_list_to_string(pa_core *c) {
pa_strbuf_printf(s, "%u source outputs(s) available.\n", pa_idxset_size(c->source_outputs));
for (o = pa_idxset_first(c->source_outputs, &idx); o; o = pa_idxset_next(c->source_outputs, &idx)) {
- char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
- const char *rm;
- pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec);
+ char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+
assert(o->source);
-
- if (!(rm = pa_resample_method_to_string(pa_source_output_get_resample_method(o))))
- rm = "invalid";
pa_strbuf_printf(
- s, " index: %u\n\tname: '%s'\n\ttype: <%s>\n\tstate: %s\n\tsource: <%u> '%s'\n\tsample_spec: <%s>\n\tresample method: %s\n",
+ s,
+ " index: %u\n"
+ "\tname: '%s'\n"
+ "\tdriver: <%s>\n"
+ "\tstate: %s\n"
+ "\tsource: <%u> '%s'\n"
+ "\tsample spec: <%s>\n"
+ "\tchannel map: <%s>\n"
+ "\tresample method: %s\n",
o->index,
o->name,
- pa_typeid_to_string(o->typeid, tid, sizeof(tid)),
+ o->driver,
state_table[o->state],
o->source->index, o->source->name,
- ss,
- rm);
+ pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec),
+ pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map),
+ pa_resample_method_to_string(pa_source_output_get_resample_method(o)));
if (o->owner)
pa_strbuf_printf(s, "\towner module: <%u>\n", o->owner->index);
if (o->client)
@@ -198,7 +215,6 @@ char *pa_sink_input_list_to_string(pa_core *c) {
pa_strbuf *s;
pa_sink_input *i;
uint32_t idx = PA_IDXSET_INVALID;
- char tid[5];
static const char* const state_table[] = {
"RUNNING",
"CORKED",
@@ -212,26 +228,32 @@ char *pa_sink_input_list_to_string(pa_core *c) {
pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_size(c->sink_inputs));
for (i = pa_idxset_first(c->sink_inputs, &idx); i; i = pa_idxset_next(c->sink_inputs, &idx)) {
- char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
- const char *rm;
-
- if (!(rm = pa_resample_method_to_string(pa_sink_input_get_resample_method(i))))
- rm = "invalid";
+ char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
- pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec);
assert(i->sink);
+
pa_strbuf_printf(
- s, " index: %u\n\tname: <%s>\n\ttype: <%s>\n\tstate: %s\n\tsink: <%u> '%s'\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n\tresample method: %s\n",
+ s,
+ " index: %u\n"
+ "\tname: <%s>\n"
+ "\tdriver: <%s>\n"
+ "\tstate: %s\n"
+ "\tsink: <%u> '%s'\n"
+ "\tvolume: <%s>\n"
+ "\tlatency: <%0.0f usec>\n"
+ "\tsample spec: <%s>\n"
+ "\tchannel map: <%s>\n"
+ "\tresample method: %s\n",
i->index,
i->name,
- pa_typeid_to_string(i->typeid, tid, sizeof(tid)),
+ i->driver,
state_table[i->state],
i->sink->index, i->sink->name,
- (unsigned) i->volume,
- pa_volume_to_dB(i->volume),
+ pa_cvolume_snprint(cv, sizeof(cv), pa_sink_input_get_volume(i)),
(double) pa_sink_input_get_latency(i),
- ss,
- rm);
+ pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec),
+ pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
+ pa_resample_method_to_string(pa_sink_input_get_resample_method(i)));
if (i->owner)
pa_strbuf_printf(s, "\towner module: <%u>\n", i->owner->index);
@@ -257,21 +279,32 @@ char *pa_scache_list_to_string(pa_core *c) {
for (e = pa_idxset_first(c->scache, &idx); e; e = pa_idxset_next(c->scache, &idx)) {
double l = 0;
- char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = "n/a";
+ char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = "n/a", cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
if (e->memchunk.memblock) {
pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec);
+ pa_channel_map_snprint(cm, sizeof(cm), &e->channel_map);
l = (double) e->memchunk.length / pa_bytes_per_second(&e->sample_spec);
}
pa_strbuf_printf(
- s, " name: <%s>\n\tindex: <%u>\n\tsample_spec: <%s>\n\tlength: <%u>\n\tduration: <%0.1fs>\n\tvolume: <0x%04x>\n\tlazy: %s\n\tfilename: %s\n",
+ s,
+ " name: <%s>\n"
+ "\tindex: <%u>\n"
+ "\tsample spec: <%s>\n"
+ "\tchannel map: <%s>\n"
+ "\tlength: <%u>\n"
+ "\tduration: <%0.1fs>\n"
+ "\tvolume: <%s>\n"
+ "\tlazy: %s\n"
+ "\tfilename: %s\n",
e->name,
e->index,
ss,
+ cm,
e->memchunk.memblock ? e->memchunk.length : 0,
l,
- e->volume,
+ pa_cvolume_snprint(cv, sizeof(cv), &e->volume),
e->lazy ? "yes" : "no",
e->filename ? e->filename : "n/a");
}
diff --git a/polyp/cli.c b/polyp/cli.c
index 7b1022c1a..bc0c285d3 100644
--- a/polyp/cli.c
+++ b/polyp/cli.c
@@ -45,7 +45,6 @@
#include "log.h"
#define PROMPT ">>> "
-#define PA_TYPEID_CLI PA_TYPEID_MAKE('C', 'L', 'I', '_')
struct pa_cli {
pa_core *core;
@@ -76,7 +75,7 @@ pa_cli* pa_cli_new(pa_core *core, pa_iochannel *io, pa_module *m) {
c->eof_callback = NULL;
pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname));
- c->client = pa_client_new(core, PA_TYPEID_CLI, cname);
+ c->client = pa_client_new(core, __FILE__, cname);
assert(c->client);
c->client->kill = client_kill;
c->client->userdata = c;
diff --git a/polyp/client.c b/polyp/client.c
index 1938a4e0c..3c2084bfb 100644
--- a/polyp/client.c
+++ b/polyp/client.c
@@ -33,16 +33,16 @@
#include "subscribe.h"
#include "log.h"
-pa_client *pa_client_new(pa_core *core, pa_typeid_t typeid, const char *name) {
+pa_client *pa_client_new(pa_core *core, const char *name, const char *driver) {
pa_client *c;
int r;
assert(core);
c = pa_xmalloc(sizeof(pa_client));
c->name = pa_xstrdup(name);
+ c->driver = pa_xstrdup(driver);
c->owner = NULL;
c->core = core;
- c->typeid = typeid;
c->kill = NULL;
c->userdata = NULL;
@@ -68,8 +68,8 @@ void pa_client_free(pa_client *c) {
pa_log_info(__FILE__": freed %u \"%s\"\n", c->index, c->name);
pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index);
pa_xfree(c->name);
+ pa_xfree(c->driver);
pa_xfree(c);
-
}
void pa_client_kill(pa_client *c) {
diff --git a/polyp/client.h b/polyp/client.h
index 198dbbf66..92430338f 100644
--- a/polyp/client.h
+++ b/polyp/client.h
@@ -24,7 +24,6 @@
#include "core.h"
#include "module.h"
-#include "typeid.h"
/* Every connection to the server should have a pa_client
* attached. That way the user may generate a listing of all connected
@@ -34,17 +33,16 @@ typedef struct pa_client pa_client;
struct pa_client {
uint32_t index;
- pa_typeid_t typeid;
pa_module *owner;
- char *name;
+ char *name, *driver;
pa_core *core;
void (*kill)(pa_client *c);
void *userdata;
};
-pa_client *pa_client_new(pa_core *c, pa_typeid_t typeid, const char *name);
+pa_client *pa_client_new(pa_core *c, const char *name, const char *driver);
/* This function should be called only by the code that created the client */
void pa_client_free(pa_client *c);
diff --git a/polyp/core.h b/polyp/core.h
index 704246a9f..9241fcd8f 100644
--- a/polyp/core.h
+++ b/polyp/core.h
@@ -70,7 +70,7 @@ struct pa_core {
pa_time_event *scache_auto_unload_event;
- pa_resample_method resample_method;
+ pa_resample_method_t resample_method;
};
pa_core* pa_core_new(pa_mainloop_api *m);
diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c
index 4ad78bab5..103cf46a4 100644
--- a/polyp/daemon-conf.c
+++ b/polyp/daemon-conf.c
@@ -126,7 +126,7 @@ int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string) {
if (u >= PA_LOG_LEVEL_MAX)
return -1;
- c->log_level = (pa_log_level) u;
+ c->log_level = (pa_log_level_t) u;
} else if (pa_startswith(string, "debug"))
c->log_level = PA_LOG_DEBUG;
else if (pa_startswith(string, "info"))
diff --git a/polyp/daemon-conf.h b/polyp/daemon-conf.h
index 4eb61365d..cebc0bd63 100644
--- a/polyp/daemon-conf.h
+++ b/polyp/daemon-conf.h
@@ -33,11 +33,11 @@ typedef enum pa_daemon_conf_cmd {
PA_CMD_DUMP_MODULES,
PA_CMD_KILL,
PA_CMD_CHECK
-} pa_daemon_conf_cmd;
+} pa_daemon_conf_cmd_t;
/* A structure containing configuration data for the Polypaudio server . */
typedef struct pa_daemon_conf {
- pa_daemon_conf_cmd cmd;
+ pa_daemon_conf_cmd_t cmd;
int daemonize,
fail,
high_priority,
@@ -48,8 +48,8 @@ typedef struct pa_daemon_conf {
auto_log_target,
use_pid_file;
char *script_commands, *dl_search_path, *default_script_file;
- pa_log_target log_target;
- pa_log_level log_level;
+ pa_log_target_t log_target;
+ pa_log_level_t log_level;
int resample_method;
char *config_file;
} pa_daemon_conf;
diff --git a/polyp/dllmain.c b/polyp/dllmain.c
index 34d0eed11..d1d120ab8 100644
--- a/polyp/dllmain.c
+++ b/polyp/dllmain.c
@@ -1,4 +1,4 @@
-/* $Id: dllmain.c 317 2004-12-11 00:10:41Z lennart $ */
+/* $Id$ */
/***
This file is part of polypaudio.
diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c
index 6552da15c..6f7c1dc54 100644
--- a/polyp/glib-mainloop.c
+++ b/polyp/glib-mainloop.c
@@ -38,9 +38,9 @@ struct pa_io_event {
GSource *source;
GIOCondition io_condition;
int fd;
- void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata);
+ void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata);
void *userdata;
- void (*destroy_callback) (pa_mainloop_api *m, pa_io_event*e, void *userdata);
+ void (*destroy_callback) (pa_mainloop_api *m, pa_io_event *e, void *userdata);
pa_io_event *next, *prev;
};
@@ -76,9 +76,9 @@ struct pa_glib_mainloop {
static void schedule_free_dead_events(pa_glib_mainloop *g);
-static void glib_io_enable(pa_io_event*e, pa_io_event_flags f);
+static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f);
-static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags f, void *userdata), void *userdata) {
+static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags_t f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata), void *userdata) {
pa_io_event *e;
pa_glib_mainloop *g;
@@ -111,7 +111,7 @@ static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags f,
/* The callback GLIB calls whenever an IO condition is met */
static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) {
pa_io_event *e = data;
- pa_io_event_flags f;
+ pa_io_event_flags_t f;
assert(source && e && e->io_channel == source);
f = (condition & G_IO_IN ? PA_IO_EVENT_INPUT : 0) |
@@ -123,7 +123,7 @@ static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data)
return TRUE;
}
-static void glib_io_enable(pa_io_event*e, pa_io_event_flags f) {
+static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f) {
GIOCondition c;
assert(e && !e->dead);
diff --git a/polyp/glib12-mainloop.c b/polyp/glib12-mainloop.c
index e322ac075..8bc4483bb 100644
--- a/polyp/glib12-mainloop.c
+++ b/polyp/glib12-mainloop.c
@@ -39,7 +39,7 @@ struct pa_io_event {
guint source;
GIOCondition io_condition;
int fd;
- void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata);
+ void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata);
void *userdata;
void (*destroy_callback) (pa_mainloop_api *m, pa_io_event*e, void *userdata);
pa_io_event *next, *prev;
@@ -76,9 +76,9 @@ struct pa_glib_mainloop {
static void schedule_free_dead_events(pa_glib_mainloop *g);
-static void glib_io_enable(pa_io_event*e, pa_io_event_flags f);
+static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f);
-static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags f, void *userdata), void *userdata) {
+static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags_t f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata), void *userdata) {
pa_io_event *e;
pa_glib_mainloop *g;
@@ -110,7 +110,7 @@ static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags f,
static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) {
pa_io_event *e = data;
- pa_io_event_flags f;
+ pa_io_event_flags_t f;
assert(source && e && e->io_channel == source);
f = (condition & G_IO_IN ? PA_IO_EVENT_INPUT : 0) |
@@ -122,7 +122,7 @@ static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data)
return TRUE;
}
-static void glib_io_enable(pa_io_event*e, pa_io_event_flags f) {
+static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f) {
GIOCondition c;
assert(e && !e->dead);
diff --git a/polyp/inet_ntop.c b/polyp/inet_ntop.c
index ac2b5295a..a25c3c951 100644
--- a/polyp/inet_ntop.c
+++ b/polyp/inet_ntop.c
@@ -1,4 +1,4 @@
-/* $Id: inet_ntop.c 428 2006-01-09 16:50:39Z ossman $ */
+/* $Id$ */
/***
This file is part of polypaudio.
diff --git a/polyp/iochannel.c b/polyp/iochannel.c
index e62713190..273d47e0d 100644
--- a/polyp/iochannel.c
+++ b/polyp/iochannel.c
@@ -55,7 +55,7 @@ static void enable_mainloop_sources(pa_iochannel *io) {
assert(io);
if (io->input_event == io->output_event && io->input_event) {
- pa_io_event_flags f = PA_IO_EVENT_NULL;
+ pa_io_event_flags_t f = PA_IO_EVENT_NULL;
assert(io->input_event);
if (!io->readable)
@@ -72,7 +72,7 @@ static void enable_mainloop_sources(pa_iochannel *io) {
}
}
-static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) {
+static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
pa_iochannel *io = userdata;
int changed = 0;
diff --git a/polyp/log.c b/polyp/log.c
index c41fbbaec..97406f799 100644
--- a/polyp/log.c
+++ b/polyp/log.c
@@ -38,9 +38,9 @@
#define ENV_LOGLEVEL "POLYP_LOG"
static char *log_ident = NULL;
-static pa_log_target log_target = PA_LOG_STDERR;
-static void (*user_log_func)(pa_log_level l, const char *s) = NULL;
-static pa_log_level maximal_level = PA_LOG_NOTICE;
+static pa_log_target_t log_target = PA_LOG_STDERR;
+static void (*user_log_func)(pa_log_level_t l, const char *s) = NULL;
+static pa_log_level_t maximal_level = PA_LOG_NOTICE;
#ifdef HAVE_SYSLOG_H
static const int level_to_syslog[] = {
@@ -59,18 +59,18 @@ void pa_log_set_ident(const char *p) {
log_ident = pa_xstrdup(p);
}
-void pa_log_set_maximal_level(pa_log_level l) {
+void pa_log_set_maximal_level(pa_log_level_t l) {
assert(l < PA_LOG_LEVEL_MAX);
maximal_level = l;
}
-void pa_log_set_target(pa_log_target t, void (*func)(pa_log_level l, const char*s)) {
+void pa_log_set_target(pa_log_target_t t, void (*func)(pa_log_level_t l, const char*s)) {
assert(t == PA_LOG_USER || !func);
log_target = t;
user_log_func = func;
}
-void pa_log_with_levelv(pa_log_level level, const char *format, va_list ap) {
+void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) {
const char *e;
assert(level < PA_LOG_LEVEL_MAX);
@@ -107,44 +107,44 @@ void pa_log_with_levelv(pa_log_level level, const char *format, va_list ap) {
}
-void pa_log_with_level(pa_log_level level, const char *format, ...) {
+void pa_log_level(pa_log_level_t level, const char *format, ...) {
va_list ap;
va_start(ap, format);
- pa_log_with_levelv(level, format, ap);
+ pa_log_levelv(level, format, ap);
va_end(ap);
}
void pa_log_debug(const char *format, ...) {
va_list ap;
va_start(ap, format);
- pa_log_with_levelv(PA_LOG_DEBUG, format, ap);
+ pa_log_levelv(PA_LOG_DEBUG, format, ap);
va_end(ap);
}
void pa_log_info(const char *format, ...) {
va_list ap;
va_start(ap, format);
- pa_log_with_levelv(PA_LOG_INFO, format, ap);
+ pa_log_levelv(PA_LOG_INFO, format, ap);
va_end(ap);
}
void pa_log_notice(const char *format, ...) {
va_list ap;
va_start(ap, format);
- pa_log_with_levelv(PA_LOG_INFO, format, ap);
+ pa_log_levelv(PA_LOG_INFO, format, ap);
va_end(ap);
}
void pa_log_warn(const char *format, ...) {
va_list ap;
va_start(ap, format);
- pa_log_with_levelv(PA_LOG_WARN, format, ap);
+ pa_log_levelv(PA_LOG_WARN, format, ap);
va_end(ap);
}
void pa_log_error(const char *format, ...) {
va_list ap;
va_start(ap, format);
- pa_log_with_levelv(PA_LOG_ERROR, format, ap);
+ pa_log_levelv(PA_LOG_ERROR, format, ap);
va_end(ap);
}
diff --git a/polyp/log.h b/polyp/log.h
index 7c6a8e614..ce8aea986 100644
--- a/polyp/log.h
+++ b/polyp/log.h
@@ -33,7 +33,7 @@ typedef enum pa_log_target {
PA_LOG_SYSLOG,
PA_LOG_USER, /* to user specified function */
PA_LOG_NULL /* to /dev/null */
-} pa_log_target;
+} pa_log_target_t;
typedef enum pa_log_level {
PA_LOG_ERROR = 0, /* Error messages */
@@ -42,16 +42,16 @@ typedef enum pa_log_level {
PA_LOG_INFO = 3, /* Info messages */
PA_LOG_DEBUG = 4, /* debug message */
PA_LOG_LEVEL_MAX
-} pa_log_level;
+} pa_log_level_t;
/* Set an identification for the current daemon. Used when logging to syslog. */
void pa_log_set_ident(const char *p);
/* Set another log target. If t is PA_LOG_USER you may specify a function that is called every log string */
-void pa_log_set_target(pa_log_target t, void (*func)(pa_log_level, const char*s));
+void pa_log_set_target(pa_log_target_t t, void (*func)(pa_log_level_t t, const char*s));
/* Minimal log level */
-void pa_log_set_maximal_level(pa_log_level l);
+void pa_log_set_maximal_level(pa_log_level_t l);
/* Do a log line */
void pa_log_debug(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2);
@@ -60,9 +60,9 @@ void pa_log_notice(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2);
void pa_log_warn(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2);
void pa_log_error(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2);
-void pa_log_with_level(pa_log_level level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3);
+void pa_log_level(pa_log_level_t level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3);
-void pa_log_with_levelv(pa_log_level level, const char *format, va_list ap);
+void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap);
#define pa_log pa_log_error
diff --git a/polyp/main.c b/polyp/main.c
index 1c3b566d8..c984e28e0 100644
--- a/polyp/main.c
+++ b/polyp/main.c
@@ -37,6 +37,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
+#include <liboil/liboil.h>
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
@@ -386,6 +387,8 @@ int main(int argc, char *argv[]) {
pa_signal_new(SIGHUP, signal_callback, c);
#endif
+ oil_init();
+
r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop));
assert(r == 0);
diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h
index 1604e7406..91ee41114 100644
--- a/polyp/mainloop-api.h
+++ b/polyp/mainloop-api.h
@@ -51,7 +51,7 @@ typedef enum pa_io_event_flags {
PA_IO_EVENT_OUTPUT = 2, /**< Output event */
PA_IO_EVENT_HANGUP = 4, /**< Hangup event */
PA_IO_EVENT_ERROR = 8 /**< Error event */
-} pa_io_event_flags;
+} pa_io_event_flags_t;
/** \pa_io_event
* An opaque IO event source object */
@@ -73,10 +73,10 @@ struct pa_mainloop_api {
void *userdata;
/** Create a new IO event source object */
- pa_io_event* (*io_new)(pa_mainloop_api*a, int fd, pa_io_event_flags events, void (*callback) (pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags events, void *userdata), void *userdata);
+ pa_io_event* (*io_new)(pa_mainloop_api*a, int fd, pa_io_event_flags_t events, void (*callback) (pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata), void *userdata);
/** Enable or disable IO events on this object */
- void (*io_enable)(pa_io_event* e, pa_io_event_flags events);
+ void (*io_enable)(pa_io_event* e, pa_io_event_flags_t events);
/** Free a IO event source object */
void (*io_free)(pa_io_event* e);
diff --git a/polyp/mainloop-signal.c b/polyp/mainloop-signal.c
index f225e60b4..769360311 100644
--- a/polyp/mainloop-signal.c
+++ b/polyp/mainloop-signal.c
@@ -119,7 +119,7 @@ static void defer(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event*e, PA_GCC_UNUS
}
}
-static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags f, PA_GCC_UNUSED void *userdata) {
+static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags_t f, PA_GCC_UNUSED void *userdata) {
ssize_t r;
int sig;
assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]);
diff --git a/polyp/mainloop-test.c b/polyp/mainloop-test.c
index 097ce1c79..ee0f8711a 100644
--- a/polyp/mainloop-test.c
+++ b/polyp/mainloop-test.c
@@ -51,7 +51,7 @@ static GMainLoop* glib_main_loop = NULL;
static pa_defer_event *de;
-static void iocb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) {
+static void iocb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
unsigned char c;
read(fd, &c, sizeof(c));
fprintf(stderr, "IO EVENT: %c\n", c < 32 ? '.' : c);
diff --git a/polyp/mainloop.c b/polyp/mainloop.c
index 599a90f85..26ba2425e 100644
--- a/polyp/mainloop.c
+++ b/polyp/mainloop.c
@@ -50,8 +50,8 @@ struct pa_io_event {
pa_mainloop *mainloop;
int dead;
int fd;
- pa_io_event_flags events;
- void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata);
+ pa_io_event_flags_t events;
+ void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata);
struct pollfd *pollfd;
void *userdata;
void (*destroy_callback) (pa_mainloop_api*a, pa_io_event *e, void *userdata);
@@ -91,7 +91,13 @@ struct pa_mainloop {
};
/* IO events */
-static pa_io_event* mainloop_io_new(pa_mainloop_api*a, int fd, pa_io_event_flags events, void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags events, void *userdata), void *userdata) {
+static pa_io_event* mainloop_io_new(
+ pa_mainloop_api*a,
+ int fd,
+ pa_io_event_flags_t events,
+ void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata),
+ void *userdata) {
+
pa_mainloop *m;
pa_io_event *e;
@@ -135,7 +141,7 @@ static pa_io_event* mainloop_io_new(pa_mainloop_api*a, int fd, pa_io_event_flags
return e;
}
-static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags events) {
+static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) {
assert(e && e->mainloop);
e->events = events;
diff --git a/polyp/memblock.h b/polyp/memblock.h
index cbf5d6843..c57514065 100644
--- a/polyp/memblock.h
+++ b/polyp/memblock.h
@@ -31,12 +31,12 @@
* memory blocks. */
/* The type of memory this block points to */
-typedef enum {
+typedef enum pa_memblock_type {
PA_MEMBLOCK_FIXED, /* data is a pointer to fixed memory that needs not to be freed */
PA_MEMBLOCK_APPENDED, /* The most common kind: the data is appended to the memory block */
PA_MEMBLOCK_DYNAMIC, /* data is a pointer to some memory allocated with pa_xmalloc() */
PA_MEMBLOCK_USER /* User supplied memory, to be freed with free_cb */
-} pa_memblock_type ;
+} pa_memblock_type_t;
/* A structure of keeping memory block statistics */
/* Maintains statistics about memory blocks */
@@ -49,7 +49,7 @@ typedef struct pa_memblock_stat {
} pa_memblock_stat;
typedef struct pa_memblock {
- pa_memblock_type type;
+ pa_memblock_type_t type;
unsigned ref; /* the reference counter */
int read_only; /* boolean */
size_t length;
diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c
index 14070d635..ea6ca4246 100644
--- a/polyp/module-alsa-sink.c
+++ b/polyp/module-alsa-sink.c
@@ -51,8 +51,6 @@ PA_MODULE_DESCRIPTION("ALSA Sink")
PA_MODULE_VERSION(PACKAGE_VERSION)
PA_MODULE_USAGE("sink_name=<name for the sink> device=<ALSA device> format=<sample format> channels=<number of channels> rate=<sample rate> fragments=<number of fragments> fragment_size=<fragment size>")
-#define PA_TYPEID_ALSA PA_TYPEID_MAKE('A', 'L', 'S', 'A')
-
struct userdata {
snd_pcm_t *pcm_handle;
pa_sink *sink;
@@ -142,7 +140,7 @@ static void do_write(struct userdata *u) {
}
}
-static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) {
+static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
struct userdata *u = userdata;
assert(u && a && e);
@@ -220,7 +218,7 @@ int pa__init(pa_core *c, pa_module*m) {
goto fail;
}
- u->sink = pa_sink_new(c, PA_TYPEID_ALSA, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss);
+ u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL);
assert(u->sink);
u->sink->get_latency = sink_get_latency_cb;
@@ -236,7 +234,7 @@ int pa__init(pa_core *c, pa_module*m) {
u->frame_size = frame_size;
u->fragment_size = period_size;
- pa_log(__FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size);
+ pa_log_info(__FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size);
u->silence.memblock = pa_memblock_new(u->silence.length = u->fragment_size, c->memblock_stat);
assert(u->silence.memblock);
diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c
index 4ad8dd84c..2aa47aadd 100644
--- a/polyp/module-alsa-source.c
+++ b/polyp/module-alsa-source.c
@@ -51,8 +51,6 @@ PA_MODULE_DESCRIPTION("ALSA Source")
PA_MODULE_VERSION(PACKAGE_VERSION)
PA_MODULE_USAGE("source_name=<name for the source> device=<ALSA device> format=<sample format> channels=<number of channels> rate=<sample rate> fragments=<number of fragments> fragment_size=<fragment size>")
-#define PA_TYPEID_ALSA PA_TYPEID_MAKE('A', 'L', 'S', 'A')
-
struct userdata {
snd_pcm_t *pcm_handle;
pa_source *source;
@@ -142,7 +140,7 @@ static void do_read(struct userdata *u) {
}
}
-static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) {
+static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
struct userdata *u = userdata;
assert(u && a && e);
@@ -211,7 +209,7 @@ int pa__init(pa_core *c, pa_module*m) {
goto fail;
}
- u->source = pa_source_new(c, PA_TYPEID_ALSA, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss);
+ u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL);
assert(u->source);
u->source->userdata = u;
diff --git a/polyp/module-combine.c b/polyp/module-combine.c
index cee0a5dc3..0c21c2f55 100644
--- a/polyp/module-combine.c
+++ b/polyp/module-combine.c
@@ -43,8 +43,6 @@ PA_MODULE_DESCRIPTION("Combine multiple sinks to one")
PA_MODULE_VERSION(PACKAGE_VERSION)
PA_MODULE_USAGE("sink_name=<name for the sink> master=<master sink> slaves=<slave sinks> adjust_time=<seconds> resample_method=<method>")
-#define PA_TYPEID_COMBINE PA_TYPEID_MAKE('C', 'M', 'B', 'N')
-
#define DEFAULT_SINK_NAME "combined"
#define MEMBLOCKQ_MAXLENGTH (1024*170)
#define RENDER_SIZE (1024*10)
@@ -216,7 +214,7 @@ static struct output *output_new(struct userdata *u, pa_sink *sink, int resample
o->memblockq = pa_memblockq_new(MEMBLOCKQ_MAXLENGTH, MEMBLOCKQ_MAXLENGTH, pa_frame_size(&u->sink->sample_spec), 0, 0, sink->core->memblock_stat);
snprintf(t, sizeof(t), "%s: output #%u", u->sink->name, u->n_outputs+1);
- if (!(o->sink_input = pa_sink_input_new(sink, PA_TYPEID_COMBINE, t, &u->sink->sample_spec, 1, resample_method)))
+ if (!(o->sink_input = pa_sink_input_new(sink, __FILE__, t, &u->sink->sample_spec, &u->sink->channel_map, 1, resample_method)))
goto fail;
o->sink_input->get_latency = sink_input_get_latency_cb;
@@ -327,7 +325,7 @@ int pa__init(pa_core *c, pa_module*m) {
goto fail;
}
- if (!(u->sink = pa_sink_new(c, PA_TYPEID_COMBINE, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &master_sink->sample_spec))) {
+ if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &master_sink->sample_spec, &master_sink->channel_map))) {
pa_log(__FILE__": failed to create sink\n");
goto fail;
}
diff --git a/polyp/module-esound-sink.c b/polyp/module-esound-sink.c
index ac211a316..afd5feed8 100644
--- a/polyp/module-esound-sink.c
+++ b/polyp/module-esound-sink.c
@@ -46,14 +46,12 @@
#include "authkey.h"
PA_MODULE_AUTHOR("Lennart Poettering")
-PA_MODULE_DESCRIPTION("Esound ")
+PA_MODULE_DESCRIPTION("ESOUND Sink")
PA_MODULE_VERSION(PACKAGE_VERSION)
PA_MODULE_USAGE("sink_name=<name for the sink> server=<address> cookie=<filename> format=<sample format> channels=<number of channels> rate=<sample rate>")
#define DEFAULT_SINK_NAME "esound_output"
-#define PA_TYPEID_ESOUND_SINK PA_TYPEID_MAKE('E', 'S', 'D', 'S')
-
struct userdata {
pa_core *core;
@@ -354,7 +352,7 @@ int pa__init(pa_core *c, pa_module*m) {
u->state = STATE_AUTH;
u->latency = 0;
- if (!(u->sink = pa_sink_new(c, PA_TYPEID_ESOUND_SINK, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
+ if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) {
pa_log(__FILE__": failed to create sink.\n");
goto fail;
}
diff --git a/polyp/module-lirc.c b/polyp/module-lirc.c
index eb71c47f5..d2e248aa0 100644
--- a/polyp/module-lirc.c
+++ b/polyp/module-lirc.c
@@ -61,7 +61,7 @@ struct userdata {
static int lirc_in_use = 0;
-static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags events, void*userdata) {
+static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void*userdata) {
struct userdata *u = userdata;
char *name = NULL, *code = NULL;
assert(io);
@@ -109,26 +109,45 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1)))
pa_log(__FILE__": failed to get sink '%s'\n", u->sink_name);
else {
- double v = pa_volume_to_user(s->volume);
-
+ pa_volume_t v = pa_cvolume_avg(pa_sink_get_volume(s, PA_MIXER_HARDWARE));
+ pa_cvolume cv;
+#define DELTA (PA_VOLUME_NORM/20)
+
switch (volchange) {
- case UP: v += .05; break;
- case DOWN: v -= .05; break;
- case MUTE: v = 0; break;
- case RESET: v = 1; break;
+ case UP:
+ v += PA_VOLUME_NORM/20;
+ break;
+
+ case DOWN:
+ if (v > DELTA)
+ v -= DELTA;
+ else
+ v = PA_VOLUME_MUTED;
+
+ break;
+
+ case MUTE:
+ v = PA_VOLUME_MUTED;
+ break;
+
+ case RESET:
+ v = PA_VOLUME_NORM;
+ break;
+
case MUTE_TOGGLE: {
if (v > 0) {
u->mute_toggle_save = v;
- v = 0;
+ v = PA_VOLUME_MUTED;
} else
v = u->mute_toggle_save;
}
default:
;
}
-
- pa_sink_set_volume(s, pa_volume_from_user(v));
+
+ pa_cvolume_set(&cv, PA_CHANNELS_MAX, v);
+ pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv);
}
}
}
diff --git a/polyp/module-match.c b/polyp/module-match.c
index e48d55ca0..e3e7b17d2 100644
--- a/polyp/module-match.c
+++ b/polyp/module-match.c
@@ -154,7 +154,7 @@ finish:
return ret;
}
-static void callback(pa_core *c, pa_subscription_event_type t, uint32_t idx, void *userdata) {
+static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
struct userdata *u = userdata;
pa_sink_input *si;
struct rule *r;
@@ -171,8 +171,10 @@ static void callback(pa_core *c, pa_subscription_event_type t, uint32_t idx, voi
for (r = u->rules; r; r = r->next) {
if (!regexec(&r->regex, si->name, 0, NULL, 0)) {
+ pa_cvolume cv;
pa_log_debug(__FILE__": changing volume of sink input '%s' to 0x%03x\n", si->name, r->volume);
- pa_sink_input_set_volume(si, r->volume);
+ pa_cvolume_set(&cv, r->volume, si->sample_spec.channels);
+ pa_sink_input_set_volume(si, &cv);
}
}
}
diff --git a/polyp/module-mmkbd-evdev.c b/polyp/module-mmkbd-evdev.c
index 5eb55e35c..ec45ec4b9 100644
--- a/polyp/module-mmkbd-evdev.c
+++ b/polyp/module-mmkbd-evdev.c
@@ -74,7 +74,7 @@ struct userdata {
float mute_toggle_save;
};
-static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags events, void*userdata) {
+static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void*userdata) {
struct userdata *u = userdata;
assert(io);
assert(u);
@@ -109,16 +109,28 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1)))
pa_log(__FILE__": failed to get sink '%s'\n", u->sink_name);
else {
- double v = pa_volume_to_user(s->volume);
+ pa_volume_t v = pa_cvolume_avg(pa_sink_get_volume(s, PA_MIXER_HARDWARE));
+ pa_cvolume cv;
+#define DELTA (PA_VOLUME_NORM/20)
switch (volchange) {
- case UP: v += .05; break;
- case DOWN: v -= .05; break;
+ case UP:
+ v += DELTA;
+ break;
+
+ case DOWN:
+ if (v > DELTA)
+ v -= DELTA;
+ else
+ v = PA_VOLUME_MUTED;
+
+ break;
+
case MUTE_TOGGLE: {
if (v > 0) {
u->mute_toggle_save = v;
- v = 0;
+ v = PA_VOLUME_MUTED;
} else
v = u->mute_toggle_save;
}
@@ -126,7 +138,8 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
;
}
- pa_sink_set_volume(s, pa_volume_from_user(v));
+ pa_cvolume_set(&cv, PA_CHANNELS_MAX, v);
+ pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv);
}
}
}
diff --git a/polyp/module-null-sink.c b/polyp/module-null-sink.c
index b26ea50bd..93abca78d 100644
--- a/polyp/module-null-sink.c
+++ b/polyp/module-null-sink.c
@@ -49,8 +49,6 @@ PA_MODULE_USAGE("format=<sample format> channels=<number of channels> rate=<samp
#define DEFAULT_SINK_NAME "null"
-#define PA_TYPEID_NULL PA_TYPEID_MAKE('N', 'U', 'L', 'L')
-
struct userdata {
pa_core *core;
pa_module *module;
@@ -108,7 +106,7 @@ int pa__init(pa_core *c, pa_module*m) {
u->module = m;
m->userdata = u;
- if (!(u->sink = pa_sink_new(c, PA_TYPEID_NULL, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
+ if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) {
pa_log(__FILE__": failed to create sink.\n");
goto fail;
}
diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c
index ac510f96c..f976cf81c 100644
--- a/polyp/module-oss-mmap.c
+++ b/polyp/module-oss-mmap.c
@@ -53,8 +53,6 @@ PA_MODULE_DESCRIPTION("OSS Sink/Source (mmap)")
PA_MODULE_VERSION(PACKAGE_VERSION)
PA_MODULE_USAGE("sink_name=<name for the sink> source_name=<name for the source> device=<OSS device> record=<enable source?> playback=<enable sink?> format=<sample format> channels=<number of channels> rate=<sample rate> fragments=<number of fragments> fragment_size=<fragment size>")
-#define PA_TYPEID_OSS_MMAP PA_TYPEID_MAKE('O', 'S', 'S', 'M')
-
struct userdata {
pa_sink *sink;
pa_source *source;
@@ -204,7 +202,7 @@ static void do_read(struct userdata *u) {
in_clear_memblocks(u, u->in_fragments/2);
}
-static void io_callback(pa_mainloop_api *m, pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags f, void *userdata) {
+static void io_callback(pa_mainloop_api *m, pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t f, void *userdata) {
struct userdata *u = userdata;
assert (u && u->core->mainloop == m && u->io_event == e);
@@ -304,7 +302,7 @@ int pa__init(pa_core *c, pa_module*m) {
}
} else {
- u->source = pa_source_new(c, PA_TYPEID_OSS_MMAP, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec);
+ u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec, NULL);
assert(u->source);
u->source->userdata = u;
pa_source_set_owner(u->source, m);
@@ -336,7 +334,7 @@ int pa__init(pa_core *c, pa_module*m) {
} else {
pa_silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec);
- u->sink = pa_sink_new(c, PA_TYPEID_OSS_MMAP, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &u->sample_spec);
+ u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &u->sample_spec, NULL);
assert(u->sink);
u->sink->get_latency = sink_get_latency_cb;
u->sink->userdata = u;
diff --git a/polyp/module-oss.c b/polyp/module-oss.c
index 06679a97d..b5c7ae8cf 100644
--- a/polyp/module-oss.c
+++ b/polyp/module-oss.c
@@ -52,8 +52,6 @@ PA_MODULE_DESCRIPTION("OSS Sink/Source")
PA_MODULE_VERSION(PACKAGE_VERSION)
PA_MODULE_USAGE("sink_name=<name for the sink> source_name=<name for the source> device=<OSS device> record=<enable source?> playback=<enable sink?> format=<sample format> channels=<number of channels> rate=<sample rate> fragments=<number of fragments> fragment_size=<fragment size>")
-#define PA_TYPEID_OSS PA_TYPEID_MAKE('O', 'S', 'S', '_')
-
struct userdata {
pa_sink *sink;
pa_source *source;
@@ -222,7 +220,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) {
assert(s && u && u->sink);
if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) {
- pa_log_info(__FILE__": device doesn't support SNDCTL_DSP_GETODELAY.\n");
+ pa_log_info(__FILE__": device doesn't support SNDCTL_DSP_GETODELAY: %s\n", strerror(errno));
s->get_latency = NULL;
return 0;
}
@@ -254,6 +252,46 @@ static pa_usec_t source_get_latency_cb(pa_source *s) {
return pa_bytes_to_usec(info.bytes, &s->sample_spec);
}
+static int sink_get_hw_volume(pa_sink *s) {
+ struct userdata *u = s->userdata;
+ char cv[PA_CVOLUME_SNPRINT_MAX];
+ unsigned vol;
+
+ if (ioctl(u->fd, SOUND_MIXER_READ_PCM, &vol) < 0) {
+ pa_log_info(__FILE__": device doesn't support reading mixer settings: %s\n", strerror(errno));
+ s->get_hw_volume = NULL;
+ return -1;
+ }
+
+ s->hw_volume.values[0] = ((vol & 0xFF) * PA_VOLUME_NORM) / 100;
+
+ if ((s->hw_volume.channels = s->sample_spec.channels) >= 2)
+ s->hw_volume.values[1] = (((vol >> 8) & 0xFF) * PA_VOLUME_NORM) / 100;
+
+ pa_log_info(__FILE__": Read mixer settings: %s\n", pa_cvolume_snprint(cv, sizeof(cv), &s->hw_volume));
+ return 0;
+}
+
+static int sink_set_hw_volume(pa_sink *s) {
+ struct userdata *u = s->userdata;
+ char cv[PA_CVOLUME_SNPRINT_MAX];
+ unsigned vol;
+
+ vol = (s->hw_volume.values[0]*100)/PA_VOLUME_NORM;
+
+ if (s->sample_spec.channels >= 2)
+ vol |= ((s->hw_volume.values[1]*100)/PA_VOLUME_NORM) << 8;
+
+ if (ioctl(u->fd, SOUND_MIXER_WRITE_PCM, &vol) < 0) {
+ pa_log_info(__FILE__": device doesn't support writing mixer settings: %s\n", strerror(errno));
+ s->set_hw_volume = NULL;
+ return -1;
+ }
+
+ pa_log_info(__FILE__": Wrote mixer settings: %s\n", pa_cvolume_snprint(cv, sizeof(cv), &s->hw_volume));
+ return 0;
+}
+
int pa__init(pa_core *c, pa_module*m) {
struct audio_buf_info info;
struct userdata *u = NULL;
@@ -332,7 +370,7 @@ int pa__init(pa_core *c, pa_module*m) {
}
if (mode != O_WRONLY) {
- u->source = pa_source_new(c, PA_TYPEID_OSS, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss);
+ u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL);
assert(u->source);
u->source->userdata = u;
u->source->notify = source_notify_cb;
@@ -343,9 +381,11 @@ int pa__init(pa_core *c, pa_module*m) {
u->source = NULL;
if (mode != O_RDONLY) {
- u->sink = pa_sink_new(c, PA_TYPEID_OSS, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss);
+ u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL);
assert(u->sink);
u->sink->get_latency = sink_get_latency_cb;
+ u->sink->get_hw_volume = sink_get_hw_volume;
+ u->sink->set_hw_volume = sink_set_hw_volume;
u->sink->userdata = u;
pa_sink_set_owner(u->sink, m);
u->sink->description = pa_sprintf_malloc("Open Sound System PCM on '%s'", p);
@@ -384,6 +424,10 @@ int pa__init(pa_core *c, pa_module*m) {
read(u->fd, buf, u->sample_size);
}
+ /* Read mixer settings */
+ if (u->sink)
+ sink_get_hw_volume(u->sink);
+
return 0;
fail:
diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c
index 537cb86bf..20e220ce9 100644
--- a/polyp/module-pipe-sink.c
+++ b/polyp/module-pipe-sink.c
@@ -50,8 +50,6 @@ PA_MODULE_USAGE("sink_name=<name for the sink> file=<path of the FIFO> format=<s
#define DEFAULT_FIFO_NAME "/tmp/music.output"
#define DEFAULT_SINK_NAME "fifo_output"
-#define PA_TYPEID_PIPE PA_TYPEID_MAKE('P', 'I', 'P', 'E')
-
struct userdata {
pa_core *core;
@@ -177,7 +175,7 @@ int pa__init(pa_core *c, pa_module*m) {
u->module = m;
m->userdata = u;
- if (!(u->sink = pa_sink_new(c, PA_TYPEID_PIPE, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
+ if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) {
pa_log(__FILE__": failed to create sink.\n");
goto fail;
}
diff --git a/polyp/module-pipe-source.c b/polyp/module-pipe-source.c
index 31653627c..42f13d4b0 100644
--- a/polyp/module-pipe-source.c
+++ b/polyp/module-pipe-source.c
@@ -50,8 +50,6 @@ PA_MODULE_USAGE("source_name=<name for the source> file=<path of the FIFO> forma
#define DEFAULT_FIFO_NAME "/tmp/music.input"
#define DEFAULT_SOURCE_NAME "fifo_input"
-#define PA_TYPEID_PIPE PA_TYPEID_MAKE('P', 'I', 'P', 'E')
-
struct userdata {
pa_core *core;
@@ -154,7 +152,7 @@ int pa__init(pa_core *c, pa_module*m) {
u->filename = pa_xstrdup(p);
u->core = c;
- if (!(u->source = pa_source_new(c, PA_TYPEID_PIPE, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) {
+ if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL))) {
pa_log(__FILE__": failed to create source.\n");
goto fail;
}
diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c
index 3cf3d9d4a..44d1c0220 100644
--- a/polyp/module-protocol-stub.c
+++ b/polyp/module-protocol-stub.c
@@ -146,7 +146,7 @@
#else
#include "module-esound-protocol-unix-symdef.h"
#endif
- PA_MODULE_DESCRIPTION("EsounD protocol "SOCKET_DESCRIPTION)
+ PA_MODULE_DESCRIPTION("ESOUND protocol "SOCKET_DESCRIPTION)
PA_MODULE_USAGE("sink=<sink to connect to> source=<source to connect to> public=<don't check for cookies?> cookie=<path to cookie file> "SOCKET_USAGE)
#else
#error "Broken build system"
diff --git a/polyp/module-sine.c b/polyp/module-sine.c
index c531386a6..529c061a7 100644
--- a/polyp/module-sine.c
+++ b/polyp/module-sine.c
@@ -40,8 +40,6 @@ PA_MODULE_DESCRIPTION("Sine wave generator")
PA_MODULE_USAGE("sink=<sink to connect to> frequency=<frequency in Hz>")
PA_MODULE_VERSION(PACKAGE_VERSION)
-#define PA_TYPEID_SINE PA_TYPEID_MAKE('S', 'I', 'N', 'E')
-
struct userdata {
pa_core *core;
pa_module *module;
@@ -142,7 +140,7 @@ int pa__init(pa_core *c, pa_module*m) {
calc_sine(u->memblock->data, u->memblock->length, frequency);
snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency);
- if (!(u->sink_input = pa_sink_input_new(sink, PA_TYPEID_SINE, t, &ss, 0, -1)))
+ if (!(u->sink_input = pa_sink_input_new(sink, __FILE__, t, &ss, NULL, 0, -1)))
goto fail;
u->sink_input->peek = sink_input_peek;
diff --git a/polyp/module-solaris.c b/polyp/module-solaris.c
index 01a151d63..ce9308be3 100644
--- a/polyp/module-solaris.c
+++ b/polyp/module-solaris.c
@@ -1,4 +1,4 @@
-/* $Id: module-oss.c 333 2005-01-08 21:36:53Z lennart $ */
+/* $Id$ */
/***
This file is part of polypaudio.
diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c
index e0eab6c2d..c088dae0b 100644
--- a/polyp/module-tunnel.c
+++ b/polyp/module-tunnel.c
@@ -59,8 +59,6 @@ PA_MODULE_USAGE("server=<address> source=<remote source name> cookie=<filename>
PA_MODULE_AUTHOR("Lennart Poettering")
PA_MODULE_VERSION(PACKAGE_VERSION)
-#define PA_TYPEID_TUNNEL PA_TYPEID_MAKE('T', 'U', 'N', 'L')
-
#define DEFAULT_SINK_NAME "tunnel"
#define DEFAULT_SOURCE_NAME "tunnel"
@@ -625,7 +623,7 @@ int pa__init(pa_core *c, pa_module*m) {
pa_socket_client_set_callback(u->client, on_connection, u);
#ifdef TUNNEL_SINK
- if (!(u->sink = pa_sink_new(c, PA_TYPEID_TUNNEL, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
+ if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) {
pa_log(__FILE__": failed to create sink.\n");
goto fail;
}
@@ -637,7 +635,7 @@ int pa__init(pa_core *c, pa_module*m) {
pa_sink_set_owner(u->sink, m);
#else
- if (!(u->source = pa_source_new(c, PA_TYPEID_TUNNEL, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) {
+ if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL))) {
pa_log(__FILE__": failed to create source.\n");
goto fail;
}
diff --git a/polyp/module-waveout.c b/polyp/module-waveout.c
index 4d6d8c7b6..a5ef847b5 100644
--- a/polyp/module-waveout.c
+++ b/polyp/module-waveout.c
@@ -1,4 +1,4 @@
-/* $Id: module-waveout.c 333 2005-01-08 21:36:53Z lennart $ */
+/* $Id$ */
/***
This file is part of polypaudio.
diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c
index 9b08c1667..4fc4a60d4 100644
--- a/polyp/module-x11-bell.c
+++ b/polyp/module-x11-bell.c
@@ -66,6 +66,7 @@ static const char* const valid_modargs[] = {
static int ring_bell(struct userdata *u, int percent) {
pa_sink *s;
+ pa_cvolume cv;
assert(u);
if (!(s = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) {
@@ -73,7 +74,7 @@ static int ring_bell(struct userdata *u, int percent) {
return -1;
}
- pa_scache_play_item(u->core, u->scache_item, s, percent*2);
+ pa_scache_play_item(u->core, u->scache_item, s, pa_cvolume_set(&cv, PA_CHANNELS_MAX, percent*PA_VOLUME_NORM/100));
return 0;
}
diff --git a/polyp/namereg.c b/polyp/namereg.c
index 7c53a05d0..07fb485c8 100644
--- a/polyp/namereg.c
+++ b/polyp/namereg.c
@@ -38,7 +38,7 @@
#include "util.h"
struct namereg_entry {
- pa_namereg_type type;
+ pa_namereg_type_t type;
char *name;
void *data;
};
@@ -51,7 +51,7 @@ void pa_namereg_free(pa_core *c) {
pa_hashmap_free(c->namereg, NULL, NULL);
}
-const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type type, void *data, int fail) {
+const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, int fail) {
struct namereg_entry *e;
char *n = NULL;
int r;
@@ -110,7 +110,7 @@ void pa_namereg_unregister(pa_core *c, const char *name) {
pa_xfree(e);
}
-void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type type, int autoload) {
+void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int autoload) {
struct namereg_entry *e;
uint32_t idx;
assert(c);
@@ -152,7 +152,7 @@ void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type type, int aut
return NULL;
}
-void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type type) {
+void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type) {
char **s;
assert(c && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE));
diff --git a/polyp/namereg.h b/polyp/namereg.h
index 04f1737ba..961fd44b5 100644
--- a/polyp/namereg.h
+++ b/polyp/namereg.h
@@ -28,14 +28,14 @@ typedef enum pa_namereg_type {
PA_NAMEREG_SINK,
PA_NAMEREG_SOURCE,
PA_NAMEREG_SAMPLE
-} pa_namereg_type ;
+} pa_namereg_type_t;
void pa_namereg_free(pa_core *c);
-const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type type, void *data, int fail);
+const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, int fail);
void pa_namereg_unregister(pa_core *c, const char *name);
-void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type type, int autoload);
-void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type type);
+void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int autoload);
+void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type);
const char *pa_namereg_get_default_sink_name(pa_core *c);
const char *pa_namereg_get_default_source_name(pa_core *c);
diff --git a/polyp/native-common.h b/polyp/native-common.h
index 892629e8a..569f3b71a 100644
--- a/polyp/native-common.h
+++ b/polyp/native-common.h
@@ -51,6 +51,7 @@ enum {
PA_COMMAND_FINISH_UPLOAD_STREAM,
PA_COMMAND_PLAY_SAMPLE,
PA_COMMAND_REMOVE_SAMPLE,
+
PA_COMMAND_GET_SERVER_INFO,
PA_COMMAND_GET_SINK_INFO,
PA_COMMAND_GET_SINK_INFO_LIST,
@@ -68,15 +69,19 @@ enum {
PA_COMMAND_GET_SAMPLE_INFO_LIST,
PA_COMMAND_SUBSCRIBE,
PA_COMMAND_SUBSCRIBE_EVENT,
+
PA_COMMAND_SET_SINK_VOLUME,
PA_COMMAND_SET_SINK_INPUT_VOLUME,
PA_COMMAND_CORK_PLAYBACK_STREAM,
PA_COMMAND_FLUSH_PLAYBACK_STREAM,
PA_COMMAND_TRIGGER_PLAYBACK_STREAM,
+
PA_COMMAND_SET_DEFAULT_SINK,
PA_COMMAND_SET_DEFAULT_SOURCE,
+
PA_COMMAND_SET_PLAYBACK_STREAM_NAME,
PA_COMMAND_SET_RECORD_STREAM_NAME,
+
PA_COMMAND_KILL_CLIENT,
PA_COMMAND_KILL_SINK_INPUT,
PA_COMMAND_KILL_SOURCE_OUTPUT,
diff --git a/polyp/pacat-simple.c b/polyp/pacat-simple.c
index 373cdd576..2825fee55 100644
--- a/polyp/pacat-simple.c
+++ b/polyp/pacat-simple.c
@@ -48,7 +48,7 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) {
int error;
/* Create a new playback stream */
- if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, PA_VOLUME_NORM, &error))) {
+ if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, &error))) {
fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
goto finish;
}
diff --git a/polyp/pacat.c b/polyp/pacat.c
index 6842d61ac..bd2b64fd5 100644
--- a/polyp/pacat.c
+++ b/polyp/pacat.c
@@ -162,16 +162,17 @@ static void context_state_callback(pa_context *c, void *userdata) {
if (verbose)
fprintf(stderr, "Connection established.\n");
- stream = pa_stream_new(c, stream_name, &sample_spec);
+ stream = pa_stream_new(c, stream_name, &sample_spec, NULL);
assert(stream);
pa_stream_set_state_callback(stream, stream_state_callback, NULL);
pa_stream_set_write_callback(stream, stream_write_callback, NULL);
pa_stream_set_read_callback(stream, stream_read_callback, NULL);
- if (mode == PLAYBACK)
- pa_stream_connect_playback(stream, device, NULL, 0, volume);
- else
+ if (mode == PLAYBACK) {
+ pa_cvolume cv;
+ pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume));
+ } else
pa_stream_connect_record(stream, device, NULL, 0);
break;
@@ -219,7 +220,7 @@ static void stream_drain_complete(pa_stream*s, int success, void *userdata) {
}
/* New data on STDIN **/
-static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) {
+static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
size_t l, w = 0;
ssize_t r;
assert(a == mainloop_api && e && stdio_event == e);
@@ -257,7 +258,7 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even
}
/* Some data may be written to STDOUT */
-static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) {
+static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
ssize_t r;
assert(a == mainloop_api && e && stdio_event == e);
diff --git a/polyp/pactl.c b/polyp/pactl.c
index 6943a11f1..23bd924b8 100644
--- a/polyp/pactl.c
+++ b/polyp/pactl.c
@@ -149,8 +149,8 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi
}
static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) {
- char s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5];
-
+ char s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+
if (is_last < 0) {
fprintf(stderr, "Failed to get sink information: %s\n", pa_strerror(pa_context_errno(c)));
quit(1);
@@ -168,31 +168,31 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_
printf("\n");
nl = 1;
- pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec);
-
printf("*** Sink #%u ***\n"
"Name: %s\n"
- "Type: %s\n"
+ "Driver: %s\n"
"Description: %s\n"
"Sample Specification: %s\n"
+ "Channel Map: %s\n"
"Owner Module: %u\n"
- "Volume: 0x%03x (%0.2f dB)\n"
+ "Volume: %s\n"
"Monitor Source: %u\n"
"Latency: %0.0f usec\n",
i->index,
i->name,
- pa_typeid_to_string(i->_typeid, tid, sizeof(tid)),
+ i->driver,
i->description,
- s,
+ pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
+ pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
i->owner_module,
- i->volume, pa_volume_to_dB(i->volume),
+ pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
i->monitor_source,
(double) i->latency);
}
static void get_source_info_callback(pa_context *c, const pa_source_info *i, int is_last, void *userdata) {
- char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32], tid[5];
+ char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
if (is_last < 0) {
fprintf(stderr, "Failed to get source information: %s\n", pa_strerror(pa_context_errno(c)));
@@ -213,21 +213,21 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int
snprintf(t, sizeof(t), "%u", i->monitor_of_sink);
- pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec);
-
printf("*** Source #%u ***\n"
"Name: %s\n"
- "Type: %s\n"
+ "Driver: %s\n"
"Description: %s\n"
"Sample Specification: %s\n"
+ "Channel Map: %s\n"
"Owner Module: %u\n"
"Monitor of Sink: %s\n"
"Latency: %0.0f usec\n",
i->index,
- pa_typeid_to_string(i->_typeid, tid, sizeof(tid)),
+ i->driver,
i->name,
i->description,
- s,
+ pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
+ pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
i->owner_module,
i->monitor_of_sink != PA_INVALID_INDEX ? t : "no",
(double) i->latency);
@@ -269,7 +269,7 @@ static void get_module_info_callback(pa_context *c, const pa_module_info *i, int
}
static void get_client_info_callback(pa_context *c, const pa_client_info *i, int is_last, void *userdata) {
- char t[32], tid[5];
+ char t[32];
if (is_last < 0) {
fprintf(stderr, "Failed to get client information: %s\n", pa_strerror(pa_context_errno(c)));
@@ -292,16 +292,16 @@ static void get_client_info_callback(pa_context *c, const pa_client_info *i, int
printf("*** Client #%u ***\n"
"Name: %s\n"
- "Type: %s\n"
+ "Driver: %s\n"
"Owner Module: %s\n",
i->index,
i->name,
- pa_typeid_to_string(i->_typeid, tid, sizeof(tid)),
+ i->driver,
i->owner_module != PA_INVALID_INDEX ? t : "n/a");
}
static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info *i, int is_last, void *userdata) {
- char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5];
+ char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
if (is_last < 0) {
fprintf(stderr, "Failed to get sink input information: %s\n", pa_strerror(pa_context_errno(c)));
@@ -320,29 +320,30 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info
printf("\n");
nl = 1;
- pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec);
snprintf(t, sizeof(t), "%u", i->owner_module);
snprintf(k, sizeof(k), "%u", i->client);
printf("*** Sink Input #%u ***\n"
"Name: %s\n"
- "Type: %s\n"
+ "Driver: %s\n"
"Owner Module: %s\n"
"Client: %s\n"
"Sink: %u\n"
"Sample Specification: %s\n"
- "Volume: 0x%03x (%0.2f dB)\n"
+ "Channel Map: %s\n"
+ "Volume: %s\n"
"Buffer Latency: %0.0f usec\n"
"Sink Latency: %0.0f usec\n"
"Resample method: %s\n",
i->index,
i->name,
- pa_typeid_to_string(i->_typeid, tid, sizeof(tid)),
+ i->driver,
i->owner_module != PA_INVALID_INDEX ? t : "n/a",
i->client != PA_INVALID_INDEX ? k : "n/a",
i->sink,
- s,
- i->volume, pa_volume_to_dB(i->volume),
+ pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
+ pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
+ pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
(double) i->buffer_usec,
(double) i->sink_usec,
i->resample_method ? i->resample_method : "n/a");
@@ -350,7 +351,7 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info
static void get_source_output_info_callback(pa_context *c, const pa_source_output_info *i, int is_last, void *userdata) {
- char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5];
+ char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
if (is_last < 0) {
fprintf(stderr, "Failed to get source output information: %s\n", pa_strerror(pa_context_errno(c)));
@@ -369,34 +370,36 @@ static void get_source_output_info_callback(pa_context *c, const pa_source_outpu
printf("\n");
nl = 1;
- pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec);
+
snprintf(t, sizeof(t), "%u", i->owner_module);
snprintf(k, sizeof(k), "%u", i->client);
printf("*** Source Output #%u ***\n"
"Name: %s\n"
- "Type: %s\n"
+ "Driver: %s\n"
"Owner Module: %s\n"
"Client: %s\n"
"Source: %u\n"
"Sample Specification: %s\n"
+ "Channel Map: %s\n"
"Buffer Latency: %0.0f usec\n"
"Source Latency: %0.0f usec\n"
"Resample method: %s\n",
i->index,
i->name,
- pa_typeid_to_string(i->_typeid, tid, sizeof(tid)),
+ i->driver,
i->owner_module != PA_INVALID_INDEX ? t : "n/a",
i->client != PA_INVALID_INDEX ? k : "n/a",
i->source,
- s,
+ pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
+ pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
(double) i->buffer_usec,
(double) i->source_usec,
i->resample_method ? i->resample_method : "n/a");
}
static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int is_last, void *userdata) {
- char t[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX];
+ char t[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
if (is_last < 0) {
fprintf(stderr, "Failed to get sample information: %s\n", pa_strerror(pa_context_errno(c)));
@@ -415,21 +418,23 @@ static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int
printf("\n");
nl = 1;
- pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec);
+
pa_bytes_snprint(t, sizeof(t), i->bytes);
printf("*** Sample #%u ***\n"
"Name: %s\n"
- "Volume: 0x%03x (%0.2f dB)\n"
+ "Volume: %s\n"
"Sample Specification: %s\n"
+ "Channel Map: %s\n"
"Duration: %0.1fs\n"
"Size: %s\n"
"Lazy: %s\n"
"Filename: %s\n",
i->index,
i->name,
- i->volume, pa_volume_to_dB(i->volume),
- pa_sample_spec_valid(&i->sample_spec) ? s : "n/a",
+ pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
+ pa_sample_spec_valid(&i->sample_spec) ? pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec) : "n/a",
+ pa_sample_spec_valid(&i->sample_spec) ? pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map) : "n/a",
(double) i->duration/1000000,
t,
i->lazy ? "yes" : "no",
@@ -547,7 +552,7 @@ static void context_state_callback(pa_context *c, void *userdata) {
break;
case UPLOAD_SAMPLE:
- sample_stream = pa_stream_new(c, sample_name, &sample_spec);
+ sample_stream = pa_stream_new(c, sample_name, &sample_spec, NULL);
assert(sample_stream);
pa_stream_set_state_callback(sample_stream, stream_state_callback, NULL);
diff --git a/polyp/paplay.c b/polyp/paplay.c
index d9aa71a6d..ddc1cbc16 100644
--- a/polyp/paplay.c
+++ b/polyp/paplay.c
@@ -155,21 +155,23 @@ static void context_state_callback(pa_context *c, void *userdata) {
case PA_CONTEXT_SETTING_NAME:
break;
- case PA_CONTEXT_READY:
+ case PA_CONTEXT_READY: {
+ pa_cvolume cv;
assert(c && !stream);
if (verbose)
fprintf(stderr, "Connection established.\n");
- stream = pa_stream_new(c, stream_name, &sample_spec);
+ stream = pa_stream_new(c, stream_name, &sample_spec, NULL);
assert(stream);
pa_stream_set_state_callback(stream, stream_state_callback, NULL);
pa_stream_set_write_callback(stream, stream_write_callback, NULL);
- pa_stream_connect_playback(stream, device, NULL, 0, volume);
+ pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume));
break;
+ }
case PA_CONTEXT_TERMINATED:
quit(0);
diff --git a/polyp/parec-simple.c b/polyp/parec-simple.c
index 5f5abe111..524cc4f16 100644
--- a/polyp/parec-simple.c
+++ b/polyp/parec-simple.c
@@ -67,7 +67,7 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) {
int error;
/* Create the recording stream */
- if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, 0, &error))) {
+ if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, &error))) {
fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
goto finish;
}
diff --git a/polyp/parseaddr.h b/polyp/parseaddr.h
index f0efd766a..eff9dd3bd 100644
--- a/polyp/parseaddr.h
+++ b/polyp/parseaddr.h
@@ -29,10 +29,10 @@ typedef enum pa_parsed_address_type {
PA_PARSED_ADDRESS_TCP4,
PA_PARSED_ADDRESS_TCP6,
PA_PARSED_ADDRESS_TCP_AUTO
-} pa_parsed_address_type;
+} pa_parsed_address_type_t;
typedef struct pa_parsed_address {
- pa_parsed_address_type type;
+ pa_parsed_address_type_t type;
char *path_or_host;
uint16_t port;
} pa_parsed_address;
diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c
index c3db14627..e24d44273 100644
--- a/polyp/play-memchunk.c
+++ b/polyp/play-memchunk.c
@@ -33,8 +33,6 @@
#include "xmalloc.h"
#include "gccmacro.h"
-#define PA_TYPEID_MEMCHUNK PA_TYPEID_MAKE('M', 'C', 'N', 'K')
-
static void sink_input_kill(pa_sink_input *i) {
pa_memchunk *c;
assert(i && i->userdata);
@@ -45,7 +43,6 @@ static void sink_input_kill(pa_sink_input *i) {
pa_memblock_unref(c->memblock);
pa_xfree(c);
-
}
static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
@@ -82,24 +79,35 @@ static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t le
pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i);
}
-int pa_play_memchunk(pa_sink *sink, const char *name, const pa_sample_spec *ss, const pa_memchunk *chunk, pa_volume_t volume) {
+int pa_play_memchunk(
+ pa_sink *sink,
+ const char *name,
+ const pa_sample_spec *ss,
+ const pa_channel_map *map,
+ const pa_memchunk *chunk,
+ pa_cvolume *cvolume) {
+
pa_sink_input *si;
pa_memchunk *nchunk;
- assert(sink && chunk);
+ assert(sink);
+ assert(ss);
+ assert(chunk);
- if (volume <= 0)
+ if (cvolume && pa_cvolume_is_muted(cvolume))
return 0;
- if (!(si = pa_sink_input_new(sink, PA_TYPEID_MEMCHUNK, name, ss, 0, -1)))
+ if (!(si = pa_sink_input_new(sink, name, __FILE__, ss, map, 0, PA_RESAMPLER_INVALID)))
return -1;
- si->volume = volume;
+ if (cvolume)
+ si->volume = *cvolume;
+
si->peek = sink_input_peek;
si->drop = sink_input_drop;
si->kill = sink_input_kill;
- si->userdata = nchunk = pa_xmalloc(sizeof(pa_memchunk));
+ si->userdata = nchunk = pa_xnew(pa_memchunk, 1);
*nchunk = *chunk;
pa_memblock_ref(chunk->memblock);
diff --git a/polyp/play-memchunk.h b/polyp/play-memchunk.h
index 247cc8708..fc0654a6f 100644
--- a/polyp/play-memchunk.h
+++ b/polyp/play-memchunk.h
@@ -25,6 +25,12 @@
#include "sink.h"
#include "memchunk.h"
-int pa_play_memchunk(pa_sink *sink, const char *name, const pa_sample_spec *ss, const pa_memchunk *chunk, pa_volume_t volume);
+int pa_play_memchunk(
+ pa_sink *sink,
+ const char *name,
+ const pa_sample_spec *ss,
+ const pa_channel_map *map,
+ const pa_memchunk *chunk,
+ pa_cvolume *cvolume);
#endif
diff --git a/polyp/poll.c b/polyp/poll.c
index 6a260daf0..193fc8128 100644
--- a/polyp/poll.c
+++ b/polyp/poll.c
@@ -1,4 +1,4 @@
-/* $Id: mainloop.c 302 2004-11-21 17:02:25Z lennart $ */
+/* $Id$ */
/***
Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
diff --git a/polyp/poll.h b/polyp/poll.h
index 573f90eac..c201014eb 100644
--- a/polyp/poll.h
+++ b/polyp/poll.h
@@ -1,4 +1,4 @@
-/* $Id: mainloop.c 302 2004-11-21 17:02:25Z lennart $ */
+/* $Id$ */
/***
Compatibility definitions for System V `poll' interface.
diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c
index 0cf324901..15f2e4cd7 100644
--- a/polyp/polyplib-context.c
+++ b/polyp/polyplib-context.c
@@ -187,7 +187,7 @@ void pa_context_unref(pa_context *c) {
context_free(c);
}
-void pa_context_set_state(pa_context *c, pa_context_state st) {
+void pa_context_set_state(pa_context *c, pa_context_state_t st) {
assert(c);
if (c->state == st)
@@ -644,7 +644,7 @@ void pa_context_disconnect(pa_context *c) {
pa_context_set_state(c, PA_CONTEXT_TERMINATED);
}
-pa_context_state pa_context_get_state(pa_context *c) {
+pa_context_state_t pa_context_get_state(pa_context *c) {
assert(c && c->ref >= 1);
return c->state;
}
diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h
index 80c1b6014..febb75f42 100644
--- a/polyp/polyplib-context.h
+++ b/polyp/polyplib-context.h
@@ -75,7 +75,7 @@ int pa_context_errno(pa_context *c);
int pa_context_is_pending(pa_context *c);
/** Return the current context status */
-pa_context_state pa_context_get_state(pa_context *c);
+pa_context_state_t pa_context_get_state(pa_context *c);
/** Connect the context to the specified server. If server is NULL,
connect to the default server. This routine may but will not always
diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h
index 499282c4d..0591ce6c1 100644
--- a/polyp/polyplib-def.h
+++ b/polyp/polyplib-def.h
@@ -43,7 +43,7 @@ typedef enum pa_context_state {
PA_CONTEXT_READY, /**< The connection is established, the context is ready to execute operations */
PA_CONTEXT_FAILED, /**< The connection failed or was disconnected */
PA_CONTEXT_TERMINATED /**< The connection was terminated cleanly */
-} pa_context_state;
+} pa_context_state_t;
/** The state of a stream */
typedef enum pa_stream_state {
@@ -52,14 +52,14 @@ typedef enum pa_stream_state {
PA_STREAM_READY, /**< The stream is established, you may pass audio data to it now */
PA_STREAM_FAILED, /**< An error occured that made the stream invalid */
PA_STREAM_TERMINATED /**< The stream has been terminated cleanly */
-} pa_stream_state;
+} pa_stream_state_t;
/** The state of an operation */
typedef enum pa_operation_state {
PA_OPERATION_RUNNING, /**< The operation is still running */
PA_OPERATION_DONE, /**< The operation has been completed */
PA_OPERATION_CANCELED /**< The operation has been canceled */
-} pa_operation_state;
+} pa_operation_state_t;
/** An invalid index */
#define PA_INVALID_INDEX ((uint32_t) -1)
@@ -70,7 +70,7 @@ typedef enum pa_stream_direction {
PA_STREAM_PLAYBACK, /**< Playback stream */
PA_STREAM_RECORD, /**< Record stream */
PA_STREAM_UPLOAD /**< Sample upload stream */
-} pa_stream_direction;
+} pa_stream_direction_t;
/** Some special flags for stream connections. \since 0.6 */
typedef enum pa_stream_flags {
@@ -90,7 +90,7 @@ typedef enum pa_stream_flags {
* information. This is
* especially useful on long latency
* network connections. */
-} pa_stream_flags;
+} pa_stream_flags_t;
/** Playback and record buffer metrics */
typedef struct pa_buffer_attr {
@@ -133,7 +133,7 @@ typedef enum pa_subscription_mask {
PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64, /**< Sample cache events */
PA_SUBSCRIPTION_MASK_SERVER = 128, /**< Other global server changes. \since 0.4 */
PA_SUBSCRIPTION_MASK_AUTOLOAD = 256 /**< Autoload table events. \since 0.5 */
-} pa_subscription_mask;
+} pa_subscription_mask_t;
/** Subscription event types, as used by pa_context_subscribe() */
typedef enum pa_subscription_event_type {
@@ -152,7 +152,7 @@ typedef enum pa_subscription_event_type {
PA_SUBSCRIPTION_EVENT_CHANGE = 16, /**< A property of the object was modified */
PA_SUBSCRIPTION_EVENT_REMOVE = 32, /**< An object was removed */
PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32 /**< A mask to extract the event operation from an event value */
-} pa_subscription_event_type;
+} pa_subscription_event_type_t;
/** Return one if an event type t matches an event mask bitfield */
#define pa_subscription_match_flags(m, t) (!!((m) & (1 << ((t) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK))))
diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h
index 09f9473ac..295960695 100644
--- a/polyp/polyplib-internal.h
+++ b/polyp/polyplib-internal.h
@@ -55,12 +55,12 @@ struct pa_context {
uint32_t ctag;
uint32_t error;
- pa_context_state state;
+ pa_context_state_t state;
void (*state_callback)(pa_context*c, void *userdata);
void *state_userdata;
- void (*subscribe_callback)(pa_context *c, pa_subscription_event_type t, uint32_t idx, void *userdata);
+ void (*subscribe_callback)(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata);
void *subscribe_userdata;
pa_memblock_stat *memblock_stat;
@@ -86,15 +86,16 @@ struct pa_stream {
char *name;
pa_buffer_attr buffer_attr;
pa_sample_spec sample_spec;
+ pa_channel_map channel_map;
uint32_t channel;
int channel_valid;
uint32_t device_index;
- pa_stream_direction direction;
+ pa_stream_direction_t direction;
uint32_t requested_bytes;
uint64_t counter;
pa_usec_t previous_time;
pa_usec_t previous_ipol_time;
- pa_stream_state state;
+ pa_stream_state_t state;
pa_mcalign *mcalign;
int interpolate;
@@ -123,7 +124,7 @@ struct pa_operation {
pa_stream *stream;
PA_LLIST_FIELDS(pa_operation);
- pa_operation_state state;
+ pa_operation_state_t state;
void *userdata;
pa_operation_callback callback;
};
@@ -141,11 +142,11 @@ void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t
void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
void pa_context_fail(pa_context *c, int error);
-void pa_context_set_state(pa_context *c, pa_context_state st);
+void pa_context_set_state(pa_context *c, pa_context_state_t st);
int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t);
pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, void (*internal_callback)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata), void (*cb)(void), void *userdata);
-void pa_stream_set_state(pa_stream *s, pa_stream_state st);
+void pa_stream_set_state(pa_stream *s, pa_stream_state_t st);
void pa_stream_trash_ipol(pa_stream *s);
diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c
index 911059690..8c0c4449b 100644
--- a/polyp/polyplib-introspect.c
+++ b/polyp/polyplib-introspect.c
@@ -128,12 +128,13 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P
pa_tagstruct_gets(t, &i.name) < 0 ||
pa_tagstruct_gets(t, &i.description) < 0 ||
pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
+ pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
+ pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
pa_tagstruct_get_usec(t, &i.latency) < 0 ||
- pa_tagstruct_getu32(t, &i._typeid) < 0) {
+ pa_tagstruct_gets(t, &i.driver) < 0) {
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
goto finish;
@@ -223,11 +224,12 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
pa_tagstruct_gets(t, &i.name) < 0 ||
pa_tagstruct_gets(t, &i.description) < 0 ||
pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
+ pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 ||
pa_tagstruct_get_usec(t, &i.latency) < 0 ||
- pa_tagstruct_getu32(t, &i._typeid) < 0) {
+ pa_tagstruct_gets(t, &i.driver) < 0) {
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
goto finish;
@@ -316,7 +318,7 @@ static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command,
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
pa_tagstruct_gets(t, &i.name) < 0 ||
pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i._typeid) < 0 ) {
+ pa_tagstruct_gets(t, &i.driver) < 0 ) {
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
goto finish;
}
@@ -452,11 +454,12 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm
pa_tagstruct_getu32(t, &i.client) < 0 ||
pa_tagstruct_getu32(t, &i.sink) < 0 ||
pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
+ pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
+ pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 ||
pa_tagstruct_get_usec(t, &i.sink_usec) < 0 ||
pa_tagstruct_gets(t, &i.resample_method) < 0 ||
- pa_tagstruct_getu32(t, &i._typeid) < 0) {
+ pa_tagstruct_gets(t, &i.driver) < 0) {
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
goto finish;
@@ -526,10 +529,11 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c
pa_tagstruct_getu32(t, &i.client) < 0 ||
pa_tagstruct_getu32(t, &i.source) < 0 ||
pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
+ pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 ||
pa_tagstruct_get_usec(t, &i.source_usec) < 0 ||
pa_tagstruct_gets(t, &i.resample_method) < 0 ||
- pa_tagstruct_getu32(t, &i._typeid) < 0) {
+ pa_tagstruct_gets(t, &i.driver) < 0) {
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
goto finish;
@@ -662,9 +666,10 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command,
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
+ pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
pa_tagstruct_get_usec(t, &i.duration) < 0 ||
pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
+ pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
pa_tagstruct_getu32(t, &i.bytes) < 0 ||
pa_tagstruct_get_boolean(t, &i.lazy) < 0 ||
pa_tagstruct_gets(t, &i.filename) < 0) {
@@ -861,7 +866,7 @@ finish:
pa_operation_unref(o);
}
-pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata) {
+pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata) {
pa_tagstruct *t;
pa_operation *o;
uint32_t tag;
@@ -933,8 +938,7 @@ finish:
pa_operation_unref(o);
}
-
-pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type type, const char *module, const char*argument, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) {
+pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) {
pa_operation *o;
pa_tagstruct *t;
uint32_t tag;
@@ -957,7 +961,7 @@ pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autolo
return pa_operation_ref(o);
}
-pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) {
+pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) {
pa_operation *o;
pa_tagstruct *t;
uint32_t tag;
diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h
index 2848e22f9..10e6d0e38 100644
--- a/polyp/polyplib-introspect.h
+++ b/polyp/polyplib-introspect.h
@@ -27,7 +27,8 @@
#include <polyp/polyplib-operation.h>
#include <polyp/polyplib-context.h>
#include <polyp/cdecl.h>
-#include <polyp/typeid.h>
+#include <polyp/channelmap.h>
+#include <polyp/volume.h>
/** \file
*
@@ -52,13 +53,14 @@ typedef struct pa_sink_info {
const char *name; /**< Name of the sink */
uint32_t index; /**< Index of the sink */
const char *description; /**< Description of this sink */
- pa_sample_spec sample_spec; /**< Sample spec of this sink */
+ pa_sample_spec sample_spec; /**< Sample spec of this sink */
+ pa_channel_map channel_map; /**< Channel map \since 0.9 */
uint32_t owner_module; /**< Index of the owning module of this sink, or PA_INVALID_INDEX */
- pa_volume_t volume; /**< Volume of the sink */
+ pa_cvolume volume; /**< Volume of the sink */
uint32_t monitor_source; /**< Index of the monitor source connected to this sink */
const char *monitor_source_name; /**< The name of the monitor source */
pa_usec_t latency; /**< Length of filled playback buffer of this sink */
- pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */
+ const char *driver; /**< Driver name. \since 0.9 */
} pa_sink_info;
/** Get information about a sink by its name */
@@ -75,12 +77,13 @@ typedef struct pa_source_info {
const char *name ; /**< Name of the source */
uint32_t index; /**< Index of the source */
const char *description; /**< Description of this source */
- pa_sample_spec sample_spec; /**< Sample spec of this source */
+ pa_sample_spec sample_spec; /**< Sample spec of this source */
+ pa_channel_map channel_map; /**< Channel map \since 0.9 */
uint32_t owner_module; /**< Owning module index, or PA_INVALID_INDEX */
uint32_t monitor_of_sink; /**< If this is a monitor source the index of the owning sink, otherwise PA_INVALID_INDEX */
const char *monitor_of_sink_name; /**< Name of the owning sink, or PA_INVALID_INDEX */
pa_usec_t latency; /**< Length of filled record buffer of this source. \since 0.5 */
- pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */
+ const char *driver; /**< Driver name \since 0.9 */
} pa_source_info;
/** Get information about a source by its name */
@@ -98,7 +101,7 @@ typedef struct pa_server_info {
const char *host_name; /**< Host name the daemon is running on */
const char *server_version; /**< Version string of the daemon */
const char *server_name; /**< Server package name (usually "polypaudio") */
- pa_sample_spec sample_spec; /**< Default sample specification */
+ pa_sample_spec sample_spec; /**< Default sample specification */
const char *default_sink_name; /**< Name of default sink. \since 0.4 */
const char *default_source_name; /**< Name of default sink. \since 0.4*/
uint32_t cookie; /**< A random cookie for identifying this instance of polypaudio. \since 0.8 */
@@ -127,7 +130,7 @@ typedef struct pa_client_info {
uint32_t index; /**< Index of this client */
const char *name; /**< Name of this client */
uint32_t owner_module; /**< Index of the owning module, or PA_INVALID_INDEX */
- pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */
+ const char *driver; /**< Driver name \since 0.9 */
} pa_client_info;
/** Get information about a client by its index */
@@ -143,12 +146,13 @@ typedef struct pa_sink_input_info {
uint32_t owner_module; /**< Index of the module this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any module */
uint32_t client; /**< Index of the client this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any client */
uint32_t sink; /**< Index of the connected sink */
- pa_sample_spec sample_spec; /**< The sample specification of the sink input */
- pa_volume_t volume; /**< The volume of this sink input */
+ pa_sample_spec sample_spec; /**< The sample specification of the sink input */
+ pa_channel_map channel_map; /**< Channel map */
+ pa_cvolume volume; /**< The volume of this sink input */
pa_usec_t buffer_usec; /**< Latency due to buffering in sink input, see pa_latency_info for details */
pa_usec_t sink_usec; /**< Latency of the sink device, see pa_latency_info for details */
const char *resample_method; /**< Thre resampling method used by this sink input. \since 0.7 */
- pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */
+ const char *driver; /**< Driver name \since 0.9 */
} pa_sink_input_info;
/** Get some information about a sink input by its index */
@@ -164,11 +168,12 @@ typedef struct pa_source_output_info {
uint32_t owner_module; /**< Index of the module this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any module */
uint32_t client; /**< Index of the client this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any client */
uint32_t source; /**< Index of the connected source */
- pa_sample_spec sample_spec; /**< The sample specification of the source output */
+ pa_sample_spec sample_spec; /**< The sample specification of the source output */
+ pa_channel_map channel_map; /**< Channel map */
pa_usec_t buffer_usec; /**< Latency due to buffering in the source output, see pa_latency_info for details. \since 0.5 */
pa_usec_t source_usec; /**< Latency of the source device, see pa_latency_info for details. \since 0.5 */
const char *resample_method; /**< Thre resampling method used by this source output. \since 0.7 */
- pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */
+ const char *driver; /**< Driver name \since 0.9 */
} pa_source_output_info;
/** Get information about a source output by its index */
@@ -202,8 +207,9 @@ pa_operation* pa_context_stat(pa_context *c, void (*cb)(pa_context *c, const pa_
typedef struct pa_sample_info {
uint32_t index; /**< Index of this entry */
const char *name; /**< Name of this entry */
- pa_volume_t volume; /**< Default volume of this entry */
- pa_sample_spec sample_spec; /**< Sample specification of the sampel */
+ pa_cvolume volume; /**< Default volume of this entry */
+ pa_sample_spec sample_spec; /**< Sample specification of the sample */
+ pa_channel_map channel_map; /**< The channel map */
pa_usec_t duration; /**< Duration of this entry */
uint32_t bytes; /**< Length of this sample in bytes. \since 0.4 */
int lazy; /**< Non-zero when this is a lazy cache entry. \since 0.5 */
@@ -238,19 +244,19 @@ pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, void (*cb)(p
typedef enum pa_autoload_type {
PA_AUTOLOAD_SINK = 0,
PA_AUTOLOAD_SOURCE = 1
-} pa_autoload_type;
+} pa_autoload_type_t;
/** Stores information about autoload entries. \since 0.5 */
typedef struct pa_autoload_info {
uint32_t index; /**< Index of this autoload entry */
const char *name; /**< Name of the sink or source */
- pa_autoload_type type; /**< Type of the autoload entry */
+ pa_autoload_type_t type; /**< Type of the autoload entry */
const char *module; /**< Module name to load */
const char *argument; /**< Argument string for module */
} pa_autoload_info;
/** Get info about a specific autoload entry. \since 0.6 */
-pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata);
+pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata);
/** Get info about a specific autoload entry. \since 0.6 */
pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata);
@@ -259,10 +265,10 @@ pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx,
pa_operation* pa_context_get_autoload_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata);
/** Add a new autoload entry. \since 0.5 */
-pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type type, const char *module, const char*argument, void (*cb)(pa_context *c, int idx, void *userdata), void* userdata);
+pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, void (*cb)(pa_context *c, int idx, void *userdata), void* userdata);
/** Remove an autoload entry. \since 0.6 */
-pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata);
+pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata);
/** Remove an autoload entry. \since 0.6 */
pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void* userdata);
diff --git a/polyp/polyplib-operation.c b/polyp/polyplib-operation.c
index 3bee8cc72..68bc8c6a1 100644
--- a/polyp/polyplib-operation.c
+++ b/polyp/polyplib-operation.c
@@ -62,7 +62,7 @@ void pa_operation_unref(pa_operation *o) {
}
}
-static void operation_set_state(pa_operation *o, pa_operation_state st) {
+static void operation_set_state(pa_operation *o, pa_operation_state_t st) {
assert(o && o->ref >= 1);
if (st == o->state)
@@ -97,7 +97,7 @@ void pa_operation_done(pa_operation *o) {
operation_set_state(o, PA_OPERATION_DONE);
}
-pa_operation_state pa_operation_get_state(pa_operation *o) {
+pa_operation_state_t pa_operation_get_state(pa_operation *o) {
assert(o && o->ref >= 1);
return o->state;
}
diff --git a/polyp/polyplib-operation.h b/polyp/polyplib-operation.h
index 63dcbc9fb..cac03e30b 100644
--- a/polyp/polyplib-operation.h
+++ b/polyp/polyplib-operation.h
@@ -44,7 +44,7 @@ void pa_operation_unref(pa_operation *o);
void pa_operation_cancel(pa_operation *o);
/** Return the current status of the operation */
-pa_operation_state pa_operation_get_state(pa_operation *o);
+pa_operation_state_t pa_operation_get_state(pa_operation *o);
PA_C_DECL_END
diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c
index b13571289..e55121529 100644
--- a/polyp/polyplib-simple.c
+++ b/polyp/polyplib-simple.c
@@ -39,7 +39,7 @@ struct pa_simple {
pa_mainloop *mainloop;
pa_context *context;
pa_stream *stream;
- pa_stream_direction direction;
+ pa_stream_direction_t direction;
int dead;
@@ -51,8 +51,8 @@ struct pa_simple {
static void read_callback(pa_stream *s, const void*data, size_t length, void *userdata);
static int check_error(pa_simple *p, int *rerror) {
- pa_context_state cst;
- pa_stream_state sst;
+ pa_context_state_t cst;
+ pa_stream_state_t sst;
assert(p);
if ((cst = pa_context_get_state(p->context)) == PA_CONTEXT_FAILED)
@@ -118,12 +118,11 @@ static int iterate(pa_simple *p, int block, int *rerror) {
pa_simple* pa_simple_new(
const char *server,
const char *name,
- pa_stream_direction dir,
+ pa_stream_direction_t dir,
const char *dev,
const char *stream_name,
const pa_sample_spec *ss,
const pa_buffer_attr *attr,
- pa_volume_t volume,
int *rerror) {
pa_simple *p;
@@ -152,11 +151,11 @@ pa_simple* pa_simple_new(
goto fail;
}
- if (!(p->stream = pa_stream_new(p->context, stream_name, ss)))
+ if (!(p->stream = pa_stream_new(p->context, stream_name, ss, NULL)))
goto fail;
if (dir == PA_STREAM_PLAYBACK)
- pa_stream_connect_playback(p->stream, dev, attr, 0, volume);
+ pa_stream_connect_playback(p->stream, dev, attr, 0, NULL);
else
pa_stream_connect_record(p->stream, dev, attr, 0);
diff --git a/polyp/polyplib-simple.h b/polyp/polyplib-simple.h
index d15891159..0c80f460e 100644
--- a/polyp/polyplib-simple.h
+++ b/polyp/polyplib-simple.h
@@ -49,12 +49,11 @@ typedef struct pa_simple pa_simple;
pa_simple* pa_simple_new(
const char *server, /**< Server name, or NULL for default */
const char *name, /**< A descriptive name for this client (application name, ...) */
- pa_stream_direction dir, /**< Open this stream for recording or playback? */
+ pa_stream_direction_t dir, /**< Open this stream for recording or playback? */
const char *dev, /**< Sink (resp. source) name, or NULL for default */
const char *stream_name, /**< A descriptive name for this client (application name, song title, ...) */
const pa_sample_spec *ss, /**< The sample type to use */
const pa_buffer_attr *attr, /**< Buffering attributes, or NULL for default */
- pa_volume_t volume, /**< Initial volume. Only for playback streams. \since 0.5 */
int *error /**< A pointer where the error code is stored when the routine returns NULL. It is OK to pass NULL here. */
);
diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c
index 6c8ed9c5d..51ee6a225 100644
--- a/polyp/polyplib-stream.c
+++ b/polyp/polyplib-stream.c
@@ -36,11 +36,18 @@
#define LATENCY_IPOL_INTERVAL_USEC (10000L)
-pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss) {
+pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) {
pa_stream *s;
- assert(c && ss);
+ assert(c);
+ assert(ss);
- s = pa_xmalloc(sizeof(pa_stream));
+ if (!pa_sample_spec_valid(ss))
+ return NULL;
+
+ if (map && !pa_channel_map_valid(map))
+ return NULL;
+
+ s = pa_xnew(pa_stream, 1);
s->ref = 1;
s->context = c;
s->mainloop = c->mainloop;
@@ -55,6 +62,12 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *
s->direction = PA_STREAM_NODIRECTION;
s->name = pa_xstrdup(name);
s->sample_spec = *ss;
+
+ if (map)
+ s->channel_map = *map;
+ else
+ pa_channel_map_init_auto(&s->channel_map, ss->channels);
+
s->channel = 0;
s->channel_valid = 0;
s->device_index = PA_INVALID_INDEX;
@@ -108,7 +121,7 @@ pa_stream* pa_stream_ref(pa_stream *s) {
return s;
}
-pa_stream_state pa_stream_get_state(pa_stream *s) {
+pa_stream_state_t pa_stream_get_state(pa_stream *s) {
assert(s && s->ref >= 1);
return s->state;
}
@@ -123,7 +136,7 @@ uint32_t pa_stream_get_index(pa_stream *s) {
return s->device_index;
}
-void pa_stream_set_state(pa_stream *s, pa_stream_state st) {
+void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) {
assert(s && s->ref >= 1);
if (s->state == st)
@@ -271,7 +284,7 @@ finish:
pa_stream_unref(s);
}
-static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags, pa_volume_t volume) {
+static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags_t flags, const pa_cvolume *volume) {
pa_tagstruct *t;
uint32_t tag;
assert(s && s->ref >= 1 && s->state == PA_STREAM_DISCONNECTED);
@@ -308,15 +321,23 @@ static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *a
pa_tagstruct_putu32(t, tag = s->context->ctag++);
pa_tagstruct_puts(t, s->name);
pa_tagstruct_put_sample_spec(t, &s->sample_spec);
+ pa_tagstruct_put_channel_map(t, &s->channel_map);
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
pa_tagstruct_puts(t, dev);
pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
pa_tagstruct_put_boolean(t, !!(flags & PA_STREAM_START_CORKED));
if (s->direction == PA_STREAM_PLAYBACK) {
+ pa_cvolume cv;
pa_tagstruct_putu32(t, s->buffer_attr.tlength);
pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- pa_tagstruct_putu32(t, volume);
+
+ if (!volume) {
+ pa_cvolume_reset(&cv, s->sample_spec.channels);
+ volume = &cv;
+ }
+
+ pa_tagstruct_put_cvolume(t, volume);
} else
pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
@@ -326,13 +347,13 @@ static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *a
pa_stream_unref(s);
}
-void pa_stream_connect_playback(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags, pa_volume_t volume) {
+void pa_stream_connect_playback(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags_t flags, pa_cvolume *volume) {
assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1);
s->direction = PA_STREAM_PLAYBACK;
create_stream(s, dev, attr, flags, volume);
}
-void pa_stream_connect_record(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags) {
+void pa_stream_connect_record(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags_t flags) {
assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1);
s->direction = PA_STREAM_RECORD;
create_stream(s, dev, attr, flags, 0);
diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h
index 806579f57..bc828b71c 100644
--- a/polyp/polyplib-stream.h
+++ b/polyp/polyplib-stream.h
@@ -25,6 +25,8 @@
#include <sys/types.h>
#include <polyp/sample.h>
+#include <polyp/channelmap.h>
+#include <polyp/volume.h>
#include <polyp/polyplib-def.h>
#include <polyp/cdecl.h>
#include <polyp/polyplib-operation.h>
@@ -39,7 +41,7 @@ PA_C_DECL_BEGIN
typedef struct pa_stream pa_stream;
/** Create a new, unconnected stream with the specified name and sample type */
-pa_stream* pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss);
+pa_stream* pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map);
/** Decrease the reference counter by one */
void pa_stream_unref(pa_stream *s);
@@ -48,7 +50,7 @@ void pa_stream_unref(pa_stream *s);
pa_stream *pa_stream_ref(pa_stream *s);
/** Return the current state of the stream */
-pa_stream_state pa_stream_get_state(pa_stream *p);
+pa_stream_state_t pa_stream_get_state(pa_stream *p);
/** Return the context this stream is attached to */
pa_context* pa_stream_get_context(pa_stream *p);
@@ -57,10 +59,19 @@ pa_context* pa_stream_get_context(pa_stream *p);
uint32_t pa_stream_get_index(pa_stream *s);
/** Connect the stream to a sink */
-void pa_stream_connect_playback(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags, pa_volume_t volume);
+void pa_stream_connect_playback(
+ pa_stream *s,
+ const char *dev,
+ const pa_buffer_attr *attr,
+ pa_stream_flags_t flags,
+ pa_cvolume *volume);
/** Connect the stream to a source */
-void pa_stream_connect_record(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags);
+void pa_stream_connect_record(
+ pa_stream *s,
+ const char *dev,
+ const pa_buffer_attr *attr,
+ pa_stream_flags_t flags);
/** Disconnect a stream from a source/sink */
void pa_stream_disconnect(pa_stream *s);
diff --git a/polyp/polyplib-subscribe.c b/polyp/polyplib-subscribe.c
index 69ae588fb..ef90ab0b6 100644
--- a/polyp/polyplib-subscribe.c
+++ b/polyp/polyplib-subscribe.c
@@ -33,7 +33,7 @@
void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_context *c = userdata;
- pa_subscription_event_type e;
+ pa_subscription_event_type_t e;
uint32_t index;
assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
@@ -54,7 +54,7 @@ finish:
}
-pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) {
+pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) {
pa_operation *o;
pa_tagstruct *t;
uint32_t tag;
@@ -74,7 +74,7 @@ pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask m, void (
return pa_operation_ref(o);
}
-void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
+void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata) {
assert(c);
c->subscribe_callback = cb;
c->subscribe_userdata = userdata;
diff --git a/polyp/polyplib-subscribe.h b/polyp/polyplib-subscribe.h
index f2760ee63..920c98533 100644
--- a/polyp/polyplib-subscribe.h
+++ b/polyp/polyplib-subscribe.h
@@ -37,10 +37,10 @@
PA_C_DECL_BEGIN
/** Enable event notification */
-pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata);
+pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata);
/** Set the context specific call back function that is called whenever the state of the daemon changes */
-void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
+void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata);
PA_C_DECL_END
diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c
index a97bc25ce..ce183a6f4 100644
--- a/polyp/protocol-esound.c
+++ b/polyp/protocol-esound.c
@@ -64,8 +64,6 @@
#define SCACHE_PREFIX "esound."
-#define PA_TYPEID_ESOUND PA_TYPEID_MAKE('E', 'S', 'D', 'P')
-
/* This is heavily based on esound's code */
struct connection {
@@ -326,7 +324,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t
assert(!c->sink_input && !c->input_memblockq);
- if (!(c->sink_input = pa_sink_input_new(sink, PA_TYPEID_ESOUND, name, &ss, 0, -1))) {
+ if (!(c->sink_input = pa_sink_input_new(sink, __FILE__, name, &ss, NULL, 0, -1))) {
pa_log(__FILE__": failed to create sink input.\n");
return -1;
}
@@ -398,7 +396,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co
assert(!c->output_memblockq && !c->source_output);
- if (!(c->source_output = pa_source_output_new(source, PA_TYPEID_ESOUND, name, &ss, -1))) {
+ if (!(c->source_output = pa_source_output_new(source, __FILE__, name, &ss, NULL, -1))) {
pa_log(__FILE__": failed to create source output\n");
return -1;
}
@@ -476,7 +474,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
assert(k);
for (conn = pa_idxset_first(c->protocol->connections, &idx); conn; conn = pa_idxset_next(c->protocol->connections, &idx)) {
- int format = ESD_BITS16 | ESD_STEREO, rate = 44100, volume = 0xFF;
+ int format = ESD_BITS16 | ESD_STEREO, rate = 44100, lvolume = 0xFF, rvolume = 0xFF;
if (conn->state != ESD_STREAMING_DATA)
continue;
@@ -485,7 +483,8 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
if (conn->sink_input) {
rate = conn->sink_input->sample_spec.rate;
- volume = (conn->sink_input->volume*0xFF)/0x100;
+ lvolume = (conn->sink_input->volume.values[0]*0xFF)/0x100;
+ rvolume = (conn->sink_input->volume.values[1]*0xFF)/0x100;
format = format_native2esd(&conn->sink_input->sample_spec);
}
@@ -503,11 +502,11 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
response += sizeof(int);
/* left */
- *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, volume);
+ *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, lvolume);
response += sizeof(int);
/*right*/
- *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, volume);
+ *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, rvolume);
response += sizeof(int);
/*format*/
@@ -545,11 +544,11 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
response += sizeof(int);
/* left */
- *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume*0xFF)/0x100);
+ *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume.values[0]*0xFF)/0x100);
response += sizeof(int);
/*right*/
- *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume*0xFF)/0x100);
+ *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume.values[0]*0xFF)/0x100);
response += sizeof(int);
/*format*/
@@ -572,20 +571,25 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
int *ok;
- uint32_t idx, volume;
+ uint32_t idx;
+ pa_volume_t lvolume, rvolume;
struct connection *conn;
assert(c && data && length == sizeof(int)*3);
idx = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *(const int*)data)-1;
- volume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 1));
- volume = (volume*0x100)/0xFF;
+ lvolume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 1));
+ lvolume = (lvolume*0x100)/0xFF;
+ rvolume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 2));
+ rvolume = (rvolume*0x100)/0xFF;
ok = connection_write(c, sizeof(int));
assert(ok);
if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx))) {
assert(conn->sink_input);
- conn->sink_input->volume = volume;
+ conn->sink_input->volume.values[0] = lvolume;
+ conn->sink_input->volume.values[1] = rvolume;
+ conn->sink_input->volume.channels = 2;
*ok = 1;
} else
*ok = 0;
@@ -627,7 +631,7 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_
c->state = ESD_CACHING_SAMPLE;
- pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, &idx);
+ pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, NULL, &idx);
ok = connection_write(c, sizeof(int));
assert(ok);
@@ -676,7 +680,7 @@ static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t reque
pa_sink *sink;
if ((sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1)))
- if (pa_scache_play_item(c->protocol->core, name, sink, PA_VOLUME_NORM) >= 0)
+ if (pa_scache_play_item(c->protocol->core, name, sink, NULL) >= 0)
*ok = (int) idx+1;
} else {
assert(request == ESD_PROTO_SAMPLE_FREE);
@@ -801,7 +805,7 @@ static int do_read(struct connection *c) {
int *ok;
c->scache.memchunk.index = 0;
- pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, &c->scache.memchunk, &idx);
+ pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, NULL, &c->scache.memchunk, &idx);
pa_memblock_unref(c->scache.memchunk.memblock);
c->scache.memchunk.memblock = NULL;
@@ -1067,7 +1071,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname));
assert(p->core);
- c->client = pa_client_new(p->core, PA_TYPEID_ESOUND, cname);
+ c->client = pa_client_new(p->core, __FILE__, cname);
assert(c->client);
c->client->owner = p->module;
c->client->kill = client_kill_cb;
diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c
index b19d30d93..0491dc411 100644
--- a/polyp/protocol-native.c
+++ b/polyp/protocol-native.c
@@ -56,8 +56,6 @@
/* Don't accept more connection than this */
#define MAX_CONNECTIONS 10
-#define PA_TYPEID_NATIVE PA_TYPEID_MAKE('N', 'A', 'T', 'V')
-
struct connection;
struct pa_protocol_native;
@@ -88,6 +86,7 @@ struct upload_stream {
size_t length;
char *name;
pa_sample_spec sample_spec;
+ pa_channel_map channel_map;
};
struct output_stream {
@@ -235,7 +234,12 @@ static const pa_pdispatch_callback command_table[PA_COMMAND_MAX] = {
/* structure management */
-static struct upload_stream* upload_stream_new(struct connection *c, const pa_sample_spec *ss, const char *name, size_t length) {
+static struct upload_stream* upload_stream_new(
+ struct connection *c,
+ const pa_sample_spec *ss,
+ const pa_channel_map *map,
+ const char *name, size_t length) {
+
struct upload_stream *s;
assert(c && ss && name && length);
@@ -243,6 +247,7 @@ static struct upload_stream* upload_stream_new(struct connection *c, const pa_sa
s->type = UPLOAD_STREAM;
s->connection = c;
s->sample_spec = *ss;
+ s->channel_map = *map;
s->name = pa_xstrdup(name);
s->memchunk.memblock = NULL;
@@ -268,13 +273,21 @@ static void upload_stream_free(struct upload_stream *o) {
pa_xfree(o);
}
-static struct record_stream* record_stream_new(struct connection *c, pa_source *source, const pa_sample_spec *ss, const char *name, size_t maxlength, size_t fragment_size) {
+static struct record_stream* record_stream_new(
+ struct connection *c,
+ pa_source *source,
+ const pa_sample_spec *ss,
+ const pa_channel_map *map,
+ const char *name,
+ size_t maxlength,
+ size_t fragment_size) {
+
struct record_stream *s;
pa_source_output *source_output;
size_t base;
assert(c && source && ss && name && maxlength);
- if (!(source_output = pa_source_output_new(source, PA_TYPEID_NATIVE, name, ss, -1)))
+ if (!(source_output = pa_source_output_new(source, __FILE__, name, ss, map, -1)))
return NULL;
s = pa_xmalloc(sizeof(struct record_stream));
@@ -308,17 +321,23 @@ static void record_stream_free(struct record_stream* r) {
pa_xfree(r);
}
-static struct playback_stream* playback_stream_new(struct connection *c, pa_sink *sink, const pa_sample_spec *ss, const char *name,
- size_t maxlength,
- size_t tlength,
- size_t prebuf,
- size_t minreq,
- pa_volume_t volume) {
+static struct playback_stream* playback_stream_new(
+ struct connection *c,
+ pa_sink *sink,
+ const pa_sample_spec *ss,
+ const pa_channel_map *map,
+ const char *name,
+ size_t maxlength,
+ size_t tlength,
+ size_t prebuf,
+ size_t minreq,
+ pa_cvolume *volume) {
+
struct playback_stream *s;
pa_sink_input *sink_input;
assert(c && sink && ss && name && maxlength);
- if (!(sink_input = pa_sink_input_new(sink, PA_TYPEID_NATIVE, name, ss, 0, -1)))
+ if (!(sink_input = pa_sink_input_new(sink, __FILE__, name, ss, map, 0, -1)))
return NULL;
s = pa_xmalloc(sizeof(struct playback_stream));
@@ -340,7 +359,7 @@ static struct playback_stream* playback_stream_new(struct connection *c, pa_sink
s->requested_bytes = 0;
s->drain_request = 0;
- s->sink_input->volume = volume;
+ s->sink_input->volume = *volume;
pa_idxset_put(c->output_streams, s, &s->index);
return s;
@@ -561,14 +580,17 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
uint32_t sink_index;
const char *name, *sink_name;
pa_sample_spec ss;
+ pa_channel_map map;
pa_tagstruct *reply;
pa_sink *sink;
- pa_volume_t volume;
+ pa_cvolume volume;
int corked;
+
assert(c && t && c->protocol && c->protocol->core);
if (pa_tagstruct_gets(t, &name) < 0 || !name ||
pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
+ pa_tagstruct_get_channel_map(t, &map) < 0 ||
pa_tagstruct_getu32(t, &sink_index) < 0 ||
pa_tagstruct_gets(t, &sink_name) < 0 ||
pa_tagstruct_getu32(t, &maxlength) < 0 ||
@@ -576,13 +598,12 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
pa_tagstruct_getu32(t, &tlength) < 0 ||
pa_tagstruct_getu32(t, &prebuf) < 0 ||
pa_tagstruct_getu32(t, &minreq) < 0 ||
- pa_tagstruct_getu32(t, &volume) < 0 ||
+ pa_tagstruct_get_cvolume(t, &volume) < 0 ||
!pa_tagstruct_eof(t)) {
protocol_error(c);
return;
}
-
if (!c->authorized) {
pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
return;
@@ -599,7 +620,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
return;
}
- if (!(s = playback_stream_new(c, sink, &ss, name, maxlength, tlength, prebuf, minreq, volume))) {
+ if (!(s = playback_stream_new(c, sink, &ss, &map, name, maxlength, tlength, prebuf, minreq, &volume))) {
pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID);
return;
}
@@ -671,6 +692,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
uint32_t source_index;
const char *name, *source_name;
pa_sample_spec ss;
+ pa_channel_map map;
pa_tagstruct *reply;
pa_source *source;
int corked;
@@ -678,6 +700,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
if (pa_tagstruct_gets(t, &name) < 0 || !name ||
pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
+ pa_tagstruct_get_channel_map(t, &map) < 0 ||
pa_tagstruct_getu32(t, &source_index) < 0 ||
pa_tagstruct_gets(t, &source_name) < 0 ||
pa_tagstruct_getu32(t, &maxlength) < 0 ||
@@ -703,7 +726,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
return;
}
- if (!(s = record_stream_new(c, source, &ss, name, maxlength, fragment_size))) {
+ if (!(s = record_stream_new(c, source, &ss, &map, name, maxlength, fragment_size))) {
pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID);
return;
}
@@ -984,11 +1007,13 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
size_t length;
const char *name;
pa_sample_spec ss;
+ pa_channel_map map;
pa_tagstruct *reply;
assert(c && t && c->protocol && c->protocol->core);
if (pa_tagstruct_gets(t, &name) < 0 || !name ||
pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
+ pa_tagstruct_get_channel_map(t, &map) < 0 ||
pa_tagstruct_getu32(t, &length) < 0 ||
!pa_tagstruct_eof(t)) {
protocol_error(c);
@@ -1005,7 +1030,7 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
return;
}
- if (!(s = upload_stream_new(c, &ss, name, length))) {
+ if (!(s = upload_stream_new(c, &ss, &map, name, length))) {
pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID);
return;
}
@@ -1042,21 +1067,22 @@ static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
return;
}
- pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->memchunk, &idx);
+ pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, &idx);
pa_pstream_send_simple_ack(c->pstream, tag);
upload_stream_free(s);
}
static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
struct connection *c = userdata;
- uint32_t sink_index, volume;
+ uint32_t sink_index;
+ pa_cvolume volume;
pa_sink *sink;
const char *name, *sink_name;
assert(c && t);
if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
pa_tagstruct_gets(t, &sink_name) < 0 ||
- pa_tagstruct_getu32(t, &volume) < 0 ||
+ pa_tagstruct_get_cvolume(t, &volume) < 0 ||
pa_tagstruct_gets(t, &name) < 0 || !name ||
!pa_tagstruct_eof(t)) {
protocol_error(c);
@@ -1078,7 +1104,7 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui
return;
}
- if (pa_scache_play_item(c->protocol->core, name, sink, volume) < 0) {
+ if (pa_scache_play_item(c->protocol->core, name, sink, &volume) < 0) {
pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
return;
}
@@ -1116,12 +1142,13 @@ static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) {
pa_tagstruct_puts(t, sink->name);
pa_tagstruct_puts(t, sink->description);
pa_tagstruct_put_sample_spec(t, &sink->sample_spec);
+ pa_tagstruct_put_channel_map(t, &sink->channel_map);
pa_tagstruct_putu32(t, sink->owner ? sink->owner->index : (uint32_t) -1);
- pa_tagstruct_putu32(t, sink->volume);
+ pa_tagstruct_put_cvolume(t, pa_sink_get_volume(sink, PA_MIXER_HARDWARE));
pa_tagstruct_putu32(t, sink->monitor_source->index);
pa_tagstruct_puts(t, sink->monitor_source->name);
pa_tagstruct_put_usec(t, pa_sink_get_latency(sink));
- pa_tagstruct_putu32(t, sink->typeid);
+ pa_tagstruct_puts(t, sink->driver);
}
static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) {
@@ -1130,11 +1157,12 @@ static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) {
pa_tagstruct_puts(t, source->name);
pa_tagstruct_puts(t, source->description);
pa_tagstruct_put_sample_spec(t, &source->sample_spec);
+ pa_tagstruct_put_channel_map(t, &source->channel_map);
pa_tagstruct_putu32(t, source->owner ? source->owner->index : (uint32_t) -1);
pa_tagstruct_putu32(t, source->monitor_of ? source->monitor_of->index : (uint32_t) -1);
pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : NULL);
pa_tagstruct_put_usec(t, pa_source_get_latency(source));
- pa_tagstruct_putu32(t, source->typeid);
+ pa_tagstruct_puts(t, source->driver);
}
static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) {
@@ -1142,7 +1170,7 @@ static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) {
pa_tagstruct_putu32(t, client->index);
pa_tagstruct_puts(t, client->name);
pa_tagstruct_putu32(t, client->owner ? client->owner->index : (uint32_t) -1);
- pa_tagstruct_putu32(t, client->typeid);
+ pa_tagstruct_puts(t, client->driver);
}
static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) {
@@ -1162,11 +1190,12 @@ static void sink_input_fill_tagstruct(pa_tagstruct *t, pa_sink_input *s) {
pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1);
pa_tagstruct_putu32(t, s->sink->index);
pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_putu32(t, s->volume);
+ pa_tagstruct_put_channel_map(t, &s->channel_map);
+ pa_tagstruct_put_cvolume(t, &s->volume);
pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s));
pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink));
pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
- pa_tagstruct_putu32(t, s->typeid);
+ pa_tagstruct_puts(t, s->driver);
}
static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) {
@@ -1177,19 +1206,21 @@ static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) {
pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1);
pa_tagstruct_putu32(t, s->source->index);
pa_tagstruct_put_sample_spec(t, &s->sample_spec);
+ pa_tagstruct_put_channel_map(t, &s->channel_map);
pa_tagstruct_put_usec(t, pa_source_output_get_latency(s));
pa_tagstruct_put_usec(t, pa_source_get_latency(s->source));
pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
- pa_tagstruct_putu32(t, s->typeid);
+ pa_tagstruct_puts(t, s->driver);
}
static void scache_fill_tagstruct(pa_tagstruct *t, pa_scache_entry *e) {
assert(t && e);
pa_tagstruct_putu32(t, e->index);
pa_tagstruct_puts(t, e->name);
- pa_tagstruct_putu32(t, e->volume);
+ pa_tagstruct_put_cvolume(t, &e->volume);
pa_tagstruct_put_usec(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec));
pa_tagstruct_put_sample_spec(t, &e->sample_spec);
+ pa_tagstruct_put_channel_map(t, &e->channel_map);
pa_tagstruct_putu32(t, e->memchunk.length);
pa_tagstruct_put_boolean(t, e->lazy);
pa_tagstruct_puts(t, e->filename);
@@ -1379,7 +1410,7 @@ static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE
pa_pstream_send_tagstruct(c->pstream, reply);
}
-static void subscription_cb(pa_core *core, pa_subscription_event_type e, uint32_t idx, void *userdata) {
+static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
pa_tagstruct *t;
struct connection *c = userdata;
assert(c && core);
@@ -1395,7 +1426,7 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type e, uint32_
static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
struct connection *c = userdata;
- pa_subscription_mask m;
+ pa_subscription_mask_t m;
assert(c && t);
if (pa_tagstruct_getu32(t, &m) < 0 ||
@@ -1423,7 +1454,8 @@ static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint
static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
struct connection *c = userdata;
- uint32_t idx, volume;
+ uint32_t idx;
+ pa_cvolume volume;
pa_sink *sink = NULL;
pa_sink_input *si = NULL;
const char *name = NULL;
@@ -1431,7 +1463,7 @@ static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command,
if (pa_tagstruct_getu32(t, &idx) < 0 ||
(command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
- pa_tagstruct_getu32(t, &volume) ||
+ pa_tagstruct_get_cvolume(t, &volume) ||
!pa_tagstruct_eof(t)) {
protocol_error(c);
return;
@@ -1458,9 +1490,9 @@ static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command,
}
if (sink)
- pa_sink_set_volume(sink, volume);
+ pa_sink_set_volume(sink, PA_MIXER_HARDWARE, &volume);
else if (si)
- pa_sink_input_set_volume(si, volume);
+ pa_sink_input_set_volume(si, &volume);
pa_pstream_send_simple_ack(c->pstream, tag);
}
@@ -2032,7 +2064,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
c->protocol = p;
assert(p->core);
- c->client = pa_client_new(p->core, PA_TYPEID_NATIVE, "Client");
+ c->client = pa_client_new(p->core, __FILE__, "Client");
assert(c->client);
c->client->kill = client_kill_cb;
c->client->userdata = c;
diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c
index a3d7099c8..113919b35 100644
--- a/polyp/protocol-simple.c
+++ b/polyp/protocol-simple.c
@@ -42,8 +42,6 @@
/* Don't allow more than this many concurrent connections */
#define MAX_CONNECTIONS 10
-#define PA_TYPEID_SIMPLE PA_TYPEID_MAKE('S', 'M', 'P', 'L')
-
struct connection {
pa_protocol_simple *protocol;
pa_iochannel *io;
@@ -310,7 +308,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
c->playback.fragment_size = 0;
pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname));
- c->client = pa_client_new(p->core, PA_TYPEID_SIMPLE, cname);
+ c->client = pa_client_new(p->core, __FILE__, cname);
assert(c->client);
c->client->owner = p->module;
c->client->kill = client_kill_cb;
@@ -325,7 +323,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
goto fail;
}
- if (!(c->sink_input = pa_sink_input_new(sink, PA_TYPEID_SIMPLE, c->client->name, &p->sample_spec, 0, -1))) {
+ if (!(c->sink_input = pa_sink_input_new(sink, __FILE__, c->client->name, &p->sample_spec, NULL, 0, -1))) {
pa_log(__FILE__": Failed to create sink input.\n");
goto fail;
}
@@ -355,7 +353,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
goto fail;
}
- c->source_output = pa_source_output_new(source, PA_TYPEID_SIMPLE, c->client->name, &p->sample_spec, -1);
+ c->source_output = pa_source_output_new(source, __FILE__, c->client->name, &p->sample_spec, NULL, -1);
if (!c->source_output) {
pa_log(__FILE__": Failed to create source output.\n");
goto fail;
diff --git a/polyp/resampler.c b/polyp/resampler.c
index 96a1678f4..0417e44ef 100644
--- a/polyp/resampler.c
+++ b/polyp/resampler.c
@@ -27,6 +27,8 @@
#include <string.h>
#include <samplerate.h>
+#include <liboil/liboilfuncs.h>
+#include <liboil/liboil.h>
#include "resampler.h"
#include "sconv.h"
@@ -34,24 +36,28 @@
#include "log.h"
struct pa_resampler {
+ pa_resample_method_t resample_method;
pa_sample_spec i_ss, o_ss;
+ pa_channel_map i_cm, o_cm;
size_t i_fz, o_fz;
pa_memblock_stat *memblock_stat;
- void *impl_data;
- int channels;
- pa_resample_method resample_method;
void (*impl_free)(pa_resampler *r);
- void (*impl_set_input_rate)(pa_resampler *r, uint32_t rate);
+ void (*impl_update_input_rate)(pa_resampler *r, uint32_t rate);
void (*impl_run)(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out);
+ void *impl_data;
};
struct impl_libsamplerate {
- float* i_buf, *o_buf;
- unsigned i_alloc, o_alloc;
+ float* buf1, *buf2, *buf3, *buf4;
+ unsigned buf1_samples, buf2_samples, buf3_samples, buf4_samples;
+
pa_convert_to_float32ne_func_t to_float32ne_func;
pa_convert_from_float32ne_func_t from_float32ne_func;
SRC_STATE *src_state;
+
+ int map_table[PA_CHANNELS_MAX][PA_CHANNELS_MAX];
+ int map_required;
};
struct impl_trivial {
@@ -62,35 +68,54 @@ struct impl_trivial {
static int libsamplerate_init(pa_resampler*r);
static int trivial_init(pa_resampler*r);
-pa_resampler* pa_resampler_new(const pa_sample_spec *a, const pa_sample_spec *b, pa_memblock_stat *s, pa_resample_method resample_method) {
+pa_resampler* pa_resampler_new(
+ const pa_sample_spec *a,
+ const pa_channel_map *am,
+ const pa_sample_spec *b,
+ const pa_channel_map *bm,
+ pa_memblock_stat *s,
+ pa_resample_method_t resample_method) {
+
pa_resampler *r = NULL;
- assert(a && b && pa_sample_spec_valid(a) && pa_sample_spec_valid(b) && resample_method != PA_RESAMPLER_INVALID);
- if (a->channels != b->channels && a->channels != 1 && b->channels != 1)
- goto fail;
+ assert(a);
+ assert(b);
+ assert(pa_sample_spec_valid(a));
+ assert(pa_sample_spec_valid(b));
+ assert(resample_method != PA_RESAMPLER_INVALID);
- r = pa_xmalloc(sizeof(pa_resampler));
+ r = pa_xnew(pa_resampler, 1);
r->impl_data = NULL;
r->memblock_stat = s;
r->resample_method = resample_method;
r->impl_free = NULL;
- r->impl_set_input_rate = NULL;
+ r->impl_update_input_rate = NULL;
r->impl_run = NULL;
/* Fill sample specs */
r->i_ss = *a;
r->o_ss = *b;
+ if (am)
+ r->i_cm = *am;
+ else
+ pa_channel_map_init_auto(&r->i_cm, r->i_ss.channels);
+
+ if (bm)
+ r->o_cm = *bm;
+ else
+ pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels);
+
r->i_fz = pa_frame_size(a);
r->o_fz = pa_frame_size(b);
- r->channels = a->channels;
- if (b->channels < r->channels)
- r->channels = b->channels;
-
/* Choose implementation */
- if (a->channels != b->channels || a->format != b->format || resample_method != PA_RESAMPLER_TRIVIAL) {
+ if (a->channels != b->channels ||
+ a->format != b->format ||
+ !pa_channel_map_equal(&r->i_cm, &r->o_cm) ||
+ resample_method != PA_RESAMPLER_TRIVIAL) {
+
/* Use the libsamplerate based resampler for the complicated cases */
if (resample_method == PA_RESAMPLER_TRIVIAL)
r->resample_method = PA_RESAMPLER_SRC_ZERO_ORDER_HOLD;
@@ -123,11 +148,16 @@ void pa_resampler_free(pa_resampler *r) {
}
void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) {
- assert(r && rate);
+ assert(r);
+ assert(rate > 0);
+ if (r->i_ss.rate == rate)
+ return;
+
r->i_ss.rate = rate;
- if (r->impl_set_input_rate)
- r->impl_set_input_rate(r, rate);
+
+ if (r->impl_update_input_rate)
+ r->impl_update_input_rate(r, rate);
}
void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
@@ -141,168 +171,342 @@ size_t pa_resampler_request(pa_resampler *r, size_t out_length) {
return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz;
}
-pa_resample_method pa_resampler_get_method(pa_resampler *r) {
+pa_resample_method_t pa_resampler_get_method(pa_resampler *r) {
assert(r);
return r->resample_method;
}
-/* Parse a libsamplrate compatible resampling implementation */
-pa_resample_method pa_parse_resample_method(const char *string) {
+static const char * const resample_methods[] = {
+ "src-sinc-best-quality",
+ "src-sinc-medium-quality",
+ "src-sinc-fastest",
+ "src-zero-order-hold",
+ "src-linear",
+ "trivial"
+};
+
+const char *pa_resample_method_to_string(pa_resample_method_t m) {
+
+ if (m < 0 || m >= PA_RESAMPLER_MAX)
+ return NULL;
+
+ return resample_methods[m];
+}
+
+pa_resample_method_t pa_parse_resample_method(const char *string) {
+ pa_resample_method_t m;
+
assert(string);
- if (!strcmp(string, "src-sinc-best-quality"))
- return PA_RESAMPLER_SRC_SINC_BEST_QUALITY;
- else if (!strcmp(string, "src-sinc-medium-quality"))
- return PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY;
- else if (!strcmp(string, "src-sinc-fastest"))
- return PA_RESAMPLER_SRC_SINC_FASTEST;
- else if (!strcmp(string, "src-zero-order-hold"))
- return PA_RESAMPLER_SRC_ZERO_ORDER_HOLD;
- else if (!strcmp(string, "src-linear"))
- return PA_RESAMPLER_SRC_LINEAR;
- else if (!strcmp(string, "trivial"))
- return PA_RESAMPLER_TRIVIAL;
- else
- return PA_RESAMPLER_INVALID;
+ for (m = 0; m < PA_RESAMPLER_MAX; m++)
+ if (!strcmp(string, resample_methods[m]))
+ return m;
+
+ return PA_RESAMPLER_INVALID;
}
+
/*** libsamplerate based implementation ***/
static void libsamplerate_free(pa_resampler *r) {
- struct impl_libsamplerate *i;
- assert(r && r->impl_data);
- i = r->impl_data;
+ struct impl_libsamplerate *u;
+
+ assert(r);
+ assert(r->impl_data);
- if (i->src_state)
- src_delete(i->src_state);
+ u = r->impl_data;
+
+ if (u->src_state)
+ src_delete(u->src_state);
+
+ pa_xfree(u->buf1);
+ pa_xfree(u->buf2);
+ pa_xfree(u->buf3);
+ pa_xfree(u->buf4);
+ pa_xfree(u);
+}
+
+static void calc_map_table(pa_resampler *r) {
+ struct impl_libsamplerate *u;
+ unsigned oc;
+ assert(r);
+ assert(r->impl_data);
- pa_xfree(i->i_buf);
- pa_xfree(i->o_buf);
- pa_xfree(i);
+ u = r->impl_data;
+
+ if (!(u->map_required = (!pa_channel_map_equal(&r->i_cm, &r->o_cm) || r->i_ss.channels != r->o_ss.channels)))
+ return;
+
+ for (oc = 0; oc < r->o_ss.channels; oc++) {
+ unsigned ic, i = 0;
+
+ for (ic = 0; ic < r->i_ss.channels; ic++) {
+ pa_channel_position_t a, b;
+
+ a = r->i_cm.map[ic];
+ b = r->o_cm.map[oc];
+
+ if (a == b ||
+ (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_LEFT) ||
+ (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_RIGHT) ||
+ (a == PA_CHANNEL_POSITION_LEFT && b == PA_CHANNEL_POSITION_MONO) ||
+ (a == PA_CHANNEL_POSITION_RIGHT && b == PA_CHANNEL_POSITION_MONO))
+
+ u->map_table[oc][i++] = ic;
+ }
+
+ /* Add an end marker */
+ if (i < PA_CHANNELS_MAX)
+ u->map_table[oc][i] = -1;
+ }
}
-static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
- unsigned i_nchannels, o_nchannels, ins, ons, eff_ins, eff_ons;
- float *cbuf;
- struct impl_libsamplerate *i;
- assert(r && in && out && in->length && in->memblock && (in->length % r->i_fz) == 0 && r->impl_data);
- i = r->impl_data;
+static float * convert_to_float(pa_resampler *r, float *input, unsigned n_frames) {
+ struct impl_libsamplerate *u;
+ unsigned n_samples;
- /* How many input samples? */
- ins = in->length/r->i_fz;
+ assert(r);
+ assert(input);
+ assert(r->impl_data);
+ u = r->impl_data;
+
+ /* Convert the incoming sample into floats and place them in buf1 */
-/* pa_log("%u / %u = %u\n", in->length, r->i_fz, ins); */
+ if (!u->to_float32ne_func)
+ return input;
+
+ n_samples = n_frames * r->i_ss.channels;
- /* How much space for output samples? */
- if (i->src_state)
- ons = (ins*r->o_ss.rate/r->i_ss.rate)+1024;
- else
- ons = ins;
+ if (u->buf1_samples < n_samples)
+ u->buf1 = pa_xrealloc(u->buf1, sizeof(float) * (u->buf1_samples = n_samples));
- /* How many channels? */
- if (r->i_ss.channels == r->o_ss.channels) {
- i_nchannels = o_nchannels = 1;
- eff_ins = ins*r->i_ss.channels; /* effective samples */
- eff_ons = ons*r->o_ss.channels;
- } else {
- i_nchannels = r->i_ss.channels;
- o_nchannels = r->o_ss.channels;
- eff_ins = ins;
- eff_ons = ons;
- }
+ u->to_float32ne_func(n_samples, input, u->buf1);
-/* pa_log("eff_ins = %u \n", eff_ins); */
+ return u->buf1;
+}
+
+static float *remap_channels(pa_resampler *r, float *input, unsigned n_frames) {
+ struct impl_libsamplerate *u;
+ unsigned n_samples;
+ int i_skip, o_skip;
+ unsigned oc;
+ assert(r);
+ assert(input);
+ assert(r->impl_data);
+ u = r->impl_data;
+
+ /* Remap channels and place the result int buf2 */
- out->memblock = pa_memblock_new(out->length = (ons*r->o_fz), r->memblock_stat);
- out->index = 0;
- assert(out->memblock);
+ if (!u->map_required)
+ return input;
- if (i->i_alloc < eff_ins)
- i->i_buf = pa_xrealloc(i->i_buf, sizeof(float) * (i->i_alloc = eff_ins));
- assert(i->i_buf);
+ n_samples = n_frames * r->o_ss.channels;
-/* pa_log("eff_ins = %u \n", eff_ins); */
+ if (u->buf2_samples < n_samples)
+ u->buf2 = pa_xrealloc(u->buf2, sizeof(float) * (u->buf2_samples = n_samples));
- i->to_float32ne_func(eff_ins, (uint8_t*) in->memblock->data+in->index, i_nchannels, i->i_buf);
+ memset(u->buf2, 0, n_samples * sizeof(float));
- if (i->src_state) {
- int ret;
- SRC_DATA data;
+ o_skip = sizeof(float) * r->o_ss.channels;
+ i_skip = sizeof(float) * r->i_ss.channels;
+
+ for (oc = 0; oc < r->o_ss.channels; oc++) {
+ unsigned i;
+ static const float one = 1.0;
+
+ for (i = 0; i < PA_CHANNELS_MAX && u->map_table[oc][i] >= 0; i++)
+ oil_vectoradd_f32(
+ u->buf2 + oc, o_skip,
+ u->buf2 + oc, o_skip,
+ input + u->map_table[oc][i], i_skip,
+ n_frames,
+ &one, &one);
+ }
- if (i->o_alloc < eff_ons)
- i->o_buf = pa_xrealloc(i->o_buf, sizeof(float) * (i->o_alloc = eff_ons));
- assert(i->o_buf);
+ return u->buf2;
+}
- data.data_in = i->i_buf;
- data.input_frames = ins;
+static float *resample(pa_resampler *r, float *input, unsigned *n_frames) {
+ struct impl_libsamplerate *u;
+ SRC_DATA data;
+ unsigned out_n_frames, out_n_samples;
+ int ret;
- data.data_out = i->o_buf;
- data.output_frames = ons;
-
- data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate;
- data.end_of_input = 0;
+ assert(r);
+ assert(input);
+ assert(n_frames);
+ assert(r->impl_data);
+ u = r->impl_data;
+
+ /* Resample the data and place the result in buf3 */
+
+ if (!u->src_state)
+ return input;
+
+ out_n_frames = (*n_frames*r->o_ss.rate/r->i_ss.rate)+1024;
+ out_n_samples = out_n_frames * r->o_ss.channels;
+
+ if (u->buf3_samples < out_n_samples)
+ u->buf3 = pa_xrealloc(u->buf3, sizeof(float) * (u->buf3_samples = out_n_samples));
+
+ data.data_in = input;
+ data.input_frames = *n_frames;
+
+ data.data_out = u->buf3;
+ data.output_frames = out_n_frames;
- ret = src_process(i->src_state, &data);
- assert(ret == 0);
- assert((unsigned) data.input_frames_used == ins);
+ data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate;
+ data.end_of_input = 0;
- cbuf = i->o_buf;
- ons = data.output_frames_gen;
-
- if (r->i_ss.channels == r->o_ss.channels)
- eff_ons = ons*r->o_ss.channels;
- else
- eff_ons = ons;
- } else
- cbuf = i->i_buf;
-
- if (eff_ons)
- i->from_float32ne_func(eff_ons, cbuf, (uint8_t*)out->memblock->data+out->index, o_nchannels);
- out->length = ons*r->o_fz;
-
- if (!out->length) {
- pa_memblock_unref(out->memblock);
+ ret = src_process(u->src_state, &data);
+ assert(ret == 0);
+ assert((unsigned) data.input_frames_used == *n_frames);
+
+ *n_frames = data.output_frames_gen;
+
+ return u->buf3;
+}
+
+static float *convert_from_float(pa_resampler *r, float *input, unsigned n_frames) {
+ struct impl_libsamplerate *u;
+ unsigned n_samples;
+
+ assert(r);
+ assert(input);
+ assert(r->impl_data);
+ u = r->impl_data;
+
+ /* Convert the data into the correct sample type and place the result in buf4 */
+
+ if (!u->from_float32ne_func)
+ return input;
+
+ n_samples = n_frames * r->o_ss.channels;
+
+ if (u->buf4_samples < n_samples)
+ u->buf4 = pa_xrealloc(u->buf4, sizeof(float) * (u->buf4_samples = n_samples));
+
+ u->from_float32ne_func(n_samples, input, u->buf4);
+
+ return u->buf4;
+}
+
+static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
+ struct impl_libsamplerate *u;
+ float *buf, *input;
+ unsigned n_frames;
+
+ assert(r);
+ assert(in);
+ assert(out);
+ assert(in->length);
+ assert(in->memblock);
+ assert(in->length % r->i_fz == 0);
+ assert(r->impl_data);
+
+ u = r->impl_data;
+
+ buf = input = (float*) ((uint8_t*) in->memblock->data + in->index);
+ n_frames = in->length / r->i_fz;
+ assert(n_frames > 0);
+
+ buf = convert_to_float(r, buf, n_frames);
+ buf = remap_channels(r, buf, n_frames);
+ buf = resample(r, buf, &n_frames);
+
+ if (n_frames) {
+ buf = convert_from_float(r, buf, n_frames);
+
+ if (buf == input) {
+ /* Mm, no adjustment has been necessary, so let's return the original block */
+ out->memblock = pa_memblock_ref(in->memblock);
+ out->index = in->index;
+ out->length = in->length;
+ } else {
+ float **p = NULL;
+
+ out->length = n_frames * r->o_fz;
+ out->index = 0;
+
+ if (buf == u->buf1) {
+ p = &u->buf1;
+ u->buf1_samples = 0;
+ } else if (buf == u->buf2) {
+ p = &u->buf2;
+ u->buf2_samples = 0;
+ } else if (buf == u->buf3) {
+ p = &u->buf3;
+ u->buf3_samples = 0;
+ } else if (buf == u->buf4) {
+ p = &u->buf4;
+ u->buf4_samples = 0;
+ }
+
+ assert(p);
+
+ /* Take the existing buffer and make it a memblock */
+ out->memblock = pa_memblock_new_dynamic(*p, out->length, r->memblock_stat);
+ *p = NULL;
+ }
+ } else {
out->memblock = NULL;
+ out->index = out->length = 0;
}
}
-static void libsamplerate_set_input_rate(pa_resampler *r, uint32_t rate) {
- int ret;
- struct impl_libsamplerate *i;
- assert(r && rate > 0 && r->impl_data);
- i = r->impl_data;
-
- ret = src_set_ratio(i->src_state, (double) r->o_ss.rate / r->i_ss.rate);
- assert(ret == 0);
+static void libsamplerate_update_input_rate(pa_resampler *r, uint32_t rate) {
+ struct impl_libsamplerate *u;
+
+ assert(r);
+ assert(rate > 0);
+ assert(r->impl_data);
+ u = r->impl_data;
+
+ if (!u->src_state) {
+ int err;
+ u->src_state = src_new(r->resample_method, r->o_ss.channels, &err);
+ assert(u->src_state);
+ } else {
+ int ret = src_set_ratio(u->src_state, (double) r->o_ss.rate / rate);
+ assert(ret == 0);
+ }
}
static int libsamplerate_init(pa_resampler *r) {
- struct impl_libsamplerate *i = NULL;
+ struct impl_libsamplerate *u = NULL;
int err;
- r->impl_data = i = pa_xmalloc(sizeof(struct impl_libsamplerate));
-
- i->to_float32ne_func = pa_get_convert_to_float32ne_function(r->i_ss.format);
- i->from_float32ne_func = pa_get_convert_from_float32ne_function(r->o_ss.format);
+ r->impl_data = u = pa_xnew(struct impl_libsamplerate, 1);
+
+ u->buf1 = u->buf2 = u->buf3 = u->buf4 = NULL;
+ u->buf1_samples = u->buf2_samples = u->buf3_samples = u->buf4_samples = 0;
- if (!i->to_float32ne_func || !i->from_float32ne_func)
+ if (r->i_ss.format == PA_SAMPLE_FLOAT32NE)
+ u->to_float32ne_func = NULL;
+ else if (!(u->to_float32ne_func = pa_get_convert_to_float32ne_function(r->i_ss.format)))
goto fail;
-
- if (!(i->src_state = src_new(r->resample_method, r->channels, &err)) || !i->src_state)
+
+ if (r->o_ss.format == PA_SAMPLE_FLOAT32NE)
+ u->from_float32ne_func = NULL;
+ else if (!(u->from_float32ne_func = pa_get_convert_from_float32ne_function(r->o_ss.format)))
goto fail;
- i->i_buf = i->o_buf = NULL;
- i->i_alloc = i->o_alloc = 0;
+ if (r->o_ss.rate == r->i_ss.rate)
+ u->src_state = NULL;
+ else if (!(u->src_state = src_new(r->resample_method, r->o_ss.channels, &err)))
+ goto fail;
r->impl_free = libsamplerate_free;
- r->impl_set_input_rate = libsamplerate_set_input_rate;
+ r->impl_update_input_rate = libsamplerate_update_input_rate;
r->impl_run = libsamplerate_run;
+
+ calc_map_table(r);
return 0;
fail:
- pa_xfree(i);
+ pa_xfree(u);
return -1;
}
@@ -310,15 +514,20 @@ fail:
static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
size_t fz;
- unsigned nframes;
- struct impl_trivial *i;
- assert(r && in && out && r->impl_data);
- i = r->impl_data;
+ unsigned n_frames;
+ struct impl_trivial *u;
+
+ assert(r);
+ assert(in);
+ assert(out);
+ assert(r->impl_data);
+
+ u = r->impl_data;
fz = r->i_fz;
assert(fz == r->o_fz);
- nframes = in->length/fz;
+ n_frames = in->length/fz;
if (r->i_ss.rate == r->o_ss.rate) {
@@ -326,25 +535,25 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out
*out = *in;
pa_memblock_ref(out->memblock);
- i->o_counter += nframes;
+ u->o_counter += n_frames;
} else {
/* Do real resampling */
size_t l;
unsigned o_index;
/* The length of the new memory block rounded up */
- l = ((((nframes+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz;
+ l = ((((n_frames+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz;
out->index = 0;
out->memblock = pa_memblock_new(l, r->memblock_stat);
- for (o_index = 0;; o_index++, i->o_counter++) {
+ for (o_index = 0;; o_index++, u->o_counter++) {
unsigned j;
- j = (i->o_counter * r->i_ss.rate / r->o_ss.rate);
- j = j > i->i_counter ? j - i->i_counter : 0;
+ j = (u->o_counter * r->i_ss.rate / r->o_ss.rate);
+ j = j > u->i_counter ? j - u->i_counter : 0;
- if (j >= nframes)
+ if (j >= n_frames)
break;
assert(o_index*fz < out->memblock->length);
@@ -357,56 +566,49 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out
out->length = o_index*fz;
}
- i->i_counter += nframes;
+ u->i_counter += n_frames;
/* Normalize counters */
- while (i->i_counter >= r->i_ss.rate) {
- i->i_counter -= r->i_ss.rate;
- assert(i->o_counter >= r->o_ss.rate);
- i->o_counter -= r->o_ss.rate;
+ while (u->i_counter >= r->i_ss.rate) {
+ u->i_counter -= r->i_ss.rate;
+ assert(u->o_counter >= r->o_ss.rate);
+ u->o_counter -= r->o_ss.rate;
}
}
static void trivial_free(pa_resampler *r) {
assert(r);
+
pa_xfree(r->impl_data);
}
-static void trivial_set_input_rate(pa_resampler *r, uint32_t rate) {
- struct impl_trivial *i;
- assert(r && rate > 0 && r->impl_data);
- i = r->impl_data;
+static void trivial_update_input_rate(pa_resampler *r, uint32_t rate) {
+ struct impl_trivial *u;
+
+ assert(r);
+ assert(rate > 0);
+ assert(r->impl_data);
- i->i_counter = 0;
- i->o_counter = 0;
+ u = r->impl_data;
+ u->i_counter = 0;
+ u->o_counter = 0;
}
static int trivial_init(pa_resampler*r) {
- struct impl_trivial *i;
- assert(r && r->i_ss.format == r->o_ss.format && r->i_ss.channels == r->o_ss.channels);
+ struct impl_trivial *u;
+
+ assert(r);
+ assert(r->i_ss.format == r->o_ss.format);
+ assert(r->i_ss.channels == r->o_ss.channels);
- r->impl_data = i = pa_xmalloc(sizeof(struct impl_trivial));
- i->o_counter = i->i_counter = 0;
+ r->impl_data = u = pa_xnew(struct impl_trivial, 1);
+ u->o_counter = u->i_counter = 0;
r->impl_run = trivial_run;
r->impl_free = trivial_free;
- r->impl_set_input_rate = trivial_set_input_rate;
+ r->impl_update_input_rate = trivial_update_input_rate;
return 0;
}
-const char *pa_resample_method_to_string(pa_resample_method m) {
- static const char * const resample_methods[] = {
- "src-sinc-best-quality",
- "src-sinc-medium-quality",
- "src-sinc-fastest",
- "src-zero-order-hold",
- "src-linear",
- "trivial"
- };
- if (m < 0 || m >= PA_RESAMPLER_MAX)
- return NULL;
-
- return resample_methods[m];
-}
diff --git a/polyp/resampler.h b/polyp/resampler.h
index 358c872a3..e14942f32 100644
--- a/polyp/resampler.h
+++ b/polyp/resampler.h
@@ -27,6 +27,7 @@
#include "sample.h"
#include "memblock.h"
#include "memchunk.h"
+#include "channelmap.h"
typedef struct pa_resampler pa_resampler;
@@ -39,9 +40,16 @@ typedef enum pa_resample_method {
PA_RESAMPLER_SRC_LINEAR = SRC_LINEAR,
PA_RESAMPLER_TRIVIAL,
PA_RESAMPLER_MAX
-} pa_resample_method;
+} pa_resample_method_t;
+
+pa_resampler* pa_resampler_new(
+ const pa_sample_spec *a,
+ const pa_channel_map *am,
+ const pa_sample_spec *b,
+ const pa_channel_map *bm,
+ pa_memblock_stat *s,
+ pa_resample_method_t resample_method);
-pa_resampler* pa_resampler_new(const pa_sample_spec *a, const pa_sample_spec *b, pa_memblock_stat *s, int resample_method);
void pa_resampler_free(pa_resampler *r);
/* Returns the size of an input memory block which is required to return the specified amount of output data */
@@ -54,12 +62,12 @@ void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out);
void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate);
/* Return the resampling method of the resampler object */
-pa_resample_method pa_resampler_get_method(pa_resampler *r);
+pa_resample_method_t pa_resampler_get_method(pa_resampler *r);
/* Try to parse the resampler method */
-pa_resample_method pa_parse_resample_method(const char *string);
+pa_resample_method_t pa_parse_resample_method(const char *string);
/* return a human readable string for the specified resampling method. Inverse of pa_parse_resample_method() */
-const char *pa_resample_method_to_string(pa_resample_method m);
+const char *pa_resample_method_to_string(pa_resample_method_t m);
#endif
diff --git a/polyp/sample-util.c b/polyp/sample-util.c
index cb5dd1c38..d2bb31507 100644
--- a/polyp/sample-util.c
+++ b/polyp/sample-util.c
@@ -28,6 +28,8 @@
#include <assert.h>
#include <stdlib.h>
+#include <liboil/liboilfuncs.h>
+
#include "sample-util.h"
pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
@@ -38,6 +40,7 @@ pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
assert(c && c->memblock && c->memblock->data && spec && c->length);
+
pa_silence_memory((uint8_t*) c->memblock->data+c->index, c->length, spec);
}
@@ -65,204 +68,255 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
memset(p, c, length);
}
-size_t pa_mix(pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const pa_sample_spec *spec, pa_volume_t volume) {
- assert(channels && data && length && spec);
+size_t pa_mix(
+ const pa_mix_info streams[],
+ unsigned nstreams,
+ void *data,
+ size_t length,
+ const pa_sample_spec *spec,
+ const pa_cvolume *volume) {
- if (spec->format == PA_SAMPLE_S16NE) {
- size_t d;
-
- for (d = 0;; d += sizeof(int16_t)) {
- unsigned c;
- int32_t sum = 0;
-
- if (d >= length)
- return d;
+ assert(streams && data && length && spec);
+
+ switch (spec->format) {
+ case PA_SAMPLE_S16NE:{
+ size_t d;
+ unsigned channel = 0;
- for (c = 0; c < nchannels; c++) {
- int32_t v;
- pa_volume_t cvolume = channels[c].volume;
+ for (d = 0;; d += sizeof(int16_t)) {
+ int32_t sum = 0;
- if (d >= channels[c].chunk.length)
+ if (d >= length)
return d;
-
- if (cvolume == PA_VOLUME_MUTED)
- v = 0;
- else {
- v = *((int16_t*) ((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d));
+
+ if (volume->values[channel] != PA_VOLUME_MUTED) {
+ unsigned i;
- if (cvolume != PA_VOLUME_NORM) {
- v *= cvolume;
- v /= PA_VOLUME_NORM;
+ for (i = 0; i < nstreams; i++) {
+ int32_t v;
+ pa_volume_t cvolume = streams[i].volume.values[channel];
+
+ if (d >= streams[i].chunk.length)
+ return d;
+
+ if (cvolume == PA_VOLUME_MUTED)
+ v = 0;
+ else {
+ v = *((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d));
+
+ if (cvolume != PA_VOLUME_NORM) {
+ v *= cvolume;
+ v /= PA_VOLUME_NORM;
+ }
+ }
+
+ sum += v;
+ }
+
+ if (volume->values[channel] != PA_VOLUME_NORM) {
+ sum *= volume->values[channel];
+ sum /= PA_VOLUME_NORM;
}
+
+ if (sum < -0x8000) sum = -0x8000;
+ if (sum > 0x7FFF) sum = 0x7FFF;
+
}
- sum += v;
- }
-
- if (volume == PA_VOLUME_MUTED)
- sum = 0;
- else if (volume != PA_VOLUME_NORM) {
- sum *= volume;
- sum /= PA_VOLUME_NORM;
+ *((int16_t*) data) = sum;
+ data = (uint8_t*) data + sizeof(int16_t);
+
+ if (++channel >= spec->channels)
+ channel = 0;
}
-
- if (sum < -0x8000) sum = -0x8000;
- if (sum > 0x7FFF) sum = 0x7FFF;
-
- *((int16_t*) data) = sum;
- data = (uint8_t*) data + sizeof(int16_t);
}
- } else if (spec->format == PA_SAMPLE_U8) {
- size_t d;
-
- for (d = 0;; d ++) {
- int32_t sum = 0;
- unsigned c;
- if (d >= length)
- return d;
+ case PA_SAMPLE_U8: {
+ size_t d;
+ unsigned channel = 0;
- for (c = 0; c < nchannels; c++) {
- int32_t v;
- pa_volume_t cvolume = channels[c].volume;
+ for (d = 0;; d ++) {
+ int32_t sum = 0;
- if (d >= channels[c].chunk.length)
+ if (d >= length)
return d;
-
- if (cvolume == PA_VOLUME_MUTED)
- v = 0;
- else {
- v = (int32_t) *((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d) - 0x80;
+
+ if (volume->values[channel] != PA_VOLUME_MUTED) {
+ unsigned i;
- if (cvolume != PA_VOLUME_NORM) {
- v *= cvolume;
- v /= PA_VOLUME_NORM;
+ for (i = 0; i < nstreams; i++) {
+ int32_t v;
+ pa_volume_t cvolume = streams[i].volume.values[channel];
+
+ if (d >= streams[i].chunk.length)
+ return d;
+
+ if (cvolume == PA_VOLUME_MUTED)
+ v = 0;
+ else {
+ v = (int32_t) *((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d) - 0x80;
+
+ if (cvolume != PA_VOLUME_NORM) {
+ v *= cvolume;
+ v /= PA_VOLUME_NORM;
+ }
+ }
+
+ sum += v;
+ }
+
+ if (volume->values[channel] != PA_VOLUME_NORM) {
+ sum *= volume->values[channel];
+ sum /= PA_VOLUME_NORM;
}
+
+ if (sum < -0x80) sum = -0x80;
+ if (sum > 0x7F) sum = 0x7F;
+
}
- sum += v;
- }
-
- if (volume == PA_VOLUME_MUTED)
- sum = 0;
- else if (volume != PA_VOLUME_NORM) {
- sum *= volume;
- sum /= PA_VOLUME_NORM;
+ *((uint8_t*) data) = (uint8_t) (sum + 0x80);
+ data = (uint8_t*) data + 1;
+
+ if (++channel >= spec->channels)
+ channel = 0;
}
-
- if (sum < -0x80) sum = -0x80;
- if (sum > 0x7F) sum = 0x7F;
-
- *((uint8_t*) data) = (uint8_t) (sum + 0x80);
- data = (uint8_t*) data + 1;
}
-
- } else if (spec->format == PA_SAMPLE_FLOAT32NE) {
- size_t d;
-
- for (d = 0;; d += sizeof(float)) {
- float sum = 0;
- unsigned c;
- if (d >= length)
- return d;
+ case PA_SAMPLE_FLOAT32NE: {
+ size_t d;
+ unsigned channel = 0;
- for (c = 0; c < nchannels; c++) {
- float v;
- pa_volume_t cvolume = channels[c].volume;
+ for (d = 0;; d += sizeof(float)) {
+ float sum = 0;
- if (d >= channels[c].chunk.length)
+ if (d >= length)
return d;
- if (cvolume == PA_VOLUME_MUTED)
- v = 0;
- else {
- v = *((float*) ((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d));
+ if (volume->values[channel] != PA_VOLUME_MUTED) {
+ unsigned i;
- if (cvolume != PA_VOLUME_NORM)
- v = v*cvolume/PA_VOLUME_NORM;
- }
-
- sum += v;
- }
-
- if (volume == PA_VOLUME_MUTED)
- sum = 0;
- else if (volume != PA_VOLUME_NORM)
- sum = sum*volume/PA_VOLUME_NORM;
+ for (i = 0; i < nstreams; i++) {
+ float v;
+ pa_volume_t cvolume = streams[i].volume.values[channel];
+
+ if (d >= streams[i].chunk.length)
+ return d;
+
+ if (cvolume == PA_VOLUME_MUTED)
+ v = 0;
+ else {
+ v = *((float*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d));
+
+ if (cvolume != PA_VOLUME_NORM) {
+ v *= cvolume;
+ v /= PA_VOLUME_NORM;
+ }
+ }
+
+ sum += v;
+ }
- if (sum < -1) sum = -1;
- if (sum > 1) sum = 1;
+ if (volume->values[channel] != PA_VOLUME_NORM) {
+ sum *= volume->values[channel];
+ sum /= PA_VOLUME_NORM;
+ }
+ }
- *((float*) data) = sum;
- data = (uint8_t*) data + sizeof(float);
+ *((float*) data) = sum;
+ data = (uint8_t*) data + sizeof(float);
+
+ if (++channel >= spec->channels)
+ channel = 0;
+ }
}
- } else {
- abort();
+
+ default:
+ abort();
}
}
-void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, pa_volume_t volume) {
+void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvolume *volume) {
assert(c && spec && (c->length % pa_frame_size(spec) == 0));
+ assert(volume);
- if (volume == PA_VOLUME_NORM)
+ if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_NORM))
return;
- if (volume == PA_VOLUME_MUTED) {
+ if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_MUTED)) {
pa_silence_memchunk(c, spec);
return;
}
- if (spec->format == PA_SAMPLE_S16NE) {
- int16_t *d;
- size_t n;
-
- for (d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
- int32_t t = (int32_t)(*d);
+ switch (spec->format) {
+ case PA_SAMPLE_S16NE: {
+ int16_t *d;
+ size_t n;
+ unsigned channel = 0;
- t *= volume;
- t /= PA_VOLUME_NORM;
+ for (d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
+ int32_t t = (int32_t)(*d);
+
+ t *= volume->values[channel];
+ t /= PA_VOLUME_NORM;
+
+ if (t < -0x8000) t = -0x8000;
+ if (t > 0x7FFF) t = 0x7FFF;
+
+ *d = (int16_t) t;
+
+ if (++channel >= spec->channels)
+ channel = 0;
+ }
+ }
- if (t < -0x8000) t = -0x8000;
- if (t > 0x7FFF) t = 0x7FFF;
+ case PA_SAMPLE_U8: {
+ uint8_t *d;
+ size_t n;
+ unsigned channel = 0;
- *d = (int16_t) t;
+ for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) {
+ int32_t t = (int32_t) *d - 0x80;
+
+ t *= volume->values[channel];
+ t /= PA_VOLUME_NORM;
+
+ if (t < -0x80) t = -0x80;
+ if (t > 0x7F) t = 0x7F;
+
+ *d = (uint8_t) (t + 0x80);
+
+ if (++channel >= spec->channels)
+ channel = 0;
+ }
}
- } else if (spec->format == PA_SAMPLE_U8) {
- uint8_t *d;
- size_t n;
-
- for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) {
- int32_t t = (int32_t) *d - 0x80;
-
- t *= volume;
- t /= PA_VOLUME_NORM;
-
- if (t < -0x80) t = -0x80;
- if (t > 0x7F) t = 0x7F;
-
- *d = (uint8_t) (t + 0x80);
+ case PA_SAMPLE_FLOAT32NE: {
+ float *d;
+ int skip;
+ unsigned n;
+ unsigned channel;
+
+ d = (float*) ((uint8_t*) c->memblock->data + c->index);
+ skip = spec->channels * sizeof(float);
+ n = c->length/sizeof(float)/spec->channels;
+
+ for (channel = 0; channel < spec->channels ; channel ++) {
+ float v, *t;
+
+ if (volume->values[channel] == PA_VOLUME_NORM)
+ continue;
+
+ v = (float) volume->values[channel] / PA_VOLUME_NORM;
+
+ t = d + channel;
+ oil_scalarmult_f32(t, skip, t, skip, &v, n);
+ }
}
- } else if (spec->format == PA_SAMPLE_FLOAT32NE) {
- float *d;
- size_t n;
-
- for (d = (float*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(float); n > 0; d++, n--) {
- float t = *d;
-
- t *= volume;
- t /= PA_VOLUME_NORM;
- if (t < -1) t = -1;
- if (t > 1) t = 1;
-
- *d = t;
- }
-
- } else {
- abort();
+ default:
+ abort();
}
}
diff --git a/polyp/sample-util.h b/polyp/sample-util.h
index eaebe91d9..e433f9c81 100644
--- a/polyp/sample-util.h
+++ b/polyp/sample-util.h
@@ -25,7 +25,7 @@
#include "sample.h"
#include "memblock.h"
#include "memchunk.h"
-
+#include "volume.h"
pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec);
void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec);
@@ -33,12 +33,21 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec);
typedef struct pa_mix_info {
pa_memchunk chunk;
- pa_volume_t volume;
+ pa_cvolume volume;
void *userdata;
-} pa_mix_info ;
-
-size_t pa_mix(pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const pa_sample_spec *spec, pa_volume_t volume);
-
-void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, pa_volume_t volume);
+} pa_mix_info;
+
+size_t pa_mix(
+ const pa_mix_info channels[],
+ unsigned nchannels,
+ void *data,
+ size_t length,
+ const pa_sample_spec *spec,
+ const pa_cvolume *volume);
+
+void pa_volume_memchunk(
+ pa_memchunk*c,
+ const pa_sample_spec *spec,
+ const pa_cvolume *volume);
#endif
diff --git a/polyp/sample.c b/polyp/sample.c
index 37ab96a0a..d587170c9 100644
--- a/polyp/sample.c
+++ b/polyp/sample.c
@@ -30,29 +30,29 @@
#include "sample.h"
-size_t pa_frame_size(const pa_sample_spec *spec) {
- size_t b = 1;
+size_t pa_sample_size(const pa_sample_spec *spec) {
assert(spec);
switch (spec->format) {
case PA_SAMPLE_U8:
case PA_SAMPLE_ULAW:
case PA_SAMPLE_ALAW:
- b = 1;
- break;
+ return 1;
case PA_SAMPLE_S16LE:
case PA_SAMPLE_S16BE:
- b = 2;
- break;
+ return 2;
case PA_SAMPLE_FLOAT32LE:
case PA_SAMPLE_FLOAT32BE:
- b = 4;
- break;
+ return 4;
default:
assert(0);
}
+}
+
+size_t pa_frame_size(const pa_sample_spec *spec) {
+ assert(spec);
- return b * spec->channels;
+ return pa_sample_size(spec) * spec->channels;
}
size_t pa_bytes_per_second(const pa_sample_spec *spec) {
@@ -69,10 +69,11 @@ pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) {
int pa_sample_spec_valid(const pa_sample_spec *spec) {
assert(spec);
- if (spec->rate <= 0 || spec->channels <= 0)
- return 0;
-
- if (spec->format >= PA_SAMPLE_MAX || spec->format < 0)
+ if (spec->rate <= 0 ||
+ spec->channels <= 0 ||
+ spec->channels > PA_CHANNELS_MAX ||
+ spec->format >= PA_SAMPLE_MAX ||
+ spec->format < 0)
return 0;
return 1;
@@ -84,15 +85,15 @@ int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b) {
return (a->format == b->format) && (a->rate == b->rate) && (a->channels == b->channels);
}
-const char *pa_sample_format_to_string(pa_sample_format f) {
+const char *pa_sample_format_to_string(pa_sample_format_t f) {
static const char* const table[]= {
- [PA_SAMPLE_U8] = "U8",
- [PA_SAMPLE_ALAW] = "ALAW",
- [PA_SAMPLE_ULAW] = "ULAW",
- [PA_SAMPLE_S16LE] = "S16LE",
- [PA_SAMPLE_S16BE] = "S16BE",
- [PA_SAMPLE_FLOAT32LE] = "FLOAT32LE",
- [PA_SAMPLE_FLOAT32BE] = "FLOAT32BE",
+ [PA_SAMPLE_U8] = "u8",
+ [PA_SAMPLE_ALAW] = "aLaw",
+ [PA_SAMPLE_ULAW] = "uLaw",
+ [PA_SAMPLE_S16LE] = "s16le",
+ [PA_SAMPLE_S16BE] = "s16be",
+ [PA_SAMPLE_FLOAT32LE] = "float32le",
+ [PA_SAMPLE_FLOAT32BE] = "float32be",
};
if (f >= PA_SAMPLE_MAX)
@@ -112,44 +113,6 @@ char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) {
return s;
}
-pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b) {
- uint64_t p = a;
- p *= b;
- p /= PA_VOLUME_NORM;
-
- return (pa_volume_t) p;
-}
-
-pa_volume_t pa_volume_from_dB(double f) {
- if (f <= PA_DECIBEL_MININFTY)
- return PA_VOLUME_MUTED;
-
- return (pa_volume_t) (pow(10, f/20)*PA_VOLUME_NORM);
-}
-
-double pa_volume_to_dB(pa_volume_t v) {
- if (v == PA_VOLUME_MUTED)
- return PA_DECIBEL_MININFTY;
-
- return 20*log10((double) v/PA_VOLUME_NORM);
-}
-
-#define USER_DECIBEL_RANGE 30
-
-double pa_volume_to_user(pa_volume_t v) {
- double dB = pa_volume_to_dB(v);
-
- return dB < -USER_DECIBEL_RANGE ? 0 : dB/USER_DECIBEL_RANGE+1;
-}
-
-pa_volume_t pa_volume_from_user(double v) {
-
- if (v <= 0)
- return PA_VOLUME_MUTED;
-
- return pa_volume_from_dB((v-1)*USER_DECIBEL_RANGE);
-}
-
void pa_bytes_snprint(char *s, size_t l, unsigned v) {
if (v >= ((unsigned) 1024)*1024*1024)
snprintf(s, l, "%0.1f GB", ((double) v)/1024/1024/1024);
@@ -161,7 +124,7 @@ void pa_bytes_snprint(char *s, size_t l, unsigned v) {
snprintf(s, l, "%u B", (unsigned) v);
}
-pa_sample_format pa_parse_sample_format(const char *format) {
+pa_sample_format_t pa_parse_sample_format(const char *format) {
if (strcasecmp(format, "s16le") == 0)
return PA_SAMPLE_S16LE;
diff --git a/polyp/sample.h b/polyp/sample.h
index 739cb337b..c1b98f1cf 100644
--- a/polyp/sample.h
+++ b/polyp/sample.h
@@ -33,6 +33,9 @@
PA_C_DECL_BEGIN
+/* Maximum allowed channels */
+#define PA_CHANNELS_MAX 16
+
/** Sample format */
typedef enum pa_sample_format {
PA_SAMPLE_U8, /**< Unsigned 8 Bit PCM */
@@ -44,7 +47,7 @@ typedef enum pa_sample_format {
PA_SAMPLE_FLOAT32BE, /**< 32 Bit IEEE floating point, big endian, range -1..1 */
PA_SAMPLE_MAX, /**< Upper limit of valid sample types */
PA_SAMPLE_INVALID = -1 /**< An invalid value */
-} pa_sample_format;
+} pa_sample_format_t;
#ifdef WORDS_BIGENDIAN
/** Signed 16 Bit PCM, native endian */
@@ -71,7 +74,7 @@ typedef enum pa_sample_format {
/** A sample format and attribute specification */
typedef struct pa_sample_spec {
- pa_sample_format format; /**< The sample format */
+ pa_sample_format_t format; /**< The sample format */
uint32_t rate; /**< The sample rate. (e.g. 44100) */
uint8_t channels; /**< Audio channels. (1 for mono, 2 for stereo, ...) */
} pa_sample_spec;
@@ -85,6 +88,9 @@ size_t pa_bytes_per_second(const pa_sample_spec *spec);
/** Return the size of a frame with the specific sample type */
size_t pa_frame_size(const pa_sample_spec *spec);
+/** Return the size of a sample with the specific sample type */
+size_t pa_sample_size(const pa_sample_spec *spec);
+
/** Calculate the time the specified bytes take to play with the specified sample type */
pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec);
@@ -95,7 +101,10 @@ int pa_sample_spec_valid(const pa_sample_spec *spec);
int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b);
/* Return a descriptive string for the specified sample format. \since 0.8 */
-const char *pa_sample_format_to_string(pa_sample_format f);
+const char *pa_sample_format_to_string(pa_sample_format_t f);
+
+/** Parse a sample format text. Inverse of pa_sample_format_to_string() */
+pa_sample_format_t pa_parse_sample_format(const char *format);
/** Maximum required string length for pa_sample_spec_snprint() */
#define PA_SAMPLE_SPEC_SNPRINT_MAX 32
@@ -103,43 +112,9 @@ const char *pa_sample_format_to_string(pa_sample_format f);
/** Pretty print a sample type specification to a string */
char* pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec);
-/** Volume specification: 0: silence; < 256: diminished volume; 256: normal volume; > 256 amplified volume */
-typedef uint32_t pa_volume_t;
-
-/** Normal volume (100%) */
-#define PA_VOLUME_NORM (0x100)
-
-/** Muted volume (0%) */
-#define PA_VOLUME_MUTED (0)
-
-/** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. */
-pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b);
-
-/** Convert volume from decibel to linear level. \since 0.4 */
-pa_volume_t pa_volume_from_dB(double f);
-
-/** Convert volume from linear level to decibel. \since 0.4 */
-double pa_volume_to_dB(pa_volume_t v);
-
-/** Convert volume to scaled value understandable by the user (between 0 and 1). \since 0.6 */
-double pa_volume_to_user(pa_volume_t v);
-
-/** Convert user volume to polypaudio volume. \since 0.6 */
-pa_volume_t pa_volume_from_user(double v);
-
-#ifdef INFINITY
-#define PA_DECIBEL_MININFTY (-INFINITY)
-#else
-/** This value is used as minus infinity when using pa_volume_{to,from}_dB(). \since 0.4 */
-#define PA_DECIBEL_MININFTY (-200)
-#endif
-
/** Pretty print a byte size value. (i.e. "2.5 MB") */
void pa_bytes_snprint(char *s, size_t l, unsigned v);
-/** Parse a sample format text. Inverse of pa_sample_format_to_string() */
-pa_sample_format pa_parse_sample_format(const char *format);
-
PA_C_DECL_END
#endif
diff --git a/polyp/scache.c b/polyp/scache.c
index 32c89a998..39fa26f33 100644
--- a/polyp/scache.c
+++ b/polyp/scache.c
@@ -52,6 +52,8 @@
#include "sound-file.h"
#include "util.h"
#include "log.h"
+#include "channelmap.h"
+#include "volume.h"
#define UNLOAD_POLL_TIME 2
@@ -112,7 +114,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_NEW, e->index);
}
- e->volume = PA_VOLUME_NORM;
+ pa_cvolume_reset(&e->volume, PA_CHANNELS_MAX);
e->last_used_time = 0;
e->memchunk.memblock = NULL;
e->memchunk.index = e->memchunk.length = 0;
@@ -125,15 +127,20 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
return e;
}
-int pa_scache_add_item(pa_core *c, const char *name, pa_sample_spec *ss, 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, uint32_t *idx) {
pa_scache_entry *e;
assert(c && name);
if (!(e = scache_add_item(c, name)))
return -1;
- if (ss)
+ if (ss) {
e->sample_spec = *ss;
+ pa_channel_map_init_auto(&e->channel_map, ss->channels);
+ }
+
+ if (map)
+ e->channel_map = *map;
if (chunk) {
e->memchunk = *chunk;
@@ -161,7 +168,7 @@ int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint3
if (pa_sound_file_load(filename, &ss, &chunk, c->memblock_stat) < 0)
return -1;
- r = pa_scache_add_item(c, name, &ss, &chunk, idx);
+ r = pa_scache_add_item(c, name, &ss, NULL, &chunk, idx);
pa_memblock_unref(chunk.memblock);
return r;
@@ -230,9 +237,10 @@ void pa_scache_free(pa_core *c) {
c->mainloop->time_free(c->scache_auto_unload_event);
}
-int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, uint32_t volume) {
+int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, const pa_cvolume *volume) {
pa_scache_entry *e;
char *t;
+ pa_cvolume r;
assert(c && name && sink);
if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1)))
@@ -249,7 +257,8 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, uint32_t vo
return -1;
t = pa_sprintf_malloc("sample:%s", name);
- if (pa_play_memchunk(sink, t, &e->sample_spec, &e->memchunk, pa_volume_multiply(volume, e->volume)) < 0) {
+
+ if (pa_play_memchunk(sink, t, &e->sample_spec, &e->channel_map, &e->memchunk, pa_sw_cvolume_multiply(&r, volume, &e->volume)) < 0) {
free(t);
return -1;
}
diff --git a/polyp/scache.h b/polyp/scache.h
index c23e33de1..d667ae60c 100644
--- a/polyp/scache.h
+++ b/polyp/scache.h
@@ -31,8 +31,9 @@ typedef struct pa_scache_entry {
uint32_t index;
char *name;
- uint32_t volume;
+ pa_cvolume volume;
pa_sample_spec sample_spec;
+ pa_channel_map channel_map;
pa_memchunk memchunk;
char *filename;
@@ -41,14 +42,14 @@ typedef struct pa_scache_entry {
time_t last_used_time;
} pa_scache_entry;
-int pa_scache_add_item(pa_core *c, const char *name, pa_sample_spec *ss, 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, uint32_t *idx);
int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint32_t *idx);
int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename, uint32_t *idx);
int pa_scache_add_directory_lazy(pa_core *c, const char *pathname);
int pa_scache_remove_item(pa_core *c, const char *name);
-int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, uint32_t volume);
+int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, const pa_cvolume *cvolume);
void pa_scache_free(pa_core *c);
const char *pa_scache_get_name_by_id(pa_core *c, uint32_t id);
diff --git a/polyp/sconv-s16be.c b/polyp/sconv-s16be.c
index 3880b0431..8b076f06f 100644
--- a/polyp/sconv-s16be.c
+++ b/polyp/sconv-s16be.c
@@ -23,11 +23,19 @@
#include <config.h>
#endif
+#include "endianmacros.h"
+
#define INT16_FROM INT16_FROM_BE
#define INT16_TO INT16_TO_BE
#define pa_sconv_s16le_to_float32ne pa_sconv_s16be_to_float32ne
#define pa_sconv_s16le_from_float32ne pa_sconv_s16be_from_float32ne
+#ifdef WORDS_BIGENDIAN
+#define SWAP_WORDS 0
+#else
+#define SWAP_WORDS 1
+#endif
+
#include "sconv-s16le.h"
#include "sconv-s16le.c"
diff --git a/polyp/sconv-s16be.h b/polyp/sconv-s16be.h
index 86107fb5a..b2b6a8c74 100644
--- a/polyp/sconv-s16be.h
+++ b/polyp/sconv-s16be.h
@@ -22,7 +22,7 @@
USA.
***/
-void pa_sconv_s16be_to_float32ne(unsigned n, const void *a, unsigned an, float *b);
-void pa_sconv_s16be_from_float32ne(unsigned n, const float *a, void *b, unsigned bn);
+void pa_sconv_s16be_to_float32ne(unsigned n, const void *a, float *b);
+void pa_sconv_s16be_from_float32ne(unsigned n, const float *a, void *b);
#endif
diff --git a/polyp/sconv-s16le.c b/polyp/sconv-s16le.c
index c9682fff1..e47c5e8e8 100644
--- a/polyp/sconv-s16le.c
+++ b/polyp/sconv-s16le.c
@@ -26,6 +26,8 @@
#include <assert.h>
#include <inttypes.h>
+#include <liboil/liboilfuncs.h>
+
#include "endianmacros.h"
#include "sconv.h"
#include "sconv-s16le.h"
@@ -39,49 +41,61 @@
#define INT16_TO INT16_TO_LE
#endif
-void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, unsigned an, float *b) {
+#ifndef SWAP_WORDS
+#ifdef WORDS_BIGENDIAN
+#define SWAP_WORDS 1
+#else
+#define SWAP_WORDS 0
+#endif
+#endif
+
+void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, float *b) {
const int16_t *ca = a;
- assert(n && a && an && b);
+ assert(a);
+ assert(b);
+
+#if SWAP_WORDS == 1
+
for (; n > 0; n--) {
- unsigned i;
- float sum = 0;
-
- for (i = 0; i < an; i++) {
- int16_t s = *(ca++);
- sum += ((float) INT16_FROM(s))/0x7FFF;
- }
-
- if (sum > 1)
- sum = 1;
- if (sum < -1)
- sum = -1;
-
- *(b++) = sum;
+ int16_t s = *(ca++);
+ *(b++) = ((float) INT16_FROM(s))/0x7FFF;
}
+
+#else
+{
+ static const double add = 0, factor = 1.0/0x7FFF;
+ oil_scaleconv_f32_s16(b, ca, n, &add, &factor);
+}
+#endif
}
-void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) {
+void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b) {
int16_t *cb = b;
-
-/* pa_log("%u %p %p %u\n", n, a, b, bn); */
- assert(n && a && b && bn);
+ assert(a);
+ assert(b);
+
+#if SWAP_WORDS == 1
for (; n > 0; n--) {
- unsigned i;
int16_t s;
float v = *(a++);
if (v > 1)
v = 1;
+
if (v < -1)
v = -1;
s = (int16_t) (v * 0x7FFF);
- s = INT16_TO(s);
-
- for (i = 0; i < bn; i++)
- *(cb++) = s;
+ *(cb++) = INT16_TO(s);
}
+
+#else
+{
+ static const double add = 0, factor = 0x7FFF;
+ oil_scaleconv_s16_f32(cb, a, n, &add, &factor);
+}
+#endif
}
diff --git a/polyp/sconv-s16le.h b/polyp/sconv-s16le.h
index caed826ec..ef5e31e8a 100644
--- a/polyp/sconv-s16le.h
+++ b/polyp/sconv-s16le.h
@@ -22,7 +22,7 @@
USA.
***/
-void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, unsigned an, float *b);
-void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b, unsigned bn);
+void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, float *b);
+void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b);
#endif
diff --git a/polyp/sconv.c b/polyp/sconv.c
index 223df5d9b..1fcb5a0c8 100644
--- a/polyp/sconv.c
+++ b/polyp/sconv.c
@@ -26,6 +26,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
+
+#include <liboil/liboilfuncs.h>
+#include <liboil/liboil.h>
+
#include "endianmacros.h"
#include "sconv.h"
#include "g711.h"
@@ -33,107 +37,58 @@
#include "sconv-s16le.h"
#include "sconv-s16be.h"
-static void u8_to_float32ne(unsigned n, const void *a, unsigned an, float *b) {
- unsigned i;
+static void u8_to_float32ne(unsigned n, const void *a, float *b) {
const uint8_t *ca = a;
- assert(n && a && an && b);
-
- for (; n > 0; n--) {
- float sum = 0;
+ static const double add = -128.0/127.0, factor = 1.0/127.0;
+
+ assert(a);
+ assert(b);
- for (i = 0; i < an; i++) {
- uint8_t v = *(ca++);
- sum += (((float) v)-128)/127;
- }
-
- if (sum > 1)
- sum = 1;
- if (sum < -1)
- sum = -1;
-
- *(b++) = sum;
- }
+ oil_scaleconv_f32_u8(b, ca, n, &add, &factor);
}
-static void u8_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) {
- unsigned i;
+static void u8_from_float32ne(unsigned n, const float *a, void *b) {
uint8_t *cb = b;
+ static const double add = 128.0, factor = 127.0;
- assert(n && a && b && bn);
- for (; n > 0; n--) {
- float v = *(a++);
- uint8_t u;
-
- if (v > 1)
- v = 1;
-
- if (v < -1)
- v = -1;
+ assert(a);
+ assert(b);
- u = (uint8_t) (v*127+128);
-
- for (i = 0; i < bn; i++)
- *(cb++) = u;
- }
+ oil_scaleconv_u8_f32(cb, a, n, &add, &factor);
}
-static void float32ne_to_float32ne(unsigned n, const void *a, unsigned an, float *b) {
- unsigned i;
- const float *ca = a;
- assert(n && a && an && b);
- for (; n > 0; n--) {
- float sum = 0;
-
- for (i = 0; i < an; i++)
- sum += *(ca++);
+static void float32ne_to_float32ne(unsigned n, const void *a, float *b) {
+ assert(a);
+ assert(b);
- if (sum > 1)
- sum = 1;
- if (sum < -1)
- sum = -1;
-
- *(b++) = sum;
- }
+ oil_memcpy(b, a, sizeof(float) * n);
}
-static void float32ne_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) {
- unsigned i;
- float *cb = b;
- assert(n && a && b && bn);
- for (; n > 0; n--) {
- float v = *(a++);
- for (i = 0; i < bn; i++)
- *(cb++) = v;
- }
+static void float32ne_from_float32ne(unsigned n, const float *a, void *b) {
+ assert(a);
+ assert(b);
+
+ oil_memcpy(b, a, sizeof(float) * n);
}
-static void ulaw_to_float32ne(unsigned n, const void *a, unsigned an, float *b) {
- unsigned i;
+static void ulaw_to_float32ne(unsigned n, const void *a, float *b) {
const uint8_t *ca = a;
- assert(n && a && an && b);
- for (; n > 0; n--) {
- float sum = 0;
-
- for (i = 0; i < an; i++)
- sum += st_ulaw2linear16(*ca++) * 1.0F / 0x7FFF;
- if (sum > 1)
- sum = 1;
- if (sum < -1)
- sum = -1;
-
- *(b++) = sum;
- }
+ assert(a);
+ assert(b);
+
+ for (; n > 0; n--)
+ *(b++) = st_ulaw2linear16(*(ca++)) * 1.0F / 0x7FFF;
}
-static void ulaw_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) {
- unsigned i;
+static void ulaw_from_float32ne(unsigned n, const float *a, void *b) {
uint8_t *cb = b;
- assert(n && a && b && bn);
+ assert(a);
+ assert(b);
+
for (; n > 0; n--) {
float v = *(a++);
- uint8_t u;
if (v > 1)
v = 1;
@@ -141,40 +96,28 @@ static void ulaw_from_float32ne(unsigned n, const float *a, void *b, unsigned bn
if (v < -1)
v = -1;
- u = st_14linear2ulaw((int16_t) (v * 0x1FFF));
-
- for (i = 0; i < bn; i++)
- *(cb++) = u;
+ *(cb++) = st_14linear2ulaw((int16_t) (v * 0x1FFF));
}
}
-static void alaw_to_float32ne(unsigned n, const void *a, unsigned an, float *b) {
- unsigned i;
+static void alaw_to_float32ne(unsigned n, const void *a, float *b) {
const uint8_t *ca = a;
- assert(n && a && an && b);
- for (; n > 0; n--) {
- float sum = 0;
-
- for (i = 0; i < an; i++)
- sum += st_alaw2linear16(*ca++) * 1.0F / 0x7FFF;
- if (sum > 1)
- sum = 1;
- if (sum < -1)
- sum = -1;
+ assert(a);
+ assert(b);
- *(b++) = sum;
- }
+ for (; n > 0; n--)
+ *(b++) = st_alaw2linear16(*(ca++)) * 1.0F / 0x7FFF;
}
-static void alaw_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) {
- unsigned i;
+static void alaw_from_float32ne(unsigned n, const float *a, void *b) {
uint8_t *cb = b;
- assert(n && a && b && bn);
+ assert(a);
+ assert(b);
+
for (; n > 0; n--) {
float v = *(a++);
- uint8_t u;
if (v > 1)
v = 1;
@@ -182,15 +125,11 @@ static void alaw_from_float32ne(unsigned n, const float *a, void *b, unsigned bn
if (v < -1)
v = -1;
- u = st_13linear2alaw((int16_t) (v * 0xFFF));
-
- for (i = 0; i < bn; i++)
- *(cb++) = u;
+ *(cb++) = st_13linear2alaw((int16_t) (v * 0xFFF));
}
}
-
-pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format f) {
+pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f) {
switch(f) {
case PA_SAMPLE_U8:
return u8_to_float32ne;
@@ -209,7 +148,7 @@ pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_fo
}
}
-pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format f) {
+pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f) {
switch(f) {
case PA_SAMPLE_U8:
return u8_from_float32ne;
diff --git a/polyp/sconv.h b/polyp/sconv.h
index 2866fd419..2a0052196 100644
--- a/polyp/sconv.h
+++ b/polyp/sconv.h
@@ -24,10 +24,10 @@
#include "sample.h"
-typedef void (*pa_convert_to_float32ne_func_t)(unsigned n, const void *a, unsigned an, float *b);
-typedef void (*pa_convert_from_float32ne_func_t)(unsigned n, const float *a, void *b, unsigned bn);
+typedef void (*pa_convert_to_float32ne_func_t)(unsigned n, const void *a, float *b);
+typedef void (*pa_convert_from_float32ne_func_t)(unsigned n, const float *a, void *b);
-pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format f);
-pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format f);
+pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f);
+pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f);
#endif
diff --git a/polyp/sink-input.c b/polyp/sink-input.c
index 682b3222d..4a847e468 100644
--- a/polyp/sink-input.c
+++ b/polyp/sink-input.c
@@ -36,47 +36,66 @@
#define CONVERT_BUFFER_LENGTH 4096
-pa_sink_input* pa_sink_input_new(pa_sink *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int variable_rate, int resample_method) {
+pa_sink_input* pa_sink_input_new(
+ pa_sink *s,
+ const char *driver,
+ const char *name,
+ const pa_sample_spec *spec,
+ const pa_channel_map *map,
+ int variable_rate,
+ int resample_method) {
+
pa_sink_input *i;
pa_resampler *resampler = NULL;
int r;
char st[256];
- assert(s && spec && s->state == PA_SINK_RUNNING);
+ pa_channel_map tmap;
+
+ assert(s);
+ assert(spec);
+ assert(s->state == PA_SINK_RUNNING);
if (pa_idxset_size(s->inputs) >= PA_MAX_INPUTS_PER_SINK) {
- pa_log(__FILE__": Failed to create sink input: too many inputs per sink.\n");
+ pa_log_warn(__FILE__": Failed to create sink input: too many inputs per sink.\n");
return NULL;
}
if (resample_method == PA_RESAMPLER_INVALID)
resample_method = s->core->resample_method;
- if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec))
- if (!(resampler = pa_resampler_new(spec, &s->sample_spec, s->core->memblock_stat, resample_method)))
+ if (!map) {
+ pa_channel_map_init_auto(&tmap, spec->channels);
+ map = &tmap;
+ }
+
+ if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec) || !pa_channel_map_equal(map, &s->channel_map))
+ if (!(resampler = pa_resampler_new(spec, map, &s->sample_spec, &s->channel_map, s->core->memblock_stat, resample_method)))
return NULL;
- i = pa_xmalloc(sizeof(pa_sink_input));
+ i = pa_xnew(pa_sink_input, 1);
i->ref = 1;
i->state = PA_SINK_INPUT_RUNNING;
i->name = pa_xstrdup(name);
- i->typeid = typeid;
- i->client = NULL;
+ i->driver = pa_xstrdup(driver);
i->owner = NULL;
i->sink = s;
+ i->client = NULL;
+
i->sample_spec = *spec;
+ i->channel_map = *map;
+ pa_cvolume_reset(&i->volume, spec->channels);
+
i->peek = NULL;
i->drop = NULL;
i->kill = NULL;
i->get_latency = NULL;
- i->userdata = NULL;
i->underrun = NULL;
+ i->userdata = NULL;
- i->volume = PA_VOLUME_NORM;
i->playing = 0;
- i->resampled_chunk.memblock = NULL;
- i->resampled_chunk.index = i->resampled_chunk.length = 0;
+ pa_memchunk_reset(&i->resampled_chunk);
i->resampler = resampler;
assert(s->core);
@@ -94,7 +113,10 @@ pa_sink_input* pa_sink_input_new(pa_sink *s, pa_typeid_t typeid, const char *nam
}
void pa_sink_input_disconnect(pa_sink_input *i) {
- assert(i && i->state != PA_SINK_INPUT_DISCONNECTED && i->sink && i->sink->core);
+ assert(i);
+ assert(i->state != PA_SINK_INPUT_DISCONNECTED);
+ assert(i->sink);
+ assert(i->sink->core);
pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL);
pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
@@ -106,7 +128,9 @@ void pa_sink_input_disconnect(pa_sink_input *i) {
i->drop = NULL;
i->kill = NULL;
i->get_latency = NULL;
+ i->underrun = NULL;
+ i->playing = 0;
i->state = PA_SINK_INPUT_DISCONNECTED;
}
@@ -120,28 +144,34 @@ static void sink_input_free(pa_sink_input* i) {
if (i->resampled_chunk.memblock)
pa_memblock_unref(i->resampled_chunk.memblock);
+
if (i->resampler)
pa_resampler_free(i->resampler);
pa_xfree(i->name);
+ pa_xfree(i->driver);
pa_xfree(i);
}
void pa_sink_input_unref(pa_sink_input *i) {
- assert(i && i->ref >= 1);
+ assert(i);
+ assert(i->ref >= 1);
if (!(--i->ref))
sink_input_free(i);
}
pa_sink_input* pa_sink_input_ref(pa_sink_input *i) {
- assert(i && i->ref >= 1);
+ assert(i);
+ assert(i->ref >= 1);
+
i->ref++;
return i;
}
void pa_sink_input_kill(pa_sink_input*i) {
- assert(i && i->ref >= 1);
+ assert(i);
+ assert(i->ref >= 1);
if (i->kill)
i->kill(i);
@@ -149,7 +179,9 @@ void pa_sink_input_kill(pa_sink_input*i) {
pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) {
pa_usec_t r = 0;
- assert(i && i->ref >= 1);
+
+ assert(i);
+ assert(i->ref >= 1);
if (i->get_latency)
r += i->get_latency(i);
@@ -160,20 +192,28 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) {
return r;
}
-int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
+int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) {
int ret = -1;
- assert(i && chunk && i->ref >= 1);
+ int do_volume_adj_here;
+
+ assert(i);
+ assert(i->ref >= 1);
+ assert(chunk);
+ assert(volume);
pa_sink_input_ref(i);
if (!i->peek || !i->drop || i->state == PA_SINK_INPUT_CORKED)
goto finish;
-
+
if (!i->resampler) {
+ do_volume_adj_here = 0;
ret = i->peek(i, chunk);
goto finish;
}
+ do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);
+
while (!i->resampled_chunk.memblock) {
pa_memchunk tchunk;
size_t l;
@@ -182,6 +222,12 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
goto finish;
assert(tchunk.length);
+
+ /* It might be necessary to adjust the volume here */
+ if (do_volume_adj_here) {
+ pa_memchunk_make_writable(&tchunk, i->sink->core->memblock_stat, 0);
+ pa_volume_memchunk(&tchunk, &i->sample_spec, &i->volume);
+ }
l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH);
@@ -195,7 +241,9 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
pa_memblock_unref(tchunk.memblock);
}
- assert(i->resampled_chunk.memblock && i->resampled_chunk.length);
+ assert(i->resampled_chunk.memblock);
+ assert(i->resampled_chunk.length);
+
*chunk = i->resampled_chunk;
pa_memblock_ref(i->resampled_chunk.memblock);
@@ -207,6 +255,19 @@ finish:
i->underrun(i);
i->playing = ret >= 0;
+
+ if (ret >= 0) {
+ /* Let's see if we had to apply the volume adjustment
+ * ourselves, or if this can be done by the sink for us */
+
+ if (do_volume_adj_here)
+ /* We've both the same channel map, so let's have the sink do the adjustment for us*/
+
+ pa_cvolume_reset(volume, i->sample_spec.channels);
+ else
+ /* We had different channel maps, so we already did the adjustment */
+ *volume = i->volume;
+ }
pa_sink_input_unref(i);
@@ -214,7 +275,9 @@ finish:
}
void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
- assert(i && length && i->ref >= 1);
+ assert(i);
+ assert(i->ref >= 1);
+ assert(length > 0);
if (!i->resampler) {
if (i->drop)
@@ -222,35 +285,50 @@ void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t lengt
return;
}
- assert(i->resampled_chunk.memblock && i->resampled_chunk.length >= length);
+ assert(i->resampled_chunk.memblock);
+ assert(i->resampled_chunk.length >= length);
i->resampled_chunk.index += length;
i->resampled_chunk.length -= length;
- if (!i->resampled_chunk.length) {
+ if (i->resampled_chunk.length <= 0) {
pa_memblock_unref(i->resampled_chunk.memblock);
i->resampled_chunk.memblock = NULL;
i->resampled_chunk.index = i->resampled_chunk.length = 0;
}
}
-void pa_sink_input_set_volume(pa_sink_input *i, pa_volume_t volume) {
- assert(i && i->sink && i->sink->core && i->ref >= 1);
+void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) {
+ assert(i);
+ assert(i->ref >= 1);
+ assert(i->sink);
+ assert(i->sink->core);
- if (i->volume != volume) {
- i->volume = volume;
- pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
- }
+ if (pa_cvolume_equal(&i->volume, volume))
+ return;
+
+ i->volume = *volume;
+ pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
+}
+
+const pa_cvolume * pa_sink_input_get_volume(pa_sink_input *i) {
+ assert(i);
+ assert(i->ref >= 1);
+
+ return &i->volume;
}
void pa_sink_input_cork(pa_sink_input *i, int b) {
int n;
- assert(i && i->ref >= 1);
+
+ assert(i);
+ assert(i->ref >= 1);
if (i->state == PA_SINK_INPUT_DISCONNECTED)
return;
n = i->state == PA_SINK_INPUT_CORKED && !b;
+
i->state = b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
if (n)
@@ -258,7 +336,9 @@ void pa_sink_input_cork(pa_sink_input *i, int b) {
}
void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
- assert(i && i->resampler && i->ref >= 1);
+ assert(i);
+ assert(i->resampler);
+ assert(i->ref >= 1);
if (i->sample_spec.rate == rate)
return;
@@ -268,7 +348,8 @@ void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
}
void pa_sink_input_set_name(pa_sink_input *i, const char *name) {
- assert(i && i->ref >= 1);
+ assert(i);
+ assert(i->ref >= 1);
pa_xfree(i->name);
i->name = pa_xstrdup(name);
@@ -276,8 +357,9 @@ void pa_sink_input_set_name(pa_sink_input *i, const char *name) {
pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
}
-pa_resample_method pa_sink_input_get_resample_method(pa_sink_input *i) {
- assert(i && i->ref >= 1);
+pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
+ assert(i);
+ assert(i->ref >= 1);
if (!i->resampler)
return PA_RESAMPLER_INVALID;
diff --git a/polyp/sink-input.h b/polyp/sink-input.h
index b4c3ec7f8..1db993f5c 100644
--- a/polyp/sink-input.h
+++ b/polyp/sink-input.h
@@ -33,25 +33,27 @@ typedef struct pa_sink_input pa_sink_input;
#include "module.h"
#include "client.h"
-typedef enum {
+typedef enum pa_sink_input_state {
PA_SINK_INPUT_RUNNING,
PA_SINK_INPUT_CORKED,
PA_SINK_INPUT_DISCONNECTED
-} pa_sink_input_state ;
+} pa_sink_input_state_t;
struct pa_sink_input {
int ref;
- pa_sink_input_state state;
-
uint32_t index;
- pa_typeid_t typeid;
-
- char *name;
+ pa_sink_input_state_t state;
+
+ char *name, *driver;
pa_module *owner;
- pa_client *client;
+
pa_sink *sink;
+ pa_client *client;
+
pa_sample_spec sample_spec;
- uint32_t volume;
+ pa_channel_map channel_map;
+
+ pa_cvolume volume;
int (*peek) (pa_sink_input *i, pa_memchunk *chunk);
void (*drop) (pa_sink_input *i, const pa_memchunk *chunk, size_t length);
@@ -67,7 +69,15 @@ struct pa_sink_input {
pa_resampler *resampler;
};
-pa_sink_input* pa_sink_input_new(pa_sink *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int variable_rate, int resample_method);
+pa_sink_input* pa_sink_input_new(
+ pa_sink *s,
+ const char *driver,
+ const char *name,
+ const pa_sample_spec *spec,
+ const pa_channel_map *map,
+ int variable_rate,
+ int resample_method);
+
void pa_sink_input_unref(pa_sink_input* i);
pa_sink_input* pa_sink_input_ref(pa_sink_input* i);
@@ -79,10 +89,11 @@ void pa_sink_input_kill(pa_sink_input*i);
pa_usec_t pa_sink_input_get_latency(pa_sink_input *i);
-int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk);
+int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume);
void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length);
-void pa_sink_input_set_volume(pa_sink_input *i, pa_volume_t volume);
+void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume);
+const pa_cvolume * pa_sink_input_get_volume(pa_sink_input *i);
void pa_sink_input_cork(pa_sink_input *i, int b);
@@ -90,6 +101,6 @@ void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate);
void pa_sink_input_set_name(pa_sink_input *i, const char *name);
-pa_resample_method pa_sink_input_get_resample_method(pa_sink_input *i);
+pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i);
#endif
diff --git a/polyp/sink.c b/polyp/sink.c
index aac90c047..bb6566498 100644
--- a/polyp/sink.c
+++ b/polyp/sink.c
@@ -40,43 +40,54 @@
#define MAX_MIX_CHANNELS 32
-pa_sink* pa_sink_new(pa_core *core, pa_typeid_t typeid, const char *name, int fail, const pa_sample_spec *spec) {
+pa_sink* pa_sink_new(
+ pa_core *core,
+ const char *driver,
+ const char *name,
+ int fail,
+ const pa_sample_spec *spec,
+ const pa_channel_map *map) {
+
pa_sink *s;
char *n = NULL;
char st[256];
int r;
- assert(core && name && *name && spec);
- s = pa_xmalloc(sizeof(pa_sink));
+ assert(core);
+ assert(name);
+ assert(*name);
+ assert(spec);
+
+ s = pa_xnew(pa_sink, 1);
if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) {
pa_xfree(s);
return NULL;
}
- s->name = pa_xstrdup(name);
- s->description = NULL;
- s->typeid = typeid;
-
s->ref = 1;
+ s->core = core;
s->state = PA_SINK_RUNNING;
-
+ s->name = pa_xstrdup(name);
+ s->description = NULL;
+ s->driver = pa_xstrdup(driver);
s->owner = NULL;
- s->core = core;
+
s->sample_spec = *spec;
+ if (map)
+ s->channel_map = *map;
+ else
+ pa_channel_map_init_auto(&s->channel_map, spec->channels);
+
s->inputs = pa_idxset_new(NULL, NULL);
- n = pa_sprintf_malloc("%s_monitor", name);
- s->monitor_source = pa_source_new(core, typeid, n, 0, spec);
- assert(s->monitor_source);
- pa_xfree(n);
- s->monitor_source->monitor_of = s;
- s->monitor_source->description = pa_sprintf_malloc("Monitor source of sink '%s'", s->name);
-
- s->volume = PA_VOLUME_NORM;
+ pa_cvolume_reset(&s->sw_volume, spec->channels);
+ pa_cvolume_reset(&s->hw_volume, spec->channels);
- s->notify = NULL;
s->get_latency = NULL;
+ s->notify = NULL;
+ s->set_hw_volume = NULL;
+ s->get_hw_volume = NULL;
s->userdata = NULL;
r = pa_idxset_put(core->sinks, s, &s->index);
@@ -85,6 +96,13 @@ pa_sink* pa_sink_new(pa_core *core, pa_typeid_t typeid, const char *name, int fa
pa_sample_spec_snprint(st, sizeof(st), spec);
pa_log_info(__FILE__": created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st);
+ n = pa_sprintf_malloc("%s_monitor", name);
+ s->monitor_source = pa_source_new(core, driver, n, 0, spec, map);
+ assert(s->monitor_source);
+ pa_xfree(n);
+ s->monitor_source->monitor_of = s;
+ s->monitor_source->description = pa_sprintf_malloc("Monitor source of sink '%s'", s->name);
+
pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
return s;
@@ -92,7 +110,9 @@ pa_sink* pa_sink_new(pa_core *core, pa_typeid_t typeid, const char *name, int fa
void pa_sink_disconnect(pa_sink* s) {
pa_sink_input *i, *j = NULL;
- assert(s && s->state == PA_SINK_RUNNING);
+
+ assert(s);
+ assert(s->state == PA_SINK_RUNNING);
pa_namereg_unregister(s->core, s->name);
@@ -105,16 +125,19 @@ void pa_sink_disconnect(pa_sink* s) {
pa_source_disconnect(s->monitor_source);
pa_idxset_remove_by_data(s->core->sinks, s, NULL);
- pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
- s->notify = NULL;
s->get_latency = NULL;
+ s->notify = NULL;
+ s->get_hw_volume = NULL;
+ s->set_hw_volume = NULL;
s->state = PA_SINK_DISCONNECTED;
+ pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
}
static void sink_free(pa_sink *s) {
- assert(s && s->ref == 0);
+ assert(s);
+ assert(!s->ref);
if (s->state != PA_SINK_DISCONNECTED)
pa_sink_disconnect(s);
@@ -128,24 +151,29 @@ static void sink_free(pa_sink *s) {
pa_xfree(s->name);
pa_xfree(s->description);
+ pa_xfree(s->driver);
pa_xfree(s);
}
void pa_sink_unref(pa_sink*s) {
- assert(s && s->ref >= 1);
+ assert(s);
+ assert(s->ref >= 1);
if (!(--s->ref))
sink_free(s);
}
pa_sink* pa_sink_ref(pa_sink *s) {
- assert(s && s->ref >= 1);
+ assert(s);
+ assert(s->ref >= 1);
+
s->ref++;
return s;
}
void pa_sink_notify(pa_sink*s) {
- assert(s && s->ref >= 1);
+ assert(s);
+ assert(s->ref >= 1);
if (s->notify)
s->notify(s);
@@ -156,20 +184,25 @@ static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) {
pa_sink_input *i;
unsigned n = 0;
- assert(s && s->ref >= 1 && info);
+ assert(s);
+ assert(s->ref >= 1);
+ assert(info);
for (i = pa_idxset_first(s->inputs, &idx); maxinfo > 0 && i; i = pa_idxset_next(s->inputs, &idx)) {
+ /* Increase ref counter, to make sure that this input doesn't
+ * vanish while we still need it */
pa_sink_input_ref(i);
- if (pa_sink_input_peek(i, &info->chunk) < 0) {
+ if (pa_sink_input_peek(i, &info->chunk, &info->volume) < 0) {
pa_sink_input_unref(i);
continue;
}
- info->volume = i->volume;
info->userdata = i;
- assert(info->chunk.memblock && info->chunk.memblock->data && info->chunk.length);
+ assert(info->chunk.memblock);
+ assert(info->chunk.memblock->data);
+ assert(info->chunk.length);
info++;
maxinfo--;
@@ -180,15 +213,21 @@ static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) {
}
static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned maxinfo, size_t length) {
- assert(s && s->ref >= 1 && info);
+ assert(s);
+ assert(s->ref >= 1);
+ assert(info);
for (; maxinfo > 0; maxinfo--, info++) {
pa_sink_input *i = info->userdata;
- assert(i && info->chunk.memblock);
+ assert(i);
+ assert(info->chunk.memblock);
+
+ /* Drop read data */
pa_sink_input_drop(i, &info->chunk, length);
pa_memblock_unref(info->chunk.memblock);
+ /* Decrease ref counter */
pa_sink_input_unref(i);
info->userdata = NULL;
}
@@ -197,8 +236,8 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned maxinfo, size_t
int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
pa_mix_info info[MAX_MIX_CHANNELS];
unsigned n;
- size_t l;
int r = -1;
+
assert(s);
assert(s->ref >= 1);
assert(length);
@@ -212,37 +251,29 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
goto finish;
if (n == 1) {
- uint32_t volume = PA_VOLUME_NORM;
- pa_sink_input *i = info[0].userdata;
- assert(i);
+ pa_cvolume volume;
+
*result = info[0].chunk;
pa_memblock_ref(result->memblock);
if (result->length > length)
result->length = length;
- l = result->length;
-
- if (s->volume != PA_VOLUME_NORM || info[0].volume != PA_VOLUME_NORM)
- volume = pa_volume_multiply(s->volume, info[0].volume);
+ pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume);
- if (volume != PA_VOLUME_NORM) {
+ if (!pa_cvolume_is_norm(&volume)) {
pa_memchunk_make_writable(result, s->core->memblock_stat, 0);
- pa_volume_memchunk(result, &s->sample_spec, volume);
+ pa_volume_memchunk(result, &s->sample_spec, &volume);
}
} else {
result->memblock = pa_memblock_new(length, s->core->memblock_stat);
assert(result->memblock);
- result->length = l = pa_mix(info, n, result->memblock->data, length, &s->sample_spec, s->volume);
+ result->length = pa_mix(info, n, result->memblock->data, length, &s->sample_spec, &s->sw_volume);
result->index = 0;
-
- assert(l);
}
- inputs_drop(s, info, n, l);
-
- assert(s->monitor_source);
+ inputs_drop(s, info, n, result->length);
pa_source_post(s->monitor_source, result);
r = 0;
@@ -256,9 +287,14 @@ finish:
int pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
pa_mix_info info[MAX_MIX_CHANNELS];
unsigned n;
- size_t l;
int r = -1;
- assert(s && s->ref >= 1 && target && target->length && target->memblock && target->memblock->data);
+
+ assert(s);
+ assert(s->ref >= 1);
+ assert(target);
+ assert(target->memblock);
+ assert(target->length);
+ assert(target->memblock->data);
pa_sink_ref(s);
@@ -268,27 +304,27 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
goto finish;
if (n == 1) {
- uint32_t volume = PA_VOLUME_NORM;
+ pa_cvolume volume;
- l = target->length;
- if (l > info[0].chunk.length)
- l = info[0].chunk.length;
+ if (target->length > info[0].chunk.length)
+ target->length = info[0].chunk.length;
- memcpy((uint8_t*) target->memblock->data+target->index, (uint8_t*) info[0].chunk.memblock->data + info[0].chunk.index, l);
- target->length = l;
-
- if (s->volume != PA_VOLUME_NORM || info[0].volume != PA_VOLUME_NORM)
- volume = pa_volume_multiply(s->volume, info[0].volume);
+ memcpy((uint8_t*) target->memblock->data + target->index,
+ (uint8_t*) info[0].chunk.memblock->data + info[0].chunk.index,
+ target->length);
- if (volume != PA_VOLUME_NORM)
- pa_volume_memchunk(target, &s->sample_spec, volume);
+ pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume);
+
+ if (!pa_cvolume_is_norm(&volume))
+ pa_volume_memchunk(target, &s->sample_spec, &volume);
} else
- target->length = l = pa_mix(info, n, (uint8_t*) target->memblock->data+target->index, target->length, &s->sample_spec, s->volume);
+ target->length = pa_mix(info, n,
+ (uint8_t*) target->memblock->data + target->index,
+ target->length,
+ &s->sample_spec,
+ &s->sw_volume);
- assert(l);
- inputs_drop(s, info, n, l);
-
- assert(s->monitor_source);
+ inputs_drop(s, info, n, target->length);
pa_source_post(s->monitor_source, target);
r = 0;
@@ -302,7 +338,13 @@ finish:
void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
pa_memchunk chunk;
size_t l, d;
- assert(s && s->ref >= 1 && target && target->memblock && target->length && target->memblock->data);
+
+ assert(s);
+ assert(s->ref >= 1);
+ assert(target);
+ assert(target->memblock);
+ assert(target->length);
+ assert(target->memblock->data);
pa_sink_ref(s);
@@ -331,7 +373,10 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
}
void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
- assert(s && s->ref >= 1 && length && result);
+ assert(s);
+ assert(s->ref >= 1);
+ assert(length);
+ assert(result);
/*** This needs optimization ***/
@@ -342,7 +387,8 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
}
pa_usec_t pa_sink_get_latency(pa_sink *s) {
- assert(s && s->ref >= 1);
+ assert(s);
+ assert(s->ref >= 1);
if (!s->get_latency)
return 0;
@@ -351,7 +397,8 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) {
}
void pa_sink_set_owner(pa_sink *s, pa_module *m) {
- assert(s && s->ref >= 1);
+ assert(s);
+ assert(s->ref >= 1);
s->owner = m;
@@ -359,11 +406,40 @@ void pa_sink_set_owner(pa_sink *s, pa_module *m) {
pa_source_set_owner(s->monitor_source, m);
}
-void pa_sink_set_volume(pa_sink *s, pa_volume_t volume) {
- assert(s && s->ref >= 1);
+void pa_sink_set_volume(pa_sink *s, pa_mixer_t m, const pa_cvolume *volume) {
+ pa_cvolume *v;
- if (s->volume != volume) {
- s->volume = volume;
- pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
- }
+ assert(s);
+ assert(s->ref >= 1);
+ assert(volume);
+
+ if (m == PA_MIXER_HARDWARE && s->set_hw_volume)
+ v = &s->hw_volume;
+ else
+ v = &s->sw_volume;
+
+ if (pa_cvolume_equal(v, volume))
+ return;
+
+ *v = *volume;
+
+ if (v == &s->hw_volume)
+ if (s->set_hw_volume(s) < 0)
+ s->sw_volume = *volume;
+
+ pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+}
+
+const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_mixer_t m) {
+ assert(s);
+ assert(s->ref >= 1);
+
+ if (m == PA_MIXER_HARDWARE && s->set_hw_volume) {
+
+ if (s->get_hw_volume)
+ s->get_hw_volume(s);
+
+ return &s->hw_volume;
+ } else
+ return &s->sw_volume;
}
diff --git a/polyp/sink.h b/polyp/sink.h
index 22d908582..33aba2331 100644
--- a/polyp/sink.h
+++ b/polyp/sink.h
@@ -30,39 +30,55 @@ typedef struct pa_sink pa_sink;
#include "sample.h"
#include "idxset.h"
#include "source.h"
-#include "typeid.h"
+#include "channelmap.h"
#include "module.h"
+#include "volume.h"
#define PA_MAX_INPUTS_PER_SINK 6
typedef enum pa_sink_state {
PA_SINK_RUNNING,
PA_SINK_DISCONNECTED
-} pa_sink_state;
+} pa_sink_state_t;
+
+typedef enum pa_mixer {
+ PA_MIXER_SOFTWARE,
+ PA_MIXER_HARDWARE
+} pa_mixer_t;
struct pa_sink {
int ref;
- pa_sink_state state;
-
uint32_t index;
- pa_typeid_t typeid;
+ pa_core *core;
+ pa_sink_state_t state;
- char *name, *description;
+ char *name, *description, *driver;
pa_module *owner;
- pa_core *core;
+
pa_sample_spec sample_spec;
- pa_idxset *inputs;
+ pa_channel_map channel_map;
+ pa_idxset *inputs;
pa_source *monitor_source;
-
- pa_volume_t volume;
+
+ pa_cvolume hw_volume, sw_volume;
void (*notify)(pa_sink*sink);
pa_usec_t (*get_latency)(pa_sink *s);
+ int (*set_hw_volume)(pa_sink *s);
+ int (*get_hw_volume)(pa_sink *s);
+
void *userdata;
};
-pa_sink* pa_sink_new(pa_core *core, pa_typeid_t typeid, const char *name, int fail, const pa_sample_spec *spec);
+pa_sink* pa_sink_new(
+ pa_core *core,
+ const char *driver,
+ const char *name,
+ int namereg_fail,
+ const pa_sample_spec *spec,
+ const pa_channel_map *map);
+
void pa_sink_disconnect(pa_sink* s);
void pa_sink_unref(pa_sink*s);
pa_sink* pa_sink_ref(pa_sink *s);
@@ -78,6 +94,7 @@ void pa_sink_notify(pa_sink*s);
void pa_sink_set_owner(pa_sink *sink, pa_module *m);
-void pa_sink_set_volume(pa_sink *sink, pa_volume_t volume);
+void pa_sink_set_volume(pa_sink *sink, pa_mixer_t m, const pa_cvolume *volume);
+const pa_cvolume *pa_sink_get_volume(pa_sink *sink, pa_mixer_t m);
#endif
diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index a884aa617..29c9775ef 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -173,7 +173,7 @@ static void connect_fixed_cb(pa_mainloop_api *m, pa_defer_event *e, void *userda
do_call(c);
}
-static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) {
+static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
pa_socket_client *c = userdata;
assert(m && c && c->io_event == e && fd >= 0);
do_call(c);
@@ -344,7 +344,7 @@ pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[
#ifdef HAVE_LIBASYNCNS
-static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) {
+static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
pa_socket_client *c = userdata;
struct addrinfo *res = NULL;
int ret;
diff --git a/polyp/socket-server.c b/polyp/socket-server.c
index 6f1794bc9..262b32a76 100644
--- a/polyp/socket-server.c
+++ b/polyp/socket-server.c
@@ -78,7 +78,7 @@ struct pa_socket_server {
enum { SOCKET_SERVER_GENERIC, SOCKET_SERVER_IPV4, SOCKET_SERVER_UNIX, SOCKET_SERVER_IPV6 } type;
};
-static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) {
+static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
pa_socket_server *s = userdata;
pa_iochannel *io;
int nfd;
diff --git a/polyp/sound-file-stream.c b/polyp/sound-file-stream.c
index a277eb254..881e30772 100644
--- a/polyp/sound-file-stream.c
+++ b/polyp/sound-file-stream.c
@@ -36,7 +36,6 @@
#include "log.h"
#define BUF_SIZE (1024*10)
-#define PA_TYPEID_SOUND_FILE PA_TYPEID_MAKE('S', 'N', 'D', 'F')
struct userdata {
SNDFILE *sndfile;
@@ -116,15 +115,12 @@ static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t le
}
}
-int pa_play_file(pa_sink *sink, const char *fname, pa_volume_t volume) {
+int pa_play_file(pa_sink *sink, const char *fname, const pa_cvolume *volume) {
struct userdata *u = NULL;
SF_INFO sfinfo;
pa_sample_spec ss;
assert(sink && fname);
- if (volume <= 0)
- goto fail;
-
u = pa_xmalloc(sizeof(struct userdata));
u->sink_input = NULL;
u->memchunk.memblock = NULL;
@@ -161,10 +157,11 @@ int pa_play_file(pa_sink *sink, const char *fname, pa_volume_t volume) {
goto fail;
}
- if (!(u->sink_input = pa_sink_input_new(sink, PA_TYPEID_SOUND_FILE, fname, &ss, 0, -1)))
+ if (!(u->sink_input = pa_sink_input_new(sink, __FILE__, fname, &ss, NULL, 0, -1)))
goto fail;
- u->sink_input->volume = volume;
+ if (volume)
+ u->sink_input->volume = *volume;
u->sink_input->peek = sink_input_peek;
u->sink_input->drop = sink_input_drop;
u->sink_input->kill = sink_input_kill;
diff --git a/polyp/sound-file-stream.h b/polyp/sound-file-stream.h
index 0b383f963..2e56ef49b 100644
--- a/polyp/sound-file-stream.h
+++ b/polyp/sound-file-stream.h
@@ -24,6 +24,6 @@
#include "sink.h"
-int pa_play_file(pa_sink *sink, const char *fname, pa_volume_t volume);
+int pa_play_file(pa_sink *sink, const char *fname, const pa_cvolume *volume);
#endif
diff --git a/polyp/source-output.c b/polyp/source-output.c
index 7a5406336..e1d8ccf72 100644
--- a/polyp/source-output.c
+++ b/polyp/source-output.c
@@ -33,13 +33,24 @@
#include "subscribe.h"
#include "log.h"
-pa_source_output* pa_source_output_new(pa_source *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int resample_method) {
+pa_source_output* pa_source_output_new(
+ pa_source *s,
+ const char *driver,
+ const char *name,
+ const pa_sample_spec *spec,
+ const pa_channel_map *map,
+ int resample_method) {
+
pa_source_output *o;
pa_resampler *resampler = NULL;
int r;
char st[256];
- assert(s && spec);
+ pa_channel_map tmap;
+ assert(s);
+ assert(spec);
+ assert(s->state == PA_SOURCE_RUNNING);
+
if (pa_idxset_size(s->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) {
pa_log(__FILE__": Failed to create source output: too many outputs per source.\n");
return NULL;
@@ -48,25 +59,31 @@ pa_source_output* pa_source_output_new(pa_source *s, pa_typeid_t typeid, const c
if (resample_method == PA_RESAMPLER_INVALID)
resample_method = s->core->resample_method;
- if (!pa_sample_spec_equal(&s->sample_spec, spec))
- if (!(resampler = pa_resampler_new(&s->sample_spec, spec, s->core->memblock_stat, resample_method)))
+ if (!map) {
+ pa_channel_map_init_auto(&tmap, spec->channels);
+ map = &tmap;
+ }
+
+ if (!pa_sample_spec_equal(&s->sample_spec, spec) || !pa_channel_map_equal(&s->channel_map, map))
+ if (!(resampler = pa_resampler_new(&s->sample_spec, &s->channel_map, spec, map, s->core->memblock_stat, resample_method)))
return NULL;
o = pa_xmalloc(sizeof(pa_source_output));
o->ref = 1;
o->state = PA_SOURCE_OUTPUT_RUNNING;
o->name = pa_xstrdup(name);
- o->typeid = typeid;
-
- o->client = NULL;
+ o->driver = pa_xstrdup(driver);
o->owner = NULL;
o->source = s;
+ o->client = NULL;
+
o->sample_spec = *spec;
+ o->channel_map = *map;
o->push = NULL;
o->kill = NULL;
- o->userdata = NULL;
o->get_latency = NULL;
+ o->userdata = NULL;
o->resampler = resampler;
@@ -85,7 +102,10 @@ pa_source_output* pa_source_output_new(pa_source *s, pa_typeid_t typeid, const c
}
void pa_source_output_disconnect(pa_source_output*o) {
- assert(o && o->state != PA_SOURCE_OUTPUT_DISCONNECTED && o->source && o->source->core);
+ assert(o);
+ assert(o->state != PA_SOURCE_OUTPUT_DISCONNECTED);
+ assert(o->source);
+ assert(o->source->core);
pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL);
pa_idxset_remove_by_data(o->source->outputs, o, NULL);
@@ -95,7 +115,7 @@ void pa_source_output_disconnect(pa_source_output*o) {
o->push = NULL;
o->kill = NULL;
-
+ o->get_latency = NULL;
o->state = PA_SOURCE_OUTPUT_DISCONNECTED;
}
@@ -112,26 +132,31 @@ static void source_output_free(pa_source_output* o) {
pa_resampler_free(o->resampler);
pa_xfree(o->name);
+ pa_xfree(o->driver);
pa_xfree(o);
}
void pa_source_output_unref(pa_source_output* o) {
- assert(o && o->ref >= 1);
+ assert(o);
+ assert(o->ref >= 1);
if (!(--o->ref))
source_output_free(o);
}
pa_source_output* pa_source_output_ref(pa_source_output *o) {
- assert(o && o->ref >= 1);
+ assert(o);
+ assert(o->ref >= 1);
+
o->ref++;
return o;
}
void pa_source_output_kill(pa_source_output*o) {
- assert(o && o->ref >= 1);
+ assert(o);
+ assert(o->ref >= 1);
if (o->kill)
o->kill(o);
@@ -139,7 +164,11 @@ void pa_source_output_kill(pa_source_output*o) {
void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
pa_memchunk rchunk;
- assert(o && chunk && chunk->length && o->push);
+
+ assert(o);
+ assert(chunk);
+ assert(chunk->length);
+ assert(o->push);
if (o->state == PA_SOURCE_OUTPUT_CORKED)
return;
@@ -159,7 +188,9 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
}
void pa_source_output_set_name(pa_source_output *o, const char *name) {
- assert(o && o->ref >= 1);
+ assert(o);
+ assert(o->ref >= 1);
+
pa_xfree(o->name);
o->name = pa_xstrdup(name);
@@ -167,7 +198,8 @@ void pa_source_output_set_name(pa_source_output *o, const char *name) {
}
pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
- assert(o && o->ref >= 1);
+ assert(o);
+ assert(o->ref >= 1);
if (o->get_latency)
return o->get_latency(o);
@@ -176,7 +208,8 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
}
void pa_source_output_cork(pa_source_output *o, int b) {
- assert(o && o->ref >= 1);
+ assert(o);
+ assert(o->ref >= 1);
if (o->state == PA_SOURCE_OUTPUT_DISCONNECTED)
return;
@@ -184,9 +217,10 @@ void pa_source_output_cork(pa_source_output *o, int b) {
o->state = b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
}
-pa_resample_method pa_source_output_get_resample_method(pa_source_output *o) {
- assert(o && o->ref >= 1);
-
+pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) {
+ assert(o);
+ assert(o->ref >= 1);
+
if (!o->resampler)
return PA_RESAMPLER_INVALID;
diff --git a/polyp/source-output.h b/polyp/source-output.h
index ef8f9fa92..f8e4b1525 100644
--- a/polyp/source-output.h
+++ b/polyp/source-output.h
@@ -37,20 +37,21 @@ typedef enum {
PA_SOURCE_OUTPUT_RUNNING,
PA_SOURCE_OUTPUT_CORKED,
PA_SOURCE_OUTPUT_DISCONNECTED
-} pa_source_output_state;
+} pa_source_output_state_t;
struct pa_source_output {
int ref;
- pa_source_output_state state;
-
uint32_t index;
- pa_typeid_t typeid;
-
- char *name;
+ pa_source_output_state_t state;
+
+ char *name, *driver;
pa_module *owner;
- pa_client *client;
+
pa_source *source;
+ pa_client *client;
+
pa_sample_spec sample_spec;
+ pa_channel_map channel_map;
void (*push)(pa_source_output *o, const pa_memchunk *chunk);
void (*kill)(pa_source_output* o);
@@ -61,7 +62,14 @@ struct pa_source_output {
void *userdata;
};
-pa_source_output* pa_source_output_new(pa_source *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int resample_method);
+pa_source_output* pa_source_output_new(
+ pa_source *s,
+ const char *driver,
+ const char *name,
+ const pa_sample_spec *spec,
+ const pa_channel_map *map,
+ int resample_method);
+
void pa_source_output_unref(pa_source_output* o);
pa_source_output* pa_source_output_ref(pa_source_output *o);
@@ -79,6 +87,6 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *i);
void pa_source_output_cork(pa_source_output *i, int b);
-pa_resample_method pa_source_output_get_resample_method(pa_source_output *o);
+pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o);
#endif
diff --git a/polyp/source.c b/polyp/source.c
index c287899e4..6e377b20e 100644
--- a/polyp/source.c
+++ b/polyp/source.c
@@ -35,13 +35,24 @@
#include "subscribe.h"
#include "log.h"
-pa_source* pa_source_new(pa_core *core, pa_typeid_t typeid, const char *name, int fail, const pa_sample_spec *spec) {
+pa_source* pa_source_new(
+ pa_core *core,
+ const char *driver,
+ const char *name,
+ int fail,
+ const pa_sample_spec *spec,
+ const pa_channel_map *map) {
+
pa_source *s;
char st[256];
int r;
- assert(core && spec && name && *name);
+
+ assert(core);
+ assert(name);
+ assert(*name);
+ assert(spec);
- s = pa_xmalloc(sizeof(pa_source));
+ s = pa_xnew(pa_source, 1);
if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SOURCE, s, fail))) {
pa_xfree(s);
@@ -49,15 +60,19 @@ pa_source* pa_source_new(pa_core *core, pa_typeid_t typeid, const char *name, in
}
s->ref = 1;
+ s->core = core;
s->state = PA_SOURCE_RUNNING;
-
s->name = pa_xstrdup(name);
s->description = NULL;
- s->typeid = typeid;
-
+ s->driver = pa_xstrdup(driver);
s->owner = NULL;
- s->core = core;
+
s->sample_spec = *spec;
+ if (map)
+ s->channel_map = *map;
+ else
+ pa_channel_map_init_auto(&s->channel_map, spec->channels);
+
s->outputs = pa_idxset_new(NULL, NULL);
s->monitor_of = NULL;
@@ -78,7 +93,9 @@ pa_source* pa_source_new(pa_core *core, pa_typeid_t typeid, const char *name, in
void pa_source_disconnect(pa_source *s) {
pa_source_output *o, *j = NULL;
- assert(s && s->state == PA_SOURCE_RUNNING);
+
+ assert(s);
+ assert(s->state == PA_SOURCE_RUNNING);
pa_namereg_unregister(s->core, s->name);
@@ -89,15 +106,17 @@ void pa_source_disconnect(pa_source *s) {
}
pa_idxset_remove_by_data(s->core->sources, s, NULL);
- pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
+ s->get_latency = NULL;
s->notify = NULL;
s->state = PA_SOURCE_DISCONNECTED;
+ pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
}
static void source_free(pa_source *s) {
- assert(s && !s->ref);
+ assert(s);
+ assert(!s->ref);
if (s->state != PA_SOURCE_DISCONNECTED)
pa_source_disconnect(s);
@@ -108,40 +127,49 @@ static void source_free(pa_source *s) {
pa_xfree(s->name);
pa_xfree(s->description);
+ pa_xfree(s->driver);
pa_xfree(s);
}
void pa_source_unref(pa_source *s) {
- assert(s && s->ref >= 1);
+ assert(s);
+ assert(s->ref >= 1);
if (!(--s->ref))
source_free(s);
}
pa_source* pa_source_ref(pa_source *s) {
- assert(s && s->ref >= 1);
+ assert(s);
+ assert(s->ref >= 1);
+
s->ref++;
return s;
}
void pa_source_notify(pa_source*s) {
- assert(s && s->ref >= 1);
+ assert(s);
+ assert(s->ref >= 1);
if (s->notify)
s->notify(s);
}
static int do_post(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void*userdata) {
- const pa_memchunk *chunk = userdata;
pa_source_output *o = p;
- assert(o && o->push && del && chunk);
+ const pa_memchunk *chunk = userdata;
+
+ assert(o);
+ assert(chunk);
pa_source_output_push(o, chunk);
return 0;
}
void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
- assert(s && s->ref >= 1 && chunk);
+ assert(s);
+ assert(s->ref >= 1);
+ assert(chunk);
pa_source_ref(s);
pa_idxset_foreach(s->outputs, do_post, (void*) chunk);
@@ -150,11 +178,14 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
void pa_source_set_owner(pa_source *s, pa_module *m) {
assert(s);
+ assert(s->ref >= 1);
+
s->owner = m;
}
pa_usec_t pa_source_get_latency(pa_source *s) {
- assert(s && s->ref >= 1);
+ assert(s);
+ assert(s->ref >= 1);
if (!s->get_latency)
return 0;
diff --git a/polyp/source.h b/polyp/source.h
index c7f8d059a..823a9424d 100644
--- a/polyp/source.h
+++ b/polyp/source.h
@@ -31,7 +31,7 @@ typedef struct pa_source pa_source;
#include "memblock.h"
#include "memchunk.h"
#include "sink.h"
-#include "typeid.h"
+#include "channelmap.h"
#include "module.h"
#define PA_MAX_OUTPUTS_PER_SOURCE 16
@@ -39,28 +39,37 @@ typedef struct pa_source pa_source;
typedef enum pa_source_state {
PA_SOURCE_RUNNING,
PA_SOURCE_DISCONNECTED
-} pa_source_state;
+} pa_source_state_t;
struct pa_source {
int ref;
- pa_source_state state;
-
uint32_t index;
- pa_typeid_t typeid;
+ pa_core *core;
+ pa_source_state_t state;
- char *name, *description;
+ char *name, *description, *driver;
pa_module *owner;
- pa_core *core;
+
pa_sample_spec sample_spec;
+ pa_channel_map channel_map;
+
pa_idxset *outputs;
pa_sink *monitor_of;
-
+
void (*notify)(pa_source*source);
pa_usec_t (*get_latency)(pa_source *s);
+
void *userdata;
};
-pa_source* pa_source_new(pa_core *core, pa_typeid_t typeid, const char *name, int fail, const pa_sample_spec *spec);
+pa_source* pa_source_new(
+ pa_core *core,
+ const char *driver,
+ const char *name,
+ int namereg_fail,
+ const pa_sample_spec *spec,
+ const pa_channel_map *map);
+
void pa_source_disconnect(pa_source *s);
void pa_source_unref(pa_source *s);
pa_source* pa_source_ref(pa_source *c);
diff --git a/polyp/subscribe.c b/polyp/subscribe.c
index d3db90f74..e8b3c8418 100644
--- a/polyp/subscribe.c
+++ b/polyp/subscribe.c
@@ -41,22 +41,22 @@
struct pa_subscription {
pa_core *core;
int dead;
- void (*callback)(pa_core *c, pa_subscription_event_type t, uint32_t index, void *userdata);
+ void (*callback)(pa_core *c, pa_subscription_event_type_t t, uint32_t index, void *userdata);
void *userdata;
- pa_subscription_mask mask;
+ pa_subscription_mask_t mask;
pa_subscription *prev, *next;
};
struct pa_subscription_event {
- pa_subscription_event_type type;
+ pa_subscription_event_type_t type;
uint32_t index;
};
static void sched_event(pa_core *c);
/* Allocate a new subscription object for the given subscription mask. Use the specified callback function and user data */
-pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask m, void (*callback)(pa_core *c, pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
+pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, void (*callback)(pa_core *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata) {
pa_subscription *s;
assert(c);
@@ -210,7 +210,7 @@ static void sched_event(pa_core *c) {
}
/* Append a new subscription event to the subscription event queue and schedule a main loop event */
-void pa_subscription_post(pa_core *c, pa_subscription_event_type t, uint32_t index) {
+void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t index) {
pa_subscription_event *e;
assert(c);
diff --git a/polyp/subscribe.h b/polyp/subscribe.h
index 6980328fb..625159e37 100644
--- a/polyp/subscribe.h
+++ b/polyp/subscribe.h
@@ -28,10 +28,10 @@ typedef struct pa_subscription_event pa_subscription_event;
#include "core.h"
#include "native-common.h"
-pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask m, void (*callback)(pa_core *c, pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
+pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, void (*callback)(pa_core *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata);
void pa_subscription_free(pa_subscription*s);
void pa_subscription_free_all(pa_core *c);
-void pa_subscription_post(pa_core *c, pa_subscription_event_type t, uint32_t idx);
+void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t idx);
#endif
diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c
index 28b1afa6c..d49804112 100644
--- a/polyp/tagstruct.c
+++ b/polyp/tagstruct.c
@@ -54,7 +54,9 @@ enum tags {
TAG_BOOLEAN_TRUE = '1',
TAG_BOOLEAN_FALSE = '0',
TAG_TIMEVAL = 'T',
- TAG_USEC = 'U' /* 64bit unsigned */
+ TAG_USEC = 'U' /* 64bit unsigned */,
+ TAG_CHANNEL_MAP = 'm',
+ TAG_CVOLUME = 'v'
};
struct pa_tagstruct {
@@ -204,6 +206,34 @@ void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t u) {
t->length += 9;
}
+void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map) {
+ unsigned i;
+
+ assert(t);
+ extend(t, 2 + map->channels);
+
+ t->data[t->length++] = TAG_CHANNEL_MAP;
+ t->data[t->length++] = map->channels;
+
+ for (i = 0; i < map->channels; i ++)
+ t->data[t->length++] = (uint8_t) map->map[i];
+}
+
+void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) {
+ unsigned i;
+
+ assert(t);
+ extend(t, 2 + cvolume->channels * sizeof(pa_volume_t));
+
+ t->data[t->length++] = TAG_CVOLUME;
+ t->data[t->length++] = cvolume->channels;
+
+ for (i = 0; i < cvolume->channels; i ++) {
+ *(pa_volume_t*) (t->data + t->length) = htonl(cvolume->values[i]);
+ t->length += sizeof(pa_volume_t);
+ }
+}
+
int pa_tagstruct_gets(pa_tagstruct*t, const char **s) {
int error = 0;
size_t n;
@@ -283,6 +313,9 @@ int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss) {
ss->channels = t->data[t->rindex+2];
memcpy(&ss->rate, t->data+t->rindex+3, 4);
ss->rate = ntohl(ss->rate);
+
+ if (!pa_sample_spec_valid(ss))
+ return -1;
t->rindex += 7;
return 0;
@@ -387,3 +420,59 @@ int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *u) {
t->rindex +=9;
return 0;
}
+
+int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) {
+ unsigned i;
+
+ assert(t);
+ assert(map);
+
+ if (t->rindex+2 > t->length)
+ return -1;
+
+ if (t->data[t->rindex] != TAG_CHANNEL_MAP)
+ return -1;
+
+ if ((map->channels = t->data[t->rindex+1]) > PA_CHANNELS_MAX)
+ return -1;
+
+ if (t->rindex+2+map->channels > t->length)
+ return -1;
+
+ for (i = 0; i < map->channels; i ++)
+ map->map[i] = (int8_t) t->data[t->rindex + 2 + i];
+
+ if (!pa_channel_map_valid(map))
+ return -1;
+
+ t->rindex += 2 + map->channels;
+ return 0;
+}
+
+int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) {
+ unsigned i;
+
+ assert(t);
+ assert(cvolume);
+
+ if (t->rindex+2 > t->length)
+ return -1;
+
+ if (t->data[t->rindex] != TAG_CVOLUME)
+ return -1;
+
+ if ((cvolume->channels = t->data[t->rindex+1]) > PA_CHANNELS_MAX)
+ return -1;
+
+ if (t->rindex+2+cvolume->channels*sizeof(pa_volume_t) > t->length)
+ return -1;
+
+ for (i = 0; i < cvolume->channels; i ++)
+ cvolume->values[i] = (pa_volume_t) ntohl(*((pa_volume_t*) (t->data + t->rindex + 2)+i));
+
+ if (!pa_cvolume_valid(cvolume))
+ return -1;
+
+ t->rindex += 2 + cvolume->channels * sizeof(pa_volume_t);
+ return 0;
+}
diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h
index 85b324b7e..cd6a8f999 100644
--- a/polyp/tagstruct.h
+++ b/polyp/tagstruct.h
@@ -28,6 +28,8 @@
#include <time.h>
#include "sample.h"
+#include "channelmap.h"
+#include "volume.h"
typedef struct pa_tagstruct pa_tagstruct;
@@ -44,6 +46,8 @@ void pa_tagstruct_put_arbitrary(pa_tagstruct*t, const void *p, size_t length);
void pa_tagstruct_put_boolean(pa_tagstruct*t, int b);
void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv);
void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u);
+void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map);
+void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume);
int pa_tagstruct_gets(pa_tagstruct*t, const char **s);
int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c);
@@ -54,6 +58,8 @@ int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length);
int pa_tagstruct_get_boolean(pa_tagstruct *t, int *b);
int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv);
int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u);
+int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map);
+int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *v);
int pa_tagstruct_eof(pa_tagstruct*t);
const uint8_t* pa_tagstruct_data(pa_tagstruct*t, size_t *l);
diff --git a/polyp/typeid.c b/polyp/typeid.c
deleted file mode 100644
index 70d3df336..000000000
--- a/polyp/typeid.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/* $Id$ */
-
-/***
- This file is part of polypaudio.
-
- polypaudio 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.1 of the
- License, or (at your option) any later version.
-
- polypaudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with polypaudio; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- USA.
-***/
-
-#include <stdio.h>
-
-#include "typeid.h"
-
-char *pa_typeid_to_string(pa_typeid_t id, char *ret_s, size_t length) {
- if (id == PA_TYPEID_UNKNOWN)
- snprintf(ret_s, length, "????");
- else
- snprintf(ret_s, length, "%c%c%c%c", (char) (id >> 24), (char) (id >> 16), (char) (id >> 8), (char) (id));
-
- return ret_s;
-}
diff --git a/polyp/typeid.h b/polyp/typeid.h
deleted file mode 100644
index cc1676bc0..000000000
--- a/polyp/typeid.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef footypeidhfoo
-#define footypeidhfoo
-
-/* $Id$ */
-
-/***
- This file is part of polypaudio.
-
- polypaudio 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.1 of the
- License, or (at your option) any later version.
-
- polypaudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with polypaudio; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- USA.
-***/
-
-#include <inttypes.h>
-#include <sys/types.h>
-
-#include <polyp/cdecl.h>
-
-PA_C_DECL_BEGIN
-
-typedef uint32_t pa_typeid_t;
-
-#define PA_TYPEID_UNKNOWN ((pa_typeid_t) -1)
-
-char *pa_typeid_to_string(pa_typeid_t id, char *ret_s, size_t length);
-
-#define PA_TYPEID_MAKE(a,b,c,d) (\
- (((pa_typeid_t) a & 0xFF) << 24) | \
- (((pa_typeid_t) b & 0xFF) << 16) | \
- (((pa_typeid_t) c & 0xFF) << 8) | \
- (((pa_typeid_t) d & 0xFF)))
-
-PA_C_DECL_END
-
-#endif
diff --git a/polyp/voltest.c b/polyp/voltest.c
index 286334d08..917e04d35 100644
--- a/polyp/voltest.c
+++ b/polyp/voltest.c
@@ -2,14 +2,19 @@
#include <stdio.h>
-#include <polyp/sample.h>
+#include <polyp/volume.h>
#include "gccmacro.h"
int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
- int p;
- for (p = 0; p <= 200; p++) {
- pa_volume_t v = pa_volume_from_user((double) p/100);
- double dB = pa_volume_to_dB(v);
- printf("%3i%% = %u = %0.2f dB = %u = %3i%%\n", p, v, dB, pa_volume_from_dB(dB), (int) (pa_volume_to_user(v)*100));
+ pa_volume_t v;
+
+ for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) {
+
+ double dB = pa_sw_volume_to_dB(v);
+ double f = pa_sw_volume_to_linear(v);
+
+ printf("Volume: %3i; percent: %i%%; decibel %0.2f; linear = %0.2f; volume(decibel): %3i; volume(linear): %3i\n",
+ v, (v*100)/PA_VOLUME_NORM, dB, f, pa_sw_volume_from_dB(dB), pa_sw_volume_from_linear(f));
+
}
}
diff --git a/polyp/volume.c b/polyp/volume.c
new file mode 100644
index 000000000..0f1531410
--- /dev/null
+++ b/polyp/volume.c
@@ -0,0 +1,176 @@
+/* $Id$ */
+
+/***
+ This file is part of polypaudio.
+
+ polypaudio 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,
+ or (at your option) any later version.
+
+ polypaudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with polypaudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "volume.h"
+
+int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) {
+ int i;
+ assert(a);
+ assert(b);
+
+ if (a->channels != b->channels)
+ return 0;
+
+ for (i = 0; i < a->channels; i++)
+ if (a->values[i] != b->values[i])
+ return 0;
+
+ return 1;
+}
+
+pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) {
+ int i;
+
+ assert(a);
+ assert(channels > 0);
+ assert(channels <= PA_CHANNELS_MAX);
+
+ a->channels = channels;
+
+ for (i = 0; i < a->channels; i++)
+ a->values[i] = v;
+
+ return a;
+}
+
+pa_volume_t pa_cvolume_avg(const pa_cvolume *a) {
+ uint64_t sum = 0;
+ int i;
+ assert(a);
+
+ for (i = 0; i < a->channels; i++)
+ sum += a->values[i];
+
+ sum /= a->channels;
+
+ return (pa_volume_t) sum;
+}
+
+pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) {
+ return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a)* pa_sw_volume_to_linear(b));
+}
+
+#define USER_DECIBEL_RANGE 30
+
+pa_volume_t pa_sw_volume_from_dB(double dB) {
+ if (dB <= -USER_DECIBEL_RANGE)
+ return PA_VOLUME_MUTED;
+
+ return (pa_volume_t) ((dB/USER_DECIBEL_RANGE+1)*PA_VOLUME_NORM);
+}
+
+double pa_sw_volume_to_dB(pa_volume_t v) {
+ if (v == PA_VOLUME_MUTED)
+ return PA_DECIBEL_MININFTY;
+
+ return ((double) v/PA_VOLUME_NORM-1)*USER_DECIBEL_RANGE;
+}
+
+pa_volume_t pa_sw_volume_from_linear(double v) {
+
+ if (v <= 0)
+ return PA_VOLUME_MUTED;
+
+ if (v > .999 && v < 1.001)
+ return PA_VOLUME_NORM;
+
+ return pa_sw_volume_from_dB(20*log10(v));
+}
+
+double pa_sw_volume_to_linear(pa_volume_t v) {
+
+ if (v == PA_VOLUME_MUTED)
+ return 0;
+
+ return pow(10, pa_sw_volume_to_dB(v)/20);
+}
+
+char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
+ unsigned channel;
+ int first = 1;
+ char *e;
+
+ assert(s);
+ assert(l > 0);
+ assert(c);
+
+ *(e = s) = 0;
+
+ for (channel = 0; channel < c->channels && l > 1; channel++) {
+ l -= snprintf(e, l, "%s%u: %3u%%",
+ first ? "" : " ",
+ channel,
+ (c->values[channel]*100)/PA_VOLUME_NORM);
+
+ e = strchr(e, 0);
+ first = 0;
+ }
+
+ return s;
+}
+
+/** Return non-zero if the volume of all channels is equal to the specified value */
+int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) {
+ unsigned c;
+ assert(a);
+
+ for (c = 0; c < a->channels; c++)
+ if (a->values[c] != v)
+ return 0;
+
+ return 1;
+}
+
+pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
+ unsigned i;
+
+ assert(dest);
+ assert(a);
+ assert(b);
+
+ for (i = 0; i < a->channels || i < b->channels || i < PA_CHANNELS_MAX; i++) {
+
+ dest->values[i] = pa_sw_volume_multiply(
+ i < a->channels ? a->values[i] : PA_VOLUME_NORM,
+ i < b->channels ? b->values[i] : PA_VOLUME_NORM);
+ }
+
+ dest->channels = i;
+
+ return dest;
+}
+
+int pa_cvolume_valid(const pa_cvolume *v) {
+ assert(v);
+
+ if (v->channels <= 0 || v->channels > PA_CHANNELS_MAX)
+ return 0;
+
+ return 1;
+}
diff --git a/polyp/volume.h b/polyp/volume.h
new file mode 100644
index 000000000..b2a480848
--- /dev/null
+++ b/polyp/volume.h
@@ -0,0 +1,107 @@
+#ifndef foovolumehfoo
+#define foovolumehfoo
+
+/* $Id$ */
+
+/***
+ This file is part of polypaudio.
+
+ polypaudio 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,
+ or (at your option) any later version.
+
+ polypaudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with polypaudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include <inttypes.h>
+#include <polyp/cdecl.h>
+#include <polyp/sample.h>
+
+/** \file
+ * Constants and routines for volume handling */
+
+PA_C_DECL_BEGIN
+
+/** Volume specification:
+ * PA_VOLUME_MUTED: silence;
+ * < PA_VOLUME_NORM: decreased volume;
+ * PA_VOLUME_NORM: normal volume;
+ * > PA_VOLUME_NORM: increased volume */
+typedef uint32_t pa_volume_t;
+
+/** Normal volume (100%) */
+#define PA_VOLUME_NORM (0x10000)
+
+/** Muted volume (0%) */
+#define PA_VOLUME_MUTED (0)
+
+/** A structure encapsulating a per-channel volume */
+typedef struct pa_cvolume {
+ uint8_t channels;
+ pa_volume_t values[PA_CHANNELS_MAX];
+} pa_cvolume;
+
+/** Return non-zero when *a == *b */
+int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b);
+
+/** Set the volume of all channels to PA_VOLUME_NORM */
+#define pa_cvolume_reset(a, n) pa_cvolume_set((a), (n), PA_VOLUME_NORM)
+
+/** Set the volume of all channels to PA_VOLUME_MUTED */
+#define pa_cvolume_mute(a, n) pa_cvolume_set((a), (n), PA_VOLUME_MUTED)
+
+/** Set the volume of all channels to the specified parameter */
+pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v);
+
+/** Pretty print a volume structure */
+#define PA_CVOLUME_SNPRINT_MAX 64
+char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c);
+
+/** Return the average volume of all channels */
+pa_volume_t pa_cvolume_avg(const pa_cvolume *a);
+
+/** Return TRUE when the passed cvolume structure is valid, FALSE otherwise */
+int pa_cvolume_valid(const pa_cvolume *v);
+
+/** Return non-zero if the volume of all channels is equal to the specified value */
+int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v);
+
+#define pa_cvolume_is_muted(a) pa_cvolume_channels_equal_to((a), PA_VOLUME_MUTED)
+#define pa_cvolume_is_norm(a) pa_cvolume_channels_equal_to((a), PA_VOLUME_NORM)
+
+/** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. */
+pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b);
+
+pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b);
+
+/** Convert a decibel value to a volume. \since 0.4 */
+pa_volume_t pa_sw_volume_from_dB(double f);
+
+/** Convert a volume to a decibel value. \since 0.4 */
+double pa_sw_volume_to_dB(pa_volume_t v);
+
+/** Convert a linear factor to a volume. \since 0.8 */
+pa_volume_t pa_sw_volume_from_linear(double v);
+
+/** Convert a volume to a linear factor. \since 0.8 */
+double pa_sw_volume_to_linear(pa_volume_t v);
+
+#ifdef INFINITY
+#define PA_DECIBEL_MININFTY (-INFINITY)
+#else
+/** This value is used as minus infinity when using pa_volume_{to,from}_dB(). \since 0.4 */
+#define PA_DECIBEL_MININFTY (-200)
+#endif
+
+PA_C_DECL_END
+
+#endif
diff --git a/polyp/x11prop.c b/polyp/x11prop.c
index bbe3e32c1..e57fc136e 100644
--- a/polyp/x11prop.c
+++ b/polyp/x11prop.c
@@ -33,7 +33,7 @@
void pa_x11_set_prop(Display *d, const char *name, const char *data) {
Atom a = XInternAtom(d, name, False);
- XChangeProperty(d, RootWindow(d, 0), a, XA_STRING, 8, PropModeReplace, (unsigned char*) data, strlen(data)+1);
+ XChangeProperty(d, RootWindow(d, 0), a, XA_STRING, 8, PropModeReplace, (const unsigned char*) data, strlen(data)+1);
}
void pa_x11_del_prop(Display *d, const char *name) {
diff --git a/polyp/x11wrap.c b/polyp/x11wrap.c
index 64923320b..e20a50a63 100644
--- a/polyp/x11wrap.c
+++ b/polyp/x11wrap.c
@@ -76,7 +76,7 @@ static void work(pa_x11_wrapper *w) {
}
/* IO notification event for the X11 display connection */
-static void display_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) {
+static void display_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
pa_x11_wrapper *w = userdata;
assert(m && e && fd >= 0 && w && w->ref >= 1);
work(w);
@@ -90,7 +90,7 @@ static void defer_event(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
}
/* IO notification event for X11 internal connections */
-static void internal_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) {
+static void internal_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
pa_x11_wrapper *w = userdata;
assert(m && e && fd >= 0 && w && w->ref >= 1);