#!/usr/bin/liquidsoap

# No loggin for now
set("log.stdout",false)
set("log.file",false)

# Audio player implemented in liquidsoap
version = "11.07"

# Detect available outputs
outputs = [
%ifdef output.ao
"ao",
%endif
%ifdef output.pulseaudio
"pulseaudio",
%endif
%ifdef output.alsa
"alsa",
%endif
%ifdef output.oss
"oss",
%endif
%ifdef output.jack
"jack",
%endif
"dummy"
]

if list.length(outputs) == 1 then
  print("No local output available.")
  shutdown ()
end
outs = string.concat(separator=", ", outputs)

usage = 
"Usage: liq123 [ -h ] [ -o output ] " ^ 
%ifdef lastfm.submit
"[ -s user ] " ^
%endif
%ifdef librefm.submit
"[ -s user ] " ^
%endif
"[ -r ] [ -f ] [ -d ] [ http://... " ^
%ifdef lastfm.submit
"| lastfm://... " ^
%endif
"| directory | filename ]
* Output can be: #{outs}
  Default: " ^ list.hd(outputs) ^ "\n" ^  
%ifdef lastfm.submit
"* -s option is for optional lastfm submission, 
  password request will be prompted.\n" ^ 
%endif
%ifdef librefm.submit
"* -l option is for optional librefm submission,
  password request will be prompted.\n" ^
%endif
"* -d turns on internal logging for debugging.
* -r randomize directory listings.
* For safety reasons, when ready a directory, 
  liq123 needs an initial valid file.
  It will shutdown if the first file found is not valid
  Use -f to force reading in this case.
* -h, --help: print this message."

# Initial message
print("Starting liq123 version #{version}")

# Get lastfm options
lastfm_submit = getopt(default="none","-s")
lastfm_user = ref lastfm_submit
lastfm_password = ref "none"
# Get librefm options
librefm_submit = getopt(default="none","-l")
librefm_user = ref librefm_submit
librefm_password = ref "none"
# Use two even queues to prevent lastfm submission
# from blocking file resolution
if lastfm_submit != "none" or librefm_submit != "none" then
  set("scheduler.event_queues",2)
end

# Get debugging option
if getopt("-d") == "1" then
  print("Enabling debug messages.")
  set("log.stdout",true)
  set("log.level",4)
end

# Get randomization option
random = getopt("-r")

# Get force option
force = getopt("-f")

# Get help option
help = 
 if getopt("-h") == "1" or getopt("--help") == "1" then
  true
 else
  false
 end

# Get output option
driver = getopt(default="unset","-o")
driver_is_set = ref (driver != "unset")
def output(s) = output.dummy(id="dummy",s) end
def test_driver(d) = 
  if (driver == d) or (not !driver_is_set) then
    driver_is_set := true
    true
  else
    false
  end
end
%ifdef output.alsa
def output(s) =
  if test_driver("alsa") then
    output.alsa(id="alsa",s)
  else
    output(s)
  end
end
%endif
%ifdef output.oss
def output(s) =
  if test_driver("oss") then
    output.oss(id="oss",s)
  else
    output(s)
  end
end
%endif
%ifdef output.jack
def output(s) =
  if test_driver("jack") then
    pid = string_of(getpid())
    output.jack(id="jack-" ^ pid,s)
  else
    output(s)
  end
end
%endif
%ifdef output.ao
def output(s) = 
  if test_driver("ao") then
    output.ao(id="ao",s)
  else
    output(s)
  end
end
%endif
%ifdef output.pulseaudio
def output(s) =
  if test_driver("pulseaudio") then
    output.pulseaudio(id="pulseaudio",s)
  else
    output(s)
  end
end
%endif

# Get arguments from command line
uri = argv(default="",1)

# Print metadatas
def process_meta(meta)
  title = '$(if $(title),"$(title)","Unknown Title")'%[("title",meta['title'])]
  print("Title: #{title}")
  artist = meta["artist"]
  if artist != "" then
    print("Artist: #{artist}")
  end
  album = meta["album"]
  if album != "" then
    print("Album: #{album}")
  end
%ifdef lastfm.submit
  if lastfm_submit != "none" then
    print("Submiting song to lastfm...")
    lastfm.submit(user=!lastfm_user,password=!lastfm_password,meta)
  end
%endif
%ifdef librefm.submit
  if librefm_submit != "none" then
    print("Submiting song to librefm...")
    librefm.submit(user=!librefm_user,password=!librefm_password,meta)
  end
%endif
  print("")
