mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
devices: Set certain sink/source flags automatically.
Some sink flags are really just a product of what callbacks are set on the device. We still enforce a degree of sanity that the flags match the callbacks set, but we also set the flags automatically in our callback setter functions to help ensure that a) people use them and b) flags & callbacks are kept in sync.
This commit is contained in:
parent
ded07a5898
commit
a9cf320bc1
13 changed files with 100 additions and 45 deletions
|
|
@ -1759,9 +1759,9 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB, pa_bool_t sync_v
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!u->mixer_path->has_volume)
|
if (!u->mixer_path->has_volume) {
|
||||||
pa_log_info("Driver does not support hardware volume control, falling back to software volume control.");
|
pa_log_info("Driver does not support hardware volume control, falling back to software volume control.");
|
||||||
else {
|
} else {
|
||||||
|
|
||||||
if (u->mixer_path->has_dB) {
|
if (u->mixer_path->has_dB) {
|
||||||
pa_log_info("Hardware volume ranges from %0.2f dB to %0.2f dB.", u->mixer_path->min_dB, u->mixer_path->max_dB);
|
pa_log_info("Hardware volume ranges from %0.2f dB to %0.2f dB.", u->mixer_path->min_dB, u->mixer_path->max_dB);
|
||||||
|
|
@ -1779,13 +1779,11 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB, pa_bool_t sync_v
|
||||||
|
|
||||||
pa_sink_set_get_volume_callback(u->sink, sink_get_volume_cb);
|
pa_sink_set_get_volume_callback(u->sink, sink_get_volume_cb);
|
||||||
pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
|
pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
|
||||||
pa_sink_set_write_volume_callback(u->sink, sink_write_volume_cb);
|
|
||||||
|
|
||||||
u->sink->flags |= PA_SINK_HW_VOLUME_CTRL;
|
|
||||||
if (u->mixer_path->has_dB) {
|
if (u->mixer_path->has_dB) {
|
||||||
u->sink->flags |= PA_SINK_DECIBEL_VOLUME;
|
u->sink->flags |= PA_SINK_DECIBEL_VOLUME;
|
||||||
if (sync_volume) {
|
if (sync_volume) {
|
||||||
u->sink->flags |= PA_SINK_SYNC_VOLUME;
|
pa_sink_set_write_volume_callback(u->sink, sink_write_volume_cb);
|
||||||
pa_log_info("Successfully enabled synchronous volume.");
|
pa_log_info("Successfully enabled synchronous volume.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1798,11 +1796,10 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB, pa_bool_t sync_v
|
||||||
} else {
|
} else {
|
||||||
pa_sink_set_get_mute_callback(u->sink, sink_get_mute_cb);
|
pa_sink_set_get_mute_callback(u->sink, sink_get_mute_cb);
|
||||||
pa_sink_set_set_mute_callback(u->sink, sink_set_mute_cb);
|
pa_sink_set_set_mute_callback(u->sink, sink_set_mute_cb);
|
||||||
u->sink->flags |= PA_SINK_HW_MUTE_CTRL;
|
|
||||||
pa_log_info("Using hardware mute control.");
|
pa_log_info("Using hardware mute control.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (u->sink->flags & (PA_SINK_HW_VOLUME_CTRL|PA_SINK_HW_MUTE_CTRL)) {
|
if (u->mixer_path->has_volume || u->mixer_path->has_mute) {
|
||||||
int (*mixer_callback)(snd_mixer_elem_t *, unsigned int);
|
int (*mixer_callback)(snd_mixer_elem_t *, unsigned int);
|
||||||
if (u->sink->flags & PA_SINK_SYNC_VOLUME) {
|
if (u->sink->flags & PA_SINK_SYNC_VOLUME) {
|
||||||
u->mixer_pd = pa_alsa_mixer_pdata_new();
|
u->mixer_pd = pa_alsa_mixer_pdata_new();
|
||||||
|
|
|
||||||
|
|
@ -1534,9 +1534,9 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB, pa_bool_t sync_v
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!u->mixer_path->has_volume)
|
if (!u->mixer_path->has_volume) {
|
||||||
pa_log_info("Driver does not support hardware volume control, falling back to software volume control.");
|
pa_log_info("Driver does not support hardware volume control, falling back to software volume control.");
|
||||||
else {
|
} else {
|
||||||
|
|
||||||
if (u->mixer_path->has_dB) {
|
if (u->mixer_path->has_dB) {
|
||||||
pa_log_info("Hardware volume ranges from %0.2f dB to %0.2f dB.", u->mixer_path->min_dB, u->mixer_path->max_dB);
|
pa_log_info("Hardware volume ranges from %0.2f dB to %0.2f dB.", u->mixer_path->min_dB, u->mixer_path->max_dB);
|
||||||
|
|
@ -1554,13 +1554,11 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB, pa_bool_t sync_v
|
||||||
|
|
||||||
pa_source_set_get_volume_callback(u->source, source_get_volume_cb);
|
pa_source_set_get_volume_callback(u->source, source_get_volume_cb);
|
||||||
pa_source_set_set_volume_callback(u->source, source_set_volume_cb);
|
pa_source_set_set_volume_callback(u->source, source_set_volume_cb);
|
||||||
pa_source_set_write_volume_callback(u->source, source_write_volume_cb);
|
|
||||||
|
|
||||||
u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL;
|
|
||||||
if (u->mixer_path->has_dB) {
|
if (u->mixer_path->has_dB) {
|
||||||
u->source->flags |= PA_SOURCE_DECIBEL_VOLUME;
|
u->source->flags |= PA_SOURCE_DECIBEL_VOLUME;
|
||||||
if (sync_volume) {
|
if (sync_volume) {
|
||||||
u->source->flags |= PA_SOURCE_SYNC_VOLUME;
|
pa_source_set_write_volume_callback(u->source, source_write_volume_cb);
|
||||||
pa_log_info("Successfully enabled synchronous volume.");
|
pa_log_info("Successfully enabled synchronous volume.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1573,11 +1571,10 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB, pa_bool_t sync_v
|
||||||
} else {
|
} else {
|
||||||
pa_source_set_get_mute_callback(u->source, source_get_mute_cb);
|
pa_source_set_get_mute_callback(u->source, source_get_mute_cb);
|
||||||
pa_source_set_set_mute_callback(u->source, source_set_mute_cb);
|
pa_source_set_set_mute_callback(u->source, source_set_mute_cb);
|
||||||
u->source->flags |= PA_SOURCE_HW_MUTE_CTRL;
|
|
||||||
pa_log_info("Using hardware mute control.");
|
pa_log_info("Using hardware mute control.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (u->source->flags & (PA_SOURCE_HW_VOLUME_CTRL|PA_SOURCE_HW_MUTE_CTRL)) {
|
if (u->mixer_path->has_volume || u->mixer_path->has_mute) {
|
||||||
int (*mixer_callback)(snd_mixer_elem_t *, unsigned int);
|
int (*mixer_callback)(snd_mixer_elem_t *, unsigned int);
|
||||||
if (u->source->flags & PA_SOURCE_SYNC_VOLUME) {
|
if (u->source->flags & PA_SOURCE_SYNC_VOLUME) {
|
||||||
u->mixer_pd = pa_alsa_mixer_pdata_new();
|
u->mixer_pd = pa_alsa_mixer_pdata_new();
|
||||||
|
|
|
||||||
|
|
@ -2022,7 +2022,7 @@ static int add_sink(struct userdata *u) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u->sink = pa_sink_new(u->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY | (u->profile == PROFILE_HSP ? PA_SINK_HW_VOLUME_CTRL : 0));
|
u->sink = pa_sink_new(u->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
|
||||||
pa_sink_new_data_done(&data);
|
pa_sink_new_data_done(&data);
|
||||||
|
|
||||||
if (!u->sink) {
|
if (!u->sink) {
|
||||||
|
|
@ -2084,7 +2084,7 @@ static int add_source(struct userdata *u) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u->source = pa_source_new(u->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY | (u->profile == PROFILE_HSP ? PA_SOURCE_HW_VOLUME_CTRL : 0));
|
u->source = pa_source_new(u->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
|
||||||
pa_source_new_data_done(&data);
|
pa_source_new_data_done(&data);
|
||||||
|
|
||||||
if (!u->source) {
|
if (!u->source) {
|
||||||
|
|
|
||||||
|
|
@ -1523,7 +1523,7 @@ int pa__init(pa_module*m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
u->source = pa_source_new(m->core, &source_data,
|
u->source = pa_source_new(m->core, &source_data,
|
||||||
PA_SOURCE_HW_MUTE_CTRL|PA_SOURCE_HW_VOLUME_CTRL|PA_SOURCE_DECIBEL_VOLUME|
|
PA_SOURCE_DECIBEL_VOLUME|
|
||||||
(source_master->flags & (PA_SOURCE_LATENCY|PA_SOURCE_DYNAMIC_LATENCY)));
|
(source_master->flags & (PA_SOURCE_LATENCY|PA_SOURCE_DYNAMIC_LATENCY)));
|
||||||
pa_source_new_data_done(&source_data);
|
pa_source_new_data_done(&source_data);
|
||||||
|
|
||||||
|
|
@ -1571,7 +1571,7 @@ int pa__init(pa_module*m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
u->sink = pa_sink_new(m->core, &sink_data,
|
u->sink = pa_sink_new(m->core, &sink_data,
|
||||||
PA_SINK_HW_MUTE_CTRL|PA_SINK_HW_VOLUME_CTRL|PA_SINK_DECIBEL_VOLUME|
|
PA_SINK_DECIBEL_VOLUME|
|
||||||
(sink_master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY)));
|
(sink_master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY)));
|
||||||
pa_sink_new_data_done(&sink_data);
|
pa_sink_new_data_done(&sink_data);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1178,7 +1178,7 @@ int pa__init(pa_module*m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
u->sink = pa_sink_new(m->core, &sink_data,
|
u->sink = pa_sink_new(m->core, &sink_data,
|
||||||
PA_SINK_HW_MUTE_CTRL|PA_SINK_HW_VOLUME_CTRL|PA_SINK_DECIBEL_VOLUME|
|
PA_SINK_DECIBEL_VOLUME|
|
||||||
(master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY)));
|
(master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY)));
|
||||||
pa_sink_new_data_done(&sink_data);
|
pa_sink_new_data_done(&sink_data);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -883,7 +883,7 @@ int pa__init(pa_module*m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
u->sink = pa_sink_new(m->core, &sink_data,
|
u->sink = pa_sink_new(m->core, &sink_data,
|
||||||
PA_SINK_HW_MUTE_CTRL|PA_SINK_HW_VOLUME_CTRL|PA_SINK_DECIBEL_VOLUME|
|
PA_SINK_DECIBEL_VOLUME|
|
||||||
(master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY)));
|
(master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY)));
|
||||||
pa_sink_new_data_done(&sink_data);
|
pa_sink_new_data_done(&sink_data);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -933,7 +933,7 @@ int pa__init(pa_module *m) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
u->source = pa_source_new(m->core, &source_new_data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY|PA_SOURCE_HW_VOLUME_CTRL);
|
u->source = pa_source_new(m->core, &source_new_data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
|
||||||
pa_source_new_data_done(&source_new_data);
|
pa_source_new_data_done(&source_new_data);
|
||||||
pa_xfree(name_buf);
|
pa_xfree(name_buf);
|
||||||
|
|
||||||
|
|
@ -981,7 +981,7 @@ int pa__init(pa_module *m) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
u->sink = pa_sink_new(m->core, &sink_new_data, PA_SINK_HARDWARE|PA_SINK_LATENCY|PA_SINK_HW_VOLUME_CTRL|PA_SINK_HW_MUTE_CTRL);
|
u->sink = pa_sink_new(m->core, &sink_new_data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
|
||||||
pa_sink_new_data_done(&sink_new_data);
|
pa_sink_new_data_done(&sink_new_data);
|
||||||
|
|
||||||
pa_assert(u->sink);
|
pa_assert(u->sink);
|
||||||
|
|
|
||||||
|
|
@ -2003,7 +2003,7 @@ int pa__init(pa_module*m) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
u->sink = pa_sink_new(m->core, &data, PA_SINK_NETWORK|PA_SINK_LATENCY|PA_SINK_HW_VOLUME_CTRL|PA_SINK_HW_MUTE_CTRL);
|
u->sink = pa_sink_new(m->core, &data, PA_SINK_NETWORK|PA_SINK_LATENCY);
|
||||||
pa_sink_new_data_done(&data);
|
pa_sink_new_data_done(&data);
|
||||||
|
|
||||||
if (!u->sink) {
|
if (!u->sink) {
|
||||||
|
|
|
||||||
|
|
@ -1418,11 +1418,9 @@ int pa__init(pa_module*m) {
|
||||||
|
|
||||||
if (ioctl(fd, SOUND_MIXER_READ_DEVMASK, &u->mixer_devmask) < 0)
|
if (ioctl(fd, SOUND_MIXER_READ_DEVMASK, &u->mixer_devmask) < 0)
|
||||||
pa_log_warn("SOUND_MIXER_READ_DEVMASK failed: %s", pa_cstrerror(errno));
|
pa_log_warn("SOUND_MIXER_READ_DEVMASK failed: %s", pa_cstrerror(errno));
|
||||||
|
|
||||||
else {
|
else {
|
||||||
if (u->sink && (u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM))) {
|
if (u->sink && (u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM))) {
|
||||||
pa_log_debug("Found hardware mixer track for playback.");
|
pa_log_debug("Found hardware mixer track for playback.");
|
||||||
u->sink->flags |= PA_SINK_HW_VOLUME_CTRL;
|
|
||||||
pa_sink_set_get_volume_callback(u->sink, sink_get_volume);
|
pa_sink_set_get_volume_callback(u->sink, sink_get_volume);
|
||||||
pa_sink_set_set_volume_callback(u->sink, sink_set_volume);
|
pa_sink_set_set_volume_callback(u->sink, sink_set_volume);
|
||||||
u->sink->n_volume_steps = 101;
|
u->sink->n_volume_steps = 101;
|
||||||
|
|
@ -1431,7 +1429,6 @@ int pa__init(pa_module*m) {
|
||||||
|
|
||||||
if (u->source && (u->mixer_devmask & (SOUND_MASK_RECLEV|SOUND_MASK_IGAIN))) {
|
if (u->source && (u->mixer_devmask & (SOUND_MASK_RECLEV|SOUND_MASK_IGAIN))) {
|
||||||
pa_log_debug("Found hardware mixer track for recording.");
|
pa_log_debug("Found hardware mixer track for recording.");
|
||||||
u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL;
|
|
||||||
pa_source_set_get_volume_callback(u->source, source_get_volume);
|
pa_source_set_get_volume_callback(u->source, source_get_volume);
|
||||||
pa_source_set_set_volume_callback(u->source, source_set_volume);
|
pa_source_set_set_volume_callback(u->source, source_set_volume);
|
||||||
u->source->n_volume_steps = 101;
|
u->source->n_volume_steps = 101;
|
||||||
|
|
|
||||||
|
|
@ -596,7 +596,7 @@ int pa__init(pa_module*m) {
|
||||||
u->sink->userdata = u;
|
u->sink->userdata = u;
|
||||||
pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
|
pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
|
||||||
pa_sink_set_set_mute_callback(u->sink, sink_set_mute_cb);
|
pa_sink_set_set_mute_callback(u->sink, sink_set_mute_cb);
|
||||||
u->sink->flags = PA_SINK_LATENCY|PA_SINK_NETWORK|PA_SINK_HW_VOLUME_CTRL;
|
u->sink->flags = PA_SINK_LATENCY|PA_SINK_NETWORK;
|
||||||
|
|
||||||
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
|
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
|
||||||
pa_sink_set_rtpoll(u->sink, u->rtpoll);
|
pa_sink_set_rtpoll(u->sink, u->rtpoll);
|
||||||
|
|
|
||||||
|
|
@ -712,7 +712,8 @@ typedef enum pa_sink_flags {
|
||||||
/**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */
|
/**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */
|
||||||
|
|
||||||
PA_SINK_HW_VOLUME_CTRL = 0x0001U,
|
PA_SINK_HW_VOLUME_CTRL = 0x0001U,
|
||||||
/**< Supports hardware volume control */
|
/**< Supports hardware volume control. This is a dynamic flag and may
|
||||||
|
* change at runtime after the sink has initialized */
|
||||||
|
|
||||||
PA_SINK_LATENCY = 0x0002U,
|
PA_SINK_LATENCY = 0x0002U,
|
||||||
/**< Supports latency querying */
|
/**< Supports latency querying */
|
||||||
|
|
@ -725,10 +726,12 @@ typedef enum pa_sink_flags {
|
||||||
/**< Is a networked sink of some kind. \since 0.9.7 */
|
/**< Is a networked sink of some kind. \since 0.9.7 */
|
||||||
|
|
||||||
PA_SINK_HW_MUTE_CTRL = 0x0010U,
|
PA_SINK_HW_MUTE_CTRL = 0x0010U,
|
||||||
/**< Supports hardware mute control \since 0.9.11 */
|
/**< Supports hardware mute control. This is a dynamic flag and may
|
||||||
|
* change at runtime after the sink has initialized \since 0.9.11 */
|
||||||
|
|
||||||
PA_SINK_DECIBEL_VOLUME = 0x0020U,
|
PA_SINK_DECIBEL_VOLUME = 0x0020U,
|
||||||
/**< Volume can be translated to dB with pa_sw_volume_to_dB()
|
/**< Volume can be translated to dB with pa_sw_volume_to_dB(). This is a
|
||||||
|
* dynamic flag and may change at runtime after the sink has initialized
|
||||||
* \since 0.9.11 */
|
* \since 0.9.11 */
|
||||||
|
|
||||||
PA_SINK_FLAT_VOLUME = 0x0040U,
|
PA_SINK_FLAT_VOLUME = 0x0040U,
|
||||||
|
|
@ -820,7 +823,8 @@ typedef enum pa_source_flags {
|
||||||
/**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */
|
/**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */
|
||||||
|
|
||||||
PA_SOURCE_HW_VOLUME_CTRL = 0x0001U,
|
PA_SOURCE_HW_VOLUME_CTRL = 0x0001U,
|
||||||
/**< Supports hardware volume control */
|
/**< Supports hardware volume control. This is a dynamic flag and may
|
||||||
|
* change at runtime after the source has initialized */
|
||||||
|
|
||||||
PA_SOURCE_LATENCY = 0x0002U,
|
PA_SOURCE_LATENCY = 0x0002U,
|
||||||
/**< Supports latency querying */
|
/**< Supports latency querying */
|
||||||
|
|
@ -833,10 +837,12 @@ typedef enum pa_source_flags {
|
||||||
/**< Is a networked source of some kind. \since 0.9.7 */
|
/**< Is a networked source of some kind. \since 0.9.7 */
|
||||||
|
|
||||||
PA_SOURCE_HW_MUTE_CTRL = 0x0010U,
|
PA_SOURCE_HW_MUTE_CTRL = 0x0010U,
|
||||||
/**< Supports hardware mute control \since 0.9.11 */
|
/**< Supports hardware mute control. This is a dynamic flag and may
|
||||||
|
* change at runtime after the source has initialized \since 0.9.11 */
|
||||||
|
|
||||||
PA_SOURCE_DECIBEL_VOLUME = 0x0020U,
|
PA_SOURCE_DECIBEL_VOLUME = 0x0020U,
|
||||||
/**< Volume can be translated to dB with pa_sw_volume_to_dB()
|
/**< Volume can be translated to dB with pa_sw_volume_to_dB(). This is a
|
||||||
|
* dynamic flag and may change at runtime after the source has initialized
|
||||||
* \since 0.9.11 */
|
* \since 0.9.11 */
|
||||||
|
|
||||||
PA_SOURCE_DYNAMIC_LATENCY = 0x0040U,
|
PA_SOURCE_DYNAMIC_LATENCY = 0x0040U,
|
||||||
|
|
|
||||||
|
|
@ -458,13 +458,27 @@ void pa_sink_set_get_volume_callback(pa_sink *s, pa_sink_cb_t cb) {
|
||||||
void pa_sink_set_set_volume_callback(pa_sink *s, pa_sink_cb_t cb) {
|
void pa_sink_set_set_volume_callback(pa_sink *s, pa_sink_cb_t cb) {
|
||||||
pa_assert(s);
|
pa_assert(s);
|
||||||
|
|
||||||
|
pa_assert(!s->write_volume || cb);
|
||||||
|
|
||||||
s->set_volume = cb;
|
s->set_volume = cb;
|
||||||
|
|
||||||
|
if (cb)
|
||||||
|
s->flags |= PA_SINK_HW_VOLUME_CTRL;
|
||||||
|
else
|
||||||
|
s->flags &= ~PA_SINK_HW_VOLUME_CTRL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pa_sink_set_write_volume_callback(pa_sink *s, pa_sink_cb_t cb) {
|
void pa_sink_set_write_volume_callback(pa_sink *s, pa_sink_cb_t cb) {
|
||||||
pa_assert(s);
|
pa_assert(s);
|
||||||
|
|
||||||
|
pa_assert(!cb || s->set_volume);
|
||||||
|
|
||||||
s->write_volume = cb;
|
s->write_volume = cb;
|
||||||
|
|
||||||
|
if (cb)
|
||||||
|
s->flags |= PA_SINK_SYNC_VOLUME;
|
||||||
|
else
|
||||||
|
s->flags &= ~PA_SINK_SYNC_VOLUME;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pa_sink_set_get_mute_callback(pa_sink *s, pa_sink_cb_t cb) {
|
void pa_sink_set_get_mute_callback(pa_sink *s, pa_sink_cb_t cb) {
|
||||||
|
|
@ -477,6 +491,11 @@ void pa_sink_set_set_mute_callback(pa_sink *s, pa_sink_cb_t cb) {
|
||||||
pa_assert(s);
|
pa_assert(s);
|
||||||
|
|
||||||
s->set_mute = cb;
|
s->set_mute = cb;
|
||||||
|
|
||||||
|
if (cb)
|
||||||
|
s->flags |= PA_SINK_HW_MUTE_CTRL;
|
||||||
|
else
|
||||||
|
s->flags &= ~PA_SINK_HW_MUTE_CTRL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called from main context */
|
/* Called from main context */
|
||||||
|
|
@ -492,8 +511,18 @@ void pa_sink_put(pa_sink* s) {
|
||||||
pa_assert(s->thread_info.min_latency <= s->thread_info.max_latency);
|
pa_assert(s->thread_info.min_latency <= s->thread_info.max_latency);
|
||||||
|
|
||||||
/* Generally, flags should be initialized via pa_sink_new(). As a
|
/* Generally, flags should be initialized via pa_sink_new(). As a
|
||||||
* special exception we allow volume related flags to be set
|
* special exception we allow some volume related flags to be set
|
||||||
* between _new() and _put(). */
|
* between _new() and _put() by the callback setter functions above.
|
||||||
|
*
|
||||||
|
* Thus we implement a couple safeguards here which ensure the above
|
||||||
|
* setters were used (or at least the implementor made manual changes
|
||||||
|
* in a compatible way).
|
||||||
|
*
|
||||||
|
* Note: All of these flags set here can change over the life time
|
||||||
|
* of the sink. */
|
||||||
|
pa_assert(!(s->flags & PA_SINK_HW_VOLUME_CTRL) || s->set_volume);
|
||||||
|
pa_assert(!(s->flags & PA_SINK_SYNC_VOLUME) || s->write_volume);
|
||||||
|
pa_assert(!(s->flags & PA_SINK_HW_MUTE_CTRL) || s->set_mute);
|
||||||
|
|
||||||
/* XXX: Currently decibel volume is disabled for all sinks that use volume
|
/* XXX: Currently decibel volume is disabled for all sinks that use volume
|
||||||
* sharing. When the master sink supports decibel volume, it would be good
|
* sharing. When the master sink supports decibel volume, it would be good
|
||||||
|
|
@ -502,6 +531,10 @@ void pa_sink_put(pa_sink* s) {
|
||||||
* a master sink to another. One solution for this problem would be to
|
* a master sink to another. One solution for this problem would be to
|
||||||
* remove user-visible volume altogether from filter sinks when volume
|
* remove user-visible volume altogether from filter sinks when volume
|
||||||
* sharing is used, but the current approach was easier to implement... */
|
* sharing is used, but the current approach was easier to implement... */
|
||||||
|
/* We always support decibel volumes in software, otherwise we leave it to
|
||||||
|
* the sink implementor to set this flag as needed.
|
||||||
|
*
|
||||||
|
* Note: This flag can also change over the life time of the sink. */
|
||||||
if (!(s->flags & PA_SINK_HW_VOLUME_CTRL) && !(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
|
if (!(s->flags & PA_SINK_HW_VOLUME_CTRL) && !(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
|
||||||
s->flags |= PA_SINK_DECIBEL_VOLUME;
|
s->flags |= PA_SINK_DECIBEL_VOLUME;
|
||||||
|
|
||||||
|
|
@ -536,10 +569,6 @@ void pa_sink_put(pa_sink* s) {
|
||||||
pa_assert(!(s->flags & PA_SINK_DYNAMIC_LATENCY) == (s->thread_info.fixed_latency != 0));
|
pa_assert(!(s->flags & PA_SINK_DYNAMIC_LATENCY) == (s->thread_info.fixed_latency != 0));
|
||||||
pa_assert(!(s->flags & PA_SINK_LATENCY) == !(s->monitor_source->flags & PA_SOURCE_LATENCY));
|
pa_assert(!(s->flags & PA_SINK_LATENCY) == !(s->monitor_source->flags & PA_SOURCE_LATENCY));
|
||||||
pa_assert(!(s->flags & PA_SINK_DYNAMIC_LATENCY) == !(s->monitor_source->flags & PA_SOURCE_DYNAMIC_LATENCY));
|
pa_assert(!(s->flags & PA_SINK_DYNAMIC_LATENCY) == !(s->monitor_source->flags & PA_SOURCE_DYNAMIC_LATENCY));
|
||||||
pa_assert(!(s->flags & PA_SINK_HW_VOLUME_CTRL) || s->set_volume);
|
|
||||||
pa_assert(!(s->flags & PA_SINK_SYNC_VOLUME) || (s->flags & PA_SINK_HW_VOLUME_CTRL));
|
|
||||||
pa_assert(!(s->flags & PA_SINK_SYNC_VOLUME) || s->write_volume);
|
|
||||||
pa_assert(!(s->flags & PA_SINK_HW_MUTE_CTRL) || s->set_mute);
|
|
||||||
|
|
||||||
pa_assert(s->monitor_source->thread_info.fixed_latency == s->thread_info.fixed_latency);
|
pa_assert(s->monitor_source->thread_info.fixed_latency == s->thread_info.fixed_latency);
|
||||||
pa_assert(s->monitor_source->thread_info.min_latency == s->thread_info.min_latency);
|
pa_assert(s->monitor_source->thread_info.min_latency == s->thread_info.min_latency);
|
||||||
|
|
|
||||||
|
|
@ -390,13 +390,27 @@ void pa_source_set_get_volume_callback(pa_source *s, pa_source_cb_t cb) {
|
||||||
void pa_source_set_set_volume_callback(pa_source *s, pa_source_cb_t cb) {
|
void pa_source_set_set_volume_callback(pa_source *s, pa_source_cb_t cb) {
|
||||||
pa_assert(s);
|
pa_assert(s);
|
||||||
|
|
||||||
|
pa_assert(!s->write_volume || cb);
|
||||||
|
|
||||||
s->set_volume = cb;
|
s->set_volume = cb;
|
||||||
|
|
||||||
|
if (cb)
|
||||||
|
s->flags |= PA_SOURCE_HW_VOLUME_CTRL;
|
||||||
|
else
|
||||||
|
s->flags &= ~PA_SOURCE_HW_VOLUME_CTRL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pa_source_set_write_volume_callback(pa_source *s, pa_source_cb_t cb) {
|
void pa_source_set_write_volume_callback(pa_source *s, pa_source_cb_t cb) {
|
||||||
pa_assert(s);
|
pa_assert(s);
|
||||||
|
|
||||||
|
pa_assert(!cb || s->set_volume);
|
||||||
|
|
||||||
s->write_volume = cb;
|
s->write_volume = cb;
|
||||||
|
|
||||||
|
if (cb)
|
||||||
|
s->flags |= PA_SOURCE_SYNC_VOLUME;
|
||||||
|
else
|
||||||
|
s->flags &= ~PA_SOURCE_SYNC_VOLUME;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pa_source_set_get_mute_callback(pa_source *s, pa_source_cb_t cb) {
|
void pa_source_set_get_mute_callback(pa_source *s, pa_source_cb_t cb) {
|
||||||
|
|
@ -409,6 +423,11 @@ void pa_source_set_set_mute_callback(pa_source *s, pa_source_cb_t cb) {
|
||||||
pa_assert(s);
|
pa_assert(s);
|
||||||
|
|
||||||
s->set_mute = cb;
|
s->set_mute = cb;
|
||||||
|
|
||||||
|
if (cb)
|
||||||
|
s->flags |= PA_SOURCE_HW_MUTE_CTRL;
|
||||||
|
else
|
||||||
|
s->flags &= ~PA_SOURCE_HW_MUTE_CTRL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called from main context */
|
/* Called from main context */
|
||||||
|
|
@ -424,8 +443,18 @@ void pa_source_put(pa_source *s) {
|
||||||
pa_assert(s->thread_info.min_latency <= s->thread_info.max_latency);
|
pa_assert(s->thread_info.min_latency <= s->thread_info.max_latency);
|
||||||
|
|
||||||
/* Generally, flags should be initialized via pa_source_new(). As a
|
/* Generally, flags should be initialized via pa_source_new(). As a
|
||||||
* special exception we allow volume related flags to be set
|
* special exception we allow some volume related flags to be set
|
||||||
* between _new() and _put(). */
|
* between _new() and _put() by the callback setter functions above.
|
||||||
|
*
|
||||||
|
* Thus we implement a couple safeguards here which ensure the above
|
||||||
|
* setters were used (or at least the implementor made manual changes
|
||||||
|
* in a compatible way).
|
||||||
|
*
|
||||||
|
* Note: All of these flags set here can change over the life time
|
||||||
|
* of the source. */
|
||||||
|
pa_assert(!(s->flags & PA_SOURCE_HW_VOLUME_CTRL) || s->set_volume);
|
||||||
|
pa_assert(!(s->flags & PA_SOURCE_SYNC_VOLUME) || s->write_volume);
|
||||||
|
pa_assert(!(s->flags & PA_SOURCE_HW_MUTE_CTRL) || s->set_mute);
|
||||||
|
|
||||||
/* XXX: Currently decibel volume is disabled for all sources that use volume
|
/* XXX: Currently decibel volume is disabled for all sources that use volume
|
||||||
* sharing. When the master source supports decibel volume, it would be good
|
* sharing. When the master source supports decibel volume, it would be good
|
||||||
|
|
@ -434,6 +463,10 @@ void pa_source_put(pa_source *s) {
|
||||||
* a master source to another. One solution for this problem would be to
|
* a master source to another. One solution for this problem would be to
|
||||||
* remove user-visible volume altogether from filter sources when volume
|
* remove user-visible volume altogether from filter sources when volume
|
||||||
* sharing is used, but the current approach was easier to implement... */
|
* sharing is used, but the current approach was easier to implement... */
|
||||||
|
/* We always support decibel volumes in software, otherwise we leave it to
|
||||||
|
* the source implementor to set this flag as needed.
|
||||||
|
*
|
||||||
|
* Note: This flag can also change over the life time of the source. */
|
||||||
if (!(s->flags & PA_SOURCE_HW_VOLUME_CTRL) && !(s->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER))
|
if (!(s->flags & PA_SOURCE_HW_VOLUME_CTRL) && !(s->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER))
|
||||||
s->flags |= PA_SOURCE_DECIBEL_VOLUME;
|
s->flags |= PA_SOURCE_DECIBEL_VOLUME;
|
||||||
|
|
||||||
|
|
@ -466,10 +499,6 @@ void pa_source_put(pa_source *s) {
|
||||||
&& ((s->flags & PA_SOURCE_DECIBEL_VOLUME || (s->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER)))));
|
&& ((s->flags & PA_SOURCE_DECIBEL_VOLUME || (s->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER)))));
|
||||||
pa_assert(!(s->flags & PA_SOURCE_DECIBEL_VOLUME) || s->n_volume_steps == PA_VOLUME_NORM+1);
|
pa_assert(!(s->flags & PA_SOURCE_DECIBEL_VOLUME) || s->n_volume_steps == PA_VOLUME_NORM+1);
|
||||||
pa_assert(!(s->flags & PA_SOURCE_DYNAMIC_LATENCY) == (s->thread_info.fixed_latency != 0));
|
pa_assert(!(s->flags & PA_SOURCE_DYNAMIC_LATENCY) == (s->thread_info.fixed_latency != 0));
|
||||||
pa_assert(!(s->flags & PA_SOURCE_HW_VOLUME_CTRL) || s->set_volume);
|
|
||||||
pa_assert(!(s->flags & PA_SOURCE_SYNC_VOLUME) || (s->flags & PA_SOURCE_HW_VOLUME_CTRL));
|
|
||||||
pa_assert(!(s->flags & PA_SOURCE_SYNC_VOLUME) || s->write_volume);
|
|
||||||
pa_assert(!(s->flags & PA_SOURCE_HW_MUTE_CTRL) || s->set_mute);
|
|
||||||
|
|
||||||
pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0);
|
pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue