* 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
This commit is contained in:
Lennart Poettering 2006-05-16 23:47:38 +00:00
parent c63cc7bb79
commit 4b6ab291a7
27 changed files with 237 additions and 191 deletions

View file

@ -340,47 +340,3 @@ snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name) {
return elem; 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;
}
}

View file

@ -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); 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); 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 #endif

View file

@ -324,19 +324,8 @@ int pa__init(pa_core *c, pa_module*m) {
} }
ss = c->default_sample_spec; 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"); pa_log(__FILE__": failed to parse sample specification and channel map");
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; goto fail;
} }

View file

@ -316,22 +316,11 @@ int pa__init(pa_core *c, pa_module*m) {
} }
ss = c->default_sample_spec; 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"); pa_log(__FILE__": failed to parse sample specification");
goto fail; 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); frame_size = pa_frame_size(&ss);
/* Fix latency to 100ms */ /* Fix latency to 100ms */

View file

@ -361,7 +361,7 @@ int pa__init(pa_core *c, pa_module*m) {
if (ss.channels == master_sink->sample_spec.channels) if (ss.channels == master_sink->sample_spec.channels)
map = master_sink->channel_map; map = master_sink->channel_map;
else 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)) { if ((pa_modargs_get_channel_map(ma, &map) < 0)) {
pa_log(__FILE__": invalid channel map."); pa_log(__FILE__": invalid channel map.");

View file

@ -296,7 +296,7 @@ int pa__init(pa_core *c, pa_module*m) {
goto fail; 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) { if (pa_modargs_get_channel_map(ma, &map) < 0 || map.channels != channels) {
pa_log(__FILE__": failed to parse channel_map= argument."); pa_log(__FILE__": failed to parse channel_map= argument.");
goto fail; goto fail;

View file

@ -294,7 +294,7 @@ int pa__init(pa_core *c, pa_module*m) {
goto fail; 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) { if (pa_modargs_get_channel_map(ma, &map) < 0 || map.channels != channels) {
pa_log(__FILE__": failed to parse channel_map= argument."); pa_log(__FILE__": failed to parse channel_map= argument.");
goto fail; goto fail;

View file

@ -104,7 +104,7 @@ int pa__init(pa_core *c, pa_module*m) {
} }
ss = c->default_sample_spec; 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."); pa_log(__FILE__": invalid sample format specification or channel map.");
goto fail; goto fail;
} }

View file

@ -383,7 +383,7 @@ int pa__init(pa_core *c, pa_module*m) {
} }
u->sample_spec = c->default_sample_spec; 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"); pa_log(__FILE__": failed to parse sample specification or channel map");
goto fail; goto fail;
} }

View file

@ -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)); mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
ss = c->default_sample_spec; 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"); pa_log(__FILE__": failed to parse sample specification or channel map");
goto fail; goto fail;
} }

View file

@ -154,7 +154,7 @@ int pa__init(pa_core *c, pa_module*m) {
} }
ss = c->default_sample_spec; 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"); pa_log(__FILE__": invalid sample format specification");
goto fail; goto fail;
} }

View file

@ -132,7 +132,7 @@ int pa__init(pa_core *c, pa_module*m) {
} }
ss = c->default_sample_spec; 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"); pa_log(__FILE__": invalid sample format specification or channel map");
goto fail; goto fail;
} }

View file

@ -895,7 +895,7 @@ int pa__init(pa_core *c, pa_module*m) {
} }
ss = c->default_sample_spec; 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"); pa_log(__FILE__": invalid sample format specification");
goto fail; goto fail;
} }

View file

@ -197,7 +197,7 @@ int pa__init(pa_core *c, pa_module*m) {
} }
if (ss.channels != cm.channels) 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); payload = pa_rtp_payload_from_sample_spec(&ss);

View file

@ -112,7 +112,7 @@ pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m) {
return 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(m);
assert(channels > 0); assert(channels > 0);
assert(channels <= PA_CHANNELS_MAX); assert(channels <= PA_CHANNELS_MAX);
@ -121,45 +121,98 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels) {
m->channels = channels; m->channels = channels;
/* This is somewhat compatible with RFC3551 */ switch (def) {
case PA_CHANNEL_MAP_AIFF:
/* 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;
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 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 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;
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; return m;
}
default: default:
return NULL; return NULL;

View file

@ -120,6 +120,15 @@ typedef enum pa_channel_position {
PA_CHANNEL_POSITION_MAX PA_CHANNEL_POSITION_MAX
} pa_channel_position_t; } 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 /** A channel map which can be used to attach labels to specific
* channels of a stream. These values are relevant for conversion and * channels of a stream. These values are relevant for conversion and
* mixing of streams */ * 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); pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m);
/** Initialize the specified channel map for the specified number /** Initialize the specified channel map for the specified number
* of channels using default labels and return a pointer to it. * 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, pa_channel_map_def_t def);
pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels);
/** Return a text label for the specified channel position */ /** Return a text label for the specified channel position */
const char* pa_channel_position_to_string(pa_channel_position_t pos); const char* pa_channel_position_to_string(pa_channel_position_t pos);

