]> git.tuebingen.mpg.de Git - paraslash.git/log
paraslash.git
18 months agoafs: Replace ->init of afs tables by table operations.
Andre Noll [Tue, 15 Mar 2022 20:59:12 +0000 (21:59 +0100)]
afs: Replace ->init of afs tables by table operations.

This is simpler, avoids the run-time initialization, and allows us
to mark the instances of the operations structures constant. Improve
the documentation a bit while at it.

18 months agoMerge load_playlist() into playlist_open() and simplify.
Andre Noll [Fri, 11 Mar 2022 22:38:13 +0000 (23:38 +0100)]
Merge load_playlist() into playlist_open() and simplify.

They are reasonably small. Remove the weird calling convention with
the PLAYLIST_LOADED error code and the pointless check for the dummy
row because they only obfuscate the code. Moreover, the comment of
load_playlist() is actively misleading because this function is not
a loop callback. Extend the documentation of the combined public
playlist_open() while at it.

The code can be simplified by calling pl_get_def_by_name() rather
than osl_get_row() followed by pl_get_name_and_def_by_row().

18 months agoSimplify row_belongs_to_score_table().
Andre Noll [Thu, 10 Mar 2022 19:27:08 +0000 (20:27 +0100)]
Simplify row_belongs_to_score_table().

This function was over-engineered because only one caller passed a
non-NULL rank pointer without actually using the rank for anything
other than printing it in a log message. So drop the rank parameter
and adjust the callers and the log message accordingly.

Moreover, the function returned int rather than bool to be able to
also return an error code in case the osl lookup function fails. This
should never happen though, because the only possible errors are
invalid row or table pointers, and these indicate a bug. So abort in
this case and let the function return bool.

18 months agoRemove mood.h.
Andre Noll [Fri, 11 Mar 2022 19:49:05 +0000 (20:49 +0100)]
Remove mood.h.

It's too small to be useful. Simply move the three function
declarations to afs.h, next to the playlist related functions.

18 months agoClean up and rename change_current_mood().
Andre Noll [Tue, 8 Mar 2022 17:46:07 +0000 (18:46 +0100)]
Clean up and rename change_current_mood().

Move the code which destroys the current mood to the end of the
function so that we can still return to the old mood if something
goes awry.

To make this work, various functions need to be adjusted to no longer
refer to to afs statistics via the global current_mood pointer. Pass
a pointer to the statistics structure to those.

Also get rid of the local mood pointer variable in favor of ->m of
struct admissible_array.

Rename the function because it is public and deserves the mood_ prefix.

18 months agomood.c: Simplify and rename load_mood().
Andre Noll [Tue, 8 Mar 2022 22:08:23 +0000 (23:08 +0100)]
mood.c: Simplify and rename load_mood().

We first turn the given mood name into a row of the mood table, then
get the mood definition from the row. It's equivalent and much easier
to call mood_get_def_by_name() instead.

Rename the function because init_mood_parser() tells the reader
what the function actually does.

18 months agomood.c: Move struct statistics into struct mood.
Andre Noll [Sun, 20 Mar 2022 18:22:29 +0000 (19:22 +0100)]
mood.c: Move struct statistics into struct mood.

Because it's part of the state of an open mood. Expand and improve
the documentation of struct mood and current_mood while at it, and
kill the pointless return value of update_afs_statistics().

18 months agoafs.c: Improve activate_mood_or_playlist().
Andre Noll [Mon, 7 Mar 2022 19:21:59 +0000 (20:21 +0100)]
afs.c: Improve activate_mood_or_playlist().

Merge the two conditional branches to simplify the code and increase
the event counter to notify the server also in the SIGHUP case. This
is the right thing to do because we did (re)load the mood or playlist.

18 months agoImprove playlist_open().
Andre Noll [Mon, 7 Mar 2022 18:20:07 +0000 (19:20 +0100)]
Improve playlist_open().

It's easier to let playlist_open() fill in the error text than
to do this in the caller. This is also how the counterpart of
playlist_open(), change_current_mood(), is implemented. Drop the
server log message because this error is usually caused by a client
passing a misspelt playlist name.

Fix the documentation of the return value of the function
while at it: It returns the playlist length on success, and
activate_mood_or_playlist(), its single caller in afs.c, depends
on that.

18 months agoblob.c: Don't initialize table pointer in table->init().
Andre Noll [Mon, 14 Mar 2022 22:51:46 +0000 (23:51 +0100)]
blob.c: Don't initialize table pointer in table->init().

This is a global variable which is guaranteed to be zeroed by the
compiler.

18 months agoblob: Constify name argument of blob_get_def_by_name().
Andre Noll [Tue, 8 Mar 2022 22:05:52 +0000 (23:05 +0100)]
blob: Constify name argument of blob_get_def_by_name().

This function does not modify the string, although the char pointer
is used as the ->data pointer of an osl object, which is non-constant.

We need to cast away the const qualifier to avoid a compiler warning,
but that's still better than accepting only non-constant strings,
as this means to put the cast into the callers.

18 months agoRename admissible_file_loop() -> score_loop().
Andre Noll [Tue, 8 Mar 2022 19:47:59 +0000 (20:47 +0100)]
Rename admissible_file_loop() -> score_loop().

The function simply iterates the entries of the score table. The new
name is shorter, more to the point, and indicates that the function
is implemented in score.c.

Streamline the documentation while at it and swap the arguments,
as the reversed order is more natural.

18 months agoRemove get_num_admissible_files().
Andre Noll [Tue, 8 Mar 2022 19:26:34 +0000 (20:26 +0100)]
Remove get_num_admissible_files().

This public function had only one caller outside of score.c and this
caller already knows the number of admissible files because this
number is also stored in the afs statistics structure.

Open-coding the remaining caller in score.c allows us to remove the
public function.

18 months agoDeclare {was,is}_admissible as bools.
Andre Noll [Tue, 8 Mar 2022 23:03:14 +0000 (00:03 +0100)]
Declare {was,is}_admissible as bools.

