mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-03 09:01:50 -05:00
Merge branch 'master' into dbus-work
Conflicts: src/daemon/daemon-conf.c
This commit is contained in:
commit
019331d25b
130 changed files with 24774 additions and 14714 deletions
|
|
@ -479,7 +479,6 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
|||
snd_mixer_elem_t *me;
|
||||
snd_mixer_selem_channel_id_t c;
|
||||
pa_channel_position_mask_t mask = 0;
|
||||
pa_volume_t max_channel_volume = PA_VOLUME_MUTED;
|
||||
unsigned k;
|
||||
|
||||
pa_assert(m);
|
||||
|
|
@ -546,9 +545,6 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
|||
f = from_alsa_volume(value, e->min_volume, e->max_volume);
|
||||
}
|
||||
|
||||
if (f > max_channel_volume)
|
||||
max_channel_volume = f;
|
||||
|
||||
for (k = 0; k < cm->channels; k++)
|
||||
if (e->masks[c][e->n_channels-1] & PA_CHANNEL_POSITION_MASK(cm->map[k]))
|
||||
if (v->values[k] < f)
|
||||
|
|
@ -559,7 +555,7 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
|||
|
||||
for (k = 0; k < cm->channels; k++)
|
||||
if (!(mask & PA_CHANNEL_POSITION_MASK(cm->map[k])))
|
||||
v->values[k] = max_channel_volume;
|
||||
v->values[k] = PA_VOLUME_NORM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -681,7 +677,6 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
|||
snd_mixer_elem_t *me;
|
||||
snd_mixer_selem_channel_id_t c;
|
||||
pa_channel_position_mask_t mask = 0;
|
||||
pa_volume_t max_channel_volume = PA_VOLUME_MUTED;
|
||||
unsigned k;
|
||||
|
||||
pa_assert(m);
|
||||
|
|
@ -771,9 +766,6 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
|||
f = from_alsa_volume(value, e->min_volume, e->max_volume);
|
||||
}
|
||||
|
||||
if (f > max_channel_volume)
|
||||
max_channel_volume = f;
|
||||
|
||||
for (k = 0; k < cm->channels; k++)
|
||||
if (e->masks[c][e->n_channels-1] & PA_CHANNEL_POSITION_MASK(cm->map[k]))
|
||||
if (rv.values[k] < f)
|
||||
|
|
@ -784,7 +776,7 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
|||
|
||||
for (k = 0; k < cm->channels; k++)
|
||||
if (!(mask & PA_CHANNEL_POSITION_MASK(cm->map[k])))
|
||||
rv.values[k] = max_channel_volume;
|
||||
rv.values[k] = PA_VOLUME_NORM;
|
||||
|
||||
*v = rv;
|
||||
return 0;
|
||||
|
|
@ -1716,11 +1708,11 @@ static int option_verify(pa_alsa_option *o) {
|
|||
{ "input-radio", N_("Radio") },
|
||||
{ "input-video", N_("Video") },
|
||||
{ "input-agc-on", N_("Automatic Gain Control") },
|
||||
{ "input-agc-off", "" },
|
||||
{ "input-agc-off", N_("No Automatic Gain Control") },
|
||||
{ "input-boost-on", N_("Boost") },
|
||||
{ "input-boost-off", "" },
|
||||
{ "input-boost-off", N_("No Boost") },
|
||||
{ "output-amplifier-on", N_("Amplifier") },
|
||||
{ "output-amplifier-off", "" }
|
||||
{ "output-amplifier-off", N_("No Amplifier") }
|
||||
};
|
||||
|
||||
pa_assert(o);
|
||||
|
|
@ -2889,7 +2881,7 @@ static void profile_set_add_auto_pair(
|
|||
else
|
||||
name = pa_sprintf_malloc("input:%s", n->name);
|
||||
|
||||
if ((p = pa_hashmap_get(ps->profiles, name))) {
|
||||
if (pa_hashmap_get(ps->profiles, name)) {
|
||||
pa_xfree(name);
|
||||
return;
|
||||
}
|
||||
|
|
@ -3145,7 +3137,13 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss) {
|
||||
void pa_alsa_profile_set_probe(
|
||||
pa_alsa_profile_set *ps,
|
||||
const char *dev_id,
|
||||
const pa_sample_spec *ss,
|
||||
unsigned default_n_fragments,
|
||||
unsigned default_fragment_size_msec) {
|
||||
|
||||
void *state;
|
||||
pa_alsa_profile *p, *last = NULL;
|
||||
pa_alsa_mapping *m;
|
||||
|
|
@ -3160,6 +3158,7 @@ void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, cons
|
|||
PA_HASHMAP_FOREACH(p, ps->profiles, state) {
|
||||
pa_sample_spec try_ss;
|
||||
pa_channel_map try_map;
|
||||
snd_pcm_uframes_t try_period_size, try_buffer_size;
|
||||
uint32_t idx;
|
||||
|
||||
/* Is this already marked that it is supported? (i.e. from the config file) */
|
||||
|
|
@ -3213,13 +3212,18 @@ void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, cons
|
|||
try_ss = *ss;
|
||||
try_ss.channels = try_map.channels;
|
||||
|
||||
try_period_size =
|
||||
pa_usec_to_bytes(default_fragment_size_msec * PA_USEC_PER_MSEC, &try_ss) /
|
||||
pa_frame_size(&try_ss);
|
||||
try_buffer_size = default_n_fragments * try_period_size;
|
||||
|
||||
if (!(m ->output_pcm = pa_alsa_open_by_template(
|
||||
m->device_strings,
|
||||
dev_id,
|
||||
NULL,
|
||||
&try_ss, &try_map,
|
||||
SND_PCM_STREAM_PLAYBACK,
|
||||
NULL, NULL, 0, NULL, NULL,
|
||||
&try_period_size, &try_buffer_size, 0, NULL, NULL,
|
||||
TRUE))) {
|
||||
p->supported = FALSE;
|
||||
break;
|
||||
|
|
@ -3237,13 +3241,18 @@ void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, cons
|
|||
try_ss = *ss;
|
||||
try_ss.channels = try_map.channels;
|
||||
|
||||
try_period_size =
|
||||
pa_usec_to_bytes(default_fragment_size_msec*PA_USEC_PER_MSEC, &try_ss) /
|
||||
pa_frame_size(&try_ss);
|
||||
try_buffer_size = default_n_fragments * try_period_size;
|
||||
|
||||
if (!(m ->input_pcm = pa_alsa_open_by_template(
|
||||
m->device_strings,
|
||||
dev_id,
|
||||
NULL,
|
||||
&try_ss, &try_map,
|
||||
SND_PCM_STREAM_CAPTURE,
|
||||
NULL, NULL, 0, NULL, NULL,
|
||||
&try_period_size, &try_buffer_size, 0, NULL, NULL,
|
||||
TRUE))) {
|
||||
p->supported = FALSE;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ void pa_alsa_mapping_dump(pa_alsa_mapping *m);
|
|||
void pa_alsa_profile_dump(pa_alsa_profile *p);
|
||||
|
||||
pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus);
|
||||
void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss);
|
||||
void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss, unsigned default_n_fragments, unsigned default_fragment_size_msec);
|
||||
void pa_alsa_profile_set_free(pa_alsa_profile_set *s);
|
||||
void pa_alsa_profile_set_dump(pa_alsa_profile_set *s);
|
||||
|
||||
|
|
|
|||
|
|
@ -69,9 +69,12 @@
|
|||
#define TSCHED_WATERMARK_INC_STEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms -- On underrun, increase watermark by this */
|
||||
#define TSCHED_WATERMARK_DEC_STEP_USEC (5*PA_USEC_PER_MSEC) /* 5ms -- When everything's great, decrease watermark by this */
|
||||
#define TSCHED_WATERMARK_VERIFY_AFTER_USEC (20*PA_USEC_PER_SEC) /* 20s -- How long after a drop out recheck if things are good now */
|
||||
#define TSCHED_WATERMARK_INC_THRESHOLD_USEC (1*PA_USEC_PER_MSEC) /* 3ms -- If the buffer level ever below this theshold, increase the watermark */
|
||||
#define TSCHED_WATERMARK_INC_THRESHOLD_USEC (0*PA_USEC_PER_MSEC) /* 0ms -- If the buffer level ever below this theshold, increase the watermark */
|
||||
#define TSCHED_WATERMARK_DEC_THRESHOLD_USEC (100*PA_USEC_PER_MSEC) /* 100ms -- If the buffer level didn't drop below this theshold in the verification time, decrease the watermark */
|
||||
|
||||
/* Note that TSCHED_WATERMARK_INC_THRESHOLD_USEC == 0 means tht we
|
||||
* will increase the watermark only if we hit a real underrun. */
|
||||
|
||||
#define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms -- Sleep at least 10ms on each iteration */
|
||||
#define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC) /* 4ms -- Wakeup at least this long before the buffer runs empty*/
|
||||
|
||||
|
|
@ -113,7 +116,6 @@ struct userdata {
|
|||
|
||||
pa_usec_t watermark_dec_not_before;
|
||||
|
||||
unsigned nfragments;
|
||||
pa_memchunk memchunk;
|
||||
|
||||
char *device_name; /* name of the PCM device */
|
||||
|
|
@ -410,6 +412,7 @@ static int try_recover(struct userdata *u, const char *call, int err) {
|
|||
|
||||
static size_t check_left_to_play(struct userdata *u, size_t n_bytes, pa_bool_t on_timeout) {
|
||||
size_t left_to_play;
|
||||
pa_bool_t underrun = FALSE;
|
||||
|
||||
/* We use <= instead of < for this check here because an underrun
|
||||
* only happens after the last sample was processed, not already when
|
||||
|
|
@ -422,6 +425,7 @@ static size_t check_left_to_play(struct userdata *u, size_t n_bytes, pa_bool_t o
|
|||
|
||||
/* We got a dropout. What a mess! */
|
||||
left_to_play = 0;
|
||||
underrun = TRUE;
|
||||
|
||||
#ifdef DEBUG_TIMING
|
||||
PA_DEBUG_TRAP;
|
||||
|
|
@ -443,7 +447,7 @@ static size_t check_left_to_play(struct userdata *u, size_t n_bytes, pa_bool_t o
|
|||
pa_bool_t reset_not_before = TRUE;
|
||||
|
||||
if (!u->first && !u->after_rewind) {
|
||||
if (left_to_play < u->watermark_inc_threshold)
|
||||
if (underrun || left_to_play < u->watermark_inc_threshold)
|
||||
increase_watermark(u);
|
||||
else if (left_to_play > u->watermark_dec_threshold) {
|
||||
reset_not_before = FALSE;
|
||||
|
|
@ -651,6 +655,7 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle
|
|||
snd_pcm_sframes_t n;
|
||||
size_t n_bytes;
|
||||
int r;
|
||||
pa_bool_t after_avail = TRUE;
|
||||
|
||||
if (PA_UNLIKELY((n = pa_alsa_safe_avail(u->pcm_handle, u->hwbuf_size, &u->sink->sample_spec)) < 0)) {
|
||||
|
||||
|
|
@ -705,7 +710,6 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle
|
|||
for (;;) {
|
||||
snd_pcm_sframes_t frames;
|
||||
void *p;
|
||||
pa_bool_t after_avail = TRUE;
|
||||
|
||||
/* pa_log_debug("%lu frames to write", (unsigned long) frames); */
|
||||
|
||||
|
|
@ -938,8 +942,7 @@ static int unsuspend(struct userdata *u) {
|
|||
pa_sample_spec ss;
|
||||
int err;
|
||||
pa_bool_t b, d;
|
||||
unsigned nfrags;
|
||||
snd_pcm_uframes_t period_size;
|
||||
snd_pcm_uframes_t period_size, buffer_size;
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(!u->pcm_handle);
|
||||
|
|
@ -947,7 +950,7 @@ static int unsuspend(struct userdata *u) {
|
|||
pa_log_info("Trying resume...");
|
||||
|
||||
if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_PLAYBACK,
|
||||
/*SND_PCM_NONBLOCK|*/
|
||||
SND_PCM_NONBLOCK|
|
||||
SND_PCM_NO_AUTO_RESAMPLE|
|
||||
SND_PCM_NO_AUTO_CHANNELS|
|
||||
SND_PCM_NO_AUTO_FORMAT)) < 0) {
|
||||
|
|
@ -956,12 +959,12 @@ static int unsuspend(struct userdata *u) {
|
|||
}
|
||||
|
||||
ss = u->sink->sample_spec;
|
||||
nfrags = u->nfragments;
|
||||
period_size = u->fragment_size / u->frame_size;
|
||||
buffer_size = u->hwbuf_size / u->frame_size;
|
||||
b = u->use_mmap;
|
||||
d = u->use_tsched;
|
||||
|
||||
if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, u->hwbuf_size / u->frame_size, &b, &d, TRUE)) < 0) {
|
||||
if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &period_size, &buffer_size, 0, &b, &d, TRUE)) < 0) {
|
||||
pa_log("Failed to set hardware parameters: %s", pa_alsa_strerror(err));
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -976,10 +979,11 @@ static int unsuspend(struct userdata *u) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
|
||||
pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)",
|
||||
(unsigned long) u->nfragments, (unsigned long) u->fragment_size,
|
||||
(unsigned long) nfrags, period_size * u->frame_size);
|
||||
if (period_size*u->frame_size != u->fragment_size ||
|
||||
buffer_size*u->frame_size != u->hwbuf_size) {
|
||||
pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu/%lu, New %lu/%lu)",
|
||||
(unsigned long) u->hwbuf_size, (unsigned long) u->fragment_size,
|
||||
(unsigned long) (buffer_size*u->fragment_size), (unsigned long) (period_size*u->frame_size));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -1007,7 +1011,7 @@ fail:
|
|||
u->pcm_handle = NULL;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return -PA_ERR_IO;
|
||||
}
|
||||
|
||||
/* Called from IO context */
|
||||
|
|
@ -1031,28 +1035,33 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
|
|||
|
||||
switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
|
||||
|
||||
case PA_SINK_SUSPENDED:
|
||||
case PA_SINK_SUSPENDED: {
|
||||
int r;
|
||||
|
||||
pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
|
||||
|
||||
if (suspend(u) < 0)
|
||||
return -1;
|
||||
if ((r = suspend(u)) < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PA_SINK_IDLE:
|
||||
case PA_SINK_RUNNING:
|
||||
case PA_SINK_RUNNING: {
|
||||
int r;
|
||||
|
||||
if (u->sink->thread_info.state == PA_SINK_INIT) {
|
||||
if (build_pollfd(u) < 0)
|
||||
return -1;
|
||||
return -PA_ERR_IO;
|
||||
}
|
||||
|
||||
if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
|
||||
if (unsuspend(u) < 0)
|
||||
return -1;
|
||||
if ((r = unsuspend(u)) < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PA_SINK_UNLINKED:
|
||||
case PA_SINK_INIT:
|
||||
|
|
@ -1080,7 +1089,7 @@ static int sink_set_state_cb(pa_sink *s, pa_sink_state_t new_state) {
|
|||
reserve_done(u);
|
||||
else if (old_state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(new_state))
|
||||
if (reserve_init(u, u->device_name) < 0)
|
||||
return -1;
|
||||
return -PA_ERR_BUSY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1633,8 +1642,8 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
const char *dev_id = NULL;
|
||||
pa_sample_spec ss, requested_ss;
|
||||
pa_channel_map map;
|
||||
uint32_t nfrags, hwbuf_size, frag_size, tsched_size, tsched_watermark;
|
||||
snd_pcm_uframes_t period_frames, tsched_frames;
|
||||
uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark;
|
||||
snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
|
||||
size_t frame_size;
|
||||
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE;
|
||||
pa_sink_new_data data;
|
||||
|
|
@ -1668,8 +1677,10 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
goto fail;
|
||||
}
|
||||
|
||||
hwbuf_size = frag_size * nfrags;
|
||||
buffer_size = nfrags * frag_size;
|
||||
|
||||
period_frames = frag_size/frame_size;
|
||||
buffer_frames = buffer_size/frame_size;
|
||||
tsched_frames = tsched_size/frame_size;
|
||||
|
||||
if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
|
||||
|
|
@ -1736,7 +1747,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_PLAYBACK,
|
||||
&nfrags, &period_frames, tsched_frames,
|
||||
&period_frames, &buffer_frames, tsched_frames,
|
||||
&b, &d, mapping)))
|
||||
|
||||
goto fail;
|
||||
|
|
@ -1751,7 +1762,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_PLAYBACK,
|
||||
&nfrags, &period_frames, tsched_frames,
|
||||
&period_frames, &buffer_frames, tsched_frames,
|
||||
&b, &d, profile_set, &mapping)))
|
||||
|
||||
goto fail;
|
||||
|
|
@ -1763,7 +1774,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_PLAYBACK,
|
||||
&nfrags, &period_frames, tsched_frames,
|
||||
&period_frames, &buffer_frames, tsched_frames,
|
||||
&b, &d, FALSE)))
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -1789,11 +1800,6 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
u->use_tsched = use_tsched = FALSE;
|
||||
}
|
||||
|
||||
if (use_tsched && !pa_alsa_pcm_is_hw(u->pcm_handle)) {
|
||||
pa_log_info("Device is not a hardware device, disabling timer-based scheduling.");
|
||||
u->use_tsched = use_tsched = FALSE;
|
||||
}
|
||||
|
||||
if (u->use_mmap)
|
||||
pa_log_info("Successfully enabled mmap() mode.");
|
||||
|
||||
|
|
@ -1815,7 +1821,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
|
||||
pa_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle);
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
|
||||
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
|
||||
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (buffer_frames * frame_size));
|
||||
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
|
||||
|
||||
|
|
@ -1856,13 +1862,15 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
pa_sink_set_rtpoll(u->sink, u->rtpoll);
|
||||
|
||||
u->frame_size = frame_size;
|
||||
u->fragment_size = frag_size = (uint32_t) (period_frames * frame_size);
|
||||
u->nfragments = nfrags;
|
||||
u->hwbuf_size = u->fragment_size * nfrags;
|
||||
u->fragment_size = frag_size = (size_t) (period_frames * frame_size);
|
||||
u->hwbuf_size = buffer_size = (size_t) (buffer_frames * frame_size);
|
||||
pa_cvolume_mute(&u->hardware_volume, u->sink->sample_spec.channels);
|
||||
|
||||
pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
|
||||
nfrags, (long unsigned) u->fragment_size,
|
||||
pa_log_info("Using %0.1f fragments of size %lu bytes (%0.2fms), buffer size is %lu bytes (%0.2fms)",
|
||||
(double) u->hwbuf_size / (double) u->fragment_size,
|
||||
(long unsigned) u->fragment_size,
|
||||
(double) pa_bytes_to_usec(u->fragment_size, &ss) / PA_USEC_PER_MSEC,
|
||||
(long unsigned) u->hwbuf_size,
|
||||
(double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
|
||||
|
||||
pa_sink_set_max_request(u->sink, u->hwbuf_size);
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@
|
|||
#define TSCHED_WATERMARK_INC_STEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */
|
||||
#define TSCHED_WATERMARK_DEC_STEP_USEC (5*PA_USEC_PER_MSEC) /* 5ms */
|
||||
#define TSCHED_WATERMARK_VERIFY_AFTER_USEC (20*PA_USEC_PER_SEC) /* 20s */
|
||||
#define TSCHED_WATERMARK_INC_THRESHOLD_USEC (1*PA_USEC_PER_MSEC) /* 3ms */
|
||||
#define TSCHED_WATERMARK_INC_THRESHOLD_USEC (0*PA_USEC_PER_MSEC) /* 0ms */
|
||||
#define TSCHED_WATERMARK_DEC_THRESHOLD_USEC (100*PA_USEC_PER_MSEC) /* 100ms */
|
||||
#define TSCHED_WATERMARK_STEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */
|
||||
|
||||
|
|
@ -111,8 +111,6 @@ struct userdata {
|
|||
|
||||
pa_usec_t watermark_dec_not_before;
|
||||
|
||||
unsigned nfragments;
|
||||
|
||||
char *device_name;
|
||||
char *control_device;
|
||||
|
||||
|
|
@ -406,6 +404,7 @@ static int try_recover(struct userdata *u, const char *call, int err) {
|
|||
static size_t check_left_to_record(struct userdata *u, size_t n_bytes, pa_bool_t on_timeout) {
|
||||
size_t left_to_record;
|
||||
size_t rec_space = u->hwbuf_size - u->hwbuf_unused;
|
||||
pa_bool_t overrun = FALSE;
|
||||
|
||||
/* We use <= instead of < for this check here because an overrun
|
||||
* only happens after the last sample was processed, not already when
|
||||
|
|
@ -418,6 +417,7 @@ static size_t check_left_to_record(struct userdata *u, size_t n_bytes, pa_bool_t
|
|||
|
||||
/* We got a dropout. What a mess! */
|
||||
left_to_record = 0;
|
||||
overrun = TRUE;
|
||||
|
||||
#ifdef DEBUG_TIMING
|
||||
PA_DEBUG_TRAP;
|
||||
|
|
@ -434,7 +434,7 @@ static size_t check_left_to_record(struct userdata *u, size_t n_bytes, pa_bool_t
|
|||
if (u->use_tsched) {
|
||||
pa_bool_t reset_not_before = TRUE;
|
||||
|
||||
if (left_to_record < u->watermark_inc_threshold)
|
||||
if (overrun || left_to_record < u->watermark_inc_threshold)
|
||||
increase_watermark(u);
|
||||
else if (left_to_record > u->watermark_dec_threshold) {
|
||||
reset_not_before = FALSE;
|
||||
|
|
@ -889,8 +889,7 @@ static int unsuspend(struct userdata *u) {
|
|||
pa_sample_spec ss;
|
||||
int err;
|
||||
pa_bool_t b, d;
|
||||
unsigned nfrags;
|
||||
snd_pcm_uframes_t period_size;
|
||||
snd_pcm_uframes_t period_size, buffer_size;
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(!u->pcm_handle);
|
||||
|
|
@ -898,7 +897,7 @@ static int unsuspend(struct userdata *u) {
|
|||
pa_log_info("Trying resume...");
|
||||
|
||||
if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_CAPTURE,
|
||||
/*SND_PCM_NONBLOCK|*/
|
||||
SND_PCM_NONBLOCK|
|
||||
SND_PCM_NO_AUTO_RESAMPLE|
|
||||
SND_PCM_NO_AUTO_CHANNELS|
|
||||
SND_PCM_NO_AUTO_FORMAT)) < 0) {
|
||||
|
|
@ -907,12 +906,12 @@ static int unsuspend(struct userdata *u) {
|
|||
}
|
||||
|
||||
ss = u->source->sample_spec;
|
||||
nfrags = u->nfragments;
|
||||
period_size = u->fragment_size / u->frame_size;
|
||||
buffer_size = u->hwbuf_size / u->frame_size;
|
||||
b = u->use_mmap;
|
||||
d = u->use_tsched;
|
||||
|
||||
if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, u->hwbuf_size / u->frame_size, &b, &d, TRUE)) < 0) {
|
||||
if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &period_size, &buffer_size, 0, &b, &d, TRUE)) < 0) {
|
||||
pa_log("Failed to set hardware parameters: %s", pa_alsa_strerror(err));
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -927,10 +926,11 @@ static int unsuspend(struct userdata *u) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
|
||||
pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)",
|
||||
(unsigned long) u->nfragments, (unsigned long) u->fragment_size,
|
||||
(unsigned long) nfrags, period_size * u->frame_size);
|
||||
if (period_size*u->frame_size != u->fragment_size ||
|
||||
buffer_size*u->frame_size != u->hwbuf_size) {
|
||||
pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu/%lu, New %lu/%lu)",
|
||||
(unsigned long) u->hwbuf_size, (unsigned long) u->fragment_size,
|
||||
(unsigned long) (buffer_size*u->fragment_size), (unsigned long) (period_size*u->frame_size));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -959,7 +959,7 @@ fail:
|
|||
u->pcm_handle = NULL;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return -PA_ERR_IO;
|
||||
}
|
||||
|
||||
static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
|
||||
|
|
@ -982,30 +982,34 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
|
|||
|
||||
switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
|
||||
|
||||
case PA_SOURCE_SUSPENDED:
|
||||
case PA_SOURCE_SUSPENDED: {
|
||||
int r;
|
||||
pa_assert(PA_SOURCE_IS_OPENED(u->source->thread_info.state));
|
||||
|
||||
if (suspend(u) < 0)
|
||||
return -1;
|
||||
if ((r = suspend(u)) < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PA_SOURCE_IDLE:
|
||||
case PA_SOURCE_RUNNING:
|
||||
case PA_SOURCE_RUNNING: {
|
||||
int r;
|
||||
|
||||
if (u->source->thread_info.state == PA_SOURCE_INIT) {
|
||||
if (build_pollfd(u) < 0)
|
||||
return -1;
|
||||
return -PA_ERR_IO;
|
||||
|
||||
snd_pcm_start(u->pcm_handle);
|
||||
}
|
||||
|
||||
if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
|
||||
if (unsuspend(u) < 0)
|
||||
return -1;
|
||||
if ((r = unsuspend(u)) < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PA_SOURCE_UNLINKED:
|
||||
case PA_SOURCE_INIT:
|
||||
|
|
@ -1033,7 +1037,7 @@ static int source_set_state_cb(pa_source *s, pa_source_state_t new_state) {
|
|||
reserve_done(u);
|
||||
else if (old_state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(new_state))
|
||||
if (reserve_init(u, u->device_name) < 0)
|
||||
return -1;
|
||||
return -PA_ERR_BUSY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1481,8 +1485,8 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
const char *dev_id = NULL;
|
||||
pa_sample_spec ss, requested_ss;
|
||||
pa_channel_map map;
|
||||
uint32_t nfrags, hwbuf_size, frag_size, tsched_size, tsched_watermark;
|
||||
snd_pcm_uframes_t period_frames, tsched_frames;
|
||||
uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark;
|
||||
snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
|
||||
size_t frame_size;
|
||||
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE;
|
||||
pa_source_new_data data;
|
||||
|
|
@ -1516,8 +1520,10 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
goto fail;
|
||||
}
|
||||
|
||||
hwbuf_size = frag_size * nfrags;
|
||||
buffer_size = nfrags * frag_size;
|
||||
|
||||
period_frames = frag_size/frame_size;
|
||||
buffer_frames = buffer_size/frame_size;
|
||||
tsched_frames = tsched_size/frame_size;
|
||||
|
||||
if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
|
||||
|
|
@ -1583,7 +1589,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_CAPTURE,
|
||||
&nfrags, &period_frames, tsched_frames,
|
||||
&period_frames, &buffer_frames, tsched_frames,
|
||||
&b, &d, mapping)))
|
||||
goto fail;
|
||||
|
||||
|
|
@ -1597,7 +1603,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_CAPTURE,
|
||||
&nfrags, &period_frames, tsched_frames,
|
||||
&period_frames, &buffer_frames, tsched_frames,
|
||||
&b, &d, profile_set, &mapping)))
|
||||
goto fail;
|
||||
|
||||
|
|
@ -1608,7 +1614,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_CAPTURE,
|
||||
&nfrags, &period_frames, tsched_frames,
|
||||
&period_frames, &buffer_frames, tsched_frames,
|
||||
&b, &d, FALSE)))
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -1634,11 +1640,6 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
u->use_tsched = use_tsched = FALSE;
|
||||
}
|
||||
|
||||
if (use_tsched && !pa_alsa_pcm_is_hw(u->pcm_handle)) {
|
||||
pa_log_info("Device is not a hardware device, disabling timer-based scheduling.");
|
||||
u->use_tsched = use_tsched = FALSE;
|
||||
}
|
||||
|
||||
if (u->use_mmap)
|
||||
pa_log_info("Successfully enabled mmap() mode.");
|
||||
|
||||
|
|
@ -1660,7 +1661,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
|
||||
pa_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle);
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
|
||||
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
|
||||
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (buffer_frames * frame_size));
|
||||
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
|
||||
|
||||
|
|
@ -1701,13 +1702,15 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
pa_source_set_rtpoll(u->source, u->rtpoll);
|
||||
|
||||
u->frame_size = frame_size;
|
||||
u->fragment_size = frag_size = (uint32_t) (period_frames * frame_size);
|
||||
u->nfragments = nfrags;
|
||||
u->hwbuf_size = u->fragment_size * nfrags;
|
||||
u->fragment_size = frag_size = (size_t) (period_frames * frame_size);
|
||||
u->hwbuf_size = buffer_size = (size_t) (buffer_frames * frame_size);
|
||||
pa_cvolume_mute(&u->hardware_volume, u->source->sample_spec.channels);
|
||||
|
||||
pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
|
||||
nfrags, (long unsigned) u->fragment_size,
|
||||
pa_log_info("Using %0.1f fragments of size %lu bytes (%0.2fms), buffer size is %lu bytes (%0.2fms)",
|
||||
(double) u->hwbuf_size / (double) u->fragment_size,
|
||||
(long unsigned) u->fragment_size,
|
||||
(double) pa_bytes_to_usec(u->fragment_size, &ss) / PA_USEC_PER_MSEC,
|
||||
(long unsigned) u->hwbuf_size,
|
||||
(double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
|
||||
|
||||
if (u->use_tsched) {
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_s
|
|||
int ret;
|
||||
|
||||
pa_assert(pcm_handle);
|
||||
pa_assert(hwparams);
|
||||
pa_assert(f);
|
||||
|
||||
if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
|
||||
|
|
@ -148,33 +149,71 @@ try_auto:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int set_period_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
|
||||
snd_pcm_uframes_t s;
|
||||
int d, ret;
|
||||
|
||||
pa_assert(pcm_handle);
|
||||
pa_assert(hwparams);
|
||||
|
||||
s = size;
|
||||
d = 0;
|
||||
if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
|
||||
s = size;
|
||||
d = -1;
|
||||
if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
|
||||
s = size;
|
||||
d = 1;
|
||||
if ((ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d)) < 0) {
|
||||
pa_log_info("snd_pcm_hw_params_set_period_size_near() failed: %s", pa_alsa_strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_buffer_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
|
||||
int ret;
|
||||
|
||||
pa_assert(pcm_handle);
|
||||
pa_assert(hwparams);
|
||||
|
||||
if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &size)) < 0) {
|
||||
pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the hardware parameters of the given ALSA device. Returns the
|
||||
* selected fragment settings in *period and *period_size */
|
||||
* selected fragment settings in *buffer_size and *period_size. If tsched mode can be enabled */
|
||||
int pa_alsa_set_hw_params(
|
||||
snd_pcm_t *pcm_handle,
|
||||
pa_sample_spec *ss,
|
||||
uint32_t *periods,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
snd_pcm_uframes_t *buffer_size,
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap,
|
||||
pa_bool_t *use_tsched,
|
||||
pa_bool_t require_exact_channel_number) {
|
||||
|
||||
int ret = -1;
|
||||
snd_pcm_hw_params_t *hwparams, *hwparams_copy;
|
||||
int dir;
|
||||
snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
|
||||
unsigned int _periods = periods ? *periods : 0;
|
||||
unsigned int r = ss->rate;
|
||||
unsigned int c = ss->channels;
|
||||
pa_sample_format_t f = ss->format;
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
|
||||
pa_bool_t _use_mmap = use_mmap && *use_mmap;
|
||||
pa_bool_t _use_tsched = use_tsched && *use_tsched;
|
||||
int dir;
|
||||
pa_sample_spec _ss = *ss;
|
||||
|
||||
pa_assert(pcm_handle);
|
||||
pa_assert(ss);
|
||||
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
snd_pcm_hw_params_alloca(&hwparams_copy);
|
||||
|
||||
if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
|
||||
pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
|
||||
|
|
@ -208,114 +247,143 @@ int pa_alsa_set_hw_params(
|
|||
if (!_use_mmap)
|
||||
_use_tsched = FALSE;
|
||||
|
||||
if ((ret = set_format(pcm_handle, hwparams, &f)) < 0)
|
||||
if (!pa_alsa_pcm_is_hw(pcm_handle))
|
||||
_use_tsched = FALSE;
|
||||
|
||||
if ((ret = set_format(pcm_handle, hwparams, &_ss.format)) < 0)
|
||||
goto finish;
|
||||
|
||||
if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0) {
|
||||
if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &_ss.rate, NULL)) < 0) {
|
||||
pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (require_exact_channel_number) {
|
||||
if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, c)) < 0) {
|
||||
pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", c, pa_alsa_strerror(ret));
|
||||
if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, _ss.channels)) < 0) {
|
||||
pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
|
||||
goto finish;
|
||||
}
|
||||
} else {
|
||||
unsigned int c = _ss.channels;
|
||||
|
||||
if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) {
|
||||
pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", c, pa_alsa_strerror(ret));
|
||||
pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
_ss.channels = c;
|
||||
}
|
||||
|
||||
if ((ret = snd_pcm_hw_params_set_periods_integer(pcm_handle, hwparams)) < 0) {
|
||||
pa_log_debug("snd_pcm_hw_params_set_periods_integer() failed: %s", pa_alsa_strerror(ret));
|
||||
goto finish;
|
||||
if (_use_tsched && tsched_size > 0) {
|
||||
_buffer_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * _ss.rate) / ss->rate);
|
||||
_period_size = _buffer_size;
|
||||
} else {
|
||||
_period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * _ss.rate) / ss->rate);
|
||||
_buffer_size = (snd_pcm_uframes_t) (((uint64_t) _buffer_size * _ss.rate) / ss->rate);
|
||||
}
|
||||
|
||||
if (_period_size > 0 && tsched_size > 0 && _periods > 0) {
|
||||
snd_pcm_uframes_t buffer_size;
|
||||
unsigned int p;
|
||||
if (_buffer_size > 0 || _period_size > 0) {
|
||||
snd_pcm_uframes_t max_frames = 0;
|
||||
|
||||
/* Adjust the buffer sizes, if we didn't get the rate we were asking for */
|
||||
_period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * r) / ss->rate);
|
||||
tsched_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * r) / ss->rate);
|
||||
|
||||
if (_use_tsched) {
|
||||
buffer_size = 0;
|
||||
|
||||
if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &buffer_size)) < 0)
|
||||
pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
|
||||
else
|
||||
pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size * 1000 / r);
|
||||
|
||||
_period_size = tsched_size;
|
||||
_periods = 1;
|
||||
}
|
||||
if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &max_frames)) < 0)
|
||||
pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
|
||||
else
|
||||
pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) (max_frames * PA_MSEC_PER_SEC / _ss.rate));
|
||||
|
||||
/* Some ALSA drivers really don't like if we set the buffer
|
||||
* size first and the number of periods second. (which would
|
||||
* make a lot more sense to me) So, follow this rule and
|
||||
* adjust the periods first and the buffer size second */
|
||||
* make a lot more sense to me) So, try a few combinations
|
||||
* before we give up. */
|
||||
|
||||
/* First we pass 0 as direction to get exactly what we
|
||||
* asked for. That this is necessary is presumably a bug
|
||||
* in ALSA. All in all this is mostly a hint to ALSA, so
|
||||
* we don't care if this fails. */
|
||||
if (_buffer_size > 0 && _period_size > 0) {
|
||||
snd_pcm_hw_params_copy(hwparams_copy, hwparams);
|
||||
|
||||
p = _periods;
|
||||
dir = 0;
|
||||
if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &p, &dir) < 0) {
|
||||
p = _periods;
|
||||
dir = 1;
|
||||
if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &p, &dir) < 0) {
|
||||
p = _periods;
|
||||
dir = -1;
|
||||
if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &p, &dir)) < 0)
|
||||
pa_log_info("snd_pcm_hw_params_set_periods_near() failed: %s", pa_alsa_strerror(ret));
|
||||
/* First try: set buffer size first, followed by period size */
|
||||
if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
|
||||
set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
|
||||
snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
|
||||
pa_log_debug("Set buffer size first, period size second.");
|
||||
goto success;
|
||||
}
|
||||
|
||||
/* Second try: set period size first, followed by buffer size */
|
||||
if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
|
||||
set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
|
||||
snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
|
||||
pa_log_debug("Set period size first, buffer size second.");
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now set the buffer size */
|
||||
buffer_size = _periods * _period_size;
|
||||
if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0)
|
||||
pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
|
||||
if (_buffer_size > 0) {
|
||||
snd_pcm_hw_params_copy(hwparams_copy, hwparams);
|
||||
|
||||
/* Third try: set only buffer size */
|
||||
if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
|
||||
snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
|
||||
pa_log_debug("Set only buffer size second.");
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
|
||||
if (_period_size > 0) {
|
||||
snd_pcm_hw_params_copy(hwparams_copy, hwparams);
|
||||
|
||||
/* Fourth try: set only period size */
|
||||
if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
|
||||
snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
|
||||
pa_log_debug("Set only period size second.");
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0)
|
||||
pa_log_debug("Set neither period nor buffer size.");
|
||||
|
||||
/* Last chance, set nothing */
|
||||
if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
|
||||
pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (ss->rate != r)
|
||||
pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, r);
|
||||
success:
|
||||
|
||||
if (ss->channels != c)
|
||||
pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, c);
|
||||
if (ss->rate != _ss.rate)
|
||||
pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, _ss.rate);
|
||||
|
||||
if (ss->format != f)
|
||||
pa_log_info("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));
|
||||
if (ss->channels != _ss.channels)
|
||||
pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, _ss.channels);
|
||||
|
||||
if (ss->format != _ss.format)
|
||||
pa_log_info("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(_ss.format));
|
||||
|
||||
if ((ret = snd_pcm_prepare(pcm_handle)) < 0) {
|
||||
pa_log_info("snd_pcm_prepare() failed: %s", pa_alsa_strerror(ret));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if ((ret = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) {
|
||||
pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
|
||||
(ret = snd_pcm_hw_params_get_periods(hwparams, &_periods, &dir)) < 0) {
|
||||
pa_log_info("snd_pcm_hw_params_get_period{s|_size}() failed: %s", pa_alsa_strerror(ret));
|
||||
(ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
|
||||
pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret));
|
||||
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 = (uint8_t) c;
|
||||
ss->format = f;
|
||||
if (_ss.rate < ss->rate*.95 || _ss.rate > ss->rate*1.05)
|
||||
ss->rate = _ss.rate;
|
||||
ss->channels = _ss.channels;
|
||||
ss->format = _ss.format;
|
||||
|
||||
pa_assert(_periods > 0);
|
||||
pa_assert(_period_size > 0);
|
||||
pa_assert(_buffer_size > 0);
|
||||
|
||||
if (periods)
|
||||
*periods = _periods;
|
||||
if (buffer_size)
|
||||
*buffer_size = _buffer_size;
|
||||
|
||||
if (period_size)
|
||||
*period_size = _period_size;
|
||||
|
|
@ -393,8 +461,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|||
pa_sample_spec *ss,
|
||||
pa_channel_map* map,
|
||||
int mode,
|
||||
uint32_t *nfrags,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
snd_pcm_uframes_t *buffer_size,
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap,
|
||||
pa_bool_t *use_tsched,
|
||||
|
|
@ -410,8 +478,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|||
pa_assert(dev);
|
||||
pa_assert(ss);
|
||||
pa_assert(map);
|
||||
pa_assert(nfrags);
|
||||
pa_assert(period_size);
|
||||
pa_assert(ps);
|
||||
|
||||
/* First we try to find a device string with a superset of the
|
||||
|
|
@ -433,8 +499,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|||
ss,
|
||||
map,
|
||||
mode,
|
||||
nfrags,
|
||||
period_size,
|
||||
buffer_size,
|
||||
tsched_size,
|
||||
use_mmap,
|
||||
use_tsched,
|
||||
|
|
@ -460,8 +526,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|||
ss,
|
||||
map,
|
||||
mode,
|
||||
nfrags,
|
||||
period_size,
|
||||
buffer_size,
|
||||
tsched_size,
|
||||
use_mmap,
|
||||
use_tsched,
|
||||
|
|
@ -478,7 +544,18 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|||
/* 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, tsched_size, use_mmap, use_tsched, FALSE);
|
||||
pcm_handle = pa_alsa_open_by_device_string(
|
||||
d,
|
||||
dev,
|
||||
ss,
|
||||
map,
|
||||
mode,
|
||||
period_size,
|
||||
buffer_size,
|
||||
tsched_size,
|
||||
use_mmap,
|
||||
use_tsched,
|
||||
FALSE);
|
||||
pa_xfree(d);
|
||||
|
||||
if (pcm_handle && mapping)
|
||||
|
|
@ -493,8 +570,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
|
|||
pa_sample_spec *ss,
|
||||
pa_channel_map* map,
|
||||
int mode,
|
||||
uint32_t *nfrags,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
snd_pcm_uframes_t *buffer_size,
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap,
|
||||
pa_bool_t *use_tsched,
|
||||
|
|
@ -508,8 +585,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
|
|||
pa_assert(dev);
|
||||
pa_assert(ss);
|
||||
pa_assert(map);
|
||||
pa_assert(nfrags);
|
||||
pa_assert(period_size);
|
||||
pa_assert(m);
|
||||
|
||||
try_ss.channels = m->channel_map.channels;
|
||||
|
|
@ -524,8 +599,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
|
|||
&try_ss,
|
||||
&try_map,
|
||||
mode,
|
||||
nfrags,
|
||||
period_size,
|
||||
buffer_size,
|
||||
tsched_size,
|
||||
use_mmap,
|
||||
use_tsched,
|
||||
|
|
@ -547,8 +622,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
|
|||
pa_sample_spec *ss,
|
||||
pa_channel_map* map,
|
||||
int mode,
|
||||
uint32_t *nfrags,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
snd_pcm_uframes_t *buffer_size,
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap,
|
||||
pa_bool_t *use_tsched,
|
||||
|
|
@ -579,7 +654,15 @@ snd_pcm_t *pa_alsa_open_by_device_string(
|
|||
|
||||
pa_log_debug("Managed to open %s", d);
|
||||
|
||||
if ((err = pa_alsa_set_hw_params(pcm_handle, ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, require_exact_channel_number)) < 0) {
|
||||
if ((err = pa_alsa_set_hw_params(
|
||||
pcm_handle,
|
||||
ss,
|
||||
period_size,
|
||||
buffer_size,
|
||||
tsched_size,
|
||||
use_mmap,
|
||||
use_tsched,
|
||||
require_exact_channel_number)) < 0) {
|
||||
|
||||
if (!reformat) {
|
||||
reformat = TRUE;
|
||||
|
|
@ -632,8 +715,8 @@ snd_pcm_t *pa_alsa_open_by_template(
|
|||
pa_sample_spec *ss,
|
||||
pa_channel_map* map,
|
||||
int mode,
|
||||
uint32_t *nfrags,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
snd_pcm_uframes_t *buffer_size,
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap,
|
||||
pa_bool_t *use_tsched,
|
||||
|
|
@ -653,8 +736,8 @@ snd_pcm_t *pa_alsa_open_by_template(
|
|||
ss,
|
||||
map,
|
||||
mode,
|
||||
nfrags,
|
||||
period_size,
|
||||
buffer_size,
|
||||
tsched_size,
|
||||
use_mmap,
|
||||
use_tsched,
|
||||
|
|
@ -900,7 +983,7 @@ void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
|
|||
snd_ctl_card_info_alloca(&info);
|
||||
|
||||
if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
|
||||
pa_log_warn("Error opening low-level control device '%s'", name);
|
||||
pa_log_warn("Error opening low-level control device '%s': %s", name, snd_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@
|
|||
int pa_alsa_set_hw_params(
|
||||
snd_pcm_t *pcm_handle,
|
||||
pa_sample_spec *ss, /* modified at return */
|
||||
uint32_t *periods, /* modified at return */
|
||||
snd_pcm_uframes_t *period_size, /* modified at return */
|
||||
snd_pcm_uframes_t *buffer_size, /* modified at return */
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap, /* modified at return */
|
||||
pa_bool_t *use_tsched, /* modified at return */
|
||||
|
|
@ -60,8 +60,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|||
pa_sample_spec *ss, /* modified at return */
|
||||
pa_channel_map* map, /* modified at return */
|
||||
int mode,
|
||||
uint32_t *nfrags, /* modified at return */
|
||||
snd_pcm_uframes_t *period_size, /* modified at return */
|
||||
snd_pcm_uframes_t *buffer_size, /* modified at return */
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap, /* modified at return */
|
||||
pa_bool_t *use_tsched, /* modified at return */
|
||||
|
|
@ -75,8 +75,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
|
|||
pa_sample_spec *ss, /* modified at return */
|
||||
pa_channel_map* map, /* modified at return */
|
||||
int mode,
|
||||
uint32_t *nfrags, /* modified at return */
|
||||
snd_pcm_uframes_t *period_size, /* modified at return */
|
||||
snd_pcm_uframes_t *buffer_size, /* modified at return */
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap, /* modified at return */
|
||||
pa_bool_t *use_tsched, /* modified at return */
|
||||
|
|
@ -89,8 +89,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
|
|||
pa_sample_spec *ss, /* modified at return */
|
||||
pa_channel_map* map, /* modified at return */
|
||||
int mode,
|
||||
uint32_t *nfrags, /* modified at return */
|
||||
snd_pcm_uframes_t *period_size, /* modified at return */
|
||||
snd_pcm_uframes_t *buffer_size, /* modified at return */
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap, /* modified at return */
|
||||
pa_bool_t *use_tsched, /* modified at return */
|
||||
|
|
@ -104,8 +104,8 @@ snd_pcm_t *pa_alsa_open_by_template(
|
|||
pa_sample_spec *ss, /* modified at return */
|
||||
pa_channel_map* map, /* modified at return */
|
||||
int mode,
|
||||
uint32_t *nfrags, /* modified at return */
|
||||
snd_pcm_uframes_t *period_size, /* modified at return */
|
||||
snd_pcm_uframes_t *buffer_size, /* modified at return */
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap, /* modified at return */
|
||||
pa_bool_t *use_tsched, /* modified at return */
|
||||
|
|
|
|||
|
|
@ -78,6 +78,10 @@ priority = 19
|
|||
name = input-microphone
|
||||
priority = 19
|
||||
|
||||
[Option Input Source:Internal Mic]
|
||||
name = input-microphone
|
||||
priority = 19
|
||||
|
||||
[Option Input Source:Line]
|
||||
name = input-linein
|
||||
priority = 18
|
||||
|
|
@ -90,6 +94,10 @@ priority = 18
|
|||
name = input-linein
|
||||
priority = 18
|
||||
|
||||
[Option Input Source:Docking-Station]
|
||||
name = input-docking
|
||||
priority = 17
|
||||
|
||||
;;; ' Capture Source'
|
||||
|
||||
[Element Capture Source]
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ volume = off
|
|||
switch = off
|
||||
volume = off
|
||||
|
||||
[Element Sourround]
|
||||
[Element Surround]
|
||||
switch = off
|
||||
volume = off
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ volume = off
|
|||
switch = off
|
||||
volume = off
|
||||
|
||||
[Element Sourround]
|
||||
[Element Surround]
|
||||
switch = off
|
||||
volume = off
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ volume = off
|
|||
switch = off
|
||||
volume = off
|
||||
|
||||
[Element Sourround]
|
||||
[Element Surround]
|
||||
switch = off
|
||||
volume = off
|
||||
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ int pa__init(pa_module *m) {
|
|||
if (!u->profile_set)
|
||||
goto fail;
|
||||
|
||||
pa_alsa_profile_set_probe(u->profile_set, u->device_id, &m->core->default_sample_spec);
|
||||
pa_alsa_profile_set_probe(u->profile_set, u->device_id, &m->core->default_sample_spec, m->core->default_n_fragments, m->core->default_fragment_size_msec);
|
||||
|
||||
pa_card_new_data_init(&data);
|
||||
data.driver = __FILE__;
|
||||
|
|
|
|||
|
|
@ -221,9 +221,7 @@ static int service_recv(struct userdata *u, bt_audio_msg_header_t *msg, size_t r
|
|||
pa_assert(u);
|
||||
pa_assert(u->service_fd >= 0);
|
||||
pa_assert(msg);
|
||||
|
||||
if (room <= 0)
|
||||
room = BT_SUGGESTED_BUFFER_SIZE;
|
||||
pa_assert(room >= sizeof(*msg));
|
||||
|
||||
pa_log_debug("Trying to receive message from audio service...");
|
||||
|
||||
|
|
@ -236,6 +234,11 @@ static int service_recv(struct userdata *u, bt_audio_msg_header_t *msg, size_t r
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (msg->length > room) {
|
||||
pa_log_error("Not enough room.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Secondly, read the payload */
|
||||
if (msg->length > sizeof(*msg)) {
|
||||
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ int pa__init(pa_module*m) {
|
|||
|
||||
if ((u->fd = pa_start_child_for_read(
|
||||
#if defined(__linux__) && !defined(__OPTIMIZE__)
|
||||
pa_run_from_build_tree() ? PA_BUILDDIR "/.libs/gconf-helper" :
|
||||
pa_run_from_build_tree() ? PA_BUILDDIR "/gconf-helper" :
|
||||
#endif
|
||||
PA_GCONF_HELPER, NULL, &u->pid)) < 0)
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ int pa_hal_get_info(pa_core *core, pa_proplist *p, int card) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
if (!(udis = libhal_find_device_by_capability(hal, "sound", &n, &error)) < 0) {
|
||||
if (!(udis = libhal_find_device_by_capability(hal, "sound", &n, &error))) {
|
||||
pa_log_error("Couldn't find devices: %s: %s", error.name, error.message);
|
||||
goto finish;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#endif
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/core.h>
|
||||
#include <pulsecore/sink-input.h>
|
||||
|
|
@ -35,7 +36,7 @@
|
|||
#include "module-always-sink-symdef.h"
|
||||
|
||||
PA_MODULE_AUTHOR("Colin Guthrie");
|
||||
PA_MODULE_DESCRIPTION("Always keeps at least one sink loaded even if it's a null one");
|
||||
PA_MODULE_DESCRIPTION(_("Always keeps at least one sink loaded even if it's a null one"));
|
||||
PA_MODULE_VERSION(PACKAGE_VERSION);
|
||||
PA_MODULE_LOAD_ONCE(TRUE);
|
||||
PA_MODULE_USAGE(
|
||||
|
|
@ -78,7 +79,8 @@ static void load_null_sink_if_needed(pa_core *c, pa_sink *sink, struct userdata*
|
|||
|
||||
u->ignore = TRUE;
|
||||
|
||||
t = pa_sprintf_malloc("sink_name=%s", u->sink_name);
|
||||
t = pa_sprintf_malloc("sink_name=%s sink_properties='device.description=\"%s\"'", u->sink_name,
|
||||
_("Dummy Output"));
|
||||
m = pa_module_load(c, "module-null-sink", t);
|
||||
u->null_module = m ? m->index : PA_INVALID_INDEX;
|
||||
pa_xfree(t);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <pulsecore/module.h>
|
||||
#include <pulsecore/iochannel.h>
|
||||
|
|
@ -33,6 +35,8 @@
|
|||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
|
||||
#include "module-cli-symdef.h"
|
||||
|
||||
|
|
@ -69,6 +73,7 @@ int pa__init(pa_module*m) {
|
|||
pa_iochannel *io;
|
||||
pa_modargs *ma;
|
||||
pa_bool_t exit_on_eof = FALSE;
|
||||
int fd;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
|
|
@ -88,15 +93,28 @@ int pa__init(pa_module*m) {
|
|||
}
|
||||
|
||||
if (pa_stdio_acquire() < 0) {
|
||||
pa_log("STDIN/STDUSE already in use.");
|
||||
pa_log("STDIN/STDOUT already in use.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
io = pa_iochannel_new(m->core->mainloop, STDIN_FILENO, STDOUT_FILENO);
|
||||
pa_iochannel_set_noclose(io, 1);
|
||||
/* We try to open the controlling tty anew here. This has the
|
||||
* benefit of giving us a new fd that doesn't share the O_NDELAY
|
||||
* flag with fds 0, 1, or 2. Since pa_iochannel_xxx needs O_NDELAY
|
||||
* on its fd using those fds directly could set O_NDELAY which
|
||||
* fprintf() doesn't really like, resulting in truncated output
|
||||
* of log messages, particularly because if stdout and stderr are
|
||||
* dup'ed they share the same O_NDELAY, too. */
|
||||
|
||||
if ((fd = open("/dev/tty", O_RDWR|O_CLOEXEC|O_NONBLOCK)) >= 0) {
|
||||
io = pa_iochannel_new(m->core->mainloop, fd, fd);
|
||||
pa_log_debug("Managed to open /dev/tty.");
|
||||
} else {
|
||||
io = pa_iochannel_new(m->core->mainloop, STDIN_FILENO, STDOUT_FILENO);
|
||||
pa_iochannel_set_noclose(io, TRUE);
|
||||
pa_log_debug("Failed to open /dev/tty, using stdin/stdout fds instead.");
|
||||
}
|
||||
|
||||
m->userdata = pa_cli_new(m->core, io, m);
|
||||
|
||||
pa_cli_set_eof_callback(m->userdata, exit_on_eof ? eof_and_exit_cb : eof_and_unload_cb, m);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
|
|
@ -114,7 +132,7 @@ fail:
|
|||
void pa__done(pa_module*m) {
|
||||
pa_assert(m);
|
||||
|
||||
if (m->core->running_as_daemon == 0) {
|
||||
if (m->userdata) {
|
||||
pa_cli_free(m->userdata);
|
||||
pa_stdio_release();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -435,9 +435,7 @@ static int hal_device_add_all(struct userdata *u) {
|
|||
int i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
struct device *d;
|
||||
|
||||
if ((d = hal_device_add(u, udis[i]))) {
|
||||
if (hal_device_add(u, udis[i])) {
|
||||
count++;
|
||||
pa_log_debug("Loaded device %s", udis[i]);
|
||||
} else
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ struct userdata {
|
|||
LADSPA_Data control_out;
|
||||
|
||||
pa_memblockq *memblockq;
|
||||
|
||||
pa_bool_t auto_desc;
|
||||
};
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
|
|
@ -423,6 +425,19 @@ static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
|
|||
pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags);
|
||||
} else
|
||||
pa_sink_set_asyncmsgq(u->sink, NULL);
|
||||
|
||||
if (u->auto_desc && dest) {
|
||||
const char *z;
|
||||
pa_proplist *pl;
|
||||
|
||||
pl = pa_proplist_new();
|
||||
z = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
|
||||
pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "LADSPA Plugin %s on %s",
|
||||
pa_proplist_gets(u->sink->proplist, "device.ladspa.name"), z ? z : dest->name);
|
||||
|
||||
pa_sink_update_proplist(u->sink, PA_UPDATE_REPLACE, pl);
|
||||
pa_proplist_free(pl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
|
|
@ -451,7 +466,6 @@ int pa__init(pa_module*m) {
|
|||
pa_channel_map map;
|
||||
pa_modargs *ma;
|
||||
char *t;
|
||||
const char *z;
|
||||
pa_sink *master;
|
||||
pa_sink_input_new_data sink_input_data;
|
||||
pa_sink_new_data sink_data;
|
||||
|
|
@ -765,8 +779,6 @@ int pa__init(pa_module*m) {
|
|||
sink_data.name = pa_sprintf_malloc("%s.ladspa", master->name);
|
||||
pa_sink_new_data_set_sample_spec(&sink_data, &ss);
|
||||
pa_sink_new_data_set_channel_map(&sink_data, &map);
|
||||
z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
|
||||
pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "LADSPA Plugin %s on %s", d->Name, z ? z : master->name);
|
||||
pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
|
||||
pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
|
||||
pa_proplist_sets(sink_data.proplist, "device.ladspa.module", plugin);
|
||||
|
|
@ -782,6 +794,13 @@ int pa__init(pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
|
||||
const char *z;
|
||||
|
||||
z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
|
||||
pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "LADSPA Plugin %s on %s", d->Name, z ? z : master->name);
|
||||
}
|
||||
|
||||
u->sink = pa_sink_new(m->core, &sink_data,
|
||||
PA_SINK_HW_MUTE_CTRL|PA_SINK_HW_VOLUME_CTRL|PA_SINK_DECIBEL_VOLUME|
|
||||
(master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY)));
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include <pulse/rtclock.h>
|
||||
#include <pulse/timeval.h>
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/sink.h>
|
||||
|
|
@ -51,7 +52,7 @@
|
|||
#include "module-null-sink-symdef.h"
|
||||
|
||||
PA_MODULE_AUTHOR("Lennart Poettering");
|
||||
PA_MODULE_DESCRIPTION("Clocked NULL sink");
|
||||
PA_MODULE_DESCRIPTION(_("Clocked NULL sink"));
|
||||
PA_MODULE_VERSION(PACKAGE_VERSION);
|
||||
PA_MODULE_LOAD_ONCE(FALSE);
|
||||
PA_MODULE_USAGE(
|
||||
|
|
@ -287,7 +288,7 @@ int pa__init(pa_module*m) {
|
|||
pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
|
||||
pa_sink_new_data_set_sample_spec(&data, &ss);
|
||||
pa_sink_new_data_set_channel_map(&data, &map);
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "Null Output"));
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", _("Null Output")));
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract");
|
||||
|
||||
if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
|
||||
|
|
|
|||
|
|
@ -57,35 +57,69 @@ struct userdata {
|
|||
pa_hook_slot *sink_input_fixate_hook_slot;
|
||||
};
|
||||
|
||||
static int parse_pos(const char *pos, double *f) {
|
||||
|
||||
if (pa_atod(pos, f) < 0) {
|
||||
pa_log_warn("Failed to parse hpos/vpos property '%s'.", pos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*f < 0.0 || *f > 1.0) {
|
||||
pa_log_debug("Property hpos/vpos out of range %0.2f", *f);
|
||||
|
||||
*f = PA_CLAMP(*f, 0.0, 1.0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *core, pa_sink_input_new_data *data, struct userdata *u) {
|
||||
const char *hpos;
|
||||
const char *hpos, *vpos, *role;
|
||||
double f;
|
||||
char t[PA_CVOLUME_SNPRINT_MAX];
|
||||
pa_cvolume v;
|
||||
|
||||
pa_assert(data);
|
||||
|
||||
if (!(role = pa_proplist_gets(data->proplist, PA_PROP_MEDIA_ROLE)))
|
||||
return PA_HOOK_OK;
|
||||
|
||||
if (!pa_streq(role, "event"))
|
||||
return PA_HOOK_OK;
|
||||
|
||||
if (!(hpos = pa_proplist_gets(data->proplist, PA_PROP_EVENT_MOUSE_HPOS)))
|
||||
hpos = pa_proplist_gets(data->proplist, PA_PROP_WINDOW_HPOS);
|
||||
|
||||
if (!(vpos = pa_proplist_gets(data->proplist, PA_PROP_EVENT_MOUSE_VPOS)))
|
||||
vpos = pa_proplist_gets(data->proplist, PA_PROP_WINDOW_VPOS);
|
||||
|
||||
if (!hpos && !vpos)
|
||||
return PA_HOOK_OK;
|
||||
|
||||
if (pa_atod(hpos, &f) < 0) {
|
||||
pa_log_warn("Failed to parse "PA_PROP_EVENT_MOUSE_HPOS" property '%s'.", hpos);
|
||||
return PA_HOOK_OK;
|
||||
pa_cvolume_reset(&v, data->sink->sample_spec.channels);
|
||||
|
||||
if (hpos) {
|
||||
if (parse_pos(hpos, &f) < 0)
|
||||
return PA_HOOK_OK;
|
||||
|
||||
if (pa_channel_map_can_balance(&data->sink->channel_map)) {
|
||||
pa_log_debug("Positioning event sound '%s' horizontally at %0.2f.", pa_strnull(pa_proplist_gets(data->proplist, PA_PROP_EVENT_ID)), f);
|
||||
pa_cvolume_set_balance(&v, &data->sink->channel_map, f*2.0-1.0);
|
||||
}
|
||||
}
|
||||
|
||||
if (f < 0.0 || f > 1.0) {
|
||||
pa_log_warn("Property "PA_PROP_EVENT_MOUSE_HPOS" out of range %0.2f", f);
|
||||
return PA_HOOK_OK;
|
||||
if (vpos) {
|
||||
if (parse_pos(vpos, &f) < 0)
|
||||
return PA_HOOK_OK;
|
||||
|
||||
if (pa_channel_map_can_fade(&data->sink->channel_map)) {
|
||||
pa_log_debug("Positioning event sound '%s' vertically at %0.2f.", pa_strnull(pa_proplist_gets(data->proplist, PA_PROP_EVENT_ID)), f);
|
||||
pa_cvolume_set_fade(&v, &data->sink->channel_map, f*2.0-1.0);
|
||||
}
|
||||
}
|
||||
|
||||
pa_log_debug("Positioning event sound '%s' at %0.2f.", pa_strnull(pa_proplist_gets(data->proplist, PA_PROP_EVENT_ID)), f);
|
||||
|
||||
pa_cvolume_reset(&v, data->sample_spec.channels);
|
||||
pa_cvolume_set_balance(&v, &data->channel_map, f*2.0-1.0);
|
||||
|
||||
pa_log_debug("Final volume factor %s.", pa_cvolume_snprint(t, sizeof(t), &v));
|
||||
|
||||
pa_sink_input_new_data_apply_volume_factor(data, &v);
|
||||
pa_sink_input_new_data_apply_volume_factor_sink(data, &v);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ struct userdata {
|
|||
|
||||
pa_sink *sink;
|
||||
pa_sink_input *sink_input;
|
||||
|
||||
pa_bool_t auto_desc;
|
||||
};
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
|
|
@ -307,6 +309,18 @@ static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
|
|||
pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags);
|
||||
} else
|
||||
pa_sink_set_asyncmsgq(u->sink, NULL);
|
||||
|
||||
if (u->auto_desc && dest) {
|
||||
const char *k;
|
||||
pa_proplist *pl;
|
||||
|
||||
pl = pa_proplist_new();
|
||||
k = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
|
||||
pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : dest->name);
|
||||
|
||||
pa_sink_update_proplist(u->sink, PA_UPDATE_REPLACE, pl);
|
||||
pa_proplist_free(pl);
|
||||
}
|
||||
}
|
||||
|
||||
int pa__init(pa_module*m) {
|
||||
|
|
@ -314,7 +328,6 @@ int pa__init(pa_module*m) {
|
|||
pa_sample_spec ss;
|
||||
pa_channel_map sink_map, stream_map;
|
||||
pa_modargs *ma;
|
||||
const char *k;
|
||||
pa_sink *master;
|
||||
pa_sink_input_new_data sink_input_data;
|
||||
pa_sink_new_data sink_data;
|
||||
|
|
@ -370,8 +383,6 @@ int pa__init(pa_module*m) {
|
|||
sink_data.name = pa_sprintf_malloc("%s.remapped", master->name);
|
||||
pa_sink_new_data_set_sample_spec(&sink_data, &ss);
|
||||
pa_sink_new_data_set_channel_map(&sink_data, &sink_map);
|
||||
k = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
|
||||
pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : master->name);
|
||||
pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
|
||||
pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
|
||||
|
||||
|
|
@ -381,6 +392,13 @@ int pa__init(pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
|
||||
const char *k;
|
||||
|
||||
k = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
|
||||
pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : master->name);
|
||||
}
|
||||
|
||||
u->sink = pa_sink_new(m->core, &sink_data, master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY));
|
||||
pa_sink_new_data_done(&sink_data);
|
||||
|
||||
|
|
|
|||
|
|
@ -1476,7 +1476,7 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source,
|
|||
if (!so->source)
|
||||
continue;
|
||||
|
||||
/* It might happen that a stream and a sink are set up at the
|
||||
/* It might happen that a stream and a source are set up at the
|
||||
same time, in which case we want to make sure we don't
|
||||
interfere with that */
|
||||
if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(so)))
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ static void command_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
|
|||
|
||||
static void command_stream_buffer_attr_changed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
uint32_t channel, maxlength, tlength, fragsize, prebuf, minreq;
|
||||
uint32_t channel, maxlength, tlength = 0, fragsize, prebuf, minreq;
|
||||
pa_usec_t usec;
|
||||
|
||||
pa_assert(pd);
|
||||
|
|
@ -1069,6 +1069,33 @@ static void sink_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_t
|
|||
}
|
||||
}
|
||||
|
||||
if (u->version >= 16) {
|
||||
uint32_t n_ports;
|
||||
const char *s;
|
||||
|
||||
if (pa_tagstruct_getu32(t, &n_ports)) {
|
||||
pa_log("Parse failure");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (uint32_t j = 0; j < n_ports; j++) {
|
||||
uint32_t priority;
|
||||
|
||||
if (pa_tagstruct_gets(t, &s) < 0 || /* name */
|
||||
pa_tagstruct_gets(t, &s) < 0 || /* description */
|
||||
pa_tagstruct_getu32(t, &priority) < 0) {
|
||||
|
||||
pa_log("Parse failure");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (pa_tagstruct_gets(t, &s) < 0) { /* active port */
|
||||
pa_log("Parse failure");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pa_tagstruct_eof(t)) {
|
||||
pa_log("Packet too long");
|
||||
goto fail;
|
||||
|
|
@ -1097,7 +1124,7 @@ static void sink_input_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag
|
|||
uint32_t idx, owner_module, client, sink;
|
||||
pa_usec_t buffer_usec, sink_usec;
|
||||
const char *name, *driver, *resample_method;
|
||||
pa_bool_t mute;
|
||||
pa_bool_t mute = FALSE;
|
||||
pa_sample_spec sample_spec;
|
||||
pa_channel_map channel_map;
|
||||
pa_cvolume volume;
|
||||
|
|
@ -1245,6 +1272,33 @@ static void source_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
|
|||
}
|
||||
}
|
||||
|
||||
if (u->version >= 16) {
|
||||
uint32_t n_ports;
|
||||
const char *s;
|
||||
|
||||
if (pa_tagstruct_getu32(t, &n_ports)) {
|
||||
pa_log("Parse failure");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (uint32_t j = 0; j < n_ports; j++) {
|
||||
uint32_t priority;
|
||||
|
||||
if (pa_tagstruct_gets(t, &s) < 0 || /* name */
|
||||
pa_tagstruct_gets(t, &s) < 0 || /* description */
|
||||
pa_tagstruct_getu32(t, &priority) < 0) {
|
||||
|
||||
pa_log("Parse failure");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (pa_tagstruct_gets(t, &s) < 0) { /* active port */
|
||||
pa_log("Parse failure");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pa_tagstruct_eof(t)) {
|
||||
pa_log("Packet too long");
|
||||
goto fail;
|
||||
|
|
@ -1345,12 +1399,11 @@ static void command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32
|
|||
/* Called from main context */
|
||||
static void start_subscribe(struct userdata *u) {
|
||||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
pa_assert(u);
|
||||
|
||||
t = pa_tagstruct_new(NULL, 0);
|
||||
pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
|
||||
pa_tagstruct_putu32(t, tag = u->ctag++);
|
||||
pa_tagstruct_putu32(t, u->ctag++);
|
||||
pa_tagstruct_putu32(t, PA_SUBSCRIPTION_MASK_SERVER|
|
||||
#ifdef TUNNEL_SINK
|
||||
PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SINK
|
||||
|
|
@ -1526,7 +1579,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
|
|||
|
||||
reply = pa_tagstruct_new(NULL, 0);
|
||||
pa_tagstruct_putu32(reply, PA_COMMAND_SET_CLIENT_NAME);
|
||||
pa_tagstruct_putu32(reply, tag = u->ctag++);
|
||||
pa_tagstruct_putu32(reply, u->ctag++);
|
||||
|
||||
if (u->version >= 13) {
|
||||
pa_proplist *pl;
|
||||
|
|
@ -1753,7 +1806,6 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata
|
|||
static void sink_set_volume(pa_sink *sink) {
|
||||
struct userdata *u;
|
||||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
pa_assert(sink);
|
||||
u = sink->userdata;
|
||||
|
|
@ -1761,7 +1813,7 @@ static void sink_set_volume(pa_sink *sink) {
|
|||
|
||||
t = pa_tagstruct_new(NULL, 0);
|
||||
pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_VOLUME);
|
||||
pa_tagstruct_putu32(t, tag = u->ctag++);
|
||||
pa_tagstruct_putu32(t, u->ctag++);
|
||||
pa_tagstruct_putu32(t, u->device_index);
|
||||
pa_tagstruct_put_cvolume(t, &sink->real_volume);
|
||||
pa_pstream_send_tagstruct(u->pstream, t);
|
||||
|
|
@ -1771,7 +1823,6 @@ static void sink_set_volume(pa_sink *sink) {
|
|||
static void sink_set_mute(pa_sink *sink) {
|
||||
struct userdata *u;
|
||||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
pa_assert(sink);
|
||||
u = sink->userdata;
|
||||
|
|
@ -1782,7 +1833,7 @@ static void sink_set_mute(pa_sink *sink) {
|
|||
|
||||
t = pa_tagstruct_new(NULL, 0);
|
||||
pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_MUTE);
|
||||
pa_tagstruct_putu32(t, tag = u->ctag++);
|
||||
pa_tagstruct_putu32(t, u->ctag++);
|
||||
pa_tagstruct_putu32(t, u->device_index);
|
||||
pa_tagstruct_put_boolean(t, !!sink->muted);
|
||||
pa_pstream_send_tagstruct(u->pstream, t);
|
||||
|
|
|
|||
|
|
@ -29,10 +29,13 @@
|
|||
#include <sys/inotify.h>
|
||||
#include <libudev.h>
|
||||
|
||||
#include <pulse/timeval.h>
|
||||
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/namereg.h>
|
||||
#include <pulsecore/ratelimit.h>
|
||||
|
||||
#include "module-udev-detect-symdef.h"
|
||||
|
||||
|
|
@ -50,6 +53,7 @@ struct device {
|
|||
char *card_name;
|
||||
char *args;
|
||||
uint32_t module;
|
||||
pa_ratelimit ratelimit;
|
||||
};
|
||||
|
||||
struct userdata {
|
||||
|
|
@ -110,6 +114,9 @@ static pa_bool_t is_card_busy(const char *id) {
|
|||
|
||||
pa_assert(id);
|
||||
|
||||
/* This simply uses /proc/asound/card.../pcm.../sub.../status to
|
||||
* check whether there is still a process using this audio device. */
|
||||
|
||||
card_path = pa_sprintf_malloc("/proc/asound/card%s", id);
|
||||
|
||||
if (!(card_dir = opendir(card_path))) {
|
||||
|
|
@ -234,14 +241,41 @@ static void verify_access(struct userdata *u, struct device *d) {
|
|||
pa_log_debug("%s is busy: %s", d->path, pa_yes_no(busy));
|
||||
|
||||
if (!busy) {
|
||||
pa_log_debug("Loading module-alsa-card with arguments '%s'", d->args);
|
||||
m = pa_module_load(u->core, "module-alsa-card", d->args);
|
||||
|
||||
if (m) {
|
||||
d->module = m->index;
|
||||
pa_log_info("Card %s (%s) module loaded.", d->path, d->card_name);
|
||||
/* So, why do we rate limit here? It's certainly ugly,
|
||||
* but there seems to be no other way. Problem is
|
||||
* this: if we are unable to configure/probe an audio
|
||||
* device after opening it we will close it again and
|
||||
* the module initialization will fail. This will then
|
||||
* cause an inotify event on the device node which
|
||||
* will be forwarded to us. We then try to reopen the
|
||||
* audio device again, practically entering a busy
|
||||
* loop.
|
||||
*
|
||||
* A clean fix would be if we would be able to ignore
|
||||
* our own inotify close events. However, inotify
|
||||
* lacks such functionality. Also, during probing of
|
||||
* the device we cannot really distuingish between
|
||||
* other processes causing EBUSY or ourselves, which
|
||||
* means we have no way to figure out if the probing
|
||||
* during opening was canceled by a "try again"
|
||||
* failure or a "fatal" failure. */
|
||||
|
||||
if (pa_ratelimit_test(&d->ratelimit)) {
|
||||
pa_log_debug("Loading module-alsa-card with arguments '%s'", d->args);
|
||||
m = pa_module_load(u->core, "module-alsa-card", d->args);
|
||||
|
||||
if (m) {
|
||||
d->module = m->index;
|
||||
pa_log_info("Card %s (%s) module loaded.", d->path, d->card_name);
|
||||
} else
|
||||
pa_log_info("Card %s (%s) failed to load module.", d->path, d->card_name);
|
||||
} else
|
||||
pa_log_info("Card %s (%s) failed to load module.", d->path, d->card_name);
|
||||
pa_log_warn("Tried to configure %s (%s) more often than %u times in %llus",
|
||||
d->path,
|
||||
d->card_name,
|
||||
d->ratelimit.burst,
|
||||
(long long unsigned) (d->ratelimit.interval / PA_USEC_PER_SEC));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -277,6 +311,7 @@ static void card_changed(struct userdata *u, struct udev_device *dev) {
|
|||
d = pa_xnew0(struct device, 1);
|
||||
d->path = pa_xstrdup(path);
|
||||
d->module = PA_INVALID_INDEX;
|
||||
PA_INIT_RATELIMIT(d->ratelimit, 10*PA_USEC_PER_SEC, 5);
|
||||
|
||||
if (!(t = udev_device_get_property_value(dev, "PULSE_NAME")))
|
||||
if (!(t = udev_device_get_property_value(dev, "ID_ID")))
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ int pa_base64_encode(const void *data, int size, char **str)
|
|||
|
||||
p = s = pa_xnew(char, size * 4 / 3 + 4);
|
||||
q = (const unsigned char *) data;
|
||||
i = 0;
|
||||
for (i = 0; i < size;) {
|
||||
c = q[i++];
|
||||
c *= 256;
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ static void browser_cb(
|
|||
struct tunnel *t2;
|
||||
|
||||
if ((t2 = pa_hashmap_get(u->tunnels, t))) {
|
||||
pa_module_unload_by_index(u->core, t2->module_index, TRUE);
|
||||
pa_module_unload_request_by_index(u->core, t2->module_index, TRUE);
|
||||
pa_hashmap_remove(u->tunnels, t2);
|
||||
tunnel_free(t2);
|
||||
}
|
||||
|
|
@ -386,7 +386,7 @@ void pa__done(pa_module*m) {
|
|||
struct tunnel *t;
|
||||
|
||||
while ((t = pa_hashmap_steal_first(u->tunnels))) {
|
||||
pa_module_unload_by_index(u->core, t->module_index, TRUE);
|
||||
pa_module_unload_request_by_index(u->core, t->module_index, TRUE);
|
||||
tunnel_free(t);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ pa_reserve_wrapper* pa_reserve_wrapper_get(pa_core *c, const char *device_name)
|
|||
|
||||
#ifdef HAVE_DBUS
|
||||
if (!(r->connection = pa_dbus_bus_get(c, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) {
|
||||
pa_log_warn("Unable to contact D-Bus session bus: %s: %s", error.name, error.message);
|
||||
pa_log_debug("Unable to contact D-Bus session bus: %s: %s", error.name, error.message);
|
||||
|
||||
/* We don't treat this as error here because we want allow PA
|
||||
* to run even when no session bus is available. */
|
||||
|
|
@ -154,10 +154,10 @@ pa_reserve_wrapper* pa_reserve_wrapper_get(pa_core *c, const char *device_name)
|
|||
NULL)) < 0) {
|
||||
|
||||
if (k == -EBUSY) {
|
||||
pa_log_error("Device '%s' already locked.", device_name);
|
||||
pa_log_debug("Device '%s' already locked.", device_name);
|
||||
goto fail;
|
||||
} else {
|
||||
pa_log_warn("Failed to acquire reservation lock on device '%s': %s", device_name, pa_cstrerror(-k));
|
||||
pa_log_debug("Failed to acquire reservation lock on device '%s': %s", device_name, pa_cstrerror(-k));
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
|
@ -280,7 +280,7 @@ pa_reserve_monitor_wrapper* pa_reserve_monitor_wrapper_get(pa_core *c, const cha
|
|||
|
||||
#ifdef HAVE_DBUS
|
||||
if (!(w->connection = pa_dbus_bus_get(c, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) {
|
||||
pa_log_warn("Unable to contact D-Bus session bus: %s: %s", error.name, error.message);
|
||||
pa_log_debug("Unable to contact D-Bus session bus: %s: %s", error.name, error.message);
|
||||
|
||||
/* We don't treat this as error here because we want allow PA
|
||||
* to run even when no session bus is available. */
|
||||
|
|
@ -294,7 +294,7 @@ pa_reserve_monitor_wrapper* pa_reserve_monitor_wrapper_get(pa_core *c, const cha
|
|||
change_cb,
|
||||
NULL)) < 0) {
|
||||
|
||||
pa_log_warn("Failed to create watch on device '%s': %s", device_name, pa_cstrerror(-k));
|
||||
pa_log_debug("Failed to create watch on device '%s': %s", device_name, pa_cstrerror(-k));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ struct pa_rtsp_client {
|
|||
uint16_t port;
|
||||
|
||||
pa_socket_client *sc;
|
||||
pa_iochannel *io;
|
||||
pa_ioline *ioline;
|
||||
|
||||
pa_rtsp_cb_t callback;
|
||||
|
|
@ -111,10 +110,8 @@ void pa_rtsp_client_free(pa_rtsp_client* c) {
|
|||
|
||||
if (c->sc)
|
||||
pa_socket_client_unref(c->sc);
|
||||
if (c->ioline)
|
||||
pa_ioline_close(c->ioline);
|
||||
else if (c->io)
|
||||
pa_iochannel_free(c->io);
|
||||
|
||||
pa_rtsp_disconnect(c);
|
||||
|
||||
pa_xfree(c->hostname);
|
||||
pa_xfree(c->url);
|
||||
|
|
@ -187,7 +184,6 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) {
|
|||
if (!s) {
|
||||
/* Keep the ioline/iochannel open as they will be freed automatically */
|
||||
c->ioline = NULL;
|
||||
c->io = NULL;
|
||||
c->callback(c, STATE_DISCONNECTED, NULL, c->userdata);
|
||||
return;
|
||||
}
|
||||
|
|
@ -303,8 +299,7 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata
|
|||
pa_log("Connection failed: %s", pa_cstrerror(errno));
|
||||
return;
|
||||
}
|
||||
pa_assert(!c->io);
|
||||
c->io = io;
|
||||
pa_assert(!c->ioline);
|
||||
|
||||
c->ioline = pa_ioline_new(io);
|
||||
pa_ioline_set_callback(c->ioline, line_callback, c);
|
||||
|
|
@ -360,9 +355,6 @@ void pa_rtsp_disconnect(pa_rtsp_client *c) {
|
|||
|
||||
if (c->ioline)
|
||||
pa_ioline_close(c->ioline);
|
||||
else if (c->io)
|
||||
pa_iochannel_free(c->io);
|
||||
c->io = NULL;
|
||||
c->ioline = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -408,13 +400,11 @@ static int rtsp_exec(pa_rtsp_client* c, const char* cmd,
|
|||
pa_headerlist* headers) {
|
||||
pa_strbuf* buf;
|
||||
char* hdrs;
|
||||
ssize_t l;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(c->url);
|
||||
|
||||
if (!cmd)
|
||||
return -1;
|
||||
pa_assert(cmd);
|
||||
pa_assert(c->ioline);
|
||||
|
||||
pa_log_debug("Sending command: %s", cmd);
|
||||
|
||||
|
|
@ -453,7 +443,7 @@ static int rtsp_exec(pa_rtsp_client* c, const char* cmd,
|
|||
hdrs = pa_strbuf_tostring_free(buf);
|
||||
/*pa_log_debug("Submitting request:");
|
||||
pa_log_debug(hdrs);*/
|
||||
l = pa_iochannel_write(c->io, hdrs, strlen(hdrs));
|
||||
pa_ioline_puts(c->ioline, hdrs);
|
||||
pa_xfree(hdrs);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ static void publish_servers(struct userdata *u, pa_strlist *l) {
|
|||
|
||||
l = pa_strlist_reverse(l);
|
||||
s = pa_strlist_tostring(l);
|
||||
l = pa_strlist_reverse(l);
|
||||
pa_strlist_reverse(l);
|
||||
|
||||
pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SERVER", s);
|
||||
pa_xfree(s);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue