Andre Noll [Sat, 14 Aug 2021 21:14:38 +0000 (23:14 +0200)]
mp4: Clean up membuffer_transfer_from_file().
The buffer pointer can never be NULL, so drop this check. Next, instead
of defining a void * pointer and cast it to char *, use char * directly.
Finally, the cast to unsigned has no effect, so drop it.
Andre Noll [Sat, 14 Aug 2021 20:40:00 +0000 (22:40 +0200)]
mp4: Simplify membuffer_create().
Since para_malloc() never returns NULL, the error state can only be
zero. Use para_calloc(), skip the zero initializations and kill a
pointless local variable.
Andre Noll [Sat, 14 Aug 2021 20:27:12 +0000 (22:27 +0200)]
mp4: Check return value of membuffer_transfer_from_file().
This function calls the ->read() method of the callback, which may
fail. Currently all three callers ignore the return value and rely
on the fact that the membuffer is set to error state, which will be
detected later.
It's easier and clearer to check for errors in the callers and fail
early on read errors. Since the membuffer is useless in the error
case, free it right away in membuffer_transfer_from_file(). Change
the function to return bool instead of unsigned while at it and remove
a pointless cast in one of its callers.
Andre Noll [Sat, 14 Aug 2021 18:53:15 +0000 (20:53 +0200)]
mp4: Drop integer return type from modify_moov().
This function returns either zero or one to indicate success. On
success, a pointer to a buffer and the buffer size are returned. It
is simpler and less redundant to indicate failure by returning a NULL
buffer pointer. Rather than using a void ** argument for the buffer,
let the function return void *.
Andre Noll [Sat, 14 Aug 2021 18:21:51 +0000 (20:21 +0200)]
mp4: Merge mp4_close() and tag_delete().
The latter is only called by the former, and both are short enough.
Don't bother to zero out meta->tags and meta->count because we free
the containing mp4 structure as well.
Andre Noll [Sat, 14 Aug 2021 17:38:21 +0000 (19:38 +0200)]
mp4: Clean up membuffer_write_std_tag().
Remove the check for the compilation flag since we never pass "cpil"
to this function. Remove the flags variable whose value is now always
one. Introduce a variable for the string length instead of calling
strlen() three times, and unify the way comments are formatted.
Andre Noll [Sat, 14 Aug 2021 17:22:17 +0000 (19:22 +0200)]
mp4: Clean up find_standard_meta().
Use ARRAY_SIZE() instead of open-coding it, move the stdmetas array
into the function since it is only used there, and make it const.
Also replace 0 by NULL, since the function returns a pointer, and
remove the pointless comment.
Finally, move the function and the declaration of the stdmeta_entry
structure closer to its single user.
Andre Noll [Sat, 14 Aug 2021 17:15:29 +0000 (19:15 +0200)]
mp4: Simplify create_ilst().
This function contains a lot of overhead which is just dead code
for paraslash since we only care about five standard tags, In
particular, we never write custom tags. Removing the single caller
of membuffer_write_custom_tag() left a whole bunch of other functions
and data structures unused, so these can be removed as well.
Andre Noll [Sat, 14 Aug 2021 17:00:06 +0000 (19:00 +0200)]
mp4: Call metadata structures "meta".
Currently they are called "tags" or "data", both of which are confusing
because struct mp4_metadata has a member called "tags", and "data"
is also used for generic buffers in the various I/O helpers.
Andre Noll [Sat, 14 Aug 2021 15:53:59 +0000 (17:53 +0200)]
mp4: Simplify and speed up metadata editing.
Currently the aac audio format handler first calls mp4_open_meta()
to get the metadata tags, then alters the in-memory structure of the
tags according to the command line options and passes this modified
structure to mp4_meta_update() to rewrite the tags. This latter call
parses the tags again, which is unnecessary overhead.
This patch changes the signature of mp4_meta_update() to accept an
mp4 structure instead of a callback structure and uses that instead
of re-opening the file.
Andre Noll [Fri, 13 Aug 2021 18:51:38 +0000 (20:51 +0200)]
mp4: Simplify and doxify meta tag accessors.
The integer return value is redundant, so get rid of the value
parameter and simplify meta_find_by_name() accordingly. Document that
tag values are allocated on the heap and should be freed by the caller.
Andre Noll [Fri, 13 Aug 2021 18:19:43 +0000 (20:19 +0200)]
mp4: Simplify parse_tag().
We don't care about arbitrarily named tags, and those tags we're
interested in are generally present in form of the standard tags
(ATOM_TITLE, ATOM_ARTIST etc.).
Since we now always call get_metadata_name() to get the string
representation of the tag, we don't need to make a copy any more,
just pass the const pointer directly to tag_add_field().
With this change in place it is obvious that we never pass a NULL or
empty tag name to tag_add_field(), and we don't pass a NULL pointer
for the value argument either, so remove the safety check.
Andre Noll [Wed, 11 Aug 2021 20:52:11 +0000 (22:52 +0200)]
mp4: Rename and simplify set_metadata_name()
This function is an atrocious mess. For one, the naming is confusing
because the function does not set the atom name, it *returns* it.
More importantly, the function defines a static array for no good
reason and then hard-codes the array indices in a large switch
statement.
It's much easier to simply return a pointer to a string literal and
perform the strdup operation in the single caller.
Andre Noll [Wed, 11 Aug 2021 19:45:12 +0000 (21:45 +0200)]
mp4: Use uniform names for callback and mp4 structures.
Currently it's a confusing mess, with callbacks called f, ff, or
stream, where the former two are also used for pointers to struct
mp4. Let's call a spade a spade and use cb everywhere for the callbacks
while f is reserved to denote an mp4 pointer.
Andre Noll [Wed, 11 Aug 2021 19:37:16 +0000 (21:37 +0200)]
mp4: Hide ->read_error.
This does not belong into the callback structure whose fields are
supposed to get initialized by the audio format handler. Move it to
the internal struct mp4 instead, next to the existing error counter.
Andre Noll [Wed, 11 Aug 2021 17:26:00 +0000 (19:26 +0200)]
mp4: Don't parse the esds atom any more.
With the decoder specific config no longer in use, we can simplify
mp4.c further by getting rid of some cryptic and underdocumented code
which no longer does anything useful for us.
Andre Noll [Wed, 11 Aug 2021 17:12:07 +0000 (19:12 +0200)]
mp4: Introduce mp4_is_audio_track().
Currently the aac audio format handler iterates over the tracks
in an mp4 file. For each track it tries to get the audio-specific
configuration by calling mp4_get_decoder_config() and calls into faad
to check whether it is a valid configuration for the aac decoder.
We can simplify all this because the mp4 code already knows the type
of each track, albeit it does not expose this information yet. So
provide the new mp4_is_audio_track() helper and let the aac audio
format handler pick the first track for which this helper returns true.
As an additional benefit, we can remove the now unused
mp4_get_decoder_config().
The old name is misleading because the returned file handle is by no
means opened read-only. In fact we call mp4ff_meta_update() on it,
which alters the file to store the modified metadata.
Andre Noll [Wed, 11 Aug 2021 13:41:37 +0000 (15:41 +0200)]
mp4: Introduce mp4ff_get_duration().
This allows us to get rid of an ugly hack in aac_afh.c where we peeked
at the audio-specific config structure to get the scaling factor which
was needed to compute the duration.
Andre Noll [Tue, 10 Aug 2021 16:57:42 +0000 (18:57 +0200)]
mp4: Remove const qualifier from non-pointer function arguments.
In contrast to the pointer case, it's generally not very interesting
to know whether a function will modify the automatic variable which
corresponds to a non-pointer argument.
Andre Noll [Mon, 9 Aug 2021 22:14:53 +0000 (00:14 +0200)]
mp4: Reduce indentation of create_ilst().
This function contained an indented block for no good reason. No real
change except that a few variables are exposed to the code below the
former block, but this is not a problem.
Andre Noll [Mon, 9 Aug 2021 21:13:35 +0000 (23:13 +0200)]
mp4: Use read/write functions from portable_io.h.
This removes quite a bit of ugly code. In particular, atom_get_size()
is completely unnecessary and can be removed. Since there is no
function in portable_io.h to read a 24 bit integer, we have to add
read_u24_be().
Andre Noll [Mon, 9 Aug 2021 18:27:28 +0000 (20:27 +0200)]
mp4: Further reduce the indentation of mp4ff_parse_tag().
Handle the easy cases first. Again, this patch looks unreviewable,
but it in essence it is only one large block that is shifted to the
left with no other changes.
Andre Noll [Mon, 9 Aug 2021 18:05:10 +0000 (20:05 +0200)]
mp4: Use para_strdup().
Like malloc(), strdup() may fail. The current code does not always
check that. Using the paraslash wrapper avoids the issue and has the
additional benefit that para_strdup(NULL) does not segfault.
Andre Noll [Mon, 9 Aug 2021 17:43:36 +0000 (19:43 +0200)]
mp4: Use para_{c,m}alloc() to allocate memory.
With mp4ff being internal we can afford to just abort if allocations
fail (which is what the para_ wrappers do). This allows us to simplify
the code quite a bit.
The code used to cast the pointer returned from malloc(). This is
unnecessary, so drop these casts.
Andre Noll [Mon, 9 Aug 2021 17:10:46 +0000 (19:10 +0200)]
mp4: Simplify and rename mp4ff_read_sample_getsize().
The new code is much shorter. It is equivalent because the single
caller only checks whether the return value is less or equal then zero,
and does not use the return value in this case.
Andre Noll [Mon, 9 Aug 2021 16:43:44 +0000 (18:43 +0200)]
aac: Move declaration of mp4ff_set_sample_position() to mp4.h.
We used to provide the declaration of mp4ff_set_sample_position()
in aac_afh.c. With the internal mp4.c this is no longer necessary as
we may as well declare the function in mp4.h.
Remove the documentation since it has become stale.
Andre Noll [Sun, 8 Aug 2021 20:09:28 +0000 (22:09 +0200)]
mp4: Make non-public functions static.
It's generally a good thing to reduce the scope to the compilation
unit where possible. Static functions also reduce the number of
symbols and help the compiler to optimize the generated code.
Andre Noll [Thu, 21 Oct 2021 17:09:59 +0000 (19:09 +0200)]
mp4: Wire it in and make it compile cleanly.
This switches to our local copy of libmp4ff. The configure script
now turns on support for the aac audio format even if libmp4ff is
not installed.
Some changes to mp4.c were necessary to silence warnings, most of
which are trivial. The single notably non-trivial change is the missing
initialization of chunk_sample and chunk in mp4ff_chunk_of_sample().
Andre Noll [Sun, 8 Aug 2021 19:13:41 +0000 (21:13 +0200)]
Provide our own copy of libmp4ff.
This library was removed from the faad repository in 2017. This
commit put everything we need from the libmp4ff code base into the
new mp4.c and mp4.h files. All content was taken unmodified from
commit 1cf5a505daf0 of the faad2 repo, the last commit that contains
the library.
The code needs a lot of cleanup and does not compile without warnings.
We commit it as-is to track what exactly has been copied from
libmp4ff. The new mp4.c has not been included into the build system,
however, so this commit has no effect yet.
It is broken because the recipe for the .d files does not honor
CPPFLAGS since we only modify the CPPFLAGS variable for the .o
targets. Adding the corresponding .d targets would be too ugly,
so revert the commit for now until a better solution has been found.
Andre Noll [Mon, 14 Mar 2022 21:28:27 +0000 (22:28 +0100)]
Makefile: Fix compilation after header removal.
When switching from an older git version which still contains some
header file to a newer version where it got removed, a .d file remains
in build/deps which lists the no longer existing header file as a
prerequisite. This causes the build to fail because the prerequisite
cannot be created. The problem can be worked around by removing the
stale .d file, for example by running make clean, but this is no real
fix, and is inefficient.
The root of the matter is that .d files depend on their .c counterpart,
but this dependency is not stated anywhere in the Makefile. Thus, we
need a rule for the .d target with the same prerequisites and the same
recipe as the object file target. GNU make supports multiple targets,
but the feature does not seem to work as advertised, regardless of
whether rules with independent targets or rules with grouped targets
(using the &: separator) are employed. Thus we bite the bullet and
use two separate rules.
We have to add at least one mood to trigger the bug. Since addmood is
a stdin command we must redirect stdin for the para_client command. It
does not hurt to do this for all commands, not just the new one.
Andre Noll [Wed, 16 Mar 2022 18:21:24 +0000 (19:21 +0100)]
Minor log severity adjustments.
Two small changes which improve the error output of para_audiod. The
first makes sure we get a message when hitting ctrl+c when audiod
is running in forground mode. The second decreases the severity of
the log message which is shown when a client connection terminates,
since this is not necessarily an error.
Andre Noll [Wed, 20 Oct 2021 19:13:58 +0000 (21:13 +0200)]
server: Early vss shutdown for command handlers.
Command must communicate with the vss through the shared memory area
(mmd). Deallocating all resources early in the command handler makes
the code more robust and saves some memory.
Andre Noll [Fri, 27 Aug 2021 13:12:34 +0000 (15:12 +0200)]
afh: Limit chunk numbers to 32 bit.
The number of chunks and the chunk offsets are stored in the audio
file table as 32 bit unsigned integers. Thus, chunk numbers and
sizes cannot exceed 2^32 - 1. Make this fact obvious by changing
the corresponding parameters of aac_afh_get_chunk() from size_t or
unsigned long to uint32_t.
Andre Noll [Wed, 9 Mar 2022 22:56:56 +0000 (23:56 +0100)]
audiod: Stop stream immediately when being switched off.
When para_audiod enters off/standby mode, we stop the receiver
but continue to filter and write data already received until the
input queue has drained. This can take several seconds, which may
be annoying.
To stop the stream immediately, stop the writer(s) rather than the
receiver. We still only stop the receiver when the server has paused
or stopped the stream because we don't want to discard any data in
this case.
Andre Noll [Sat, 19 Mar 2022 22:48:18 +0000 (23:48 +0100)]
vss: Reset afhi.chunks_total on eof.
Without this, the server can be crashed by running
para_client nomore # set the nomore flag
# wait for eof
para_client jmp 50 # set the repos flag, clear the next flag
para_client play # boom
The problem is that the command handler of the jmp command checks
afhi.chunks_total to determine if some audio file is currently
open. Since vss_eof() did not reset chunks_total, the command handler
wrongly believes that there is an open audio file, sets the repos
flag and clears the next flag. When streaming is resumed later, the
virtual streaming system attempts to access the chunk table which
was freed earlier in vss_eof().
Andre Noll [Thu, 17 Mar 2022 21:44:11 +0000 (22:44 +0100)]
afs.c: Improve documentation of callback_query.
It had some language issues and focussed too much on details rather than
explaining the big picture. The new text is shorter and should be much easier
to understand.
Andre Noll [Wed, 9 Mar 2022 21:43:26 +0000 (22:43 +0100)]
afs.c: Improve documentation of score table.
The text focussed on implementation details rather than describing the
purpose of the table. It was also slightly incorrect because playlists
also use the score tables, albeit in a much simpler way and without
"Gaussian normal distributions".
Andre Noll [Tue, 15 Mar 2022 20:33:03 +0000 (21:33 +0100)]
attribute.c: De-doxify static functions.
Because static functions don't need doxygen comments. The existing
comments for attribute_close() and attribute_open() did not contain
useful information, so remove these,
Andre Noll [Mon, 14 Mar 2022 18:52:46 +0000 (19:52 +0100)]
afs: Update dummy mood assumptions to reflect the reality.
The code in afs.c assumes that loading the dummy mood always succeeds,
and this is even documented in change_current_mood(). However, this
has never been true because we call into osl library functions which
may fail for various reasons. In particular, if the server is started
without a database the attempt to load the dummy mood fails because
the audio file table does not exist.
The current code was not prepared to handle this case, and does stupid
things like storing the negative error code in *num_admissible and
returning success.
Fix this confusion by adjusting the documentation and letting
activate_mood_or_playlist() fail early. One of its callers,
init_admissible_files(), needs also be adjusted because it asserted
in its error path that the mood which failed to load was not the
dummy mood.
This is a benign bug because the most common way to hit this is
at startup on a fresh install when the database does not exist. In
this case the caller, init_admissible_files(), ignores the negative
num_admissible value.