These are only used as a bool, so change the declarations in mood.c and
score.c accordingly and remove an unnecessary initialization in mood.c.

18 months agoscore.c: Remove event handler.
Andre Noll [Fri, 18 Mar 2022 18:06:28 +0000 (19:06 +0100)]
score.c: Remove event handler.

Event handlers are optional, and the one for the score table did not
do anything, so..

18 months agoscore.c: Merge score_add into score_update().
Andre Noll [Fri, 18 Mar 2022 17:53:47 +0000 (18:53 +0100)]
score.c: Merge score_add into score_update().

The function is simple and has only one caller.

18 months agomood.c: Remove pointless check in reload_current_mood().
Andre Noll [Wed, 9 Mar 2022 20:59:18 +0000 (21:59 +0100)]
mood.c: Remove pointless check in reload_current_mood().

The function gets only called from the event handler, which returns
early without calling reload_current_mood if current_mood and is NULL.

18 months agomood.c: Remove row_is_admissible().
Andre Noll [Tue, 8 Mar 2022 22:55:26 +0000 (23:55 +0100)]
mood.c: Remove row_is_admissible().

The function has become trivial, so open-code the one-liner twice.
Since mp_eval_row() returns bool and never fails, the comment was
misleading and the error checking unnecessary.

18 months agoRemove E_NO_MOOD,
Andre Noll [Tue, 8 Mar 2022 22:50:02 +0000 (23:50 +0100)]
Remove E_NO_MOOD,

row_is_admissible() is never called with a NULL mood pointer.

18 months agoafs.c: Remove enum afs_table_num.
Andre Noll [Tue, 15 Mar 2022 18:09:46 +0000 (19:09 +0100)]
afs.c: Remove enum afs_table_num.

The definition of afs_tables[] does not need this enumeration to
initialize the array and everybody else just needs the number of
elements which can as well be obtained with ARRAY_SIZE.

Since enum values are of type int but ARRAY_SIZE expands to a size_t
value we need an adjustment for a format string in open_afs_tables().

18 months agoattribute.c: Remove struct addatt_event_data().
Andre Noll [Mon, 14 Mar 2022 22:22:58 +0000 (23:22 +0100)]
attribute.c: Remove struct addatt_event_data().

It is passed to afs_event() to tell the table event handlers the
name and bit number of the newly added attribute. However, the only
table which does not ignore attribute add events is the mood table,
and this just reloads the current mood without even looking at the
information passed.

18 months agoscore.c: Remove pointless assignment.
Andre Noll [Mon, 7 Mar 2022 21:38:20 +0000 (22:38 +0100)]
score.c: Remove pointless assignment.

The value is NULL anyway because the score table description was
declared as a global static variable.

18 months agomixer: sleep: Fade out before stopping the stream.
Andre Noll [Tue, 11 Oct 2022 16:30:24 +0000 (18:30 +0200)]
mixer: sleep: Fade out before stopping the stream.

The user is about to fall asleep, so try to make the transition a
bit smoother by fading out to volume zero before stopping the stream.

18 months agomixer: sleep: Cycle audiod on stop.
Andre Noll [Sun, 6 Mar 2022 20:05:09 +0000 (21:05 +0100)]
mixer: sleep: Cycle audiod on stop.

This modifies the sleep command to turn off audiod before sending the
stop command to the server. This way the stream terminates immediately
(on the local machine) rather than when the input queue of the stream
has drained, which may be a several seconds later.

This is important because we are going to set the initial volume but
don't want to change the volume of the stream which is about to end.
Currently this is "solved" by sleeping one second, but this has always
been a hack that never worked well in practice.

In order to be able to send commands to para_audiod we introduce
audioc_cmd() which shares most of the implementation of client_cmd(),
so we make both functions wrappers for the new run() which works for both
command types.

To avoid code duplications we also introduce stop() which does the
equivalent of

para_audioc off
para_client stop
para_audioc on

18 months agomixer: sleep: Add --initial-mood and --initial-delay.
Andre Noll [Sat, 5 Mar 2022 20:04:31 +0000 (21:04 +0100)]
mixer: sleep: Add --initial-mood and --initial-delay.

The new options allow the user to run the sleep subcommand to do the
equivalent of

$ para_client stop
$ # set initial volume
$ para_client select m/initial
$ para_client play
$ sleep $initial_delay
$ para_mixer sleep

Fortunately, the implementation is very simple.

18 months agomixer: sleep: Always set initial volume and channel.
Andre Noll [Sat, 5 Mar 2022 20:03:15 +0000 (21:03 +0100)]
mixer: sleep: Always set initial volume and channel.

It does not hurt to do this unconditionally, and it simplifies
subsequent work.

18 months agomixer: sleep: Improve description of sleep subcommand.
Andre Noll [Sat, 5 Mar 2022 19:08:23 +0000 (20:08 +0100)]
mixer: sleep: Improve description of sleep subcommand.

The first mood to switch to is called fade-out mood rather than
initial mood. Streamline the text a bit while at it.

18 months agonet: De-doxify static functions.
Andre Noll [Sat, 3 Sep 2022 22:54:32 +0000 (00:54 +0200)]
net: De-doxify static functions.

They don't make it into the web doc anyway.

18 months agonet: Refer to correct man page in stringify_port().
Andre Noll [Sat, 3 Sep 2022 22:53:16 +0000 (00:53 +0200)]
net: Refer to correct man page in stringify_port().

The function calls getservbyport(), not getservent().

18 months agonet: Pass true/false instead of 0/1 to makesock().
Andre Noll [Sat, 3 Sep 2022 21:57:54 +0000 (23:57 +0200)]
net: Pass true/false instead of 0/1 to makesock().

The function receives a boolean argument, after all.

18 months agonet: Demote log level of error message in makesock().
Andre Noll [Sun, 20 Mar 2022 18:48:41 +0000 (19:48 +0100)]
net: Demote log level of error message in makesock().

