Skip to content
Snippets Groups Projects
functions.liq 7.39 KiB
Newer Older
  • Learn to ignore specific revisions
  • #
    # Aura Engine (https://gitlab.servus.at/aura/engine)
    #
    # Copyright (C) 2017-2020 - The Aura Engine Team.
    #
    # This program is free software: you can redistribute it and/or modify
    # it under the terms of the GNU Affero General Public License as published by
    # the Free Software Foundation, either version 3 of the License, or
    # (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU Affero General Public License for more details.
    #
    # You should have received a copy of the GNU Affero General Public License
    # along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
    
    
    
    David Trattnig's avatar
    David Trattnig committed
    #
    # METADATA
    #
    
    
    # Merge with previous metadata, avoid duplicates
    def merge_meta(last_meta, meta) =
        log(level=5, label="metadata", "Merge | last metadata: #{last_meta}")
        log(level=5, label="metadata", "Merge | current metadata: #{meta}")
        merged = ref(last_meta)
    
        def add_meta_entry(entry) =
            let (k, _) = entry
            if list.assoc.mem(k, !merged) then
                log(level=5, label="metadata", "Remove existing entry #{entry}")
                merged := list.assoc.remove(k, !merged)
            end
            merged := list.add(entry, !merged)
        end
    
        list.iter(add_meta_entry, (meta))
        log(level=5, label="metadata", "Merge | resulting metadata: #{!merged}")
        !merged
    end
    
    # Checks for the existence of show-specific metadata
    def has_show_meta(meta) =
        list.assoc.mem(engine_meta_key_show_id, meta) ? true : false
    end
    
    # Checks if the show ID in two metadata objects matches
    def is_same_show(last_meta, current_meta) =
        last_meta[engine_meta_key_show_id] == current_meta[engine_meta_key_show_id] ? true : false
    end
    
    # Checks if the current show metadata is same as the previous one
    def is_same_show(last_meta, current_meta) =
        if has_show_meta(last_meta) then
            if not has_show_meta(current_meta) then
                # No current show meta: handle as same show
                true
            elsif is_same_show(last_meta, current_meta) then
                true
            else
                # A new show has started
                false
            end
        else
            # Last show has no show meta
            if not has_show_meta(current_meta) then
                # And the current one either: handle as same show
                true
            else
                # Treat missing last show info as the same show
                true
            end
        end
    end
    
    # Handles either insert or merge & insert of metadata, depending on the show ID
    def do_meta_insert(last_meta_callback, insert_meta_callback, meta) =
        lm = (last_meta_callback() ?? [])
        if is_same_show(lm, meta) then
            lm = (last_meta_callback() ?? [])
            merged = merge_meta(lm, meta)
            insert_meta_callback(merged)
        else
            insert_meta_callback(meta)
        end
    end
    
    # Builds a metadata object from data passed as JSON
    
    def build_metadata(json_string) =
    
        let json.parse (data : {
                show_name: string,
                show_id: int,
                timeslot_id: int,
                playlist_id: int,
                playlist_item: string,
                track_type: int,
    
                track_start: string?,
                track_duration: int?,
                track_title: string?,
                track_album: string?,
                track_artist: string?
    
            }) = json_string
        [
            ("show_name", data.show_name),
            ("show_id", "#{data.show_id}"),
            ("timeslot_id", "#{data.timeslot_id}"),
            ("playlist_id", "#{data.playlist_id}"),
            ("playlist_item", "#{data.playlist_item}"),
            ("track_type", "#{data.track_type}"),
    
            ("track_start", "#{data.track_start}"),
    
            ("track_duration", "#{data.track_duration}"),
    
            ("track_title", "#{data.track_title}"),
            ("track_album", "#{data.track_album}"),
            ("track_artist", "#{data.track_artist}"),
    
    # Reads the track duration
    #   a.) when available from the file
    #   b.) as a fallback from the meta field "track_duration"
    #
    # Returns
    #   (int) duration in seconds
    def get_meta_track_duration(meta) =
        track_duration = int_of_float(request.duration(meta["filename"]))
        if track_duration != -1 then
            track_duration
        else
            int_of_string(meta["track_duration"])
        end
    end
    
    
    # Posts a playlog to the Engine API
    def post_playlog(api_url, data) =
        json_data = json()
    
        json_data.add("log_source", int_of_string(list.assoc("log_source", data)))
        json_data.add("show_name", list.assoc("show_name", data))
        json_data.add("show_id", int_of_string(list.assoc("show_id", data)))
        json_data.add("timeslot_id", int_of_string(list.assoc("timeslot_id", data)))
        json_data.add("playlist_id", int_of_string(list.assoc("playlist_id", data)))
        json_data.add("track_type", int_of_string(list.assoc("track_type", data)))
        json_data.add("track_start", list.assoc("track_start", data))
    
        json_data.add("track_duration", int_of_string(list.assoc("track_duration", data)))
    
        json_data.add("track_title", list.assoc("track_title", data))
        json_data.add("track_album", list.assoc("track_album", data))
        json_data.add("track_artist", list.assoc("track_artist", data))
        if list.assoc("track_num", data) != "" then
            json_data.add("track_num", int_of_string(list.assoc("track_num", data)))
        end
    
        playlog = json.stringify(json_data)
        log("Posting playlog to '#{api_url}': #{playlog}")
        headers = [("Content-Type","application/json")]
        result = http.post(headers=headers, data="#{playlog}", "#{api_url}")
    
        if result.status_code < 400 then
            log("Successfully posted playlog to Engine API.")
        else
            log("ERROR during playlog POST: #{result.status_code} | #{result.status_message}")
        end
    end
    
    
    
    # Evaluate the type of source
    #
    # Returns
    #   "fallback", "queue", "stream", "analog_in", "unknown_source"
    def eval_source_type(source_id) =
        type_mapping = [
            ("fallback_folder", "fallback"),
            ("fallback_playlist", "fallback"),
    
            ("in_queue_0", "queue"),
            ("in_queue_1", "queue"),
            ("in_stream_0", "stream"),
            ("in_stream_1", "stream"),
            ("in_line_0", "analog_in"),
            ("in_line_1", "analog_in"),
            ("in_line_2", "analog_in"),
            ("in_line_3", "analog_in"),
            ("in_line_4", "analog_in")
    
        ]
        let source_type = list.assoc(
            default="unknown_source",
            source_id,
            type_mapping
        )
        source_type
    end
    
    # Evaluates the track type based on the given:
    #   a.) "meta.track_type" passed as annotation, and if not available on
    #   b.) "engine_current_track_type" passed via server function
    #   c.) "meta.source" and if not available on
    #   d.) configured default track type setting
    #
    # Returns:
    #   0=QUEUE/FILE, 1=STREAM, 2=LIVE ANALOG, 3=PLAYLIST
    #
    def eval_track_type(meta_track_type, meta_source) =
        type_mapping = [
            ("fallback_folder", "0"),
            ("fallback_playlist", "3"),
    
            ("in_queue_0", "0"),
            ("in_queue_1", "0"),
            ("in_stream_0", "1"),
            ("in_stream_1", "1"),
            ("in_line_0", "2"),
            ("in_line_1", "2"),
            ("in_line_2", "2"),
            ("in_line_3", "2"),
            ("in_line_4", "2")
    
        ]
    
        track_type = list.assoc(
            default=engine_default_track_type,
            meta_source,
            type_mapping
        )
    
        if meta_track_type != "" then
            meta_track_type
        elsif track_type != "" then
            track_type
        else
            engine_default_track_type
        end
    end