sig
  type client = { client : string; version : string; }
  type login = { user : string; password : string; }
  module type Http_t =
    sig
      type request = Get | Post of string
      exception Http of string
      val default_timeout : float Stdlib.ref
      val request :
        ?timeout:float ->
        ?headers:(string * string) list ->
        ?port:int ->
        host:string ->
        url:string -> request:Lastfm_generic.Http_t.request -> unit -> string
    end
  module type Audioscrobbler_t =
    sig
      type source = User | Broadcast | Recommendation | Lastfm | Unknown
      type rating = Love | Ban | Skip
      type action = NowPlaying | Submit
      type song = {
        artist : string;
        track : string;
        time : float option;
        source : Lastfm_generic.Audioscrobbler_t.source option;
        rating : Lastfm_generic.Audioscrobbler_t.rating option;
        length : float option;
        album : string option;
        trackauth : string option;
        tracknumber : int option;
        musicbrainzid : string option;
      }
      type error =
          Http of string
        | Banned
        | Badauth
        | Badtime
        | Failed of string
        | UnknownError of string
        | Success
        | Internal of string
        | BadData of string
      exception Error of Lastfm_generic.Audioscrobbler_t.error
      val string_of_error : Lastfm_generic.Audioscrobbler_t.error -> string
      val base_port : int Stdlib.ref
      val base_host : string Stdlib.ref
      val get_song :
        ?time:float ->
        ?source:Lastfm_generic.Audioscrobbler_t.source ->
        ?rating:Lastfm_generic.Audioscrobbler_t.rating ->
        ?length:float ->
        ?album:string ->
        ?tracknumber:int ->
        ?musicbrainzid:string ->
        ?trackauth:string ->
        artist:string ->
        track:string -> unit -> Lastfm_generic.Audioscrobbler_t.song
      val check_song :
        Lastfm_generic.Audioscrobbler_t.song ->
        Lastfm_generic.Audioscrobbler_t.action -> unit
      val do_np :
        ?timeout:float ->
        ?host:string * int ->
        Lastfm_generic.client ->
        Lastfm_generic.login -> Lastfm_generic.Audioscrobbler_t.song -> unit
      val do_submit :
        ?timeout:float ->
        ?host:string * int ->
        Lastfm_generic.client ->
        Lastfm_generic.login ->
        Lastfm_generic.Audioscrobbler_t.song list ->
        (Lastfm_generic.Audioscrobbler_t.error *
         Lastfm_generic.Audioscrobbler_t.song)
        list
      val handshake :
        ?timeout:float ->
        ?host:string * int ->
        Lastfm_generic.client -> Lastfm_generic.login -> string
      val np :
        ?timeout:float ->
        string -> Lastfm_generic.Audioscrobbler_t.song -> unit
      val submit :
        ?timeout:float ->
        string ->
        Lastfm_generic.Audioscrobbler_t.song list ->
        (Lastfm_generic.Audioscrobbler_t.error *
         Lastfm_generic.Audioscrobbler_t.song)
        list
    end
  module type Radio_t =
    sig
      type track = (string * string) list * string
      type error =
          Http of string
        | Auth of string
        | Adjust of string * string
        | Playlist
        | Empty
      exception Error of Lastfm_generic.Radio_t.error
      val string_of_error : Lastfm_generic.Radio_t.error -> string
      val base_host : string Stdlib.ref
      val get : ?timeout:float -> string -> Lastfm_generic.Radio_t.track list
      val parse : string -> Lastfm_generic.login * string * string option
      val init : ?timeout:float -> Lastfm_generic.login -> string
      val adjust :
        ?timeout:float -> string -> string -> (string * string) list
      val playlist : ?timeout:float -> string -> string option -> string
      val tracks :
        ?timeout:float ->
        string -> string option -> Lastfm_generic.Radio_t.track list
      val clear : string -> unit
    end
  module Audioscrobbler_generic : functor (Http : Http_t-> Audioscrobbler_t
  module Radio_generic : functor (Http : Http_t-> Radio_t
end