This function has no idea how severe the failure actually is, so log
only with loglevel notice and let the callers be more verbose if this
is a stern error.

The visible result of this change is that audiod no longer prints a
warning every five seconds if the server is not running.

18 months agonet: Rename para_connect_simple() -> para_connect().
Andre Noll [Thu, 10 Mar 2022 23:30:14 +0000 (00:30 +0100)]
net: Rename para_connect_simple() -> para_connect().

We used to have para_connect() at some point (hence the need for the
_simple suffix), but it was removed long ago.

18 months agonet: Make is_valid_ipv{4,6}_address() local to net.c.
Andre Noll [Thu, 10 Mar 2022 22:59:04 +0000 (23:59 +0100)]
net: Make is_valid_ipv{4,6}_address() local to net.c.

These inline functions are only used in net.c, so they do not need
to be declared in net.h. De-doxyfy their documentation because static
functions don't need doxygen comments.

18 months agonet: Remove IPPROTO_DCCP define.
Andre Noll [Thu, 10 Mar 2022 23:48:20 +0000 (00:48 +0100)]
net: Remove IPPROTO_DCCP define.

This macro is defined in the system headers on all moderately new
Linux versions, FreeBSD-13 and NetBSD-9, so our local fallback is
not needed anymore.

18 months agonet: Make single-use macros local.
Andre Noll [Thu, 10 Mar 2022 22:38:01 +0000 (23:38 +0100)]
net: Make single-use macros local.

A few macros are defined in net.h but are only used in a single
C file. Move those to where they are used to make the code easier
to follow.

DCCP_SOCKOPT_RX_CCID is not used at all, so remove that.

18 months agonet: Combine documentation of struct flowopts.
Andre Noll [Thu, 10 Mar 2022 22:19:56 +0000 (23:19 +0100)]
net: Combine documentation of struct flowopts.

It was documented both in net.h and net.c.

18 months agonet: Drop extern keyword of function declarations.
Andre Noll [Thu, 10 Mar 2022 22:09:18 +0000 (23:09 +0100)]
net: Drop extern keyword of function declarations.

It has no effect.

18 months agobuild: Run test-clean on maintainer-clean.
Andre Noll [Wed, 14 Sep 2022 19:04:57 +0000 (21:04 +0200)]
build: Run test-clean on maintainer-clean.

So that not too much stuff piles up below t/.

18 months agoMakefile: Fix compilation after header removal, try #2.
Andre Noll [Mon, 14 Mar 2022 21:28:27 +0000 (22:28 +0100)]
Makefile: Fix compilation after header removal, try #2.

This is a revised version of 3bc858ee0d9b, which got reverted in
f0b8296a0635 because of a flaw related to how CPPFLAGS was handled.

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.

Another issue is that the CC command refers to CFLAGS and CPPFLAGS,
which get modified according to the target. We currently do this
modification only for object files but not for the dependency files,
so this needs to be fixed as well. We make use of make's "call"
function feature to avoid having to duplicate the file names and
patterns.

18 months agoOpen-code find_arg().
Andre Noll [Thu, 25 Aug 2022 14:33:29 +0000 (16:33 +0200)]
Open-code find_arg().

There is only one caller in client_common.c, so open-code the logic
there and get rid of the public function and the unused error code.

18 months agocom_term(): Ignore SIGTERM.
Andre Noll [Thu, 24 Mar 2022 21:06:02 +0000 (22:06 +0100)]
com_term(): Ignore SIGTERM.

Just to shut up valgrind when the server terminates due to the term
command.

18 months agopara_play: Compute the current time more accurately.
Andre Noll [Sun, 13 Mar 2022 19:49:41 +0000 (20:49 +0100)]
para_play: Compute the current time more accurately.

Currently get_play_time() throws away the subsecond part of the
timeval and returns a number in seconds. We can improve on that
by letting the function return milliseconds instead. However, with
milliseconds we must perform multiplications using 64 bit integers
to avoid integer overflows.

This also affects the pause and play commands, which should now
reposition the stream more accurately. It still won't be perfect,
though, because play.c has no way of knowing the number of the chunk
which is currently being decoded.

18 months agoparaslash 0.7.1 v0.7.1
Andre Noll [Mon, 3 Oct 2022 18:52:01 +0000 (20:52 +0200)]
paraslash 0.7.1

18 months agoMerge topic branch t/overflow into master
Andre Noll [Mon, 3 Oct 2022 15:59:56 +0000 (17:59 +0200)]
Merge topic branch t/overflow into master

This series implements a new memory allocation API which checks
for overflows. The first part of the series just renames the main
allocation functions. Later patches in the series implement allocators
which take two size_t arguments (like calloc(3)) and check whether the
multiplication overflows by employing the __builtin_mul_overflow()
primitive supported by gcc and clang. This requires us to bump the
lowest supported gcc and clang version.

* refs/heads/t/overflow:
  build: Compile with -ftrapv.
  string: Introduce arr_zalloc().
  string: Introduce arr_alloc().
  string: Introduce arr_realloc() and check for integer overflow.
  string: Rename para_calloc() -> zalloc().
  string: Rename para_malloc() -> alloc().
  string: Overhaul para_strdup().

18 months agoi9e: Remove \return from documentation of i9e_attach_to_stdout().
Andre Noll [Sun, 25 Sep 2022 21:50:17 +0000 (23:50 +0200)]
i9e: Remove \return from documentation of i9e_attach_to_stdout().

The function returns void.

Fixes: 367daa451bd837c3e267c8385bbc92898f06ecca
18 months agodaemon: Improve documentation of daemon_open_log_or_die().
Andre Noll [Sun, 25 Sep 2022 21:48:47 +0000 (23:48 +0200)]
daemon: Improve documentation of daemon_open_log_or_die().

This function has no return value, so don't use \return.

18 months agoRemove unused error code MOOD_SYNTAX.
Andre Noll [Wed, 14 Sep 2022 18:12:10 +0000 (20:12 +0200)]
Remove unused error code MOOD_SYNTAX.