View file

@ -74,7 +74,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *
if (map) if (map)
s->channel_map = *map; s->channel_map = *map;
else 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 = 0;
s->channel_valid = 0; s->channel_valid = 0;

View file

@ -141,7 +141,7 @@ int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, c
if (ss) { if (ss) {
e->sample_spec = *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; e->volume.channels = e->sample_spec.channels;
} }

View file

@ -280,7 +280,7 @@ int pa_modargs_get_channel_map(pa_modargs *ma, pa_channel_map *rmap) {
return 0; 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_sample_spec ss;
pa_channel_map map; 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) if (pa_modargs_get_sample_spec(ma, &ss) < 0)
return -1; 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) if (pa_modargs_get_channel_map(ma, &map) < 0)
return -1; return -1;

View file

@ -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 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() */ 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 #endif

View file

@ -101,12 +101,12 @@ pa_resampler* pa_resampler_new(
if (am) if (am)
r->i_cm = *am; r->i_cm = *am;
else 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) if (bm)
r->o_cm = *bm; r->o_cm = *bm;
else 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->i_fz = pa_frame_size(a);
r->o_fz = pa_frame_size(b); r->o_fz = pa_frame_size(b);

View file

@ -32,31 +32,52 @@
#include <polypcore/xmalloc.h> #include <polypcore/xmalloc.h>
#include <polypcore/core-subscribe.h> #include <polypcore/core-subscribe.h>
#include <polypcore/log.h> #include <polypcore/log.h>
#include <polypcore/utf8.h>
#include "sink-input.h" #include "sink-input.h"
#define CONVERT_BUFFER_LENGTH 4096 #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_input* pa_sink_input_new(
pa_sink *s, pa_sink *s,
const char *driver, const char *driver,
const char *name, const char *name,
const pa_sample_spec *spec, const pa_sample_spec *spec,
const pa_channel_map *map, const pa_channel_map *map,
const pa_cvolume *volume, const pa_cvolume *volume,
int variable_rate, int variable_rate,
int resample_method) { int resample_method) {
pa_sink_input *i; pa_sink_input *i;
pa_resampler *resampler = NULL; pa_resampler *resampler = NULL;
int r; int r;
char st[256]; char st[256];
pa_channel_map tmap; pa_channel_map tmap;
pa_cvolume tvol;
assert(s); assert(s);
assert(spec); assert(spec);
assert(s->state == PA_SINK_RUNNING); 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) { 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."); pa_log_warn(__FILE__": Failed to create sink input: too many inputs per sink.");
@ -66,19 +87,6 @@ pa_sink_input* pa_sink_input_new(
if (resample_method == PA_RESAMPLER_INVALID) if (resample_method == PA_RESAMPLER_INVALID)
resample_method = s->core->resample_method; 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 (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))) if (!(resampler = pa_resampler_new(spec, map, &s->sample_spec, &s->channel_map, s->core->memblock_stat, resample_method)))
return NULL; return NULL;
@ -94,11 +102,7 @@ pa_sink_input* pa_sink_input_new(
i->sample_spec = *spec; i->sample_spec = *spec;
i->channel_map = *map; i->channel_map = *map;
i->volume = *volume;
if (volume)
i->volume = *volume;
else
pa_cvolume_reset(&i->volume, spec->channels);
i->peek = NULL; i->peek = NULL;
i->drop = NULL; i->drop = NULL;

View file

@ -29,6 +29,7 @@
#include <stdio.h> #include <stdio.h>
#include <polyp/introspect.h> #include <polyp/introspect.h>
#include <polypcore/sink-input.h> #include <polypcore/sink-input.h>
#include <polypcore/namereg.h> #include <polypcore/namereg.h>
#include <polypcore/util.h> #include <polypcore/util.h>
@ -36,29 +37,46 @@
#include <polypcore/xmalloc.h> #include <polypcore/xmalloc.h>
#include <polypcore/core-subscribe.h> #include <polypcore/core-subscribe.h>
#include <polypcore/log.h> #include <polypcore/log.h>
#include <polypcore/utf8.h>
#include "sink.h" #include "sink.h"
#define MAX_MIX_CHANNELS 32 #define MAX_MIX_CHANNELS 32
#define CHECK_VALIDITY_RETURN_NULL(condition) \
do {\
if (!(condition)) \
return NULL; \
} while (0)
pa_sink* pa_sink_new( pa_sink* pa_sink_new(
pa_core *core, pa_core *core,
const char *driver, const char *driver,
const char *name, const char *name,
int fail, int fail,
const pa_sample_spec *spec, const pa_sample_spec *spec,
const pa_channel_map *map) { const pa_channel_map *map) {
pa_sink *s; pa_sink *s;
char *n = NULL; char *n = NULL;
char st[256]; char st[256];
int r; int r;
pa_channel_map tmap;
assert(core); assert(core);
assert(name); assert(name);
assert(*name);
assert(spec); 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); s = pa_xnew(pa_sink, 1);
if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) { 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->owner = NULL;
s->sample_spec = *spec; s->sample_spec = *spec;
if (map) s->channel_map = *map;
s->channel_map = *map;
else
pa_channel_map_init_auto(&s->channel_map, spec->channels);
s->inputs = pa_idxset_new(NULL, NULL); s->inputs = pa_idxset_new(NULL, NULL);

View file

@ -75,7 +75,7 @@ int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_channel_map *ma
} }
if (map) 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) { if ((l = pa_frame_size(ss)*sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
pa_log(__FILE__": File too large"); pa_log(__FILE__": File too large");

View file

@ -31,16 +31,23 @@
#include <polypcore/xmalloc.h> #include <polypcore/xmalloc.h>
#include <polypcore/core-subscribe.h> #include <polypcore/core-subscribe.h>
#include <polypcore/log.h> #include <polypcore/log.h>
#include <polypcore/utf8.h>
#include "source-output.h" #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_output* pa_source_output_new(
pa_source *s, pa_source *s,
const char *driver, const char *driver,
const char *name, const char *name,
const pa_sample_spec *spec, const pa_sample_spec *spec,
const pa_channel_map *map, const pa_channel_map *map,
int resample_method) { int resample_method) {
pa_source_output *o; pa_source_output *o;
pa_resampler *resampler = NULL; pa_resampler *resampler = NULL;
@ -52,6 +59,16 @@ pa_source_output* pa_source_output_new(
assert(spec); assert(spec);
assert(s->state == PA_SOURCE_RUNNING); 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) { if (pa_idxset_size(s->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) {
pa_log(__FILE__": Failed to create source output: too many outputs per source."); pa_log(__FILE__": Failed to create source output: too many outputs per source.");
return NULL; return NULL;
@ -60,16 +77,11 @@ pa_source_output* pa_source_output_new(
if (resample_method == PA_RESAMPLER_INVALID) if (resample_method == PA_RESAMPLER_INVALID)
resample_method = s->core->resample_method; 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 (!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))) if (!(resampler = pa_resampler_new(&s->sample_spec, &s->channel_map, spec, map, s->core->memblock_stat, resample_method)))
return NULL; return NULL;
o = pa_xmalloc(sizeof(pa_source_output)); o = pa_xnew(pa_source_output, 1);
o->ref = 1; o->ref = 1;
o->state = PA_SOURCE_OUTPUT_RUNNING; o->state = PA_SOURCE_OUTPUT_RUNNING;
o->name = pa_xstrdup(name); o->name = pa_xstrdup(name);
@ -137,7 +149,6 @@ static void source_output_free(pa_source_output* o) {
pa_xfree(o); pa_xfree(o);
} }
void pa_source_output_unref(pa_source_output* o) { void pa_source_output_unref(pa_source_output* o) {
assert(o); assert(o);
assert(o->ref >= 1); assert(o->ref >= 1);

View file

@ -34,26 +34,43 @@
#include <polypcore/core-subscribe.h> #include <polypcore/core-subscribe.h>
#include <polypcore/log.h> #include <polypcore/log.h>
#include <polypcore/sample-util.h> #include <polypcore/sample-util.h>
#include <polypcore/utf8.h>
#include "source.h" #include "source.h"
#define CHECK_VALIDITY_RETURN_NULL(condition) \
do {\
if (!(condition)) \
return NULL; \
} while (0)
pa_source* pa_source_new( pa_source* pa_source_new(
pa_core *core, pa_core *core,
const char *driver, const char *driver,
const char *name, const char *name,
int fail, int fail,
const pa_sample_spec *spec, const pa_sample_spec *spec,
const pa_channel_map *map) { const pa_channel_map *map) {
pa_source *s; pa_source *s;
char st[256]; char st[256];
int r; int r;
pa_channel_map tmap;
assert(core); assert(core);
assert(name); assert(name);
assert(*name);
assert(spec); 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); s = pa_xnew(pa_source, 1);
if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SOURCE, s, fail))) { 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->owner = NULL;
s->sample_spec = *spec; s->sample_spec = *spec;
if (map) s->channel_map = *map;
s->channel_map = *map;
else
pa_channel_map_init_auto(&s->channel_map, spec->channels);
s->outputs = pa_idxset_new(NULL, NULL); s->outputs = pa_idxset_new(NULL, NULL);
s->monitor_of = NULL; s->monitor_of = NULL;

View file

@ -10,7 +10,15 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
pa_channel_map map, map2; 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)); fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map));