Closed pavlos2 closed 3 years ago
Well interestingly, I just wrote the following test: https://github.com/savonet/liquidsoap/blob/master/scripts/tests/BUG403.liq
Does this code makes sense to you? It tracks which sources are played in the rotation.
You could adapt it to track which tracks are played in your rotate and flip a switch to make it unavailable.. Something like:
joyful_ready = ref true
def f(_) =
[("id","playlist_1")]
end
playlist_1 = map_metadata(f,playlist_1)
def f(_) =
[("id","playlist_2")]
end
playlist_2 = map_metadata(f,playlist_2)
def f(_) =
[("id","radio")]
end
radio = map_metadata(f,radio)
Joyful = rotate(weights=[1, 1, 1], [playlist_1, playlist_2, radio])
selected = ref []
def f(m) =
selected := list.cons(m["id"],!selected)
s = list.rev(!selected)
if list.nth(default="",s,0) == "playlist_1" and
list.nth(default="",s,1) == "playlist_2" and
list.nth(default="",s,2) == "radio" then
joyful_ready := false
end
end
Joyful = on_track(f,Joyful)
Joyful = switch([{!joyful_ready}, Joyful)])
radio = switch(track_sensitive=true, [
({ 7w and 0m - 5m }, Joyful ),
({true}, radio)])
Couple of questions:
Joyful
available again?list.length(!selected) == 3
above..Thank you Romain. Unfortunately, I did not manage to get the code run in the AzuraCast environment, I get an error for undefined var at line:
selected := list.cons(m["id"],!selected)
and a syntax error for the line:
Joyful = switch([{!joyful_ready}, Joyful)])
With regards to your questions:
When do you want to make Joyful available again?
Every hour for two days per week.
I suspect you only want to test for list.length(!selected) == 3 above..
Indeed, actually Joyful (as well as three more similar sources) will be the result by rotating more than 30 playlists.
Anyway, isn't it a bit a lengthy solution especially when it comes to rotating a big number of playlists? I suggest a simple operator to stop the rotation after playing and the last playlist in the row would be the simplest approach.
Thanks for the great support.
Hi Romain, allow me to ask again about this issue, is it considered in the coming 1.4.2 release?
Hi @pavlos2. This looks more like a user feature than an issue. The general philosophy of our operators is that "simple things should be simple but complex things should be possible". Here, I think it applies pretty well by letting the user implement their own specific use of the base operator.
In your case, I believe that you need a little more massaging of the API to implement what you need. If I understand correctly, you want:
[s1, s2, s3]
.For 1., assuming your tracks are less than 5
min in length, { 7w and 0m - 5m }
seems like a good condition, It will make sure that the source is picked at the top of the hour until 5 min past. If we do 2. fine, it should be okay to extend the range to more than 5
min.
For 2., cross
can actually be a great tool. You can track the number of tracks and make the source unavailable when it is past 3
. This should do:
tracks_played = ref 0
def count_tracks(_, _, _, _, old, new) =
tracks_played := !tracks_played + 1
sequence([old, new])
end
Joyful = cross(count_tracks, Joyful)
Now, you can refine your switch and do: { 7w and 0m - 5m and !tracks_played < 3 }
tracks_count
is reset to 0
at the top of each hour. I think a simple idea would be to use a repeated call back. Something like this:
def reset_tracks_played() =
if 50m-59m then
tracks_played := 0
end
# Repeat every 5 min
5. * 60.
end
add_timeout(0., reset_tracks_played)
Altogether:
Joyful = rotate(weights=[1, 1, 1], [playlist_1, playlist_2, radio])
tracks_played = ref 0
def count_tracks(_, _, _, _, old, new) =
tracks_played := !tracks_played + 1
sequence([old, new])
end
Joyful = cross(count_tracks, Joyful)
def reset_tracks_played() =
if 50m-59m then
tracks_played := 0
end
# Repeat every 5 min
5. * 60.
end
add_timeout(0., reset_tracks_played)
radio = switch(track_sensitive=true, [
({ 7w and 0m - 15m and !tracks_played > 3 }, Joyful ),
({true}, radio)])
I haven't tested this script but at least it should be syntactically correct this time :-)
Hi @toots. Totally agree with your words "The general philosophy of our operators is that "simple things should be simple but complex things should be possible". Allow me to seize the opportunity at this point and say I think a more detailed manual for Liquidsoap, as well as an online testing environment, would help a lot.
Also, thanks for providing the above solution, although it did not work because of a timer error given by the cross operator I will keep digging into that.
Hi, More on this issue, by running the above suggested code, that is:
Joyful = rotate(weights=[1,1,1,1], [playlist_01_inj, playlist_03_of, playlist_06_sm, radio])
tracks_played = ref 0
def count_tracks(_, _, _, _, old, new) =
tracks_played := !tracks_played + 1
sequence([old, new])
end
Joyful = cross(count_tracks, Joyful)
def reset_tracks_played() =
if 50m-59m then
tracks_played := 0
end
# Repeat every 5 min
5. * 60.
end
add_timeout(0., reset_tracks_played)
radio = switch(track_sensitive=true, [
({ 1w and 0m - 5m and !tracks_played < 3 }, Joyful ),
({true}, radio)])
I get the following nested clocks error:
At line 70 char 8 - line 72 char 17:
Error 11: Cannot unify two nested clocks (cross_7779[cue_cut_7749[],cue_cut_7727[],cue_cut_7717[],cue_cut_7737[],cue_cut_7707[]],
?(3fd4526e0a58:0)[cross_7779[cue_cut_7749[],cue_cut_7727[],cue_cut_7717[],cue_cut_7737[],cue_cut_7707[]]]).
I presume the code provided by @toots is correct, then is it something wrong with AzuraCast?
Hi! What is the definition of radio
? Also, it looks like you should be able to remove it from the rotate
since it is already present as the next choice in the switch
..
Hi Romain! The source radio
is the standard/fallback source and is defined as:
# Standard Playlists
radio = random(id="testing_liquidsoap_standard_playlists", weights=[3, 3, 3], [playlist_default, playlist_01_inj, playlist_03_of])
requests = request.queue(id="testing_liquidsoap_requests")
requests = audio_to_stereo(id="testing_liquidsoap_stereo_requests", requests)
requests = cue_cut(id="testing_liquidsoap_cue_requests", requests)
radio = fallback(id="testing_liquidsoap_requests_fallback", track_sensitive = true, [requests, radio])
The error persists even is if radio
is removed from the rotate operator switch
.
Thanks for the support!
This issue is now fixed. Romain was right the presence of radio
in Joyful
source would cause the nested_clock problem, since radio
it is already present as the next choice in the switch
. Thanks a lot Romain for the hint!
The next challenge on this matter is how to modify the above code so that to include more sources in the switch
operator. For instance:
radio = switch(track_sensitive=true, [
({ 1w and 0m - 5m and !tracks_played < 3 }, Joyful ),
({ 2w and 0m - 5m and !tracks_played < 3 }, Joyful2 ),
({ 3w and 0m - 5m and !tracks_played < 3 }, Joyful3 ),
({true}, radio)])
Thanks for the support!
Hi Romain,
After your remarkable contribution, and of course continuous support, to fix the memory issue I wonder if I can have some further help with the above code you kindly provided back in May. More specific, I need to add more sources (as depicted below) and that produces the fatal error "a source cannot belong to two clocks". I read the online help on Nested Clocks but I am afraid I will need for once more your help. Here is a sample of the code I would like to use:
Joyful = rotate(weights=[1,1,1, ....], [playlist_01_inj, playlist_03_of, playlist_06_sm, ...])
Joyful2 = rotate(weights=[1,1,1, ...], [playlist_01_inj2, playlist_03_of2, playlist_06_sm2, ...])
Joyful3 = rotate(weights=[1,1,1, ...], [playlist_01_inj3, playlist_03_of3, playlist_06_sm3, ...])
tracks_played = ref 0
def count_tracks(_, _, _, _, old, new) =
tracks_played := !tracks_played + 1
sequence([old, new])
end
Joyful = cross(count_tracks, Joyful)
Joyful2 = cross(count_tracks, Joyful2)
Joyful3 = cross(count_tracks, Joyful3)
def reset_tracks_played() =
if 50m-59m then
tracks_played := 0
end
# Repeat every 5 min
5. * 60.
end
add_timeout(0., reset_tracks_played)
radio = switch(track_sensitive=true, [
({ 1w and 0m - 5m and !tracks_played < 3 }, Joyful ),
({ 2w and 0m - 5m and !tracks_played < 3 }, Joyful2 ),
({ 3w and 0m - 5m and !tracks_played < 3 }, Joyful3 ),
({true}, radio)])
Regards, pavlos
Hi! The problem that you are having is that crossfade
needs full control over its child sources because it accelerates them to compute transitions. However, these same sources are also present at top-level via radio
. You should re-organize your script so that you do not use the same sources in the crossfade and in radio
..
Hi Romain! Thanks for the response, I have already tried couple of alterations in the script (mainly changing the name of the sources) after reading the online help on Nested Clocks. Nope, I still get the error "a source cannot belong to two clocks". Could you please help further on this matter?
Hi, can I have some further help on this matter please?
Hi, I'm trying to figure out how to fix the following code so that after playing one random track from playlist_1, one random track from playlist_2, and finally one random track from radio to exit
rotate()
.Thanks in advance!