end

# Fetch lastfm user/password
def fetch_lastfm () = 
  if (!lastfm_user) == "none" then
    print(newline=false,"Please enter lastfm user: ")
    lastfm_user := read()
  end
  if (!lastfm_password) == "none" then
    print(newline=false,"Please enter lastfm password for #{!lastfm_user}: ")
    lastfm_password := read(hide=true)
  end
end

# Fetch librefm user/password
def fetch_librefm () =
  if (!librefm_user) == "none" then
    print(newline=false,"Please enter librefm user: ")
    librefm_user := read()
  end
  if (!librefm_password) == "none" then
    print(newline=false,"Please enter librefm password for #{!librefm_user}: ")
    librefm_password := read(hide=true)
  end
end

# Main source
def sri(uri) =
%ifdef lastfm.submit
  # Test for lastfm submition
  if lastfm_submit != "none" then
    print("Will submit songs to lastfm")
    fetch_lastfm ()
  end
%endif
%ifdef librefm.submit
  # Test for librefm submition
  if librefm_submit != "none" then
    print("Will submit songs to librefm")
    fetch_librefm ()
  end
%endif
  def playlist.custom(files)
    position = ref 0
    length = list.length(files)
    if length == 0 then
      print("Directory or playlist is empty, shutting down..")
      shutdown ()
    end
    # Trying to resolve the first file
    first = request.create(persistent=true,list.hd(files))
    if not request.resolve(first) then
      print("Could not read first file: #{request.filename(first)}")
      if force != "1" then
        print("Shutting down..")
        shutdown ()
      end
    end
    def next () =
      state = !position
      file =
        if state < length then
          position := state + 1
          list.nth(files,state)
        else
          # Playlist finished
          ""
        end
      request.create(file)
    end
    request.dynamic(next)
  end
# Shutdown source and transition
  s = blank(id="shutdown")
  def transition (a,b)
    if source.id(b) == "shutdown" then
      print("Work finished: shutting down..")
      shutdown ()
    end
    b
  end
  # Test if source is a file
  if test_process("test -f #{quote(uri)}") then
    print("Listening to local file: #{uri}")
    # Check for playlist file
    # Set to false by default
    is_playlist = false
    %ifdef file.mime
    mime = file.mime(uri)
    is_playlist = 
      if list.hd(string.split(separator="/",mime)) == "text" then
        print("Text file treated as playlist.")
        true
      else
        is_playlist
      end
    %endif
    source = 
      if is_playlist then
        playlist = request.create(uri)
        if not request.resolve(playlist) then
          print("Could not get file from playlist")
          shutdown ()
        end
        playlist = playlist.parse(request.filename(playlist))
        playlist = list.map(snd,playlist)
        playlist.custom(playlist)
      else
        sequence([single(uri),fallback([])])
      end
    source = on_metadata(
            process_meta,
            source)
    fallback([source,s],transitions=[transition,transition])
  # Test for a directory
  elsif test_process("test -d #{quote(uri)}") then
    print("Listening to local directory: #{uri}")
    print("Reading directory, this may take some time")
    # Filtering to wav ogg and mp3 extensions for now..
    sort_mode = 
      if random != "1" then
        ""
      else
        "-R"
      end
    files = get_process_lines("find #{quote(uri)} -type f | grep '\.wav$\|\.mp3$\|\.ogg$' | sort #{sort_mode}")
    playlist = on_metadata(
                 process_meta,
                 playlist.custom(files))
    fallback(track_sensitive=false,[playlist,s],transitions=[transition,transition])
%ifdef input.lastfm
  # Test for lastfm:// streams
  elsif string.match(pattern="^lastfm://",uri) then
    print("Listening to lastfm stream: #{uri}")
    fetch_lastfm ()  
    source = on_metadata(
               process_meta,
               input.lastfm(user=!lastfm_user,password=!lastfm_password,
                            uri))
    mksafe(source)
%endif
  # Now test http://
  elsif string.match(pattern="^http://",uri) then
    print("Listening to http stream: #{uri}")
    source = on_metadata(
               process_meta,
               input.http(uri))
    mksafe(source)
  else
    print("Unknown source : #{uri}")
    shutdown()
    blank()
  end
end

if (not help) and uri != "" then 
   # Start !
   s = output(sri(uri))
   id = source.id(s)
   print("Selected output: #{id}")
   if not string.match(pattern=driver,id) and driver != "unset" then
     print("-> Driver #{driver} might not be available.")
   end
   print("")
else
   print(usage)
end

