From 4b6ab291a787ff597c938842b569a35434ab11d8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 23:47:38 +0000 Subject: * modify pa_channel_map_init_auto() to take an extra argument specifying the standard to use (ALSA, AIFF, ...) * add some more validity checks to pa_source_new(),pa_sink_new(),pa_sink_input_new(),pa_source_output_new() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@888 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 44 -------------- src/modules/alsa-util.h | 2 - src/modules/module-alsa-sink.c | 15 +---- src/modules/module-alsa-source.c | 13 +--- src/modules/module-combine.c | 2 +- src/modules/module-jack-sink.c | 2 +- src/modules/module-jack-source.c | 2 +- src/modules/module-null-sink.c | 2 +- src/modules/module-oss-mmap.c | 2 +- src/modules/module-oss.c | 2 +- src/modules/module-pipe-sink.c | 2 +- src/modules/module-pipe-source.c | 2 +- src/modules/module-tunnel.c | 2 +- src/modules/rtp/module-rtp-send.c | 2 +- src/polyp/channelmap.c | 125 +++++++++++++++++++++++++++----------- src/polyp/channelmap.h | 14 ++++- src/polyp/stream.c | 2 +- src/polypcore/core-scache.c | 2 +- src/polypcore/modargs.c | 5 +- src/polypcore/modargs.h | 2 +- src/polypcore/resampler.c | 4 +- src/polypcore/sink-input.c | 58 ++++++++++-------- src/polypcore/sink.c | 37 +++++++---- src/polypcore/sound-file.c | 2 +- src/polypcore/source-output.c | 37 +++++++---- src/polypcore/source.c | 36 +++++++---- src/tests/channelmap-test.c | 10 ++- 27 files changed, 237 insertions(+), 191 deletions(-) (limited to 'src') diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index a8192165..503b8efb 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -340,47 +340,3 @@ snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name) { return elem; } - -pa_channel_map* pa_alsa_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; - - /* The standard ALSA channel order */ - - 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; - } -} diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index bad6e9bf..69d4eddc 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -42,6 +42,4 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint3 int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev); snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name); -pa_channel_map* pa_alsa_channel_map_init_auto(pa_channel_map *m, unsigned channels); - #endif diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 99e74bfc..47065659 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -324,19 +324,8 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": failed to parse sample specification"); - goto fail; - } - - pa_alsa_channel_map_init_auto(&map, ss.channels); - if ((pa_modargs_get_channel_map(ma, &map) < 0)) { - pa_log(__FILE__": invalid channel map."); - goto fail; - } - - if (ss.channels != map.channels) { - pa_log(__FILE__": channel map and sample specification don't match."); + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) { + pa_log(__FILE__": failed to parse sample specification and channel map"); goto fail; } diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 660bc83b..d46f8e42 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -316,22 +316,11 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) { pa_log(__FILE__": failed to parse sample specification"); goto fail; } - pa_alsa_channel_map_init_auto(&map, ss.channels); - if ((pa_modargs_get_channel_map(ma, &map) < 0)) { - pa_log(__FILE__": invalid channel map."); - goto fail; - } - - if (ss.channels != map.channels) { - pa_log(__FILE__": channel map and sample specification don't match."); - goto fail; - } - frame_size = pa_frame_size(&ss); /* Fix latency to 100ms */ diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 3b927d13..369778a6 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -361,7 +361,7 @@ int pa__init(pa_core *c, pa_module*m) { if (ss.channels == master_sink->sample_spec.channels) map = master_sink->channel_map; else - pa_channel_map_init_auto(&map, ss.channels); + pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_DEFAULT); if ((pa_modargs_get_channel_map(ma, &map) < 0)) { pa_log(__FILE__": invalid channel map."); diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 09030530..324a2cb3 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -296,7 +296,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - pa_channel_map_init_auto(&map, channels); + pa_channel_map_init_auto(&map, channels, PA_CHANNEL_MAP_ALSA); if (pa_modargs_get_channel_map(ma, &map) < 0 || map.channels != channels) { pa_log(__FILE__": failed to parse channel_map= argument."); goto fail; diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index ad39b9dd..94cabbea 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -294,7 +294,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - pa_channel_map_init_auto(&map, channels); + pa_channel_map_init_auto(&map, channels, PA_CHANNEL_MAP_ALSA); if (pa_modargs_get_channel_map(ma, &map) < 0 || map.channels != channels) { pa_log(__FILE__": failed to parse channel_map= argument."); goto fail; diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 9c564429..5cdfeab8 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -104,7 +104,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log(__FILE__": invalid sample format specification or channel map."); goto fail; } diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index e032ce46..b8012214 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -383,7 +383,7 @@ int pa__init(pa_core *c, pa_module*m) { } u->sample_spec = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &u->sample_spec, &map) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &u->sample_spec, &map, PA_CHANNEL_MAP_ALSA) < 0) { pa_log(__FILE__": failed to parse sample specification or channel map"); goto fail; } diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 4d811a76..eab9a60a 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -347,7 +347,7 @@ int pa__init(pa_core *c, pa_module*m) { mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) { pa_log(__FILE__": failed to parse sample specification or channel map"); goto fail; } diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index 2be1b297..0fb73cd8 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -154,7 +154,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log(__FILE__": invalid sample format specification"); goto fail; } diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index c80bfd09..d999754a 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -132,7 +132,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log(__FILE__": invalid sample format specification or channel map"); goto fail; } diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index bffcc7c0..2e04b120 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -895,7 +895,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log(__FILE__": invalid sample format specification"); goto fail; } diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 0bb20979..d0def859 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -197,7 +197,7 @@ int pa__init(pa_core *c, pa_module*m) { } if (ss.channels != cm.channels) - pa_channel_map_init_auto(&cm, ss.channels); + pa_channel_map_init_auto(&cm, ss.channels, PA_CHANNEL_MAP_AIFF); payload = pa_rtp_payload_from_sample_spec(&ss); diff --git a/src/polyp/channelmap.c b/src/polyp/channelmap.c index 794711ae..8d16f7b3 100644 --- a/src/polyp/channelmap.c +++ b/src/polyp/channelmap.c @@ -112,7 +112,7 @@ pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m) { return m; } -pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels) { +pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def) { assert(m); assert(channels > 0); assert(channels <= PA_CHANNELS_MAX); @@ -121,46 +121,99 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels) { m->channels = channels; - /* This is somewhat compatible with RFC3551 */ - - switch (channels) { - case 1: - m->map[0] = PA_CHANNEL_POSITION_MONO; - return m; - - case 6: - m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; - m->map[1] = PA_CHANNEL_POSITION_SIDE_LEFT; - m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; - m->map[3] = PA_CHANNEL_POSITION_FRONT_RIGHT; - m->map[4] = PA_CHANNEL_POSITION_SIDE_RIGHT; - m->map[5] = PA_CHANNEL_POSITION_LFE; - return m; + switch (def) { + case PA_CHANNEL_MAP_AIFF: - case 5: - m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; - m->map[3] = PA_CHANNEL_POSITION_REAR_LEFT; - m->map[4] = PA_CHANNEL_POSITION_REAR_RIGHT; - /* Fall through */ + /* This is somewhat compatible with RFC3551 */ - case 2: - m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; - m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; - return m; + switch (channels) { + case 1: + m->map[0] = PA_CHANNEL_POSITION_MONO; + return m; + + case 6: + m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + m->map[1] = PA_CHANNEL_POSITION_SIDE_LEFT; + m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; + m->map[3] = PA_CHANNEL_POSITION_FRONT_RIGHT; + m->map[4] = PA_CHANNEL_POSITION_SIDE_RIGHT; + m->map[5] = PA_CHANNEL_POSITION_LFE; + return m; + + case 5: + m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; + m->map[3] = PA_CHANNEL_POSITION_REAR_LEFT; + m->map[4] = 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; + + case 3: + m->map[0] = PA_CHANNEL_POSITION_LEFT; + m->map[1] = PA_CHANNEL_POSITION_RIGHT; + m->map[2] = PA_CHANNEL_POSITION_CENTER; + return m; + + case 4: + m->map[0] = PA_CHANNEL_POSITION_LEFT; + m->map[1] = PA_CHANNEL_POSITION_CENTER; + m->map[2] = PA_CHANNEL_POSITION_RIGHT; + m->map[3] = PA_CHANNEL_POSITION_LFE; + return m; + + default: + return NULL; + } - case 3: - m->map[0] = PA_CHANNEL_POSITION_LEFT; - m->map[1] = PA_CHANNEL_POSITION_RIGHT; - m->map[2] = PA_CHANNEL_POSITION_CENTER; - return m; + case PA_CHANNEL_MAP_ALSA: + + 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; + } - case 4: - m->map[0] = PA_CHANNEL_POSITION_LEFT; - m->map[1] = PA_CHANNEL_POSITION_CENTER; - m->map[2] = PA_CHANNEL_POSITION_RIGHT; - m->map[3] = PA_CHANNEL_POSITION_LFE; - return m; + case PA_CHANNEL_MAP_AUX: { + unsigned i; + + if (channels >= PA_CHANNELS_MAX) + return NULL; + + for (i = 0; i < channels; i++) + m->map[i] = PA_CHANNEL_POSITION_AUX0 + i; + return m; + } + default: return NULL; } diff --git a/src/polyp/channelmap.h b/src/polyp/channelmap.h index 0fd1e593..8270a5b3 100644 --- a/src/polyp/channelmap.h +++ b/src/polyp/channelmap.h @@ -120,6 +120,15 @@ typedef enum pa_channel_position { PA_CHANNEL_POSITION_MAX } pa_channel_position_t; +/** A list of channel mapping definitions for pa_channel_map_init_auto() */ +typedef enum pa_channel_map_def { + PA_CHANNEL_MAP_AIFF, /**< The mapping from RFC3551, which is based on AIFF-C */ + PA_CHANNEL_MAP_ALSA, /**< The default mapping used by ALSA */ + PA_CHANNEL_MAP_AUX, /**< Only aux channels */ + + PA_CHANNEL_MAP_DEFAULT = PA_CHANNEL_MAP_AIFF /**< The default channel map */ +} pa_channel_map_def_t; + /** A channel map which can be used to attach labels to specific * channels of a stream. These values are relevant for conversion and * mixing of streams */ @@ -138,9 +147,8 @@ pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m); pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m); /** Initialize the specified channel map for the specified number - * of channels using default labels and return a pointer to it. - * Uses the mapping from RFC3551, which is based on AIFF-C. */ -pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels); + * of channels using default labels and return a pointer to it. */ +pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def); /** Return a text label for the specified channel position */ const char* pa_channel_position_to_string(pa_channel_position_t pos); diff --git a/src/polyp/stream.c b/src/polyp/stream.c index bccdebe5..b2711ce0 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -74,7 +74,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * if (map) s->channel_map = *map; else - pa_channel_map_init_auto(&s->channel_map, ss->channels); + pa_channel_map_init_auto(&s->channel_map, ss->channels, PA_CHANNEL_MAP_DEFAULT); s->channel = 0; s->channel_valid = 0; diff --git a/src/polypcore/core-scache.c b/src/polypcore/core-scache.c index 82c61a1d..3bba38ed 100644 --- a/src/polypcore/core-scache.c +++ b/src/polypcore/core-scache.c @@ -141,7 +141,7 @@ int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, c if (ss) { e->sample_spec = *ss; - pa_channel_map_init_auto(&e->channel_map, ss->channels); + pa_channel_map_init_auto(&e->channel_map, ss->channels, PA_CHANNEL_MAP_DEFAULT); e->volume.channels = e->sample_spec.channels; } diff --git a/src/polypcore/modargs.c b/src/polypcore/modargs.c index 6a02df0a..713326bf 100644 --- a/src/polypcore/modargs.c +++ b/src/polypcore/modargs.c @@ -280,7 +280,7 @@ int pa_modargs_get_channel_map(pa_modargs *ma, pa_channel_map *rmap) { return 0; } -int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *rss, pa_channel_map *rmap) { +int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *rss, pa_channel_map *rmap, pa_channel_map_def_t def) { pa_sample_spec ss; pa_channel_map map; @@ -293,7 +293,8 @@ int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *r if (pa_modargs_get_sample_spec(ma, &ss) < 0) return -1; - pa_channel_map_init_auto(&map, ss.channels); + if (!pa_channel_map_init_auto(&map, ss.channels, def)) + map.channels = 0; if (pa_modargs_get_channel_map(ma, &map) < 0) return -1; diff --git a/src/polypcore/modargs.h b/src/polypcore/modargs.h index 481ead99..b6977d37 100644 --- a/src/polypcore/modargs.h +++ b/src/polypcore/modargs.h @@ -55,6 +55,6 @@ pa_modargs_get_channel_map(). Not always suitable, since this routine initializes the map parameter based on the channels field of the ss structure if no channel_map is found, using pa_channel_map_init_auto() */ -int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *ss, pa_channel_map *map); +int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *ss, pa_channel_map *map, pa_channel_map_def_t def); #endif diff --git a/src/polypcore/resampler.c b/src/polypcore/resampler.c index 7e85e270..b2a8874b 100644 --- a/src/polypcore/resampler.c +++ b/src/polypcore/resampler.c @@ -101,12 +101,12 @@ pa_resampler* pa_resampler_new( if (am) r->i_cm = *am; else - pa_channel_map_init_auto(&r->i_cm, r->i_ss.channels); + pa_channel_map_init_auto(&r->i_cm, r->i_ss.channels, PA_CHANNEL_MAP_DEFAULT); if (bm) r->o_cm = *bm; else - pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels); + pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels, PA_CHANNEL_MAP_DEFAULT); r->i_fz = pa_frame_size(a); r->o_fz = pa_frame_size(b); diff --git a/src/polypcore/sink-input.c b/src/polypcore/sink-input.c index 26e63b85..c1026390 100644 --- a/src/polypcore/sink-input.c +++ b/src/polypcore/sink-input.c @@ -32,32 +32,53 @@ #include #include #include +#include #include "sink-input.h" #define CONVERT_BUFFER_LENGTH 4096 +#define CHECK_VALIDITY_RETURN_NULL(condition) \ +do {\ +if (!(condition)) \ + return NULL; \ +} while (0) + 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, - const pa_cvolume *volume, - int variable_rate, - int resample_method) { + pa_sink *s, + const char *driver, + const char *name, + const pa_sample_spec *spec, + const pa_channel_map *map, + const pa_cvolume *volume, + int variable_rate, + int resample_method) { pa_sink_input *i; pa_resampler *resampler = NULL; int r; char st[256]; pa_channel_map tmap; + pa_cvolume tvol; assert(s); assert(spec); assert(s->state == PA_SINK_RUNNING); + CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec)); + + if (!map) + map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT); + if (!volume) + volume = pa_cvolume_reset(&tvol, spec->channels); + CHECK_VALIDITY_RETURN_NULL(map && pa_channel_map_valid(map)); + CHECK_VALIDITY_RETURN_NULL(volume && pa_cvolume_valid(volume)); + CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels); + CHECK_VALIDITY_RETURN_NULL(volume->channels == spec->channels); + CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver)); + CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name)); + if (pa_idxset_size(s->inputs) >= PA_MAX_INPUTS_PER_SINK) { pa_log_warn(__FILE__": Failed to create sink input: too many inputs per sink."); return NULL; @@ -66,19 +87,6 @@ pa_sink_input* pa_sink_input_new( if (resample_method == PA_RESAMPLER_INVALID) resample_method = s->core->resample_method; - if (map && spec->channels != map->channels) - return NULL; - - if (volume && spec->channels != volume->channels) - return NULL; - - if (!map) { - if (!(pa_channel_map_init_auto(&tmap, spec->channels))) - return NULL; - - 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; @@ -94,12 +102,8 @@ pa_sink_input* pa_sink_input_new( i->sample_spec = *spec; i->channel_map = *map; - - if (volume) - i->volume = *volume; - else - pa_cvolume_reset(&i->volume, spec->channels); - + i->volume = *volume; + i->peek = NULL; i->drop = NULL; i->kill = NULL; diff --git a/src/polypcore/sink.c b/src/polypcore/sink.c index 17294059..b59f1eaa 100644 --- a/src/polypcore/sink.c +++ b/src/polypcore/sink.c @@ -29,6 +29,7 @@ #include #include + #include #include #include @@ -36,29 +37,46 @@ #include #include #include +#include #include "sink.h" #define MAX_MIX_CHANNELS 32 +#define CHECK_VALIDITY_RETURN_NULL(condition) \ +do {\ +if (!(condition)) \ + return NULL; \ +} while (0) + 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_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; + pa_channel_map tmap; assert(core); assert(name); - assert(*name); assert(spec); + CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec)); + + if (!map) + map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT); + + CHECK_VALIDITY_RETURN_NULL(map && pa_channel_map_valid(map)); + CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels); + CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver)); + CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name) && *name); + s = pa_xnew(pa_sink, 1); if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) { @@ -75,10 +93,7 @@ pa_sink* pa_sink_new( s->owner = NULL; s->sample_spec = *spec; - if (map) - s->channel_map = *map; - else - pa_channel_map_init_auto(&s->channel_map, spec->channels); + s->channel_map = *map; s->inputs = pa_idxset_new(NULL, NULL); diff --git a/src/polypcore/sound-file.c b/src/polypcore/sound-file.c index a6ccb064..f0378009 100644 --- a/src/polypcore/sound-file.c +++ b/src/polypcore/sound-file.c @@ -75,7 +75,7 @@ int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_channel_map *ma } if (map) - pa_channel_map_init_auto(map, ss->channels); + pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_DEFAULT); if ((l = pa_frame_size(ss)*sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) { pa_log(__FILE__": File too large"); diff --git a/src/polypcore/source-output.c b/src/polypcore/source-output.c index 0cb5f356..b3113071 100644 --- a/src/polypcore/source-output.c +++ b/src/polypcore/source-output.c @@ -31,16 +31,23 @@ #include #include #include +#include #include "source-output.h" +#define CHECK_VALIDITY_RETURN_NULL(condition) \ +do {\ +if (!(condition)) \ + return NULL; \ +} while (0) + 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 *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; @@ -51,7 +58,17 @@ pa_source_output* pa_source_output_new( assert(s); assert(spec); assert(s->state == PA_SOURCE_RUNNING); + + CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec)); + + if (!map) + map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT); + CHECK_VALIDITY_RETURN_NULL(map && pa_channel_map_valid(map)); + CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels); + CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver)); + CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name)); + if (pa_idxset_size(s->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { pa_log(__FILE__": Failed to create source output: too many outputs per source."); return NULL; @@ -60,16 +77,11 @@ pa_source_output* pa_source_output_new( if (resample_method == PA_RESAMPLER_INVALID) resample_method = s->core->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 = pa_xnew(pa_source_output, 1); o->ref = 1; o->state = PA_SOURCE_OUTPUT_RUNNING; o->name = pa_xstrdup(name); @@ -137,7 +149,6 @@ static void source_output_free(pa_source_output* o) { pa_xfree(o); } - void pa_source_output_unref(pa_source_output* o) { assert(o); assert(o->ref >= 1); diff --git a/src/polypcore/source.c b/src/polypcore/source.c index 3a78825b..fca281a7 100644 --- a/src/polypcore/source.c +++ b/src/polypcore/source.c @@ -34,26 +34,43 @@ #include #include #include +#include #include "source.h" +#define CHECK_VALIDITY_RETURN_NULL(condition) \ +do {\ +if (!(condition)) \ + return NULL; \ +} while (0) + 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_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; + pa_channel_map tmap; assert(core); assert(name); - assert(*name); assert(spec); + CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec)); + + if (!map) + map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT); + + CHECK_VALIDITY_RETURN_NULL(map && pa_channel_map_valid(map)); + CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels); + CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver)); + CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name) && *name); + s = pa_xnew(pa_source, 1); if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SOURCE, s, fail))) { @@ -70,10 +87,7 @@ pa_source* pa_source_new( s->owner = NULL; s->sample_spec = *spec; - if (map) - s->channel_map = *map; - else - pa_channel_map_init_auto(&s->channel_map, spec->channels); + s->channel_map = *map; s->outputs = pa_idxset_new(NULL, NULL); s->monitor_of = NULL; diff --git a/src/tests/channelmap-test.c b/src/tests/channelmap-test.c index 522c136f..c6644229 100644 --- a/src/tests/channelmap-test.c +++ b/src/tests/channelmap-test.c @@ -10,10 +10,18 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; pa_channel_map map, map2; - pa_channel_map_init_auto(&map, 5); + pa_channel_map_init_auto(&map, 6, PA_CHANNEL_MAP_AIFF); fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map)); + pa_channel_map_init_auto(&map, 6, PA_CHANNEL_MAP_AUX); + + fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map)); + + pa_channel_map_init_auto(&map, 6, PA_CHANNEL_MAP_ALSA); + + fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map)); + pa_channel_map_parse(&map2, cm); assert(pa_channel_map_equal(&map, &map2)); -- cgit