From 53372327125d7cb2460320dba008b497d417af1f Mon Sep 17 00:00:00 2001
From: Loxbie <ole@freirad.at>
Date: Thu, 28 Mar 2024 12:18:55 +0100
Subject: [PATCH] Refactor: replace ini config with yaml config

---
 config/engine-core.yaml |  14 +-
 src/settings.liq        | 468 +++++++++++++++++++++++-----------------
 2 files changed, 275 insertions(+), 207 deletions(-)

diff --git a/config/engine-core.yaml b/config/engine-core.yaml
index 77a6ea9..cf24a23 100644
--- a/config/engine-core.yaml
+++ b/config/engine-core.yaml
@@ -3,13 +3,13 @@ general:
   socket_dir: "../socket"
   log_dir: "../logs"
   log_level: "3"
-  liquidsoap_as_root: "false"
+  liquidsoap_as_root: false
   liquidsoap_min_version: "2.2.4"
   api_url_playlog: "http://127.0.0.1:8008/api/v1/playlog"
 
 telnet:
-  server_enable: "true"
-  server_timeout: "16380"
+  server_enable: true
+  server_timeout: 16380
   server_host: "127.0.0.1"
   server_port: "1234"
 
@@ -19,10 +19,10 @@ fallback:
   show_id: "-1"
   type: "folder"
   music_playlist: "station-fallback-playlist.m3u"
-  music_folder_reload: "300"
-  max_blank: "15."
-  min_noise: "0."
-  threshold: "-80."
+  music_folder_reload: 300
+  max_blank: 15.
+  min_noise: 0.
+  threshold: -80.
 
 audio:
   soundsystem: "jack"
diff --git a/src/settings.liq b/src/settings.liq
index 5e7eb96..866a57a 100644
--- a/src/settings.liq
+++ b/src/settings.liq
@@ -37,13 +37,13 @@ let yaml.parse (config :
       socket_dir: string,
       log_dir: string,
       log_level: string,
-      liquidsoap_as_root: string,
+      liquidsoap_as_root: bool,
       liquidsoap_min_version: string,
       api_url_playlog: string
     },
     telnet: {
-      server_enable: string,
-      server_timeout: string,
+      server_enable: bool,
+      server_timeout: float,
       server_host: string,
       server_port: string
     },
