### Description
Previously the `now` macro used the current time. This is a bit
confusing for autoloading playlists with dynamic smart blocks, as you
have to think about when autoloading happens. This just makes the
autoload datetime be the show start datetime.
**This is a new feature**:
Yes
**I have updated the documentation to reflect these changes**:
Yes
### Testing Notes
**What I did:**
I started up libretime, created an autoloading playlist with a dynamic
block set for one hour ahead. I then created a show with the autoloading
playlist one hour ahead of now and saw that it autoloaded properly and
that the hour matched the show start hour and not the current hour. I
also verified that the now functionality was not changed when not
autoloading by using the preview tracks button on the dynamic smart
block.
**How you can replicate my testing:**
See `What I did` section.
### **Links**
_Issues links or other related resources. Use the line Closes:
#bug_number to
link a bug in the issue tracker._
### Description
Not all forward auth solutions use a comma for group seperator.
**This is a new feature**:
Yes
**I have updated the documentation to reflect these changes**:
Yes
### **Links**
[Authentik uses `|` so may as well make the group separator
configurable](https://docs.goauthentik.io/docs/add-secure-apps/providers/proxy/)
### Description
The playout exchange was changed to `fanout` without migrating the
previous `direct` exchange. This cause issues during upgrades, such as:
```
amqp.exceptions.PreconditionFailed: Exchange.declare: (406) PRECONDITION_FAILED - inequivalent arg 'type' for exchange 'airtime-pypo' in vhost '/libretime': received 'fanout' but current is 'direct'
```
This is documented upstream in
https://www.rabbitmq.com/docs/queues#property-equivalence
This change provides an upgrade path by renaming the exchange, and leave
the old exchange behind. Loosing messages is not a concern for the
playout queue.
### Testing Notes
- Checkout version `4.4.0`
- Run `make dev`
- Checkout 9e55d3bb6f2fa0f9a4dc858359a99e9d50c826a4
- Run `make dev`
- See the exception in playout: `docker compose logs -f playout`
- Checkout this PR
- Run `make dev`
- See playout fine working.
### **Links**
https://github.com/libretime/libretime/pull/3161
### Description
Currently, only one service can listen to libretime schedule change
events. This change allows for as many services as desired to listen for
schedule change events.
**This is a new feature**:
Yes
**I have updated the documentation to reflect these changes**:
No, as this seems like the obvious default
### Testing Notes
**What I did:**
I created 2 playout blocks, connected them both to the fanout queue and
saw that they could all connect and receive schedule change events at
the same time.
**How you can replicate my testing:**
See testing notes
### Description
When generating a show that contains a playlist with dynamic blocks, the
show will be incorrectly under scheduled because the fade time was added
onto the total track length. Fade should not add time to an overall
track length as then it wouldn't be a fade.
**This is a new feature**:
No
**I have updated the documentation to reflect these changes**:
No, none needed.
### Testing Notes
**What I did:**
I created a playlist with 3 dynamic blocks:
1. 10 minute length dynamic block
2. 1 item dynamic block
3. fill rest of show dynamic block
I then created a show with the defined auto loading playlist. I then saw
that on auto-load the show was not under scheduled.
**How you can replicate my testing:**
See testing notes
Co-authored-by: Kyle Robbertze <paddatrapper@users.noreply.github.com>
### Description
The `now{}` macro for criteria filtering used UTC rather than station
timezone leading to confusing results.
**This is a new feature**:
No
**I have updated the documentation to reflect these changes**:
Yes
### Testing Notes
**What I did:**
I named a track the current date and hour, and used the date macro to
try to select it. It failed, I then implemented this fix and saw that
the track was selected.
**How you can replicate my testing:**
See what I did.
### **Links**
None
### Description
Added support for previewing FLAC files in the web interface, provided
in #509 by marmotte32 on Github in the comments for this issue.
I have tested this against a script-installed copy of 4.2.0, and FLAC
preview is working, although auto-play isn't. I haven't tested to
confirm if this behavior matches MP3 and OGG uploads.
**This is a new feature**:
_Do the changes in this PR implement a new feature?_
**I have updated the documentation to reflect these changes**:
No changes needed; this bug is a missing file format in preview, and it
requires no updates to the documentation.
### Testing Notes
**What I did:**
I installed a LibreTime 4.2.0 system using the default installation
script against a fully-updated, brand new Debian 11 system. I logged
into the web interface, uploaded some FLAC files, and attempted to
preview them. They failed to preview.
I then replaced the preview_jplayer.js file with the contents in this PR
and then refreshed the page. I was able to preview the FLAC files and
hear the results in my local browser audio output.
**How you can replicate my testing:**
Perform the same steps above, or replace the same file in the
libretime_legacy_1 docker image to see the same results.
### **Links**
Closes: #509
---------
Co-authored-by: Kyle Robbertze <kyle@paddatrapper.com>
### Description
The existing implementation for exporting playout logs to a CSV file
incorporates a very simplified CSV format. Some aspects of the complete
[RFC](https://www.rfc-editor.org/rfc/rfc4180) are missing, such as
escaping of quotes, and quoting of fields that contain certain
characters. This is problematic for common office spreadsheet tools, and
practically, anything else. Many radio stations rely on this
functionality to work well for exporting playout data, for example, in
order to compile data for reporting requirements.
**This is a new feature**:
The changes in this PR add quoting of fields containing a comma, as well
as those containing a CR/LF. It also escapes quotes by doubling them.
I'm not sure it makes CSVexport.js completely RFC 4180 compliant, but it
is much closer than it was.
**I have updated the documentation to reflect these changes**:
I don't think there are any documentation changes necessary; this is
probably expected behavior for anyone trying to use the CSV exporter.
### Testing Notes
**What I did:**
To validate this, I did a clean install of Debian, cloned from the
official libretime repo, and applied the code as a patch to the
installer. I then proceeded with the install and then loaded a database
from a running system (so that I had some playout data to test with). I
then performed the playout history export and examined the resulting CSV
file and after seeing previously problematic fields properly quoted, was
convinced it looked the way I expected. I loaded the csv file into
Libreoffice Calc and did not see any errors.
**How you can replicate my testing:**
See "What I did" above, basically run the patch after cloning the
installer from the repo. You could also apply the changes to a running
system by applying the patch to the file:
/usr/share/libretime/legacy/public/js/libs/CSVexport.js
Be sure to clear your browser cache and do a hard reload of the web
interface, before re-testing.
### **Links**
Closes: #2477
### Description
Having a global intro and outro playlist in settings is not very
flexible for special programming. This adds an override intro/outro
playlist per show. If it is not set, the global one is used. also it's
ignored if there's no autloading at all.
**I have updated the documentation to reflect these changes**:
Yes
### Testing Notes
**What I did:**
Schedule 2 shows, one without defining custom lists, one with defining
custom lists. one hour before the show starts it should be populated
correctly. If you define a global list it shojuld be replaced with the
per-show list.
---------
Co-authored-by: Thomas Göttgens <tgoettgens@mail.com>
### Description
When running a radio station it is generally a good idea to reduce dead
air time. The current algorithm for adding tracks to a block/show can
leave a lot of dead air time at the end as it doesn't use a very good
algorithm. Adding tracks to a show until it is full while making it as
full as possible is a well known problem in computer science. It is the
[Subset Sum Problem](https://en.wikipedia.org/wiki/Subset_sum_problem).
This PR implements a Randomized Greedy with Local Improvement (RGLI)
approximation solution for the Subset Sum Problem. The new algorithm is
only used when sort type is random and overflow is not enabled and there
is no limit on the number of tracks that can be used.
**This is a new feature**:
Improvement on an existing feature.
**I have not updated the documentation to reflect these changes**:
I did not update the documentation because the current scheduling
algorithm is not currently documented and its existing features have not
changed.
### Testing Notes
**What I did:**
I first attempted a fully polynomial time approximation scheme solution,
however it is really bad at finding good solutions for high density
values and can kinda slow the more tracks/time you have. So I instead
implemented an RGLI which is O(nlogn) and has been giving much better
results.
I implemented the solution in a separate project and tested it and timed
the values with a normal distribution of 500 songs with a mean of 3
minutes and a standard deviation of 1 minute. With a show size of 1 hour
the algorithm took around 10-15 ms to run. When adjusting the block size
and track size the algorithm still was pretty quick to run. Am going to
be testing on an instance with lots of tracks later, will update PR when
I have done that.
**How you can replicate my testing:**
_How can the reviewer validate this PR?_
### **Links**
Closes#3018
### Description
Add File Name and Size to the metadata editor screen, and added a File
Name column to the tracks data table.
**This is a new feature**:
Yes
**I have updated the documentation to reflect these changes**:
No, just some simple UI additions so no documentation needed.
### Testing Notes
**What I did:**
I uploaded some tracks, clicked on edit, and saw that the filename and
size showed up at the top. I also went out to the tracks view and added
the File Name column and saw that the filename displayed properly.
**How you can replicate my testing:**
Do what I did
### **Links**
Fixes#3053
### Description
It is good to have a deterministic order when doing explicit file
sorting. This sorts by filename when last played time is null. I would
expect filename to be the next sort after last played time in case of a
tie, and was surprised to find it was not explicit. It should not break
any existing use cases.
**This is a new feature**:
Kind of?
**I have updated the documentation to reflect these changes**:
I did not update any documentation as this way seems like the logical
expected way to do the sort.
### Testing Notes
**What I did:**
I loaded up some tracks into a local libretime instance, let some of
them play, and tested that all the old sorts worked as before as well as
tracks getting sorted by filepath in case of a last played time
### Description
The filename criteria searched the full file path and as such does not
work as expected.
**This is a new feature**:
No
**I have updated the documentation to reflect these changes**:
No docs changes are required as this is fixing a bug to make things work
as expected and documented.
### Testing Notes
**What I did:**
I uploaded some files, and tested that the file name criteria worked as
expected.
**How you can replicate my testing:**
Spin up the stack, upload some files and make sure the filename criteria
works as expected.
### Description
It is useful to be able to automatically filter tracks to a certain date
or day when scheduling tracks for playback. This adds the ability to do
just that in any string filter with the `date{format}` macro.
Closes: #3012
### Description
In the existing logic of `retrieveMediaFiles`, the time remaining in
show is calculated incorrectly in some scenarios. Each time a duration
is subtracted from `showLimit`, it is not the duration of the files just
added, but instead the length of all files scheduled. This can cause
cases where a smart block set to "time remaining in show" fails to
completely fill the program.
For example, given a 30 minute show, and a playlist like follows:
1. a 5 minute track
2. another 5 minute track
3. smart block, set to time remaining in show
When item 1 is added, `showLimit` is reduced by 5 minutes as expected.
When item 2 is added, `showLimit` is reduced by 10 minutes (as both
items 1 and 2 are counted). As a result, the smart block is only run to
fill 15 minutes, leaving 5 minutes unfilled.
This PR resolves this issue, by recalculating `showLimit` from the
original duration rather than subtracting from a running total.
This change not does implement a new feature and should not require any
changes to documentation.
### Testing Notes
**What I did:**
- On a dev environment, set up a playlist as described above.
- Before applying this PR, created a show and scheduled playlist, and
confirmed issue was reproducible
- Applied PR and repeated, and confirmed show was filled completely.
Also repeated this testing with sample data from our production
instance.
Here is a sample schedule of the "before" case with sample data, showing
the issue

The smartblock that scheduled the music is set to allow last track to
overflow, but 3m55s was left unscheduled.
Using the same playlist and same track library, here is a sample
schedule after the PR applied:

As expected, the show is fully scheduled with the last track
overflowing.
Additionally, I've applied this PR as a hot fix to our production
instance, where it has been running for a week without issue.
Also performed spot tests of playlists without smart blocks, smart
blocks scheduled directly (not in playlists) and autoloading playlists,
with no change in behaviour observed as a result of this change.
**How you can replicate my testing:**
Same test steps as I followed should be able to reproduce issue &
validate fix on any instance.
### **Links**
Not directly related to issue fixed by #3019, but also addresses the
issue of dead air left at end of blocks.
Co-authored-by: Kyle Robbertze <paddatrapper@users.noreply.github.com>
When calling DELETE "/rest/media/<id>" the call fails with 'unknown error'
if it's not within a GUI session. The StoredFile delete method checks
for user permissions regardless of if a user is even known.
### Description
Build and use the schedule events only in playout, the events generated
by legacy are not used anymore.
This ensure that we don't have to maintain 2 different implementation in
2 different languages. We still need the php function to run to make
sure the side effects of this function are executed (filling the
schedule in the DB).
A visual cue point editor in the track editor view. This view displays the track as a waveform and allows you to set where the in- and out-cue points are set. These cue points determine the start and end points of the track.
---------
Co-authored-by: Thomas Göttgens <tgoettgens@mail.com>
Co-authored-by: Kyle Robbertze <paddatrapper@users.noreply.github.com>
### Description
Fixes#2939
The zend form validation was not performed, only a custom method to
validate the code was used. This merge both validation, and leverage the
Zend form validation framework.
Also allow updating the track type code from the track type form.
Related to #2955
Since moving to an indexed track_type model for 3.0, the constraint of the code being immutable is no longer
valid, since it's not used as index anymore. This commit removes the readonly flag from that form field.
### Description
Some combination of preload/postload and autoloding playlists with
smartblocks generate massively overbooked shows that clutter up the
interface. This addition performs a 'trim overbooked' after filling up
the autoload list, and does the same as pushing the 'trim overbooked'
button in the UI.
### Testing Notes
Define an autoloading playlist of 2 hours and schedule it for a one hour
show. Without patch, you'll get entries for 2 hours, with the patch, you
only get one hour and a 'overboarding' orange entry at most.
---------
Co-authored-by: Kyle Robbertze <paddatrapper@users.noreply.github.com>
Co-authored-by: Thomas Göttgens <tgoettgens@mail.com>
Co-authored-by: jo <ljonas@riseup.net>
### Description
Many people don't need the public page and use libretime purely for
playout management. This adds the ability to have libretime publicly
available but only present the login page to the user.
**I have updated the documentation to reflect these changes**:
no, but i will add documentation if this PR is accepted.
### Testing Notes
**What I did:**
Toggle the new ceckbox on the general settings, log out and back in and
check behaviour.
note: this may have conflicts with the trim overbooked PR since the
toggle sits in the same place. If both are accepted this needs to be
formatted nicely :-)
---------
Co-authored-by: Thomas Göttgens <tgoettgens@mail.com>
Co-authored-by: Jonas L. <jooola@users.noreply.github.com>
Co-authored-by: Kyle Robbertze <paddatrapper@users.noreply.github.com>
Co-authored-by: jo <ljonas@riseup.net>
### Description
lot of streams forbid
http://libretime.example.org/preference/stream-setting to open (max=4)
this patch prevent the crash by displaying an error message and truncate
streamcount to 4.
Co-authored-by: Kyle Robbertze <paddatrapper@users.noreply.github.com>
### Description
The Player on the dashbaord does not correctly play an AAC stream. The
rewritng logic only takes into account the ogg format. Add rewriting
from aac to m4a in the javascript calls so the player works.
**This is a new feature**:
AAC output currently only works with replacing liquidsoap, so
technically this is a new feature.
**I have updated the documentation to reflect these changes**:
The dashboard player is not documented. The player widget works with AAC
streams already.
### Testing Notes
**What I did:**
Swapped liquidsoap and reconfigured the default mp3 stream as AAC
**How you can replicate my testing:**
on ubuntu focal, drop in the upstream liquidsoap deb to enable aac, then
configure the secondary output to use 128kbit aac instead of mp3.
Restart the target, login to the dashboard and open the dashboard
player. Both streams from the dropdown should work.
---------
Co-authored-by: Thomas Göttgens <tgoettgens@mail.com>
Co-authored-by: Jonas L <jooola@users.noreply.github.com>
### Description
Add hardware configuration to liquidsoap so that users may
set hardware output in config.yml.
---------
Co-authored-by: jo <ljonas@riseup.net>
BREAKING CHANGE: The default system output
(`stream.outputs.system[].kind`) changed from `alsa` to `pulseaudio`.
Make sure to update your configuration file if you rely on the default
system output.
Closes#2542
BREAKING CHANGE: The `general.secret_key` configuration field is now
required. Make sure to update your configuration file and add a secret
key.
Closes#2426
### Description
Closes#2798
COALESCE last played null values with date -infinity, to ensure newly
added files are found by the last played smart block criteria.
* fix(deps): update dependency friendsofphp/php-cs-fixer to <3.41.2
* style: format files using php-cs-fixer
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: jo <ljonas@riseup.net>