command: always allow setting volume/mute properties

This seems generally easier when using libmpv (and was already requested
and implemented before: see commit 327a779a; it was reverted some time
later).

With the weird internal logic we have to deal with, in particular the
--softvol=no case (using system volume), and using the audio API's mixer
(--softvol=auto on some systems), we still can't avoid all glitches and
corner cases that complicate this issue so much. The API user is either
recommended to use --softvol=yes or auto, or to watch the new
mixer-active property, and assume the volume/mute properties have
significant values if the mixer is active.

Remaining glitches:
- changing the volume/mute properties has no effect if no internal mixer
  is used (--softvol=no) and the mixer is not active; the actual mixer
  controls do not change, only the property values
- --volume/--mute do not have an effect on the volume/mute properties
  before mixer initialization (the options strictly are only applied
  during mixer init)
- volume-max is 100 while the mixer is not active
This commit is contained in:
wm4 2016-01-26 15:12:42 +01:00
parent 502763fcc7
commit d8aeeaa4b1
4 changed files with 42 additions and 7 deletions

View File

@ -29,6 +29,9 @@ Interface changes
instead of "sample"
- change VO opengl scaler-resizes-only default to enabled
- add VO opengl "tscale-interpolates-only" suboption
- make "volume" and "mute" properties changeable even if no audio output is
active (this gives not-ideal behavior if --softvol=no is used)
- add "volume-max" and "mixer-active" properties
--- mpv 0.15.0 ---
- change "yadif" video filter defaults
--- mpv 0.14.0 ---

View File

@ -1224,11 +1224,30 @@ Property list
``hr-seek`` (RW)
See ``--hr-seek``.
``mixer-active``
Return ``yes`` if the audio mixer is active, ``no`` otherwise. This has
implications for ``--softvol=no`` mode: if the mixer is active, changing
``volume`` doesn't actually change anything on the system mixer. If the
``--volume`` or ``--mute`` option are used, these might not be applied
property until the mixer becomes active either. (The options, if set, will
just overwrite the mixer state at audio initialization.)
While the behavior with ``mixer-active==yes`` is relatively well-defined,
the ``no`` case will provide possibly wrong or insignificant values.
Note that an active mixer does not necessarily imply active audio output,
although this is implied in the current implementation.
``volume`` (RW)
Current volume (see ``--volume`` for details).
Current volume (see ``--volume`` for details). Also see ``mixer-active``
property.
``volume-max``
Current maximum value the volume property can be set to. (This may depend
on the ``--softvol-max`` option.)
``mute`` (RW)
Current mute status (``yes``/``no``).
Current mute status (``yes``/``no``). Also see ``mixer-active`` property.
``audio-delay`` (RW)
See ``--audio-delay``.

View File

@ -399,4 +399,5 @@ void mixer_uninit_audio(struct mixer *mixer)
}
mixer->ao = NULL;
mixer->af = NULL;
mixer->softvol = false;
}

View File

@ -1538,13 +1538,18 @@ static int mp_property_partially_seekable(void *ctx, struct m_property *prop,
return m_property_flag_ro(action, arg, mpctx->demuxer->partially_seekable);
}
static int mp_property_mixer_active(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
return m_property_flag_ro(action, arg, mixer_audio_initialized(mpctx->mixer));
}
/// Volume (RW)
static int mp_property_volume(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
if (!mixer_audio_initialized(mpctx->mixer))
return M_PROPERTY_UNAVAILABLE;
switch (action) {
case M_PROPERTY_GET:
mixer_getbothvolume(mpctx->mixer, arg);
@ -1578,13 +1583,18 @@ static int mp_property_volume(void *ctx, struct m_property *prop,
return M_PROPERTY_NOT_IMPLEMENTED;
}
static int mp_property_volume_max(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
return m_property_float_ro(action, arg, mixer_getmaxvolume(mpctx->mixer));
}
/// Mute (RW)
static int mp_property_mute(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
if (!mixer_audio_initialized(mpctx->mixer))
return M_PROPERTY_ERROR;
switch (action) {
case M_PROPERTY_SET:
mixer_setmute(mpctx->mixer, *(int *) arg);
@ -3553,7 +3563,9 @@ static const struct m_property mp_properties[] = {
M_PROPERTY_ALIAS("playlist-count", "playlist/count"),
// Audio
{"mixer-active", mp_property_mixer_active},
{"volume", mp_property_volume},
{"volume-max", mp_property_volume_max},
{"mute", mp_property_mute},
{"audio-delay", mp_property_audio_delay},
{"audio-codec-name", mp_property_audio_codec_name},
@ -3734,7 +3746,7 @@ static const char *const *const mp_event_property_change[] = {
E(MPV_EVENT_AUDIO_RECONFIG, "audio-format", "audio-codec", "audio-bitrate",
"samplerate", "channels", "audio", "volume", "mute", "balance",
"volume-restore-data", "current-ao", "audio-codec-name", "audio-params",
"audio-out-params"),
"audio-out-params", "volume-max", "mixer-active"),
E(MPV_EVENT_SEEK, "seeking", "core-idle", "eof-reached"),
E(MPV_EVENT_PLAYBACK_RESTART, "seeking", "core-idle", "eof-reached"),
E(MPV_EVENT_METADATA_UPDATE, "metadata", "filtered-metadata", "media-title"),