Age | Commit message (Collapse) | Author |
|
|
|
This class had slightly confusing semantics and the added weirdness
doesn't seem worth it just so we can say "." instead of "->" when
iterating over a vector of NNRPs.
This patch replaces NonnullRefPtrVector<T> with Vector<NNRP<T>>.
|
|
|
|
As usual, this removes many unused includes and moves used includes
further down the chain.
|
|
|
|
This also removes a few cases where the respective header wasn't
actually required to be included.
|
|
|
|
clang-format sure has some interesting opinions about where to put a
method call that comes after a lambda. :thonk:
|
|
These instances were detected by searching for files that include
stdlib.h, but don't match the regex:
\\b(_abort|abort|abs|aligned_alloc|arc4random|arc4random_buf|arc4random_
uniform|atexit|atof|atoi|atol|atoll|bsearch|calloc|clearenv|div|div_t|ex
it|_Exit|EXIT_FAILURE|EXIT_SUCCESS|free|getenv|getprogname|grantpt|labs|
ldiv|ldiv_t|llabs|lldiv|lldiv_t|malloc|malloc_good_size|malloc_size|mble
n|mbstowcs|mbtowc|mkdtemp|mkstemp|mkstemps|mktemp|posix_memalign|posix_o
penpt|ptsname|ptsname_r|putenv|qsort|qsort_r|rand|RAND_MAX|random|reallo
c|realpath|secure_getenv|serenity_dump_malloc_stats|serenity_setenv|sete
nv|setprogname|srand|srandom|strtod|strtof|strtol|strtold|strtoll|strtou
l|strtoull|system|unlockpt|unsetenv|wcstombs|wctomb)\\b
(Without the linebreaks.)
This regex is pessimistic, so there might be more files that don't
actually use anything from the stdlib.
In theory, one might use LibCPP to detect things like this
automatically, but let's do this one step after another.
|
|
Because IPC is used very little in audio server communication, a
ping-pong method like WindowServer is neither a good nor a reliable way
of detecting detached audio clients. AudioServer was previously doing
nothing to detect the kinds of clients that never closed their
connection properly, which happens e.g. when a program is force-closed.
Due to reference-counting cycles, the associated client connection
queues were being kept alive. However, the is_open method of local
sockets reliably detects all kinds of disconnected sockets and can
easily be adapted for this use case. With this fix, we no longer get
"Audio client can't keep up" spam on improperly disconnected clients,
and the client queues don't fill up indefinitely, reducing processing
and memory usage in AudioServer.
|
|
The buffer provided to `OutputMemoryStream` was made a private class
member. This is because there is no reason to re-create it in every
iteration. Also, the logic becomes more symmetric with
`m_zero_filled_buffer` which is already a class member.
|
|
Initialize the `AudioServer::Mixer::m_zero_filled_buffer` to zero. The
garbage memory inside that buffer was causing a glitch sound when the
user was toggling the mute checkbox or was moving the volume slider on
and off zero. Glitching was more obvious if the toggling was happening
without any sound being played in parallel.
In addition to that, the `m_zero_filled_buffer` turned to `const` since
there is no intention to modify its content.
|
|
When volume is zero it is not necessary to go through the mixing loop.
The zero-filled buffer can be written directly to the device, instead,
similar to the muted case. Tested by using the piano app and the main
volume control.
|
|
Otherwise, we end up propagating those dependencies into targets that
link against that library, which creates unnecessary link-time
dependencies.
Also included are changes to readd now missing dependencies to tools
that actually need them.
|
|
|
|
We previously put the generated headers in SOURCES, which did not mark
them as GENERATED (and did not produce a proper dependency).
This commit moves all generated headers into GENERATED_SOURCES, and
removes useless header SOURCES.
|
|
LLVM 15 now warns (and thus errors) about this, and there is really no
point in keeping them.
|
|
Each of these strings would previously rely on StringView's char const*
constructor overload, which would call __builtin_strlen on the string.
Since we now have operator ""sv, we can replace these with much simpler
versions. This opens the door to being able to remove
StringView(char const*).
No functional changes.
|
|
|
|
This removes some old cruft to refactor the hardware buffer-related
datastructures into depending on a single constant, which determines the
number of samples per hardware buffer that the audio server mixes. This
is set to 1024 as before, so there are no functional changes.
|
|
|
|
The file is now renamed to Queue.h, and the Resampler APIs with
LegacyBuffer are also removed. These changes look large because nobody
actually needs Buffer.h (or Queue.h). It was mostly transitive
dependencies on the massive list of includes in that header, which are
now almost all gone. Instead, we include common things like Sample.h
directly, which should give faster compile times as very few files
actually need Queue.h.
|
|
We aren't actually using these for anything, and the spaceship operator
requires ``<compare>`` from the STL, which we'd rather not include.
|
|
This fixes a bunch of audio clients that don't actually play audio.
|
|
Previously, we were sending Buffers to the server whenever we had new
audio data for it. This meant that for every audio enqueue action, we
needed to create a new shared memory anonymous buffer, send that
buffer's file descriptor over IPC (+recfd on the other side) and then
map the buffer into the audio server's memory to be able to play it.
This was fine for sending large chunks of audio data, like when playing
existing audio files. However, in the future we want to move to
real-time audio in some applications like Piano. This means that the
size of buffers that are sent need to be very small, as just the size of
a buffer itself is part of the audio latency. If we were to try
real-time audio with the existing system, we would run into problems
really quickly. Dealing with a continuous stream of new anonymous files
like the current audio system is rather expensive, as we need Kernel
help in multiple places. Additionally, every enqueue incurs an IPC call,
which are not optimized for >1000 calls/second (which would be needed
for real-time audio with buffer sizes of ~40 samples). So a fundamental
change in how we handle audio sending in userspace is necessary.
This commit moves the audio sending system onto a shared single producer
circular queue (SSPCQ) (introduced with one of the previous commits).
This queue is intended to live in shared memory and be accessed by
multiple processes at the same time. It was specifically written to
support the audio sending case, so e.g. it only supports a single
producer (the audio client). Now, audio sending follows these general
steps:
- The audio client connects to the audio server.
- The audio client creates a SSPCQ in shared memory.
- The audio client sends the SSPCQ's file descriptor to the audio server
with the set_buffer() IPC call.
- The audio server receives the SSPCQ and maps it.
- The audio client signals start of playback with start_playback().
- At the same time:
- The audio client writes its audio data into the shared-memory queue.
- The audio server reads audio data from the shared-memory queue(s).
Both sides have additional before-queue/after-queue buffers, depending
on the exact application.
- Pausing playback is just an IPC call, nothing happens to the buffer
except that the server stops reading from it until playback is
resumed.
- Muting has nothing to do with whether audio data is read or not.
- When the connection closes, the queues are unmapped on both sides.
This should already improve audio playback performance in a bunch of
places.
Implementation & commit notes:
- Audio loaders don't create LegacyBuffers anymore. LegacyBuffer is kept
for WavLoader, see previous commit message.
- Most intra-process audio data passing is done with FixedArray<Sample>
or Vector<Sample>.
- Improvements to most audio-enqueuing applications. (If necessary I can
try to extract some of the aplay improvements.)
- New APIs on LibAudio/ClientConnection which allows non-realtime
applications to enqueue audio in big chunks like before.
- Removal of status APIs from the audio server connection for
information that can be directly obtained from the shared queue.
- Split the pause playback API into two APIs with more intuitive names.
I know this is a large commit, and you can kinda tell from the commit
message. It's basically impossible to break this up without hacks, so
please forgive me. These are some of the best changes to the audio
subsystem and I hope that that makes up for this :yaktangle: commit.
:yakring:
|
|
With the following change in how we send audio, the old Buffer type is
not really needed anymore. However, moving WavLoader to the new system
is a bit more involved and out of the scope of this PR. Therefore, we
need to keep Buffer around, but to make it clear that it's the old
buffer type which will be removed soon, we rename it to LegacyBuffer.
Most of the users will be gone after the next commit anyways.
|
|
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#cother-other-default-operation-rules
"The compiler is more likely to get the default semantics right and
you cannot implement these functions better than the compiler."
|
|
This might still be too much, but it's better than what we had before.
|
|
This was done with CLion's automatic rename feature and with:
find . -name ClientConnection.h
| rename 's/ClientConnection\.h/ConnectionFromClient.h/'
find . -name ClientConnection.cpp
| rename 's/ClientConnection\.cpp/ConnectionFromClient.cpp/'
|
|
Currently this method always succeeds, but that won't be true once we
switch to the Core::Stream API. :^)
Some of these places would ideally show an error message to the user,
since failure to save a file is significant, but let's not get
distracted right now.
|
|
I've attempted to handle the errors gracefully where it was clear how to
do so, and simple, but a lot of this was just adding
`release_value_but_fixme_should_propagate_errors()` in places.
|
|
For now, just use the first audio channel in the /dev/audio directory.
In the future we can add support for watching and loading other channels
so we can route audio to multiple sound cards on the system.
|
|
This change unfortunately cannot be atomically made without a single
commit changing everything.
Most of the important changes are in LibIPC/Connection.cpp,
LibIPC/ServerConnection.cpp and LibCore/LocalServer.cpp.
The notable changes are:
- IPCCompiler now generates the decode and decode_message functions such
that they take a Core::Stream::LocalSocket instead of the socket fd.
- IPC::Decoder now uses the receive_fd method of LocalSocket instead of
doing system calls directly on the fd.
- IPC::ConnectionBase and related classes now use the Stream API
functions.
- IPC::ServerConnection no longer constructs the socket itself; instead,
a convenience macro, IPC_CLIENT_CONNECTION, is used in place of
C_OBJECT and will generate a static try_create factory function for
the ServerConnection subclass. The subclass is now responsible for
passing the socket constructed in this function to its
ServerConnection base; the socket is passed as the first argument to
the constructor (as a NonnullOwnPtr<Core::Stream::LocalServer>) before
any other arguments.
- The functionality regarding taking over sockets from SystemServer has
been moved to LibIPC/SystemServerTakeover.cpp. The Core::LocalSocket
implementation of this functionality hasn't been deleted due to my
intention of removing this class in the near future and to reduce
noise on this (already quite noisy) PR.
|
|
|
|
|
|
This new state will allow us to ignore muted clients when computing the
'output mix' in the Mixer.
|
|
When computing the 'output mix', the Mixer iterates over all client
audio streams and computes a 'mixed sample' taking into account mainly
the client's volume.
This new member and methods will allow us to ignore a muted client
when computing that mix.
|
|
The 'muted' methods referred to the 'main mix muted' but it wasn't
really clear from the name. This change will be useful because in the
next commit, a 'self muted' state will be added to each audio client
connection.
|
|
The `m_remaining_samples` attribute was underflowing at the end of an
audio stream. This fix guards against the underflow by only decrementing
the attribute when it is greater than zero.
I found this bug because the SoundPlayer userland application was not
correctly detecting when an audio stream was completed. This was
happening because the remaining samples being returned from the client
audio connection was an underflowed 16 bit integer instead of zero.
|
|
This allows us to use TRY() or MUST() when calling it.
|
|
These ones all manage their storage internally, whereas the WebContent
and ImageDecoder ones require the caller to manage their lifetime. This
distinction is not obvious to the user without looking through the code,
so an API that makes this clearer would be nice.
|
|
|
|
Everyone used this hook in the same way: immediately accept() on the
socket and then do something with the newly accepted fd.
This patch simplifies the hook by having LocalServer do the accepting
automatically.
|
|
Previously, a libc-like out-of-line error information was used in the
loader and its plugins. Now, all functions that may fail to do their job
return some sort of Result. The universally-used error type ist the new
LoaderError, which can contain information about the general error
category (such as file format, I/O, unimplemented features), an error
description, and location information, such as file index or sample
index.
Additionally, the loader plugins try to do as little work as possible in
their constructors. Right after being constructed, a user should call
initialize() and check the errors returned from there. (This is done
transparently by Loader itself.) If a constructor caused an error, the
call to initialize should check and return it immediately.
This opportunity was used to rework a lot of the internal error
propagation in both loader classes, especially FlacLoader. Therefore, a
couple of other refactorings may have sneaked in as well.
The adoption of LibAudio users is minimal. Piano's adoption is not
important, as the code will receive major refactoring in the near future
anyways. SoundPlayer's adoption is also less important, as changes to
refactor it are in the works as well. aplay's adoption is the best and
may serve as an example for other users. It also includes new buffering
behavior.
Buffer also gets some attention, making it OOM-safe and thereby also
propagating its errors to the user.
|
|
Executing `asctl set r 96000` no longer results in weird sample rates
being set on the audio devices. SB16 checks for a sample rate between 1
and 44100 Hz, while AC97 implements double-rate support which allows
sample rates between 8kHz and 96kHZ.
|
|
|
|
This fixes all current code smells, bugs and issues reported by
SonarCloud static analysis. Other issues are almost exclusively false
positives. This makes much code clearer, and some minor benefits in
performance or bug evasion may be gained.
|
|
"Frame" is an MPEG term, which is not only unintuitive but also
overloaded with different meaning by other codecs (e.g. FLAC).
Therefore, use the standard term Sample for the central audio structure.
The class is also extracted to its own file, because it's becoming quite
large. Bundling these two changes means not distributing similar
modifications (changing names and paths) across commits.
Co-authored-by: kleines Filmröllchen <malu.bertsch@gmail.com>
|
|
Derivatives of Core::Object should be constructed through
ClassName::construct(), to avoid handling ref-counted objects with
refcount zero. Fixing the visibility means that misuses like this are
more difficult.
This commit is separate from the other Servives changes because it
required additional adaption of the code. Note that the old code did
precisely what these changes try to prevent: Create and handle a
ref-counted object with a refcount of zero.
|
|
Previously, AudioServer would deadlock when trying to play another audio
stream, i.e. creating a queue. The m_pending_cond condition was used
improperly, and the condition wait now happens independently of querying
the pending queue for new clients if the mixer is running.
To make the mixer's concurrency-safety code more readable, the use of
raw POSIX mutex and condition syscalls is replaced with Threading::Mutex
and Threading::ConditionVariable.
|