@@ -53,10 +53,10 @@ let yaml.parse (config :
       show_id: string,
       type: string,
       music_playlist: string,
-      music_folder_reload: string,
-      max_blank: string,
-      min_noise: string,
-      threshold: string
+      music_folder_reload: float,
+      max_blank: float,
+      min_noise: float,
+      threshold: float
     },
     stream: [
       {
@@ -90,9 +90,16 @@ print(
 
 # 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)
+# 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)
 end
 
 # VERSION CHECK
@@ -108,10 +115,9 @@ then
 end
 
 # ALLOW LIQUIDSOAP RUN AS ROOT
-lqs_allow_root =
-  get_setting("false", "liquidsoap_as_root", "AURA_ENGINE_RUN_AS_ROOT")
 if
-  lqs_allow_root == "true"
+  # 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"
@@ -125,22 +131,22 @@ else
 end
 
 # SERVER SETTINGS
-server_timeout =
-  float_of_string(
-    get_setting("16380.", "server_timeout", "AURA_ENGINE_SERVER_TIMEOUT")
-  )
-settings.server.timeout.set(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")
-  )
+# 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")
+#   )
 if
-  telnet_server_enable != "true"
+  not config.telnet.server_enable
 then
   print(
     "\tLiquidsoap Telnet Server: disabled"
@@ -148,12 +154,12 @@ then
   settings.server.telnet.set(false)
 else
   print(
-    "\tLiquidsoap Telnet Server at #{telnet_server_host}:#{telnet_server_port} (#{
-      server_timeout
-    }s timeout)"
+    "\tLiquidsoap Telnet Server at #{config.telnet.server_host}:#{
+      config.telnet.server_port
+    } (#{config.telnet.server_timeout}s timeout)"
   )
   settings.server.telnet.bind_addr.set(telnet_server_host)
-  settings.server.telnet.port.set(telnet_server_port)
+  settings.server.telnet.port.set(int_of_float(config.telnet.server_port))
   settings.server.telnet.set(true)
 end
 
@@ -183,10 +189,24 @@ log(
 # LOGGING SETTINGS
 settings.log.stdout.set(true)
 settings.log.file.set(true)
-log_level = get_setting("3", "log_level", "AURA_ENGINE_CORE_LOG_LEVEL")
-settings.log.level.set(int_of_string(log_level))
-log_dir = get_setting("../logs", "log_dir", "AURA_ENGINE_CORE_LOG_DIR")
-log_file = "#{log_dir}/engine-core.log"
+
+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(og_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}"
@@ -197,12 +217,12 @@ log(
 
 # CONFIGURATION FILE
 log(
-  "\tConfig file: '#{config}'"
+  "\tConfig file: '#{config_file}'"
 )
 
 # SOCKET SETTINGS
-socket_dir = get_setting("../socket", "socket_dir", "AURA_ENGINE_SOCKET_DIR")
-socket_file = "#{socket_dir}/engine.sock"
+# socket_dir = get_setting("../socket", "socket_dir", "AURA_ENGINE_SOCKET_DIR")
+socket_file = "#{config.general.socket_dir}/engine.sock"
 if
   socket_dir != ""
 then
@@ -221,19 +241,26 @@ end
 # settings.audio.converter.samplerate.converters.set(["ffmpeg","libsamplerate","native"])
 # settings.decoder.decoders.set(["META","WAV","AIFF","FLAC","AAC","MP4","OGG","MAD"])
 
-a0_in = get_setting("", "input_device_0", "AURA_ENGINE_INPUT_DEVICE")
-a1_in = list.assoc(default="", "input_device_1", ini)
-a2_in = list.assoc(default="", "input_device_2", ini)
-a3_in = list.assoc(default="", "input_device_3", ini)
-a4_in = list.assoc(default="", "input_device_4", ini)
-a0_out = get_setting("", "output_device_0", "AURA_ENGINE_OUTPUT_DEVICE")
-a1_out = list.assoc(default="", "output_device_1", ini)
-a2_out = list.assoc(default="", "output_device_2", ini)
-a3_out = list.assoc(default="", "output_device_3", ini)
-a4_out = list.assoc(default="", "output_device_4", ini)
+# 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_in = list.hd(config.audio.devices.input).name
+
+# a1_in = list.assoc(default="", "input_device_1", ini)
+# a2_in = list.assoc(default="", "input_device_2", ini)
+# a3_in = list.assoc(default="", "input_device_3", ini)
+# a4_in = list.assoc(default="", "input_device_4", ini)
+# a0_out = get_setting("", "output_device_0", "AURA_ENGINE_OUTPUT_DEVICE")
+a0_out = list.hd(config.audio.devices.output).name
+# a1_out = list.assoc(default="", "output_device_1", ini)
+# a2_out = list.assoc(default="", "output_device_2", ini)
+# a3_out = list.assoc(default="", "output_device_3", ini)
+# a4_out = list.assoc(default="", "output_device_4", ini)
 
 # ALSA / pulse settings
-soundsystem = get_setting("alsa", "soundsystem", "AURA_ENGINE_SOUNDSYSTEM")
+# soundsystem = get_setting("alsa", "soundsystem", "AURA_ENGINE_SOUNDSYSTEM")
+soundsystem = config.audio.soundsystem
 use_alsa = soundsystem == "alsa"
 use_jack = soundsystem == "jack"
 
@@ -252,14 +279,17 @@ then
 end
 
 # ReplayGain Settings
-enable_replaygain_resolver =
-  bool_of_string(
-    get_setting(
-      "false",
-      "enable_replaygain_resolver",
-      "AURA_ENGINE_ENABLE_REPLAYGAIN_RESOLVER"
-    )
-  )
+# 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
@@ -270,17 +300,23 @@ then
 end
 
 # Frame Settings
-frame_audio_sample_rate =
-  int_of_string(
-    get_setting("0", "frame_audio_sample_rate", "AURA_ENGINE_FRAME_SAMPLERATE")
-  )
-frame_duration =
-  float_of_string(
-    get_setting("0.0", "frame_duration", "AURA_ENGINE_FRAME_DURATION")
-  )
-frame_audio_size =
-  int_of_string(get_setting("0", "frame_audio_size", "AURA_ENGINE_FRAME_SIZE"))
-
+# 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
@@ -309,83 +345,88 @@ end
 alsa_buffered_input = ref(true)
 alsa_buffered_output = ref(true)
 
-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
+# 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_timeout =
-  float_of_string(
-    get_setting(
-      "10.0", "input_stream_timeout", "AURA_ENGINE_STREAM_INPUT_TIMEOUT"
-    )
-  )
+# 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}"
 )
@@ -394,8 +435,10 @@ log(
 )
 
 # OUTPUT STREAM
-s0_enable =
-  get_setting("false", "stream_0", "AURA_ENGINE_STREAM_OUTPUT_ENABLE") == "true"
+# 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"
@@ -410,56 +453,75 @@ log(
 )
 
 # AUDIO AND PLAYLIST SOURCES
-audio_playlist_folder =
-  get_setting(
-    "../audio/playlists", "audio_playlist_folder", "AURA_ENGINE_PLAYLIST_FOLDER"
-  )
+# 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_id =
-  ref(get_setting("-1", "fallback_show_id", "AURA_ENGINE_FALLBACK_SHOW_ID"))
-fallback_type =
-  get_setting("folder", "fallback_type", "AURA_ENGINE_FALLBACK_TYPE")
-fallback_station_playlist_name =
-  get_setting(
-    "station-fallback-playlist.m3u",
-    "fallback_music_playlist",
-    "AURA_ENGINE_FALLBACK_PLAYLIST"
-  )
+# 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_reload =
-  int_of_string(
-    get_setting(
-      "300",
-      "fallback_music_folder_reload",
-      "AURA_ENGINE_FALLBACK_FOLDER_RELOAD"
-    )
-  )
-fallback_max_blank =
-  float_of_string(
-    get_setting("15.", "fallback_max_blank", "AURA_ENGINE_FALLBACK_MAX_BLANK")
-  )
-fallback_min_noise =
-  float_of_string(
-    get_setting("0.", "fallback_min_noise", "AURA_ENGINE_FALLBACK_MIN_NOISE")
-  )
-fallback_threshold =
-  float_of_string(
-    get_setting("-80.", "fallback_threshold", "AURA_ENGINE_FALLBACK_THRESHOLD")
-  )
+
+# 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}'"
 )
@@ -472,20 +534,26 @@ log(
 # fade_out_time = list.assoc(default="", "fade_out_time", ini) #int_of_string(list.assoc(default="", "fade_out_time", ini))
 
 # Metadata Configuration
-engine_meta_key_show_id =
-  get_setting("show_id", "meta_key_show_id", "AURA_ENGINE_META_KEY_SHOW_ID")
-engine_default_track_type =
-  get_setting("0", "default_track_type", "AURA_ENGINE_DEFAULT_TRACK_TYPE")
-engine_api_playlog =
-  get_setting(
-    "http://127.0.0.1:8008/api/v1/playlog",
-    "api_url_playlog",
-    "AURA_ENGINE_API_URL_PLAYLOG"
-  )
+# 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 = get_setting("1", "engine_id", "AURA_ENGINE_ID")
+engine_id = config.general.engine_id
 log(
   "\n######################################################################################"
 )
-- 
GitLab