The error callback can be called before the transition of the sink
state has completed. It therefore needs to wait until the sink has
left init state before reconfiguring it with pa_sink_suspend calls.
Also try to recover from all errors (and log what the error is when
it is not AAUDIO_ERROR_DISCONNECTED).
Instead provide langinfo.h with inline implemention of nl_langinfo()
as a system header.
This avoids linking in libandroid-support.so in some places, and
improves compatibility when building code on-device.
Building against later api levels causes problems such as
CANNOT LINK EXECUTABLE: could not load library "libpulse.so" [...];
caused by could not load library "libpulsecommon-12.2.so" needed by
"libpulse.so"; caused by cannot locate symbol "__register_atfork"
referenced by "libpulsecommon-12.2.so"...
Add a sink module that makes use of the AAudio API, which is
available in Oreo or later.
The sink will have its sample rate and latency configured based on
the info we got with the API. They will also be updated accordingly
when the output device is changed.
To start pulseaudio manually as a daemon, you just need "-D", but
if you set daemonize=yes in daemon.conf, when you want start it
undaemonized, you will need "--daemonize=no".
We don't really need to set enable-shm to no explicitly.
Setting exit-idle-time to -1 may not be as preferred as when it was
when autospawn did not work.
There's no point setting log-target to stderr. auto works fine (or
perhaps even better) for us.
Autospawn needs to use the wrapper we made, otherwise the sles sink
module cannot be loaded.
Also patch caps.c to remove the silly warning that somehow ignores
log-level and log-target to avoid programs like cmus being ruined
when pulse is spawned.
Turns out it's pretty easy to implement. Now the buffer queue will
stop requesting for data once the sink is suspended on idle. No
more power wasted.
Note that it is natural that there would be a bit of extra delay
when resume playback after the sink is suspended. In case it is
wanted to be avoided, make sure the module-suspend-on-idle is not
loaded.
This should work way better than the old code, as it makes use of
the buffer queue callback to do Enqueue(), which might be the only
nice/right way to use OpenSLES on Android. CPU usage is low and
RAM usage seems reasonable. No memory leak noticed. Tested with
mpv on my Oreo phone (wired and Bluetooth).
The latency was chosen base on Bluetooth audio requirement on Oreo.
Shouldn't be hard to make it configurable as a module param in the
future.
The new code has a known downside though, that is it doesn't really
support sink suspension, as in, silence will kept being written
to the audio device even when the sink is suspended, which may have
certain impact to battery time.
It's probably possible to catch the state change of the sink and
notify the buffer queue about it. It's just I don't want to bother
digging further at the moment.