Before this change, AOs could have internal alignment, and play() would
not consume the trailing data if the size passed to it is not aligned.
Change this to require AOs to report their alignment (via period_size),
and make sure to always send aligned data.
The buffer reported by get_space() now always has to be correct and
reliable. If play() does not consume all data provided (which is bounded
by get_space()), an error is printed.
This is preparation for potential further AO changes.
I casually checked alsa/lavc/null/pcm, the other AOs might or might not
work.
Long planned. Leads to some sanity.
There still are some rather gross things. Especially g_groups is ugly,
and a hack that can hopefully be removed. (There is a plan for it, but
whether it's implemented depends on how much energy is left.)
They are useless. Not only are they actually rarely in use; but
libavcodec doesn't even output them, as libavcodec has no such sample
formats for decoded audio.
Even if it should happen that we actually still need them (e.g. if doing
direct hardware output), there are better solutions. Swapping the sign
is a fast and lossless operation and can be done inplace, so AO actually
needing it could do this directly.
If you wonder why we keep U8 instead of S8: because libavcodec does it.
The code actually uses blocking mode, so opening sound device in non-blocking
mode results in choppy sound. Also, inflating the buffer isn't necessary in
blocking mode, so the function may simply return without doing anything.
The one in msg.c was mistakenly removed with commit e99a37f6.
I didn't actually test the change in ao_sndio.c (but obviously "ap"
shouldn't be static).
libsndio has absolutely no mechanism to discard already written audio
(other than SIGKILLing the sound server). sio_stop() will always block
until all audio is played. This is a legitimate design bug.
In theory, we could just not stop it at all, so if the player is e.g.
paused, the remaining audio would be played. When resuming, we would
have to do something to ensure get_delay() returns the right value. But
I couldn't get it to work in all cases.
get_delay needs to report the current audio buffer status. It's
important for A/V sync that this information is current, but functions
which update it were called on play() or get_space() calls only.
This was in bytes, but it's more convenient to use samples (or frames;
in any case the smallest unit of audio that includes all channels).
Remove the ao->bps line too; it will be set after init() returns.
Until now, the audio chain could handle both little endian and big
endian formats. This actually doesn't make much sense, since the audio
API and the HW will most likely prefer native formats. Or at the very
least, it should be trivial for audio drivers to do the byte swapping
themselves.
From now on, the audio chain contains native-endian formats only. All
AOs and some filters are adjusted. af_convertsignendian.c is now wrongly
named, but the filter name is adjusted. In some cases, the audio
infrastructure was reused on the demuxer side, but that is relatively
easy to rectify.
This is a quite intrusive and radical change. It's possible that it will
break some things (especially if they're obscure or not Linux), so watch
out for regressions. It's probably still better to do it the bulldozer
way, since slow transition and researching foreign platforms would take
a lot of time and effort.
Round get_space() results in the same way play() rounds the input size.
Some audio APIs do this for various reasons.
This affects only "push" based AOs. Some of these need no change,
because they either do it already right (like ao_openal), or they seem
not to have any such requirements (like ao_pulse).
Needed for the following commit.
Remove the unnecessary indirection through ao fields.
Also fix the inverted result of AOCONTROL_HAS_TEMP_VOLUME. Hopefully the
change is equivalent. But actually, it looks like the old code did it
wrong.
Until now, this was always conflated with uninit. This was ugly, and
also many AOs emulated this manually (or just ignored it). Make draining
an explicit operation, so AOs which support it can provide it, and for
all others generic code will emulate it.
For ao_wasapi, we keep it simple and basically disable the internal
draining implementation (maybe it should be restored later).
Tested on Linux only.
We want to move the AO to its own thread. There's no technical reason
for making the ao struct opaque to do this. But it helps us sleep at
night, because we can control access to shared state better.
Since m_option.h and options.h are extremely often included, a lot of
files have to be changed.
Moving path.c/h to options/ is a bit questionable, but since this is
mainly about access to config files (which are also handled in
options/), it's probably ok.
This comes with two internal AO API changes:
1. ao_driver.play now can take non-interleaved audio. For this purpose,
the data pointer is changed to void **data, where data[0] corresponds to
the pointer in the old API. Also, the len argument as well as the return
value are now in samples, not bytes. "Sample" in this context means the
unit of the smallest possible audio frame, i.e. sample_size * channels.
2. ao_driver.get_space now returns samples instead of bytes. (Similar to
the play function.)
Change all AOs to use the new API.
The AO API as exposed to the rest of the player still uses the old API.
It's emulated in ao.c. This is purely to split the commits changing all
AOs and the commits adding actual support for outputting N-I audio.
No AO can handle these, so it would be a problem if they get added
later, and non-interleaved formats get accepted erroneously. Let them
gracefully fall back to other formats.
Most AOs actually would fall back, but to an unrelated formats. This is
covered by this commit too, and if possible they should pick the
interleaved variant if a non-interleaved format is requested.