The error code became unused when version 1 moods were removed.

Fixes: 184ea897a9b446611a9d02315160b6d77c0926fe
19 months agoMerge branch 'refs/heads/t/ll'
Andre Noll [Sun, 18 Sep 2022 14:28:33 +0000 (16:28 +0200)]
Merge branch 'refs/heads/t/ll'

Two little cleanups related to the logging facility and two commits
which add the ll command to para_server and para_audiod.

The merge resulted in a conflict in afs.c due to the earlier merge of
the poll topic branch which replaced all calls to select() by calls
to poll(). The implementation of the ll server command introduced a
new caller of select(), afs_select(), which needs to be replaced by
afs_poll() to resolve the conflict.

* refs/heads/t/ll:
  New server command: ll to change the log level at runtime.
  New audiod command: ll to change the log level at runtime.
  daemon: Kill get_loglevel_by_name().
  server/audiod: Don't parse loglevel argument unnecessarily.

19 months agoMerge branch 'refs/heads/t/poll'
Andre Noll [Sun, 11 Sep 2022 14:34:12 +0000 (16:34 +0200)]
Merge branch 'refs/heads/t/poll'

This series modifies all calls to select(2) to use poll(2) instead in
order to avoid the known shortcomings of the select API, in particular
its limit of at most 1024 file descriptors and the fact that fds above
1023 cannot be monitored with select(2) even if fewer than 1024 fds
are open.

The first patches of the series prepare this switch, converting the
easy cases, hiding select specific data structures such as fd sets,
and adjusting function names and documentation. The crucial commit
is the last one. See its rather verbose log message for details.

* refs/heads/t/poll:
  Switch from select(2) to poll(2).
  Rename ->{pre,post}_select methods to ->{pre,post}_monitor.
  Misc documentation cleanups related to select().
  stdin/stdout: Streamline documentation of {pre,post}_select().
  Consolidate receiver/filter/writer {pre,post}_select() docs.
  Hide implementation of para_fd_set().
  send: Avoid select-specific arguments in {pre,post}_select().
  sched: Introduce sched_{read,write}_ok().
  audiod: Rename handle_connect().
  net: Drop fd_set parameter from para_accept().
  fd: Drop fd_set parameter from read_nonblock() and friends.
  interactive: Avoid select(2) in input_available().
  fd.c: Prefer poll(2) over select(2) for write_ok().
  sched: Use integer value for select timeout.

19 months agoMerge branch 'refs/heads/t/mp4ff'
Andre Noll [Sat, 3 Sep 2022 14:29:10 +0000 (16:29 +0200)]
Merge branch 'refs/heads/t/mp4ff'

This 140 patch behemoth adds a stripped down copy of libmp4ff to the
repo. This has become necessary because the library was dropped from
the faad project.

The series starts with a patch which adds an unmodified copy of the
relevant parts of libmp4ff to the repo. All code is combined in a
single file, mp4.c, which contains approximately 2K lines of code. The
public API is defined in the new mp4.h.

The remaining patches clean up the two new files, simplifying and
removing large parts of it. Some of the patches modify the API,
and those require small changes to the aac audio format handler,
which also becomes simpler due to these changes. The aac decoder,
however, is not touched in this series.

* refs/heads/t/mp4ff: (140 commits)
  mp4: Don't abort on truncated files.
  mp4: Document the purpose of each atom.
  mp4: Doxify the public API.
  mp4: Check for missing metadata also for regular opens.
  mp4: Rename mp4_open_read() to mp4_open().
  mp4: Rename mp4_meta_update() to mp4_update_meta().
  mp4: Simplify mp4_num_samples().
  mp4: Reject files with zero time scale.
  mp4: Assorted trivial cleanups.
  mp4: Remove ->len member of struct mp4_tag.
  mp4: Fix possible memory leak on errors.
  mp4: Return proper types for sample rate and count.
  mp4: Fail early on invalid sample rate or sample count.
  mp4: Remove E_MP4_BAD_CHANNEL_COUNT.
  mp4: Improve mp4_get_sample_size().
  mp4: Make sample number be an unsigned parameter.
  mp4: Check the return value of ->truncate().
  mp4: Make most loop variables unsigned.
  mp4: Replace the five tag value functions by a single one.
  mp4: Provide proper error codes for all errors.
  ...

19 months agoMerge branch 'refs/heads/t/autogen'
Andre Noll [Wed, 31 Aug 2022 13:04:00 +0000 (15:04 +0200)]
Merge branch 'refs/heads/t/autogen'

A single patch which removes everything from autogen.sh except the
autoconf and autoheader commands.

* refs/heads/t/autogen:
  Simplify autogen.sh.

19 months agoSwitch from select(2) to poll(2).
Andre Noll [Sun, 10 Oct 2021 20:18:24 +0000 (22:18 +0200)]
Switch from select(2) to poll(2).

The select(2) API is kind of obsolete because it does not work for
file descriptors greater or equal than 1024, The general advice is
to switch to poll(2), which offers equivalent functionality and does
not suffer from this restriction. This patch implements this switch.

The fd sets of select(2) have one nice feature: One can determine in
O(1) time whether the bit for a given fd is turned on in an fd set.

For poll(2), the monitored file descriptors are organized in an array
of struct pollfd. Without information about the given fd's index in the
pollfd array, one can only perform a linear search which requires O(n)
time, with n being the number of fds being watched. Since this would
have to be done for each fd, the running time becomes quadratic in
the number of monitored fds, which is bad. Keeping the pollfd array
sorted would reduce that to n * log(n) at the cost of additional work
at insert time.

This patch implements a different approach. The scheduler now maintains
an additional array of unsigned integers which map fds to indices
into the pollfd array. This new index array is transparent to the
individual tasks, which still simply pass one or more fds from their
->pre_monitor() method to the scheduler. The length of the index array
equals the highest fd given. This might become prohibitive in theory,
but should not be an issue for the time being.

