mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
Completely rework ALSA device selection code: choose the device to open depending on the requested number of channels and channel map. In most cases it will now suffice to set default-channels=6 to enable 5.1 sound for all devices that support it
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2050 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
f752882525
commit
d17bb53d3e
15 changed files with 350 additions and 122 deletions
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
|
||||
#include "alsa-util.h"
|
||||
|
||||
|
|
@ -284,13 +285,21 @@ try_auto:
|
|||
|
||||
/* Set the hardware parameters of the given ALSA device. Returns the
|
||||
* selected fragment settings in *period and *period_size */
|
||||
int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size, int *use_mmap) {
|
||||
int pa_alsa_set_hw_params(
|
||||
snd_pcm_t *pcm_handle,
|
||||
pa_sample_spec *ss,
|
||||
uint32_t *periods,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
pa_bool_t *use_mmap,
|
||||
pa_bool_t require_exact_channel_number) {
|
||||
|
||||
int ret = -1;
|
||||
snd_pcm_uframes_t buffer_size;
|
||||
unsigned int r = ss->rate;
|
||||
unsigned int c = ss->channels;
|
||||
pa_sample_format_t f = ss->format;
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
pa_bool_t _use_mmap = use_mmap && *use_mmap;
|
||||
|
||||
pa_assert(pcm_handle);
|
||||
pa_assert(ss);
|
||||
|
|
@ -305,7 +314,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
|
|||
(ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0)
|
||||
goto finish;
|
||||
|
||||
if (use_mmap && *use_mmap) {
|
||||
if (_use_mmap) {
|
||||
if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0) {
|
||||
|
||||
/* mmap() didn't work, fall back to interleaved */
|
||||
|
|
@ -313,8 +322,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
|
|||
if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
|
||||
goto finish;
|
||||
|
||||
if (use_mmap)
|
||||
*use_mmap = 0;
|
||||
_use_mmap = FALSE;
|
||||
}
|
||||
|
||||
} else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
|
||||
|
|
@ -326,8 +334,13 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
|
|||
if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0)
|
||||
goto finish;
|
||||
|
||||
if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0)
|
||||
goto finish;
|
||||
if (require_exact_channel_number) {
|
||||
if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, c)) < 0)
|
||||
goto finish;
|
||||
} else {
|
||||
if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if ((*period_size > 0 && (ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, period_size, NULL)) < 0) ||
|
||||
(*periods > 0 && (ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0))
|
||||
|
|
@ -336,23 +349,14 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
|
|||
if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0)
|
||||
goto finish;
|
||||
|
||||
if (ss->rate != r) {
|
||||
if (ss->rate != r)
|
||||
pa_log_warn("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, r);
|
||||
|
||||
/* If the sample rate deviates too much, we need to resample */
|
||||
if (r < ss->rate*.95 || r > ss->rate*1.05)
|
||||
ss->rate = r;
|
||||
}
|
||||
|
||||
if (ss->channels != c) {
|
||||
if (ss->channels != c)
|
||||
pa_log_warn("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, c);
|
||||
ss->channels = c;
|
||||
}
|
||||
|
||||
if (ss->format != f) {
|
||||
if (ss->format != f)
|
||||
pa_log_warn("Device %s doesn't support sample format %s, changed to %s.", snd_pcm_name(pcm_handle), pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f));
|
||||
ss->format = f;
|
||||
}
|
||||
|
||||
if ((ret = snd_pcm_prepare(pcm_handle)) < 0)
|
||||
goto finish;
|
||||
|
|
@ -361,11 +365,20 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
|
|||
(ret = snd_pcm_hw_params_get_period_size(hwparams, period_size, NULL)) < 0)
|
||||
goto finish;
|
||||
|
||||
/* If the sample rate deviates too much, we need to resample */
|
||||
if (r < ss->rate*.95 || r > ss->rate*1.05)
|
||||
ss->rate = r;
|
||||
ss->channels = c;
|
||||
ss->format = f;
|
||||
|
||||
pa_assert(buffer_size > 0);
|
||||
pa_assert(*period_size > 0);
|
||||
*periods = buffer_size / *period_size;
|
||||
pa_assert(*periods > 0);
|
||||
|
||||
if (use_mmap)
|
||||
*use_mmap = _use_mmap;
|
||||
|
||||
ret = 0;
|
||||
|
||||
finish:
|
||||
|
|
@ -404,6 +417,209 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct device_info {
|
||||
pa_channel_map map;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const struct device_info device_table[] = {
|
||||
{{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } }, "front" },
|
||||
|
||||
{{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }}, "surround40" },
|
||||
|
||||
{{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
|
||||
PA_CHANNEL_POSITION_LFE }}, "surround41" },
|
||||
|
||||
{{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
|
||||
PA_CHANNEL_POSITION_CENTER }}, "surround50" },
|
||||
|
||||
{{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
|
||||
PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE }}, "surround51" },
|
||||
|
||||
{{ 8, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
|
||||
PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE,
|
||||
PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT }} , "surround71" },
|
||||
|
||||
{{ 0, { 0 }}, NULL }
|
||||
};
|
||||
|
||||
static pa_bool_t channel_map_superset(const pa_channel_map *a, const pa_channel_map *b) {
|
||||
pa_bool_t in_a[PA_CHANNEL_POSITION_MAX];
|
||||
unsigned i;
|
||||
|
||||
pa_assert(a);
|
||||
pa_assert(b);
|
||||
|
||||
memset(in_a, 0, sizeof(in_a));
|
||||
|
||||
for (i = 0; i < a->channels; i++)
|
||||
in_a[a->map[i]] = TRUE;
|
||||
|
||||
for (i = 0; i < b->channels; i++)
|
||||
if (!in_a[b->map[i]])
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
snd_pcm_t *pa_alsa_open_by_device_id(
|
||||
const char *dev_id,
|
||||
char **dev,
|
||||
pa_sample_spec *ss,
|
||||
pa_channel_map* map,
|
||||
int mode,
|
||||
uint32_t *nfrags,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
pa_bool_t *use_mmap) {
|
||||
|
||||
int i;
|
||||
int direction = 1;
|
||||
int err;
|
||||
char *d;
|
||||
snd_pcm_t *pcm_handle;
|
||||
|
||||
pa_assert(dev_id);
|
||||
pa_assert(dev);
|
||||
pa_assert(ss);
|
||||
pa_assert(map);
|
||||
pa_assert(nfrags);
|
||||
pa_assert(period_size);
|
||||
|
||||
/* First we try to find a device string with a superset of the
|
||||
* requested channel map and open it without the plug: prefix. We
|
||||
* iterate through our device table from top to bottom and take
|
||||
* the first that matches. If we didn't find a working device that
|
||||
* way, we iterate backwards, and check all devices that do not
|
||||
* provide a superset of the requested channel map.*/
|
||||
|
||||
for (i = 0;; i += direction) {
|
||||
pa_sample_spec try_ss;
|
||||
|
||||
if (i < 0) {
|
||||
pa_assert(direction == -1);
|
||||
|
||||
/* OK, so we iterated backwards, and now are at the
|
||||
* beginning of our list. */
|
||||
|
||||
break;
|
||||
|
||||
} else if (!device_table[i].name) {
|
||||
pa_assert(direction == 1);
|
||||
|
||||
/* OK, so we are at the end of our list. at iterated
|
||||
* forwards. */
|
||||
|
||||
i--;
|
||||
direction = -1;
|
||||
}
|
||||
|
||||
if ((direction > 0) == !channel_map_superset(&device_table[i].map, map))
|
||||
continue;
|
||||
|
||||
d = pa_sprintf_malloc("%s:%s", device_table[i].name, dev_id);
|
||||
pa_log_debug("Trying %s...", d);
|
||||
|
||||
if ((err = snd_pcm_open(&pcm_handle, d, mode, SND_PCM_NONBLOCK)) < 0) {
|
||||
pa_log_info("Couldn't open PCM device %s: %s", d, snd_strerror(err));
|
||||
pa_xfree(d);
|
||||
continue;
|
||||
}
|
||||
|
||||
try_ss.channels = device_table[i].map.channels;
|
||||
try_ss.rate = ss->rate;
|
||||
try_ss.format = ss->format;
|
||||
|
||||
if ((err = pa_alsa_set_hw_params(pcm_handle, &try_ss, nfrags, period_size, use_mmap, TRUE)) < 0) {
|
||||
pa_log_info("PCM device %s refused our hw parameters: %s", d, snd_strerror(err));
|
||||
pa_xfree(d);
|
||||
snd_pcm_close(pcm_handle);
|
||||
continue;
|
||||
}
|
||||
|
||||
*ss = try_ss;
|
||||
*map = device_table[i].map;
|
||||
pa_assert(map->channels == ss->channels);
|
||||
*dev = d;
|
||||
return pcm_handle;
|
||||
}
|
||||
|
||||
/* OK, we didn't find any good device, so let's try the raw hw: stuff */
|
||||
|
||||
d = pa_sprintf_malloc("hw:%s", dev_id);
|
||||
pa_log_debug("Trying %s as last resort...", d);
|
||||
pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, use_mmap);
|
||||
pa_xfree(d);
|
||||
|
||||
return pcm_handle;
|
||||
}
|
||||
|
||||
snd_pcm_t *pa_alsa_open_by_device_string(
|
||||
const char *device,
|
||||
char **dev,
|
||||
pa_sample_spec *ss,
|
||||
pa_channel_map* map,
|
||||
int mode,
|
||||
uint32_t *nfrags,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
pa_bool_t *use_mmap) {
|
||||
|
||||
int err;
|
||||
char *d;
|
||||
snd_pcm_t *pcm_handle;
|
||||
|
||||
pa_assert(device);
|
||||
pa_assert(dev);
|
||||
pa_assert(ss);
|
||||
pa_assert(map);
|
||||
pa_assert(nfrags);
|
||||
pa_assert(period_size);
|
||||
|
||||
d = pa_xstrdup(device);
|
||||
|
||||
for (;;) {
|
||||
|
||||
if ((err = snd_pcm_open(&pcm_handle, d, mode, SND_PCM_NONBLOCK)) < 0) {
|
||||
pa_log("Error opening PCM device %s: %s", d, snd_strerror(err));
|
||||
pa_xfree(d);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((err = pa_alsa_set_hw_params(pcm_handle, ss, nfrags, period_size, use_mmap, FALSE)) < 0) {
|
||||
|
||||
if (err == -EPERM) {
|
||||
/* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
|
||||
|
||||
if (pa_startswith(d, "hw:")) {
|
||||
char *t = pa_sprintf_malloc("plughw:%s", d+3);
|
||||
pa_log_debug("Opening the device as '%s' didn't work, retrying with '%s'.", d, t);
|
||||
pa_xfree(d);
|
||||
d = t;
|
||||
|
||||
snd_pcm_close(pcm_handle);
|
||||
continue;
|
||||
}
|
||||
|
||||
pa_log("Failed to set hardware parameters on %s: %s", d, snd_strerror(err));
|
||||
pa_xfree(d);
|
||||
snd_pcm_close(pcm_handle);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
*dev = d;
|
||||
|
||||
if (ss->channels != map->channels)
|
||||
pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_ALSA);
|
||||
|
||||
return pcm_handle;
|
||||
}
|
||||
}
|
||||
|
||||
int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) {
|
||||
int err;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,10 +38,37 @@ struct pa_alsa_fdlist *pa_alsa_fdlist_new(void);
|
|||
void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl);
|
||||
int pa_alsa_fdlist_set_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m);
|
||||
|
||||
int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size, int *use_mmap);
|
||||
int pa_alsa_set_hw_params(
|
||||
snd_pcm_t *pcm_handle,
|
||||
pa_sample_spec *ss,
|
||||
uint32_t *periods,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
pa_bool_t *use_mmap,
|
||||
pa_bool_t require_exact_channel_number);
|
||||
|
||||
int pa_alsa_set_sw_params(snd_pcm_t *pcm);
|
||||
|
||||
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, const char *fallback);
|
||||
|
||||
snd_pcm_t *pa_alsa_open_by_device_id(
|
||||
const char *dev_id,
|
||||
char **dev,
|
||||
pa_sample_spec *ss,
|
||||
pa_channel_map* map,
|
||||
int mode,
|
||||
uint32_t *nfrags,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
pa_bool_t *use_mmap);
|
||||
|
||||
snd_pcm_t *pa_alsa_open_by_device_string(
|
||||
const char *device,
|
||||
char **dev,
|
||||
pa_sample_spec *ss,
|
||||
pa_channel_map* map,
|
||||
int mode,
|
||||
uint32_t *nfrags,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
pa_bool_t *use_mmap);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ PA_MODULE_LOAD_ONCE(FALSE);
|
|||
PA_MODULE_USAGE(
|
||||
"sink_name=<name for the sink> "
|
||||
"device=<ALSA device> "
|
||||
"device_id=<ALSA device id> "
|
||||
"format=<sample format> "
|
||||
"channels=<number of channels> "
|
||||
"rate=<sample rate> "
|
||||
|
|
@ -89,15 +90,16 @@ struct userdata {
|
|||
|
||||
char *device_name;
|
||||
|
||||
int use_mmap;
|
||||
pa_bool_t use_mmap;
|
||||
|
||||
int first;
|
||||
pa_bool_t first;
|
||||
|
||||
pa_rtpoll_item *alsa_rtpoll_item;
|
||||
};
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"device",
|
||||
"device_id",
|
||||
"sink_name",
|
||||
"format",
|
||||
"channels",
|
||||
|
|
@ -127,7 +129,7 @@ static int mmap_write(struct userdata *u) {
|
|||
|
||||
if (n == -EPIPE) {
|
||||
pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
|
||||
u->first = 1;
|
||||
u->first = TRUE;
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0)
|
||||
|
|
@ -151,7 +153,7 @@ static int mmap_write(struct userdata *u) {
|
|||
|
||||
if (err == -EPIPE) {
|
||||
pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!");
|
||||
u->first = 1;
|
||||
u->first = TRUE;
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
|
||||
|
|
@ -188,7 +190,7 @@ static int mmap_write(struct userdata *u) {
|
|||
|
||||
if (err == -EPIPE) {
|
||||
pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!");
|
||||
u->first = 1;
|
||||
u->first = TRUE;
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
|
||||
|
|
@ -355,7 +357,8 @@ static int suspend(struct userdata *u) {
|
|||
|
||||
static int unsuspend(struct userdata *u) {
|
||||
pa_sample_spec ss;
|
||||
int err, b;
|
||||
int err;
|
||||
pa_bool_t b;
|
||||
unsigned nfrags;
|
||||
snd_pcm_uframes_t period_size;
|
||||
|
||||
|
|
@ -375,7 +378,7 @@ static int unsuspend(struct userdata *u) {
|
|||
period_size = u->fragment_size / u->frame_size;
|
||||
b = u->use_mmap;
|
||||
|
||||
if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) {
|
||||
if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b, TRUE)) < 0) {
|
||||
pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -405,7 +408,7 @@ static int unsuspend(struct userdata *u) {
|
|||
|
||||
/* FIXME: We need to reload the volume somehow */
|
||||
|
||||
u->first = 1;
|
||||
u->first = TRUE;
|
||||
|
||||
pa_log_info("Resumed successfully...");
|
||||
|
||||
|
|
@ -628,7 +631,7 @@ static void thread_func(void *userdata) {
|
|||
if (work_done && u->first) {
|
||||
pa_log_info("Starting playback.");
|
||||
snd_pcm_start(u->pcm_handle);
|
||||
u->first = 0;
|
||||
u->first = FALSE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -709,7 +712,7 @@ int pa__init(pa_module*m) {
|
|||
|
||||
pa_modargs *ma = NULL;
|
||||
struct userdata *u = NULL;
|
||||
char *dev;
|
||||
const char *dev_id;
|
||||
pa_sample_spec ss;
|
||||
pa_channel_map map;
|
||||
uint32_t nfrags, frag_size;
|
||||
|
|
@ -721,7 +724,7 @@ int pa__init(pa_module*m) {
|
|||
const char *name;
|
||||
char *name_buf = NULL;
|
||||
int namereg_fail;
|
||||
int use_mmap = 1, b;
|
||||
pa_bool_t use_mmap = TRUE, b;
|
||||
|
||||
snd_pcm_info_alloca(&pcm_info);
|
||||
|
||||
|
|
@ -761,7 +764,7 @@ int pa__init(pa_module*m) {
|
|||
u->module = m;
|
||||
m->userdata = u;
|
||||
u->use_mmap = use_mmap;
|
||||
u->first = 1;
|
||||
u->first = TRUE;
|
||||
pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
|
||||
u->rtpoll = pa_rtpoll_new();
|
||||
u->alsa_rtpoll_item = NULL;
|
||||
|
|
@ -769,43 +772,35 @@ int pa__init(pa_module*m) {
|
|||
|
||||
snd_config_update_free_global();
|
||||
|
||||
dev = pa_xstrdup(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE));
|
||||
b = use_mmap;
|
||||
|
||||
for (;;) {
|
||||
if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
|
||||
|
||||
if (!(u->pcm_handle = pa_alsa_open_by_device_id(
|
||||
dev_id,
|
||||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_PLAYBACK,
|
||||
&nfrags, &period_size,
|
||||
&b)))
|
||||
|
||||
if ((err = snd_pcm_open(&u->pcm_handle, dev, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
|
||||
pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err));
|
||||
pa_xfree(dev);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
b = use_mmap;
|
||||
if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) {
|
||||
} else {
|
||||
|
||||
if (err == -EPERM) {
|
||||
/* Hmm, some hw is very exotic, so we retry with plughw, if hw didn't work */
|
||||
|
||||
if (pa_startswith(dev, "hw:")) {
|
||||
char *d = pa_sprintf_malloc("plughw:%s", dev+3);
|
||||
pa_log_debug("Opening the device as '%s' didn't work, retrying with '%s'.", dev, d);
|
||||
pa_xfree(dev);
|
||||
dev = d;
|
||||
|
||||
snd_pcm_close(u->pcm_handle);
|
||||
u->pcm_handle = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
|
||||
pa_xfree(dev);
|
||||
if (!(u->pcm_handle = pa_alsa_open_by_device_string(
|
||||
pa_modargs_get_value(ma, "device", DEFAULT_DEVICE),
|
||||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_PLAYBACK,
|
||||
&nfrags, &period_size,
|
||||
&b)))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
u->device_name = dev;
|
||||
pa_assert(u->device_name);
|
||||
pa_log_info("Successfully opened device %s.", u->device_name);
|
||||
|
||||
if (use_mmap && !b) {
|
||||
pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
|
||||
|
|
@ -828,15 +823,11 @@ int pa__init(pa_module*m) {
|
|||
/* ALSA might tweak the sample spec, so recalculate the frame size */
|
||||
frame_size = pa_frame_size(&ss);
|
||||
|
||||
if (ss.channels != map.channels)
|
||||
/* Seems ALSA didn't like the channel number, so let's fix the channel map */
|
||||
pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA);
|
||||
|
||||
if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0)
|
||||
pa_log_warn("Error opening mixer: %s", snd_strerror(err));
|
||||
else {
|
||||
|
||||
if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) ||
|
||||
if ((pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) < 0) ||
|
||||
!(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Master", "PCM"))) {
|
||||
|
||||
snd_mixer_close(u->mixer_handle);
|
||||
|
|
@ -847,7 +838,7 @@ int pa__init(pa_module*m) {
|
|||
if ((name = pa_modargs_get_value(ma, "sink_name", NULL)))
|
||||
namereg_fail = 1;
|
||||
else {
|
||||
name = name_buf = pa_sprintf_malloc("alsa_output.%s", dev);
|
||||
name = name_buf = pa_sprintf_malloc("alsa_output.%s", u->device_name);
|
||||
namereg_fail = 0;
|
||||
}
|
||||
|
||||
|
|
@ -867,7 +858,7 @@ int pa__init(pa_module*m) {
|
|||
pa_sink_set_rtpoll(u->sink, u->rtpoll);
|
||||
pa_sink_set_description(u->sink, t = pa_sprintf_malloc(
|
||||
"ALSA PCM on %s (%s)%s",
|
||||
dev,
|
||||
u->device_name,
|
||||
snd_pcm_info_get_name(pcm_info),
|
||||
use_mmap ? " via DMA" : ""));
|
||||
pa_xfree(t);
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ PA_MODULE_LOAD_ONCE(FALSE);
|
|||
PA_MODULE_USAGE(
|
||||
"source_name=<name for the source> "
|
||||
"device=<ALSA device> "
|
||||
"device_id=<ALSA device id> "
|
||||
"format=<sample format> "
|
||||
"channels=<number of channels> "
|
||||
"rate=<sample rate> "
|
||||
|
|
@ -89,13 +90,14 @@ struct userdata {
|
|||
|
||||
char *device_name;
|
||||
|
||||
int use_mmap;
|
||||
pa_bool_t use_mmap;
|
||||
|
||||
pa_rtpoll_item *alsa_rtpoll_item;
|
||||
};
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"device",
|
||||
"device_id",
|
||||
"source_name",
|
||||
"channels",
|
||||
"rate",
|
||||
|
|
@ -342,7 +344,8 @@ static int suspend(struct userdata *u) {
|
|||
|
||||
static int unsuspend(struct userdata *u) {
|
||||
pa_sample_spec ss;
|
||||
int err, b;
|
||||
int err;
|
||||
pa_bool_t b;
|
||||
unsigned nfrags;
|
||||
snd_pcm_uframes_t period_size;
|
||||
|
||||
|
|
@ -362,7 +365,7 @@ static int unsuspend(struct userdata *u) {
|
|||
period_size = u->fragment_size / u->frame_size;
|
||||
b = u->use_mmap;
|
||||
|
||||
if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) {
|
||||
if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b, TRUE)) < 0) {
|
||||
pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -691,10 +694,10 @@ int pa__init(pa_module*m) {
|
|||
|
||||
pa_modargs *ma = NULL;
|
||||
struct userdata *u = NULL;
|
||||
char *dev;
|
||||
const char *dev_id;
|
||||
pa_sample_spec ss;
|
||||
pa_channel_map map;
|
||||
unsigned nfrags, frag_size;
|
||||
uint32_t nfrags, frag_size;
|
||||
snd_pcm_uframes_t period_size;
|
||||
size_t frame_size;
|
||||
snd_pcm_info_t *pcm_info = NULL;
|
||||
|
|
@ -703,7 +706,7 @@ int pa__init(pa_module*m) {
|
|||
const char *name;
|
||||
char *name_buf = NULL;
|
||||
int namereg_fail;
|
||||
int use_mmap = 1, b;
|
||||
pa_bool_t use_mmap = TRUE, b;
|
||||
|
||||
snd_pcm_info_alloca(&pcm_info);
|
||||
|
||||
|
|
@ -750,43 +753,31 @@ int pa__init(pa_module*m) {
|
|||
|
||||
snd_config_update_free_global();
|
||||
|
||||
dev = pa_xstrdup(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE));
|
||||
if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
|
||||
|
||||
for (;;) {
|
||||
|
||||
if ((err = snd_pcm_open(&u->pcm_handle, dev, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) {
|
||||
pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err));
|
||||
pa_xfree(dev);
|
||||
if (!(u->pcm_handle = pa_alsa_open_by_device_id(
|
||||
dev_id,
|
||||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_CAPTURE,
|
||||
&nfrags, &period_size,
|
||||
&b)))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
b = use_mmap;
|
||||
if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) {
|
||||
} else {
|
||||
|
||||
if (err == -EPERM) {
|
||||
/* Hmm, some hw is very exotic, so we retry with plughw, if hw didn't work */
|
||||
|
||||
if (pa_startswith(dev, "hw:")) {
|
||||
char *d = pa_sprintf_malloc("plughw:%s", dev+3);
|
||||
pa_log_debug("Opening the device as '%s' didn't work, retrying with '%s'.", dev, d);
|
||||
pa_xfree(dev);
|
||||
dev = d;
|
||||
|
||||
snd_pcm_close(u->pcm_handle);
|
||||
u->pcm_handle = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
|
||||
pa_xfree(dev);
|
||||
if (!(u->pcm_handle = pa_alsa_open_by_device_string(
|
||||
pa_modargs_get_value(ma, "device", DEFAULT_DEVICE),
|
||||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_CAPTURE,
|
||||
&nfrags, &period_size,
|
||||
&b)))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
u->device_name = dev;
|
||||
pa_assert(u->device_name);
|
||||
pa_log_info("Successfully opened device %s.", u->device_name);
|
||||
|
||||
if (use_mmap && !b) {
|
||||
pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
|
||||
|
|
@ -817,7 +808,7 @@ int pa__init(pa_module*m) {
|
|||
pa_log("Error opening mixer: %s", snd_strerror(err));
|
||||
else {
|
||||
|
||||
if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) ||
|
||||
if ((pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) < 0) ||
|
||||
!(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", NULL))) {
|
||||
snd_mixer_close(u->mixer_handle);
|
||||
u->mixer_handle = NULL;
|
||||
|
|
@ -827,7 +818,7 @@ int pa__init(pa_module*m) {
|
|||
if ((name = pa_modargs_get_value(ma, "source_name", NULL)))
|
||||
namereg_fail = 1;
|
||||
else {
|
||||
name = name_buf = pa_sprintf_malloc("alsa_input.%s", dev);
|
||||
name = name_buf = pa_sprintf_malloc("alsa_input.%s", u->device_name);
|
||||
namereg_fail = 0;
|
||||
}
|
||||
|
||||
|
|
@ -847,7 +838,7 @@ int pa__init(pa_module*m) {
|
|||
pa_source_set_rtpoll(u->source, u->rtpoll);
|
||||
pa_source_set_description(u->source, t = pa_sprintf_malloc(
|
||||
"ALSA PCM on %s (%s)%s",
|
||||
dev,
|
||||
u->device_name,
|
||||
snd_pcm_info_get_name(pcm_info),
|
||||
use_mmap ? " via DMA" : ""));
|
||||
pa_xfree(t);
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ static struct bonding* bonding_new(struct userdata *u, const char *a) {
|
|||
dbus_message_unref(m);
|
||||
dbus_message_unref(r);
|
||||
|
||||
pa_hashmap_put(u->bondings, a, b);
|
||||
pa_hashmap_put(u->bondings, b->address, b);
|
||||
|
||||
return b;
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ static void eof_and_exit_cb(pa_cli*c, void *userdata) {
|
|||
int pa__init(pa_module*m) {
|
||||
pa_iochannel *io;
|
||||
pa_modargs *ma;
|
||||
int exit_on_eof = 0;
|
||||
pa_bool_t exit_on_eof = FALSE;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
|
|
|
|||
|
|
@ -222,7 +222,8 @@ static int detect_waveout(pa_core *c, int just_one) {
|
|||
#endif
|
||||
|
||||
int pa__init(pa_module*m) {
|
||||
int just_one = 0, n = 0;
|
||||
pa_bool_t just_one = FALSE;
|
||||
int n = 0;
|
||||
pa_modargs *ma;
|
||||
|
||||
pa_assert(m);
|
||||
|
|
|
|||
|
|
@ -191,12 +191,12 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, char
|
|||
*sink_name = pa_sprintf_malloc("alsa_output.%s", strip_udi(udi));
|
||||
|
||||
module_name = "module-alsa-sink";
|
||||
args = pa_sprintf_malloc("device=hw:%u sink_name=%s", card, *sink_name);
|
||||
args = pa_sprintf_malloc("device_id=%u sink_name=%s", card, *sink_name);
|
||||
} else {
|
||||
*source_name = pa_sprintf_malloc("alsa_input.%s", strip_udi(udi));
|
||||
|
||||
module_name = "module-alsa-source";
|
||||
args = pa_sprintf_malloc("device=hw:%u source_name=%s", card, *source_name);
|
||||
args = pa_sprintf_malloc("device_id=%u source_name=%s", card, *source_name);
|
||||
}
|
||||
|
||||
pa_log_debug("Loading %s with arguments '%s'", module_name, args);
|
||||
|
|
|
|||
|
|
@ -1139,7 +1139,7 @@ int pa__init(pa_module*m) {
|
|||
int fd = -1;
|
||||
int nfrags, frag_size;
|
||||
int mode, caps;
|
||||
int record = 1, playback = 1, use_mmap = 1;
|
||||
pa_bool_t record = TRUE, playback = TRUE, use_mmap = TRUE;
|
||||
pa_sample_spec ss;
|
||||
pa_channel_map map;
|
||||
pa_modargs *ma = NULL;
|
||||
|
|
|
|||
|
|
@ -179,11 +179,11 @@ int pa__init(pa_module*m) {
|
|||
pa_source_output *o = NULL;
|
||||
uint8_t payload;
|
||||
char *p;
|
||||
int r;
|
||||
int r, j;
|
||||
socklen_t k;
|
||||
struct timeval tv;
|
||||
char hn[128], *n;
|
||||
int loop = 0;
|
||||
pa_bool_t loop = FALSE;
|
||||
pa_source_output_new_data data;
|
||||
|
||||
pa_assert(m);
|
||||
|
|
@ -274,8 +274,9 @@ int pa__init(pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0 ||
|
||||
setsockopt(sap_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) {
|
||||
j = !!loop;
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &j, sizeof(j)) < 0 ||
|
||||
setsockopt(sap_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &j, sizeof(j)) < 0) {
|
||||
pa_log("IP_MULTICAST_LOOP failed: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ int pa_modargs_get_value_s32(pa_modargs *ma, const char *key, int32_t *value) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, int *value) {
|
||||
int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, pa_bool_t *value) {
|
||||
const char *v;
|
||||
int r;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <pulse/sample.h>
|
||||
#include <pulse/channelmap.h>
|
||||
#include <pulsecore/core.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
typedef struct pa_modargs pa_modargs;
|
||||
|
||||
|
|
@ -44,7 +45,7 @@ const char *pa_modargs_get_value(pa_modargs *ma, const char *key, const char *de
|
|||
/* Return a module argument as unsigned 32bit value in *value */
|
||||
int pa_modargs_get_value_u32(pa_modargs *ma, const char *key, uint32_t *value);
|
||||
int pa_modargs_get_value_s32(pa_modargs *ma, const char *key, int32_t *value);
|
||||
int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, int *value);
|
||||
int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, pa_bool_t *value);
|
||||
|
||||
/* Return sample spec data from the three arguments "rate", "format" and "channels" */
|
||||
int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *ss);
|
||||
|
|
|
|||
|
|
@ -1406,7 +1406,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
|
|||
|
||||
pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *server, pa_module *m, pa_modargs *ma) {
|
||||
pa_protocol_esound *p = NULL;
|
||||
int public = 0;
|
||||
pa_bool_t public = FALSE;
|
||||
const char *acl;
|
||||
|
||||
pa_assert(core);
|
||||
|
|
|
|||
|
|
@ -2956,7 +2956,7 @@ static int load_key(pa_protocol_native*p, const char*fn) {
|
|||
|
||||
static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_modargs *ma) {
|
||||
pa_protocol_native *p;
|
||||
int public = 0;
|
||||
pa_bool_t public = FALSE;
|
||||
const char *acl;
|
||||
|
||||
pa_assert(c);
|
||||
|
|
@ -2976,7 +2976,7 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo
|
|||
|
||||
#ifdef HAVE_CREDS
|
||||
{
|
||||
int a = 1;
|
||||
pa_bool_t a = 1;
|
||||
if (pa_modargs_get_value_boolean(ma, "auth-group-enabled", &a) < 0) {
|
||||
pa_log("auth-group-enabled= expects a boolean argument.");
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -566,7 +566,7 @@ fail:
|
|||
|
||||
pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma) {
|
||||
pa_protocol_simple* p = NULL;
|
||||
int enable;
|
||||
pa_bool_t enable;
|
||||
|
||||
pa_assert(core);
|
||||
pa_assert(server);
|
||||
|
|
@ -587,7 +587,7 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv
|
|||
p->source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL));
|
||||
p->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
|
||||
|
||||
enable = 0;
|
||||
enable = FALSE;
|
||||
if (pa_modargs_get_value_boolean(ma, "record", &enable) < 0) {
|
||||
pa_log("record= expects a numeric argument.");
|
||||
goto fail;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue