Skip to content
Snippets Groups Projects
settings.liq 14.3 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/>.
    
    # READ INI FILE
    
    default_config = "../config/engine-core.yaml"
    config_file =
    
      list.hd(
        default=default_config,
        process.read.lines(
    
          "ls /etc/aura/engine-core.yaml"
    
      "\tConfig file: '#{config_file}'"
    
    Ole Binder's avatar
    Ole Binder committed
    
    let yaml.parse (config :
      {
        general: {
          engine_id: string,
          socket_dir: string,
          log_dir: string,
          log_level: string,
    
          liquidsoap_as_root: bool,
    
    Ole Binder's avatar
    Ole Binder committed
          liquidsoap_min_version: string,
          api_url_playlog: string
        },
        telnet: {
    
          server_enable: bool,
          server_timeout: float,
    
    Ole Binder's avatar
    Ole Binder committed
          server_host: string,
    
          server_port: float
    
    Ole Binder's avatar
    Ole Binder committed
        },
        fallback: {
          music_folder: string,
          show_name: string,
          show_id: string,
          type: string,
          music_playlist: string,
    
          music_folder_reload: float,
          max_blank: float,
          min_noise: float,
          threshold: float
    
    Ole Binder's avatar
    Ole Binder committed
        },
        stream: [
          {
            enabled: bool,
            encoding: string,
            bitrate: string,
            channels: string,
            host: string,
            port: float,
            mountpoint: string,
            user: string,
            password: string,
            url: string,
            name: string,
            genre: string,
            description: string
          }
        ],
        audio: {
          soundsystem: string,
          devices: {output: [{name: string}], input: [{name: string}]}
        }
      }
    ) = file.contents(config_file)
    
    Ole Binder's avatar
    Ole Binder committed
    engine_config_folder = string.split(separator="/engine-core.yaml", config_file)
    
    engine_config_folder = list.nth(default="../config/", engine_config_folder, 0)
    
    print(
      "\tengine_config_folder = '#{engine_config_folder}'"
    )
    
    # Retrieve a setting either bei 1.) environment variable or 2.) config property.
    
    # If none is available the default value is returned.
    
    # def get_setting(default_value, config_prop, env_var) =
    #   dv = list.assoc(default=default_value, config_prop, ini)
    #   environment.get(default=dv, env_var)
    # end
    
    # FIXME: env vars are always strings, we would have to guess the type here
    # since the config_value might not be a string. Maybe we can extract the type
    # from config_value?
    def get_setting(config_value, env_var) =
      environment.get(default=config_value, env_var)
    
    # VERSION CHECK
    
      not liquidsoap.version.at_least(config.general.liquidsoap_min_version)
    
        "AURA Engine Core requires at least Liquidsoap v#{
          config.general.liquidsoap_min_version
        }"
    
    # ALLOW LIQUIDSOAP RUN AS ROOT
    
      # get_setting(config.general.liquidsoap_as_root, "AURA_ENGINE_RUN_AS_ROOT")
      config.general.liquidsoap_as_root
    
    then
      print(
        "\tAllow Liquidsoap running as root user: true"
      )
      settings.init.allow_root.set(true)
    
      print(
        "\tAllow Liquidsoap running as root user: false"
      )
      settings.init.allow_root.set(false)
    
    # server_timeout =
    #   float_of_string(
    #     get_setting("16380.", "server_timeout", "AURA_ENGINE_SERVER_TIMEOUT")
    #   )
    settings.server.timeout.set(config.telnet.server_timeout)
    
    # telnet_server_enable =
    #   get_setting("true", "telnet_server_enable", "AURA_ENGINE_TELNET_ENABLE")
    # telnet_server_host =
    #   get_setting("127.0.0.1", "telnet_server_host", "AURA_ENGINE_TELNET_HOST")
    # telnet_server_port =
    #   int_of_string(
    #     get_setting("1234", "telnet_server_port", "AURA_ENGINE_TELNET_PORT")
    #   )
    
      not config.telnet.server_enable
    
    then
      print(
        "\tLiquidsoap Telnet Server: disabled"
      )
      settings.server.telnet.set(false)
    
        "\tLiquidsoap Telnet Server at " ^
          config.telnet.server_host ^
          ":" ^
          string.float(config.telnet.server_port) ^
          " (" ^
          string.float(config.telnet.server_timeout) ^
          "s timeout)"
    
      settings.server.telnet.bind_addr.set(config.telnet.server_host)
    
      settings.server.telnet.port.set(int_of_float(config.telnet.server_port))
    
      settings.server.telnet.set(true)
    
    settings.console.colorize.set("always")
    #settings.request.grace_time.set(2.)
    
    # LOG SETTINGS
    
    engine_version =
      process.read(
        "cat ../VERSION"
      )
    log(
      "######################################################################################"
    )
    log(
      "AURA Engine:Core v#{engine_version} starting ..."
    )
    log(
      "######################################################################################"
    )
    
    log(
      "System Settings:"
    )
    
    # LOGGING SETTINGS
    
    settings.log.stdout.set(true)
    settings.log.file.set(true)
    
    
    log_level =
      if
        config.general.log_level == "DEBUG"
      then
        5
      elsif config.general.log_level == "INFO" then 3
      elsif config.general.log_level == "WARNING" then 2
      elsif config.general.log_level == "ERROR" then 1
      else
        3
      end
    
    # log_level = get_setting("3", "log_level", "AURA_ENGINE_CORE_LOG_LEVEL")
    
    settings.log.level.set(log_level)
    
    
    # log_dir = get_setting("../logs", "log_dir", "AURA_ENGINE_CORE_LOG_DIR")
    log_file = "#{config.general.log_dir}/engine-core.log"
    
    settings.log.file.path.set(log_file)
    
    print(
      "\tLogging to '#{log_file}' with log level #{log_level}"
    )
    
    log(
      "\tLog level #{log_level}"
    )
    
    
    # CONFIGURATION FILE
    
      "\tConfig file: '#{config_file}'"
    
    # SOCKET SETTINGS
    
    # socket_dir = get_setting("../socket", "socket_dir", "AURA_ENGINE_SOCKET_DIR")
    socket_file = "#{config.general.socket_dir}/engine.sock"
    
      config.general.socket_dir != ""
    
    then
      log(
        "\tSocket location: '#{socket_file}'"
      )
      settings.server.socket.path.set(socket_file)
      settings.server.socket.set(true)
    
      log(
        "\tCRITICAL: No socket directory set!"
      )
    
    
    # SOUND CARD SETTINGS
    
    # settings.audio.converter.samplerate.converters.set(["ffmpeg","libsamplerate","native"])
    # settings.decoder.decoders.set(["META","WAV","AIFF","FLAC","AAC","MP4","OGG","MAD"])
    
    # TODO: This needs refactoring
    # we save the device name in the corresponding variable name
    # I guess the variable name is then later used to create the in- and outputs
    # a0_in = get_setting("", "input_device_0", "AURA_ENGINE_INPUT_DEVICE")
    
    # a0_out = get_setting("", "output_device_0", "AURA_ENGINE_OUTPUT_DEVICE")
    
    # ALSA / pulse settings
    
    # soundsystem = get_setting("alsa", "soundsystem", "AURA_ENGINE_SOUNDSYSTEM")
    soundsystem = config.audio.soundsystem
    
    use_alsa = soundsystem == "alsa"
    use_jack = soundsystem == "jack"
    
    log(
      "\nAudio Settings:"
    )
    
    def print_device(device) =
    
        "\t\t- #{device.name}"
    
    log(
      "\tOutput Devices:"
    )
    list.iter(print_device, config.audio.devices.output)
    log(
      "\tInput Devices:"
    )
    list.iter(print_device, config.audio.devices.input)
    
    
    # ReplayGain Settings
    
    # enable_replaygain_resolver =
    #   bool_of_string(
    #     get_setting(
    #       "false",
    #       "enable_replaygain_resolver",
    #       "AURA_ENGINE_ENABLE_REPLAYGAIN_RESOLVER"
    #     )
    #   )
    
    # FIXME: read this from the config file?
    enable_replaygain_resolver = false
    
    if
      enable_replaygain_resolver == true
    then
      enable_replaygain_metadata()
      log(
        "\tReplayGain resolver enabled"
      )
    
    # TODO: due to the switch to jack these settings are not needed anymore. Maybe if we
    # enable ALSA in some point in the future again.
    # frame_audio_sample_rate =
    #   int_of_string(
    #     get_setting("0", "frame_audio_sample_rate", "AURA_ENGINE_FRAME_SAMPLERATE")
    #   )
    frame_audio_sample_rate = 0
    
    # frame_duration =
    #   float_of_string(
    #     get_setting("0.0", "frame_duration", "AURA_ENGINE_FRAME_DURATION")
    #   )
    frame_duration = 0.0
    
    # frame_audio_size =
    #   int_of_string(get_setting("0", "frame_audio_size", "AURA_ENGINE_FRAME_SIZE"))
    frame_audio_size = 0
    
    if
      frame_audio_sample_rate > 0
    then
      log(
        "\tframe.audio.samplerate = #{frame_audio_sample_rate} Hz"
      )
      settings.frame.audio.samplerate.set(frame_audio_sample_rate)
    
    if
      frame_duration > 0.0
    then
      log(
        "\tframe.duration = #{frame_duration} seconds"
      )
      settings.frame.duration.set(frame_duration)
    
    if
      frame_audio_size > 0
    then
      log(
        "\tframe.audio.size = #{frame_audio_size} ticks"
      )
      settings.frame.audio.size.set(frame_audio_size)
    
    alsa_buffered_input = ref(true)
    alsa_buffered_output = ref(true)
    
    
    # TODO: same question, do we want to keep this code?
    # if
    #   use_alsa
    # then
    #   log(
    #     "\nALSA Settings:"
    #   )
    #   alsa_buffered_input :=
    #     bool_of_string(
    #       get_setting(
    #         "true", "alsa_buffered_input", "AURA_ENGINE_ALSA_BUFFERED_INPUT"
    #       )
    #     )
    #   alsa_buffered_output :=
    #     bool_of_string(
    #       get_setting(
    #         "true", "alsa_buffered_output", "AURA_ENGINE_ALSA_BUFFERED_OUTPUT"
    #       )
    #     )
    #   alsa_buffer =
    #     int_of_string(get_setting("0", "alsa_buffer", "AURA_ENGINE_ALSA_BUFFER"))
    #   alsa_buffer_length =
    #     int_of_string(
    #       get_setting("0", "alsa_buffer_length", "AURA_ENGINE_ALSA_BUFFER_LENGTH")
    #     )
    #   alsa_periods =
    #     int_of_string(get_setting("0", "alsa_periods", "AURA_ENGINE_ALSA_PERIODS"))
    
    #   log(
    #     "\talsa_buffered_input = #{alsa_buffered_input()}"
    #   )
    #   log(
    #     "\talsa_buffered_output = #{alsa_buffered_output()}"
    #   )
    
    #   if
    #     alsa_buffer > 0
    #   then
    #     log(
    #       "\tInternal buffer size (alsa.alsa_buffer) = #{alsa_buffer}"
    #     )
    #     settings.alsa.alsa_buffer.set(alsa_buffer)
    #   end
    #   if
    #     alsa_buffer_length > 0
    #   then
    #     log(
    #       "\tBuffer size, in frames (alsa.buffer_length) = #{alsa_buffer_length}"
    #     )
    #     settings.alsa.buffer_length.set(alsa_buffer_length)
    #   end
    #   if
    #     alsa_periods > 0
    #   then
    #     log(
    #       "\tPeriods (alsa.periods) = #{alsa_periods}"
    #     )
    #     settings.alsa.periods.set(alsa_periods)
    #   end
    # end
    
    log(
      "\nStream Settings:"
    )
    
    # TODO: read this from the config file
    
    # INPUT STREAM SETTINGS
    
    # input_stream_max_buffer =
    #   float_of_string(
    #     get_setting(
    #       "5.0", "input_stream_max_buffer", "AURA_ENGINE_STREAM_INPUT_MAX_BUFFER"
    #     )
    #   )
    input_stream_max_buffer = 5.0
    
    # input_stream_timeout =
    #   float_of_string(
    #     get_setting(
    #       "10.0", "input_stream_timeout", "AURA_ENGINE_STREAM_INPUT_TIMEOUT"
    #     )
    #   )
    input_stream_timeout = 10.0
    
    log(
      "\tInput stream max buffer: #{input_stream_max_buffer}"
    )
    log(
      "\tInput stream timeout: #{input_stream_timeout}"
    )
    
    # TODO: refactor this to use the list of streams
    # s0_enable =
    #   get_setting("false", "stream_0", "AURA_ENGINE_STREAM_OUTPUT_ENABLE") == "true"
    s0_enable = list.hd(config.stream).enabled
    
    
    # s1_enable = list.assoc(default="false", "stream_1", ini) == "true"
    # s2_enable = list.assoc(default="false", "stream_2", ini) == "true"
    # s3_enable = list.assoc(default="false", "stream_3", ini) == "true"
    # s4_enable = list.assoc(default="false", "stream_4", ini) == "true"
    
    log(
      "\tOutput stream enabled: #{s0_enable}"
    )
    
    log(
      "\nOther Settings:"
    )
    
    
    # AUDIO AND PLAYLIST SOURCES
    
    # TODO: read this from config
    # audio_playlist_folder =
    #   get_setting(
    #     "../audio/playlists", "audio_playlist_folder", "AURA_ENGINE_PLAYLIST_FOLDER"
    #   )
    audio_playlist_folder = "../audio/playlists"
    
    
    # FALLBACK SETTINGS
    
    # fallback_show_name =
    #   ref(
    #     get_setting(
    #       "Station Fallback",
    #       "fallback_show_name",
    #       "AURA_ENGINE_FALLBACK_SHOW_NAME"
    #     )
    #   )
    fallback_show_name = ref(config.fallback.show_name)
    
    # fallback_show_id =
    #   ref(get_setting("-1", "fallback_show_id", "AURA_ENGINE_FALLBACK_SHOW_ID"))
    fallback_show_id = ref(config.fallback.show_id)
    
    # fallback_type =
    #   get_setting("folder", "fallback_type", "AURA_ENGINE_FALLBACK_TYPE")
    fallback_type = config.fallback.type
    
    # fallback_station_playlist_name =
    #   get_setting(
    #     "station-fallback-playlist.m3u",
    #     "fallback_music_playlist",
    #     "AURA_ENGINE_FALLBACK_PLAYLIST"
    #   )
    fallback_station_playlist_name = config.fallback.music_playlist
    
    fallback_station_playlist_path =
      "#{audio_playlist_folder}/#{fallback_station_playlist_name}"
    
    
    # fallback_station_dir =
    #   get_setting(
    #     "../audio/fallback", "fallback_music_folder", "AURA_ENGINE_FALLBACK_FOLDER"
    #   )
    fallback_station_dir = config.fallback.music_folder
    
    # fallback_station_dir_reload =
    #   int_of_string(
    #     get_setting(
    #       "300",
    #       "fallback_music_folder_reload",
    #       "AURA_ENGINE_FALLBACK_FOLDER_RELOAD"
    #     )
    #   )
    fallback_station_dir_reload = int_of_float(config.fallback.music_folder_reload)
    
    # fallback_max_blank =
    #   float_of_string(
    #     get_setting("15.", "fallback_max_blank", "AURA_ENGINE_FALLBACK_MAX_BLANK")
    #   )
    fallback_max_blank = config.fallback.max_blank
    
    # fallback_min_noise =
    #   float_of_string(
    #     get_setting("0.", "fallback_min_noise", "AURA_ENGINE_FALLBACK_MIN_NOISE")
    #   )
    fallback_min_noise = config.fallback.min_noise
    
    # fallback_threshold =
    #   float_of_string(
    #     get_setting("-80.", "fallback_threshold", "AURA_ENGINE_FALLBACK_THRESHOLD")
    #   )
    fallback_threshold = config.fallback.threshold
    
    log(
      "\tfallback_station_playlist_path = '#{fallback_station_playlist_path}'"
    )
    log(
      "\tfallback_station_dir = '#{fallback_station_dir}'"
    )
    
    
    # FADING SETTINGS
    # fade_in_time = list.assoc(default="", "fade_in_time", ini) #int_of_string(list.assoc(default="", "fade_in_time", ini))
    # fade_out_time = list.assoc(default="", "fade_out_time", ini) #int_of_string(list.assoc(default="", "fade_out_time", ini))
    
    
    # Metadata Configuration
    
    # FIXME: whats this? Move into config file
    # engine_meta_key_show_id =
    #   get_setting("show_id", "meta_key_show_id", "AURA_ENGINE_META_KEY_SHOW_ID")
    engine_meta_key_show_id = "show_id"
    
    # engine_default_track_type =
    #   get_setting("0", "default_track_type", "AURA_ENGINE_DEFAULT_TRACK_TYPE")
    engine_default_track_type = "0"
    
    # engine_api_playlog =
    #   get_setting(
    #     "http://127.0.0.1:8008/api/v1/playlog",
    #     "api_url_playlog",
    #     "AURA_ENGINE_API_URL_PLAYLOG"
    #   )
    engine_api_playlog = config.general.api_url_playlog
    
    
    # "1" or "2" used for HA setups
    
    # engine_id = get_setting("1", "engine_id", "AURA_ENGINE_ID")
    engine_id = config.general.engine_id
    
    log(
      "\n######################################################################################"
    )