Care needs to be taken in order to deal with callers which ask for
the readiness of an fd without having called sched_monitor_readfd() or
sched_monitor_writefd() in the ->pre_monitor() step. Before the patch,
thanks to the FD_ZERO() call at the beginning of each iteration of
the scheduler's main loop, both sched_read_ok() and sched_write_ok()
returned false for fds which were not asked to be watched. We need
to keep it this way for a seamless transition.

We achieve this by replacing the FD_ZERO() call by a memset(3) call
which fills the index array with 0xff bytes. Both sched_read_ok() and
sched_write_ok() call the new get_revents() helper, where we check the
fd argument against the allocation sizes of the two arrays. If either
function is called with an fd that was not asked to be monitored in
the ->pre_monitor() step, the checks notice that the index of this
fd, 0xffffffff, is larger than the highest open fd and we return
"not ready for I/O".

Another issue is the case where the same file descriptor is submitted
twice in ->pre_monitor() to check for readiness with respect to both
reading and writing. The code in client_comon.c currently does that.
To keep it working, the scheduler needs to detect this case and re-use
the existing slot in both arrays.

20 months agoRename ->{pre,post}_select methods to ->{pre,post}_monitor.
Andre Noll [Sun, 10 Oct 2021 16:10:09 +0000 (18:10 +0200)]
Rename ->{pre,post}_select methods to ->{pre,post}_monitor.

The word "monitor" is neutral and continues to be correct after the
switch from select(2) to poll(2).

Pure rename, nothing to see here.

20 months agoMisc documentation cleanups related to select().
Andre Noll [Thu, 7 Oct 2021 20:16:09 +0000 (22:16 +0200)]
Misc documentation cleanups related to select().

Assorted comment cleanups which avoid to talk about select(2) and
fd sets. No code changes.

20 months agostdin/stdout: Streamline documentation of {pre,post}_select().
Andre Noll [Thu, 7 Oct 2021 19:22:59 +0000 (21:22 +0200)]
stdin/stdout: Streamline documentation of {pre,post}_select().

Don't state the obvious and avoid talking about fd sets.

20 months agoConsolidate receiver/filter/writer {pre,post}_select() docs.
Andre Noll [Thu, 7 Oct 2021 17:22:47 +0000 (19:22 +0200)]
Consolidate receiver/filter/writer {pre,post}_select() docs.

The documentation of these three ->pre_select() and ->post_select()
methods overlapped quite a bit. Some comments stated general properties
of the sched API which fit better in the documentation of sched.h,
so move these bits there.

Improve the text a bit while at it and avoid talking about select(2)
and fd sets as these are implementation details. Instead, focus on
the general concept of fd monitoring.

Pure comment cleanups, no code changes.

20 months agoHide implementation of para_fd_set().
Andre Noll [Sun, 3 Oct 2021 19:52:02 +0000 (21:52 +0200)]
Hide implementation of para_fd_set().

This preparatory patch for replacing select() renames para_fd_set()
to sched_fd_set(), moves it to sched.c and makes it static. All
users are modified to call either of the two new public functions
sched_monitor_{read,write}fd() which take a pointer to struct sched
rather than an fd set pointer.

20 months agosend: Avoid select-specific arguments in {pre,post}_select().
Andre Noll [Sun, 3 Oct 2021 19:37:40 +0000 (21:37 +0200)]
send: Avoid select-specific arguments in {pre,post}_select().

Just pass a pointer to struct sched instead of the fd sets. Since
two of the prototypes declared in send.h now refer to this structure,
sched.h must be included before send.h.

The udp sender implements neither ->pre_select() nor ->post_select(),
so we only need to fix the order in which send.h and sched.h are
included.

20 months agosched: Introduce sched_{read,write}_ok().
Andre Noll [Thu, 30 Sep 2021 20:35:10 +0000 (22:35 +0200)]
sched: Introduce sched_{read,write}_ok().

Two trivial wrappers for FD_ISSET() which hide the fact that we're
still using the select(2) API.

20 months agoaudiod: Rename handle_connect().
Andre Noll [Tue, 12 Oct 2021 17:50:53 +0000 (19:50 +0200)]
audiod: Rename handle_connect().

Now that it has the same signature as para_server's handle_connect(),
doxygen gets confused and complains as follows:

audiod_command.c:359: warning: argument 'accept_fd' of command @param is not found in the argument list of handle_connect(int fd)

This is a false positive, but since "handle_connect" is not a very
descriptive name for a public function in the first place, let's
rename it.

20 months agonet: Drop fd_set parameter from para_accept().
Andre Noll [Thu, 30 Sep 2021 20:18:43 +0000 (22:18 +0200)]
net: Drop fd_set parameter from para_accept().

As for read_nonblock(), the parameter is dispensable because it is
only used for an optimization to avoid a system call. Get rid of it
because it hinders the conversion from select(2) to poll(2).

20 months agofd: Drop fd_set parameter from read_nonblock() and friends.
Andre Noll [Thu, 30 Sep 2021 19:46:58 +0000 (21:46 +0200)]
fd: Drop fd_set parameter from read_nonblock() and friends.

This parameter is not necessary because its only purpose is to
avoid the readv(2) system call in case it would likely return EAGAIN
because we just called select(2) which reported that there is no data
to read. Since the parameter is an obstacle for the conversion of
the code base from select(2) to poll(2), get rid of it for the time
being. If needed we can add back an equivalent optimization which
checks for POLLIN after the conversion.

20 months agointeractive: Avoid select(2) in input_available().
Andre Noll [Wed, 29 Sep 2021 20:29:51 +0000 (22:29 +0200)]
interactive: Avoid select(2) in input_available().

In analogy to write_ok(), introduce read_ok() which uses poll(2)
rather than select(2). To avoid duplications, abstract out the common
code to the new xpoll() helper.

We could avoid the timeout parameter of xpoll() at this point because
both callers call it with a zero timeout (causing poll() to return
immediately), but later patches introduce other callers which specify
non-zero timeouts.

