def notify(m) #current_media_id := string_of(m['schedule_table_id']) command = "/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --data='#{!pypo_data}' --media-id=#{m['schedule_table_id']} &" log(command) system(command) end def notify_stream(m) json_str = string.replace(pattern="\n",(fun (s) -> ""), json_of(m)) #if a string has a single apostrophe in it, let's comment it out by ending the string before right before it #escaping the apostrophe, and then starting a new string right after it. This is why we use 3 apostrophes. json_str = string.replace(pattern="'",(fun (s) -> "'\''"), json_str) command = "/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --webstream='#{json_str}' --media-id=#{!current_dyn_id} &" log(command) system(command) end # A function applied to each metadata chunk def append_title(m) = log("Using stream_format #{!stream_metadata_type}") if !stream_metadata_type == 1 then [("title", "#{!show_name} - #{m['artist']} - #{m['title']}")] elsif !stream_metadata_type == 2 then [("title", "#{!station_name} - #{!show_name}")] else [("title", "#{m['artist']} - #{m['title']}")] end end def crossfade(s) #duration is automatically overwritten by metadata fields passed in #with audio s = fade.in(type="log", duration=0., s) s = fade.out(type="log", duration=0., s) fader = fun (a,b) -> add(normalize=false,[b,a]) cross(fader,s) end def transition(a,b) = log("transition called...") add(normalize=false, [ sequence([ blank(duration=0.01), fade.initial(duration=!default_dj_fade, b) ]), fade.final(duration=!default_dj_fade, a) ]) end # we need this function for special transition case(from default to queue) # we don't want the trasition fade to have effect on the first song that would # be played siwtching out of the default(silent) source def transition_default(a,b) = log("transition called...") if !just_switched then just_switched := false add(normalize=false, [ sequence([ blank(duration=0.01), fade.initial(duration=!default_dj_fade, b) ]), fade.final(duration=!default_dj_fade, a) ]) else just_switched := false b end end # Define a transition that fades out the # old source, adds a single, and then # plays the new source def to_live(old,new) = # Fade out old source old = fade.final(old) # Compose this in sequence with # the new source sequence([old,new]) end def output_to(output_type, type, bitrate, host, port, pass, mount_point, url, description, genre, user, s, stream, connected, name, channels) = source = ref s def on_error(msg) connected := "false" system("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --error='#{msg}' --stream-id=#{stream} --time=#{!time} &") log("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --error='#{msg}' --stream-id=#{stream} --time=#{!time} &") 5. end def on_connect() connected := "true" system("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --connect --stream-id=#{stream} --time=#{!time} &") log("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --connect --stream-id=#{stream} --time=#{!time} &") end stereo = (channels == "stereo") if output_type == "icecast" then user_ref = ref user if user == "" then user_ref := "source" end output_mono = output.icecast(host = host, port = port, password = pass, mount = mount_point, fallible = true, url = url, description = description, name = name, genre = genre, user = !user_ref, on_error = on_error, on_connect = on_connect) output_stereo = output.icecast(host = host, port = port, password = pass, mount = mount_point, fallible = true, url = url, description = description, name = name, genre = genre, user = !user_ref, on_error = on_error, on_connect = on_connect) if type == "mp3" then if bitrate == 24 then if stereo then ignore(output_stereo(%mp3(bitrate = 24, stereo = true), !source)) else ignore(output_mono(%mp3(bitrate = 24, stereo = false), mean(!source))) end elsif bitrate == 32 then if stereo then ignore(output_stereo(%mp3(bitrate = 32, stereo = true), !source)) else ignore(output_mono(%mp3(bitrate = 32, stereo = false), mean(!source))) end elsif bitrate == 48 then if stereo then ignore(output_stereo(%mp3(bitrate = 48, stereo = true), !source)) else ignore(output_mono(%mp3(bitrate = 48, stereo = false), mean(!source))) end elsif bitrate == 64 then if stereo then ignore(output_stereo(%mp3(bitrate = 64, stereo = true), !source)) else ignore(output_mono(%mp3(bitrate = 64, stereo = false), mean(!source))) end elsif bitrate == 96 then if stereo then ignore(output_stereo(%mp3(bitrate = 96, stereo = true), !source)) else ignore(output_mono(%mp3(bitrate = 96, stereo = false), mean(!source))) end elsif bitrate == 128 then if stereo then ignore(output_stereo(%mp3(bitrate = 128, stereo = true), !source)) else ignore(output_mono(%mp3(bitrate = 128, stereo = false), mean(!source))) end elsif bitrate == 160 then if stereo then ignore(output_stereo(%mp3(bitrate = 160, stereo = true), !source)) else ignore(output_mono(%mp3(bitrate = 160, stereo = false), mean(!source))) end elsif bitrate == 192 then if stereo then ignore(output_stereo(%mp3(bitrate = 192, stereo = true), !source)) else ignore(output_mono(%mp3(bitrate = 192, stereo = false), mean(!source))) end elsif bitrate == 224 then if stereo then ignore(output_stereo(%mp3(bitrate = 224, stereo = true), !source)) else ignore(output_mono(%mp3(bitrate = 224, stereo = false), mean(!source))) end elsif bitrate == 256 then if stereo then ignore(output_stereo(%mp3(bitrate = 256, stereo = true), !source)) else ignore(output_mono(%mp3(bitrate = 256, stereo = false), mean(!source))) end elsif bitrate == 320 then if stereo then ignore(output_stereo(%mp3(bitrate = 320, stereo = true), !source)) else ignore(output_mono(%mp3(bitrate = 320, stereo = false), mean(!source))) end end else if not icecast_vorbis_metadata then source := add(normalize=false, [amplify(0.00001, noise()), !source]) end if bitrate == 24 or bitrate == 32 or bitrate == 48 then if stereo then ignore(output_stereo(%vorbis(quality=-0.1, channels = 2), !source)) else ignore(output_mono(%vorbis(quality=-0.1, channels = 1), mean(!source))) end elsif bitrate == 64 then if stereo then ignore(output_stereo(%vorbis(quality=0, channels = 2), !source)) else ignore(output_mono(%vorbis(quality=0, channels = 1), mean(!source))) end elsif bitrate == 96 then if stereo then ignore(output_stereo(%vorbis(quality=0.2, channels = 2), !source)) else ignore(output_mono(%vorbis(quality=0.2, channels = 1), mean(!source))) end elsif bitrate == 128 then if stereo then ignore(output_stereo(%vorbis(quality=0.4, channels = 2), !source)) else ignore(output_mono(%vorbis(quality=0.4, channels = 1), mean(!source))) end elsif bitrate == 160 then if stereo then ignore(output_stereo(%vorbis(quality=0.5, channels = 2), !source)) else ignore(output_mono(%vorbis(quality=0.5, channels = 1), mean(!source))) end elsif bitrate == 192 then if stereo then ignore(output_stereo(%vorbis(quality=0.6, channels = 2), !source)) else ignore(output_mono(%vorbis(quality=0.6, channels = 1), mean(!source))) end elsif bitrate == 224 then if stereo then ignore(output_stereo(%vorbis(quality=0.7, channels = 2), !source)) else ignore(output_mono(%vorbis(quality=0.7, channels = 1), mean(!source))) end elsif bitrate == 256 then if stereo then ignore(output_stereo(%vorbis(quality=0.8, channels = 2), !source)) else ignore(output_mono(%vorbis(quality=0.8, channels = 1), mean(!source))) end elsif bitrate == 320 then if stereo then ignore(output_stereo(%vorbis(quality=0.9, channels = 2), !source)) else ignore(output_mono(%vorbis(quality=0.9, channels = 1), mean(!source))) end end end else user_ref = ref user if user == "" then user_ref := "source" end description_ref = ref description if description == "" then description_ref := "N/A" end genre_ref = ref genre if genre == "" then genre_ref := "N/A" end url_ref = ref url if url == "" then url_ref := "N/A" end output.shoutcast_mono = output.shoutcast(id = "shoutcast_stream_#{stream}", host = host, port = port, password = pass, fallible = true, url = !url_ref, genre = !genre_ref, name = !description_ref, user = !user_ref, on_error = on_error, on_connect = on_connect) output.shoutcast_stereo = output.shoutcast(id = "shoutcast_stream_#{stream}", host = host, port = port, password = pass, fallible = true, url = !url_ref, genre = !genre_ref, name = !description_ref, user = !user_ref, on_error = on_error, on_connect = on_connect) if bitrate == 24 then if stereo then ignore(output.shoutcast_stereo(%mp3(bitrate = 24, stereo = true), !source)) else ignore(output.shoutcast_mono(%mp3(bitrate = 24, stereo = false), mean(!source))) end elsif bitrate == 32 then if stereo then ignore(output.shoutcast_stereo(%mp3(bitrate = 32, stereo = true), !source)) else ignore(output.shoutcast_mono(%mp3(bitrate = 32, stereo = false), mean(!source))) end elsif bitrate == 48 then if stereo then ignore(output.shoutcast_stereo(%mp3(bitrate = 48, stereo = true), !source)) else ignore(output.shoutcast_mono(%mp3(bitrate = 48, stereo = false), mean(!source))) end elsif bitrate == 64 then if stereo then ignore(output.shoutcast_stereo(%mp3(bitrate = 64, stereo = true), !source)) else ignore(output.shoutcast_mono(%mp3(bitrate = 64, stereo = false), mean(!source))) end elsif bitrate == 96 then if stereo then ignore(output.shoutcast_stereo(%mp3(bitrate = 96, stereo = true), !source)) else ignore(output.shoutcast_mono(%mp3(bitrate = 96, stereo = false), mean(!source))) end elsif bitrate == 128 then if stereo then ignore(output.shoutcast_stereo(%mp3(bitrate = 128, stereo = true), !source)) else ignore(output.shoutcast_mono(%mp3(bitrate = 128, stereo = false), mean(!source))) end elsif bitrate == 160 then if stereo then ignore(output.shoutcast_stereo(%mp3(bitrate = 160, stereo = true), !source)) else ignore(output.shoutcast_mono(%mp3(bitrate = 160, stereo = false), mean(!source))) end elsif bitrate == 192 then if stereo then ignore(output.shoutcast_stereo(%mp3(bitrate = 192, stereo = true), !source)) else ignore(output.shoutcast_mono(%mp3(bitrate = 192, stereo = false), mean(!source))) end elsif bitrate == 224 then if stereo then ignore(output.shoutcast_stereo(%mp3(bitrate = 224, stereo = true), !source)) else ignore(output.shoutcast_mono(%mp3(bitrate = 224, stereo = false), mean(!source))) end elsif bitrate == 256 then if stereo then ignore(output.shoutcast_stereo(%mp3(bitrate = 256, stereo = true), !source)) else ignore(output.shoutcast_mono(%mp3(bitrate = 256, stereo = false), mean(!source))) end elsif bitrate == 320 then if stereo then ignore(output.shoutcast_stereo(%mp3(bitrate = 320, stereo = true), !source)) else ignore(output.shoutcast_mono(%mp3(bitrate = 320, stereo = false), mean(!source))) end end end end # Add a skip function to a source # when it does not have one # by default def add_skip_command(s) # A command to skip def skip(_) # get playing (active) queue and flush it l = list.hd(server.execute("queue.secondary_queue")) l = string.split(separator=" ",l) list.iter(fun (rid) -> ignore(server.execute("queue.remove #{rid}")), l) l = list.hd(server.execute("queue.primary_queue")) l = string.split(separator=" ", l) if list.length(l) > 0 then source.skip(s) "Skipped" else "Not skipped" end end # Register the command: server.register(namespace="source", usage="skip", description="Skip the current song.", "skip",fun(s) -> begin log("source.skip") skip(s) end) end dyn_out = output.icecast(%wav, host="localhost", port=8999, password=stream_harbor_pass, mount="test-harbor", fallible=true) def set_dynamic_source_id(id) = current_dyn_id := id string_of(!current_dyn_id) end # Function to create a playlist source and output it. def create_dynamic_source(uri) = # The playlist source s = audio_to_stereo(input.http(buffer=2., max=12., uri)) # The output active_dyn_out = dyn_out(s) # We register both source and output # in the list of sources dyn_sources := list.append([(uri,s),(uri,active_dyn_out)], !dyn_sources) notify([("schedule_table_id", !current_dyn_id)]) "Done!" end # A function to destroy a dynamic source def destroy_dynamic_source_all(uri) = # We need to find the source in the list, # remove it and destroy it. Currently, the language # lacks some nice operators for that so we do it # the functional way # This function is executed on every item in the list # of dynamic sources def parse_list(ret, current_element) = # ret is of the form: (matching_sources, remaining_sources) # We extract those two: matching_sources = fst(ret) remaining_sources = snd(ret) # current_element is of the form: ("uri", source) so # we check the first element current_uri = fst(current_element) # in this case, we add the source to the list of # matched sources (list.append( [snd(current_element)], matching_sources), remaining_sources) end # now we execute the function: result = list.fold(parse_list, ([], []), !dyn_sources) matching_sources = fst(result) remaining_sources = snd(result) # we store the remaining sources in dyn_sources dyn_sources := remaining_sources # if no source matched, we return an error if list.length(matching_sources) == 0 then "error: no matching sources!" else # we stop all sources list.iter(source.shutdown, matching_sources) # And return "Done!" end end # A function to destroy a dynamic source def destroy_dynamic_source(uri) = # We need to find the source in the list, # remove it and destroy it. Currently, the language # lacks some nice operators for that so we do it # the functional way # This function is executed on every item in the list # of dynamic sources def parse_list(ret, current_element) = # ret is of the form: (matching_sources, remaining_sources) # We extract those two: matching_sources = fst(ret) remaining_sources = snd(ret) # current_element is of the form: ("uri", source) so # we check the first element current_uri = fst(current_element) if current_uri == uri then # In this case, we add the source to the list of # matched sources (list.append( [snd(current_element)], matching_sources), remaining_sources) else # In this case, we put the element in the list of remaining # sources (matching_sources, list.append([current_element], remaining_sources)) end end # Now we execute the function: result = list.fold(parse_list, ([], []), !dyn_sources) matching_sources = fst(result) remaining_sources = snd(result) # We store the remaining sources in dyn_sources dyn_sources := remaining_sources # If no source matched, we return an error if list.length(matching_sources) == 0 then "Error: no matching sources!" else # We stop all sources list.iter(source.shutdown, matching_sources) # And return "Done!" end end