20 months agofd.c: Prefer poll(2) over select(2) for write_ok().
Andre Noll [Wed, 29 Sep 2021 20:07:13 +0000 (22:07 +0200)]
fd.c: Prefer poll(2) over select(2) for write_ok().

This is easy to do and avoids the old and well-known shortcomings of
select(2). See

http://0pointer.net/blog/file-descriptor-limits.html

for a short discussion, or the references in the log message of commit
e4a403876d2c of the man-pages repository.

The linux poll manpage says:

On some other UNIX systems, poll() can fail with the error EAGAIN if
the system fails to allocate kernel-internal resources, rather than
ENOMEM as Linux does. POSIX permits this behavior. Portable programs
may wish to check for EAGAIN and loop, just as with EINTR.

We do not follow this approach since failing the call in the out of
memory case seems to be the right thing to do while busy looping
without trying to free memory between the calls is not likely to
help. Also, looping on EAGAIN would be inconsistent since in the
OOM case the code would fail on Linux but loop on those other UNIX
systems. To be consistent, one must check for both EAGAIN and ENOMEM.

20 months agosched: Use integer value for select timeout.
Andre Noll [Fri, 24 Sep 2021 16:11:06 +0000 (18:11 +0200)]
sched: Use integer value for select timeout.

This modifies the public struct sched so that users pass in the
default timeout as an integer value in milliseconds rather than
a struct timeval. This simplifies the code a little and eases the
transition from select(2) to poll(2) because poll(2) also takes a
plain integer for the timeout.

Since para_select() of fd.c now calls ms2tv() to convert the timeout
back to a struct timeval, all executables which link with fd.o must
also link with time.o. This was not the case for para_mixer and
para_audioc, so configure.ac needs to be adjusted accordingly.

20 months agopara_play: Avoid invalid time display on pause.
Andre Noll [Wed, 27 Jul 2022 13:27:14 +0000 (15:27 +0200)]
para_play: Avoid invalid time display on pause.

When para_play enters pause mode, playback is stopped by notifying
the writer node, causing it to terminate in the next iteration of the
main loop. Until then the play time is computed incorrectly because
we add the running time of the moribund writer node to the start time
computed from the *new* start chunk set in com_pause().

Fortunately, the fix is simple. We just need to enqueue a reposition
request in the same way the ff and jmp commands do.

20 months agoMerge branch 'maint'
Andre Noll [Sun, 21 Aug 2022 15:16:32 +0000 (17:16 +0200)]
Merge branch 'maint'

Two fixes for para_play.

20 months agoi9e: Fix invalid key handling.
Andre Noll [Mon, 25 Jul 2022 22:08:43 +0000 (00:08 +0200)]
i9e: Fix invalid key handling.

If an unmapped key is pressed repeatedly, we store the key sequence in
a 32 byte buffer until there is no more space left in the buffer. Then
we terminate the process with

para_play: interactive.c:304: i9e_post_monitor: Assertion `len < sizeof(i9ep->key_sequence) - 1' failed.

This is not a nice way to deal with invalid input, so be a bit more
graceful and discard the buffer when it is full or when there is no
further input available at the moment.

20 months agoi9e: Fix braino in i9e_post_select().
Andre Noll [Mon, 25 Jul 2022 21:20:11 +0000 (23:20 +0200)]
i9e: Fix braino in i9e_post_select().

Due to this bug we mishandled the case where the read() returns zero
to indicate EOF. In this case we stuffed a random character instead
of shutting down the i9e task.

20 months agobuild: Compile with -ftrapv.
Andre Noll [Tue, 26 Oct 2021 17:11:02 +0000 (19:11 +0200)]
build: Compile with -ftrapv.

This causes signed overflow to raise an exception. The option is
supported on the lowest gcc version we support, so we don't bother
to check by calling cc-option() in Makefile.real.

20 months agostring: Introduce arr_zalloc().
Andre Noll [Wed, 27 Oct 2021 18:40:07 +0000 (20:40 +0200)]
string: Introduce arr_zalloc().

Adjust all callers which pass a product of two integers to zalloc()
to call the new function instead and reduce zalloc() to a one-line
wrapper.

20 months agostring: Introduce arr_alloc().
Andre Noll [Wed, 27 Oct 2021 18:40:04 +0000 (20:40 +0200)]
string: Introduce arr_alloc().

Change all callers of alloc() which pass a product of two integers as
the allocation size to call the new function instead. This function
aborts if the multiplication overflows. With arr_alloc() in place,
alloc() reduces to a trivial wrapper which calls new arr_alloc()
with the first argument equal to one.

20 months agostring: Introduce arr_realloc() and check for integer overflow.
Andre Noll [Wed, 27 Oct 2021 16:11:41 +0000 (18:11 +0200)]
string: Introduce arr_realloc() and check for integer overflow.

Use __builtin_mul_overflow() for the check. This builtin was introduced
in gcc-5, so we need to bump the lowest supported version.

Re-implement para_realloc() as a trivial wrapper for arr_realloc()
to simplify and to avoid duplicating the size check.

20 months agostring: Rename para_calloc() -> zalloc().
Andre Noll [Tue, 9 Nov 2021 17:41:17 +0000 (18:41 +0100)]
string: Rename para_calloc() -> zalloc().

Reword the documentation a bit since the function has never been a
wrapper for calloc(3). No code changes.

20 months agostring: Rename para_malloc() -> alloc().
Andre Noll [Tue, 26 Oct 2021 18:22:49 +0000 (20:22 +0200)]
string: Rename para_malloc() -> alloc().

Just because it's shorter and matches the naming of the new allocators
we are about to introduce. The bulk of this patch was created with

sed -i 's/para_malloc/alloc/g' *.c *.h yy/mp.y

20 months agostring: Overhaul para_strdup().
Andre Noll [Wed, 27 Oct 2021 17:14:03 +0000 (19:14 +0200)]
string: Overhaul para_strdup().

We don't need to print an error message because it will be clear what
has happened when the assertion triggers.

Reword the documentation and mention that the memory allocated by
this function must be freed by the caller.

20 months agoaudiod: Demote severity level of command errors.
Andre Noll [Sun, 17 Jul 2022 19:33:24 +0000 (21:33 +0200)]
audiod: Demote severity level of command errors.

handle_connect() returning negative is a normal condition which
occurs, for example, when the user specifies an invalid argument to
a command. Therefore the "notice" severity level is more appropriate
than the current "error" severity.

20 months agoaudiod: Fix time diff warning log message.
Andre Noll [Mon, 13 Jun 2022 18:31:23 +0000 (20:31 +0200)]
audiod: Fix time diff warning log message.

The format string contains %lu to print a long unsigned, but we
possibly multiply the value with -1, which can lead to output like

Jun 13 13:36:37 baader (3) compute_time_diff: time diff jump: 4294808018ms

Fix this by replacing the multiplication with an additional format
string directive to print the leading +/- explicitly. This is easy
since we already have the sign in a variable, and it avoids any
integer conversion/overflow issues.

21 months agoNew server command: ll to change the log level at runtime.
Andre Noll [Tue, 19 Oct 2021 19:41:45 +0000 (21:41 +0200)]
New server command: ll to change the log level at runtime.

This makes use of the infrastructure introduced in the previous patch.
However, the implementation of the ll command for para_server is more
involved than its audiod counterpart because in the server case we
have to tell two different processes (server and afs) to change their
log level while the calling process, the command handler, does not
need to set the loglevel because it is about to exit anyway.

For the inter-process communication we introduce a new field in the
mmd shared memory area so that command handlers can read the current
value or set a new value. The log level propagates from there via
daemon_set_loglevel() to the server and afs processes during each
iteration of the scheduler loop where para_log() will pick it up to
set the log level threshold for subsequent log events.

The si command handler currently refers to the argument of the
--loglevel server option to include the log level in its output. With
dynamic log levels this no longer works because it always prints the
value from the command line or the config file rather than the run
time log level. Since the new ll command also prints the loglevel
when it is executed with no arguments, we simply remove this line
from the si output and hope that nobody cares.

The si command handler was the last user of the ENUM_STRING_VAL macro
in command.c. Removing the macro also allows us to make CMD_PTR local
to server.c and to remove the lopsub definitions of the server suite
from command.c. However, we still include the lopsub definitions of
the server *command* suite (server_cmd.lsg.h) of course.

We let any authenticated user run the command with no arguments to
report the current loglevel but require full privileges to change
the loglevel. Thus, the check for sufficient privileges needs to be
performed in the command handler.

21 months agoNew audiod command: ll to change the log level at runtime.
Andre Noll [Tue, 19 Oct 2021 20:19:25 +0000 (22:19 +0200)]
New audiod command: ll to change the log level at runtime.

The new public daemon_get_loglevel() is needed in the zero argument
case. Otherwise, the ll command handler parses the argument and calls
daemon_set_loglevel().

The lopsub stanza for the subcommand is stored in a separate file
which is currently only included by the lopsub suite for para_audiod,
but will be included as well by the server suite.

For similar reasons we implement the completer as a generic public
function, i9e_ll_completer(), although it only has one caller in
audioc.c. Another caller follows when the ll server command is added.

21 months agodaemon: Kill get_loglevel_by_name().
Andre Noll [Tue, 19 Oct 2021 19:44:14 +0000 (21:44 +0200)]
daemon: Kill get_loglevel_by_name().

Open-code the logic in daemon_set_log_color_or_die() and get the
values from the new SEVERTIES macro rather than duplicating the
severity list in get_loglevel_by_name().

The SEVERTIES macro will turn out to be handy for the ll subcommands of
para_server and para_audiod which are introduced in subsequent commits.

21 months agoserver/audiod: Don't parse loglevel argument unnecessarily.
Andre Noll [Tue, 19 Oct 2021 19:28:30 +0000 (21:28 +0200)]
server/audiod: Don't parse loglevel argument unnecessarily.

Currently the severity string (debug, info, etc.) given to --loglevel
is parsed twice: Once by lopsub, which returns the loglevel as the
index into the array of severity strings. We turn this index into a
string and pass the string to daemon_set_loglevel() which parses the
string again to turn it back into a log level value (which happens
to coincide with the index value).

Clean this up by letting daemon_set_loglevel() receive a log level
value rather than a severity string. This also allows us to remove
the now unused ENUM_STRING_VAL() macro from audiod.c.

21 months agomp4: Don't abort on truncated files.
Andre Noll [Wed, 29 Jun 2022 11:38:02 +0000 (13:38 +0200)]
mp4: Don't abort on truncated files.

If the source file got truncated it may happen that a chunk cannot
be read because the computed file offset is beyond EOF. Currently,
aac_afh_get_chunk() aborts in this case because we assert that the
file offset is within range. Return a proper error code instead and
also change aac_get_file_info() to bail out if aac_afh_get_chunk()
returns negative.

21 months agomp4: Document the purpose of each atom.
Andre Noll [Mon, 30 Aug 2021 16:57:15 +0000 (18:57 +0200)]
mp4: Document the purpose of each atom.

This gives the reader a rough idea about the atoms we care about.

21 months agomp4: Doxify the public API.
Andre Noll [Sat, 28 Aug 2021 20:12:41 +0000 (22:12 +0200)]
mp4: Doxify the public API.

This adds doxygen comments to all public functions of the mp4 API
and to the macros and enumerations of mp4.c.

21 months agomp4: Check for missing metadata also for regular opens.
Andre Noll [Sat, 28 Aug 2021 19:15:35 +0000 (21:15 +0200)]
mp4: Check for missing metadata also for regular opens.

Since we allow to update the metadata of a file handle returned by
mp4_open(), we should check for both types of opens that the file
actually contains the udta, meta and ilst atoms.

21 months agomp4: Rename mp4_open_read() to mp4_open().
Andre Noll [Sat, 28 Aug 2021 18:53:23 +0000 (20:53 +0200)]
mp4: Rename mp4_open_read() to mp4_open().

The function may be called with the intention to update the meta tags
later by calling mp4_update_meta(), albeit mp4_open_meta() is cheaper
if the caller only wants to modify the metadata. The old name is thus
slightly misleading, and it's longer.

21 months agomp4: Rename mp4_meta_update() to mp4_update_meta().
Andre Noll [Sat, 28 Aug 2021 18:50:13 +0000 (20:50 +0200)]
mp4: Rename mp4_meta_update() to mp4_update_meta().

Just to be consistent with mp4_open_meta() and friends.

21 months agomp4: Simplify mp4_num_samples().
Andre Noll [Sat, 28 Aug 2021 18:29:06 +0000 (20:29 +0200)]
mp4: Simplify mp4_num_samples().

We don't need to iterate over the entries of the stts_sample_count
array because the number stored in the stsz_sample_count field should
be identical to the sum of the sample counts.

21 months agomp4: Reject files with zero time scale.
Andre Noll [Sat, 28 Aug 2021 16:35:18 +0000 (18:35 +0200)]
mp4: Reject files with zero time scale.

A value of zero indicates a corrupt mp4 file or a missing mdhd
atom. This is fatal because we need to divide by the time scale to
compute the duration of the audio track.

This patch modifies mp4_open_read() to check the value at open time
and fail the operation rather than allowing the open to succeed and
checking the value in mp4_get_duration(),

Only regular opens are affected since we don't look at the mdhd atom
for metadata opens.

21 months agomp4: Assorted trivial cleanups.
Andre Noll [Sat, 28 Aug 2021 14:40:19 +0000 (16:40 +0200)]
mp4: Assorted trivial cleanups.

Avoid C++ comments, use int rather than int32_t as the standard return
type, kill a pointless cast and use plain unsigned rather than uint32_t
for the number of tag items.

21 months agomp4: Remove ->len member of struct mp4_tag.
Andre Noll [Sat, 28 Aug 2021 13:18:41 +0000 (15:18 +0200)]
mp4: Remove ->len member of struct mp4_tag.

It is set but never read.

21 months agomp4: Fix possible memory leak on errors.
Andre Noll [Fri, 27 Aug 2021 17:20:42 +0000 (19:20 +0200)]
mp4: Fix possible memory leak on errors.

If the sanity checks in open_file() fail, we free the mp4 structure
but not the various tables and metadata items we might already have
allocated at this point.

Fix this by calling mp4_close() instead of freeing the mp4 struct
directly. We have to move mp4_close() above open_file() to avoid a
forward declaration.

21 months agomp4: Return proper types for sample rate and count.
Andre Noll [Fri, 27 Aug 2021 17:10:51 +0000 (19:10 +0200)]
mp4: Return proper types for sample rate and count.

The sample rate and the number of samples are stored as 16-bit/32-bit
unsigned integers in the mp4 file, so let mp4_get_sample_rate()
and mp4_num_samples() return these types.

21 months agomp4: Fail early on invalid sample rate or sample count.
Andre Noll [Fri, 27 Aug 2021 17:06:11 +0000 (19:06 +0200)]
mp4: Fail early on invalid sample rate or sample count.

If the sample rate or the sample count happen to be zero, we should
fail the open rather than return success and let the caller deal with
it. This patch moves the corresponding sanity checks from aac_afh.c
to mp4_open_read() of mp4.c. The sample rate is always read while
sample count is skipped for metadata-only opens. So the first check
belongs to the common open_file() while the second check needs to go
to mp4_open_read().

22 months agomp4: Remove E_MP4_BAD_CHANNEL_COUNT.
Andre Noll [Fri, 27 Aug 2021 14:07:24 +0000 (16:07 +0200)]
mp4: Remove E_MP4_BAD_CHANNEL_COUNT.

If the mp4 file does not contain an m4a atom, the channel
count stays at zero and open_file() returns -E_MP4_TRACK in this
case. So the check in aac_afh.c for a non-positive return value from
mp4_get_channel_count() can never trigger. Replace the check by an
assertion and remove the error code.

Also, let mp4_get_channel_count() return uint16_t as the number of
channels is stored as an unsigned 16 bit number in the mp4 file.

22 months agomp4: Improve mp4_get_sample_size().
Andre Noll [Fri, 27 Aug 2021 13:38:25 +0000 (15:38 +0200)]
mp4: Improve mp4_get_sample_size().

Use an unsigned type for the sample number and check that the passed
number is within range. Since the function can fail now, let it return
int and return the sample size via an additional pointer argument.

22 months agomp4: Make sample number be an unsigned parameter.
Andre Noll [Fri, 27 Aug 2021 13:23:24 +0000 (15:23 +0200)]
mp4: Make sample number be an unsigned parameter.

There is no reason to convert the 32-bit unsigned paraslash chunk
number into a signed quantity here, as sample numbers are also stored
as 32 bit unsigned in the mp4 file.

22 months agomp4: Check the return value of ->truncate().
Andre Noll [Thu, 26 Aug 2021 20:11:40 +0000 (22:11 +0200)]
mp4: Check the return value of ->truncate().

This callback is implemented as a simple wrapper for the ftruncate()
system call, which can fail for a number of reasons. Currently the
callback returns unsigned and the return value is ignored. Fortunately,
this is easy to fix.

22 months agomp4: Make most loop variables unsigned.
Andre Noll [Thu, 26 Aug 2021 19:39:31 +0000 (21:39 +0200)]
mp4: Make most loop variables unsigned.

If the loop variable iterates from zero to some number stored in a
variable of unsigned type, the loop variable should be of the same
unsigned type. This was not always the case, and if it was, the loop
variable was sometimes called i, which is confusing because i usually
indicates a signed quantity.

Quoting Andrew Morton:

Doing "unsigned i;" is an act of insane vandalism, punishable by
spending five additional years coding in fortran.