From 4146f2e1977fb09887576285ba1bc33cc91bbe01 Mon Sep 17 00:00:00 2001 From: Yuriy Shirokov Date: Fri, 23 Jun 2023 02:30:55 +0400 Subject: [PATCH 1/4] It compiles with OCaml 4.13 now --- bin/Ompdc_common.ml | 8 +-- bin/Ompdc_idle.ml | 2 +- bin/Ompdc_playback.ml | 18 +++---- bin/Ompdc_playback_options.ml | 2 +- bin/Ompdc_status.ml | 2 +- bin/Ompdc_stored_playlists.ml | 2 +- bin/dune | 7 ++- bin/ompdc.ml | 20 ++++---- lib/Client_lwt.mli | 4 +- lib/Connection.ml | 6 +-- lib/Connection.mli | 4 +- lib/dune | 7 ++- samples/dune | 26 +++------- samples/get_mpd_responses.ml | 12 ++--- samples/mpd_count.ml | 2 +- samples/mpd_lwt_client_idle.ml | 26 +++++----- samples/mpd_lwt_client_idle_loop.ml | 6 +-- samples/mpd_lwt_client_idle_noidle.ml | 70 +++++++++++++-------------- samples/mpd_lwt_count.ml | 2 +- samples/mpd_lwt_send_ping.ml | 2 +- samples/mpd_playlist_info.ml | 3 -- samples/mpd_status_query.ml | 7 +-- samples/mpd_tagtypes_query.ml | 3 -- samples/mpd_volume_query.ml | 3 -- samples/try_mpd_queries.ml | 7 +-- tests/dune | 5 +- 26 files changed, 113 insertions(+), 143 deletions(-) diff --git a/bin/Ompdc_common.ml b/bin/Ompdc_common.ml index bfbc9da..e9ce0c5 100644 --- a/bin/Ompdc_common.ml +++ b/bin/Ompdc_common.ml @@ -22,7 +22,7 @@ open Mpd.Protocol let version = "not.yet" let sdocs = Manpage.s_common_options let docs = Manpage.s_common_options -let exits = Term.default_exits +let exits = Cmd.Exit.defaults let help _copts man_format cmds topic = match topic with | None -> `Help (`Pager, None) (* help about the program. *) @@ -53,12 +53,12 @@ let common_opts host port = let common_opts_t = let host = let doc = "Set the address of the Mpd server." in - let env = Arg.env_var "OMPDC_HOST" ~doc in + let env = Cmd.Env.info "OMPDC_HOST" ~doc in Arg.(value & opt string "127.0.0.1" & info ["h"; "host"] ~docs ~env ~docv:"HOST") in let port = let doc = "Set the port of the Mpd server." in - let env = Arg.env_var "OMPDC_PORT" ~doc in + let env = Cmd.Env.info "OMPDC_PORT" ~doc in Arg.(value & opt int 6600 & info ["p"; "port"] ~docs ~env ~docv:"PORT") in Term.(const common_opts $ host $ port) @@ -76,7 +76,7 @@ let help_cmd = in Term.(ret (const help $ common_opts_t $ Arg.man_format $ Term.choice_names $topic)), - Term.info "help" ~doc ~exits ~man + Cmd.info "help" ~doc ~exits ~man let initialize_client {host; port} = diff --git a/bin/Ompdc_idle.ml b/bin/Ompdc_idle.ml index c7fa90b..4590e88 100644 --- a/bin/Ompdc_idle.ml +++ b/bin/Ompdc_idle.ml @@ -170,4 +170,4 @@ let cmd = `Blocks help_section ] in Term.(const idle $ common_opts_t), - Term.info "idle" ~doc ~sdocs ~exits ~man + Cmd.info "idle" ~doc ~sdocs ~exits ~man diff --git a/bin/Ompdc_playback.ml b/bin/Ompdc_playback.ml index e801bfb..b2522c7 100644 --- a/bin/Ompdc_playback.ml +++ b/bin/Ompdc_playback.ml @@ -48,7 +48,7 @@ let play_t = `Blocks help_section; ] in Term.(const play $ common_opts_t $ song_pos), - Term.info "play" ~doc ~sdocs ~exits ~man + Cmd.info "play" ~doc ~sdocs ~exits ~man let play_id_t = let doc = "Play the song SONG_ID." @@ -59,7 +59,7 @@ let play_id_t = `Blocks help_section; ] in Term.(const play $ common_opts_t $ song_id), - Term.info "play_id" ~doc ~sdocs ~exits ~man + Cmd.info "play_id" ~doc ~sdocs ~exits ~man let time = let doc = "Float value that could represents the length of a song or the \ @@ -93,7 +93,7 @@ let seek_t = `Blocks help_section; ] in Term.(const seek $ common_opts_t $ song_pos $ time), - Term.info "seek" ~doc ~sdocs ~exits ~man + Cmd.info "seek" ~doc ~sdocs ~exits ~man let seek_id_t = let doc = "Play the song SONG_ID at TIME" @@ -104,7 +104,7 @@ let seek_id_t = `Blocks help_section; ] in Term.(const seek_id $ common_opts_t $ song_id $ time), - Term.info "seek_id" ~doc ~sdocs ~exits ~man + Cmd.info "seek_id" ~doc ~sdocs ~exits ~man let seek_cur_t = let doc = "Play the current song at TIME" in @@ -113,7 +113,7 @@ let seek_cur_t = `P doc; `Blocks help_section; ] in Term.(const seek_cur $ common_opts_t $ time), - Term.info "seek_cur" ~doc ~sdocs ~exits ~man + Cmd.info "seek_cur" ~doc ~sdocs ~exits ~man let next common_opts = let {host; port} = common_opts in @@ -130,7 +130,7 @@ let next_t = `Blocks help_section; ] in Term.(const next $ common_opts_t), - Term.info "next" ~doc ~sdocs ~exits ~man + Cmd.info "next" ~doc ~sdocs ~exits ~man let previous common_opts = let {host; port} = common_opts in @@ -147,7 +147,7 @@ let previous_t = `Blocks help_section; ] in Term.(const previous $ common_opts_t), - Term.info "previous" ~doc ~sdocs ~exits ~man + Cmd.info "previous" ~doc ~sdocs ~exits ~man let stop common_opts = let {host; port} = common_opts in @@ -164,7 +164,7 @@ let stop_t = `Blocks help_section; ] in Term.(const stop $ common_opts_t), - Term.info "stop" ~doc ~sdocs ~exits ~man + Cmd.info "stop" ~doc ~sdocs ~exits ~man let pause common_opts value = let {host; port} = common_opts in @@ -185,6 +185,6 @@ let pause_t = `Blocks help_section; ] in Term.(const pause $ common_opts_t $ toggle_value), - Term.info "pause" ~doc ~sdocs ~exits ~man + Cmd.info "pause" ~doc ~sdocs ~exits ~man let cmds = [play_t; play_id_t; seek_t; seek_id_t; seek_cur_t; next_t; previous_t; stop_t; pause_t] diff --git a/bin/Ompdc_playback_options.ml b/bin/Ompdc_playback_options.ml index f53fd22..ad08f0c 100644 --- a/bin/Ompdc_playback_options.ml +++ b/bin/Ompdc_playback_options.ml @@ -130,4 +130,4 @@ let cmd = Term.(const playback_options $ common_opts_t $ consume $ crossfade $ mixrampdb $ random $ repeat $ setvol $ single $ mixrampdelay $ replay_gain_mode), - Term.info "playback_options" ~doc ~sdocs ~exits ~man + Cmd.info "playback_options" ~doc ~sdocs ~exits ~man diff --git a/bin/Ompdc_status.ml b/bin/Ompdc_status.ml index 0015803..6018570 100644 --- a/bin/Ompdc_status.ml +++ b/bin/Ompdc_status.ml @@ -149,4 +149,4 @@ let cmd = `Blocks help_section ] in Term.(const get_status $ common_opts_t $ status_fields), - Term.info "status" ~doc ~sdocs ~exits ~man + Cmd.info "status" ~doc ~sdocs ~exits ~man diff --git a/bin/Ompdc_stored_playlists.ml b/bin/Ompdc_stored_playlists.ml index 8e9570c..bcebc81 100644 --- a/bin/Ompdc_stored_playlists.ml +++ b/bin/Ompdc_stored_playlists.ml @@ -37,7 +37,7 @@ let listplaylists_t = `Blocks help_section; ] in Term.(const listplaylists $ common_opts_t), - Term.info "listplaylists" ~doc ~sdocs ~exits ~man + Cmd.info "listplaylists" ~doc ~sdocs ~exits ~man let cmds = [listplaylists_t] diff --git a/bin/dune b/bin/dune index d6c7c1f..d15be45 100644 --- a/bin/dune +++ b/bin/dune @@ -1,5 +1,4 @@ (executable - (name ompdc) - (public_name ompdc) - (libraries libmpdclient lwt lwt.unix cmdliner notty notty.lwt unix) -) + (name ompdc) + (public_name ompdc) + (libraries libmpdclient lwt lwt.unix cmdliner notty notty.lwt unix)) diff --git a/bin/ompdc.ml b/bin/ompdc.ml index e06b82c..5f7134f 100644 --- a/bin/ompdc.ml +++ b/bin/ompdc.ml @@ -19,18 +19,20 @@ open Cmdliner open Ompdc_common -let default_cmd = +let default = + Term.(ret (const (fun _ -> `Help (`Pager, None)) $ common_opts_t)) + +let cmd_info = let doc = "a Mpd client written in OCaml." in let man = help_section in - Term.(ret (const (fun _ -> `Help (`Pager, None)) $ common_opts_t)), - Term.info "ompdc" ~version ~doc ~sdocs ~exits ~man + Cmd.info ~version ~doc ~sdocs ~exits ~man "ompdc" let cmds = List.concat [Ompdc_playback.cmds; Ompdc_stored_playlists.cmds; - [Ompdc_status.cmd; - Ompdc_idle.cmd; - Ompdc_playback_options.cmd; - help_cmd] - ] + [Ompdc_status.cmd; + Ompdc_idle.cmd; + Ompdc_playback_options.cmd; + help_cmd]] + |> List.map (fun t -> Cmd.v (snd t) (fst t)) -let () = Term.(exit @@ eval_choice default_cmd cmds) +let () = exit @@ Cmd.(eval @@ group ~default cmd_info cmds) diff --git a/lib/Client_lwt.mli b/lib/Client_lwt.mli index 2c77dfc..745440f 100644 --- a/lib/Client_lwt.mli +++ b/lib/Client_lwt.mli @@ -29,7 +29,7 @@ val mpd_banner: t -> string Lwt.t (** Return the mpd banner that the server send at the first connection of the client. *) -val idle: t -> (string, string) Pervasives.result Lwt.t +val idle: t -> (string, string) result Lwt.t (** Wait for an event to occur in order to return. When a Client send this * command to the Mpd server throught its connection, the Mpd server do * not answer to any other command except the noidle command. The idea is @@ -54,7 +54,7 @@ val request: an error while a request does not generate an action from Mpd and returns "some data to analyse"OK or an error.*) -val status: t -> (Status.t, string) Pervasives.result Lwt.t +val status: t -> (Status.t, string) result Lwt.t (** Create a status request and returns the status under a Mpd.Status.s Lwt.t type.*) diff --git a/lib/Connection.ml b/lib/Connection.ml index 316d806..a57db6c 100644 --- a/lib/Connection.ml +++ b/lib/Connection.ml @@ -88,7 +88,7 @@ let recvbytes t = let read t fn_to_check_for_pattern = let open Protocol in - let rec _read t = + let rec read t = match fn_to_check_for_pattern t.buffer with | Complete (response, u) -> ( let resp_len = (String.length response) + u in @@ -102,10 +102,10 @@ let read t fn_to_check_for_pattern = let bytes = recvbytes t in let buf = t.buffer ^ (Bytes.to_string bytes) in let () = t.buffer <- buf in - _read t + read t ) in - _read t + read t let read_mpd_banner connection = read connection Protocol.full_mpd_banner diff --git a/lib/Connection.mli b/lib/Connection.mli index 26cb4e5..bed86c5 100644 --- a/lib/Connection.mli +++ b/lib/Connection.mli @@ -37,8 +37,8 @@ val close: t -> unit val write: t -> string -> unit (** Write to an Mpd connection *) -(** val read: t -> string -Read in an Mpd connection *) +val read: t -> (string -> Protocol.mpd_response) -> string +(** Read in an Mpd connection *) val read_mpd_banner: t -> string (** Read in an Mpd connection *) diff --git a/lib/dune b/lib/dune index f99e68b..121fe46 100644 --- a/lib/dune +++ b/lib/dune @@ -1,5 +1,4 @@ (library - (name Mpd) - (public_name libmpdclient) - (libraries unix lwt lwt.unix str logs fmt logs.lwt logs.fmt) -) + (name Mpd) + (public_name libmpdclient) + (libraries unix lwt lwt.unix str logs fmt logs.lwt logs.fmt)) diff --git a/samples/dune b/samples/dune index 19fc89f..4a90e94 100644 --- a/samples/dune +++ b/samples/dune @@ -1,19 +1,9 @@ (executables - (names try_mpd_queries - mpd_status_query - mpd_tagtypes_query - mpd_volume_query - mpd_playlist_info - mpd_lwt_playlist_info - mpd_lwt_client_idle_loop - mpd_lwt_client_idle - mpd_lwt_client_idle_noidle - mpd_lwt_count - mpd_count - mpd_lwt_send_ping - mpd_lwt_ping - mpd_lwt_send_cmd - mpd_lwt_status - get_mpd_responses) - (libraries libmpdclient lwt lwt.unix) -) + (names try_mpd_queries mpd_status_query mpd_tagtypes_query mpd_volume_query + mpd_playlist_info mpd_lwt_playlist_info mpd_lwt_client_idle_loop + mpd_lwt_client_idle mpd_lwt_client_idle_noidle mpd_lwt_count mpd_count + mpd_lwt_send_ping mpd_lwt_ping mpd_lwt_send_cmd mpd_lwt_status + get_mpd_responses) + (libraries libmpdclient lwt lwt.unix stdlib) + (preprocess + (pps lwt_ppx))) diff --git a/samples/get_mpd_responses.ml b/samples/get_mpd_responses.ml index 64814ec..fefcd7a 100644 --- a/samples/get_mpd_responses.ml +++ b/samples/get_mpd_responses.ml @@ -16,10 +16,6 @@ * along with OCaml-libmpdclient. If not, see . *) -open Sys -open Unix -open Pervasives - (* * tool to get mpd response that will be used in tests * *) @@ -29,7 +25,7 @@ let port = 6600 let fd = let flags = [Open_trunc; Open_append; Open_creat] in let perm = 0o666 in - Pervasives.open_out_gen flags perm "responses" + Stdlib.open_out_gen flags perm "responses" let write_down question response = let _ = Printf.fprintf fd "question -|%s|-\n" question in @@ -48,14 +44,14 @@ let queries = ["ping"; let () = let connection = Mpd.Connection.initialize host port in - let banner = Mpd.Connection.read connection in + let banner = Mpd.Connection.read_mpd_banner connection in let _ = print_endline ("Server banner : " ^ banner) in let rec loop = function - | [] -> Pervasives.close_out fd + | [] -> Stdlib.close_out fd | q :: t -> let query = q ^ "\n" in let _ = Mpd.Connection.write connection query in - let response = Mpd.Connection.read connection in + let response = Mpd.Connection.read connection (fun s -> Mpd.Protocol.Complete (s, 0)) in let _ = write_down query response in loop t in diff --git a/samples/mpd_count.ml b/samples/mpd_count.ml index 7ab5069..25eefde 100644 --- a/samples/mpd_count.ml +++ b/samples/mpd_count.ml @@ -24,7 +24,7 @@ open Mpd.Music_database let () = let connection = Mpd.Connection.initialize host port in let client = Mpd.Client.initialize connection in - match Mpd.Music_database.count client [] ~group:Mpd.Music_database.Artist () with + match Mpd.Music_database.count client [] ~group:Mpd.Tags.Artist () with | Error message -> print_endline message | Ok count -> List.iter (fun {songs; playtime; misc} -> diff --git a/samples/mpd_lwt_client_idle.ml b/samples/mpd_lwt_client_idle.ml index d95bdc4..53e6e35 100644 --- a/samples/mpd_lwt_client_idle.ml +++ b/samples/mpd_lwt_client_idle.ml @@ -18,7 +18,6 @@ *) open Lwt -open Mpd (* Simple client that connects to a mpd server with the "idle" command and get * one event of the mpd server. *) @@ -35,18 +34,19 @@ let main_thread = (fun () -> Mpd.Connection_lwt.initialize host port >>= fun connection -> - Mpd.Client_lwt.initialize connection - >>= fun client -> - Lwt_io.write_line Lwt_io.stdout (Mpd.Client_lwt.mpd_banner client) - >>= fun () -> - Mpd.Client_lwt.idle client - >>= function - | Error message -> Mpd.Client_lwt.close client - >>= fun () -> - Lwt_io.write_line Lwt_io.stdout message >|= fun () -> 125 - | Ok event_name -> Lwt_io.write_line Lwt_io.stdout event_name - >>= fun () -> - Mpd.Client_lwt.close client >|= fun () -> 0 + Mpd.Client_lwt.initialize connection + >>= fun client -> + let%lwt banner = Mpd.Client_lwt.mpd_banner client in + Lwt_io.write_line Lwt_io.stdout banner + >>= fun () -> + Mpd.Client_lwt.idle client + >>= function + | Error message -> Mpd.Client_lwt.close client + >>= fun () -> + Lwt_io.write_line Lwt_io.stdout message >|= fun () -> 125 + | Ok event_name -> Lwt_io.write_line Lwt_io.stdout event_name + >>= fun () -> + Mpd.Client_lwt.close client >|= fun () -> 0 ) (function | Mpd.Connection_lwt.Lwt_unix_exn message -> diff --git a/samples/mpd_lwt_client_idle_loop.ml b/samples/mpd_lwt_client_idle_loop.ml index b9750c3..ab14867 100644 --- a/samples/mpd_lwt_client_idle_loop.ml +++ b/samples/mpd_lwt_client_idle_loop.ml @@ -18,7 +18,6 @@ *) open Lwt -open Mpd (* Simple client that connects to a mpd server with the "idle" command and get * all the events of the mpd server. @@ -39,8 +38,9 @@ let main_thread = Lwt_io.write_line Lwt_io.stdout "Client on" >>= fun () -> Mpd.Client_lwt.initialize connection - >>= fun client -> - Lwt_io.write_line Lwt_io.stdout (Mpd.Client_lwt.mpd_banner client) + >>= fun client -> + let%lwt banner = Mpd.Client_lwt.mpd_banner client in + Lwt_io.write_line Lwt_io.stdout banner >>= fun () -> Mpd.Client_lwt.idle_loop client on_mpd_event >>= fun () -> diff --git a/samples/mpd_lwt_client_idle_noidle.ml b/samples/mpd_lwt_client_idle_noidle.ml index 74a47c0..b909f87 100644 --- a/samples/mpd_lwt_client_idle_noidle.ml +++ b/samples/mpd_lwt_client_idle_noidle.ml @@ -18,7 +18,6 @@ *) open Lwt -open Mpd (* Simple client that connects to a mpd server with the "idle" command and get * one event of the mpd server. *) @@ -33,42 +32,43 @@ let main_thread = >>= fun connection -> Mpd.Client_lwt.initialize connection >>= fun client -> - Lwt_io.write_line Lwt_io.stdout (Mpd.Client_lwt.mpd_banner client) - >>= fun () -> - Lwt.join [ - let thread1 = begin - Lwt_io.write_line Lwt_io.stdout "Thread one: idle" + let%lwt banner = Mpd.Client_lwt.mpd_banner client in + Lwt_io.write_line Lwt_io.stdout banner + >>= fun () -> + let thread1 = begin + Lwt_io.write_line Lwt_io.stdout "Thread one: idle" + >>= fun () -> + Mpd.Client_lwt.idle client + >>= function + | Error message -> + Lwt_io.write_line Lwt_io.stdout message + | Ok event_name -> + Lwt_io.write_line Lwt_io.stdout event_name + end in + let _ = Lwt.on_cancel thread1 (fun () -> + Lwt_io.write_line Lwt_io.stdout "Thread one: canceled" + |> Lwt.ignore_result) in + let thread2 = begin + Lwt_io.write_line Lwt_io.stdout "Thread two: Wait" + >>= fun () -> + Lwt_unix.sleep 5.0 + >>= fun () -> + Lwt_io.write_line Lwt_io.stdout "Thread two: cancel thread one" >>= fun () -> - Mpd.Client_lwt.idle client - >>= function - | Error message -> - Lwt_io.write_line Lwt_io.stdout message - | Ok event_name -> - Lwt_io.write_line Lwt_io.stdout event_name - end in - let _ = Lwt.on_cancel thread1 (fun () -> - Lwt_io.write_line Lwt_io.stdout "Thread one: canceled" - |> Lwt.ignore_result) in - thread1; - let thread2 = begin - Lwt_io.write_line Lwt_io.stdout "Thread two: Wait" + Lwt.cancel thread1; + Lwt.return_unit >>= fun () -> - Lwt_unix.sleep 5.0 - >>= fun () -> - Lwt_io.write_line Lwt_io.stdout "Thread two: cancel thread one" - >>= fun () -> - Lwt.cancel thread1; - Lwt.return_unit - >>= fun () -> - Lwt_io.write_line Lwt_io.stdout "Thread two: send noidle" - >>= fun () -> - Mpd.Client_lwt.noidle client - >>= fun _ -> - Lwt_io.write_line Lwt_io.stdout "Thread two: noidle sent" - end - in thread2; - - ] + Lwt_io.write_line Lwt_io.stdout "Thread two: send noidle" + >>= fun () -> + Mpd.Client_lwt.noidle client + >>= fun _ -> + Lwt_io.write_line Lwt_io.stdout "Thread two: noidle sent" + end + in + Lwt.join [ + thread1; + thread2; + ] >>= fun () -> Mpd.Client_lwt.close client diff --git a/samples/mpd_lwt_count.ml b/samples/mpd_lwt_count.ml index dfc1071..121e014 100644 --- a/samples/mpd_lwt_count.ml +++ b/samples/mpd_lwt_count.ml @@ -32,7 +32,7 @@ let main_thread = >>= fun connection -> Client_lwt.initialize connection >>= fun client -> - Music_database_lwt.count client [] ~group:(Music_database_lwt.Artist) () + Music_database_lwt.count client [] ~group:(Tags.Artist) () >>= function | Error message -> lwt_print_line message | Ok count -> lwt_print_line (string_of_int (List.length count)) diff --git a/samples/mpd_lwt_send_ping.ml b/samples/mpd_lwt_send_ping.ml index 51c95ba..6be14df 100644 --- a/samples/mpd_lwt_send_ping.ml +++ b/samples/mpd_lwt_send_ping.ml @@ -34,7 +34,7 @@ let main_thread = >>= fun _ -> Connection_lwt.write connection "ping\n" >>= fun _ -> - Connection_lwt.recvstr connection + Connection_lwt.recvbytes connection >>= fun buf -> lwt_print_line (Printf.sprintf "received : %s" (Bytes.to_string buf)) >>= fun () -> diff --git a/samples/mpd_playlist_info.ml b/samples/mpd_playlist_info.ml index ae7a253..13873fa 100644 --- a/samples/mpd_playlist_info.ml +++ b/samples/mpd_playlist_info.ml @@ -16,9 +16,6 @@ * along with OCaml-libmpdclient. If not, see . *) -open Sys -open Unix - (* compile with * ocamlfind ocamlc -o mpd_playlist_info -package str,unix -linkpkg -g mpd_responses.ml mpd.ml mpd_playlist_info.ml * or diff --git a/samples/mpd_status_query.ml b/samples/mpd_status_query.ml index df73970..f4d00fd 100644 --- a/samples/mpd_status_query.ml +++ b/samples/mpd_status_query.ml @@ -16,9 +16,6 @@ * along with OCaml-libmpdclient. If not, see . *) -open Sys -open Unix - (* compile with * ocamlfind ocamlc -o mpd_status_query -package str,unix -linkpkg -g mpd_responses.ml mpd.ml mpd_status_query.ml * or @@ -31,9 +28,9 @@ let port = 6600 let () = let connection = Mpd.Connection.initialize host port in - print_endline ("received: " ^ (Mpd.Connection.read connection)); + print_endline ("received: " ^ (Mpd.Connection.read connection (fun s -> Mpd.Protocol.Complete (s, 0)))); Mpd.Connection.write connection ("status\n"); - let status = Mpd.Connection.read connection in + let status = Mpd.Connection.read connection (fun s -> Mpd.Protocol.Complete (s, 0)) in let lines = Mpd.Utils.split_lines status in let rec display_infos = function | [] -> Mpd.Connection.close connection diff --git a/samples/mpd_tagtypes_query.ml b/samples/mpd_tagtypes_query.ml index 6ac7d7e..26d8d7d 100644 --- a/samples/mpd_tagtypes_query.ml +++ b/samples/mpd_tagtypes_query.ml @@ -16,9 +16,6 @@ * along with OCaml-libmpdclient. If not, see . *) -open Sys -open Unix - (* compile with * ocamlfind ocamlc -o mpd_tagtypes_query -package str,unix -linkpkg -g mpd_responses.ml mpd.ml mpd_tagtypes_query.ml * or diff --git a/samples/mpd_volume_query.ml b/samples/mpd_volume_query.ml index 06a0de6..7e55fa0 100644 --- a/samples/mpd_volume_query.ml +++ b/samples/mpd_volume_query.ml @@ -16,9 +16,6 @@ * along with OCaml-libmpdclient. If not, see . *) -open Sys -open Unix - (* compile with * ocamlfind ocamlc -o mpd_volume_query -package str,unix -linkpkg -g mpd_responses.ml mpd.ml mpd_volume_query.ml * or diff --git a/samples/try_mpd_queries.ml b/samples/try_mpd_queries.ml index ac8b1e6..bbfdcb3 100644 --- a/samples/try_mpd_queries.ml +++ b/samples/try_mpd_queries.ml @@ -16,9 +16,6 @@ * along with OCaml-libmpdclient. If not, see . *) -open Sys -open Unix - (* compile with * ocamlfind ocamlc -o try_mpd_queries -package str,unix -linkpkg -g mpd_responses.ml mpd.ml try_mpd_queries.ml * or @@ -31,7 +28,7 @@ let port = 6600 let () = let connection = Mpd.Connection.initialize host port in - print_endline ("received: " ^ (Mpd.Connection.read connection)); + print_endline ("received: " ^ (Mpd.Connection.read connection (fun s -> Mpd.Protocol.Complete (s, 0)))); Mpd.Connection.write connection (Sys.argv.(1) ^"\n"); - print_endline ("received: " ^ (Mpd.Connection.read connection)); + print_endline ("received: " ^ (Mpd.Connection.read connection (fun s -> Mpd.Protocol.Complete (s, 0)))); Mpd.Connection.close connection; diff --git a/tests/dune b/tests/dune index 81fadad..610c10f 100644 --- a/tests/dune +++ b/tests/dune @@ -1,4 +1,3 @@ (test - (name test) - (libraries libmpdclient lwt lwt.unix unix oUnit logs logs.lwt logs.fmt) -) + (name test) + (libraries libmpdclient lwt lwt.unix unix oUnit logs logs.lwt logs.fmt)) From 0efc0362136aa00134cb3964f8b7cd072cb16a1b Mon Sep 17 00:00:00 2001 From: Yuriy Shirokov Date: Fri, 23 Jun 2023 02:35:03 +0400 Subject: [PATCH 2/4] Standard formatting --- .ocamlformat | 0 bin/Ompdc_common.ml | 102 +++++---- bin/Ompdc_idle.ml | 188 ++++++++--------- bin/Ompdc_playback.ml | 173 +++++++-------- bin/Ompdc_playback_options.ml | 114 +++++----- bin/Ompdc_status.ml | 196 ++++++++++------- bin/Ompdc_stored_playlists.ml | 24 +-- bin/ompdc.ml | 18 +- bin/ompdc_bad_implementation.ml | 203 +++++++++--------- lib/Client.ml | 69 +++--- lib/Client.mli | 20 +- lib/Client_lwt.ml | 114 +++++----- lib/Client_lwt.mli | 24 +-- lib/Connection.ml | 73 +++---- lib/Connection.mli | 18 +- lib/Connection_lwt.ml | 210 ++++++++---------- lib/Connection_lwt.mli | 23 +- lib/Music_database.ml | 96 ++++----- lib/Music_database.mli | 47 +++-- lib/Music_database_lwt.ml | 102 ++++----- lib/Music_database_lwt.mli | 60 +++--- lib/Playback.ml | 26 ++- lib/Playback.mli | 18 +- lib/Playback_lwt.ml | 31 +-- lib/Playback_lwt.mli | 27 +-- lib/Playback_options.ml | 37 ++-- lib/Playback_options.mli | 28 +-- lib/Playback_options_lwt.ml | 35 ++- lib/Playback_options_lwt.mli | 24 +-- lib/Protocol.ml | 89 ++++---- lib/Protocol.mli | 57 +++-- lib/Queue.ml | 219 ++++++++++--------- lib/Queue.mli | 58 ++--- lib/Queue_lwt.ml | 233 ++++++++++---------- lib/Queue_lwt.mli | 63 +++--- lib/Song.ml | 237 +++++++++------------ lib/Song.mli | 48 ++--- lib/Status.ml | 199 ++++++++--------- lib/Status.mli | 58 ++--- lib/Stored_playlists.ml | 37 ++-- lib/Stored_playlists.mli | 27 +-- lib/Stored_playlists_lwt.ml | 43 ++-- lib/Stored_playlists_lwt.mli | 27 +-- lib/Tags.ml | 3 +- lib/loggin.ml | 60 +++--- lib/utils.ml | 100 +++++---- samples/get_mpd_responses.ml | 39 ++-- samples/mpd_count.ml | 7 +- samples/mpd_lwt_client_idle.ml | 56 +++-- samples/mpd_lwt_client_idle_loop.ml | 48 ++--- samples/mpd_lwt_client_idle_noidle.ml | 85 +++----- samples/mpd_lwt_count.ml | 32 ++- samples/mpd_lwt_ping.ml | 27 +-- samples/mpd_lwt_playlist_info.ml | 44 ++-- samples/mpd_lwt_send_cmd.ml | 29 +-- samples/mpd_lwt_send_ping.ml | 28 +-- samples/mpd_lwt_status.ml | 30 ++- samples/mpd_playlist_info.ml | 27 +-- samples/mpd_status_query.ml | 25 ++- samples/mpd_tagtypes_query.ml | 8 +- samples/mpd_volume_query.ml | 17 +- samples/try_mpd_queries.ml | 14 +- tests/Test_connection_and_client.ml | 104 +++++---- tests/Test_connection_and_client_lwt.ml | 132 ++++++------ tests/Test_music_database.ml | 136 ++++++------ tests/Test_music_database_lwt.ml | 208 +++++++++--------- tests/Test_queue_and_playlists.ml | 125 ++++++----- tests/Test_queue_and_playlists_lwt.ml | 170 ++++++++------- tests/Test_regexp_uses.ml | 270 ++++++++++++------------ tests/Test_utils.ml | 132 ++++++------ tests/test.ml | 22 +- 71 files changed, 2659 insertions(+), 2814 deletions(-) create mode 100644 .ocamlformat diff --git a/.ocamlformat b/.ocamlformat new file mode 100644 index 0000000..e69de29 diff --git a/bin/Ompdc_common.ml b/bin/Ompdc_common.ml index e9ce0c5..2ce6162 100644 --- a/bin/Ompdc_common.ml +++ b/bin/Ompdc_common.ml @@ -24,42 +24,53 @@ let sdocs = Manpage.s_common_options let docs = Manpage.s_common_options let exits = Cmd.Exit.defaults -let help _copts man_format cmds topic = match topic with -| None -> `Help (`Pager, None) (* help about the program. *) -| Some topic -> - let topics = "topics" :: "patterns" :: "environment" :: cmds in - let conv, _ = Cmdliner.Arg.enum (List.rev_map (fun s -> (s, s)) topics) in - match conv topic with - | `Error e -> `Error (false, e) - | `Ok t when t = "topics" -> List.iter print_endline topics; `Ok () - | `Ok t when List.mem t cmds -> `Help (man_format, Some t) - | `Ok _ -> - let page = (topic, 7, "", "", ""), [`S topic; `P "Say something";] in - `Ok (Cmdliner.Manpage.print man_format Format.std_formatter page) +let help _copts man_format cmds topic = + match topic with + | None -> `Help (`Pager, None) (* help about the program. *) + | Some topic -> ( + let topics = "topics" :: "patterns" :: "environment" :: cmds in + let conv, _ = Cmdliner.Arg.enum (List.rev_map (fun s -> (s, s)) topics) in + match conv topic with + | `Error e -> `Error (false, e) + | `Ok t when t = "topics" -> + List.iter print_endline topics; + `Ok () + | `Ok t when List.mem t cmds -> `Help (man_format, Some t) + | `Ok _ -> + let page = + ((topic, 7, "", "", ""), [ `S topic; `P "Say something" ]) + in + `Ok (Cmdliner.Manpage.print man_format Format.std_formatter page)) -let help_section = [ - `S Manpage.s_common_options; - `P "These options are common to all commands."; - `S Manpage.s_bugs; `P "Check bug reports at https://github.com/cedlemo/OCaml-libmpdclient/issues"; - `S Manpage.s_authors; `P "Cedric Le Moigne " - ] +let help_section = + [ + `S Manpage.s_common_options; + `P "These options are common to all commands."; + `S Manpage.s_bugs; + `P + "Check bug reports at \ + https://github.com/cedlemo/OCaml-libmpdclient/issues"; + `S Manpage.s_authors; + `P "Cedric Le Moigne "; + ] (* Options common to all commands *) -type mpd_opts = {host : string; port : int} +type mpd_opts = { host : string; port : int } -let common_opts host port = - {host; port} +let common_opts host port = { host; port } let common_opts_t = let host = let doc = "Set the address of the Mpd server." in let env = Cmd.Env.info "OMPDC_HOST" ~doc in - Arg.(value & opt string "127.0.0.1" & info ["h"; "host"] ~docs ~env ~docv:"HOST") + Arg.( + value & opt string "127.0.0.1" + & info [ "h"; "host" ] ~docs ~env ~docv:"HOST") in let port = let doc = "Set the port of the Mpd server." in let env = Cmd.Env.info "OMPDC_PORT" ~doc in - Arg.(value & opt int 6600 & info ["p"; "port"] ~docs ~env ~docv:"PORT") + Arg.(value & opt int 6600 & info [ "p"; "port" ] ~docs ~env ~docv:"PORT") in Term.(const common_opts $ host $ port) @@ -70,34 +81,35 @@ let help_cmd = in let doc = "display help about ompdc and ompdc commands" in let man = - [`S Manpage.s_description; - `P "Prints help about ompdc commands and other subjects..."; - `Blocks help_section; ] + [ + `S Manpage.s_description; + `P "Prints help about ompdc commands and other subjects..."; + `Blocks help_section; + ] in - Term.(ret - (const help $ common_opts_t $ Arg.man_format $ Term.choice_names $topic)), - Cmd.info "help" ~doc ~exits ~man + ( Term.( + ret + (const help $ common_opts_t $ Arg.man_format $ Term.choice_names $ topic)), + Cmd.info "help" ~doc ~exits ~man ) - -let initialize_client {host; port} = - let connection = Mpd.Connection.initialize host port in - let client = Mpd.Client.initialize connection in - let _ = print_endline ("Mpd server : " ^ (Mpd.Client.mpd_banner client)) in - client +let initialize_client { host; port } = + let connection = Mpd.Connection.initialize host port in + let client = Mpd.Client.initialize connection in + let _ = print_endline ("Mpd server : " ^ Mpd.Client.mpd_banner client) in + client let check_for_mpd_error mpd_response = - let response = ( + let response = match mpd_response with | Ok msg -> ( - match msg with - | None -> "" - | Some str -> "Mpd response: " ^ str - ) + match msg with None -> "" | Some str -> "Mpd response: " ^ str) | Error (ack_error, _ack_cmd_num, _ack_cmd, ack_message) -> - String.concat " " ["Error type:"; - Mpd.Protocol.error_name ack_error; - "-- error message:"; - ack_message] - ) + String.concat " " + [ + "Error type:"; + Mpd.Protocol.error_name ack_error; + "-- error message:"; + ack_message; + ] in print_endline response diff --git a/bin/Ompdc_idle.ml b/bin/Ompdc_idle.ml index 4590e88..5edba7a 100644 --- a/bin/Ompdc_idle.ml +++ b/bin/Ompdc_idle.ml @@ -19,7 +19,6 @@ open Lwt.Infix open Notty open Ompdc_common - module Terminal = Notty_lwt.Term type status = { @@ -31,30 +30,29 @@ type status = { } let fetch_status client = - Mpd.Client_lwt.status client - >>= fun response -> - match response with - | Error message -> Lwt.return (Error message) - | Ok s -> - let timestamp = Unix.time () in - let state = Mpd.Status.state s in - let volume = Mpd.Status.volume s in - let song = Mpd.Status.song s in - Mpd.Queue_lwt.playlist client - >>= fun queue -> - Lwt.return (Ok {timestamp; state; volume; queue; song}) + Mpd.Client_lwt.status client >>= fun response -> + match response with + | Error message -> Lwt.return (Error message) + | Ok s -> + let timestamp = Unix.time () in + let state = Mpd.Status.state s in + let volume = Mpd.Status.volume s in + let song = Mpd.Status.song s in + Mpd.Queue_lwt.playlist client >>= fun queue -> + Lwt.return (Ok { timestamp; state; volume; queue; song }) let update_status status client = match status with | Error _ -> Lwt.return status - | Ok s -> Mpd.Client_lwt.noidle client - >>= fun _ -> - let now = Unix.time () in - if ((now -. s.timestamp) > 4.0) then fetch_status client - else Lwt.return status + | Ok s -> + Mpd.Client_lwt.noidle client >>= fun _ -> + let now = Unix.time () in + if now -. s.timestamp > 4.0 then fetch_status client + else Lwt.return status let gen_state_img status = - let state_img = match status.state with + let state_img = + match status.state with | Mpd.Status.Play -> I.(string A.(fg green) "play") | Mpd.Status.Pause -> I.(string A.(fg lightblack) "Pause") | Mpd.Status.Stop -> I.(string A.(fg black ++ bg lightblack) "Stop") @@ -63,111 +61,109 @@ let gen_state_img status = I.(string A.(fg white) "[state ] : " <|> state_img) let gen_volume_img status = - I.(strf ~attr:A.(fg white) "[volume] : %d" status.volume) + I.(strf ~attr:A.(fg white) "[volume] : %d" status.volume) let gen_playlist_img status (w, _h) = match status.queue with - | PlaylistError message -> Lwt.return I.(strf ~attr:A.(fg red) "Error: %s" message) + | PlaylistError message -> + Lwt.return I.(strf ~attr:A.(fg red) "Error: %s" message) | Playlist songs -> - let gen_song_img i song = - let title = Mpd.Song.title song in - let artist = Mpd.Song.artist song in - if status.song = i then - I.(strf ~attr:A.(fg lightred ++ bg lightblack) "+ %s : %s" title artist) - else - I.(strf ~attr:A.(fg lightblack) "- %s : %s" title artist) - in - let song_imgs = List.mapi gen_song_img songs in - let lines = List.map (fun i -> - let left_margin = 4 in - let i_w = I.width i in - let remain = let r = w - (i_w + left_margin) in (max r 0) in - I.hpad left_margin remain i) - song_imgs in - Lwt.return I.(vcat lines) + let gen_song_img i song = + let title = Mpd.Song.title song in + let artist = Mpd.Song.artist song in + if status.song = i then + I.( + strf ~attr:A.(fg lightred ++ bg lightblack) "+ %s : %s" title artist) + else I.(strf ~attr:A.(fg lightblack) "- %s : %s" title artist) + in + let song_imgs = List.mapi gen_song_img songs in + let lines = + List.map + (fun i -> + let left_margin = 4 in + let i_w = I.width i in + let remain = + let r = w - (i_w + left_margin) in + max r 0 + in + I.hpad left_margin remain i) + song_imgs + in + Lwt.return I.(vcat lines) let render status (w, h) = - match status with - | Error message -> Lwt.return I.(strf ~attr:A.(fg red) "[there is a pb %s]" message) - | Ok status -> let state_img = gen_state_img status in + match status with + | Error message -> + Lwt.return I.(strf ~attr:A.(fg red) "[there is a pb %s]" message) + | Ok status -> + let state_img = gen_state_img status in let volume_img = gen_volume_img status in - gen_playlist_img status (w, h) - >>= fun songs_img -> + gen_playlist_img status (w, h) >>= fun songs_img -> Lwt.return I.(state_img <-> volume_img <-> songs_img) let listen_mpd_event client = Mpd.Client_lwt.idle client >|= fun evt -> `Mpd_event evt -let event term = Lwt_stream.get (Terminal.events term) >|= function - | Some (`Resize _ | #Unescape.event as x) -> x +let event term = + Lwt_stream.get (Terminal.events term) >|= function + | Some ((`Resize _ | #Unescape.event) as x) -> x | None -> `End let rec loop term (e, t) dim client status = - (e t) >>= function - | `End | `Key (`Escape, []) | `Key (`ASCII 'C', [`Ctrl]) -> + e t >>= function + | `End | `Key (`Escape, []) | `Key (`ASCII 'C', [ `Ctrl ]) -> Mpd.Client_lwt.close client | `Mpd_event _event_name -> - fetch_status client - >>= fun status' -> - render status' dim - >>= fun img -> - Terminal.image term img - >>= fun () -> - loop term (e, listen_mpd_event client) dim client status' + fetch_status client >>= fun status' -> + render status' dim >>= fun img -> + Terminal.image term img >>= fun () -> + loop term (e, listen_mpd_event client) dim client status' | `Resize dim -> - update_status status client - >>= fun status' -> - render status' dim - >>= fun img -> - Terminal.image term img - >>= fun () -> - loop term (event term, t) dim client status' + update_status status client >>= fun status' -> + render status' dim >>= fun img -> + Terminal.image term img >>= fun () -> + loop term (event term, t) dim client status' | _ -> - update_status status client - >>= fun status' -> - render status' dim - >>= fun img -> - Terminal.image term img - >>= fun () -> - loop term (event term, t) dim client status' + update_status status client >>= fun status' -> + render status' dim >>= fun img -> + Terminal.image term img >>= fun () -> + loop term (event term, t) dim client status' let interface client = let term = Terminal.create () in let size = Terminal.size term in - fetch_status client - >>= fun result_status -> - render result_status size - >>= fun img -> - Terminal.image term img - >>= fun () -> - loop term (event term, listen_mpd_event client) size client result_status + fetch_status client >>= fun result_status -> + render result_status size >>= fun img -> + Terminal.image term img >>= fun () -> + loop term (event term, listen_mpd_event client) size client result_status let idle common_opts = let open Mpd in - let {host; port} = common_opts in + let { host; port } = common_opts in let main_thread = - Connection_lwt.initialize host port - >>= fun connection -> - Client_lwt.initialize connection - >>= fun client -> - interface client + Connection_lwt.initialize host port >>= fun connection -> + Client_lwt.initialize connection >>= fun client -> interface client in - Lwt_main.run ( - Lwt.catch - (fun () -> main_thread) - (function - | Mpd.Connection_lwt.Lwt_unix_exn message -> - Lwt_io.write_line Lwt_io.stderr message - | _ -> Lwt_io.write_line Lwt_io.stderr "Exception not handled. Exit ..." - ) - ) + Lwt_main.run + (Lwt.catch + (fun () -> main_thread) + (function + | Mpd.Connection_lwt.Lwt_unix_exn message -> + Lwt_io.write_line Lwt_io.stderr message + | _ -> + Lwt_io.write_line Lwt_io.stderr "Exception not handled. Exit ...")) open Cmdliner + let cmd = - let doc = "Use Ompdc as an Mpd server events listener. Quit with Ctl+Alt+C." in - let man = [ `S Manpage.s_description; - `P "Idle command that display events of the Mpd server."; - `Blocks help_section - ] in - Term.(const idle $ common_opts_t), - Cmd.info "idle" ~doc ~sdocs ~exits ~man + let doc = + "Use Ompdc as an Mpd server events listener. Quit with Ctl+Alt+C." + in + let man = + [ + `S Manpage.s_description; + `P "Idle command that display events of the Mpd server."; + `Blocks help_section; + ] + in + (Term.(const idle $ common_opts_t), Cmd.info "idle" ~doc ~sdocs ~exits ~man) diff --git a/bin/Ompdc_playback.ml b/bin/Ompdc_playback.ml index b2522c7..bc4a9a5 100644 --- a/bin/Ompdc_playback.ml +++ b/bin/Ompdc_playback.ml @@ -20,19 +20,22 @@ open Cmdliner open Ompdc_common let play common_opts song_pos = - let {host; port} = common_opts in - let client = initialize_client {host; port} in + let { host; port } = common_opts in + let client = initialize_client { host; port } in let _ = check_for_mpd_error @@ Mpd.Playback.play client song_pos in Mpd.Client.close client let play_id common_opts song_id = - let {host; port} = common_opts in - let client = initialize_client {host; port} in + let { host; port } = common_opts in + let client = initialize_client { host; port } in let _ = check_for_mpd_error @@ Mpd.Playback.playid client song_id in Mpd.Client.close client let song_pos = - let doc = "Integer value that represents the position of a song in the current playlist." in + let doc = + "Integer value that represents the position of a song in the current \ + playlist." + in Arg.(value & pos 0 int 0 & info [] ~doc ~docv:"SONG_POS") let song_id = @@ -40,135 +43,97 @@ let song_id = Arg.(value & pos 0 int 0 & info [] ~doc ~docv:"SONG_ID") let play_t = - let doc = "Play the song at SONG_POS in the playlist" - in - let man = [ - `S Manpage.s_description; - `P doc; - `Blocks help_section; ] - in - Term.(const play $ common_opts_t $ song_pos), - Cmd.info "play" ~doc ~sdocs ~exits ~man + let doc = "Play the song at SONG_POS in the playlist" in + let man = [ `S Manpage.s_description; `P doc; `Blocks help_section ] in + ( Term.(const play $ common_opts_t $ song_pos), + Cmd.info "play" ~doc ~sdocs ~exits ~man ) let play_id_t = - let doc = "Play the song SONG_ID." - in - let man = [ - `S Manpage.s_description; - `P doc; - `Blocks help_section; ] - in - Term.(const play $ common_opts_t $ song_id), - Cmd.info "play_id" ~doc ~sdocs ~exits ~man + let doc = "Play the song SONG_ID." in + let man = [ `S Manpage.s_description; `P doc; `Blocks help_section ] in + ( Term.(const play $ common_opts_t $ song_id), + Cmd.info "play_id" ~doc ~sdocs ~exits ~man ) let time = - let doc = "Float value that could represents the length of a song or the \ - starting point to play" in + let doc = + "Float value that could represents the length of a song or the starting \ + point to play" + in Arg.(value & pos 1 float 0.0 & info [] ~doc ~docv:"TIME") let seek common_opts song_pos time = - let {host; port} = common_opts in - let client = initialize_client {host; port} in + let { host; port } = common_opts in + let client = initialize_client { host; port } in let _ = check_for_mpd_error @@ Mpd.Playback.seek client song_pos time in Mpd.Client.close client let seek_id common_opts song_id time = - let {host; port} = common_opts in - let client = initialize_client {host; port} in + let { host; port } = common_opts in + let client = initialize_client { host; port } in let _ = check_for_mpd_error @@ Mpd.Playback.seekid client song_id time in Mpd.Client.close client let seek_cur common_opts time = - let {host; port} = common_opts in - let client = initialize_client {host; port} in + let { host; port } = common_opts in + let client = initialize_client { host; port } in let _ = check_for_mpd_error @@ Mpd.Playback.seekcur client time in Mpd.Client.close client let seek_t = - let doc = "Play the song at SONG_POS in the playlist at TIME" - in - let man = [ - `S Manpage.s_description; - `P doc; - `Blocks help_section; ] - in - Term.(const seek $ common_opts_t $ song_pos $ time), - Cmd.info "seek" ~doc ~sdocs ~exits ~man + let doc = "Play the song at SONG_POS in the playlist at TIME" in + let man = [ `S Manpage.s_description; `P doc; `Blocks help_section ] in + ( Term.(const seek $ common_opts_t $ song_pos $ time), + Cmd.info "seek" ~doc ~sdocs ~exits ~man ) let seek_id_t = - let doc = "Play the song SONG_ID at TIME" - in - let man = [ - `S Manpage.s_description; - `P doc; - `Blocks help_section; ] - in - Term.(const seek_id $ common_opts_t $ song_id $ time), - Cmd.info "seek_id" ~doc ~sdocs ~exits ~man + let doc = "Play the song SONG_ID at TIME" in + let man = [ `S Manpage.s_description; `P doc; `Blocks help_section ] in + ( Term.(const seek_id $ common_opts_t $ song_id $ time), + Cmd.info "seek_id" ~doc ~sdocs ~exits ~man ) let seek_cur_t = let doc = "Play the current song at TIME" in - let man = [ - `S Manpage.s_description; - `P doc; - `Blocks help_section; ] in - Term.(const seek_cur $ common_opts_t $ time), - Cmd.info "seek_cur" ~doc ~sdocs ~exits ~man + let man = [ `S Manpage.s_description; `P doc; `Blocks help_section ] in + ( Term.(const seek_cur $ common_opts_t $ time), + Cmd.info "seek_cur" ~doc ~sdocs ~exits ~man ) let next common_opts = - let {host; port} = common_opts in - let client = initialize_client {host; port} in + let { host; port } = common_opts in + let client = initialize_client { host; port } in let _ = check_for_mpd_error @@ Mpd.Playback.next client in Mpd.Client.close client let next_t = - let doc = "Play the next song in the playlist" - in - let man = [ - `S Manpage.s_description; - `P doc; - `Blocks help_section; ] - in - Term.(const next $ common_opts_t), - Cmd.info "next" ~doc ~sdocs ~exits ~man + let doc = "Play the next song in the playlist" in + let man = [ `S Manpage.s_description; `P doc; `Blocks help_section ] in + (Term.(const next $ common_opts_t), Cmd.info "next" ~doc ~sdocs ~exits ~man) let previous common_opts = - let {host; port} = common_opts in - let client = initialize_client {host; port} in + let { host; port } = common_opts in + let client = initialize_client { host; port } in let _ = check_for_mpd_error @@ Mpd.Playback.previous client in Mpd.Client.close client let previous_t = - let doc = "Play the previous song in the playlist" - in - let man = [ - `S Manpage.s_description; - `P doc; - `Blocks help_section; ] - in - Term.(const previous $ common_opts_t), - Cmd.info "previous" ~doc ~sdocs ~exits ~man + let doc = "Play the previous song in the playlist" in + let man = [ `S Manpage.s_description; `P doc; `Blocks help_section ] in + ( Term.(const previous $ common_opts_t), + Cmd.info "previous" ~doc ~sdocs ~exits ~man ) let stop common_opts = - let {host; port} = common_opts in - let client = initialize_client {host; port} in + let { host; port } = common_opts in + let client = initialize_client { host; port } in let _ = check_for_mpd_error @@ Mpd.Playback.stop client in Mpd.Client.close client let stop_t = - let doc = "Stop playing song." - in - let man = [ - `S Manpage.s_description; - `P doc; - `Blocks help_section; ] - in - Term.(const stop $ common_opts_t), - Cmd.info "stop" ~doc ~sdocs ~exits ~man + let doc = "Stop playing song." in + let man = [ `S Manpage.s_description; `P doc; `Blocks help_section ] in + (Term.(const stop $ common_opts_t), Cmd.info "stop" ~doc ~sdocs ~exits ~man) let pause common_opts value = - let {host; port} = common_opts in - let client = initialize_client {host; port} in + let { host; port } = common_opts in + let client = initialize_client { host; port } in let _ = check_for_mpd_error @@ Mpd.Playback.pause client value in Mpd.Client.close client @@ -177,14 +142,20 @@ let toggle_value = Arg.(value & pos 0 bool true & info [] ~doc ~docv:"TOGGLE_VAL") let pause_t = - let doc = "Switch between play/pause." - in - let man = [ - `S Manpage.s_description; - `P doc; - `Blocks help_section; ] - in - Term.(const pause $ common_opts_t $ toggle_value), - Cmd.info "pause" ~doc ~sdocs ~exits ~man - -let cmds = [play_t; play_id_t; seek_t; seek_id_t; seek_cur_t; next_t; previous_t; stop_t; pause_t] + let doc = "Switch between play/pause." in + let man = [ `S Manpage.s_description; `P doc; `Blocks help_section ] in + ( Term.(const pause $ common_opts_t $ toggle_value), + Cmd.info "pause" ~doc ~sdocs ~exits ~man ) + +let cmds = + [ + play_t; + play_id_t; + seek_t; + seek_id_t; + seek_cur_t; + next_t; + previous_t; + stop_t; + pause_t; + ] diff --git a/bin/Ompdc_playback_options.ml b/bin/Ompdc_playback_options.ml index ad08f0c..1814081 100644 --- a/bin/Ompdc_playback_options.ml +++ b/bin/Ompdc_playback_options.ml @@ -18,77 +18,97 @@ open Cmdliner open Ompdc_common - module Pb_opt = Mpd.Playback_options let consume = - let doc = "Sets consume state to STATE, STATE should be false or true. - When consume is activated, each song played is removed from playlist." in + let doc = + "Sets consume state to STATE, STATE should be false or true.\n\ + \ When consume is activated, each song played is removed from playlist." + in let docv = "STATE" in - Arg.(value & opt (some bool) None & info ["c"; "consume"] ~docs ~doc ~docv) + Arg.(value & opt (some bool) None & info [ "c"; "consume" ] ~docs ~doc ~docv) let crossfade = let doc = "Sets crossfade XFADE between songs in seconds." in let docv = "XFADE" in - Arg.(value & opt (some int) None & info ["xf"; "crossfade"] ~docs ~doc ~docv) + Arg.( + value & opt (some int) None & info [ "xf"; "crossfade" ] ~docs ~doc ~docv) let mixrampdb = - let doc = "Sets the threshold at which songs will be overlapped. - Like crossfading but doesn't fade the track volume, just overlaps. The - songs need to have MixRamp tags added by an external tool. 0dB is the - normalized maximum volume so use negative values, I prefer -17dB. - In the absence of mixramp tags crossfading will be used. - See http://sourceforge.net/projects/mixramp" in + let doc = + "Sets the threshold at which songs will be overlapped.\n\ + \ Like crossfading but doesn't fade the track volume, just overlaps. The\n\ + \ songs need to have MixRamp tags added by an external tool. 0dB is the\n\ + \ normalized maximum volume so use negative values, I prefer -17dB.\n\ + \ In the absence of mixramp tags crossfading will be used.\n\ + \ See http://sourceforge.net/projects/mixramp" + in let docv = "MIXRAMPDB" in - Arg.(value & opt (some int) None & info ["mixrampdb"] ~docs ~doc ~docv) + Arg.(value & opt (some int) None & info [ "mixrampdb" ] ~docs ~doc ~docv) let random = - let doc = "Sets random state to RAND_STATE, RAND_STATE should be true or - false" in + let doc = + "Sets random state to RAND_STATE, RAND_STATE should be true or\n false" + in let docv = "RAND_STATE" in - Arg.(value & opt (some bool) None & info ["rand"; "random"] ~docs ~doc ~docv) + Arg.( + value & opt (some bool) None & info [ "rand"; "random" ] ~docs ~doc ~docv) let repeat = - let doc = "Sets repeat state to REPEAT_STATE, REPEAT_STATE should be false \ - or true." in + let doc = + "Sets repeat state to REPEAT_STATE, REPEAT_STATE should be false or true." + in let docv = "REPEAT_STATE" in - Arg.(value & opt (some bool) None & info ["rep"; "repeat"] ~docs ~doc ~docv) + Arg.(value & opt (some bool) None & info [ "rep"; "repeat" ] ~docs ~doc ~docv) let setvol = let doc = "Sets volume to VOL, the range of volume is 0-100" in let docv = "VOL" in - Arg.(value & opt (some int) None & info ["vol"; "volume"] ~docs ~doc ~docv) + Arg.(value & opt (some int) None & info [ "vol"; "volume" ] ~docs ~doc ~docv) let single = - let doc = "Sets single state to SINGLE_STATE, SINGLE_STATE should be 0 or 1. When single is - activated, playback is stopped after current song, or song is repeated if - the 'repeat' mode is enabled." in + let doc = + "Sets single state to SINGLE_STATE, SINGLE_STATE should be 0 or 1. When \ + single is\n\ + \ activated, playback is stopped after current song, or song is \ + repeated if\n\ + \ the 'repeat' mode is enabled." + in let docv = "SINGLE_STATE" in - Arg.(value & opt (some bool) None & info ["single"] ~docs ~doc ~docv) + Arg.(value & opt (some bool) None & info [ "single" ] ~docs ~doc ~docv) let mixrampdelay = - let doc = "Additional time subtracted from the overlap calculated by mixrampdb. A - value of \"nan\" disables MixRamp overlapping and falls back to crossfading." in + let doc = + "Additional time subtracted from the overlap calculated by mixrampdb. A\n\ + \ value of \"nan\" disables MixRamp overlapping and falls back to \ + crossfading." + in let docv = "MIXRAMP_DELAY" in - Arg.(value & opt (some string) None & info ["mixrampdelay"] ~docs ~doc ~docv) + Arg.( + value & opt (some string) None & info [ "mixrampdelay" ] ~docs ~doc ~docv) let mixrampdelay_wrapper client value = let string_parse str = match str with | "nan" -> Pb_opt.Nan - | _ -> try Pb_opt.Seconds (float_of_string str) - with Failure _ -> Pb_opt.Nan + | _ -> ( + try Pb_opt.Seconds (float_of_string str) with Failure _ -> Pb_opt.Nan) in Pb_opt.mixrampdelay client (string_parse value) let replay_gain_mode = - let doc = "Sets the replay gain mode. One of off, track, album, auto with - default (value given) set to auto. - Changing the mode during playback may take several seconds, because the - new settings does not affect the buffered data. - This command triggers the options idle event." in + let doc = + "Sets the replay gain mode. One of off, track, album, auto with\n\ + \ default (value given) set to auto.\n\ + \ Changing the mode during playback may take several seconds, because the\n\ + \ new settings does not affect the buffered data.\n\ + \ This command triggers the options idle event." + in let docv = "REPLAY_GAIN_MODE" in - Arg.(value & opt (some string) None & info ["replay_gain_mode"] ~docs ~doc ~docv) + Arg.( + value + & opt (some string) None + & info [ "replay_gain_mode" ] ~docs ~doc ~docv) let replay_gain_mode_wrapper client value = let string_parse = function @@ -97,12 +117,13 @@ let replay_gain_mode_wrapper client value = | "off" -> Pb_opt.Off | "track" -> Pb_opt.Track | _ -> Pb_opt.Auto - in Pb_opt.replay_gain_mode client (string_parse value) + in + Pb_opt.replay_gain_mode client (string_parse value) let playback_options common_opts consume crossfade mixrampdb random repeat - setvol single mixrampdelay replay_gain_mode = - let {host; port} = common_opts in - let client = initialize_client {host; port} in + setvol single mixrampdelay replay_gain_mode = + let { host; port } = common_opts in + let client = initialize_client { host; port } in let on_value_do opt_val fn = match opt_val with | Some v -> check_for_mpd_error (fn client v) @@ -120,14 +141,9 @@ let playback_options common_opts consume crossfade mixrampdb random repeat Mpd.Client.close client let cmd = - let doc = "Configure all the playback options of the Mpd server." - in - let man = [ - `S Manpage.s_description; - `P doc; - `Blocks help_section; ] - in - Term.(const playback_options $ common_opts_t $ consume $ crossfade - $ mixrampdb $ random $ repeat $ setvol - $ single $ mixrampdelay $ replay_gain_mode), - Cmd.info "playback_options" ~doc ~sdocs ~exits ~man + let doc = "Configure all the playback options of the Mpd server." in + let man = [ `S Manpage.s_description; `P doc; `Blocks help_section ] in + ( Term.( + const playback_options $ common_opts_t $ consume $ crossfade $ mixrampdb + $ random $ repeat $ setvol $ single $ mixrampdelay $ replay_gain_mode), + Cmd.info "playback_options" ~doc ~sdocs ~exits ~man ) diff --git a/bin/Ompdc_status.ml b/bin/Ompdc_status.ml index 6018570..e7f2376 100644 --- a/bin/Ompdc_status.ml +++ b/bin/Ompdc_status.ml @@ -67,86 +67,140 @@ let get_info_str = function | Updating_db -> "updating_db" | Error -> "error" - let get_mpd_status_info status = function - | Volume -> ["volume:"; string_of_int @@ Mpd.Status.volume status] - | Repeat -> ["repeat:"; string_of_bool @@ Mpd.Status.repeat status] - | Random -> ["random:"; string_of_bool @@ Mpd.Status.random status] - | Single -> ["single:"; string_of_bool @@ Mpd.Status.single status] - | Consume -> ["consume:"; string_of_bool @@ Mpd.Status.consume status] - | Playlist ->["playlist:"; string_of_int @@ Mpd.Status.playlist status] - | Playlistlength -> ["playlistlength:"; - string_of_int @@ Mpd.Status.playlistlength status] - | State -> let state = Mpd.Status.state status in - ["state:"; Mpd.Status.string_of_state state] - | Song -> ["song:"; string_of_int @@ Mpd.Status.song status] - | Songid -> ["songid:"; string_of_int @@ Mpd.Status.songid status] - | Nextsong -> ["nextsong:"; string_of_int @@ Mpd.Status.nextsong status] - | Nextsongid -> ["nextsongid:"; string_of_int @@ Mpd.Status.nextsongid status] - | Time -> ["time:"; Mpd.Status.time status] - | Elapsed -> ["elapsed:"; string_of_float @@ Mpd.Status.elapsed status] - | Duration -> ["duration:"; string_of_float @@ Mpd.Status.duration status] - | Bitrate -> ["bitrate:"; string_of_int @@ Mpd.Status.bitrate status] - | Xfade -> ["xfade:"; string_of_int @@ Mpd.Status.xfade status] - | Mixrampdb -> ["mixrampdb:"; string_of_float @@ Mpd.Status.mixrampdb status] - | Mixrampdelay -> ["mixrampdelay:"; string_of_float @@ Mpd.Status.mixrampdelay status] - | Audio -> ["audio:"; Mpd.Status.audio status] - | Updating_db -> ["updating_db:"; string_of_int @@ Mpd.Status.updating_db status] - | Error -> ["error:"; Mpd.Status.error status] - + | Volume -> [ "volume:"; string_of_int @@ Mpd.Status.volume status ] + | Repeat -> [ "repeat:"; string_of_bool @@ Mpd.Status.repeat status ] + | Random -> [ "random:"; string_of_bool @@ Mpd.Status.random status ] + | Single -> [ "single:"; string_of_bool @@ Mpd.Status.single status ] + | Consume -> [ "consume:"; string_of_bool @@ Mpd.Status.consume status ] + | Playlist -> [ "playlist:"; string_of_int @@ Mpd.Status.playlist status ] + | Playlistlength -> + [ "playlistlength:"; string_of_int @@ Mpd.Status.playlistlength status ] + | State -> + let state = Mpd.Status.state status in + [ "state:"; Mpd.Status.string_of_state state ] + | Song -> [ "song:"; string_of_int @@ Mpd.Status.song status ] + | Songid -> [ "songid:"; string_of_int @@ Mpd.Status.songid status ] + | Nextsong -> [ "nextsong:"; string_of_int @@ Mpd.Status.nextsong status ] + | Nextsongid -> + [ "nextsongid:"; string_of_int @@ Mpd.Status.nextsongid status ] + | Time -> [ "time:"; Mpd.Status.time status ] + | Elapsed -> [ "elapsed:"; string_of_float @@ Mpd.Status.elapsed status ] + | Duration -> [ "duration:"; string_of_float @@ Mpd.Status.duration status ] + | Bitrate -> [ "bitrate:"; string_of_int @@ Mpd.Status.bitrate status ] + | Xfade -> [ "xfade:"; string_of_int @@ Mpd.Status.xfade status ] + | Mixrampdb -> + [ "mixrampdb:"; string_of_float @@ Mpd.Status.mixrampdb status ] + | Mixrampdelay -> + [ "mixrampdelay:"; string_of_float @@ Mpd.Status.mixrampdelay status ] + | Audio -> [ "audio:"; Mpd.Status.audio status ] + | Updating_db -> + [ "updating_db:"; string_of_int @@ Mpd.Status.updating_db status ] + | Error -> [ "error:"; Mpd.Status.error status ] let get_status common_opts fields = - let {host; port} = common_opts in - let client = initialize_client {host; port} in + let { host; port } = common_opts in + let client = initialize_client { host; port } in match Mpd.Client.status client with | Error message -> print_endline message | Ok status -> let rec _parse_fields = function | [] -> () - | i :: remain -> let info = String.concat " " @@ get_mpd_status_info status i in - let _ = print_endline info in - _parse_fields remain - in - let _ = _parse_fields fields in - Mpd.Client.close client + | i :: remain -> + let info = String.concat " " @@ get_mpd_status_info status i in + let _ = print_endline info in + _parse_fields remain + in + let _ = _parse_fields fields in + Mpd.Client.close client let status_fields = - let volume = Volume, Arg.info ["v"; "volume"; "vol"] in - let repeat = Repeat, Arg.info ["r"; "repeat"] in - let random = Random, Arg.info ["rand"; "random"] in - let single = Single, Arg.info ["single"] in - let consume = Consume, Arg.info ["c"; "consume"] in - let playlist = Playlist, Arg.info ["plist"; "playlist"] in - let playlistlength = Playlistlength, Arg.info ["plistl"; "playlistlength"] in - let state = State, Arg.info ["st"; "state"] in - let song = Song, Arg.info ["so"; "song"] in - let songid = Songid, Arg.info ["soid"; "songid"] in - let nextsong = Nextsong, Arg.info ["nso"; "nextsong"] in - let nextsongid = Nextsongid, Arg.info ["nsoid"; "nextsongid"] in - let time = Time, Arg.info ["t"; "time"] in - let elapsed = Elapsed, Arg.info ["e"; "elapsed"] in - let duration = Duration, Arg.info ["d"; "duration"] in - let bitrate = Bitrate, Arg.info ["b"; "bitrate"] in - let xfade = Xfade, Arg.info ["x"; "xfade"] in - let mixrampdb = Mixrampdb, Arg.info ["mixdb"; "mixrampdb"] in - let mixrampdelay = Mixrampdelay, Arg.info ["mixdelay"; "mixrampdelay"] in - let audio = Audio, Arg.info ["a"; "audio"] in - let updating_db = Updating_db, Arg.info ["u"; "Updating_db"] in - let error = Error, Arg.info ["err"; "error"] in - Arg.(value & vflag_all [Volume; Repeat; Random; Single; Consume; Playlist; - Playlistlength; State; Song; Songid; Nextsong; - Nextsongid; Time; Elapsed; Duration; Bitrate; Xfade; - Mixrampdb; Mixrampdelay; Audio; Updating_db; Error] - [volume; repeat; random; single; consume; playlist; - playlistlength; state; song; songid; nextsong; - nextsongid; time; elapsed; duration; bitrate; xfade; - mixrampdb; mixrampdelay; audio; updating_db; error]) + let volume = (Volume, Arg.info [ "v"; "volume"; "vol" ]) in + let repeat = (Repeat, Arg.info [ "r"; "repeat" ]) in + let random = (Random, Arg.info [ "rand"; "random" ]) in + let single = (Single, Arg.info [ "single" ]) in + let consume = (Consume, Arg.info [ "c"; "consume" ]) in + let playlist = (Playlist, Arg.info [ "plist"; "playlist" ]) in + let playlistlength = + (Playlistlength, Arg.info [ "plistl"; "playlistlength" ]) + in + let state = (State, Arg.info [ "st"; "state" ]) in + let song = (Song, Arg.info [ "so"; "song" ]) in + let songid = (Songid, Arg.info [ "soid"; "songid" ]) in + let nextsong = (Nextsong, Arg.info [ "nso"; "nextsong" ]) in + let nextsongid = (Nextsongid, Arg.info [ "nsoid"; "nextsongid" ]) in + let time = (Time, Arg.info [ "t"; "time" ]) in + let elapsed = (Elapsed, Arg.info [ "e"; "elapsed" ]) in + let duration = (Duration, Arg.info [ "d"; "duration" ]) in + let bitrate = (Bitrate, Arg.info [ "b"; "bitrate" ]) in + let xfade = (Xfade, Arg.info [ "x"; "xfade" ]) in + let mixrampdb = (Mixrampdb, Arg.info [ "mixdb"; "mixrampdb" ]) in + let mixrampdelay = (Mixrampdelay, Arg.info [ "mixdelay"; "mixrampdelay" ]) in + let audio = (Audio, Arg.info [ "a"; "audio" ]) in + let updating_db = (Updating_db, Arg.info [ "u"; "Updating_db" ]) in + let error = (Error, Arg.info [ "err"; "error" ]) in + Arg.( + value + & vflag_all + [ + Volume; + Repeat; + Random; + Single; + Consume; + Playlist; + Playlistlength; + State; + Song; + Songid; + Nextsong; + Nextsongid; + Time; + Elapsed; + Duration; + Bitrate; + Xfade; + Mixrampdb; + Mixrampdelay; + Audio; + Updating_db; + Error; + ] + [ + volume; + repeat; + random; + single; + consume; + playlist; + playlistlength; + state; + song; + songid; + nextsong; + nextsongid; + time; + elapsed; + duration; + bitrate; + xfade; + mixrampdb; + mixrampdelay; + audio; + updating_db; + error; + ]) let cmd = - let doc = "Get all status information with no arguments or chose those you want." in - let man = [ `S Manpage.s_description; - `P "Status commands in order to display Mpd server information."; - `Blocks help_section - ] in - Term.(const get_status $ common_opts_t $ status_fields), - Cmd.info "status" ~doc ~sdocs ~exits ~man + let doc = + "Get all status information with no arguments or chose those you want." + in + let man = + [ + `S Manpage.s_description; + `P "Status commands in order to display Mpd server information."; + `Blocks help_section; + ] + in + ( Term.(const get_status $ common_opts_t $ status_fields), + Cmd.info "status" ~doc ~sdocs ~exits ~man ) diff --git a/bin/Ompdc_stored_playlists.ml b/bin/Ompdc_stored_playlists.ml index bcebc81..2ac1c63 100644 --- a/bin/Ompdc_stored_playlists.ml +++ b/bin/Ompdc_stored_playlists.ml @@ -20,25 +20,19 @@ open Cmdliner open Ompdc_common let listplaylists common_opts = - let {host; port} = common_opts in - let client = initialize_client {host; port} in - let () = match Mpd.Stored_playlists.listplaylists client with + let { host; port } = common_opts in + let client = initialize_client { host; port } in + let () = + match Mpd.Stored_playlists.listplaylists client with | Error message -> print_endline message | Ok playlists -> List.iter print_endline playlists in Mpd.Client.close client let listplaylists_t = - let doc = "List all the playlists" - in - let man = [ - `S Manpage.s_description; - `P doc; - `Blocks help_section; ] - in - Term.(const listplaylists $ common_opts_t), - Cmd.info "listplaylists" ~doc ~sdocs ~exits ~man - -let cmds = [listplaylists_t] - + let doc = "List all the playlists" in + let man = [ `S Manpage.s_description; `P doc; `Blocks help_section ] in + ( Term.(const listplaylists $ common_opts_t), + Cmd.info "listplaylists" ~doc ~sdocs ~exits ~man ) +let cmds = [ listplaylists_t ] diff --git a/bin/ompdc.ml b/bin/ompdc.ml index 5f7134f..accc34a 100644 --- a/bin/ompdc.ml +++ b/bin/ompdc.ml @@ -19,20 +19,20 @@ open Cmdliner open Ompdc_common -let default = - Term.(ret (const (fun _ -> `Help (`Pager, None)) $ common_opts_t)) +let default = Term.(ret (const (fun _ -> `Help (`Pager, None)) $ common_opts_t)) let cmd_info = let doc = "a Mpd client written in OCaml." in let man = help_section in Cmd.info ~version ~doc ~sdocs ~exits ~man "ompdc" -let cmds = List.concat [Ompdc_playback.cmds; - Ompdc_stored_playlists.cmds; - [Ompdc_status.cmd; - Ompdc_idle.cmd; - Ompdc_playback_options.cmd; - help_cmd]] - |> List.map (fun t -> Cmd.v (snd t) (fst t)) +let cmds = + List.concat + [ + Ompdc_playback.cmds; + Ompdc_stored_playlists.cmds; + [ Ompdc_status.cmd; Ompdc_idle.cmd; Ompdc_playback_options.cmd; help_cmd ]; + ] + |> List.map (fun t -> Cmd.v (snd t) (fst t)) let () = exit @@ Cmd.(eval @@ group ~default cmd_info cmds) diff --git a/bin/ompdc_bad_implementation.ml b/bin/ompdc_bad_implementation.ml index 45c3cfb..edad211 100644 --- a/bin/ompdc_bad_implementation.ml +++ b/bin/ompdc_bad_implementation.ml @@ -23,48 +23,60 @@ let sdocs = Manpage.s_common_options let docs = Manpage.s_common_options let exits = Term.default_exits -let help copts man_format cmds topic = match topic with -| None -> `Help (`Pager, None) (* help about the program. *) -| Some topic -> - let topics = "topics" :: "patterns" :: "environment" :: cmds in - let conv, _ = Cmdliner.Arg.enum (List.rev_map (fun s -> (s, s)) topics) in - match conv topic with - | `Error e -> `Error (false, e) - | `Ok t when t = "topics" -> List.iter print_endline topics; `Ok () - | `Ok t when List.mem t cmds -> `Help (man_format, Some t) - | `Ok t -> - let page = (topic, 7, "", "", ""), [`S topic; `P "Say something";] in - `Ok (Cmdliner.Manpage.print man_format Format.std_formatter page) +let help copts man_format cmds topic = + match topic with + | None -> `Help (`Pager, None) (* help about the program. *) + | Some topic -> ( + let topics = "topics" :: "patterns" :: "environment" :: cmds in + let conv, _ = Cmdliner.Arg.enum (List.rev_map (fun s -> (s, s)) topics) in + match conv topic with + | `Error e -> `Error (false, e) + | `Ok t when t = "topics" -> + List.iter print_endline topics; + `Ok () + | `Ok t when List.mem t cmds -> `Help (man_format, Some t) + | `Ok t -> + let page = + ((topic, 7, "", "", ""), [ `S topic; `P "Say something" ]) + in + `Ok (Cmdliner.Manpage.print man_format Format.std_formatter page)) (* Help sections common to all commands *) -let help_section = [ - `S Manpage.s_common_options; - `P "These options are common to all commands."; - `S Manpage.s_bugs; `P "Check bug reports at https://github.com/cedlemo/OCaml-libmpdclient/issues"; - `S Manpage.s_authors; `P "Cedric Le Moigne " - ] +let help_section = + [ + `S Manpage.s_common_options; + `P "These options are common to all commands."; + `S Manpage.s_bugs; + `P + "Check bug reports at \ + https://github.com/cedlemo/OCaml-libmpdclient/issues"; + `S Manpage.s_authors; + `P "Cedric Le Moigne "; + ] (* Options common to all commands *) -type mpd_opts = {host : string; port : int} +type mpd_opts = { host : string; port : int } -let common_opts host port = - {host; port} +let common_opts host port = { host; port } let common_opts_t = let host = let doc = "Set the address of the Mpd server." in let env = Arg.env_var "OMPDC_HOST" ~doc in - Arg.(value & opt string "127.0.0.1" & info ["h"; "host"] ~docs ~env ~docv:"HOST") + Arg.( + value & opt string "127.0.0.1" + & info [ "h"; "host" ] ~docs ~env ~docv:"HOST") in let port = let doc = "Set the port of the Mpd server." in let env = Arg.env_var "OMPDC_PORT" ~doc in - Arg.(value & opt int 6600 & info ["p"; "port"] ~docs ~env ~docv:"PORT") + Arg.(value & opt int 6600 & info [ "p"; "port" ] ~docs ~env ~docv:"PORT") in Term.(const common_opts $ host $ port) type playback_cmds = Play | Next | Prev | Pause | Stop + let playback_cmds_to_string = function | Next -> "next" | Pause -> "pause" @@ -72,17 +84,18 @@ let playback_cmds_to_string = function | Prev -> "prev" | Stop -> "stop" -let initialize_client {host; port} = - let connection = Mpd.Connection.initialize host port in - let client = Mpd.Client.initialize connection in - let _ = print_endline ("Mpd server : " ^ (Mpd.Client.mpd_banner client)) in - client +let initialize_client { host; port } = + let connection = Mpd.Connection.initialize host port in + let client = Mpd.Client.initialize connection in + let _ = print_endline ("Mpd server : " ^ Mpd.Client.mpd_banner client) in + client let playback common_opts cmd = - let {host; port} = common_opts in - let client = initialize_client {host; port} in + let { host; port } = common_opts in + let client = initialize_client { host; port } in let cmd_str = playback_cmds_to_string cmd in - let _ = match cmd with + let _ = + match cmd with | Next -> ignore (Mpd.Playback.next client) | Pause -> ignore (Mpd.Playback.pause client true) | Play -> ignore (Mpd.Playback.play client 1) @@ -93,28 +106,29 @@ let playback common_opts cmd = print_endline message let playback_action = - let doc = "Play next song." in - let next = Next, Arg.info ["next"] ~doc in - let doc = "Toggle Play/Stop." in - let pause = Pause, Arg.info ["pause"] ~doc in - let doc = "Play the current song in the Mpd queue." in - let play = Play, Arg.info ["play"] ~doc in - let doc = "Stop playing songs." in - let stop = Stop, Arg.info ["stop"] ~doc in - let doc = "Play previous song." in - let prev = Prev, Arg.info ["prev"] ~doc in - Arg.(last & vflag_all [Pause] [next; pause; play; prev; stop]) + let doc = "Play next song." in + let next = (Next, Arg.info [ "next" ] ~doc) in + let doc = "Toggle Play/Stop." in + let pause = (Pause, Arg.info [ "pause" ] ~doc) in + let doc = "Play the current song in the Mpd queue." in + let play = (Play, Arg.info [ "play" ] ~doc) in + let doc = "Stop playing songs." in + let stop = (Stop, Arg.info [ "stop" ] ~doc) in + let doc = "Play previous song." in + let prev = (Prev, Arg.info [ "prev" ] ~doc) in + Arg.(last & vflag_all [ Pause ] [ next; pause; play; prev; stop ]) let playback_t = - let doc = "Playback commands" - in - let man = [ - `S Manpage.s_description; - `P "Playback commands for the current playlist (queue)."; - `Blocks help_section; ] - in - Term.(const playback $ common_opts_t $ playback_action), - Term.info "playback" ~doc ~sdocs ~exits ~man + let doc = "Playback commands" in + let man = + [ + `S Manpage.s_description; + `P "Playback commands for the current playlist (queue)."; + `Blocks help_section; + ] + in + ( Term.(const playback $ common_opts_t $ playback_action), + Term.info "playback" ~doc ~sdocs ~exits ~man ) let help_cmd = let topic = @@ -123,56 +137,57 @@ let help_cmd = in let doc = "display help about ompdc and ompdc commands" in let man = - [`S Manpage.s_description; - `P "Prints help about ompdc commands and other subjects..."; - `Blocks help_section; ] + [ + `S Manpage.s_description; + `P "Prints help about ompdc commands and other subjects..."; + `Blocks help_section; + ] in - Term.(ret - (const help $ common_opts_t $ Arg.man_format $ Term.choice_names $topic)), - Term.info "help" ~doc ~exits ~man + ( Term.( + ret + (const help $ common_opts_t $ Arg.man_format $ Term.choice_names $ topic)), + Term.info "help" ~doc ~exits ~man ) let default_cmd = let doc = "a Mpd client written in OCaml." in let man = help_section in - Term.(ret (const (fun _ -> `Help (`Pager, None)) $ common_opts_t)), - Term.info "ompdc" ~version ~doc ~sdocs ~exits ~man - -let cmds = [playback_t; help_cmd] + ( Term.(ret (const (fun _ -> `Help (`Pager, None)) $ common_opts_t)), + Term.info "ompdc" ~version ~doc ~sdocs ~exits ~man ) +let cmds = [ playback_t; help_cmd ] let () = Term.(exit @@ eval_choice default_cmd cmds) (* let playback common_opts cmd args = - let show_message host port cmd args = - let _args = match args with | None -> "no args" | Some s -> s in - let message = Printf.sprintf "%s:%d %s %s" host port cmd _args in - print_endline message - in - let {host; port} = common_opts in - match cmd with - | `Next -> show_message host port "next" args - | `Pause -> show_message host port "pause" args - | `Play -> show_message host port "play" args - | `Prev -> show_message host port "prev" args - | `Stop -> show_message host port "stop" args - -let playback_actions = - let actions = ["play", `Play; - "stop", `Stop; - "prev", `Prev; - "next", `Next; - "pause", `Pause - ] in - let substitue = Printf.sprintf in - let action_docs = List.map (fun (str, sym) -> - match sym with - | `Play -> substitue "$(b,%s) [ARG]" str - | `Pause -> substitue "$(b,%s) [ARG]" str - | `Stop | `Prev | `Next -> substitue "$(b,%s)" str - ) actions in - let doc = substitue "The action to perform. $(docv) must be one of: %s." - (String.concat ", " action_docs) - in - let action = Arg.enum actions in - Arg.(required & pos 0 (some action) None & info [] ~doc ~docv:"ACTION") + let show_message host port cmd args = + let _args = match args with | None -> "no args" | Some s -> s in + let message = Printf.sprintf "%s:%d %s %s" host port cmd _args in + print_endline message + in + let {host; port} = common_opts in + match cmd with + | `Next -> show_message host port "next" args + | `Pause -> show_message host port "pause" args + | `Play -> show_message host port "play" args + | `Prev -> show_message host port "prev" args + | `Stop -> show_message host port "stop" args + + let playback_actions = + let actions = ["play", `Play; + "stop", `Stop; + "prev", `Prev; + "next", `Next; + "pause", `Pause + ] in + let substitue = Printf.sprintf in + let action_docs = List.map (fun (str, sym) -> + match sym with + | `Play -> substitue "$(b,%s) [ARG]" str + | `Pause -> substitue "$(b,%s) [ARG]" str + | `Stop | `Prev | `Next -> substitue "$(b,%s)" str + ) actions in + let doc = substitue "The action to perform. $(docv) must be one of: %s." + (String.concat ", " action_docs) + in + let action = Arg.enum actions in + Arg.(required & pos 0 (some action) None & info [] ~doc ~docv:"ACTION") *) - diff --git a/lib/Client.ml b/lib/Client.ml index b779f24..6aedbf3 100644 --- a/lib/Client.ml +++ b/lib/Client.ml @@ -16,66 +16,71 @@ * along with OCaml-libmpdclient. If not, see . *) -type t = {connection : Connection.t; mpd_banner : string } +type t = { connection : Connection.t; mpd_banner : string } let initialize connection = let message = Connection.read_mpd_banner connection in let pattern = "OK \\(.*\\)\n" in - let mpd_banner = match Str.string_match (Str.regexp pattern) message 0 with - | true -> Str.matched_group 1 message - | false -> message - in { connection; mpd_banner } + let mpd_banner = + match Str.string_match (Str.regexp pattern) message 0 with + | true -> Str.matched_group 1 message + | false -> message + in + { connection; mpd_banner } let send_command client mpd_cmd = - let {connection = c; _} = client in - let cmd = (Utils.remove_new_lines mpd_cmd) ^ "\n" in + let { connection = c; _ } = client in + let cmd = Utils.remove_new_lines mpd_cmd ^ "\n" in Connection.write c cmd; let response = Connection.read_command_response c in let () = Utils.print_data response in Protocol.parse_response response let send_request client mpd_cmd = - let {connection = c; _} = client in - let request = (Utils.remove_new_lines mpd_cmd) ^ "\n" in + let { connection = c; _ } = client in + let request = Utils.remove_new_lines mpd_cmd ^ "\n" in Connection.write c request; let response = Connection.read_request_response c in let () = Utils.print_data response in Protocol.parse_response response -let mpd_banner {mpd_banner = banner; _ } = - banner +let mpd_banner { mpd_banner = banner; _ } = banner let status client = let response = send_request client "status" in match response with - | Ok (lines) -> ( - match lines with + | Ok lines -> ( + match lines with | None -> Error "Empty status" - | Some lines' -> let status_pairs = Utils.split_lines lines' in - Ok (Status.parse status_pairs) - ) + | Some lines' -> + let status_pairs = Utils.split_lines lines' in + Ok (Status.parse status_pairs)) | Error (ack, _ack_cmd_num, _cmd, ack_message) -> - let message = String.concat " " ["Error type:"; - Protocol.error_name ack; - "-- error message:"; - ack_message] in + let message = + String.concat " " + [ + "Error type:"; + Protocol.error_name ack; + "-- error message:"; + ack_message; + ] + in Error message -let ping client = - send_command client "ping" +let ping client = send_command client "ping" let password client mdp = - send_command client (String.concat " " ["password"; mdp]) + send_command client (String.concat " " [ "password"; mdp ]) let tagtypes client = let response = send_request client "tagtypes" in match response with - | Ok (lines) -> ( - match lines with - | None -> [] - | Some lines' -> let tagid_keys_vals = Utils.split_lines lines' in - List.rev (Utils.values_of_pairs tagid_keys_vals) - ) + | Ok lines -> ( + match lines with + | None -> [] + | Some lines' -> + let tagid_keys_vals = Utils.split_lines lines' in + List.rev (Utils.values_of_pairs tagid_keys_vals)) | Error (_ack, _ack_cmd_num, _cmd, _error) -> [] (* (** Remove one or more tags from the list of tag types the client is @@ -101,6 +106,6 @@ let tagtypes_all client = *) let close client = - let {connection = c; _} = client in - Connection.write c ("close\n"); - Connection.close c; + let { connection = c; _ } = client in + Connection.write c "close\n"; + Connection.close c diff --git a/lib/Client.mli b/lib/Client.mli index e59453a..4d7d7c3 100644 --- a/lib/Client.mli +++ b/lib/Client.mli @@ -22,40 +22,39 @@ type t (** Client type *) -val initialize: Connection.t -> t +val initialize : Connection.t -> t (** Initialize the client with a connection. *) (** val send: t -> string -> Protocol.response Send to the mpd server a command or a request. The response of the server is returned under the form of a Protocol.response type. *) -val send_request: t -> string -> Protocol.response +val send_request : t -> string -> Protocol.response +val send_command : t -> string -> Protocol.response -val send_command: t -> string -> Protocol.response - -val mpd_banner: t -> string +val mpd_banner : t -> string (** Return the mpd banner that the server send at the first connection of the client. *) -val status: t -> (Status.t, string) result +val status : t -> (Status.t, string) result (** Create a status request and returns the status under a Mpd.Status.t type if no error occurs.*) -val ping: t -> Protocol.response +val ping : t -> Protocol.response (** Does nothing but return "OK". *) -val password: t -> string -> Protocol.response +val password : t -> string -> Protocol.response (** This is used for authentication with the server. PASSWORD is simply the plaintext password. *) -val close: t -> unit +val close : t -> unit (** Close the connection to MPD. MPD will try to send the remaining output buffer before it actually closes the connection, but that cannot be guaranteed. This command will not generate a response. This function is a wrapper to the "close" command of the Mpd protocol, this means that it first send the "close" command and it close the connection at the socket level. *) -val tagtypes: t -> string list +val tagtypes : t -> string list (** Show a list of available tag types. It is an intersection of the metadata_to_use setting and this client's tag mask. About the tag mask: each client can decide to disable any number of tag @@ -64,6 +63,7 @@ val tagtypes: t -> string list commands configure this list. *) (**/**) + (* val tagtypes_disable: t -> string list -> Protocol.response val tagtypes_clear: t -> Protocol.response val tagtypes_all: t -> Protocol.response *) diff --git a/lib/Client_lwt.ml b/lib/Client_lwt.ml index cd15504..58f3f86 100644 --- a/lib/Client_lwt.ml +++ b/lib/Client_lwt.ml @@ -18,84 +18,74 @@ open Lwt.Infix -type t = {connection : Connection_lwt.t; mpd_banner : string } +type t = { connection : Connection_lwt.t; mpd_banner : string } let initialize connection = - Connection_lwt.read_mpd_banner connection - >>= fun message -> - Lwt.return {connection = connection; mpd_banner = message} + Connection_lwt.read_mpd_banner connection >>= fun message -> + Lwt.return { connection; mpd_banner = message } -let mpd_banner {mpd_banner = banner; _ } = - Lwt.return banner +let mpd_banner { mpd_banner = banner; _ } = Lwt.return banner let idle client = - let {connection = connection; _} = client in + let { connection; _ } = client in let cmd = "idle\n" in - Connection_lwt.write connection cmd - >>= function - | (-1) -> Lwt.return (Error "Connection error: unable to write \"idle\" command.") - | _ -> Connection_lwt.read_idle_events connection - >|= fun event_name -> Ok event_name + Connection_lwt.write connection cmd >>= function + | -1 -> + Lwt.return (Error "Connection error: unable to write \"idle\" command.") + | _ -> + Connection_lwt.read_idle_events connection >|= fun event_name -> + Ok event_name let rec idle_loop client on_event = - let {connection = connection; _} = client in + let { connection; _ } = client in let cmd = "idle\n" in - Connection_lwt.write connection cmd - >>= function - | (-1) -> Lwt.return () (* TODO: Should return a meaningfull value so that the user can exit on this value. *) - | _ -> Connection_lwt.read_idle_events connection - >>= fun response -> - on_event response - >>= function - | true -> Lwt.return () - | false -> idle_loop client on_event + Connection_lwt.write connection cmd >>= function + | -1 -> + Lwt.return () + (* TODO: Should return a meaningfull value so that the user can exit on this value. *) + | _ -> ( + Connection_lwt.read_idle_events connection >>= fun response -> + on_event response >>= function + | true -> Lwt.return () + | false -> idle_loop client on_event) let send client cmd = - let {connection = c; _} = client in - Connection_lwt.write c (cmd ^ "\n") - >>= fun _ -> - Connection_lwt.read_command_response c - >>= fun response -> - let parsed_response = Protocol.parse_response response in - Lwt.return parsed_response + let { connection = c; _ } = client in + Connection_lwt.write c (cmd ^ "\n") >>= fun _ -> + Connection_lwt.read_command_response c >>= fun response -> + let parsed_response = Protocol.parse_response response in + Lwt.return parsed_response let request client cmd = - let {connection = c; _} = client in - Connection_lwt.write c (cmd ^ "\n") - >>= fun _ -> - Connection_lwt.read_request_response c - >>= fun response -> - let parsed_response = Protocol.parse_response response in - Lwt.return parsed_response + let { connection = c; _ } = client in + Connection_lwt.write c (cmd ^ "\n") >>= fun _ -> + Connection_lwt.read_request_response c >>= fun response -> + let parsed_response = Protocol.parse_response response in + Lwt.return parsed_response let status client = - request client "status" - >>= function - | Ok lines -> ( - match lines with - | None -> Lwt.return (Error "No status") - | Some lines' -> let status_pairs = Utils.split_lines lines' in - let status = Status.parse status_pairs in Lwt.return (Ok status) - ) - | Error (_ack, _ack_cmd_num, _cmd, error_message) -> - Lwt.return (Error error_message) + request client "status" >>= function + | Ok lines -> ( + match lines with + | None -> Lwt.return (Error "No status") + | Some lines' -> + let status_pairs = Utils.split_lines lines' in + let status = Status.parse status_pairs in + Lwt.return (Ok status)) + | Error (_ack, _ack_cmd_num, _cmd, error_message) -> + Lwt.return (Error error_message) -let ping client = - send client "ping" - -let password client mdp = - send client (String.concat " " ["password"; mdp]) - -let noidle client = - send client "noidle" - (* let {connection = connection; _} = client in - Connection_lwt.write connection "noidle\n" - >>= fun _ -> - Connection_lwt.read_no_idle_response c - >>= fun response -> - let parsed_response = Protocol.parse_response response in - Lwt.return parsed_response *) +let ping client = send client "ping" +let password client mdp = send client (String.concat " " [ "password"; mdp ]) +let noidle client = send client "noidle" +(* let {connection = connection; _} = client in + Connection_lwt.write connection "noidle\n" + >>= fun _ -> + Connection_lwt.read_no_idle_response c + >>= fun response -> + let parsed_response = Protocol.parse_response response in + Lwt.return parsed_response *) let close client = - let {connection = connection; _} = client in + let { connection; _ } = client in Connection_lwt.close connection diff --git a/lib/Client_lwt.mli b/lib/Client_lwt.mli index 745440f..d3fa87c 100644 --- a/lib/Client_lwt.mli +++ b/lib/Client_lwt.mli @@ -22,14 +22,14 @@ type t (** Type for a Mpd Client to be used with Lwt promises. *) -val initialize: Connection_lwt.t -> t Lwt.t +val initialize : Connection_lwt.t -> t Lwt.t (** Initialize the client with a connection. *) -val mpd_banner: t -> string Lwt.t +val mpd_banner : t -> string Lwt.t (** Return the mpd banner that the server send at the first connection of the client. *) -val idle: t -> (string, string) result Lwt.t +val idle : t -> (string, string) result Lwt.t (** Wait for an event to occur in order to return. When a Client send this * command to the Mpd server throught its connection, the Mpd server do * not answer to any other command except the noidle command. The idea is @@ -37,40 +37,38 @@ val idle: t -> (string, string) result Lwt.t * Lwt.cancel and then send the noidle command to the Mpd server. An * example can be found in samples/mpd_lwt_client_idle_noidle.ml. *) -val idle_loop: t -> (string -> bool Lwt.t) -> unit Lwt.t +val idle_loop : t -> (string -> bool Lwt.t) -> unit Lwt.t (** Loop on mpd event with the "idle" command the on_event function take the event response as argument and return true to stop or false to continue the loop *) -val send: t -> string -> Protocol.response Lwt.t +val send : t -> string -> Protocol.response Lwt.t (** Send to the mpd server a command. The response of the server is returned under the form of a Protocol.response type. *) -val request: - t -> string -> Protocol.response Lwt.t +val request : t -> string -> Protocol.response Lwt.t (** Send to the mpd server a request. The response of the server is returned under the form of a Protocol.response type. A request is different from a command because a command generate an action from Mpd and returns "OK" or an error while a request does not generate an action from Mpd and returns "some data to analyse"OK or an error.*) -val status: t -> (Status.t, string) result Lwt.t +val status : t -> (Status.t, string) result Lwt.t (** Create a status request and returns the status under a Mpd.Status.s Lwt.t type.*) -val ping: t -> Protocol.response Lwt.t +val ping : t -> Protocol.response Lwt.t (** Does nothing but return "OK". *) -val password: t -> string -> Protocol.response Lwt.t +val password : t -> string -> Protocol.response Lwt.t (** This is used for authentication with the server. PASSWORD is simply the plaintext password. *) -val noidle: - t -> Protocol.response Lwt.t +val noidle : t -> Protocol.response Lwt.t (** This command is needed to stop listening after a Client.idle command. An example of usage can be seen in samples/mpd_lwt_client_idle_noidle.exe. *) -val close: t -> unit Lwt.t +val close : t -> unit Lwt.t (** Close the client. MPD will try to send the remaining output buffer before it actually closes the connection, but that cannot be guaranteed. This command will not generate a response. This function is a diff --git a/lib/Connection.ml b/lib/Connection.ml index a57db6c..06f160e 100644 --- a/lib/Connection.ml +++ b/lib/Connection.ml @@ -16,51 +16,54 @@ * along with OCaml-libmpdclient. If not, see . *) -type t = - { hostname : string; - port : int; - ip : Unix.inet_addr; - socket : Unix.file_descr; - mutable buffer : string} +type t = { + hostname : string; + port : int; + ip : Unix.inet_addr; + socket : Unix.file_descr; + mutable buffer : string; +} let unix_error_message (error, fn_name, param_name) user_str = - let strs = [Unix.error_message error; fn_name; param_name; user_str; ".Exiting..."] in + let strs = + [ Unix.error_message error; fn_name; param_name; user_str; ".Exiting..." ] + in let message = String.concat " " strs in let _ = prerr_endline message in exit 2 let initialize hostname port = let open Unix in - let ip = try (Unix.gethostbyname hostname).h_addr_list.(0) + let ip = + try (Unix.gethostbyname hostname).h_addr_list.(0) with Not_found -> let _ = prerr_endline (hostname ^ ": Host not found") in exit 2 in - let s = try Unix.socket PF_INET SOCK_STREAM 0 + let s = + try Unix.socket PF_INET SOCK_STREAM 0 with Unix_error (error, fn_name, param_name) -> let custom_message = ": unable to create socket" in unix_error_message (error, fn_name, param_name) custom_message in - let _ = try Unix.connect s (Unix.ADDR_INET(ip, port)) + let _ = + try Unix.connect s (Unix.ADDR_INET (ip, port)) with Unix_error (error, fn_name, param_name) -> - let custom_message = Printf.sprintf ": unable to connect to %s:%d" hostname port in + let custom_message = + Printf.sprintf ": unable to connect to %s:%d" hostname port + in unix_error_message (error, fn_name, param_name) custom_message in - {hostname; port; ip; socket = s; buffer = ""} - + { hostname; port; ip; socket = s; buffer = "" } -let hostname { hostname; _ } = - hostname - -let port { port; _ } = - port +let hostname { hostname; _ } = hostname +let port { port; _ } = port let close t = let open Unix in - try ( + try Unix.set_nonblock t.socket; Unix.close t.socket - ) with Unix_error (error, fn_name, param_name) -> let custom_message = ": unable to close socket" in unix_error_message (error, fn_name, param_name) custom_message @@ -69,7 +72,7 @@ let write t str = let open Unix in let b = Bytes.of_string str in let len = Bytes.length b in - try ignore(Unix.send t.socket b 0 len []) + try ignore (Unix.send t.socket b 0 len []) with Unix_error (error, fn_name, param_name) -> let custom_message = Printf.sprintf ": unable to write %s in socket" str in unix_error_message (error, fn_name, param_name) custom_message @@ -79,39 +82,31 @@ let recvbytes t = try let recvlen = Unix.recv t.socket str 0 128 [] in Bytes.(sub str 0 recvlen) - with - | Unix.Unix_error (error, fn_name, param_name) -> + with Unix.Unix_error (error, fn_name, param_name) -> ( match error with | _ -> - let custom_message = ": unable to revieve data via the socket." in - unix_error_message (error, fn_name, param_name) custom_message + let custom_message = ": unable to revieve data via the socket." in + unix_error_message (error, fn_name, param_name) custom_message) let read t fn_to_check_for_pattern = let open Protocol in let rec read t = match fn_to_check_for_pattern t.buffer with - | Complete (response, u) -> ( - let resp_len = (String.length response) + u in + | Complete (response, u) -> + let resp_len = String.length response + u in let buff_len = String.length t.buffer in let start = resp_len in let length = buff_len - resp_len in let () = t.buffer <- String.sub t.buffer start length in response - ) - | Incomplete ->( + | Incomplete -> let bytes = recvbytes t in - let buf = t.buffer ^ (Bytes.to_string bytes) in + let buf = t.buffer ^ Bytes.to_string bytes in let () = t.buffer <- buf in read t - ) in read t -let read_mpd_banner connection = - read connection Protocol.full_mpd_banner - -let read_request_response connection = - read connection Protocol.request_response - -let read_command_response connection = - read connection Protocol.command_response +let read_mpd_banner connection = read connection Protocol.full_mpd_banner +let read_request_response connection = read connection Protocol.request_response +let read_command_response connection = read connection Protocol.command_response diff --git a/lib/Connection.mli b/lib/Connection.mli index bed86c5..5438a92 100644 --- a/lib/Connection.mli +++ b/lib/Connection.mli @@ -22,29 +22,29 @@ type t (** connection type *) -val initialize: string -> int -> t +val initialize : string -> int -> t (** Create the connection, exit if the connection can not be initialized. *) -val hostname: t -> string +val hostname : t -> string (** Retrieve the host's string of the initialized connection. *) -val port: t -> int +val port : t -> int (** Retrieve the port of the connection of the initialized connection. *) -val close: t -> unit +val close : t -> unit (** Close the connection *) -val write: t -> string -> unit +val write : t -> string -> unit (** Write to an Mpd connection *) -val read: t -> (string -> Protocol.mpd_response) -> string +val read : t -> (string -> Protocol.mpd_response) -> string (** Read in an Mpd connection *) -val read_mpd_banner: t -> string +val read_mpd_banner : t -> string (** Read in an Mpd connection *) -val read_request_response: t -> string +val read_request_response : t -> string (** Read a Mpd response to a request.*) -val read_command_response: t -> string +val read_command_response : t -> string (** Read a Mpd response to a command.*) diff --git a/lib/Connection_lwt.ml b/lib/Connection_lwt.ml index 5f7b76e..6f5fb83 100644 --- a/lib/Connection_lwt.ml +++ b/lib/Connection_lwt.ml @@ -18,174 +18,142 @@ open Lwt -type t = - { hostname : string; - port : int; - ip : Unix.inet_addr; - socket : Lwt_unix.file_descr; - mutable buffer : string; - } +type t = { + hostname : string; + port : int; + ip : Unix.inet_addr; + socket : Lwt_unix.file_descr; + mutable buffer : string; +} exception Lwt_unix_exn of string -let fail_with_message m = - Lwt.fail (Lwt_unix_exn m) +let fail_with_message m = Lwt.fail (Lwt_unix_exn m) let gethostbyname name = Lwt.catch (fun () -> - Lwt_unix.gethostbyname name - >>= fun entry -> - let addrs = Array.to_list entry.Unix.h_addr_list in - Lwt.return addrs - ) + Lwt_unix.gethostbyname name >>= fun entry -> + let addrs = Array.to_list entry.Unix.h_addr_list in + Lwt.return addrs) (function - | Not_found -> let m = Printf.sprintf "Host not found, \ - Lwt_unix.gethostname: no host found\ - for %s. Exiting..." name in - fail_with_message m - - | e -> Lwt.fail e - ) + | Not_found -> + let m = + Printf.sprintf + "Host not found, Lwt_unix.gethostname: no host foundfor %s. \ + Exiting..." + name + in + fail_with_message m + | e -> Lwt.fail e) let open_socket addr port = Lwt.catch (fun () -> - let sock = Lwt_unix.socket Lwt_unix.PF_INET Lwt_unix.SOCK_STREAM 0 in - let sockaddr = Lwt_unix.ADDR_INET (addr, port) in - Lwt_unix.connect sock sockaddr - >>= fun () -> - Lwt.return sock - ) + let sock = Lwt_unix.socket Lwt_unix.PF_INET Lwt_unix.SOCK_STREAM 0 in + let sockaddr = Lwt_unix.ADDR_INET (addr, port) in + Lwt_unix.connect sock sockaddr >>= fun () -> Lwt.return sock) (function | Unix.Unix_error (error, fn_name, param_name) -> - let m = Printf.sprintf "%s, Unix.%s (%s): unable to open socket. - Exiting..." - (Unix.error_message error) - fn_name - param_name in - fail_with_message m - | e -> Lwt.fail e - ) + let m = + Printf.sprintf + "%s, Unix.%s (%s): unable to open socket.\n\ + \ Exiting..." + (Unix.error_message error) fn_name param_name + in + fail_with_message m + | e -> Lwt.fail e) let initialize hostname port = - gethostbyname hostname - >>= fun addrs -> + gethostbyname hostname >>= fun addrs -> let addr = List.hd addrs in - open_socket addr port - >>= fun socket -> - let conn = { hostname = hostname; - port = port; - ip = addr; - socket = socket; - buffer = ""; - } - in Lwt.return conn - -let hostname connection = - Lwt.return connection.hostname - -let port connection = - Lwt.return connection.port + open_socket addr port >>= fun socket -> + let conn = { hostname; port; ip = addr; socket; buffer = "" } in + Lwt.return conn -let buffer connection = - Lwt.return connection.buffer +let hostname connection = Lwt.return connection.hostname +let port connection = Lwt.return connection.port +let buffer connection = Lwt.return connection.buffer let write conn str = Lwt.catch (fun () -> - let {socket = socket; _} = conn in - let b = Bytes.of_string str in - let len = Bytes.length b in - Lwt_unix.send socket b 0 len [] - ) + let { socket; _ } = conn in + let b = Bytes.of_string str in + let len = Bytes.length b in + Lwt_unix.send socket b 0 len []) (function | Unix.Unix_error (error, fn_name, param_name) -> - let m = Printf.sprintf "%s, Unix.%s (%s): unable to write to socket \ - connected to %s:%s. Exiting..." - (Unix.error_message error) - fn_name - param_name - conn.hostname - (string_of_int conn.port) in - fail_with_message m - | e -> Lwt.fail e - ) + let m = + Printf.sprintf + "%s, Unix.%s (%s): unable to write to socket connected to %s:%s. \ + Exiting..." + (Unix.error_message error) fn_name param_name conn.hostname + (string_of_int conn.port) + in + fail_with_message m + | e -> Lwt.fail e) let recvbytes conn = Lwt.catch (fun () -> - let {socket = socket; _} = conn in - let maxlen = 1024 in - let buf = Bytes.create maxlen in - Lwt_unix.recv socket buf 0 maxlen [] - >>= fun recvlen -> - Lwt.return Bytes.(sub buf 0 recvlen) - ) + let { socket; _ } = conn in + let maxlen = 1024 in + let buf = Bytes.create maxlen in + Lwt_unix.recv socket buf 0 maxlen [] >>= fun recvlen -> + Lwt.return Bytes.(sub buf 0 recvlen)) (function | Unix.Unix_error (error, fn_name, param_name) -> - let m = Printf.sprintf "%s, Unix.%s (%s): unable to read from socket \ - connected to %s:%s. Exiting..." - (Unix.error_message error) - fn_name - param_name - conn.hostname - (string_of_int conn.port) in - fail_with_message m - | e -> Lwt.fail e - ) + let m = + Printf.sprintf + "%s, Unix.%s (%s): unable to read from socket connected to \ + %s:%s. Exiting..." + (Unix.error_message error) fn_name param_name conn.hostname + (string_of_int conn.port) + in + fail_with_message m + | e -> Lwt.fail e) let read connection fn_to_check_for_pattern = let open Protocol in let rec _read connection = match fn_to_check_for_pattern connection.buffer with - | Complete (response, u) -> ( - let resp_len = (String.length response) + u in + | Complete (response, u) -> + let resp_len = String.length response + u in let buff_len = String.length connection.buffer in let start = resp_len in let length = buff_len - resp_len in - let () = connection.buffer <- String.sub connection.buffer start length in + let () = + connection.buffer <- String.sub connection.buffer start length + in Lwt.return response - ) - | Incomplete ->( - recvbytes connection - >>= fun b -> - let buf = connection.buffer ^ (Bytes.to_string b) in + | Incomplete -> + recvbytes connection >>= fun b -> + let buf = connection.buffer ^ Bytes.to_string b in let () = connection.buffer <- buf in _read connection - ) in _read connection -let read_idle_events connection = - read connection Protocol.full_mpd_idle_event - -let read_mpd_banner connection = - read connection Protocol.full_mpd_banner - -let read_request_response connection = - read connection Protocol.request_response - -let read_command_response connection = - read connection Protocol.command_response +let read_idle_events connection = read connection Protocol.full_mpd_idle_event +let read_mpd_banner connection = read connection Protocol.full_mpd_banner +let read_request_response connection = read connection Protocol.request_response +let read_command_response connection = read connection Protocol.command_response let close conn = Lwt.catch (fun () -> - Loggin.debuf "close" - >>= fun () -> - let {socket = socket; _} = conn in - Lwt_unix.close socket - ) + Loggin.debuf "close" >>= fun () -> + let { socket; _ } = conn in + Lwt_unix.close socket) (function | Unix.Unix_error (error, fn_name, param_name) -> - let m = Printf.sprintf "%s, Unix.%s (%s): unable to read from socket \ - connected to %s:%s. Exiting..." - (Unix.error_message error) - fn_name - param_name - conn.hostname - (string_of_int conn.port) in - fail_with_message m - | e -> Lwt.fail e - ) + let m = + Printf.sprintf + "%s, Unix.%s (%s): unable to read from socket connected to \ + %s:%s. Exiting..." + (Unix.error_message error) fn_name param_name conn.hostname + (string_of_int conn.port) + in + fail_with_message m + | e -> Lwt.fail e) diff --git a/lib/Connection_lwt.mli b/lib/Connection_lwt.mli index 5d1d84d..ec6eaed 100644 --- a/lib/Connection_lwt.mli +++ b/lib/Connection_lwt.mli @@ -25,35 +25,34 @@ type t exception Lwt_unix_exn of string (** Custom exception. *) -val initialize: string -> int -> t Lwt.t +val initialize : string -> int -> t Lwt.t (** Create the connection in a Lwt thread, throws an exception Mpd_Lwt_unix_exn of string when an error occurs. *) -val hostname: t -> string Lwt.t +val hostname : t -> string Lwt.t (** Get the hostname of the current connection. *) -val port: t -> int Lwt.t +val port : t -> int Lwt.t (** Get the port of the current connection. *) -val buffer: t -> string Lwt.t +val buffer : t -> string Lwt.t (** Get the buffer used by the connection. *) -val recvbytes: t -> Bytes.t Lwt.t +val recvbytes : t -> Bytes.t Lwt.t (** Read from the connection. *) -val write: t -> string -> int Lwt.t +val write : t -> string -> int Lwt.t (** Write in a Mpd connection throught a Lwt thread. It fails with an exception Mpd_Lwt_unix_exn of string. *) (**/**) -val read_mpd_banner: t -> string Lwt.t -val read_idle_events: t -> string Lwt.t +val read_mpd_banner : t -> string Lwt.t +val read_idle_events : t -> string Lwt.t +val read_request_response : t -> string Lwt.t +val read_command_response : t -> string Lwt.t -val read_request_response: t -> string Lwt.t - -val read_command_response: t -> string Lwt.t (**/**) -val close: t -> unit Lwt.t +val close : t -> unit Lwt.t (** Close the connection. *) diff --git a/lib/Music_database.ml b/lib/Music_database.ml index 3ca6984..23c29b7 100644 --- a/lib/Music_database.ml +++ b/lib/Music_database.ml @@ -20,30 +20,30 @@ open Tags let search_find_wrapper cmd_name client what_list ?sort ?window () = let what = Tags.build_tag_parameter search_tag_to_string what_list in - let sort = match sort with - | None -> "" - | Some tag -> " sort " ^ (tag_to_string tag) + let sort = + match sort with None -> "" | Some tag -> " sort " ^ tag_to_string tag in - let window = match window with + let window = + match window with | None -> "" - | Some (start, stop) -> - Printf.sprintf " window %d:%d" start stop + | Some (start, stop) -> Printf.sprintf " window %d:%d" start stop in let cmd = Printf.sprintf "%s %s%s%s" cmd_name what sort window in match Client.send_request client cmd with | Error err -> Error err - | Ok response -> match response with - | None -> Ok [] - | Some r -> - let songs = - Str.split (Str.regexp_string "file:") r - |> let build_song s = - Utils.split_lines s |> Song.parse - in List.map build_song - in Ok songs + | Ok response -> ( + match response with + | None -> Ok [] + | Some r -> + let songs = + Str.split (Str.regexp_string "file:") r + |> + let build_song s = Utils.split_lines s |> Song.parse in + List.map build_song + in + Ok songs) let find = search_find_wrapper "find" - let search = search_find_wrapper "search" let search_find_add_wrapper cmd_name client what_list = @@ -52,31 +52,34 @@ let search_find_add_wrapper cmd_name client what_list = Client.send_command client cmd let findadd = search_find_add_wrapper "findadd" - let searchadd = search_find_add_wrapper "searchadd" let searchaddpl client playlist_name what_list = search_find_add_wrapper ("searchaddpl " ^ playlist_name) client what_list -type song_count = { songs: int; playtime: float; misc: string } +type song_count = { songs : int; playtime : float; misc : string } let count client what_list ?group () = let what = Tags.build_tag_parameter tag_to_string what_list in - let group = match group with - | None -> None - | Some tag -> Some (tag_to_string tag) + let group = + match group with None -> None | Some tag -> Some (tag_to_string tag) + in + let cmd = + Printf.sprintf "count %s %s" what + (match group with None -> "" | Some s -> " group " ^ s) in - let cmd = Printf.sprintf "count %s %s" what (match group with None -> "" | Some s -> " group " ^ s) in match Client.send_request client cmd with | Error (_, _, _, message) -> Error message - | Ok response -> match response with - | None -> Ok [] - | Some r -> - let result = Utils.parse_count_response r group in - let tuple_to_song_count (songs, playtime, misc) = {songs; playtime; misc} - in - let song_counts = List.map tuple_to_song_count result in - Ok song_counts + | Ok response -> ( + match response with + | None -> Ok [] + | Some r -> + let result = Utils.parse_count_response r group in + let tuple_to_song_count (songs, playtime, misc) = + { songs; playtime; misc } + in + let song_counts = List.map tuple_to_song_count result in + Ok song_counts) let list client tag tag_list = let filter = tag_to_string tag |> String.capitalize_ascii in @@ -84,24 +87,23 @@ let list client tag tag_list = let cmd = Printf.sprintf "list %s %s" filter tags in match Client.send_request client cmd with | Error (_, _, _, message) -> Error message - | Ok response -> match response with - | None -> Ok [] - | Some r -> - let r' = Utils.remove_trailing_new_line r in - let split_pattern = Printf.sprintf "\\(\n\\)*%s: " filter in - let l = match Str.split (Str.regexp split_pattern) r' with - | [] -> [] - | h :: t -> if h = "" then t else (h :: t) - in Ok l + | Ok response -> ( + match response with + | None -> Ok [] + | Some r -> + let r' = Utils.remove_trailing_new_line r in + let split_pattern = Printf.sprintf "\\(\n\\)*%s: " filter in + let l = + match Str.split (Str.regexp split_pattern) r' with + | [] -> [] + | h :: t -> if h = "" then t else h :: t + in + Ok l) let update client uri = - let cmd = match uri with - | None -> "update" - | Some uri' -> "update " ^ uri' - in Client.send_request client cmd + let cmd = match uri with None -> "update" | Some uri' -> "update " ^ uri' in + Client.send_request client cmd let rescan client uri = - let cmd = match uri with - | None -> "rescan" - | Some uri' -> "rescan " ^ uri' - in Client.send_command client cmd + let cmd = match uri with None -> "rescan" | Some uri' -> "rescan " ^ uri' in + Client.send_command client cmd diff --git a/lib/Music_database.mli b/lib/Music_database.mli index f1a909a..0d6d77e 100644 --- a/lib/Music_database.mli +++ b/lib/Music_database.mli @@ -18,9 +18,13 @@ (** Music_database module: regroups data base related commands. *) -val find: - Client.t -> (Tags.search_tags * string) list -> ?sort:Tags.t -> ?window:(int * int) - -> unit -> (Song.t list, Protocol.ack_error * int * string * string) result +val find : + Client.t -> + (Tags.search_tags * string) list -> + ?sort:Tags.t -> + ?window:int * int -> + unit -> + (Song.t list, Protocol.ack_error * int * string * string) result (** Find songs in the db that match exactly the a list of pairs (tag, exact_pattern). The exact_pattern is a string and the tah can be any tag supported by MPD, or one of the special parameters: @@ -29,37 +33,43 @@ val find: - base restricts the search to songs in the given directory (also relative to the music directory) - modified-since compares the file's time stamp with the given value (ISO 8601 or UNIX time stamp) *) -val findadd: - Client.t -> (Tags.search_tags * string) list -> Protocol.response +val findadd : Client.t -> (Tags.search_tags * string) list -> Protocol.response (** Find songs in the db that and adds them to current playlist. Parameters have the same meaning as for find. *) -val search: - Client.t -> (Tags.search_tags * string) list -> ?sort:Tags.t -> ?window:(int * int) - -> unit -> (Song.t list, Protocol.ack_error * int * string * string) result +val search : + Client.t -> + (Tags.search_tags * string) list -> + ?sort:Tags.t -> + ?window:int * int -> + unit -> + (Song.t list, Protocol.ack_error * int * string * string) result (** Search for any song that contains WHAT. Parameters have the same meaning as for find, except that search is not case sensitive. *) -val searchadd: +val searchadd : Client.t -> (Tags.search_tags * string) list -> Protocol.response (** Search for any song that contains WHAT in tag TYPE and adds them to current playlist. Parameters have the same meaning as for findadd, except that search is not case sensitive. *) -val searchaddpl: +val searchaddpl : Client.t -> string -> (Tags.search_tags * string) list -> Protocol.response (** Search for any song that contains WHAT in tag TYPE and adds them to the playlist named NAME. If a playlist by that name doesn't exist it is created. Parameters have the same meaning as for find, except that search is not case sensitive. *) +type song_count = { songs : int; playtime : float; misc : string } (** basic type for the response of the count command. *) -type song_count = { songs: int; playtime: float; misc: string } -val count: - Client.t -> (Tags.t * string) list -> ?group:Tags.t -> unit - -> (song_count list, string) result +val count : + Client.t -> + (Tags.t * string) list -> + ?group:Tags.t -> + unit -> + (song_count list, string) result (** Get a count of songs with filters. For examples: count group artist will return for each artist the number of sons, the total playtime and the name of the artist in misc. @@ -70,25 +80,24 @@ val count: count genre metal date 2016 group artist *) -val list: +val list : Client.t -> Tags.t -> (Tags.t * string) list -> (string list, string) result (** Get a list based on some filer. For example "list album artist "Elvis Presley"" will return a list of the album names of Elvis Presley that exists in the music database. *) -val update: - Client.t -> string option -> Protocol.response +val update : Client.t -> string option -> Protocol.response (** Updates the music database: find new files, remove deleted files, update modified files. URI is a particular directory or song/file to update. If you do not specify it, everything is updated. Prints "updating_db: JOBID" where JOBID is a positive number identifying the update job. You can read the current job id in the status response. *) -val rescan: - Client.t -> string option -> Protocol.response +val rescan : Client.t -> string option -> Protocol.response (** Same as update, but also rescans unmodified files. *) (**/**) + (* listfiles [URI] Lists the contents of the directory URI, including files are not recognized by MPD. URI can be a path relative to the music directory or an URI understood by one of the storage plugins. The response contains at least one line for each directory entry with the prefix "file: " or "directory: ", and may be followed by file attributes such as "Last-Modified" and "size". diff --git a/lib/Music_database_lwt.ml b/lib/Music_database_lwt.ml index 669ad6e..28949ef 100644 --- a/lib/Music_database_lwt.ml +++ b/lib/Music_database_lwt.ml @@ -21,30 +21,30 @@ open Tags let search_find_wrapper cmd_name client what_list ?sort ?window () = let what = Tags.build_tag_parameter search_tag_to_string what_list in - let sort = match sort with - | None -> "" - | Some tag -> " sort " ^ (tag_to_string tag) + let sort = + match sort with None -> "" | Some tag -> " sort " ^ tag_to_string tag in - let window = match window with + let window = + match window with | None -> "" | Some (start, stop) -> Printf.sprintf " window %d:%d" start stop in let cmd = Printf.sprintf "%s %s%s%s" cmd_name what sort window in - Client_lwt.request client cmd - >>= function + Client_lwt.request client cmd >>= function | Error err -> Lwt.return (Error err) - | Ok response -> match response with - | None -> Lwt.return (Ok []) - | Some r -> - let songs = - Str.split (Str.regexp_string "file:") r - |> let build_song s = - Utils.split_lines s |> Song.parse - in List.map build_song - in Lwt.return (Ok songs) + | Ok response -> ( + match response with + | None -> Lwt.return (Ok []) + | Some r -> + let songs = + Str.split (Str.regexp_string "file:") r + |> + let build_song s = Utils.split_lines s |> Song.parse in + List.map build_song + in + Lwt.return (Ok songs)) let find = search_find_wrapper "find" - let search = search_find_wrapper "search" let search_find_add_wrapper cmd_name client what_list = @@ -53,58 +53,58 @@ let search_find_add_wrapper cmd_name client what_list = Client_lwt.request client cmd let findadd = search_find_add_wrapper "findadd" - let searchadd = search_find_add_wrapper "searchadd" let searchaddpl client playlist_name what_list = search_find_add_wrapper ("searchaddpl " ^ playlist_name) client what_list -type song_count = { songs: int; playtime: float; misc: string } +type song_count = { songs : int; playtime : float; misc : string } let count client what_list ?group () = let what = Tags.build_tag_parameter tag_to_string what_list in - let group = match group with - | None -> None - | Some tag -> Some (tag_to_string tag) + let group = + match group with None -> None | Some tag -> Some (tag_to_string tag) in - let cmd = Printf.sprintf "count %s %s" what (match group with None -> "" | Some s -> "group " ^ s) in - Client_lwt.request client cmd - >>= function + let cmd = + Printf.sprintf "count %s %s" what + (match group with None -> "" | Some s -> "group " ^ s) + in + Client_lwt.request client cmd >>= function | Error (_, _, _, message) -> Lwt.return_error message - | Ok response -> match response with - | None -> Lwt.return_ok [] - | Some r -> - let result = Utils.parse_count_response r group in - let tuple_to_song_count (songs, playtime, misc) = {songs; playtime; misc} - in - let song_counts = List.map tuple_to_song_count result in - Lwt.return_ok song_counts + | Ok response -> ( + match response with + | None -> Lwt.return_ok [] + | Some r -> + let result = Utils.parse_count_response r group in + let tuple_to_song_count (songs, playtime, misc) = + { songs; playtime; misc } + in + let song_counts = List.map tuple_to_song_count result in + Lwt.return_ok song_counts) let list client tag tag_list = let filter = tag_to_string tag |> String.capitalize_ascii in let tags = Tags.build_tag_parameter tag_to_string tag_list in let cmd = Printf.sprintf "list %s %s" filter tags in - Client_lwt.request client cmd - >>= function + Client_lwt.request client cmd >>= function | Error (_, _, _, message) -> Lwt.return_error message - | Ok response -> match response with - | None -> Lwt.return_ok [] - | Some r -> - let r' = Utils.remove_trailing_new_line r in - let split_pattern = Printf.sprintf "\\(\n\\)*%s: " filter in - let l = match Str.split (Str.regexp split_pattern) r' with - | [] -> [] - | h :: t -> if h = "" then t else (h :: t) - in Lwt.return_ok l + | Ok response -> ( + match response with + | None -> Lwt.return_ok [] + | Some r -> + let r' = Utils.remove_trailing_new_line r in + let split_pattern = Printf.sprintf "\\(\n\\)*%s: " filter in + let l = + match Str.split (Str.regexp split_pattern) r' with + | [] -> [] + | h :: t -> if h = "" then t else h :: t + in + Lwt.return_ok l) let update client uri = - let cmd = match uri with - | None -> "update" - | Some uri' -> "update " ^ uri' - in Client_lwt.request client cmd + let cmd = match uri with None -> "update" | Some uri' -> "update " ^ uri' in + Client_lwt.request client cmd let rescan client uri = - let cmd = match uri with - | None -> "rescan" - | Some uri' -> "rescan " ^ uri' - in Client_lwt.send client cmd + let cmd = match uri with None -> "rescan" | Some uri' -> "rescan " ^ uri' in + Client_lwt.send client cmd diff --git a/lib/Music_database_lwt.mli b/lib/Music_database_lwt.mli index f946f99..27c7434 100644 --- a/lib/Music_database_lwt.mli +++ b/lib/Music_database_lwt.mli @@ -18,10 +18,13 @@ (** Music_database module with Lwt: regroups data base related commands. *) -val find: - Client_lwt.t -> (Tags.search_tags * string) list -> ?sort:Tags.t - -> ?window:(int * int) -> unit - -> (Song.t list, Protocol.ack_error * int * string * string) result Lwt.t +val find : + Client_lwt.t -> + (Tags.search_tags * string) list -> + ?sort:Tags.t -> + ?window:int * int -> + unit -> + (Song.t list, Protocol.ack_error * int * string * string) result Lwt.t (** Find songs in the db that match exactly the a list of pairs (tag, exact_pattern). The exact_pattern is a string and the tah can be any tag supported by MPD, or one of the special parameters: @@ -33,38 +36,47 @@ val find: (ISO 8601 or UNIX time stamp) *) -val findadd: +val findadd : Client_lwt.t -> (Tags.search_tags * string) list -> Protocol.response Lwt.t (* Find songs in the db that and adds them to current playlist. Parameters have the same meaning as for find. *) -val search: - Client_lwt.t -> (Tags.search_tags * string) list -> ?sort:Tags.t - -> ?window:(int * int) -> unit - -> (Song.t list, Protocol.ack_error * int * string * string) result Lwt.t +val search : + Client_lwt.t -> + (Tags.search_tags * string) list -> + ?sort:Tags.t -> + ?window:int * int -> + unit -> + (Song.t list, Protocol.ack_error * int * string * string) result Lwt.t (** Search for any song that contains WHAT. Parameters have the same meaning as for find, except that search is not case sensitive. *) -val searchadd: +val searchadd : Client_lwt.t -> (Tags.search_tags * string) list -> Protocol.response Lwt.t (** Search for any song that contains WHAT in tag TYPE and adds them to current playlist. Parameters have the same meaning as for findadd, except that search is not case sensitive. *) -val searchaddpl: - Client_lwt.t -> string -> (Tags.search_tags * string) list -> Protocol.response Lwt.t +val searchaddpl : + Client_lwt.t -> + string -> + (Tags.search_tags * string) list -> + Protocol.response Lwt.t (** Search for any song that contains WHAT in tag TYPE and adds them to the playlist named NAME. If a playlist by that name doesn't exist it is created. Parameters have the same meaning as for find, except that search is not case sensitive. *) -type song_count = { songs: int; playtime: float; misc: string } +type song_count = { songs : int; playtime : float; misc : string } (** basic type for the response of the count command. *) -val count: - Client_lwt.t -> (Tags.t * string) list -> ?group:Tags.t -> unit - -> (song_count list, string) result Lwt.t +val count : + Client_lwt.t -> + (Tags.t * string) list -> + ?group:Tags.t -> + unit -> + (song_count list, string) result Lwt.t (** Get a count of songs with filters. For examples: count group artist will return for each artist the number of sons, the total playtime and the name of the artist in misc. @@ -75,27 +87,27 @@ val count: count genre metal date 2016 group artist *) - -val list: - Client_lwt.t -> Tags.t -> (Tags.t * string) list - -> (string list, string) result Lwt.t +val list : + Client_lwt.t -> + Tags.t -> + (Tags.t * string) list -> + (string list, string) result Lwt.t (** Get a list based on some filer. For example "list album artist "Elvis Presley"" will return a list of the album names of Elvis Presley that exists in the music database. *) -val update: - Client_lwt.t -> string option -> Protocol.response Lwt.t +val update : Client_lwt.t -> string option -> Protocol.response Lwt.t (** Update the music database: find new files, remove deleted files, update modified files. URI is a particular directory or song/file to update. If you do not specify it, everything is updated. Prints "updating_db: JOBID" where JOBID is a positive number identifying the update job. You can read the current job id in the status response. *) -val rescan: - Client_lwt.t -> string option -> Protocol.response Lwt.t +val rescan : Client_lwt.t -> string option -> Protocol.response Lwt.t (** Same as update, but also rescans unmodified files. *) (**/**) + (* list {TYPE} [FILTERTYPE] [FILTERWHAT] [...] [group] [GROUPTYPE] [...] Lists unique tags values of the specified type. TYPE can be any tag supported by MPD or file. diff --git a/lib/Playback.ml b/lib/Playback.ml index 5c41c9f..aa06b81 100644 --- a/lib/Playback.ml +++ b/lib/Playback.ml @@ -16,32 +16,30 @@ * along with OCaml-libmpdclient. If not, see . *) -let next client = - Client.send_command client "next" - -let previous client = - Client.send_command client "previous" - -let stop client = - Client.send_command client "stop" +let next client = Client.send_command client "next" +let previous client = Client.send_command client "previous" +let stop client = Client.send_command client "stop" let pause client = function - | true -> Client.send_command client "pause 1" + | true -> Client.send_command client "pause 1" | false -> Client.send_command client "pause 0" let play client songpos = - Client.send_command client (String.concat " " ["play"; string_of_int songpos]) + Client.send_command client + (String.concat " " [ "play"; string_of_int songpos ]) let playid client songid = - Client.send_command client (String.concat " " ["playid"; string_of_int songid]) + Client.send_command client + (String.concat " " [ "playid"; string_of_int songid ]) let seek client songpos time = - String.concat " " ["seek"; string_of_int songpos; string_of_float time] + String.concat " " [ "seek"; string_of_int songpos; string_of_float time ] |> Client.send_command client let seekid client songid time = - String.concat " " ["seekid"; string_of_int songid; string_of_float time] + String.concat " " [ "seekid"; string_of_int songid; string_of_float time ] |> Client.send_command client let seekcur client time = - Client.send_command client (String.concat " " ["seekcur"; string_of_float time]) + Client.send_command client + (String.concat " " [ "seekcur"; string_of_float time ]) diff --git a/lib/Playback.mli b/lib/Playback.mli index a6c1d74..052d85d 100644 --- a/lib/Playback.mli +++ b/lib/Playback.mli @@ -19,31 +19,31 @@ (** Controlling playback functions. https://www.musicpd.org/doc/protocol/playback_commands.html *) -val next: Client.t -> Protocol.response +val next : Client.t -> Protocol.response (** Play next song in the playlist. *) -val previous: Client.t -> Protocol.response +val previous : Client.t -> Protocol.response (** Play previous song in the playlist. *) -val stop: Client.t -> Protocol.response +val stop : Client.t -> Protocol.response (** Stop playing.*) -val pause: Client.t -> bool -> Protocol.response +val pause : Client.t -> bool -> Protocol.response (** Toggle pause/resumers playing *) -val play: Client.t -> int -> Protocol.response +val play : Client.t -> int -> Protocol.response (** Begin playing the playlist at song number. *) -val playid: Client.t -> int -> Protocol.response +val playid : Client.t -> int -> Protocol.response (** Begin playing the playlist at song id. *) -val seek: Client.t -> int -> float -> Protocol.response +val seek : Client.t -> int -> float -> Protocol.response (** Seek to the position time of entry songpos in the playlist. *) -val seekid: Client.t -> int -> float -> Protocol.response +val seekid : Client.t -> int -> float -> Protocol.response (** Seek to the position time of song id. *) -val seekcur: Client.t -> float -> Protocol.response +val seekcur : Client.t -> float -> Protocol.response (** Seek to the position time within the current song. TODO : If prefixed by '+' or '-', then the time is relative to the current playing position diff --git a/lib/Playback_lwt.ml b/lib/Playback_lwt.ml index f5e7b72..2bcfb74 100644 --- a/lib/Playback_lwt.ml +++ b/lib/Playback_lwt.ml @@ -16,37 +16,28 @@ * along with OCaml-libmpdclient. If not, see . *) -let next client = - Client_lwt.send client "next" - -let previous client = - Client_lwt.send client "previous" - -let stop client = - Client_lwt.send client "stop" +let next client = Client_lwt.send client "next" +let previous client = Client_lwt.send client "previous" +let stop client = Client_lwt.send client "stop" let pause client arg = match arg with | true -> Client_lwt.send client "pause 1" - | _ -> Client_lwt.send client "pause 0" + | _ -> Client_lwt.send client "pause 0" let play client songpos = - Client_lwt.send client (String.concat " " ["play"; - string_of_int songpos]) + Client_lwt.send client (String.concat " " [ "play"; string_of_int songpos ]) let playid client songid = - Client_lwt.send client (String.concat " " ["playid"; - string_of_int songid]) + Client_lwt.send client (String.concat " " [ "playid"; string_of_int songid ]) let seek client songpos time = - Client_lwt.send client (String.concat " " ["seek"; - string_of_int songpos; - string_of_float time]) + Client_lwt.send client + (String.concat " " [ "seek"; string_of_int songpos; string_of_float time ]) let seekid client songid time = - Client_lwt.send client (String.concat " " ["seekid"; - string_of_int songid; - string_of_float time]) + Client_lwt.send client + (String.concat " " [ "seekid"; string_of_int songid; string_of_float time ]) let seekcur client time = - Client_lwt.send client (String.concat " " ["seekcur"; string_of_float time]) + Client_lwt.send client (String.concat " " [ "seekcur"; string_of_float time ]) diff --git a/lib/Playback_lwt.mli b/lib/Playback_lwt.mli index cf42654..c035e93 100644 --- a/lib/Playback_lwt.mli +++ b/lib/Playback_lwt.mli @@ -19,40 +19,31 @@ (** Controlling playback functions in Lwt thread. https://www.musicpd.org/doc/protocol/playback_commands.html *) -val next: - Client_lwt.t -> Protocol.response Lwt.t +val next : Client_lwt.t -> Protocol.response Lwt.t (** Play next song in the playlist. *) -val previous: - Client_lwt.t -> Protocol.response Lwt.t +val previous : Client_lwt.t -> Protocol.response Lwt.t (** Play previous song in the playlist. *) -val stop: - Client_lwt.t -> Protocol.response Lwt.t +val stop : Client_lwt.t -> Protocol.response Lwt.t (** Stop playing.*) -val pause: - Client_lwt.t -> bool -> Protocol.response Lwt.t +val pause : Client_lwt.t -> bool -> Protocol.response Lwt.t (** Toggle pause/resumers playing *) -val play: - Client_lwt.t -> int -> Protocol.response Lwt.t +val play : Client_lwt.t -> int -> Protocol.response Lwt.t (** Begin playing the playlist at song number. *) -val playid: - Client_lwt.t -> int -> Protocol.response Lwt.t +val playid : Client_lwt.t -> int -> Protocol.response Lwt.t (** Begin playing the playlist at song id. *) -val seek: - Client_lwt.t -> int -> float -> Protocol.response Lwt.t +val seek : Client_lwt.t -> int -> float -> Protocol.response Lwt.t (** Seek to the position time of entry songpos in the playlist. *) -val seekid: - Client_lwt.t -> int -> float -> Protocol.response Lwt.t +val seekid : Client_lwt.t -> int -> float -> Protocol.response Lwt.t (** Seek to the position time of song id. *) -val seekcur: - Client_lwt.t -> float -> Protocol.response Lwt.t +val seekcur : Client_lwt.t -> float -> Protocol.response Lwt.t (** Seek to the position time within the current song. TODO : If prefixed by '+' or '-', then the time is relative to the current playing position diff --git a/lib/Playback_options.ml b/lib/Playback_options.ml index 0bd0b81..4255f14 100644 --- a/lib/Playback_options.ml +++ b/lib/Playback_options.ml @@ -18,50 +18,46 @@ let consume client state = match state with - | true -> Client.send_command client "consume 1" + | true -> Client.send_command client "consume 1" | false -> Client.send_command client "consume 0" let crossfade client seconds = - Client.send_command client (String.concat " " ["crossfade"; - string_of_int seconds]) + Client.send_command client + (String.concat " " [ "crossfade"; string_of_int seconds ]) let mixrampdb client seconds = - Client.send_command client (String.concat " " ["mixrampdb"; - string_of_int seconds]) + Client.send_command client + (String.concat " " [ "mixrampdb"; string_of_int seconds ]) -type mixrampd_t = - | Nan - | Seconds of float +type mixrampd_t = Nan | Seconds of float let mixrampdelay client delay = match delay with | Nan -> Client.send_command client "mixrampdelay nan" - | Seconds (s) -> Client.send_command client (String.concat " " ["mixrampdelay"; - string_of_float s]) + | Seconds s -> + Client.send_command client + (String.concat " " [ "mixrampdelay"; string_of_float s ]) + let random client state = match state with - | true -> Client.send_command client "random 1" + | true -> Client.send_command client "random 1" | false -> Client.send_command client "random 0" let repeat client state = match state with - | true -> Client.send_command client "repeat 1" + | true -> Client.send_command client "repeat 1" | false -> Client.send_command client "repeat 0" let setvol client volume = - Client.send_command client (String.concat " " ["setvol"; - string_of_int volume]) + Client.send_command client + (String.concat " " [ "setvol"; string_of_int volume ]) let single client state = match state with - | true -> Client.send_command client "single 1" + | true -> Client.send_command client "single 1" | false -> Client.send_command client "single 0" -type gain_mode_t = - | Off - | Track - | Album - | Auto +type gain_mode_t = Off | Track | Album | Auto let replay_gain_mode client mode = match mode with @@ -69,4 +65,3 @@ let replay_gain_mode client mode = | Track -> Client.send_command client "replay_gain_mode track" | Album -> Client.send_command client "replay_gain_mode album" | Auto -> Client.send_command client "replay_gain_mode auto" - diff --git a/lib/Playback_options.mli b/lib/Playback_options.mli index 746e2bc..e546e1b 100644 --- a/lib/Playback_options.mli +++ b/lib/Playback_options.mli @@ -18,14 +18,14 @@ (** functions that configure all the playbackoptions *) -val consume: Client.t -> bool -> Protocol.response +val consume : Client.t -> bool -> Protocol.response (** Sets consume state to STATE, STATE should be false or true. When consume is activated, each song played is removed from playlist. *) -val crossfade: Client.t -> int -> Protocol.response +val crossfade : Client.t -> int -> Protocol.response (** Sets crossfading between songs. *) -val mixrampdb: Client.t -> int -> Protocol.response +val mixrampdb : Client.t -> int -> Protocol.response (** Sets the threshold at which songs will be overlapped. Like crossfading but doesn't fade the track volume, just overlaps. The songs need to have MixRamp tags added by an external tool. 0dB is the @@ -33,23 +33,25 @@ val mixrampdb: Client.t -> int -> Protocol.response In the absence of mixramp tags crossfading will be used. See http://sourceforge.net/projects/mixramp *) -type mixrampd_t = Nan | Seconds of float -(** Type for the command mixrampdelay, it can be float number for seconds or nan. *) +type mixrampd_t = + | Nan + | Seconds of float + (** Type for the command mixrampdelay, it can be float number for seconds or nan. *) -val mixrampdelay: Client.t -> mixrampd_t -> Protocol.response +val mixrampdelay : Client.t -> mixrampd_t -> Protocol.response (** Additional time subtracted from the overlap calculated by mixrampdb. A value of "nan" disables MixRamp overlapping and falls back to crossfading. *) -val random: Client.t -> bool -> Protocol.response +val random : Client.t -> bool -> Protocol.response (** Sets random state to STATE, STATE should be true or false *) -val repeat: Client.t -> bool -> Protocol.response +val repeat : Client.t -> bool -> Protocol.response (** Sets repeat state to STATE, STATE should be false or true. *) -val setvol: Client.t -> int -> Protocol.response +val setvol : Client.t -> int -> Protocol.response (** Sets volume to VOL, the range of volume is 0-100. *) -val single: Client.t -> bool -> Protocol.response +val single : Client.t -> bool -> Protocol.response (** Sets single state to STATE, STATE should be 0 or 1. When single is activated, playback is stopped after current song, or song is repeated if the 'repeat' mode is enabled. *) @@ -58,12 +60,10 @@ type gain_mode_t = | Off | Track | Album - | Auto -(** gain_mode type for the command replay_gain_mode. *) + | Auto (** gain_mode type for the command replay_gain_mode. *) -val replay_gain_mode: Client.t -> gain_mode_t -> Protocol.response +val replay_gain_mode : Client.t -> gain_mode_t -> Protocol.response (** Sets the replay gain mode. One of off, track, album, auto. Changing the mode during playback may take several seconds, because the new settings does not affect the buffered data. This command triggers the options idle event. *) - diff --git a/lib/Playback_options_lwt.ml b/lib/Playback_options_lwt.ml index e124b59..14c6827 100644 --- a/lib/Playback_options_lwt.ml +++ b/lib/Playback_options_lwt.ml @@ -17,46 +17,41 @@ *) let consume client = function - | true -> Client_lwt.send client "consume 1" + | true -> Client_lwt.send client "consume 1" | false -> Client_lwt.send client "consume 0" let crossfade client seconds = - Client_lwt.send client (String.concat " " ["crossfade"; - string_of_int seconds]) + Client_lwt.send client + (String.concat " " [ "crossfade"; string_of_int seconds ]) let mixrampdb client seconds = - Client_lwt.send client (String.concat " " ["mixrampdb"; - string_of_int seconds]) + Client_lwt.send client + (String.concat " " [ "mixrampdb"; string_of_int seconds ]) -type mixrampd_t = - | Nan - | Seconds of float +type mixrampd_t = Nan | Seconds of float let mixrampdelay client = function | Nan -> Client_lwt.send client "mixrampdelay nan" - | Seconds (s) -> Client_lwt.send client (String.concat " " ["mixrampdelay"; - string_of_float s]) + | Seconds s -> + Client_lwt.send client + (String.concat " " [ "mixrampdelay"; string_of_float s ]) + let random client = function - | true -> Client_lwt.send client "random 1" + | true -> Client_lwt.send client "random 1" | false -> Client_lwt.send client "random 0" let repeat client = function - | true -> Client_lwt.send client "repeat 1" + | true -> Client_lwt.send client "repeat 1" | false -> Client_lwt.send client "repeat 0" let setvol client volume = - Client_lwt.send client (String.concat " " ["setvol"; - string_of_int volume]) + Client_lwt.send client (String.concat " " [ "setvol"; string_of_int volume ]) let single client = function - | true -> Client_lwt.send client "single 1" + | true -> Client_lwt.send client "single 1" | false -> Client_lwt.send client "single 0" -type gain_mode_t = - | Off - | Track - | Album - | Auto +type gain_mode_t = Off | Track | Album | Auto let replay_gain_mode client = function | Off -> Client_lwt.send client "replay_gain_mode off" diff --git a/lib/Playback_options_lwt.mli b/lib/Playback_options_lwt.mli index a0b4303..d84b66b 100644 --- a/lib/Playback_options_lwt.mli +++ b/lib/Playback_options_lwt.mli @@ -18,14 +18,14 @@ (** functions that configure all the playbackoptions in a Lwt thread.*) -val consume: Client_lwt.t -> bool -> Protocol.response Lwt.t +val consume : Client_lwt.t -> bool -> Protocol.response Lwt.t (** Sets consume state to STATE, STATE should be false or true. When consume is activated, each song played is removed from playlist. *) -val crossfade: Client_lwt.t -> int -> Protocol.response Lwt.t +val crossfade : Client_lwt.t -> int -> Protocol.response Lwt.t (** Sets crossfading between songs. *) -val mixrampdb: Client_lwt.t -> int -> Protocol.response Lwt.t +val mixrampdb : Client_lwt.t -> int -> Protocol.response Lwt.t (** Sets the threshold at which songs will be overlapped. Like crossfading but doesn't fade the track volume, just overlaps. The songs need to have MixRamp tags added by an external tool. 0dB is the @@ -36,22 +36,22 @@ val mixrampdb: Client_lwt.t -> int -> Protocol.response Lwt.t type mixrampd_t = | Nan | Seconds of float -(** Type for the command mixrampdelay, it can be float for seconds or nan. *) + (** Type for the command mixrampdelay, it can be float for seconds or nan. *) -val mixrampdelay: Client_lwt.t -> mixrampd_t -> Protocol.response Lwt.t +val mixrampdelay : Client_lwt.t -> mixrampd_t -> Protocol.response Lwt.t (** Additional time subtracted from the overlap calculated by mixrampdb. A value of "nan" disables MixRamp overlapping and falls back to crossfading. *) -val random: Client_lwt.t -> bool -> Protocol.response Lwt.t +val random : Client_lwt.t -> bool -> Protocol.response Lwt.t (** Sets random state to STATE, STATE should be true or false *) -val repeat: Client_lwt.t -> bool -> Protocol.response Lwt.t +val repeat : Client_lwt.t -> bool -> Protocol.response Lwt.t (** Sets repeat state to STATE, STATE should be false or true. *) -val setvol: Client_lwt.t -> int -> Protocol.response Lwt.t +val setvol : Client_lwt.t -> int -> Protocol.response Lwt.t (** Sets volume to VOL, the range of volume is 0-100. *) -val single: Client_lwt.t -> bool -> Protocol.response Lwt.t +val single : Client_lwt.t -> bool -> Protocol.response Lwt.t (** Sets single state to STATE, STATE should be 0 or 1. When single is activated, playback is stopped after current song, or song is repeated if the 'repeat' mode is enabled. *) @@ -60,12 +60,10 @@ type gain_mode_t = | Off | Track | Album - | Auto -(** gain_mode type for the command replay_gain_mode. *) + | Auto (** gain_mode type for the command replay_gain_mode. *) -val replay_gain_mode: Client_lwt.t -> gain_mode_t -> Protocol.response Lwt.t +val replay_gain_mode : Client_lwt.t -> gain_mode_t -> Protocol.response Lwt.t (** Sets the replay gain mode. One of off, track, album, auto. Changing the mode during playback may take several seconds, because the new settings does not affect the buffered data. This command triggers the options idle event. *) - diff --git a/lib/Protocol.ml b/lib/Protocol.ml index c0cb22a..dfcd50c 100644 --- a/lib/Protocol.ml +++ b/lib/Protocol.ml @@ -17,42 +17,44 @@ *) type ack_error = - | Not_list (* 1 *) - | Arg (* 2 *) - | Password (* 3 *) - | Permission (* 4 *) - | Unknown (* 5 *) - | No_exist (* 50 *) - | Playlist_max (* 51 *) - | System (* 52 *) - | Playlist_load (* 53 *) - | Update_already (* 54 *) - | Player_sync (* 55 *) - | Exist (* 56 *) - -type response = Ok of string option | Error of (ack_error * int * string * string) + | Not_list (* 1 *) + | Arg (* 2 *) + | Password (* 3 *) + | Permission (* 4 *) + | Unknown (* 5 *) + | No_exist (* 50 *) + | Playlist_max (* 51 *) + | System (* 52 *) + | Playlist_load (* 53 *) + | Update_already (* 54 *) + | Player_sync (* 55 *) + | Exist (* 56 *) + +type response = + | Ok of string option + | Error of (ack_error * int * string * string) let error_name = function - | Not_list -> "Not_list" - | Arg -> "Arg" - | Password -> "Password" - | Permission -> "Permission" - | Unknown -> "Unknown" - | No_exist -> "No_exist" - | Playlist_max -> "Playlist_max" - | System -> "System" + | Not_list -> "Not_list" + | Arg -> "Arg" + | Password -> "Password" + | Permission -> "Permission" + | Unknown -> "Unknown" + | No_exist -> "No_exist" + | Playlist_max -> "Playlist_max" + | System -> "System" | Playlist_load -> "Playlist_load" - | Update_already-> "Update_already" - | Player_sync -> "Player_sync" - | Exist -> "Exist" + | Update_already -> "Update_already" + | Player_sync -> "Player_sync" + | Exist -> "Exist" let str_error_to_val str = match str with - | "1" -> Not_list - | "2" -> Arg - | "3" -> Password - | "4" -> Permission - | "5" -> Unknown + | "1" -> Not_list + | "2" -> Arg + | "3" -> Password + | "4" -> Permission + | "5" -> Unknown | "50" -> No_exist | "51" -> Playlist_max | "52" -> System @@ -63,17 +65,16 @@ let str_error_to_val str = | _ -> Unknown let ok_response_pattern = "\\(\\(\n\\|.\\)*\\)OK$" - let ok_response_reg = Str.regexp ok_response_pattern let error_response_pattern = let dec = "[0-9]" in - let error = String.concat "" ["\\("; dec; dec; "?\\)"] in - let cmd_num = String.concat "" ["\\("; dec; "+\\)"] in + let error = String.concat "" [ "\\("; dec; dec; "?\\)" ] in + let cmd_num = String.concat "" [ "\\("; dec; "+\\)" ] in let cmd = "\\(.*\\)" in let message = "\\(.*\\)" in String.concat "" - ["ACK \\["; error; "\\@"; cmd_num; "\\] \\{"; cmd; "\\} "; message; "\n"] + [ "ACK \\["; error; "\\@"; cmd_num; "\\] \\{"; cmd; "\\} "; message; "\n" ] let error_response_reg = Str.regexp error_response_pattern @@ -84,9 +85,9 @@ let is_error_response mpd_response = Str.string_match error_response_reg mpd_response 0 let parse_error_response mpd_response = - ignore(Str.string_match error_response_reg mpd_response 0); + ignore (Str.string_match error_response_reg mpd_response 0); let ack_val = str_error_to_val (Str.matched_group 1 mpd_response) in - let ack_cmd_num = int_of_string(Str.matched_group 2 mpd_response) in + let ack_cmd_num = int_of_string (Str.matched_group 2 mpd_response) in let ack_cmd = Str.matched_group 3 mpd_response in let ack_message = Str.matched_group 4 mpd_response in (ack_val, ack_cmd_num, ack_cmd, ack_message) @@ -94,23 +95,21 @@ let parse_error_response mpd_response = let parse_response mpd_response = if is_ok_response mpd_response then let str = Str.matched_group 1 mpd_response in - if str = "" then Ok (None) else Ok (Some str) - else - Error (parse_error_response mpd_response) + if str = "" then Ok None else Ok (Some str) + else Error (parse_error_response mpd_response) (** Type and functions used to check if the current response is full based on pattern defined by the mpd protocol.*) -type mpd_response = - | Incomplete - | Complete of (string * int) +type mpd_response = Incomplete | Complete of (string * int) let check_full_response mpd_data pattern group useless_char = let response = Str.regexp pattern in match Str.string_match response mpd_data 0 with | true -> Complete (Str.matched_group group mpd_data, useless_char) - | false -> match is_error_response mpd_data with - | true -> Complete (Str.matched_group 0 mpd_data, 0) - | false -> Incomplete + | false -> ( + match is_error_response mpd_data with + | true -> Complete (Str.matched_group 0 mpd_data, 0) + | false -> Incomplete) let full_mpd_banner mpd_data = let pattern = "OK \\(.*\\)\n" in diff --git a/lib/Protocol.mli b/lib/Protocol.mli index 952dcc5..e80aafe 100644 --- a/lib/Protocol.mli +++ b/lib/Protocol.mli @@ -20,57 +20,50 @@ (* https://github.com/sol/mpd/blob/master/src/ack.h *) type ack_error = - | Not_list (* 1 *) - | Arg (* 2 *) - | Password (* 3 *) - | Permission (* 4 *) - | Unknown (* 5 *) - | No_exist (* 50 *) - | Playlist_max (* 51 *) - | System (* 52 *) - | Playlist_load (* 53 *) - | Update_already (* 54 *) - | Player_sync (* 55 *) - | Exist (* 56 *) -(** Type of error that could occur when a command is sent to the mpd server. *) + | Not_list (* 1 *) + | Arg (* 2 *) + | Password (* 3 *) + | Permission (* 4 *) + | Unknown (* 5 *) + | No_exist (* 50 *) + | Playlist_max (* 51 *) + | System (* 52 *) + | Playlist_load (* 53 *) + | Update_already (* 54 *) + | Player_sync (* 55 *) + | Exist (* 56 *) + (** Type of error that could occur when a command is sent to the mpd server. *) type response = - | Ok of string option | Error of (ack_error * int * string * string) -(** Type of the response of the mpd server. *) + | Ok of string option + | Error of (ack_error * int * string * string) + (** Type of the response of the mpd server. *) -val error_name: - ack_error -> string +val error_name : ack_error -> string (** Get the error name of the error type. *) -val str_error_to_val: - string -> ack_error +val str_error_to_val : string -> ack_error (** Return the related type for the error returned by the server as a string. *) -val parse_error_response: - string -> (ack_error * int * string * string) +val parse_error_response : string -> ack_error * int * string * string (** Parse the error response of the mpd server into the error type. *) -val parse_response: - string -> response +val parse_response : string -> response (** Parse the mpd server response *) type mpd_response = | Incomplete | Complete of (string * int) -(** Type used to describe a data while reading through a socket. *) + (** Type used to describe a data while reading through a socket. *) -val full_mpd_banner: - string -> mpd_response +val full_mpd_banner : string -> mpd_response (** fetch mpd banner*) -val request_response: - string -> mpd_response +val request_response : string -> mpd_response (** fetch request response.*) -val command_response: - string -> mpd_response +val command_response : string -> mpd_response (** fetch command response.*) -val full_mpd_idle_event: - string -> mpd_response +val full_mpd_idle_event : string -> mpd_response (** Get the Mpd response for an idle command. *) diff --git a/lib/Queue.ml b/lib/Queue.ml index 8e267f9..c717a00 100644 --- a/lib/Queue.ml +++ b/lib/Queue.ml @@ -18,171 +18,186 @@ open Utils -type t = - | PlaylistError of string | Playlist of Song.t list +type t = PlaylistError of string | Playlist of Song.t list -let add client uri = - Client.send_command client uri +let add client uri = Client.send_command client uri let addid client uri position = - let cmd = String.concat " " ["addid"; uri; string_of_int position] in + let cmd = String.concat " " [ "addid"; uri; string_of_int position ] in let response = Client.send_command client cmd in match response with - |Protocol.Ok (song_id_opt) -> ( + | Protocol.Ok song_id_opt -> ( match song_id_opt with | None -> -1 - | Some song_id -> let lines = Utils.split_lines song_id in - let rec parse lines = - match lines with - | [] -> -1 - | line :: remain -> let { key = k; value = v} = Utils.read_key_val line in - if (k = "Id") then int_of_string v - else parse remain - in parse lines - ) - |Protocol.Error (_) -> -1 - -let clear client = - Client.send_command client "clear" + | Some song_id -> + let lines = Utils.split_lines song_id in + let rec parse lines = + match lines with + | [] -> -1 + | line :: remain -> + let { key = k; value = v } = Utils.read_key_val line in + if k = "Id" then int_of_string v else parse remain + in + parse lines) + | Protocol.Error _ -> -1 + +let clear client = Client.send_command client "clear" let delete client position ?position_end () = - let cmd = match position_end with - |None -> String.concat " " ["delete"; string_of_int position] - |Some pos_end -> String.concat "" ["delete "; - string_of_int position; - ":"; - string_of_int pos_end] - in Client.send_command client cmd + let cmd = + match position_end with + | None -> String.concat " " [ "delete"; string_of_int position ] + | Some pos_end -> + String.concat "" + [ "delete "; string_of_int position; ":"; string_of_int pos_end ] + in + Client.send_command client cmd let deleteid client id = - Client.send_command client (String.concat " " ["deleteid"; string_of_int id]) + Client.send_command client + (String.concat " " [ "deleteid"; string_of_int id ]) let move client position_from ?position_end position_to () = - let cmd = match position_end with - |None -> String.concat " " ["move"; - string_of_int position_from; - string_of_int position_to] - |Some pos_end -> String.concat "" ["move "; - string_of_int position_from; - ":"; - string_of_int pos_end; - " "; - string_of_int position_to] - in Client.send_command client cmd + let cmd = + match position_end with + | None -> + String.concat " " + [ "move"; string_of_int position_from; string_of_int position_to ] + | Some pos_end -> + String.concat "" + [ + "move "; + string_of_int position_from; + ":"; + string_of_int pos_end; + " "; + string_of_int position_to; + ] + in + Client.send_command client cmd let moveid client id position_to = - Client.send_command client (String.concat " " ["moveid"; - string_of_int id; - string_of_int position_to]) + Client.send_command client + (String.concat " " + [ "moveid"; string_of_int id; string_of_int position_to ]) let get_song_pos song = let pattern = "\\([0-9]+\\):file:.*" in let found = Str.string_match (Str.regexp pattern) song 0 in - if found then Str.matched_group 1 song - else "none" + if found then Str.matched_group 1 song else "none" let rec _build_songs_list client songs l = match songs with | [] -> Playlist (List.rev l) - | h :: q -> let song_infos_request = "playlistinfo " ^ (get_song_pos h) in - match Client.send_request client song_infos_request with - | Protocol.Error (_ack_val, _ack_cmd_num, _ack_cmd, ack_message) -> - let message = - Printf.sprintf "Song %s : %s " (get_song_pos h) ack_message in - PlaylistError message - | Protocol.Ok (song_infos_opt) -> begin - match song_infos_opt with - | None -> - let message = "No song infos for " ^ (get_song_pos h) in + | h :: q -> ( + let song_infos_request = "playlistinfo " ^ get_song_pos h in + match Client.send_request client song_infos_request with + | Protocol.Error (_ack_val, _ack_cmd_num, _ack_cmd, ack_message) -> + let message = + Printf.sprintf "Song %s : %s " (get_song_pos h) ack_message + in PlaylistError message - | Some song_infos -> - let song = Song.parse (Utils.split_lines song_infos) in - _build_songs_list client q (song :: l) - end + | Protocol.Ok song_infos_opt -> ( + match song_infos_opt with + | None -> + let message = "No song infos for " ^ get_song_pos h in + PlaylistError message + | Some song_infos -> + let song = Song.parse (Utils.split_lines song_infos) in + _build_songs_list client q (song :: l))) let _playlist_ client request = match Client.send_request client request with | Protocol.Error (_ack_val, _ack_cmd_num, _ack_cmd, ack_message) -> - PlaylistError (ack_message) - | Protocol.Ok (response_opt) -> match response_opt with - | None -> Playlist [] - | Some response -> let songs = Utils.split_lines response in - _build_songs_list client songs [] + PlaylistError ack_message + | Protocol.Ok response_opt -> ( + match response_opt with + | None -> Playlist [] + | Some response -> + let songs = Utils.split_lines response in + _build_songs_list client songs []) -let playlist client = - _playlist_ client "playlist" +let playlist client = _playlist_ client "playlist" let playlistid client id = - let request = "playlistid " ^ (string_of_int id) in + let request = "playlistid " ^ string_of_int id in match Client.send_request client request with | Protocol.Error (_ack_val, _ack_cmd_num, _ack_cmd, ack_message) -> - Error ack_message - | Protocol.Ok (response_opt) -> match response_opt with - | None -> - let message = "No song with id " ^ (string_of_int id) in Error message - | Some response -> - let song = Song.parse (Utils.split_lines response) in Ok song + Error ack_message + | Protocol.Ok response_opt -> ( + match response_opt with + | None -> + let message = "No song with id " ^ string_of_int id in + Error message + | Some response -> + let song = Song.parse (Utils.split_lines response) in + Ok song) let playlistfind client tag needle = - let request = String.concat " " ["playlistfind"; tag; needle] in + let request = String.concat " " [ "playlistfind"; tag; needle ] in _playlist_ client request let playlistsearch client tag needle = - let request = String.concat " " ["playlistsearch"; tag; needle] in + let request = String.concat " " [ "playlistsearch"; tag; needle ] in _playlist_ client request let swap client pos1 pos2 = - let request = String.concat " " ["swap"; - string_of_int pos1; - string_of_int pos2] in + let request = + String.concat " " [ "swap"; string_of_int pos1; string_of_int pos2 ] + in Client.send_command client request let shuffle client ?range () = - let request = match range with - |None -> "shuffle" - |Some (s, e) -> let r = String.concat ":" [string_of_int s; string_of_int e] in - String.concat " " ["shuffle"; r] - in Client.send_command client request + let request = + match range with + | None -> "shuffle" + | Some (s, e) -> + let r = String.concat ":" [ string_of_int s; string_of_int e ] in + String.concat " " [ "shuffle"; r ] + in + Client.send_command client request let prio client priority ?range () = - let priority' = string_of_int ( if priority > 255 then 255 - else if priority < 0 then 0 - else priority) + let priority' = + string_of_int + (if priority > 255 then 255 else if priority < 0 then 0 else priority) in - let request = match range with + let request = + match range with | None -> "prio " ^ priority' - | Some (s, e) -> let r = String.concat ":" [string_of_int s; string_of_int e] in - String.concat " " ["prio"; priority'; r] - in Client.send_command client request + | Some (s, e) -> + let r = String.concat ":" [ string_of_int s; string_of_int e ] in + String.concat " " [ "prio"; priority'; r ] + in + Client.send_command client request let prioid client priority ids = - let priority' = string_of_int ( if priority > 255 then 255 - else if priority < 0 then 0 - else priority) + let priority' = + string_of_int + (if priority > 255 then 255 else if priority < 0 then 0 else priority) in let ids' = String.concat " " (List.map (fun i -> string_of_int i) ids) in - let request = String.concat " " ["prioid"; priority'; ids'] in + let request = String.concat " " [ "prioid"; priority'; ids' ] in Client.send_command client request let swapid client id1 id2 = - let request = String.concat " " ["swapid"; - string_of_int id1; - string_of_int id2 ] in + let request = + String.concat " " [ "swapid"; string_of_int id1; string_of_int id2 ] + in Client.send_command client request let rangeid client id ?range () = let id' = string_of_int id in let cmd = "rangeid" in - let request = match range with - | None -> String.concat " " [cmd; id'; ":"] + let request = + match range with + | None -> String.concat " " [ cmd; id'; ":" ] | Some (s, e) -> - let r = String.concat ":" [string_of_float s; string_of_float e] in - String.concat " " [cmd; r] + let r = String.concat ":" [ string_of_float s; string_of_float e ] in + String.concat " " [ cmd; r ] in Client.send_request client request let cleartagid client id tag = - let request = String.concat " " ["cleartagid"; - string_of_int id; - tag] in + let request = String.concat " " [ "cleartagid"; string_of_int id; tag ] in Client.send_command client request diff --git a/lib/Queue.mli b/lib/Queue.mli index af00abd..d491e8b 100644 --- a/lib/Queue.mli +++ b/lib/Queue.mli @@ -20,97 +20,81 @@ type t = | PlaylistError of string - | Playlist of Song.t list -(** Playlist type. *) + | Playlist of Song.t list (** Playlist type. *) -val add: - Client.t -> string -> Protocol.response +val add : Client.t -> string -> Protocol.response (** Add the file URI to the playlist (directories add recursively). URI can also be a single file. *) -val addid: - Client.t -> string -> int -> int +val addid : Client.t -> string -> int -> int (** Add a song to the playlist (non-recursive) and returns the song id. URI is always a single file or URL. *) -val clear: - Client.t -> Protocol.response +val clear : Client.t -> Protocol.response (** Clear the current playlist. *) -val delete: - Client.t -> int -> ?position_end:int -> unit -> Protocol.response +val delete : Client.t -> int -> ?position_end:int -> unit -> Protocol.response (** Delete a song or a set of songs from the playlist. The song or the range of songs are identified by the position in the playlist. *) -val deleteid: - Client.t -> int -> Protocol.response +val deleteid : Client.t -> int -> Protocol.response (** Delete the song SONGID from the playlist. *) -val move: +val move : Client.t -> int -> ?position_end:int -> int -> unit -> Protocol.response (** Move the song at FROM or range of songs at START:END to TO in the playlist. *) -val moveid: - Client.t -> int -> int -> Protocol.response +val moveid : Client.t -> int -> int -> Protocol.response (** Move the song with FROM (songid) to TO (playlist index) in the playlist. If TO is negative, it is relative to the current song in the playlist (if there is one). *) -val playlist: - Client.t -> t +val playlist : Client.t -> t (** Get the songs in the playlist *) -val playlistid: - Client.t -> int -> (Song.t, string) result +val playlistid : Client.t -> int -> (Song.t, string) result (** Get information for one song *) -val playlistfind: - Client.t -> string -> string -> t +val playlistfind : Client.t -> string -> string -> t (** Find songs in the current playlist with strict matching.*) -val playlistsearch: - Client.t -> string -> string -> t +val playlistsearch : Client.t -> string -> string -> t (** Search case-insensitively for partial matches in the current playlist. *) -val swap: - Client.t -> int -> int -> Protocol.response +val swap : Client.t -> int -> int -> Protocol.response (** Swap the positions of SONG1 and SONG2. *) -val shuffle: - Client.t -> ?range:(int * int) -> unit -> Protocol.response +val shuffle : Client.t -> ?range:int * int -> unit -> Protocol.response (** Shuffle the current playlist. START:END is optional and specifies a range of songs. *) -val prio: - Client.t -> int -> ?range:(int * int) -> unit -> Protocol.response +val prio : Client.t -> int -> ?range:int * int -> unit -> Protocol.response (** Set the priority of the specified songs. A higher priority means that it will be played first when "random" mode is enabled. A priority is an integer between 0 and 255. The default priority of new songs is 0. *) -val prioid: - Client.t -> int -> int list -> Protocol.response +val prioid : Client.t -> int -> int list -> Protocol.response (** Same as prio, but address the songs with their id. *) -val swapid: - Client.t -> int -> int -> Protocol.response +val swapid : Client.t -> int -> int -> Protocol.response (** Swap the positions of SONG1 and SONG2 (both song ids). *) -val rangeid: - Client.t -> int -> ?range:(float * float) -> unit -> Protocol.response +val rangeid : + Client.t -> int -> ?range:float * float -> unit -> Protocol.response (** Specify the portion of the song that shall be played. START and END are offsets in seconds (fractional seconds allowed); both are optional. Omitting both (i.e. sending just ":") means "remove the range, play everything". A song that is currently playing cannot be manipulated this way. *) -val cleartagid: - Client.t -> int -> string -> Protocol.response +val cleartagid : Client.t -> int -> string -> Protocol.response (** Remove tags from the specified song. If TAG is not specified, then all tag values will be removed. Editing song tags is only possible for remote songs. *) (**/**) + (* plchanges {VERSION} [START:END] plchangesposid {VERSION} [START:END] diff --git a/lib/Queue_lwt.ml b/lib/Queue_lwt.ml index 03a98fa..9b8933a 100644 --- a/lib/Queue_lwt.ml +++ b/lib/Queue_lwt.ml @@ -19,182 +19,185 @@ open Utils open Lwt.Infix -type t = - | PlaylistError of string - | Playlist of Song.t list +type t = PlaylistError of string | Playlist of Song.t list -let add client uri = - Client_lwt.send client uri +let add client uri = Client_lwt.send client uri let addid client uri position = - let cmd = String.concat " " ["addid"; uri; string_of_int position] in - Client_lwt.request client cmd - >>= function - | Protocol.Ok (response) ->( + let cmd = String.concat " " [ "addid"; uri; string_of_int position ] in + Client_lwt.request client cmd >>= function + | Protocol.Ok response -> ( match response with | None -> Lwt.return (-1) | Some song_id -> - let lines = Utils.split_lines song_id in - let rec parse lines = - match lines with - | [] -> Lwt.return (-1) - | line :: remain -> - let { key = k; value = v} = Utils.read_key_val line in - if (k = "Id") then Lwt.return (int_of_string v) - else Lwt.return remain - >>= fun lines -> - parse lines - in parse lines - ) + let lines = Utils.split_lines song_id in + let rec parse lines = + match lines with + | [] -> Lwt.return (-1) + | line :: remain -> + let { key = k; value = v } = Utils.read_key_val line in + if k = "Id" then Lwt.return (int_of_string v) + else Lwt.return remain >>= fun lines -> parse lines + in + parse lines) | Protocol.Error _ -> Lwt.return (-1) -let clear client = - Client_lwt.send client "clear" +let clear client = Client_lwt.send client "clear" let delete client position ?position_end () = - let cmd = match position_end with - |None -> String.concat " " ["delete"; string_of_int position] - |Some pos_end -> String.concat "" ["delete "; - string_of_int position; - ":"; - string_of_int pos_end] - in Client_lwt.send client cmd + let cmd = + match position_end with + | None -> String.concat " " [ "delete"; string_of_int position ] + | Some pos_end -> + String.concat "" + [ "delete "; string_of_int position; ":"; string_of_int pos_end ] + in + Client_lwt.send client cmd let deleteid client id = - Client_lwt.send client (String.concat " " ["deleteid"; string_of_int id]) + Client_lwt.send client (String.concat " " [ "deleteid"; string_of_int id ]) let move client position_from ?position_end position_to () = - let cmd = match position_end with - |None -> String.concat " " ["move"; - string_of_int position_from; - string_of_int position_to] - |Some pos_end -> String.concat "" ["move "; - string_of_int position_from; - ":"; - string_of_int pos_end; - " "; - string_of_int position_to] - in Client_lwt.send client cmd + let cmd = + match position_end with + | None -> + String.concat " " + [ "move"; string_of_int position_from; string_of_int position_to ] + | Some pos_end -> + String.concat "" + [ + "move "; + string_of_int position_from; + ":"; + string_of_int pos_end; + " "; + string_of_int position_to; + ] + in + Client_lwt.send client cmd let moveid client id position_to = - Client_lwt.send client (String.concat " " ["moveid"; - string_of_int id; - string_of_int position_to]) + Client_lwt.send client + (String.concat " " + [ "moveid"; string_of_int id; string_of_int position_to ]) let get_song_pos song = let pattern = "\\([0-9]+\\):file:.*" in let found = Str.string_match (Str.regexp pattern) song 0 in - if found then Str.matched_group 1 song - else "none" + if found then Str.matched_group 1 song else "none" let rec _build_songs_list client songs l = match songs with - | [] -> let playlist = Playlist (List.rev l) in Lwt.return playlist - | h :: q -> let song_infos_request = "playlistinfo " ^ (get_song_pos h) in - Client_lwt.request client song_infos_request - >>= function - | Protocol.Error (_, _, _, ack_message)-> - Lwt.return (PlaylistError (ack_message)) - | Protocol.Ok (song_infos_opt) -> - match song_infos_opt with - | None -> - let message = "No song information for " ^ (get_song_pos h) in - Lwt.return (PlaylistError message) - | Some song_infos -> - let song = Song.parse (Utils.split_lines song_infos) in - _build_songs_list client q (song :: l) + | [] -> + let playlist = Playlist (List.rev l) in + Lwt.return playlist + | h :: q -> ( + let song_infos_request = "playlistinfo " ^ get_song_pos h in + Client_lwt.request client song_infos_request >>= function + | Protocol.Error (_, _, _, ack_message) -> + Lwt.return (PlaylistError ack_message) + | Protocol.Ok song_infos_opt -> ( + match song_infos_opt with + | None -> + let message = "No song information for " ^ get_song_pos h in + Lwt.return (PlaylistError message) + | Some song_infos -> + let song = Song.parse (Utils.split_lines song_infos) in + _build_songs_list client q (song :: l))) let playlist_command_responses_handler client = function - | Protocol.Error (_, _, _, ack_message)-> - Lwt.return (PlaylistError (ack_message)) - | Protocol.Ok (response_opt) -> match response_opt with - | None -> Lwt.return (Playlist []) - | Some response -> let songs = Utils.split_lines response in - _build_songs_list client songs [] + | Protocol.Error (_, _, _, ack_message) -> + Lwt.return (PlaylistError ack_message) + | Protocol.Ok response_opt -> ( + match response_opt with + | None -> Lwt.return (Playlist []) + | Some response -> + let songs = Utils.split_lines response in + _build_songs_list client songs []) let playlist client = - Client_lwt.request client "playlist" - >>= fun response -> + Client_lwt.request client "playlist" >>= fun response -> playlist_command_responses_handler client response let playlistid client id = - let request = "playlistid " ^ (string_of_int id) in - Client_lwt.request client request - >>= function + let request = "playlistid " ^ string_of_int id in + Client_lwt.request client request >>= function | Protocol.Error (_ack_val, _ack_cmd_num, _ack_cmd, ack_message) -> - Lwt.return_error ack_message - | Protocol.Ok (response_opt) -> match response_opt with - | None -> - let message = "No song with id " ^ (string_of_int id) in - Lwt.return_error message - | Some response -> - let song = Song.parse (Utils.split_lines response) in Lwt.return_ok song + Lwt.return_error ack_message + | Protocol.Ok response_opt -> ( + match response_opt with + | None -> + let message = "No song with id " ^ string_of_int id in + Lwt.return_error message + | Some response -> + let song = Song.parse (Utils.split_lines response) in + Lwt.return_ok song) let playlistfind client tag needle = - let request = String.concat " " ["playlistfind"; tag; needle] in - Client_lwt.request client request - >>= fun response -> + let request = String.concat " " [ "playlistfind"; tag; needle ] in + Client_lwt.request client request >>= fun response -> playlist_command_responses_handler client response let playlistsearch client tag needle = - let request = String.concat " " ["playlistsearch"; tag; needle] in - Client_lwt.request client request - >>= fun response -> + let request = String.concat " " [ "playlistsearch"; tag; needle ] in + Client_lwt.request client request >>= fun response -> playlist_command_responses_handler client response let swap client pos1 pos2 = - Client_lwt.send client (String.concat " " ["swap"; - string_of_int pos1; - string_of_int pos2]) + Client_lwt.send client + (String.concat " " [ "swap"; string_of_int pos1; string_of_int pos2 ]) let shuffle client ?range () = - let request = match range with - |None -> "shuffle" - |Some (s, e) -> - let r = String.concat ":" [string_of_int s; string_of_int e] in - String.concat " " ["shuffle"; r] - in Client_lwt.send client request + let request = + match range with + | None -> "shuffle" + | Some (s, e) -> + let r = String.concat ":" [ string_of_int s; string_of_int e ] in + String.concat " " [ "shuffle"; r ] + in + Client_lwt.send client request let prio client priority ?range () = - let priority' = string_of_int ( if priority > 255 then 255 - else if priority < 0 then 0 - else priority) + let priority' = + string_of_int + (if priority > 255 then 255 else if priority < 0 then 0 else priority) in - let request = match range with + let request = + match range with | None -> "prio " ^ priority' | Some (s, e) -> - let r = String.concat ":" [string_of_int s; string_of_int e] in - String.concat " " ["prio"; priority'; r] - in Client_lwt.send client request + let r = String.concat ":" [ string_of_int s; string_of_int e ] in + String.concat " " [ "prio"; priority'; r ] + in + Client_lwt.send client request let prioid client priority ids = - let priority' = string_of_int ( if priority > 255 then 255 - else if priority < 0 then 0 - else priority) + let priority' = + string_of_int + (if priority > 255 then 255 else if priority < 0 then 0 else priority) in let ids' = String.concat " " (List.map (fun i -> string_of_int i) ids) in - let request = String.concat " " ["prioid"; priority'; ids'] in + let request = String.concat " " [ "prioid"; priority'; ids' ] in Client_lwt.send client request let swapid client id1 id2 = - let request = String.concat " " ["swapid"; - string_of_int id1; - string_of_int id2 ] in + let request = + String.concat " " [ "swapid"; string_of_int id1; string_of_int id2 ] + in Client_lwt.send client request let rangeid client id ?range () = let id' = string_of_int id in let cmd = "rangeid" in - let request = match range with - | None -> String.concat " " [cmd; id'; ":"] + let request = + match range with + | None -> String.concat " " [ cmd; id'; ":" ] | Some (s, e) -> - let r = String.concat ":" [string_of_float s; string_of_float e] in - String.concat " " [cmd; r] + let r = String.concat ":" [ string_of_float s; string_of_float e ] in + String.concat " " [ cmd; r ] in Client_lwt.send client request let cleartagid client id tag = - let request = String.concat " " ["cleartagid"; - string_of_int id; - tag] in + let request = String.concat " " [ "cleartagid"; string_of_int id; tag ] in Client_lwt.send client request diff --git a/lib/Queue_lwt.mli b/lib/Queue_lwt.mli index 8147475..2ec133b 100644 --- a/lib/Queue_lwt.mli +++ b/lib/Queue_lwt.mli @@ -20,91 +20,84 @@ type t = | PlaylistError of string - | Playlist of Song.t list -(** Playlist type *) + | Playlist of Song.t list (** Playlist type *) -val add: - Client_lwt.t -> string -> Protocol.response Lwt.t +val add : Client_lwt.t -> string -> Protocol.response Lwt.t (** Add the file URI to the playlist (directories add recursively). URI can also be a single file. *) -val addid: - Client_lwt.t -> string -> int -> int Lwt.t +val addid : Client_lwt.t -> string -> int -> int Lwt.t (** Add a song to the playlist (non-recursive) and returns the song id. URI is always a single file or URL. For example: *) -val clear: - Client_lwt.t -> Protocol.response Lwt.t +val clear : Client_lwt.t -> Protocol.response Lwt.t (** Clear the current playlist. *) -val delete: +val delete : Client_lwt.t -> int -> ?position_end:int -> unit -> Protocol.response Lwt.t (** Delete a song or a set of songs from the playlist. The song or the range of songs are identified by the position in the playlist. *) -val deleteid: - Client_lwt.t -> int -> Protocol.response Lwt.t +val deleteid : Client_lwt.t -> int -> Protocol.response Lwt.t (** Delete the song SONGID from the playlist. *) -val move: - Client_lwt.t -> int -> ?position_end:int -> int -> unit -> Protocol.response Lwt.t +val move : + Client_lwt.t -> + int -> + ?position_end:int -> + int -> + unit -> + Protocol.response Lwt.t (** Move the song at FROM or range of songs at START:END to TO in the playlist. *) -val moveid: - Client_lwt.t -> int -> int -> Protocol.response Lwt.t +val moveid : Client_lwt.t -> int -> int -> Protocol.response Lwt.t (** Move the song with FROM (songid) to TO (playlist index) in the playlist. If TO is negative, it is relative to the current song in the playlist (if there is one). *) -val playlist: - Client_lwt.t -> t Lwt.t +val playlist : Client_lwt.t -> t Lwt.t (** Get a list of Song.s that represents all the songs in the current playlist. *) -val playlistid: - Client_lwt.t -> int -> (Song.t, string) result Lwt.t +val playlistid : Client_lwt.t -> int -> (Song.t, string) result Lwt.t (** Get a list with the Song.s of the song id in the playlist *) -val playlistfind: - Client_lwt.t -> string -> string -> t Lwt.t +val playlistfind : Client_lwt.t -> string -> string -> t Lwt.t (** Find songs in the current playlist with strict matching.*) -val playlistsearch: - Client_lwt.t -> string -> string -> t Lwt.t +val playlistsearch : Client_lwt.t -> string -> string -> t Lwt.t (** Search case-insensitively for partial matches in the current playlist. *) -val swap: - Client_lwt.t -> int -> int -> Protocol.response Lwt.t +val swap : Client_lwt.t -> int -> int -> Protocol.response Lwt.t (** Swap the positions of SONG1 and SONG2. *) -val shuffle: - Client_lwt.t -> ?range:(int * int) -> unit -> Protocol.response Lwt.t +val shuffle : + Client_lwt.t -> ?range:int * int -> unit -> Protocol.response Lwt.t (** Shuffle the current playlist. START:END is optional and specifies a range of songs. *) -val prio: - Client_lwt.t -> int -> ?range:(int * int) -> unit -> Protocol.response Lwt.t +val prio : + Client_lwt.t -> int -> ?range:int * int -> unit -> Protocol.response Lwt.t (** Set the priority of the specified songs. A higher priority means that it will be played first when "random" mode is enabled. A priority is an integer between 0 and 255. The default priority of new songs is 0. *) -val prioid: Client_lwt.t -> int -> int list -> Protocol.response Lwt.t +val prioid : Client_lwt.t -> int -> int list -> Protocol.response Lwt.t (** Same as prio, but address the songs with their id. *) -val swapid: Client_lwt.t -> int -> int -> Protocol.response Lwt.t +val swapid : Client_lwt.t -> int -> int -> Protocol.response Lwt.t (** Swap the positions of SONG1 and SONG2 (both song ids). *) -val rangeid: - Client_lwt.t -> int -> ?range:(float * float) -> unit -> Protocol.response Lwt.t +val rangeid : + Client_lwt.t -> int -> ?range:float * float -> unit -> Protocol.response Lwt.t (** Specify the portion of the song that shall be played. START and END are offsets in seconds (fractional seconds allowed); both are optional. Omitting both (i.e. sending just ":") means "remove the range, play everything". A song that is currently playing cannot be manipulated this way. *) -val cleartagid: - Client_lwt.t -> int -> string -> Protocol.response Lwt.t +val cleartagid : Client_lwt.t -> int -> string -> Protocol.response Lwt.t (** Remove tags from the specified song. If TAG is not specified, then all tag values will be removed. Editing song tags is only possible for remote songs. *) diff --git a/lib/Song.ml b/lib/Song.ml index 0acae5c..7977be6 100644 --- a/lib/Song.ml +++ b/lib/Song.ml @@ -19,149 +19,108 @@ open Utils type t = { - album: string; - albumsort: string; (* TODO : int ? *) - albumartist: string; - albumartistsort: string; (* TODO : int ? *) - artist: string; - artistsort: string; (* TODO : int ? *) - comment: string; - composer: string; - date: string; - disc: string; (* TODO : num_on_num *) - duration: float; - file: string; - genre: string; - id: int; - last_modified: string; - name: string; - performer: string; - pos: int; - rate: int; - time: int; - title: string; - track: string; (* TODO : num_on_num *) + album : string; + albumsort : string; (* TODO : int ? *) + albumartist : string; + albumartistsort : string; (* TODO : int ? *) + artist : string; + artistsort : string; (* TODO : int ? *) + comment : string; + composer : string; + date : string; + disc : string; (* TODO : num_on_num *) + duration : float; + file : string; + genre : string; + id : int; + last_modified : string; + name : string; + performer : string; + pos : int; + rate : int; + time : int; + title : string; + track : string; (* TODO : num_on_num *) } -let empty = { - album = ""; - albumsort = ""; - albumartist = ""; - albumartistsort = ""; - artist = ""; - artistsort = ""; - comment = ""; - composer = ""; - date = ""; - disc = ""; - duration = 0.0; - file = ""; - genre = ""; - id = 0; - last_modified = ""; - name = ""; - performer = ""; - pos = 0; - rate = 0; - time = 0; - title = ""; - track = ""; -} +let empty = + { + album = ""; + albumsort = ""; + albumartist = ""; + albumartistsort = ""; + artist = ""; + artistsort = ""; + comment = ""; + composer = ""; + date = ""; + disc = ""; + duration = 0.0; + file = ""; + genre = ""; + id = 0; + last_modified = ""; + name = ""; + performer = ""; + pos = 0; + rate = 0; + time = 0; + title = ""; + track = ""; + } let parse lines = let rec _parse pairs s = match pairs with | [] -> s - | p :: remain -> let { key = k; value = v} = Utils.read_key_val p in - match k with - | "Album" -> _parse remain { s with album = v } - | "AlbumSort" -> _parse remain { s with albumsort = v } - | "AlbumArtist" -> _parse remain { s with albumartist = v } - | "AlbumArtistSort" -> _parse remain { s with albumartistsort = v } - | "Artist" -> _parse remain { s with artist = v } - | "ArtistSort" -> _parse remain { s with artistsort = v } - | "Comment" -> _parse remain { s with comment = v } - | "Composer" -> _parse remain { s with composer = v } - | "Date" -> _parse remain { s with date = v } - | "Disc" -> _parse remain { s with disc = v } - | "duration" -> _parse remain { s with duration = float_of_string v } - | "Genre" -> _parse remain { s with genre = v } - | "File" -> _parse remain { s with file = v } - | "Id" -> _parse remain { s with id = int_of_string v } - | "Last-Modified" -> _parse remain { s with last_modified = v } - | "Name" -> _parse remain { s with title = v } - | "Performer" -> _parse remain { s with performer = v } - | "Pos" -> _parse remain { s with pos = int_of_string v } - | "Rate" -> _parse remain { s with rate = int_of_string v } - | "Time" -> _parse remain { s with time = int_of_string v } - | "Title" -> _parse remain { s with title = v } - | "Track" -> _parse remain { s with track = v } - | _ -> _parse remain s - in _parse lines empty - -let album {album = a; _} = - a - -let albumsort {albumsort = a; _} = - a - -let albumartist {albumartist = a; _} = - a - -let albumartistsort {albumartist = a; _} = - a - -let artist {artist = a; _} = - a - -let artistsort {artist = a; _} = - a - -let comment {comment = c; _} = - c - -let composer {composer = c; _} = - c - -let date {date = d; _} = - d - -let disc {disc = d; _} = - d - -let duration {duration = d; _} = - d - -let file {file = f; _} = - f - -let genre {genre = g; _} = - g - -let id {id = i; _} = - i - -let last_modified {last_modified = l; _} = - l - -let name {name = n; _} = - n - -let performer {performer = p; _} = - p - -let pos {pos = p; _} = - p - -let rate {rate = r; _} = - r - -let time {time = t; _} = - t - -let title {title = t; _} = - t - -let track {track = t; _} = - t - + | p :: remain -> ( + let { key = k; value = v } = Utils.read_key_val p in + match k with + | "Album" -> _parse remain { s with album = v } + | "AlbumSort" -> _parse remain { s with albumsort = v } + | "AlbumArtist" -> _parse remain { s with albumartist = v } + | "AlbumArtistSort" -> _parse remain { s with albumartistsort = v } + | "Artist" -> _parse remain { s with artist = v } + | "ArtistSort" -> _parse remain { s with artistsort = v } + | "Comment" -> _parse remain { s with comment = v } + | "Composer" -> _parse remain { s with composer = v } + | "Date" -> _parse remain { s with date = v } + | "Disc" -> _parse remain { s with disc = v } + | "duration" -> _parse remain { s with duration = float_of_string v } + | "Genre" -> _parse remain { s with genre = v } + | "File" -> _parse remain { s with file = v } + | "Id" -> _parse remain { s with id = int_of_string v } + | "Last-Modified" -> _parse remain { s with last_modified = v } + | "Name" -> _parse remain { s with title = v } + | "Performer" -> _parse remain { s with performer = v } + | "Pos" -> _parse remain { s with pos = int_of_string v } + | "Rate" -> _parse remain { s with rate = int_of_string v } + | "Time" -> _parse remain { s with time = int_of_string v } + | "Title" -> _parse remain { s with title = v } + | "Track" -> _parse remain { s with track = v } + | _ -> _parse remain s) + in + _parse lines empty + +let album { album = a; _ } = a +let albumsort { albumsort = a; _ } = a +let albumartist { albumartist = a; _ } = a +let albumartistsort { albumartist = a; _ } = a +let artist { artist = a; _ } = a +let artistsort { artist = a; _ } = a +let comment { comment = c; _ } = c +let composer { composer = c; _ } = c +let date { date = d; _ } = d +let disc { disc = d; _ } = d +let duration { duration = d; _ } = d +let file { file = f; _ } = f +let genre { genre = g; _ } = g +let id { id = i; _ } = i +let last_modified { last_modified = l; _ } = l +let name { name = n; _ } = n +let performer { performer = p; _ } = p +let pos { pos = p; _ } = p +let rate { rate = r; _ } = r +let time { time = t; _ } = t +let title { title = t; _ } = t +let track { track = t; _ } = t diff --git a/lib/Song.mli b/lib/Song.mli index 9a7c25a..b768b01 100644 --- a/lib/Song.mli +++ b/lib/Song.mli @@ -22,34 +22,34 @@ type t (** Song type *) -val empty: t +val empty : t (** Empty song type *) -val parse: string list -> t +val parse : string list -> t (** Parse a list of song attributes to a Song.s type *) -val album: t -> string -val albumsort: t -> string -val albumartist: t -> string -val albumartistsort: t -> string -val artist: t -> string -val artistsort: t -> string -val comment: t -> string -val composer: t -> string -val date: t -> string -val disc: t -> string -val duration: t -> float -val file: t -> string -val genre: t -> string -val id: t -> int -val last_modified: t -> string -val name: t -> string -val performer: t -> string -val pos: t -> int -val rate: t -> int -val time: t -> int -val title: t -> string -val track: t -> string +val album : t -> string +val albumsort : t -> string +val albumartist : t -> string +val albumartistsort : t -> string +val artist : t -> string +val artistsort : t -> string +val comment : t -> string +val composer : t -> string +val date : t -> string +val disc : t -> string +val duration : t -> float +val file : t -> string +val genre : t -> string +val id : t -> int +val last_modified : t -> string +val name : t -> string +val performer : t -> string +val pos : t -> int +val rate : t -> int +val time : t -> int +val title : t -> string +val track : t -> string (* TAG_MUSICBRAINZ_ARTISTID diff --git a/lib/Status.ml b/lib/Status.ml index ec16b37..723319c 100644 --- a/lib/Status.ml +++ b/lib/Status.ml @@ -33,29 +33,33 @@ let string_of_state = function | Stop -> "stop" | ErrState -> "error state" -type t = -{ volume: int; (** 0-100 *) - repeat: bool; (** false or true *) - random: bool; (** false or true *) - single: bool; (** false or true *) - consume: bool; (** false or true *) - playlist: int; (** 31-bit unsigned integer, the playlist version number *) - playlistlength: int; (** the length of the playlist *) - state: state; (** play, stop, or pause *) - song: int; (** playlist song number of the current song stopped on or playing *) - songid: int; (** playlist songid of the current song stopped on or playing *) - nextsong: int; (** playlist song number of the next song to be played *) - nextsongid: int; (** playlist songid of the next song to be played *) - time: string; (** total time elapsed (of current playing/paused song) *) - elapsed: float; (** Total time elapsed within the current song, but with higher resolution. *) - duration: float; (** Duration of the current song in seconds. *) - bitrate: int; (** instantaneous bitrate in kbps. *) - xfade: int; (** crossfade in seconds *) - mixrampdb: float; (** mixramp threshold in dB *) - mixrampdelay: float; (** mixrampdelay in seconds *) - audio: string; (** sampleRate:bits:channels TODO : Maybe create a specific type later *) - updating_db: int; (** job id *) - error: string; (** If there is an error, returns message here *) +type t = { + volume : int; (** 0-100 *) + repeat : bool; (** false or true *) + random : bool; (** false or true *) + single : bool; (** false or true *) + consume : bool; (** false or true *) + playlist : int; (** 31-bit unsigned integer, the playlist version number *) + playlistlength : int; (** the length of the playlist *) + state : state; (** play, stop, or pause *) + song : int; + (** playlist song number of the current song stopped on or playing *) + songid : int; + (** playlist songid of the current song stopped on or playing *) + nextsong : int; (** playlist song number of the next song to be played *) + nextsongid : int; (** playlist songid of the next song to be played *) + time : string; (** total time elapsed (of current playing/paused song) *) + elapsed : float; + (** Total time elapsed within the current song, but with higher resolution. *) + duration : float; (** Duration of the current song in seconds. *) + bitrate : int; (** instantaneous bitrate in kbps. *) + xfade : int; (** crossfade in seconds *) + mixrampdb : float; (** mixramp threshold in dB *) + mixrampdelay : float; (** mixrampdelay in seconds *) + audio : string; + (** sampleRate:bits:channels TODO : Maybe create a specific type later *) + updating_db : int; (** job id *) + error : string; (** If there is an error, returns message here *) } let empty = @@ -88,95 +92,60 @@ let parse lines = let rec _parse pairs s = match pairs with | [] -> s - | p :: remain -> let { key = k; value = v} = Utils.read_key_val p in - match k with - | "volume" -> _parse remain { s with volume = int_of_string v } - | "repeat" -> _parse remain { s with repeat = Utils.bool_of_int_str v } - | "random" -> _parse remain { s with random = Utils.bool_of_int_str v } - | "single" -> _parse remain { s with single = Utils.bool_of_int_str v } - | "consume" -> _parse remain { s with consume = Utils.bool_of_int_str v } - | "playlist" -> _parse remain { s with playlist = int_of_string v } - | "playlistlength" -> _parse remain { s with playlistlength = int_of_string v } - | "state" -> _parse remain { s with state = state_of_string v } - | "song" -> _parse remain { s with song = int_of_string v } - | "songid" -> _parse remain { s with songid = int_of_string v } - | "nextsong" -> _parse remain { s with nextsong = int_of_string v } - | "nextsongid" -> _parse remain { s with nextsongid = int_of_string v } - | "time" -> _parse remain { s with time = v } (* TODO: !! mpd time format min:sec*) - | "elapsed" -> _parse remain { s with elapsed = float_of_string v } - | "duration" -> _parse remain { s with duration = float_of_string v } - | "bitrate" -> _parse remain { s with bitrate = int_of_string v } - | "xfade" -> _parse remain { s with xfade = int_of_string v } - | "mixrampdb" -> _parse remain { s with mixrampdb = float_of_string v } - | "mixrampdelay" -> _parse remain { s with mixrampdelay = float_of_string v } - | "audio" -> _parse remain { s with audio = v } - | "updating_db" -> _parse remain { s with updating_db = int_of_string v } - | "error" -> _parse remain { s with error = v } - | _ -> _parse remain s - in _parse lines empty - -let volume {volume = v; _} = - v - -let repeat {repeat = r; _} = - r - -let random {random = r; _} = - r - -let single {single = s; _} = - s - -let consume {consume = c; _} = - c - -let playlist {playlist = p; _} = - p - -let playlistlength {playlistlength = p; _} = - p - -let state {state = s; _} = - s - -let song {song = s; _} = - s - -let songid {songid = s; _} = - s - -let nextsong {nextsong = n; _} = - n - -let nextsongid {nextsongid = n; _} = - n - -let time {time = t; _} = - t - -let elapsed {elapsed = e; _} = - e - -let duration {duration = d; _} = - d - -let bitrate {bitrate = b; _} = - b - -let xfade {xfade = x; _} = - x - -let mixrampdb {mixrampdb = m; _} = - m - -let mixrampdelay {mixrampdelay = m; _} = - m - -let audio {audio = a; _} = - a - -let updating_db {updating_db = u; _} = - u - -let error {error = e; _} = - e + | p :: remain -> ( + let { key = k; value = v } = Utils.read_key_val p in + match k with + | "volume" -> _parse remain { s with volume = int_of_string v } + | "repeat" -> _parse remain { s with repeat = Utils.bool_of_int_str v } + | "random" -> _parse remain { s with random = Utils.bool_of_int_str v } + | "single" -> _parse remain { s with single = Utils.bool_of_int_str v } + | "consume" -> + _parse remain { s with consume = Utils.bool_of_int_str v } + | "playlist" -> _parse remain { s with playlist = int_of_string v } + | "playlistlength" -> + _parse remain { s with playlistlength = int_of_string v } + | "state" -> _parse remain { s with state = state_of_string v } + | "song" -> _parse remain { s with song = int_of_string v } + | "songid" -> _parse remain { s with songid = int_of_string v } + | "nextsong" -> _parse remain { s with nextsong = int_of_string v } + | "nextsongid" -> _parse remain { s with nextsongid = int_of_string v } + | "time" -> + _parse remain { s with time = v } + (* TODO: !! mpd time format min:sec*) + | "elapsed" -> _parse remain { s with elapsed = float_of_string v } + | "duration" -> _parse remain { s with duration = float_of_string v } + | "bitrate" -> _parse remain { s with bitrate = int_of_string v } + | "xfade" -> _parse remain { s with xfade = int_of_string v } + | "mixrampdb" -> _parse remain { s with mixrampdb = float_of_string v } + | "mixrampdelay" -> + _parse remain { s with mixrampdelay = float_of_string v } + | "audio" -> _parse remain { s with audio = v } + | "updating_db" -> + _parse remain { s with updating_db = int_of_string v } + | "error" -> _parse remain { s with error = v } + | _ -> _parse remain s) + in + _parse lines empty + +let volume { volume = v; _ } = v +let repeat { repeat = r; _ } = r +let random { random = r; _ } = r +let single { single = s; _ } = s +let consume { consume = c; _ } = c +let playlist { playlist = p; _ } = p +let playlistlength { playlistlength = p; _ } = p +let state { state = s; _ } = s +let song { song = s; _ } = s +let songid { songid = s; _ } = s +let nextsong { nextsong = n; _ } = n +let nextsongid { nextsongid = n; _ } = n +let time { time = t; _ } = t +let elapsed { elapsed = e; _ } = e +let duration { duration = d; _ } = d +let bitrate { bitrate = b; _ } = b +let xfade { xfade = x; _ } = x +let mixrampdb { mixrampdb = m; _ } = m +let mixrampdelay { mixrampdelay = m; _ } = m +let audio { audio = a; _ } = a +let updating_db { updating_db = u; _ } = u +let error { error = e; _ } = e diff --git a/lib/Status.mli b/lib/Status.mli index 656554f..eb100a7 100644 --- a/lib/Status.mli +++ b/lib/Status.mli @@ -21,79 +21,83 @@ type t (** Main status type that contains all the status information of the server. *) -type state = Play | Pause | Stop | ErrState -(** Current state (playing, pause or stopped) of the mpd server. *) - -val string_of_state: state -> string +type state = + | Play + | Pause + | Stop + | ErrState + (** Current state (playing, pause or stopped) of the mpd server. *) + +val string_of_state : state -> string (** Get the string representation of a state. *) -val parse: string list -> t +val parse : string list -> t (** Parse list of strings into a Mpd Status type *) -val volume: t -> int +val volume : t -> int (** Get the volume level from a Mpd Status *) -val repeat: t -> bool +val repeat : t -> bool (** Find out if the player is in repeat mode *) -val random: t -> bool +val random : t -> bool (** Find out if the player is in random mode *) -val single: t -> bool +val single : t -> bool (** Find out if the player is in single mode *) -val consume: t -> bool +val consume : t -> bool (** Find out if the player is in consume mode *) -val playlist: t -> int +val playlist : t -> int (** Get the current playlist id *) -val playlistlength: t -> int +val playlistlength : t -> int (** Get the current playlist length *) -val state: t -> state +val state : t -> state (** Get the state of the player : Play / Pause / Stop *) -val song: t -> int +val song : t -> int (** Get the song number of the current song stopped on or playing *) -val songid: t -> int +val songid : t -> int (** Get the song id of the current song stopped on or playing *) -val nextsong: t -> int +val nextsong : t -> int (** Get the next song number based on the current song stopped on or playing *) -val nextsongid: t -> int +val nextsongid : t -> int (** Get the next song id based on the current song stopped on or playing *) -val time: t -> string +val time : t -> string (** Get the total time elapsed (of current playing/paused song) *) -val elapsed: t -> float +val elapsed : t -> float (** Get the total time elapsed within the current song, but with higher resolution *) -val duration: t -> float +val duration : t -> float (** Returns the totatl duration of the current song in seconds *) -val bitrate: t -> int +val bitrate : t -> int (** Get the instantaneous bitrate in kbps *) -val xfade: t -> int +val xfade : t -> int (** Get the crossfade in seconds of the current song *) -val mixrampdb: t -> float +val mixrampdb : t -> float (** Get the mixramp threshold in dB *) -val mixrampdelay: t -> float +val mixrampdelay : t -> float (** Get the mixrampdelay in seconds *) -val audio: t -> string +val audio : t -> string (** Get information of the audio file of the current song (sampleRate:bits:channels) *) -val updating_db: t -> int +val updating_db : t -> int (** Get the job id *) -val error: t -> string +val error : t -> string (** Get the error message if there is one *) diff --git a/lib/Stored_playlists.ml b/lib/Stored_playlists.ml index 40f6630..bed8da1 100644 --- a/lib/Stored_playlists.ml +++ b/lib/Stored_playlists.ml @@ -18,21 +18,24 @@ let listplaylists client = match Client.send_request client "listplaylists" with - | Protocol.Error (_, _ ,_ , message) -> Error message - | Protocol.Ok response_opt -> match response_opt with - | None -> Ok [] - | Some response -> Ok (Utils.read_list_playlists response) + | Protocol.Error (_, _, _, message) -> Error message + | Protocol.Ok response_opt -> ( + match response_opt with + | None -> Ok [] + | Some response -> Ok (Utils.read_list_playlists response)) let load client playlist ?range () = - let request = match range with + let request = + match range with | None -> "load " ^ playlist - | Some (s, e) -> let r = String.concat ":" [string_of_int s; string_of_int e] in - String.concat " " ["load"; playlist; r] + | Some (s, e) -> + let r = String.concat ":" [ string_of_int s; string_of_int e ] in + String.concat " " [ "load"; playlist; r ] in Client.send_request client request let playlistadd client playlist uri = - let request = String.concat " " ["playlistadd"; playlist; uri] in + let request = String.concat " " [ "playlistadd"; playlist; uri ] in Client.send_command client request let playlistclear client playlist = @@ -40,22 +43,20 @@ let playlistclear client playlist = Client.send_command client request let playlistdelete client playlist position = - let request = String.concat " " ["playlistclear"; - playlist; - string_of_int position] in + let request = + String.concat " " [ "playlistclear"; playlist; string_of_int position ] + in Client.send_command client request let playlistmove client playlist from to_dest = - let request = String.concat " " ["playlistmove"; - playlist; - string_of_int from; - string_of_int to_dest] in + let request = + String.concat " " + [ "playlistmove"; playlist; string_of_int from; string_of_int to_dest ] + in Client.send_command client request let rename client playlist new_name = - let request = String.concat " " ["rename"; - playlist; - new_name] in + let request = String.concat " " [ "rename"; playlist; new_name ] in Client.send_command client request let rm client playlist = diff --git a/lib/Stored_playlists.mli b/lib/Stored_playlists.mli index a07441b..9750652 100644 --- a/lib/Stored_playlists.mli +++ b/lib/Stored_playlists.mli @@ -20,40 +20,31 @@ directory. They are addressed with their file name (without the directory and without the .m3u suffix). *) -val listplaylists: - Client.t -> (string list, string) result +val listplaylists : Client.t -> (string list, string) result (** Print a list of the playlist names. *) -val load: - Client.t -> string -> ?range:(int * int) -> unit -> Protocol.response +val load : Client.t -> string -> ?range:int * int -> unit -> Protocol.response (** Load the playlist into the current queue. Playlist plugins are supported. A range may be specified to load only a part of the playlist. *) -val playlistadd: - Client.t -> string -> string -> Protocol.response +val playlistadd : Client.t -> string -> string -> Protocol.response (** Add URI to the playlist NAME.m3u. NAME.m3u will be created if it does not exist. *) -val playlistclear: - Client.t -> string -> Protocol.response +val playlistclear : Client.t -> string -> Protocol.response (** Clear the playlist NAME.m3u. *) -val playlistdelete: - Client.t -> string -> int -> Protocol.response +val playlistdelete : Client.t -> string -> int -> Protocol.response (** Delete SONGPOS from the playlist NAME.m3u. *) -val playlistmove: - Client.t -> string -> int -> int -> Protocol.response +val playlistmove : Client.t -> string -> int -> int -> Protocol.response (** Move the song at position FROM in the playlist NAME.m3u to the position TO. *) -val rename: - Client.t -> string -> string -> Protocol.response +val rename : Client.t -> string -> string -> Protocol.response (** Rename the playlist NAME.m3u to NEW_NAME.m3u. *) -val rm: - Client.t -> string -> Protocol.response +val rm : Client.t -> string -> Protocol.response (** Remove the playlist NAME.m3u from the playlist directory. *) -val save: - Client.t -> string -> Protocol.response +val save : Client.t -> string -> Protocol.response (** Save the current playlist to NAME.m3u in the playlist directory. *) diff --git a/lib/Stored_playlists_lwt.ml b/lib/Stored_playlists_lwt.ml index 5d57ce6..bb82a70 100644 --- a/lib/Stored_playlists_lwt.ml +++ b/lib/Stored_playlists_lwt.ml @@ -19,24 +19,27 @@ open Lwt.Infix let listplaylists client = - Client_lwt.request client "listplaylists" - >>= function - | Protocol.Error (_, _ ,_ , message) -> Lwt.return_error message - | Protocol.Ok (response_opt) -> match response_opt with - | None -> Lwt.return_ok [] - | Some response -> let playlists = Utils.read_list_playlists response in - Lwt.return_ok playlists + Client_lwt.request client "listplaylists" >>= function + | Protocol.Error (_, _, _, message) -> Lwt.return_error message + | Protocol.Ok response_opt -> ( + match response_opt with + | None -> Lwt.return_ok [] + | Some response -> + let playlists = Utils.read_list_playlists response in + Lwt.return_ok playlists) let load client playlist ?range () = - let request = match range with + let request = + match range with | None -> "load " ^ playlist - | Some (s, e) -> let r = String.concat ":" [string_of_int s; string_of_int e] in - String.concat " " ["load"; playlist; r] + | Some (s, e) -> + let r = String.concat ":" [ string_of_int s; string_of_int e ] in + String.concat " " [ "load"; playlist; r ] in Client_lwt.request client request let playlistadd client playlist uri = - let request = String.concat " " ["playlistadd"; playlist; uri] in + let request = String.concat " " [ "playlistadd"; playlist; uri ] in Client_lwt.send client request let playlistclear client playlist = @@ -44,22 +47,20 @@ let playlistclear client playlist = Client_lwt.send client request let playlistdelete client playlist position = - let request = String.concat " " ["playlistclear"; - playlist; - string_of_int position] in + let request = + String.concat " " [ "playlistclear"; playlist; string_of_int position ] + in Client_lwt.send client request let playlistmove client playlist from to_dest = - let request = String.concat " " ["playlistmove"; - playlist; - string_of_int from; - string_of_int to_dest] in + let request = + String.concat " " + [ "playlistmove"; playlist; string_of_int from; string_of_int to_dest ] + in Client_lwt.send client request let rename client playlist new_name = - let request = String.concat " " ["rename"; - playlist; - new_name] in + let request = String.concat " " [ "rename"; playlist; new_name ] in Client_lwt.send client request let rm client playlist = diff --git a/lib/Stored_playlists_lwt.mli b/lib/Stored_playlists_lwt.mli index c17c062..a39ff69 100644 --- a/lib/Stored_playlists_lwt.mli +++ b/lib/Stored_playlists_lwt.mli @@ -20,40 +20,33 @@ directory. They are addressed with their file name (without the directory and without the .m3u suffix). This is module is based on Lwt. *) -val listplaylists: - Client_lwt.t -> (string list, string) result Lwt.t +val listplaylists : Client_lwt.t -> (string list, string) result Lwt.t (** Print a list of the playlist names. *) -val load: - Client_lwt.t -> string -> ?range:(int * int) -> unit -> Protocol.response Lwt.t +val load : + Client_lwt.t -> string -> ?range:int * int -> unit -> Protocol.response Lwt.t (** Load the playlist into the current queue. Playlist plugins are supported. A range may be specified to load only a part of the playlist. *) -val playlistadd: - Client_lwt.t -> string -> string -> Protocol.response Lwt.t +val playlistadd : Client_lwt.t -> string -> string -> Protocol.response Lwt.t (** Add URI to the playlist NAME.m3u. NAME.m3u will be created if it does not exist. *) -val playlistclear: - Client_lwt.t -> string -> Protocol.response Lwt.t +val playlistclear : Client_lwt.t -> string -> Protocol.response Lwt.t (** Clear the playlist NAME.m3u. *) -val playlistdelete: - Client_lwt.t -> string -> int -> Protocol.response Lwt.t +val playlistdelete : Client_lwt.t -> string -> int -> Protocol.response Lwt.t (** Delete SONGPOS from the playlist NAME.m3u. *) -val playlistmove: +val playlistmove : Client_lwt.t -> string -> int -> int -> Protocol.response Lwt.t (** Move the song at position FROM in the playlist NAME.m3u to the position TO. *) -val rename: - Client_lwt.t -> string -> string -> Protocol.response Lwt.t +val rename : Client_lwt.t -> string -> string -> Protocol.response Lwt.t (** Rename the playlist NAME.m3u to NEW_NAME.m3u. *) -val rm: - Client_lwt.t -> string -> Protocol.response Lwt.t +val rm : Client_lwt.t -> string -> Protocol.response Lwt.t (** Remove the playlist NAME.m3u from the playlist directory. *) -val save: - Client_lwt.t -> string -> Protocol.response Lwt.t +val save : Client_lwt.t -> string -> Protocol.response Lwt.t (** Save the current playlist to NAME.m3u in the playlist directory. *) diff --git a/lib/Tags.ml b/lib/Tags.ml index 76982f5..af7e727 100644 --- a/lib/Tags.ml +++ b/lib/Tags.ml @@ -61,5 +61,4 @@ let build_tag_parameter printer tags = let tag_and_param_to_string (t, p) = Printf.sprintf "%s \"%s\"" (printer t) p in - List.map tag_and_param_to_string tags - |> String.concat " " + List.map tag_and_param_to_string tags |> String.concat " " diff --git a/lib/loggin.ml b/lib/loggin.ml index 3964472..e77ff94 100644 --- a/lib/loggin.ml +++ b/lib/loggin.ml @@ -3,8 +3,11 @@ open Lwt.Infix let reporter path = let buf_fmt ~like = let b = Buffer.create 512 in - Fmt.with_buffer ~like b, - fun () -> let m = Buffer.contents b in Buffer.reset b; m + ( Fmt.with_buffer ~like b, + fun () -> + let m = Buffer.contents b in + Buffer.reset b; + m ) in let app, app_flush = buf_fmt ~like:Fmt.stdout in let dst, dst_flush = buf_fmt ~like:Fmt.stderr in @@ -12,42 +15,43 @@ let reporter path = let report src level ~over k msgf = let k () = let write () = - let flags = [Unix.O_WRONLY; Unix.O_CREAT; Unix.O_APPEND] in + let flags = [ Unix.O_WRONLY; Unix.O_CREAT; Unix.O_APPEND ] in let perm = 0o777 in let log_file = path ^ "/libmpdclient.log" in - let err_file = path ^ "/libmpdclient.err" in + let err_file = path ^ "/libmpdclient.err" in Lwt_io.open_file ~flags ~perm ~mode:Lwt_io.Output log_file >>= fun fd_log -> - Lwt_io.open_file ~flags ~perm ~mode:Lwt_io.Output err_file - >>= fun fd_err -> - Lwt.return (fd_log, fd_err) - >>= fun (fd_log', fd_err') -> - match level with - | Logs.App -> Lwt_io.write fd_log' (app_flush ()) - | _ -> Lwt_io.write fd_err' (dst_flush ()) - >>= fun () -> - Lwt_io.close fd_log' - >>= fun () -> - Lwt_io.close fd_err' + Lwt_io.open_file ~flags ~perm ~mode:Lwt_io.Output err_file + >>= fun fd_err -> + Lwt.return (fd_log, fd_err) >>= fun (fd_log', fd_err') -> + match level with + | Logs.App -> Lwt_io.write fd_log' (app_flush ()) + | _ -> + Lwt_io.write fd_err' (dst_flush ()) >>= fun () -> + Lwt_io.close fd_log' >>= fun () -> Lwt_io.close fd_err' + in + let unblock () = + over (); + Lwt.return_unit in - let unblock () = over (); Lwt.return_unit in Lwt.finalize write unblock |> Lwt.ignore_result; k () in - reporter.Logs.report src level ~over:(fun () -> ()) k msgf; + reporter.Logs.report src level ~over:(fun () -> ()) k msgf in - { Logs.report = report } + { Logs.report } -let file_exists f = try ignore (Unix.stat f); true with _ -> false +let file_exists f = + try + ignore (Unix.stat f); + true + with _ -> false let setup () = - let path = "./" in - Logs.set_reporter (reporter path); - Logs.set_level (Some Debug); - Lwt.return_unit - -let debuf message = - Logs_lwt.debug (fun m -> m "%s" message) + let path = "./" in + Logs.set_reporter (reporter path); + Logs.set_level (Some Debug); + Lwt.return_unit -let err message = - Logs_lwt.err (fun m -> m "%s" message) +let debuf message = Logs_lwt.debug (fun m -> m "%s" message) +let err message = Logs_lwt.err (fun m -> m "%s" message) diff --git a/lib/utils.ml b/lib/utils.ml index c8179ed..8825f98 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -21,10 +21,7 @@ (** Remove new line char at the end of a string.*) let remove_trailing_new_line str = let len = String.length str in - if len > 0 && str.[len-1] = '\n' then - String.sub str 0 (len-1) - else - str + if len > 0 && str.[len - 1] = '\n' then String.sub str 0 (len - 1) else str (** Remove all new line characters in a string.*) let remove_new_lines str = @@ -32,8 +29,7 @@ let remove_new_lines str = Str.global_replace (Str.regexp "\n") empty str (** Split multiline string into a list of strings *) -let split_lines strings = - Str.split (Str.regexp "\n") strings +let split_lines strings = Str.split (Str.regexp "\n") strings (** Type that can save the id of an element which can be an int or two int *) type item_id = Simple of int | Num_on_num of int * int @@ -42,39 +38,43 @@ type item_id = Simple of int | Num_on_num of int * int * is used in track and disc tab of the song data *) let num_on_num_parse numbers = let is_simple_number = Str.string_match (Str.regexp "^[0-9]+$") numbers 0 in - let is_num_on_num = Str.string_match (Str.regexp "\\([0-9]+\\)/\\([0-9]+\\)") numbers 0 in + let is_num_on_num = + Str.string_match (Str.regexp "\\([0-9]+\\)/\\([0-9]+\\)") numbers 0 + in if is_simple_number then Simple (int_of_string numbers) else if is_num_on_num then - Num_on_num (int_of_string (Str.matched_group 1 numbers), - int_of_string (Str.matched_group 2 numbers)) - else - Num_on_num (-1, -1) + Num_on_num + ( int_of_string (Str.matched_group 1 numbers), + int_of_string (Str.matched_group 2 numbers) ) + else Num_on_num (-1, -1) +type pair = { key : string; value : string } (** Create a type used when splitting a line which has the form key: value . * This type is used by Mpd.Utils.read_key_val. *) -type pair = { key : string; value : string } (** Split a line with the form "k: v" in the value of type pair *) let read_key_val str = let pattern = Str.regexp "\\(.*\\): \\(.*\\)" in - if Str.string_match pattern str 0 then let k = Str.matched_group 1 str in - let v = Str.matched_group 2 str in {key = k; value = v} - else {key = ""; value = ""} + if Str.string_match pattern str 0 then + let k = Str.matched_group 1 str in + let v = Str.matched_group 2 str in + { key = k; value = v } + else { key = ""; value = "" } (** Returns all the values of a list of strings that have the key/value form. *) let values_of_pairs list_of_pairs = let rec _values pairs acc = match pairs with | [] -> acc - | pair :: remainder -> let {key = _; value = v} = read_key_val pair in _values remainder (v :: acc) - in _values list_of_pairs [] + | pair :: remainder -> + let { key = _; value = v } = read_key_val pair in + _values remainder (v :: acc) + in + _values list_of_pairs [] (** Get a boolean value from a string number. The string "0" is false while all * other string is true. *) -let bool_of_int_str b = - match b with - | "0" -> false - | _ -> true +let bool_of_int_str b = match b with "0" -> false | _ -> true (** Get the file path from the ouput of the command "listplaylist name"*) let read_file_paths data = @@ -83,9 +83,11 @@ let read_file_paths data = let rec get_paths files acc = match files with | [] -> acc - | f :: remainded -> if Str.string_match pattern f 0 - then get_paths remainded ((Str.matched_group 2 f) :: acc) - else get_paths remainded acc in + | f :: remainded -> + if Str.string_match pattern f 0 then + get_paths remainded (Str.matched_group 2 f :: acc) + else get_paths remainded acc + in let paths = get_paths lines [] in List.rev paths @@ -97,11 +99,10 @@ let read_list_playlists data = match lines with | [] -> List.rev acc | item :: remain -> - if Str.string_match pattern item 0 then - let name = Str.matched_group 1 item in - get_playlists remain (name :: acc) - else - get_playlists remain acc + if Str.string_match pattern item 0 then + let name = Str.matched_group 1 item in + get_playlists remain (name :: acc) + else get_playlists remain acc in get_playlists lines [] @@ -110,26 +111,37 @@ exception EMusic_database of string (** Get the count list from the Mpd count command. *) let parse_count_response response group_tag = match group_tag with - | None -> let songs = Str.split (Str.regexp_string "songs:") response in + | None -> + let songs = Str.split (Str.regexp_string "songs:") response in let match_pattern = "\\(.*\\)\nplaytime: *\\(.*\\)\n" in - List.map begin fun s -> - if Str.string_match (Str.regexp match_pattern) s 1 then - (int_of_string (Str.matched_group 1 s), - float_of_string (Str.matched_group 2 s), - "") - else raise (EMusic_database (Printf.sprintf "Count response parsing: empty for %s" match_pattern)) - end songs + List.map + (fun s -> + if Str.string_match (Str.regexp match_pattern) s 1 then + ( int_of_string (Str.matched_group 1 s), + float_of_string (Str.matched_group 2 s), + "" ) + else + raise + (EMusic_database + (Printf.sprintf "Count response parsing: empty for %s" + match_pattern))) + songs | Some grp -> let group_pattern = Printf.sprintf "%s:" (String.capitalize_ascii grp) in let songs = Str.split (Str.regexp_string group_pattern) response in let match_pattern = "\\(.*\\)\nsongs: *\\(.*\\)\nplaytime: *\\(.*\\)\n" in - List.map begin fun s -> - if Str.string_match (Str.regexp match_pattern) s 1 then - (int_of_string (Str.matched_group 2 s), - float_of_string (Str.matched_group 3 s), - Str.matched_group 1 s) - else raise (EMusic_database (Printf.sprintf "Count response parsing: empty for %s" match_pattern)) - end songs + List.map + (fun s -> + if Str.string_match (Str.regexp match_pattern) s 1 then + ( int_of_string (Str.matched_group 2 s), + float_of_string (Str.matched_group 3 s), + Str.matched_group 1 s ) + else + raise + (EMusic_database + (Printf.sprintf "Count response parsing: empty for %s" + match_pattern))) + songs let print_data data = let message = Printf.sprintf "-|%s|-" data in diff --git a/samples/get_mpd_responses.ml b/samples/get_mpd_responses.ml index fefcd7a..192b448 100644 --- a/samples/get_mpd_responses.ml +++ b/samples/get_mpd_responses.ml @@ -23,24 +23,27 @@ let host = "127.0.0.1" let port = 6600 let fd = - let flags = [Open_trunc; Open_append; Open_creat] in + let flags = [ Open_trunc; Open_append; Open_creat ] in let perm = 0o666 in - Stdlib.open_out_gen flags perm "responses" + Stdlib.open_out_gen flags perm "responses" let write_down question response = let _ = Printf.fprintf fd "question -|%s|-\n" question in Printf.fprintf fd "response -|%s|-\n" response -let queries = ["ping"; - "stop"; - "playlist"; - "listplaylists"; - "listplaylist zen"; - "list Artist"; - "list Album artist Nile"; - "list Title artist Nile album Ithyphallic"; - "list Title album Ithyphallic artist Nile"; - "find artist Nile album Ithyphallic";] +let queries = + [ + "ping"; + "stop"; + "playlist"; + "listplaylists"; + "listplaylist zen"; + "list Artist"; + "list Album artist Nile"; + "list Title artist Nile album Ithyphallic"; + "list Title album Ithyphallic artist Nile"; + "find artist Nile album Ithyphallic"; + ] let () = let connection = Mpd.Connection.initialize host port in @@ -49,11 +52,13 @@ let () = let rec loop = function | [] -> Stdlib.close_out fd | q :: t -> - let query = q ^ "\n" in - let _ = Mpd.Connection.write connection query in - let response = Mpd.Connection.read connection (fun s -> Mpd.Protocol.Complete (s, 0)) in - let _ = write_down query response in - loop t + let query = q ^ "\n" in + let _ = Mpd.Connection.write connection query in + let response = + Mpd.Connection.read connection (fun s -> Mpd.Protocol.Complete (s, 0)) + in + let _ = write_down query response in + loop t in let _ = loop queries in Mpd.Connection.close connection diff --git a/samples/mpd_count.ml b/samples/mpd_count.ml index 25eefde..9777c2a 100644 --- a/samples/mpd_count.ml +++ b/samples/mpd_count.ml @@ -27,6 +27,7 @@ let () = match Mpd.Music_database.count client [] ~group:Mpd.Tags.Artist () with | Error message -> print_endline message | Ok count -> - List.iter (fun {songs; playtime; misc} -> - Printf.printf "%d %f %s" songs playtime misc) count - + List.iter + (fun { songs; playtime; misc } -> + Printf.printf "%d %f %s" songs playtime misc) + count diff --git a/samples/mpd_lwt_client_idle.ml b/samples/mpd_lwt_client_idle.ml index 53e6e35..220aeef 100644 --- a/samples/mpd_lwt_client_idle.ml +++ b/samples/mpd_lwt_client_idle.ml @@ -26,36 +26,32 @@ let host = "127.0.0.1" let port = 6600 let on_mpd_event = function - | "mixer" -> print_endline "Mixer related command has been executed"; Lwt.return true - | _ as event_name -> print_endline (("-" ^ event_name) ^ "-"); Lwt.return false + | "mixer" -> + print_endline "Mixer related command has been executed"; + Lwt.return true + | _ as event_name -> + print_endline (("-" ^ event_name) ^ "-"); + Lwt.return false let main_thread = - Lwt.catch - (fun () -> - Mpd.Connection_lwt.initialize host port - >>= fun connection -> - Mpd.Client_lwt.initialize connection - >>= fun client -> - let%lwt banner = Mpd.Client_lwt.mpd_banner client in - Lwt_io.write_line Lwt_io.stdout banner - >>= fun () -> - Mpd.Client_lwt.idle client - >>= function - | Error message -> Mpd.Client_lwt.close client - >>= fun () -> - Lwt_io.write_line Lwt_io.stdout message >|= fun () -> 125 - | Ok event_name -> Lwt_io.write_line Lwt_io.stdout event_name - >>= fun () -> - Mpd.Client_lwt.close client >|= fun () -> 0 - ) - (function - | Mpd.Connection_lwt.Lwt_unix_exn message -> - Lwt_io.write_line Lwt_io.stderr message - >>= fun () -> - Lwt.return 125 - | _ -> - Lwt_io.write_line Lwt_io.stderr "Uncaught exception. Exiting ..." - >>= fun () -> - Lwt.return 125 - ) + Lwt.catch + (fun () -> + Mpd.Connection_lwt.initialize host port >>= fun connection -> + Mpd.Client_lwt.initialize connection >>= fun client -> + let%lwt banner = Mpd.Client_lwt.mpd_banner client in + Lwt_io.write_line Lwt_io.stdout banner >>= fun () -> + Mpd.Client_lwt.idle client >>= function + | Error message -> + Mpd.Client_lwt.close client >>= fun () -> + Lwt_io.write_line Lwt_io.stdout message >|= fun () -> 125 + | Ok event_name -> + Lwt_io.write_line Lwt_io.stdout event_name >>= fun () -> + Mpd.Client_lwt.close client >|= fun () -> 0) + (function + | Mpd.Connection_lwt.Lwt_unix_exn message -> + Lwt_io.write_line Lwt_io.stderr message >>= fun () -> Lwt.return 125 + | _ -> + Lwt_io.write_line Lwt_io.stderr "Uncaught exception. Exiting ..." + >>= fun () -> Lwt.return 125) + let () = exit (Lwt_main.run main_thread) diff --git a/samples/mpd_lwt_client_idle_loop.ml b/samples/mpd_lwt_client_idle_loop.ml index ab14867..6f5b618 100644 --- a/samples/mpd_lwt_client_idle_loop.ml +++ b/samples/mpd_lwt_client_idle_loop.ml @@ -27,33 +27,27 @@ let host = "127.0.0.1" let port = 6600 let on_mpd_event = function - | "mixer" -> print_endline "Mixer related command has been executed"; Lwt.return true - | _ as event_name -> print_endline (("-" ^ event_name) ^ "-"); Lwt.return false + | "mixer" -> + print_endline "Mixer related command has been executed"; + Lwt.return true + | _ as event_name -> + print_endline (("-" ^ event_name) ^ "-"); + Lwt.return false let main_thread = - Lwt.catch - (fun () -> - Mpd.Connection_lwt.initialize host port - >>= fun connection -> - Lwt_io.write_line Lwt_io.stdout "Client on" - >>= fun () -> - Mpd.Client_lwt.initialize connection - >>= fun client -> - let%lwt banner = Mpd.Client_lwt.mpd_banner client in - Lwt_io.write_line Lwt_io.stdout banner - >>= fun () -> - Mpd.Client_lwt.idle_loop client on_mpd_event - >>= fun () -> - Lwt.return 0 - ) - (function - | Mpd.Connection_lwt.Lwt_unix_exn message -> - Lwt_io.write_line Lwt_io.stderr message - >>= fun () -> - Lwt.return 125 - | _ -> - Lwt_io.write_line Lwt_io.stderr "Uncaught exception. Exiting ..." - >>= fun () -> - Lwt.return 125 - ) + Lwt.catch + (fun () -> + Mpd.Connection_lwt.initialize host port >>= fun connection -> + Lwt_io.write_line Lwt_io.stdout "Client on" >>= fun () -> + Mpd.Client_lwt.initialize connection >>= fun client -> + let%lwt banner = Mpd.Client_lwt.mpd_banner client in + Lwt_io.write_line Lwt_io.stdout banner >>= fun () -> + Mpd.Client_lwt.idle_loop client on_mpd_event >>= fun () -> Lwt.return 0) + (function + | Mpd.Connection_lwt.Lwt_unix_exn message -> + Lwt_io.write_line Lwt_io.stderr message >>= fun () -> Lwt.return 125 + | _ -> + Lwt_io.write_line Lwt_io.stderr "Uncaught exception. Exiting ..." + >>= fun () -> Lwt.return 125) + let () = exit (Lwt_main.run main_thread) diff --git a/samples/mpd_lwt_client_idle_noidle.ml b/samples/mpd_lwt_client_idle_noidle.ml index b909f87..5b25aa0 100644 --- a/samples/mpd_lwt_client_idle_noidle.ml +++ b/samples/mpd_lwt_client_idle_noidle.ml @@ -26,57 +26,38 @@ let host = "127.0.0.1" let port = 6600 let main_thread = - Lwt.catch - (fun () -> - Mpd.Connection_lwt.initialize host port - >>= fun connection -> - Mpd.Client_lwt.initialize connection - >>= fun client -> - let%lwt banner = Mpd.Client_lwt.mpd_banner client in - Lwt_io.write_line Lwt_io.stdout banner - >>= fun () -> - let thread1 = begin - Lwt_io.write_line Lwt_io.stdout "Thread one: idle" - >>= fun () -> - Mpd.Client_lwt.idle client - >>= function - | Error message -> - Lwt_io.write_line Lwt_io.stdout message - | Ok event_name -> - Lwt_io.write_line Lwt_io.stdout event_name - end in - let _ = Lwt.on_cancel thread1 (fun () -> - Lwt_io.write_line Lwt_io.stdout "Thread one: canceled" - |> Lwt.ignore_result) in - let thread2 = begin - Lwt_io.write_line Lwt_io.stdout "Thread two: Wait" - >>= fun () -> - Lwt_unix.sleep 5.0 - >>= fun () -> - Lwt_io.write_line Lwt_io.stdout "Thread two: cancel thread one" - >>= fun () -> - Lwt.cancel thread1; - Lwt.return_unit - >>= fun () -> - Lwt_io.write_line Lwt_io.stdout "Thread two: send noidle" - >>= fun () -> - Mpd.Client_lwt.noidle client - >>= fun _ -> - Lwt_io.write_line Lwt_io.stdout "Thread two: noidle sent" - end - in - Lwt.join [ - thread1; - thread2; - ] - >>= fun () -> - Mpd.Client_lwt.close client + Lwt.catch + (fun () -> + Mpd.Connection_lwt.initialize host port >>= fun connection -> + Mpd.Client_lwt.initialize connection >>= fun client -> + let%lwt banner = Mpd.Client_lwt.mpd_banner client in + Lwt_io.write_line Lwt_io.stdout banner >>= fun () -> + let thread1 = + Lwt_io.write_line Lwt_io.stdout "Thread one: idle" >>= fun () -> + Mpd.Client_lwt.idle client >>= function + | Error message -> Lwt_io.write_line Lwt_io.stdout message + | Ok event_name -> Lwt_io.write_line Lwt_io.stdout event_name + in + let _ = + Lwt.on_cancel thread1 (fun () -> + Lwt_io.write_line Lwt_io.stdout "Thread one: canceled" + |> Lwt.ignore_result) + in + let thread2 = + Lwt_io.write_line Lwt_io.stdout "Thread two: Wait" >>= fun () -> + Lwt_unix.sleep 5.0 >>= fun () -> + Lwt_io.write_line Lwt_io.stdout "Thread two: cancel thread one" + >>= fun () -> + Lwt.cancel thread1; + Lwt.return_unit >>= fun () -> + Lwt_io.write_line Lwt_io.stdout "Thread two: send noidle" >>= fun () -> + Mpd.Client_lwt.noidle client >>= fun _ -> + Lwt_io.write_line Lwt_io.stdout "Thread two: noidle sent" + in + Lwt.join [ thread1; thread2 ] >>= fun () -> Mpd.Client_lwt.close client) + (function + | Mpd.Connection_lwt.Lwt_unix_exn message -> + Lwt_io.write_line Lwt_io.stderr message + | _ -> Lwt_io.write_line Lwt_io.stderr "Uncaught exception. Exiting ...") - ) - (function - | Mpd.Connection_lwt.Lwt_unix_exn message -> - Lwt_io.write_line Lwt_io.stderr message - | _ -> - Lwt_io.write_line Lwt_io.stderr "Uncaught exception. Exiting ..." - ) let () = Lwt_main.run main_thread diff --git a/samples/mpd_lwt_count.ml b/samples/mpd_lwt_count.ml index 121e014..c549545 100644 --- a/samples/mpd_lwt_count.ml +++ b/samples/mpd_lwt_count.ml @@ -20,28 +20,22 @@ open Lwt.Infix let host = "127.0.0.1" let port = 6600 - -let lwt_print_line str = - Lwt_io.write_line Lwt_io.stdout str +let lwt_print_line str = Lwt_io.write_line Lwt_io.stdout str open Mpd.Music_database_lwt let main_thread = let open Mpd in - Connection_lwt.initialize host port - >>= fun connection -> - Client_lwt.initialize connection - >>= fun client -> - Music_database_lwt.count client [] ~group:(Tags.Artist) () - >>= function - | Error message -> lwt_print_line message - | Ok count -> lwt_print_line (string_of_int (List.length count)) - >>= fun () -> - Lwt_list.iter_s (fun {songs; playtime; misc} -> - lwt_print_line (Printf.sprintf "%d %f %s" songs playtime misc) - ) count - >>= fun () -> - Client_lwt.close client + Connection_lwt.initialize host port >>= fun connection -> + Client_lwt.initialize connection >>= fun client -> + Music_database_lwt.count client [] ~group:Tags.Artist () >>= function + | Error message -> lwt_print_line message + | Ok count -> + lwt_print_line (string_of_int (List.length count)) >>= fun () -> + Lwt_list.iter_s + (fun { songs; playtime; misc } -> + lwt_print_line (Printf.sprintf "%d %f %s" songs playtime misc)) + count + >>= fun () -> Client_lwt.close client -let () = - Lwt_main.run main_thread +let () = Lwt_main.run main_thread diff --git a/samples/mpd_lwt_ping.ml b/samples/mpd_lwt_ping.ml index ec88121..286af69 100644 --- a/samples/mpd_lwt_ping.ml +++ b/samples/mpd_lwt_ping.ml @@ -20,25 +20,16 @@ open Lwt.Infix let host = "127.0.0.1" let port = 6600 - -let lwt_print_line str = - Lwt_io.write_line Lwt_io.stdout str +let lwt_print_line str = Lwt_io.write_line Lwt_io.stdout str let main_thread = let open Mpd in - Connection_lwt.initialize host port - >>= fun connection -> - Client_lwt.initialize connection - >>= fun client -> - Client_lwt.ping client - >>= function - | Error (_, _, _, message) -> lwt_print_line (Printf.sprintf "No response : %s" message) - | Ok response -> - lwt_print_line begin - match response with - | None -> "Ok" - | Some s -> s - end + Connection_lwt.initialize host port >>= fun connection -> + Client_lwt.initialize connection >>= fun client -> + Client_lwt.ping client >>= function + | Error (_, _, _, message) -> + lwt_print_line (Printf.sprintf "No response : %s" message) + | Ok response -> + lwt_print_line (match response with None -> "Ok" | Some s -> s) -let () = - Lwt_main.run main_thread +let () = Lwt_main.run main_thread diff --git a/samples/mpd_lwt_playlist_info.ml b/samples/mpd_lwt_playlist_info.ml index b4d05c7..8f7cd97 100644 --- a/samples/mpd_lwt_playlist_info.ml +++ b/samples/mpd_lwt_playlist_info.ml @@ -25,33 +25,25 @@ open Lwt.Infix *) let host = "127.0.0.1" let port = 6600 - -let lwt_print_line str = - Lwt_io.write_line Lwt_io.stdout str +let lwt_print_line str = Lwt_io.write_line Lwt_io.stdout str let main_thread = let open Mpd in - Connection_lwt.initialize host port - >>= fun connection -> - Client_lwt.initialize connection - >>= fun client -> - Queue_lwt.playlist client - >>= function - | Queue_lwt.PlaylistError message -> lwt_print_line ("err" ^ message) - | Queue_lwt.Playlist playlist -> - Lwt.return playlist - >>= fun p -> - let n = List.length p in - lwt_print_line ("Number of songs : " ^ (string_of_int n)) - >>= fun () -> - Lwt_list.iter_s (fun song -> - let id = string_of_int (Song.id song) in - let title = Song.title song in - let album = Song.album song in - lwt_print_line (String.concat " " ["\t*"; id; title; album]) - ) p - >>= fun () -> - Client_lwt.close client + Connection_lwt.initialize host port >>= fun connection -> + Client_lwt.initialize connection >>= fun client -> + Queue_lwt.playlist client >>= function + | Queue_lwt.PlaylistError message -> lwt_print_line ("err" ^ message) + | Queue_lwt.Playlist playlist -> + Lwt.return playlist >>= fun p -> + let n = List.length p in + lwt_print_line ("Number of songs : " ^ string_of_int n) >>= fun () -> + Lwt_list.iter_s + (fun song -> + let id = string_of_int (Song.id song) in + let title = Song.title song in + let album = Song.album song in + lwt_print_line (String.concat " " [ "\t*"; id; title; album ])) + p + >>= fun () -> Client_lwt.close client -let () = - Lwt_main.run main_thread +let () = Lwt_main.run main_thread diff --git a/samples/mpd_lwt_send_cmd.ml b/samples/mpd_lwt_send_cmd.ml index c1dd786..1e244b0 100644 --- a/samples/mpd_lwt_send_cmd.ml +++ b/samples/mpd_lwt_send_cmd.ml @@ -20,25 +20,18 @@ open Lwt.Infix let host = "127.0.0.1" let port = 6600 - -let lwt_print_line str = - Lwt_io.write_line Lwt_io.stdout str +let lwt_print_line str = Lwt_io.write_line Lwt_io.stdout str let main_thread = let open Mpd in - Connection_lwt.initialize host port - >>= fun connection -> - Client_lwt.initialize connection - >>= fun client -> - Client_lwt.send client "status" - >>= function - | Ok lines -> begin match lines with - | None -> lwt_print_line "Nothing to print" - | Some s -> lwt_print_line s - end - | Error (_, _, _, message) -> lwt_print_line message - >>= fun () -> - Client_lwt.close client + Connection_lwt.initialize host port >>= fun connection -> + Client_lwt.initialize connection >>= fun client -> + Client_lwt.send client "status" >>= function + | Ok lines -> ( + match lines with + | None -> lwt_print_line "Nothing to print" + | Some s -> lwt_print_line s) + | Error (_, _, _, message) -> + lwt_print_line message >>= fun () -> Client_lwt.close client -let () = - Lwt_main.run main_thread +let () = Lwt_main.run main_thread diff --git a/samples/mpd_lwt_send_ping.ml b/samples/mpd_lwt_send_ping.ml index 6be14df..921f81e 100644 --- a/samples/mpd_lwt_send_ping.ml +++ b/samples/mpd_lwt_send_ping.ml @@ -20,25 +20,17 @@ open Lwt.Infix let host = "127.0.0.1" let port = 6600 - -let lwt_print_line str = - Lwt_io.write_line Lwt_io.stdout str +let lwt_print_line str = Lwt_io.write_line Lwt_io.stdout str let main_thread = let open Mpd in - Connection_lwt.initialize host port - >>= fun connection -> - Connection_lwt.recvbytes connection - >>= fun buf -> - lwt_print_line (Printf.sprintf "received : %s" (Bytes.to_string buf)) - >>= fun _ -> - Connection_lwt.write connection "ping\n" - >>= fun _ -> - Connection_lwt.recvbytes connection - >>= fun buf -> - lwt_print_line (Printf.sprintf "received : %s" (Bytes.to_string buf)) - >>= fun () -> - Connection_lwt.close connection + Connection_lwt.initialize host port >>= fun connection -> + Connection_lwt.recvbytes connection >>= fun buf -> + lwt_print_line (Printf.sprintf "received : %s" (Bytes.to_string buf)) + >>= fun _ -> + Connection_lwt.write connection "ping\n" >>= fun _ -> + Connection_lwt.recvbytes connection >>= fun buf -> + lwt_print_line (Printf.sprintf "received : %s" (Bytes.to_string buf)) + >>= fun () -> Connection_lwt.close connection -let () = - Lwt_main.run main_thread +let () = Lwt_main.run main_thread diff --git a/samples/mpd_lwt_status.ml b/samples/mpd_lwt_status.ml index 5cbfefa..ae81232 100644 --- a/samples/mpd_lwt_status.ml +++ b/samples/mpd_lwt_status.ml @@ -20,24 +20,20 @@ open Lwt.Infix let host = "127.0.0.1" let port = 6600 - -let lwt_print_line str = - Lwt_io.write_line Lwt_io.stdout str +let lwt_print_line str = Lwt_io.write_line Lwt_io.stdout str let main_thread = let open Mpd in - Connection_lwt.initialize host port - >>= fun connection -> - Client_lwt.initialize connection - >>= fun client -> - Client_lwt.status client - >>= function - | Error (message) -> - lwt_print_line (Printf.sprintf "No response : %s" message) - | Ok status -> - let _ = lwt_print_line (Printf.sprintf "volume: %d" (Mpd.Status.volume status)) in - lwt_print_line (Printf.sprintf "state : %s" - (Mpd.Status.state status |> Mpd.Status.string_of_state)) + Connection_lwt.initialize host port >>= fun connection -> + Client_lwt.initialize connection >>= fun client -> + Client_lwt.status client >>= function + | Error message -> lwt_print_line (Printf.sprintf "No response : %s" message) + | Ok status -> + let _ = + lwt_print_line (Printf.sprintf "volume: %d" (Mpd.Status.volume status)) + in + lwt_print_line + (Printf.sprintf "state : %s" + (Mpd.Status.state status |> Mpd.Status.string_of_state)) -let () = - Lwt_main.run main_thread +let () = Lwt_main.run main_thread diff --git a/samples/mpd_playlist_info.ml b/samples/mpd_playlist_info.ml index 13873fa..03063e2 100644 --- a/samples/mpd_playlist_info.ml +++ b/samples/mpd_playlist_info.ml @@ -26,15 +26,18 @@ let host = "127.0.0.1" let port = 6600 let () = - let connection = Mpd.Connection.initialize host port in - let client = Mpd.Client.initialize connection in - match Mpd.Queue.playlist client with - | Mpd.Queue.PlaylistError message -> print_endline message - | Mpd.Queue.Playlist playlist -> let n = List.length playlist in - print_endline ("Number of songs : " ^ (string_of_int n)); - List.iter (fun song -> - let id = string_of_int (Mpd.Song.id song) in - let title = Mpd.Song.title song in - let album = Mpd.Song.album song in - print_endline (String.concat " " ["\t*"; id; title; album])) playlist; - Mpd.Connection.close connection + let connection = Mpd.Connection.initialize host port in + let client = Mpd.Client.initialize connection in + match Mpd.Queue.playlist client with + | Mpd.Queue.PlaylistError message -> print_endline message + | Mpd.Queue.Playlist playlist -> + let n = List.length playlist in + print_endline ("Number of songs : " ^ string_of_int n); + List.iter + (fun song -> + let id = string_of_int (Mpd.Song.id song) in + let title = Mpd.Song.title song in + let album = Mpd.Song.album song in + print_endline (String.concat " " [ "\t*"; id; title; album ])) + playlist; + Mpd.Connection.close connection diff --git a/samples/mpd_status_query.ml b/samples/mpd_status_query.ml index f4d00fd..80fc546 100644 --- a/samples/mpd_status_query.ml +++ b/samples/mpd_status_query.ml @@ -27,12 +27,19 @@ let host = "127.0.0.1" let port = 6600 let () = - let connection = Mpd.Connection.initialize host port in - print_endline ("received: " ^ (Mpd.Connection.read connection (fun s -> Mpd.Protocol.Complete (s, 0)))); - Mpd.Connection.write connection ("status\n"); - let status = Mpd.Connection.read connection (fun s -> Mpd.Protocol.Complete (s, 0)) in - let lines = Mpd.Utils.split_lines status in - let rec display_infos = function - | [] -> Mpd.Connection.close connection - | h :: q -> let _ = print_endline ("*>" ^ h) in display_infos q - in display_infos lines + let connection = Mpd.Connection.initialize host port in + print_endline + ("received: " + ^ Mpd.Connection.read connection (fun s -> Mpd.Protocol.Complete (s, 0))); + Mpd.Connection.write connection "status\n"; + let status = + Mpd.Connection.read connection (fun s -> Mpd.Protocol.Complete (s, 0)) + in + let lines = Mpd.Utils.split_lines status in + let rec display_infos = function + | [] -> Mpd.Connection.close connection + | h :: q -> + let _ = print_endline ("*>" ^ h) in + display_infos q + in + display_infos lines diff --git a/samples/mpd_tagtypes_query.ml b/samples/mpd_tagtypes_query.ml index 26d8d7d..c7a3f13 100644 --- a/samples/mpd_tagtypes_query.ml +++ b/samples/mpd_tagtypes_query.ml @@ -25,7 +25,7 @@ let host = "127.0.0.1" let port = 6600 let () = - let connection = Mpd.Connection.initialize host port in - let client = Mpd.Client.initialize connection in - let tagtypes = Mpd.Client.tagtypes client in - List.iter (fun x -> print_endline ("-*-" ^ x)) tagtypes; + let connection = Mpd.Connection.initialize host port in + let client = Mpd.Client.initialize connection in + let tagtypes = Mpd.Client.tagtypes client in + List.iter (fun x -> print_endline ("-*-" ^ x)) tagtypes diff --git a/samples/mpd_volume_query.ml b/samples/mpd_volume_query.ml index 7e55fa0..f306aaa 100644 --- a/samples/mpd_volume_query.ml +++ b/samples/mpd_volume_query.ml @@ -27,11 +27,12 @@ let host = "127.0.0.1" let port = 6600 let () = - let connection = Mpd.Connection.initialize host port in - let client = Mpd.Client.initialize connection in - print_endline ("banner: " ^ (Mpd.Client.mpd_banner client)); - match Mpd.Client.status client with - | Error message -> print_endline message - | Ok status -> let vol = Mpd.Status.volume status in - print_endline (string_of_int vol); - Mpd.Connection.close connection; + let connection = Mpd.Connection.initialize host port in + let client = Mpd.Client.initialize connection in + print_endline ("banner: " ^ Mpd.Client.mpd_banner client); + match Mpd.Client.status client with + | Error message -> print_endline message + | Ok status -> + let vol = Mpd.Status.volume status in + print_endline (string_of_int vol); + Mpd.Connection.close connection diff --git a/samples/try_mpd_queries.ml b/samples/try_mpd_queries.ml index bbfdcb3..761539a 100644 --- a/samples/try_mpd_queries.ml +++ b/samples/try_mpd_queries.ml @@ -27,8 +27,12 @@ let host = "127.0.0.1" let port = 6600 let () = - let connection = Mpd.Connection.initialize host port in - print_endline ("received: " ^ (Mpd.Connection.read connection (fun s -> Mpd.Protocol.Complete (s, 0)))); - Mpd.Connection.write connection (Sys.argv.(1) ^"\n"); - print_endline ("received: " ^ (Mpd.Connection.read connection (fun s -> Mpd.Protocol.Complete (s, 0)))); - Mpd.Connection.close connection; + let connection = Mpd.Connection.initialize host port in + print_endline + ("received: " + ^ Mpd.Connection.read connection (fun s -> Mpd.Protocol.Complete (s, 0))); + Mpd.Connection.write connection (Sys.argv.(1) ^ "\n"); + print_endline + ("received: " + ^ Mpd.Connection.read connection (fun s -> Mpd.Protocol.Complete (s, 0))); + Mpd.Connection.close connection diff --git a/tests/Test_connection_and_client.ml b/tests/Test_connection_and_client.ml index 65b7ecb..d02e753 100644 --- a/tests/Test_connection_and_client.ml +++ b/tests/Test_connection_and_client.ml @@ -19,7 +19,6 @@ open OUnit2 open Mpd open Test_configuration - module Clt = Mpd.Client module Cnx = Mpd.Connection module TU = Test_utils @@ -34,69 +33,64 @@ let test_connection_initialize _test_ctxt = Cnx.close connection let test_client_send _test_ctxt = - TU.run_test begin fun client -> - match Clt.send_command client "ping" with - | Error _ -> assert_equal ~msg false true - | Ok response_opt -> match response_opt with - | None -> assert_equal true true - | Some _response -> assert_equal ~msg false true - end + TU.run_test (fun client -> + match Clt.send_command client "ping" with + | Error _ -> assert_equal ~msg false true + | Ok response_opt -> ( + match response_opt with + | None -> assert_equal true true + | Some _response -> assert_equal ~msg false true)) let test_client_send_bad_command _test_ctxt = - TU.run_test begin fun client -> - match Clt.send_command client "badcommand" with - | Error (ack_val, ack_cmd_num, ack_cmd, ack_message) -> - let () = assert_equal Protocol.Unknown ack_val in - let () = assert_equal ~printer:string_of_int 0 ack_cmd_num in - let () = assert_equal ~printer "" ack_cmd in - assert_equal ~printer "unknown command \"badcommand\"" ack_message - | Ok _ -> assert_equal ~msg false true - end + TU.run_test (fun client -> + match Clt.send_command client "badcommand" with + | Error (ack_val, ack_cmd_num, ack_cmd, ack_message) -> + let () = assert_equal Protocol.Unknown ack_val in + let () = assert_equal ~printer:string_of_int 0 ack_cmd_num in + let () = assert_equal ~printer "" ack_cmd in + assert_equal ~printer "unknown command \"badcommand\"" ack_message + | Ok _ -> assert_equal ~msg false true) let test_client_banner _test_ctxt = - TU.run_test begin fun client -> - let pattern = "MPD [0-9].[0-9][0-9].[0-9]" in - let banner = Clt.mpd_banner client in - let msg = Printf.sprintf "Banner : %s" banner in - assert_equal true ~msg Str.(string_match (regexp pattern) banner 0) - end + TU.run_test (fun client -> + let pattern = "MPD [0-9].[0-9][0-9].[0-9]" in + let banner = Clt.mpd_banner client in + let msg = Printf.sprintf "Banner : %s" banner in + assert_equal true ~msg Str.(string_match (regexp pattern) banner 0)) let test_client_status _test_ctxt = - TU.run_test begin fun client -> - match Client.status client with - | Error message -> - assert_equal ~printer:(fun _ -> message) true false - | Ok status -> - let state = Mpd.(Status.string_of_state (Status.state status)) in - assert_equal ~printer:(fun s -> s) "stop" state - end + TU.run_test (fun client -> + match Client.status client with + | Error message -> assert_equal ~printer:(fun _ -> message) true false + | Ok status -> + let state = Mpd.(Status.string_of_state (Status.state status)) in + assert_equal ~printer:(fun s -> s) "stop" state) let test_client_ping _test_ctxt = - TU.run_test begin fun client -> - match Clt.ping client with - | Error _ -> assert_equal ~msg false true - | Ok response_opt -> - match response_opt with - | None -> assert_equal true true - | Some _response -> assert_equal ~msg false true - end + TU.run_test (fun client -> + match Clt.ping client with + | Error _ -> assert_equal ~msg false true + | Ok response_opt -> ( + match response_opt with + | None -> assert_equal true true + | Some _response -> assert_equal ~msg false true)) let test_client_tagtypes _test_ctxt = - TU.run_test begin fun client -> - let tagtypes = Clt.tagtypes client in - let () = - assert_equal ~printer:string_of_bool true (List.length tagtypes > 0) in - assert_equal ~printer:string_of_bool true (List.mem "Artist" tagtypes) - end + TU.run_test (fun client -> + let tagtypes = Clt.tagtypes client in + let () = + assert_equal ~printer:string_of_bool true (List.length tagtypes > 0) + in + assert_equal ~printer:string_of_bool true (List.mem "Artist" tagtypes)) let tests = - "Connection and client tests" >::: - [ - "Connection initialize test" >:: test_connection_initialize; - "Client send test" >:: test_client_send; - "Client send bad command" >:: test_client_send_bad_command; - "Client banner test" >:: test_client_banner; - "Client status test" >:: test_client_status; - "Client ping test" >:: test_client_ping; - "Client tagtypes" >:: test_client_tagtypes - ] + "Connection and client tests" + >::: [ + "Connection initialize test" >:: test_connection_initialize; + "Client send test" >:: test_client_send; + "Client send bad command" >:: test_client_send_bad_command; + "Client banner test" >:: test_client_banner; + "Client status test" >:: test_client_status; + "Client ping test" >:: test_client_ping; + "Client tagtypes" >:: test_client_tagtypes; + ] diff --git a/tests/Test_connection_and_client_lwt.ml b/tests/Test_connection_and_client_lwt.ml index 6df6b0a..451bb75 100644 --- a/tests/Test_connection_and_client_lwt.ml +++ b/tests/Test_connection_and_client_lwt.ml @@ -20,91 +20,85 @@ open OUnit2 open Mpd open Lwt open Test_configuration - module Cnx_lwt = Connection_lwt module Clt_lwt = Client_lwt module TU = Test_utils + let printer = TU.printer let init_client () = - Cnx_lwt.initialize host port - >>= fun connection -> + Cnx_lwt.initialize host port >>= fun connection -> Clt_lwt.initialize connection let test_connection_initialize _test_ctxt = - ignore(Lwt_main.run begin - Cnx_lwt.initialize host port - >>= fun connection -> - Cnx_lwt.hostname connection - >>= fun h -> - let () = assert_equal ~printer host h in - Cnx_lwt.port connection - >>= fun p -> - let () = assert_equal ~printer:string_of_int port p in - Cnx_lwt.close connection - end) + ignore + (Lwt_main.run + ( Cnx_lwt.initialize host port >>= fun connection -> + Cnx_lwt.hostname connection >>= fun h -> + let () = assert_equal ~printer host h in + Cnx_lwt.port connection >>= fun p -> + let () = assert_equal ~printer:string_of_int port p in + Cnx_lwt.close connection )) let test_client_send _test_ctxt = - TU.run_test_lwt begin fun client -> - Clt_lwt.send client "ping" - >>= fun response -> - let () = match response with - | Error _ -> - assert_equal ~msg:"This should not has been reached" false true - | Ok response_opt -> match response_opt with - | None -> assert_equal true true - | Some response -> - let msg = Printf.sprintf "response: -%s-" response in - assert_equal ~msg false true - in Lwt.return_unit - end + TU.run_test_lwt (fun client -> + Clt_lwt.send client "ping" >>= fun response -> + let () = + match response with + | Error _ -> + assert_equal ~msg:"This should not has been reached" false true + | Ok response_opt -> ( + match response_opt with + | None -> assert_equal true true + | Some response -> + let msg = Printf.sprintf "response: -%s-" response in + assert_equal ~msg false true) + in + Lwt.return_unit) let test_client_send_bad_command _test_ctxt = - TU.run_test_lwt begin fun client -> - Clt_lwt.send client "badcommand" - >>= fun response -> - let () = match response with - | Error (ack_val, ack_cmd_num, ack_cmd, ack_message) -> - let () = assert_equal Protocol.Unknown ack_val in - let () = assert_equal ~printer:string_of_int 0 ack_cmd_num in - let () = assert_equal ~printer "" ack_cmd in - assert_equal ~printer "unknown command \"badcommand\"" ack_message - | Ok _ -> - assert_equal ~msg:"This should not has been reached" false true - in Lwt.return_unit - end + TU.run_test_lwt (fun client -> + Clt_lwt.send client "badcommand" >>= fun response -> + let () = + match response with + | Error (ack_val, ack_cmd_num, ack_cmd, ack_message) -> + let () = assert_equal Protocol.Unknown ack_val in + let () = assert_equal ~printer:string_of_int 0 ack_cmd_num in + let () = assert_equal ~printer "" ack_cmd in + assert_equal ~printer "unknown command \"badcommand\"" ack_message + | Ok _ -> + assert_equal ~msg:"This should not has been reached" false true + in + Lwt.return_unit) let test_client_banner _test_ctxt = - TU.run_test_lwt begin fun client -> - let pattern = "MPD [0-9].[0-9][0-9].[0-9]" in - Clt_lwt.mpd_banner client - >>= fun banner -> - let msg = Printf.sprintf "Banner : %s" banner in - let () = - assert_equal true ~msg Str.(string_match (regexp pattern) banner 0) - in Lwt.return_unit - end + TU.run_test_lwt (fun client -> + let pattern = "MPD [0-9].[0-9][0-9].[0-9]" in + Clt_lwt.mpd_banner client >>= fun banner -> + let msg = Printf.sprintf "Banner : %s" banner in + let () = + assert_equal true ~msg Str.(string_match (regexp pattern) banner 0) + in + Lwt.return_unit) let test_client_status _test_ctxt = - TU.run_test_lwt begin fun client -> - Clt_lwt.status client - >>= function - | Error _message -> - let printer = fun _ -> "This should not have been reached" in - assert_equal ~printer true false; - Lwt.return_unit - | Ok status -> - let state = Mpd.(Status.string_of_state (Status.state status)) in - assert_equal ~printer:(fun s -> s) "stop" state; - Lwt.return_unit - end + TU.run_test_lwt (fun client -> + Clt_lwt.status client >>= function + | Error _message -> + let printer _ = "This should not have been reached" in + assert_equal ~printer true false; + Lwt.return_unit + | Ok status -> + let state = Mpd.(Status.string_of_state (Status.state status)) in + assert_equal ~printer:(fun s -> s) "stop" state; + Lwt.return_unit) let tests = - "Connection and client lwt tests" >::: - [ - "Connection lwt initialize test" >:: test_connection_initialize; - "Client lwt send" >:: test_client_send; - "Client lwt send" >:: test_client_send_bad_command; - "Client lwt banner" >:: test_client_banner; - "Client lwt status" >:: test_client_status; - ] + "Connection and client lwt tests" + >::: [ + "Connection lwt initialize test" >:: test_connection_initialize; + "Client lwt send" >:: test_client_send; + "Client lwt send" >:: test_client_send_bad_command; + "Client lwt banner" >:: test_client_banner; + "Client lwt status" >:: test_client_status; + ] diff --git a/tests/Test_music_database.ml b/tests/Test_music_database.ml index 924d1ae..e9a6245 100644 --- a/tests/Test_music_database.ml +++ b/tests/Test_music_database.ml @@ -24,94 +24,94 @@ let queue_length = TU.queue_length let test_music_database_find _test_ctxt = let open Mpd.Music_database in - TU.run_test_on_playlist begin fun client -> - match find client [(Mpd_tag Artist, TU.artist)] () with - | Error (_, _, _, error) -> TU.bad_branch error - | Ok songs -> assert_equal 11 (List.length songs) - end + TU.run_test_on_playlist (fun client -> + match find client [ (Mpd_tag Artist, TU.artist) ] () with + | Error (_, _, _, error) -> TU.bad_branch error + | Ok songs -> assert_equal 11 (List.length songs)) let test_music_database_findadd _test_ctxt = let open Mpd.Music_database in - TU.run_test_on_playlist begin fun client -> - match findadd client [(Mpd_tag Artist, TU.artist)] with - | Error (_, _, _, error) -> TU.bad_branch error - | Ok _ -> - let len = queue_length client in - assert_equal ~printer:(fun i -> string_of_int i) 11 len - end + TU.run_test_on_playlist (fun client -> + match findadd client [ (Mpd_tag Artist, TU.artist) ] with + | Error (_, _, _, error) -> TU.bad_branch error + | Ok _ -> + let len = queue_length client in + assert_equal ~printer:(fun i -> string_of_int i) 11 len) let test_music_database_search _test_ctxt = let open Mpd.Music_database in - TU.run_test begin fun client -> - match search client [(Mpd_tag Artist, TU.bad_name_artist)] () with - | Error (_, _, _, error) -> TU.bad_branch error - | Ok songs -> assert_equal 11 (List.length songs) - end + TU.run_test (fun client -> + match search client [ (Mpd_tag Artist, TU.bad_name_artist) ] () with + | Error (_, _, _, error) -> TU.bad_branch error + | Ok songs -> assert_equal 11 (List.length songs)) let test_music_database_searchadd _test_ctxt = let open Mpd.Music_database in - TU.run_test_on_playlist begin fun client -> - match searchadd client [(Mpd_tag Artist, TU.bad_name_artist)] with - | Error (_, _, _, error) -> TU.bad_branch error - | Ok _ -> - let len = queue_length client in - assert_equal ~printer:(fun i -> string_of_int i) 11 len - end + TU.run_test_on_playlist (fun client -> + match searchadd client [ (Mpd_tag Artist, TU.bad_name_artist) ] with + | Error (_, _, _, error) -> TU.bad_branch error + | Ok _ -> + let len = queue_length client in + assert_equal ~printer:(fun i -> string_of_int i) 11 len) let test_music_database_searchaddpl _test_ctxt = let open Mpd.Music_database in - TU.run_test_on_playlist begin fun client -> - let new_playlist = "searchaddpl_new_playlist" in - let get_playlist_number () = - match Mpd.Stored_playlists.listplaylists client with - | Error message -> let () = TU.bad_branch message in -1 - | Ok playlists -> List.length playlists - in - match searchaddpl client new_playlist [(Mpd_tag Artist, TU.bad_name_artist)] with - | Error (_, _, _, error) -> TU.bad_branch error - | Ok _ -> - let () = assert_equal 3 (get_playlist_number ()) in - let () = ignore(Mpd.Stored_playlists.rm client new_playlist) in - assert_equal 2 (get_playlist_number ()) - end + TU.run_test_on_playlist (fun client -> + let new_playlist = "searchaddpl_new_playlist" in + let get_playlist_number () = + match Mpd.Stored_playlists.listplaylists client with + | Error message -> + let () = TU.bad_branch message in + -1 + | Ok playlists -> List.length playlists + in + match + searchaddpl client new_playlist [ (Mpd_tag Artist, TU.bad_name_artist) ] + with + | Error (_, _, _, error) -> TU.bad_branch error + | Ok _ -> + let () = assert_equal 3 (get_playlist_number ()) in + let () = ignore (Mpd.Stored_playlists.rm client new_playlist) in + assert_equal 2 (get_playlist_number ())) let test_music_database_count _test_ctxt = let open Mpd.Music_database in - TU.run_test begin fun client -> - match count client [] ?group:(Some Artist) () with - | Error message -> TU.bad_branch message - | Ok counts -> assert_equal ~printer:string_of_int 1 (List.length counts) - end + TU.run_test (fun client -> + match count client [] ?group:(Some Artist) () with + | Error message -> TU.bad_branch message + | Ok counts -> assert_equal ~printer:string_of_int 1 (List.length counts)) let test_music_database_list_album _test_ctxt = let open Mpd.Music_database in - TU.run_test begin fun client -> - match list client Album [(Artist, TU.artist)] with - | Error message -> TU.bad_branch message - | Ok elements -> - let () = assert_equal ~printer:string_of_int 1 (List.length elements) in - assert_equal ~printer TU.album (List.hd elements) - end + TU.run_test (fun client -> + match list client Album [ (Artist, TU.artist) ] with + | Error message -> TU.bad_branch message + | Ok elements -> + let () = + assert_equal ~printer:string_of_int 1 (List.length elements) + in + assert_equal ~printer TU.album (List.hd elements)) let test_music_database_list_title _test_ctxt = let open Mpd.Music_database in - TU.run_test begin fun client -> - match list client Title [(Artist, TU.artist); (Album, TU.album)] with - | Error message -> TU.bad_branch message - | Ok elements -> - let () = assert_equal ~printer:string_of_int 11 (List.length elements) in - assert (TU.compare TU.songs elements) - end + TU.run_test (fun client -> + match list client Title [ (Artist, TU.artist); (Album, TU.album) ] with + | Error message -> TU.bad_branch message + | Ok elements -> + let () = + assert_equal ~printer:string_of_int 11 (List.length elements) + in + assert (TU.compare TU.songs elements)) let tests = - "Queue and playlists tests" >::: - [ - "test music database find" >:: test_music_database_find; - "test music database findadd" >:: test_music_database_findadd; - "test music database search" >:: test_music_database_search; - "test music database searchadd" >:: test_music_database_searchadd; - "test music database searchaddpl" >:: test_music_database_searchaddpl; - "test music database count" >:: test_music_database_count; - "test music database list album" >:: test_music_database_list_album; - "test music database list title" >:: test_music_database_list_title; - ] + "Queue and playlists tests" + >::: [ + "test music database find" >:: test_music_database_find; + "test music database findadd" >:: test_music_database_findadd; + "test music database search" >:: test_music_database_search; + "test music database searchadd" >:: test_music_database_searchadd; + "test music database searchaddpl" >:: test_music_database_searchaddpl; + "test music database count" >:: test_music_database_count; + "test music database list album" >:: test_music_database_list_album; + "test music database list title" >:: test_music_database_list_title; + ] diff --git a/tests/Test_music_database_lwt.ml b/tests/Test_music_database_lwt.ml index a4dc9c3..7f357fd 100644 --- a/tests/Test_music_database_lwt.ml +++ b/tests/Test_music_database_lwt.ml @@ -26,130 +26,132 @@ let bad_branch = TU.bad_branch let test_music_database_find _test_ctxt = let open Mpd.Music_database_lwt in - TU.run_test_on_playlist_lwt begin fun client -> - find client [(Mpd_tag Artist, TU.artist)] () - >>= fun response -> - let () = match response with - | Error (_, _, _, error) -> bad_branch error - | Ok songs -> assert_equal 11 (List.length songs) - in - Lwt.return_unit - end + TU.run_test_on_playlist_lwt (fun client -> + find client [ (Mpd_tag Artist, TU.artist) ] () >>= fun response -> + let () = + match response with + | Error (_, _, _, error) -> bad_branch error + | Ok songs -> assert_equal 11 (List.length songs) + in + Lwt.return_unit) let test_music_database_findadd _test_ctxt = let open Mpd.Music_database_lwt in - TU.run_test_on_playlist_lwt begin fun client -> - findadd client [(Mpd_tag Artist, TU.artist)] - >>= fun response -> - TU.queue_length_lwt client - >>= fun len -> - let () = match response with - | Error (_, _, _, error) -> bad_branch error - | Ok _ -> - assert_equal ~printer:string_of_int 11 len - in - Lwt.return_unit - end + TU.run_test_on_playlist_lwt (fun client -> + findadd client [ (Mpd_tag Artist, TU.artist) ] >>= fun response -> + TU.queue_length_lwt client >>= fun len -> + let () = + match response with + | Error (_, _, _, error) -> bad_branch error + | Ok _ -> assert_equal ~printer:string_of_int 11 len + in + Lwt.return_unit) let test_music_database_search _test_ctxt = let open Mpd.Music_database_lwt in - TU.run_test_lwt begin fun client -> - search client [(Mpd_tag Artist, TU.bad_name_artist)] () - >>= fun response -> - let () = match response with - | Error (_, _, _, error) -> bad_branch error - | Ok songs -> assert_equal 11 (List.length songs) - in - Lwt.return_unit - end + TU.run_test_lwt (fun client -> + search client [ (Mpd_tag Artist, TU.bad_name_artist) ] () + >>= fun response -> + let () = + match response with + | Error (_, _, _, error) -> bad_branch error + | Ok songs -> assert_equal 11 (List.length songs) + in + Lwt.return_unit) let test_music_database_searchadd _test_ctxt = let open Mpd.Music_database_lwt in - TU.run_test_on_playlist_lwt begin fun client -> - searchadd client [(Mpd_tag Artist, TU.bad_name_artist)] - >>= fun response -> - queue_length_lwt client - >>= fun len -> - let () = match response with - | Error (_, _, _, error) -> bad_branch error - | Ok _ -> - assert_equal ~printer:string_of_int 11 len - in - Lwt.return_unit - end + TU.run_test_on_playlist_lwt (fun client -> + searchadd client [ (Mpd_tag Artist, TU.bad_name_artist) ] + >>= fun response -> + queue_length_lwt client >>= fun len -> + let () = + match response with + | Error (_, _, _, error) -> bad_branch error + | Ok _ -> assert_equal ~printer:string_of_int 11 len + in + Lwt.return_unit) let test_music_database_searchaddpl _test_ctxt = let open Mpd.Music_database_lwt in - TU.run_test_on_playlist_lwt begin fun client -> - let new_playlist = "searchaddpl_new_playlist" in - let get_playlist_number () = - Mpd.Stored_playlists_lwt.listplaylists client + TU.run_test_on_playlist_lwt (fun client -> + let new_playlist = "searchaddpl_new_playlist" in + let get_playlist_number () = + Mpd.Stored_playlists_lwt.listplaylists client >>= function + | Error message -> + let () = bad_branch message in + Lwt.return (-1) + | Ok playlists -> + let len = List.length playlists in + Lwt.return len + in + searchaddpl client new_playlist [ (Mpd_tag Artist, TU.bad_name_artist) ] >>= function - | Error message -> let () = bad_branch message in Lwt.return (-1) - | Ok playlists -> let len = List.length playlists in Lwt.return len - in - searchaddpl client new_playlist [(Mpd_tag Artist, TU.bad_name_artist)] - >>= function - | Error (_, _, _, error) -> let () = bad_branch error in Lwt.return_unit - | Ok _ -> - get_playlist_number () - >>= fun len -> - let () = assert_equal 3 len in - Mpd.Stored_playlists_lwt.rm client new_playlist - >>= fun _ -> - get_playlist_number () - >>= fun len' -> - let () = assert_equal 2 len' in - Lwt.return_unit - end + | Error (_, _, _, error) -> + let () = bad_branch error in + Lwt.return_unit + | Ok _ -> + get_playlist_number () >>= fun len -> + let () = assert_equal 3 len in + Mpd.Stored_playlists_lwt.rm client new_playlist >>= fun _ -> + get_playlist_number () >>= fun len' -> + let () = assert_equal 2 len' in + Lwt.return_unit) let test_music_database_count _test_ctxt = let open Mpd.Music_database_lwt in - TU.run_test_lwt begin fun client -> - count client [] ?group:(Some Artist) () - >>= fun response -> - let () = match response with - | Error message -> bad_branch message - | Ok counts -> assert_equal ~printer:string_of_int 1 (List.length counts) - in - Lwt.return_unit - end + TU.run_test_lwt (fun client -> + count client [] ?group:(Some Artist) () >>= fun response -> + let () = + match response with + | Error message -> bad_branch message + | Ok counts -> + assert_equal ~printer:string_of_int 1 (List.length counts) + in + Lwt.return_unit) let test_music_database_list_album _test_ctxt = let open Mpd in - TU.run_test_lwt begin fun client -> - Music_database_lwt.list client Album [(Artist, TU.artist)] - >>= fun response -> - let () = match response with - | Error message -> bad_branch message - | Ok elements -> - let () = assert_equal ~printer:string_of_int 1 (List.length elements) in - assert_equal ~printer TU.album (List.hd elements) - in Lwt.return_nil - end + TU.run_test_lwt (fun client -> + Music_database_lwt.list client Album [ (Artist, TU.artist) ] + >>= fun response -> + let () = + match response with + | Error message -> bad_branch message + | Ok elements -> + let () = + assert_equal ~printer:string_of_int 1 (List.length elements) + in + assert_equal ~printer TU.album (List.hd elements) + in + Lwt.return_nil) let test_music_database_list_title _test_ctxt = let open Mpd in - TU.run_test_lwt begin fun client -> - Music_database_lwt.list client Title [(Artist, TU.artist); (Album, TU.album)] - >>= fun response -> - let () = match response with - | Error message -> bad_branch message - | Ok elements -> - let () = assert_equal ~printer:string_of_int 11 (List.length elements) in - assert (TU.compare TU.songs elements) - in Lwt.return_nil - end + TU.run_test_lwt (fun client -> + Music_database_lwt.list client Title + [ (Artist, TU.artist); (Album, TU.album) ] + >>= fun response -> + let () = + match response with + | Error message -> bad_branch message + | Ok elements -> + let () = + assert_equal ~printer:string_of_int 11 (List.length elements) + in + assert (TU.compare TU.songs elements) + in + Lwt.return_nil) let tests = - "Queue and playlists lwt tests" >::: - [ - "test music database find" >:: test_music_database_find; - "test music database findadd" >:: test_music_database_findadd; - "test music database search" >:: test_music_database_search; - "test music database searchadd" >:: test_music_database_searchadd; - "test music database searchaddpl" >:: test_music_database_searchaddpl; - "test music database count" >:: test_music_database_count; - "test music database list album" >:: test_music_database_list_album; - "test music database list title" >:: test_music_database_list_title; - ] + "Queue and playlists lwt tests" + >::: [ + "test music database find" >:: test_music_database_find; + "test music database findadd" >:: test_music_database_findadd; + "test music database search" >:: test_music_database_search; + "test music database searchadd" >:: test_music_database_searchadd; + "test music database searchaddpl" >:: test_music_database_searchaddpl; + "test music database count" >:: test_music_database_count; + "test music database list album" >:: test_music_database_list_album; + "test music database list title" >:: test_music_database_list_title; + ] diff --git a/tests/Test_queue_and_playlists.ml b/tests/Test_queue_and_playlists.ml index 5a2708d..77e1cca 100644 --- a/tests/Test_queue_and_playlists.ml +++ b/tests/Test_queue_and_playlists.ml @@ -23,76 +23,75 @@ let printer = TU.printer let queue_length = TU.queue_length let test_stored_playlists_listplaylists _test_ctxt = - TU.run_test_on_playlist begin fun client -> - match Mpd.Stored_playlists.listplaylists client with - | Error message -> TU.bad_branch message - | Ok playlists -> - let () = assert_equal ~printer:string_of_int 2 (List.length playlists) in - let hd = List.hd playlists in - let tail = List.hd (List.tl playlists) in - let test = "bach" = hd || "bach1" = hd in - let () = assert_bool "First playlist" test in - let test' = "bach" = tail || "bach1" = tail in - assert_bool "Last playlist" test' - end + TU.run_test_on_playlist (fun client -> + match Mpd.Stored_playlists.listplaylists client with + | Error message -> TU.bad_branch message + | Ok playlists -> + let () = + assert_equal ~printer:string_of_int 2 (List.length playlists) + in + let hd = List.hd playlists in + let tail = List.hd (List.tl playlists) in + let test = "bach" = hd || "bach1" = hd in + let () = assert_bool "First playlist" test in + let test' = "bach" = tail || "bach1" = tail in + assert_bool "Last playlist" test') let test_stored_playlists_load_playlist_and_clear _test_ctxt = - TU.run_test begin fun client -> - match Mpd.Stored_playlists.load client "bach" () with - | Error (_, _, _, message) -> TU.bad_branch message - | Ok _ -> - let len = queue_length client in - let () = assert_equal ~printer:string_of_int 11 len in - match Mpd.Queue.clear client with + TU.run_test (fun client -> + match Mpd.Stored_playlists.load client "bach" () with | Error (_, _, _, message) -> TU.bad_branch message - | Ok _ -> begin + | Ok _ -> ( let len = queue_length client in - assert_equal ~printer:string_of_int 0 len - end - end + let () = assert_equal ~printer:string_of_int 11 len in + match Mpd.Queue.clear client with + | Error (_, _, _, message) -> TU.bad_branch message + | Ok _ -> + let len = queue_length client in + assert_equal ~printer:string_of_int 0 len)) let test_queue_list _test_ctxt = - TU.run_test_on_playlist begin fun client -> - match Mpd.Stored_playlists.load client "bach" () with - | Error (_, _, _, message) -> TU.bad_branch message - | Ok _ -> - match Mpd.Queue.playlist client with - | PlaylistError message -> TU.bad_branch message - | Playlist songs -> - let song_names = List.map Mpd.Song.title songs in - let same = TU.compare TU.queue song_names in - assert_bool "Songs titles do not match" same - end + TU.run_test_on_playlist (fun client -> + match Mpd.Stored_playlists.load client "bach" () with + | Error (_, _, _, message) -> TU.bad_branch message + | Ok _ -> ( + match Mpd.Queue.playlist client with + | PlaylistError message -> TU.bad_branch message + | Playlist songs -> + let song_names = List.map Mpd.Song.title songs in + let same = TU.compare TU.queue song_names in + assert_bool "Songs titles do not match" same)) let test_queue_playlistid _test_ctxt = - TU.run_test_on_playlist begin fun client -> - match Mpd.Stored_playlists.load client "bach" () with - | Error (_, _, _, message) -> TU.bad_branch message - | Ok _ -> - match Mpd.Queue.playlist client with - | PlaylistError message -> TU.bad_branch message - | Playlist songs -> - let check_song n = - let song = List.nth songs n in - let id = Mpd.Song.id song in - match Mpd.Queue.playlistid client id with - | Error message -> TU.bad_branch message - | Ok song' -> - let title = Mpd.Song.title song in - let title' = Mpd.Song.title song' in - assert_equal ~printer title title' - in - let () = check_song 0 in - let () = check_song 1 in - let () = check_song 5 in - check_song 10 - end + TU.run_test_on_playlist (fun client -> + match Mpd.Stored_playlists.load client "bach" () with + | Error (_, _, _, message) -> TU.bad_branch message + | Ok _ -> ( + match Mpd.Queue.playlist client with + | PlaylistError message -> TU.bad_branch message + | Playlist songs -> + let check_song n = + let song = List.nth songs n in + let id = Mpd.Song.id song in + match Mpd.Queue.playlistid client id with + | Error message -> TU.bad_branch message + | Ok song' -> + let title = Mpd.Song.title song in + let title' = Mpd.Song.title song' in + assert_equal ~printer title title' + in + let () = check_song 0 in + let () = check_song 1 in + let () = check_song 5 in + check_song 10)) let tests = - "Queue and playlists tests" >::: - [ - "test stored playlists listplaylists" >:: test_stored_playlists_listplaylists; - "test stored playlists load playlist and clear" >:: test_stored_playlists_load_playlist_and_clear; - "test queue playlist" >:: test_queue_list; - "test queue playlistid" >:: test_queue_playlistid; - ] + "Queue and playlists tests" + >::: [ + "test stored playlists listplaylists" + >:: test_stored_playlists_listplaylists; + "test stored playlists load playlist and clear" + >:: test_stored_playlists_load_playlist_and_clear; + "test queue playlist" >:: test_queue_list; + "test queue playlistid" >:: test_queue_playlistid; + ] diff --git a/tests/Test_queue_and_playlists_lwt.ml b/tests/Test_queue_and_playlists_lwt.ml index 5650034..d7e111d 100644 --- a/tests/Test_queue_and_playlists_lwt.ml +++ b/tests/Test_queue_and_playlists_lwt.ml @@ -24,100 +24,98 @@ let printer = TU.printer let queue_length_lwt = TU.queue_length_lwt let test_stored_playlists_listplaylists _test_ctxt = - TU.run_test_on_playlist_lwt begin fun client -> - Mpd.Stored_playlists_lwt.listplaylists client - >>= fun response -> - let () = match response with - | Error message -> - assert_equal ~printer "This should not have been reached" message - | Ok playlists -> - let () = assert_equal ~printer:string_of_int 2 (List.length playlists) in - let hd = List.hd playlists in - let tail = List.hd (List.tl playlists) in - let test = "bach" = hd || "bach1" = hd in - let () = assert_bool "First playlist" test in - let test' = "bach" = tail || "bach1" = tail in - assert_bool "Last playlist" test' - in Lwt.return_unit - end + TU.run_test_on_playlist_lwt (fun client -> + Mpd.Stored_playlists_lwt.listplaylists client >>= fun response -> + let () = + match response with + | Error message -> + assert_equal ~printer "This should not have been reached" message + | Ok playlists -> + let () = + assert_equal ~printer:string_of_int 2 (List.length playlists) + in + let hd = List.hd playlists in + let tail = List.hd (List.tl playlists) in + let test = "bach" = hd || "bach1" = hd in + let () = assert_bool "First playlist" test in + let test' = "bach" = tail || "bach1" = tail in + assert_bool "Last playlist" test' + in + Lwt.return_unit) let test_stored_playlists_load_playlist_and_clear _test_ctxt = - TU.run_test_lwt begin fun client -> - Mpd.Stored_playlists_lwt.load client "bach" () - >>= function - | Error (_, _, _, message) -> - assert_equal ~printer "This should not have been reached " message; - Lwt.return_unit - | Ok _ -> - queue_length_lwt client - >>= fun len -> - let () = assert_equal ~printer:string_of_int 11 len in - Mpd.Queue_lwt.clear client - >>= function + TU.run_test_lwt (fun client -> + Mpd.Stored_playlists_lwt.load client "bach" () >>= function | Error (_, _, _, message) -> - assert_equal ~printer "This should not have been reached " message; - Lwt.return_unit - | Ok _ -> begin - queue_length_lwt client - >>= fun len -> - assert_equal ~printer:string_of_int 0 len; + assert_equal ~printer "This should not have been reached " message; Lwt.return_unit - end - end + | Ok _ -> ( + queue_length_lwt client >>= fun len -> + let () = assert_equal ~printer:string_of_int 11 len in + Mpd.Queue_lwt.clear client >>= function + | Error (_, _, _, message) -> + assert_equal ~printer "This should not have been reached " message; + Lwt.return_unit + | Ok _ -> + queue_length_lwt client >>= fun len -> + assert_equal ~printer:string_of_int 0 len; + Lwt.return_unit)) let test_queue_list _test_ctxt = - TU.run_test_on_playlist_lwt begin fun client -> - Mpd.Stored_playlists_lwt.load client "bach" () - >>= fun response -> - match response with - | Error (_, _, _, message) -> TU.bad_branch message; Lwt.return_unit - | Ok _ -> - Mpd.Queue_lwt.playlist client - >>= fun response -> + TU.run_test_on_playlist_lwt (fun client -> + Mpd.Stored_playlists_lwt.load client "bach" () >>= fun response -> match response with - | PlaylistError message -> TU.bad_branch message; Lwt.return_unit - | Playlist songs -> - let song_names = List.map Mpd.Song.title songs in - let same = TU.compare TU.queue song_names in - let () = assert_bool "Songs titles do not match" same - in - Lwt.return_unit - end + | Error (_, _, _, message) -> + TU.bad_branch message; + Lwt.return_unit + | Ok _ -> ( + Mpd.Queue_lwt.playlist client >>= fun response -> + match response with + | PlaylistError message -> + TU.bad_branch message; + Lwt.return_unit + | Playlist songs -> + let song_names = List.map Mpd.Song.title songs in + let same = TU.compare TU.queue song_names in + let () = assert_bool "Songs titles do not match" same in + Lwt.return_unit)) let test_queue_playlistid _test_ctxt = - TU.run_test_on_playlist_lwt begin fun client -> - Mpd.Stored_playlists_lwt.load client "bach" () - >>= function - | Error (_, _, _, message) -> TU.bad_branch message; Lwt.return_unit - | Ok _ -> - Mpd.Queue_lwt.playlist client - >>= function - | PlaylistError message -> TU.bad_branch message; Lwt.return_unit - | Playlist songs -> - let check_song n = - let song = List.nth songs n in - let id = Mpd.Song.id song in - Mpd.Queue_lwt.playlistid client id - >>= function - | Error message -> TU.bad_branch message; Lwt.return_unit - | Ok song' -> - let title = Mpd.Song.title song in - let title' = Mpd.Song.title song' in - assert_equal ~printer title title'; - Lwt.return_unit - in - check_song 0 - >>= fun () -> check_song 1 - >>= fun () -> check_song 5 - >>= fun () -> check_song 10 - end - + TU.run_test_on_playlist_lwt (fun client -> + Mpd.Stored_playlists_lwt.load client "bach" () >>= function + | Error (_, _, _, message) -> + TU.bad_branch message; + Lwt.return_unit + | Ok _ -> ( + Mpd.Queue_lwt.playlist client >>= function + | PlaylistError message -> + TU.bad_branch message; + Lwt.return_unit + | Playlist songs -> + let check_song n = + let song = List.nth songs n in + let id = Mpd.Song.id song in + Mpd.Queue_lwt.playlistid client id >>= function + | Error message -> + TU.bad_branch message; + Lwt.return_unit + | Ok song' -> + let title = Mpd.Song.title song in + let title' = Mpd.Song.title song' in + assert_equal ~printer title title'; + Lwt.return_unit + in + check_song 0 >>= fun () -> + check_song 1 >>= fun () -> + check_song 5 >>= fun () -> check_song 10)) let tests = - "Queue and playlists lwt tests" >::: - [ - "test stored playlists listplaylists" >:: test_stored_playlists_listplaylists; - "test stored playlists load playlist and clear" >:: test_stored_playlists_load_playlist_and_clear; - "test queue playlist" >:: test_queue_list; - "test queue playlistid" >:: test_queue_playlistid; - ] + "Queue and playlists lwt tests" + >::: [ + "test stored playlists listplaylists" + >:: test_stored_playlists_listplaylists; + "test stored playlists load playlist and clear" + >:: test_stored_playlists_load_playlist_and_clear; + "test queue playlist" >:: test_queue_list; + "test queue playlistid" >:: test_queue_playlistid; + ] diff --git a/tests/Test_regexp_uses.ml b/tests/Test_regexp_uses.ml index b4ee965..5bcdbee 100644 --- a/tests/Test_regexp_uses.ml +++ b/tests/Test_regexp_uses.ml @@ -29,75 +29,70 @@ let test_protocol_parse_response_simple_ok _test_ctxt = let test_protocol_parse_response_request_ok _test_ctxt = let complex_response = "test: this is a complex\nresponse: request\nOK\n" in - match Protocol.parse_response complex_response with - | Error _ -> bad_branch () - | Ok response -> match response with - | None -> bad_branch () - | Some s -> + match Protocol.parse_response complex_response with + | Error _ -> bad_branch () + | Ok response -> ( + match response with + | None -> bad_branch () + | Some s -> let expected = "test: this is a complex\nresponse: request\n" in - assert_equal ~printer:(fun s -> s) expected s + assert_equal ~printer:(fun s -> s) expected s) let test_protocol_parse_response_error_50 _test_ctxt = match Protocol.parse_response "ACK [50@1] {play} error while playing\n" with | Ok _ -> bad_branch () | Error (er_val, cmd_num, cmd, message) -> - assert ( - er_val = No_exist && cmd_num = 1 && - cmd = "play" && message = "error while playing" - ) + assert ( + er_val = No_exist && cmd_num = 1 && cmd = "play" + && message = "error while playing") let test_protocol_parse_response_error_1 _test_ctxt = match Protocol.parse_response "ACK [1@12] {play} error while playing\n" with | Ok _ -> bad_branch () | Error (er_val, cmd_num, cmd, message) -> - assert ( - er_val = Not_list && cmd_num = 12 && - cmd = "play" && message = "error while playing" - ) + assert ( + er_val = Not_list && cmd_num = 12 && cmd = "play" + && message = "error while playing") open Utils let test_num_on_num_parse_simple_int _test_ctxt = let simple_int = "3" in match Utils.num_on_num_parse simple_int with - | Utils.Simple n -> assert_equal 3 n - ~msg:"Simple int value" - ~printer:string_of_int + | Utils.Simple n -> + assert_equal 3 n ~msg:"Simple int value" ~printer:string_of_int | _ -> assert_equal false true let test_num_on_num_parse_num_on_num _test_ctxt = let simple_int = "3/10" in match Utils.num_on_num_parse simple_int with - | Utils.Num_on_num (a, b) -> assert_equal 3 a - ~msg:"Simple int value" - ~printer:string_of_int; - assert_equal 10 b - ~msg:"Simple int value" - ~printer:string_of_int - + | Utils.Num_on_num (a, b) -> + assert_equal 3 a ~msg:"Simple int value" ~printer:string_of_int; + assert_equal 10 b ~msg:"Simple int value" ~printer:string_of_int | _ -> assert_equal false true let test_read_key_val _test_ctxt = let key_val = "mykey: myvalue" in - let {key = k; value = v} = Utils.read_key_val key_val in + let { key = k; value = v } = Utils.read_key_val key_val in assert_equal "mykey" k; assert_equal "myvalue" v -let song = "file: Bjork-Volta/11 Earth Intruders (Mark Stent Exten.m4a -Last-Modified: 2009-09-21T14:25:52Z -Artist: Björk -Album: Volta -Title: Earth Intruders (Mark Stent Extended Mix) -Track: 11/13 -Genre: Alternative -Date: 2007 -Composer: Björk -Disc: 1/1 -AlbumArtist: Björk -Time: 266 -duration: 266.472 -Pos: 10 -Id: 11" +let song = + "file: Bjork-Volta/11 Earth Intruders (Mark Stent Exten.m4a\n\ + Last-Modified: 2009-09-21T14:25:52Z\n\ + Artist: Björk\n\ + Album: Volta\n\ + Title: Earth Intruders (Mark Stent Extended Mix)\n\ + Track: 11/13\n\ + Genre: Alternative\n\ + Date: 2007\n\ + Composer: Björk\n\ + Disc: 1/1\n\ + AlbumArtist: Björk\n\ + Time: 266\n\ + duration: 266.472\n\ + Pos: 10\n\ + Id: 11" let test_song_parse _test_ctxt = let song = Song.parse (Utils.split_lines song) in @@ -115,169 +110,174 @@ let test_song_parse _test_ctxt = assert_equal 266.472 (Song.duration song); assert_equal 11 (Song.id song) -let playlist_info_list_data = "file: Wardruna-Runaljod-Yggdrasil-2013/01. Rotlaust Tre Fell_[plixid.com].mp3 -file: jod/02. F.mp3 -file: jod/03. N.mp3 -file: jod/04. E.mp3 -file: jod/05. A.mp3 -file: jod/06. I.mp3 -file: jod/07. I.mp3" +let playlist_info_list_data = + "file: Wardruna-Runaljod-Yggdrasil-2013/01. Rotlaust Tre Fell_[plixid.com].mp3\n\ + file: jod/02. F.mp3\n\ + file: jod/03. N.mp3\n\ + file: jod/04. E.mp3\n\ + file: jod/05. A.mp3\n\ + file: jod/06. I.mp3\n\ + file: jod/07. I.mp3" let test_list_playlist_response_parse _test_ctxt = let paths = Utils.read_file_paths playlist_info_list_data in let second = List.nth paths 1 in - assert_equal ~printer:(fun s -> - s) - "jod/02. F.mp3" second + assert_equal ~printer:(fun s -> s) "jod/02. F.mp3" second let listplaylists_data = - "playlist: zen -Last-Modified: 2014-12-02T10:15:57Z -playlist: rtl -Last-Modified: 2014-12-02T10:15:57Z -" + "playlist: zen\n\ + Last-Modified: 2014-12-02T10:15:57Z\n\ + playlist: rtl\n\ + Last-Modified: 2014-12-02T10:15:57Z\n" let test_listplaylists_response_parse _test_ctxt = let playlist_names = Utils.read_list_playlists listplaylists_data in - assert_equal ~printer:(fun s -> s) "zen rtl" (String.concat " " playlist_names) + assert_equal + ~printer:(fun s -> s) + "zen rtl" + (String.concat " " playlist_names) let count_group_artist = - "Artist: jedi mind tricks -songs: 18 -playtime: 4002 -Artist: woven hand -songs: 11 -playtime: 2491 -" + "Artist: jedi mind tricks\n\ + songs: 18\n\ + playtime: 4002\n\ + Artist: woven hand\n\ + songs: 11\n\ + playtime: 2491\n" + +let count_artist_woven_hand = "songs: 11\nplaytime: 2491\n" -let count_artist_woven_hand = - "songs: 11 -playtime: 2491 -" let test_music_database_count_parse_group_artist _test_ctxt = try let count = Utils.parse_count_response count_group_artist (Some "artist") in let _ = assert_equal 2 (List.length count) in let fst = List.nth count 0 in let scd = List.nth count 1 in - let (songs, time, misc) = fst in + let songs, time, misc = fst in let _ = assert_equal 18 songs in let _ = assert_equal 4002. time in let _ = assert_equal ~printer:(fun s -> s) "jedi mind tricks" misc in - let (songs, time, misc) = scd in + let songs, time, misc = scd in let _ = assert_equal 11 songs in let _ = assert_equal 2491. time in assert_equal ~printer:(fun s -> s) "woven hand" misc - - with Utils.EMusic_database message -> assert_equal ~printer:(fun s -> s) "" message + with Utils.EMusic_database message -> + assert_equal ~printer:(fun s -> s) "" message let test_music_database_count_parse_artist_woven_hand _test_ctxt = try let count = Utils.parse_count_response count_artist_woven_hand None in let _ = assert_equal 1 (List.length count) in let fst = List.nth count 0 in - let (songs, time, misc) = fst in + let songs, time, misc = fst in let _ = assert_equal 11 songs in let _ = assert_equal 2491. time in assert_equal ~printer:(fun s -> s) "" misc - - with Utils.EMusic_database message -> assert_equal ~printer:(fun s -> s) "" message + with Utils.EMusic_database message -> + assert_equal ~printer:(fun s -> s) "" message let test_connection_lwt_mpd_banner_regex _test_ctxt = let data = "OK MPD 1.23.4\n" in let pattern = "OK \\(.*\\)\n" in match Str.string_match (Str.regexp pattern) data 0 with | false -> assert_equal ~msg:"No banner found" true false - | true -> let result = Str.matched_group 1 data in - let _ = assert_equal ~printer:(fun s -> s) "MPD 1.23.4" result in - assert_equal ~msg:"Non used char" - ~printer:string_of_int - 4 String.((length data) - (length result)) + | true -> + let result = Str.matched_group 1 data in + let _ = assert_equal ~printer:(fun s -> s) "MPD 1.23.4" result in + assert_equal ~msg:"Non used char" ~printer:string_of_int 4 + String.(length data - length result) let test_connection_lwt_request_response_regex _test_ctxt = let data = "this is a test\nOK\n" in let pattern = "\\(\\(\n\\|.\\)*OK\n\\)" in match Str.string_match (Str.regexp pattern) data 0 with | false -> assert_equal ~msg:"Bad pattern for request response" true false - | true -> let result = Str.matched_group 1 data in - let () = assert_equal ~printer:(fun s -> s) "this is a test\nOK\n" result in - assert_equal ~msg:"Non used char" - ~printer:string_of_int - 0 String.((length data) - (length result)) + | true -> + let result = Str.matched_group 1 data in + let () = + assert_equal ~printer:(fun s -> s) "this is a test\nOK\n" result + in + assert_equal ~msg:"Non used char" ~printer:string_of_int 0 + String.(length data - length result) let test_connection_lwt_command_response_regex _test_ctxt = let data = "OK\ntototata\n" in let pattern = "^\\(OK\n\\)\\(\n\\|.\\)*" in match Str.string_match (Str.regexp pattern) data 0 with | false -> assert_equal ~msg:"Bad pattern for command response" true false - | true -> let result = Str.matched_group 1 data in - let () = assert_equal ~printer:(fun s -> s) "OK\n" result in - assert_equal ~msg:"Non used char" - ~printer:string_of_int - 9 String.((length data) - (length result)) + | true -> + let result = Str.matched_group 1 data in + let () = assert_equal ~printer:(fun s -> s) "OK\n" result in + assert_equal ~msg:"Non used char" ~printer:string_of_int 9 + String.(length data - length result) let test_connection_lwt_command_response_regex_1 _test_ctxt = let data = "OK\n" in let pattern = "^\\(OK\n\\)\\(\n\\|.\\)*" in match Str.string_match (Str.regexp pattern) data 0 with | false -> assert_equal ~msg:"Bad pattern for command response" true false - | true -> let result = Str.matched_group 1 data in - let () = assert_equal ~printer:(fun s -> s) "OK\n" result in - assert_equal ~msg:"Non used char" - ~printer:string_of_int - 0 String.((length data) - (length result)) + | true -> + let result = Str.matched_group 1 data in + let () = assert_equal ~printer:(fun s -> s) "OK\n" result in + assert_equal ~msg:"Non used char" ~printer:string_of_int 0 + String.(length data - length result) let test_connection_lwt_full_mpd_idle_event _test_ctxt = let data = "changed: mixerOK\n" in let pattern = "changed: \\(\\(\n\\|.\\)*\\)OK\n" in match Str.string_match (Str.regexp pattern) data 0 with | false -> assert_equal ~msg:"Bad pattern for idle event" true false - | true -> let result = Str.matched_group 1 data in - let _ = assert_equal ~printer:(fun s -> s) "mixer" result in - assert_equal ~msg:"Non used char" - ~printer:string_of_int - 12 String.((length data) - (length result)) + | true -> + let result = Str.matched_group 1 data in + let _ = assert_equal ~printer:(fun s -> s) "mixer" result in + assert_equal ~msg:"Non used char" ~printer:string_of_int 12 + String.(length data - length result) let test_remove_trailing_new_line _test_ctxt = let str1 = "a string with \n" in let str1' = "a string with " in let str2 = "a normal string" in - let _ = assert_equal ~printer:(fun s -> s) str1' (Utils.remove_trailing_new_line str1) in + let _ = + assert_equal + ~printer:(fun s -> s) + str1' + (Utils.remove_trailing_new_line str1) + in assert_equal ~printer:(fun s -> s) str2 (Utils.remove_trailing_new_line str2) let tests = - "Mpd responses parsing tests" >::: - ["test protocol parse response simple OK" >:: - test_protocol_parse_response_simple_ok; - "test protocol parse response request OK" >:: - test_protocol_parse_response_request_ok; - "test protocol parse response error 50" >:: - test_protocol_parse_response_error_50; - "test prototol parse response error 1" >:: - test_protocol_parse_response_error_1; - "test Mpd.utils.num_on_num_parse simple int" >:: - test_num_on_num_parse_simple_int; - "test Mpd.utils.num_on_num_parse num_on_num" >:: - test_num_on_num_parse_num_on_num; - "test Mpd.utils.read_key_value" >:: test_read_key_val; - "test Mpd.Song.parse" >:: test_song_parse; - "test Utils.read_file_path" >:: test_list_playlist_response_parse; - "test Mpd.utils.read_list_playlists" >:: - test_listplaylists_response_parse; - "test Mpd.utils.parse_count_response" >:: - test_music_database_count_parse_group_artist; - "test Mpd.utils.parse_count_response" >:: - test_music_database_count_parse_artist_woven_hand; - "test connection lwt mpd banner regex" >:: - test_connection_lwt_mpd_banner_regex; - "test connection lwt request response regex" >:: - test_connection_lwt_request_response_regex; - "test connection lwt command response regex" >:: - test_connection_lwt_command_response_regex; - "test connection lwt command response regex 1" >:: - test_connection_lwt_command_response_regex_1; - "test connection lwt full mpd idle event" >:: - test_connection_lwt_full_mpd_idle_event; - "test remove trailing new line" >:: - test_remove_trailing_new_line; - ] + "Mpd responses parsing tests" + >::: [ + "test protocol parse response simple OK" + >:: test_protocol_parse_response_simple_ok; + "test protocol parse response request OK" + >:: test_protocol_parse_response_request_ok; + "test protocol parse response error 50" + >:: test_protocol_parse_response_error_50; + "test prototol parse response error 1" + >:: test_protocol_parse_response_error_1; + "test Mpd.utils.num_on_num_parse simple int" + >:: test_num_on_num_parse_simple_int; + "test Mpd.utils.num_on_num_parse num_on_num" + >:: test_num_on_num_parse_num_on_num; + "test Mpd.utils.read_key_value" >:: test_read_key_val; + "test Mpd.Song.parse" >:: test_song_parse; + "test Utils.read_file_path" >:: test_list_playlist_response_parse; + "test Mpd.utils.read_list_playlists" + >:: test_listplaylists_response_parse; + "test Mpd.utils.parse_count_response" + >:: test_music_database_count_parse_group_artist; + "test Mpd.utils.parse_count_response" + >:: test_music_database_count_parse_artist_woven_hand; + "test connection lwt mpd banner regex" + >:: test_connection_lwt_mpd_banner_regex; + "test connection lwt request response regex" + >:: test_connection_lwt_request_response_regex; + "test connection lwt command response regex" + >:: test_connection_lwt_command_response_regex; + "test connection lwt command response regex 1" + >:: test_connection_lwt_command_response_regex_1; + "test connection lwt full mpd idle event" + >:: test_connection_lwt_full_mpd_idle_event; + "test remove trailing new line" >:: test_remove_trailing_new_line; + ] diff --git a/tests/Test_utils.ml b/tests/Test_utils.ml index 7d5cd16..2dc9c65 100644 --- a/tests/Test_utils.ml +++ b/tests/Test_utils.ml @@ -1,24 +1,23 @@ open OUnit open Lwt.Infix - open Test_configuration -let printer = fun s -> s +let printer s = s let init_client () = let connection = Mpd.Connection.initialize host port in let client = Mpd.Client.initialize connection in - let () = match Mpd.Music_database.update client None with + let () = + match Mpd.Music_database.update client None with | Error (_, _, _, message) -> - let information = "Error when updating database " in - assert_equal ~printer information message + let information = "Error when updating database " in + assert_equal ~printer information message | Ok _ -> () in client let init_client_lwt () = - Mpd.Connection_lwt.initialize host port - >>= fun connection -> + Mpd.Connection_lwt.initialize host port >>= fun connection -> Mpd.Client_lwt.initialize connection let queue_length client = @@ -27,25 +26,20 @@ let queue_length client = | Mpd.Queue.Playlist p -> List.length p let queue_length_lwt client = - Mpd.Queue_lwt.playlist client - >>= function + Mpd.Queue_lwt.playlist client >>= function | Mpd.Queue_lwt.PlaylistError _ -> Lwt.return (-1) | Mpd.Queue_lwt.Playlist p -> Lwt.return (List.length p) let ensure_playlist_is_loaded client = - if queue_length client <= 0 then begin + if queue_length client <= 0 then match Mpd.Stored_playlists.load client "bach" () with | Error (_, _, _, message) -> - let information = "Error when loading playlist" in - assert_equal ~printer information message + let information = "Error when loading playlist" in + assert_equal ~printer information message | Ok _ -> () - end - -let ensure_playback_is_stopped client = - ignore(Mpd.Playback.stop client) -let ensure_playlist_is_cleared client = - ignore(Mpd.Queue.clear client) +let ensure_playback_is_stopped client = ignore (Mpd.Playback.stop client) +let ensure_playlist_is_cleared client = ignore (Mpd.Queue.clear client) let run_test f = let client = init_client () in @@ -53,36 +47,29 @@ let run_test f = Mpd.Client.close client let run_test_lwt f = - ignore(Lwt_main.run begin - init_client_lwt () - >>= fun client -> - f client - >>= fun _ -> - Mpd.Client_lwt.close client - end) + ignore + (Lwt_main.run + ( init_client_lwt () >>= fun client -> + f client >>= fun _ -> Mpd.Client_lwt.close client )) let run_test_on_playlist f = - run_test begin fun client -> - let () = f client in - ensure_playlist_is_cleared client - end + run_test (fun client -> + let () = f client in + ensure_playlist_is_cleared client) let run_test_on_playlist_lwt f = - run_test_lwt begin fun client -> - f client - >>= fun _ -> - Mpd.Queue_lwt.clear client - end + run_test_lwt (fun client -> f client >>= fun _ -> Mpd.Queue_lwt.clear client) let assert_state client s test_name = match Mpd.Client.status client with | Error message -> - assert_equal ~printer:(fun s -> test_name ^ s) - "Unable to get status" message + assert_equal + ~printer:(fun s -> test_name ^ s) + "Unable to get status" message | Ok status -> - assert_equal ~printer:(fun s -> - test_name ^ (Mpd.Status.string_of_state s) - ) s (Mpd.Status.state status) + assert_equal + ~printer:(fun s -> test_name ^ Mpd.Status.string_of_state s) + s (Mpd.Status.state status) let assert_state_w_delay _client s test_name = let () = Unix.sleep 2 in @@ -90,51 +77,50 @@ let assert_state_w_delay _client s test_name = let check_state client s = match Mpd.Client.status client with - | Error _message -> - false - | Ok status -> - s == Mpd.Status.state status + | Error _message -> false + | Ok status -> s == Mpd.Status.state status let bad_branch error = assert_equal ~printer "This should not have been reached " error let artist = "Bach JS" - let bad_name_artist = "bACH js" - let album = "Die Kunst der Fuge, BWV 1080, for Piano" (* List of songs returned by Music_database.list *) -let songs =[ - "Contrapunctus 1"; - "Contrapunctus 10 a 4 alla Decima"; - "Contrapunctus 11 a 4"; - "Contrapunctus 2"; - "Contrapunctus 3"; - "Contrapunctus 4"; - "Contrapunctus 5"; - "Contrapunctus 6 a 4 in Stylo Francese"; - "Contrapunctus 7 a 4 per Augmentationem et Diminutionem"; - "Contrapunctus 8 a 3"; - "Contrapunctus 9 a 4 alla Duodecima"; -] +let songs = + [ + "Contrapunctus 1"; + "Contrapunctus 10 a 4 alla Decima"; + "Contrapunctus 11 a 4"; + "Contrapunctus 2"; + "Contrapunctus 3"; + "Contrapunctus 4"; + "Contrapunctus 5"; + "Contrapunctus 6 a 4 in Stylo Francese"; + "Contrapunctus 7 a 4 per Augmentationem et Diminutionem"; + "Contrapunctus 8 a 3"; + "Contrapunctus 9 a 4 alla Duodecima"; + ] (* List of songs when the Basch playlist is loaded. *) -let queue =[ - "Contrapunctus 1"; - "Contrapunctus 2"; - "Contrapunctus 3"; - "Contrapunctus 4"; - "Contrapunctus 5"; - "Contrapunctus 6 a 4 in Stylo Francese"; - "Contrapunctus 7 a 4 per Augmentationem et Diminutionem"; - "Contrapunctus 8 a 3"; - "Contrapunctus 9 a 4 alla Duodecima"; - "Contrapunctus 10 a 4 alla Decima"; - "Contrapunctus 11 a 4"; -] - -let rec compare l1 l2 = match l1, l2 with +let queue = + [ + "Contrapunctus 1"; + "Contrapunctus 2"; + "Contrapunctus 3"; + "Contrapunctus 4"; + "Contrapunctus 5"; + "Contrapunctus 6 a 4 in Stylo Francese"; + "Contrapunctus 7 a 4 per Augmentationem et Diminutionem"; + "Contrapunctus 8 a 3"; + "Contrapunctus 9 a 4 alla Duodecima"; + "Contrapunctus 10 a 4 alla Decima"; + "Contrapunctus 11 a 4"; + ] + +let rec compare l1 l2 = + match (l1, l2) with | [], [] -> true | [], _ -> false | _, [] -> false diff --git a/tests/test.ml b/tests/test.ml index 605d3f8..fe108cc 100644 --- a/tests/test.ml +++ b/tests/test.ml @@ -20,15 +20,13 @@ open OUnit2 let () = run_test_tt_main - ( - "Mpd client library tests" >::: - [ - Test_regexp_uses.tests; - Test_connection_and_client.tests; - Test_queue_and_playlists.tests; - Test_music_database.tests; - Test_connection_and_client_lwt.tests; - Test_queue_and_playlists_lwt.tests; - Test_music_database_lwt.tests; - ] -) + ("Mpd client library tests" + >::: [ + Test_regexp_uses.tests; + Test_connection_and_client.tests; + Test_queue_and_playlists.tests; + Test_music_database.tests; + Test_connection_and_client_lwt.tests; + Test_queue_and_playlists_lwt.tests; + Test_music_database_lwt.tests; + ]) From e608dc13aca1ab8f92524e39469615a7f5ffb879 Mon Sep 17 00:00:00 2001 From: Yuriy Shirokov Date: Fri, 23 Jun 2023 02:35:39 +0400 Subject: [PATCH 3/4] .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..88f9974 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +_build/* From 974980d5c91313352a25eb293ecd22d41f82d59f Mon Sep 17 00:00:00 2001 From: Yuriy Shirokov Date: Fri, 23 Jun 2023 02:41:41 +0400 Subject: [PATCH 4/4] Makefile fixed --- Makefile | 2 +- docs/Mpd/{.dune-keep => .dummy} | 0 docs/Mpd/Client/index.html | 2 +- docs/Mpd/Client_lwt/index.html | 2 +- docs/Mpd/Connection/index.html | 2 +- docs/Mpd/Connection_lwt/index.html | 2 +- docs/Mpd/Loggin/index.html | 2 +- docs/Mpd/Music_database/index.html | 30 +- docs/Mpd/Music_database_lwt/index.html | 33 +- docs/Mpd/Playback/index.html | 2 +- docs/Mpd/Playback_lwt/index.html | 2 +- docs/Mpd/Playback_options/index.html | 2 +- docs/Mpd/Playback_options_lwt/index.html | 2 +- docs/Mpd/Protocol/index.html | 2 +- docs/Mpd/Queue/index.html | 13 +- docs/Mpd/Queue_lwt/index.html | 27 +- docs/Mpd/Song/index.html | 2 +- docs/Mpd/Status/index.html | 2 +- docs/Mpd/Stored_playlists/index.html | 7 +- docs/Mpd/Stored_playlists_lwt/index.html | 12 +- docs/Mpd/Tags/index.html | 2 +- docs/Mpd/Utils/index.html | 5 +- docs/Mpd/index.html | 2 +- docs/Mpd__Client/.dune-keep | 0 docs/Mpd__Client/index.html | 2 - docs/Mpd__Client_lwt/.dune-keep | 0 docs/Mpd__Client_lwt/index.html | 2 - docs/Mpd__Connection/.dune-keep | 0 docs/Mpd__Connection/index.html | 2 - docs/Mpd__Connection_lwt/.dune-keep | 0 docs/Mpd__Connection_lwt/index.html | 2 - docs/Mpd__Loggin/.dune-keep | 0 docs/Mpd__Loggin/index.html | 2 - docs/Mpd__Music_database/.dune-keep | 0 docs/Mpd__Music_database/index.html | 2 - docs/Mpd__Music_database_lwt/.dune-keep | 0 docs/Mpd__Music_database_lwt/index.html | 2 - docs/Mpd__Playback/.dune-keep | 0 docs/Mpd__Playback/index.html | 2 - docs/Mpd__Playback_lwt/.dune-keep | 0 docs/Mpd__Playback_lwt/index.html | 2 - docs/Mpd__Playback_options/.dune-keep | 0 docs/Mpd__Playback_options/index.html | 2 - docs/Mpd__Playback_options_lwt/.dune-keep | 0 docs/Mpd__Playback_options_lwt/index.html | 2 - docs/Mpd__Protocol/.dune-keep | 0 docs/Mpd__Protocol/index.html | 2 - docs/Mpd__Queue/.dune-keep | 0 docs/Mpd__Queue/index.html | 2 - docs/Mpd__Queue_lwt/.dune-keep | 0 docs/Mpd__Queue_lwt/index.html | 2 - docs/Mpd__Song/.dune-keep | 0 docs/Mpd__Song/index.html | 2 - docs/Mpd__Status/.dune-keep | 0 docs/Mpd__Status/index.html | 2 - docs/Mpd__Stored_playlists/.dune-keep | 0 docs/Mpd__Stored_playlists/index.html | 2 - docs/Mpd__Stored_playlists_lwt/.dune-keep | 0 docs/Mpd__Stored_playlists_lwt/index.html | 2 - docs/Mpd__Tags/.dune-keep | 0 docs/Mpd__Tags/index.html | 2 - docs/Mpd__Utils/.dune-keep | 0 docs/Mpd__Utils/index.html | 2 - docs/index.html | 2 +- docs/odoc.css | 507 ++++++++++++---------- 65 files changed, 403 insertions(+), 303 deletions(-) rename docs/Mpd/{.dune-keep => .dummy} (100%) delete mode 100644 docs/Mpd__Client/.dune-keep delete mode 100644 docs/Mpd__Client/index.html delete mode 100644 docs/Mpd__Client_lwt/.dune-keep delete mode 100644 docs/Mpd__Client_lwt/index.html delete mode 100644 docs/Mpd__Connection/.dune-keep delete mode 100644 docs/Mpd__Connection/index.html delete mode 100644 docs/Mpd__Connection_lwt/.dune-keep delete mode 100644 docs/Mpd__Connection_lwt/index.html delete mode 100644 docs/Mpd__Loggin/.dune-keep delete mode 100644 docs/Mpd__Loggin/index.html delete mode 100644 docs/Mpd__Music_database/.dune-keep delete mode 100644 docs/Mpd__Music_database/index.html delete mode 100644 docs/Mpd__Music_database_lwt/.dune-keep delete mode 100644 docs/Mpd__Music_database_lwt/index.html delete mode 100644 docs/Mpd__Playback/.dune-keep delete mode 100644 docs/Mpd__Playback/index.html delete mode 100644 docs/Mpd__Playback_lwt/.dune-keep delete mode 100644 docs/Mpd__Playback_lwt/index.html delete mode 100644 docs/Mpd__Playback_options/.dune-keep delete mode 100644 docs/Mpd__Playback_options/index.html delete mode 100644 docs/Mpd__Playback_options_lwt/.dune-keep delete mode 100644 docs/Mpd__Playback_options_lwt/index.html delete mode 100644 docs/Mpd__Protocol/.dune-keep delete mode 100644 docs/Mpd__Protocol/index.html delete mode 100644 docs/Mpd__Queue/.dune-keep delete mode 100644 docs/Mpd__Queue/index.html delete mode 100644 docs/Mpd__Queue_lwt/.dune-keep delete mode 100644 docs/Mpd__Queue_lwt/index.html delete mode 100644 docs/Mpd__Song/.dune-keep delete mode 100644 docs/Mpd__Song/index.html delete mode 100644 docs/Mpd__Status/.dune-keep delete mode 100644 docs/Mpd__Status/index.html delete mode 100644 docs/Mpd__Stored_playlists/.dune-keep delete mode 100644 docs/Mpd__Stored_playlists/index.html delete mode 100644 docs/Mpd__Stored_playlists_lwt/.dune-keep delete mode 100644 docs/Mpd__Stored_playlists_lwt/index.html delete mode 100644 docs/Mpd__Tags/.dune-keep delete mode 100644 docs/Mpd__Tags/index.html delete mode 100644 docs/Mpd__Utils/.dune-keep delete mode 100644 docs/Mpd__Utils/index.html diff --git a/Makefile b/Makefile index 52bf522..59ce3a0 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ documentation : dune build @doc find _build/default/_doc/_html/libmpdclient/ -type f |xargs sed -i 's/\.\.\/odoc\.css/odoc\.css/g' - mv _build/default/_doc/_html/odoc.css _build/default/_doc/_html/libmpdclient/ + mv _build/default/_doc/_html/odoc.support/odoc.css _build/default/_doc/_html/libmpdclient/ rm -rf docs/* cp -rf _build/default/_doc/_html/libmpdclient/* docs/ dune clean diff --git a/docs/Mpd/.dune-keep b/docs/Mpd/.dummy similarity index 100% rename from docs/Mpd/.dune-keep rename to docs/Mpd/.dummy diff --git a/docs/Mpd/Client/index.html b/docs/Mpd/Client/index.html index aaff6f4..0df5de3 100644 --- a/docs/Mpd/Client/index.html +++ b/docs/Mpd/Client/index.html @@ -1,2 +1,2 @@ -Client (libmpdclient.Mpd.Client)

Module Mpd.Client

type t

Client type

val initialize : Connection.t -> t

Initialize the client with a connection.

val send_request : t -> string -> Protocol.response
val send_command : t -> string -> Protocol.response
val mpd_banner : t -> string

Return the mpd banner that the server send at the first connection of the client.

val status : t -> (Status.t, string) Stdlib.result

Create a status request and returns the status under a Mpd.Status.t type if no error occurs.

val ping : t -> Protocol.response

Does nothing but return "OK".

val password : t -> string -> Protocol.response

This is used for authentication with the server. PASSWORD is simply the plaintext password.

val close : t -> unit

Close the connection to MPD. MPD will try to send the remaining output buffer before it actually closes the connection, but that cannot be guaranteed. This command will not generate a response. This function is a wrapper to the "close" command of the Mpd protocol, this means that it first send the "close" command and it close the connection at the socket level.

val tagtypes : t -> string list

Show a list of available tag types. It is an intersection of the metadata_to_use setting and this client's tag mask. About the tag mask: each client can decide to disable any number of tag types, which will be omitted from responses to this client. That is a good idea, because it makes responses smaller. The following tagtypes sub commands configure this list.

\ No newline at end of file +Client (libmpdclient.Mpd.Client)

Module Mpd.Client

Provides functions and type in order to communicate to the mpd server with commands and requests.

type t

Client type

val initialize : Connection.t -> t

Initialize the client with a connection.

val send: t -> string -> Protocol.response Send to the mpd server a command or a request. The response of the server is returned under the form of a Protocol.response type.

val send_request : t -> string -> Protocol.response
val send_command : t -> string -> Protocol.response
val mpd_banner : t -> string

Return the mpd banner that the server send at the first connection of the client.

val status : t -> (Status.t, string) Stdlib.result

Create a status request and returns the status under a Mpd.Status.t type if no error occurs.

val ping : t -> Protocol.response

Does nothing but return "OK".

val password : t -> string -> Protocol.response

This is used for authentication with the server. PASSWORD is simply the plaintext password.

val close : t -> unit

Close the connection to MPD. MPD will try to send the remaining output buffer before it actually closes the connection, but that cannot be guaranteed. This command will not generate a response. This function is a wrapper to the "close" command of the Mpd protocol, this means that it first send the "close" command and it close the connection at the socket level.

val tagtypes : t -> string list

Show a list of available tag types. It is an intersection of the metadata_to_use setting and this client's tag mask. About the tag mask: each client can decide to disable any number of tag types, which will be omitted from responses to this client. That is a good idea, because it makes responses smaller. The following tagtypes sub commands configure this list.

\ No newline at end of file diff --git a/docs/Mpd/Client_lwt/index.html b/docs/Mpd/Client_lwt/index.html index 696b664..b143ed7 100644 --- a/docs/Mpd/Client_lwt/index.html +++ b/docs/Mpd/Client_lwt/index.html @@ -1,2 +1,2 @@ -Client_lwt (libmpdclient.Mpd.Client_lwt)

Module Mpd.Client_lwt

type t

Type for a Mpd Client to be used with Lwt promises.

val initialize : Connection_lwt.t -> t Lwt.t

Initialize the client with a connection.

val mpd_banner : t -> string Lwt.t

Return the mpd banner that the server send at the first connection of the client.

val idle : t -> (string, string) Stdlib.Pervasives.result Lwt.t

Wait for an event to occur in order to return. When a Client send this * command to the Mpd server throught its connection, the Mpd server do * not answer to any other command except the noidle command. The idea is * to first cancel the promise that has send the "idle" command with * Lwt.cancel and then send the noidle command to the Mpd server. An * example can be found in samples/mpd_lwt_client_idle_noidle.ml.

val idle_loop : t -> (string -> bool Lwt.t) -> unit Lwt.t

Loop on mpd event with the "idle" command the on_event function take the event response as argument and return true to stop or false to continue the loop

val send : t -> string -> Protocol.response Lwt.t

Send to the mpd server a command. The response of the server is returned under the form of a Protocol.response type.

val request : t -> string -> Protocol.response Lwt.t

Send to the mpd server a request. The response of the server is returned under the form of a Protocol.response type. A request is different from a command because a command generate an action from Mpd and returns "OK" or an error while a request does not generate an action from Mpd and returns "some data to analyse"OK or an error.

val status : t -> (Status.t, string) Stdlib.Pervasives.result Lwt.t

Create a status request and returns the status under a Mpd.Status.s Lwt.t type.

val ping : t -> Protocol.response Lwt.t

Does nothing but return "OK".

val password : t -> string -> Protocol.response Lwt.t

This is used for authentication with the server. PASSWORD is simply the plaintext password.

val noidle : t -> Protocol.response Lwt.t

This command is needed to stop listening after a Client.idle command. An example of usage can be seen in samples/mpd_lwt_client_idle_noidle.exe.

val close : t -> unit Lwt.t

Close the client. MPD will try to send the remaining output buffer before it actually closes the connection, but that cannot be guaranteed. This command will not generate a response. This function is a wrapper to the "close" command of the Mpd protocol, this means that it first send the "close" command and it close the connection at the socket level.

\ No newline at end of file +Client_lwt (libmpdclient.Mpd.Client_lwt)

Module Mpd.Client_lwt

Provides functions and type in order to communicate to the mpd server with commands and requests in Lwt threads.

type t

Type for a Mpd Client to be used with Lwt promises.

val initialize : Connection_lwt.t -> t Lwt.t

Initialize the client with a connection.

val mpd_banner : t -> string Lwt.t

Return the mpd banner that the server send at the first connection of the client.

val idle : t -> (string, string) Stdlib.result Lwt.t

Wait for an event to occur in order to return. When a Client send this * command to the Mpd server throught its connection, the Mpd server do * not answer to any other command except the noidle command. The idea is * to first cancel the promise that has send the "idle" command with * Lwt.cancel and then send the noidle command to the Mpd server. An * example can be found in samples/mpd_lwt_client_idle_noidle.ml.

val idle_loop : t -> (string -> bool Lwt.t) -> unit Lwt.t

Loop on mpd event with the "idle" command the on_event function take the event response as argument and return true to stop or false to continue the loop

val send : t -> string -> Protocol.response Lwt.t

Send to the mpd server a command. The response of the server is returned under the form of a Protocol.response type.

val request : t -> string -> Protocol.response Lwt.t

Send to the mpd server a request. The response of the server is returned under the form of a Protocol.response type. A request is different from a command because a command generate an action from Mpd and returns "OK" or an error while a request does not generate an action from Mpd and returns "some data to analyse"OK or an error.

val status : t -> (Status.t, string) Stdlib.result Lwt.t

Create a status request and returns the status under a Mpd.Status.s Lwt.t type.

val ping : t -> Protocol.response Lwt.t

Does nothing but return "OK".

val password : t -> string -> Protocol.response Lwt.t

This is used for authentication with the server. PASSWORD is simply the plaintext password.

val noidle : t -> Protocol.response Lwt.t

This command is needed to stop listening after a Client.idle command. An example of usage can be seen in samples/mpd_lwt_client_idle_noidle.exe.

val close : t -> unit Lwt.t

Close the client. MPD will try to send the remaining output buffer before it actually closes the connection, but that cannot be guaranteed. This command will not generate a response. This function is a wrapper to the "close" command of the Mpd protocol, this means that it first send the "close" command and it close the connection at the socket level.

\ No newline at end of file diff --git a/docs/Mpd/Connection/index.html b/docs/Mpd/Connection/index.html index dec248d..50750b0 100644 --- a/docs/Mpd/Connection/index.html +++ b/docs/Mpd/Connection/index.html @@ -1,2 +1,2 @@ -Connection (libmpdclient.Mpd.Connection)

Module Mpd.Connection

type t

connection type

val initialize : string -> int -> t

Create the connection, exit if the connection can not be initialized.

val hostname : t -> string

Retrieve the host's string of the initialized connection.

val port : t -> int

Retrieve the port of the connection of the initialized connection.

val close : t -> unit

Close the connection

val write : t -> string -> unit

Write to an Mpd connection

val read_mpd_banner : t -> string

Read in an Mpd connection

val read_request_response : t -> string

Read a Mpd response to a request.

val read_command_response : t -> string

Read a Mpd response to a command.

\ No newline at end of file +Connection (libmpdclient.Mpd.Connection)

Module Mpd.Connection

Offer functions and type in order to handle connections to the mpd server at the socket level.

type t

connection type

val initialize : string -> int -> t

Create the connection, exit if the connection can not be initialized.

val hostname : t -> string

Retrieve the host's string of the initialized connection.

val port : t -> int

Retrieve the port of the connection of the initialized connection.

val close : t -> unit

Close the connection

val write : t -> string -> unit

Write to an Mpd connection

val read : t -> (string -> Protocol.mpd_response) -> string

Read in an Mpd connection

val read_mpd_banner : t -> string

Read in an Mpd connection

val read_request_response : t -> string

Read a Mpd response to a request.

val read_command_response : t -> string

Read a Mpd response to a command.

\ No newline at end of file diff --git a/docs/Mpd/Connection_lwt/index.html b/docs/Mpd/Connection_lwt/index.html index 19c64d6..c02a5fc 100644 --- a/docs/Mpd/Connection_lwt/index.html +++ b/docs/Mpd/Connection_lwt/index.html @@ -1,2 +1,2 @@ -Connection_lwt (libmpdclient.Mpd.Connection_lwt)

Module Mpd.Connection_lwt

type t

Lwt connection type for thread usage

exception Lwt_unix_exn of string

Custom exception.

val initialize : string -> int -> t Lwt.t

Create the connection in a Lwt thread, throws an exception Mpd_Lwt_unix_exn of string when an error occurs.

val hostname : t -> string Lwt.t

Get the hostname of the current connection.

val port : t -> int Lwt.t

Get the port of the current connection.

val buffer : t -> string Lwt.t

Get the buffer used by the connection.

val recvbytes : t -> Stdlib.Bytes.t Lwt.t

Read from the connection.

val write : t -> string -> int Lwt.t

Write in a Mpd connection throught a Lwt thread. It fails with an exception Mpd_Lwt_unix_exn of string.

val close : t -> unit Lwt.t

Close the connection.

\ No newline at end of file +Connection_lwt (libmpdclient.Mpd.Connection_lwt)

Module Mpd.Connection_lwt

Offer functions and type in order to handle connections to the mpd server at the socket level in Lwt thread.

type t

Lwt connection type for thread usage

exception Lwt_unix_exn of string

Custom exception.

val initialize : string -> int -> t Lwt.t

Create the connection in a Lwt thread, throws an exception Mpd_Lwt_unix_exn of string when an error occurs.

val hostname : t -> string Lwt.t

Get the hostname of the current connection.

val port : t -> int Lwt.t

Get the port of the current connection.

val buffer : t -> string Lwt.t

Get the buffer used by the connection.

val recvbytes : t -> Stdlib.Bytes.t Lwt.t

Read from the connection.

val write : t -> string -> int Lwt.t

Write in a Mpd connection throught a Lwt thread. It fails with an exception Mpd_Lwt_unix_exn of string.

val close : t -> unit Lwt.t

Close the connection.

\ No newline at end of file diff --git a/docs/Mpd/Loggin/index.html b/docs/Mpd/Loggin/index.html index 61e31e0..3a999d2 100644 --- a/docs/Mpd/Loggin/index.html +++ b/docs/Mpd/Loggin/index.html @@ -1,2 +1,2 @@ -Loggin (libmpdclient.Mpd.Loggin)

Module Mpd.Loggin

val reporter : string -> Logs.reporter
val file_exists : string -> bool
val setup : unit -> unit Lwt.t
val debuf : string -> unit Lwt.t
val err : string -> unit Lwt.t
\ No newline at end of file +Loggin (libmpdclient.Mpd.Loggin)

Module Mpd.Loggin

val reporter : string -> Logs.reporter
val file_exists : string -> bool
val setup : unit -> unit Lwt.t
val debuf : string -> unit Lwt.t
val err : string -> unit Lwt.t
\ No newline at end of file diff --git a/docs/Mpd/Music_database/index.html b/docs/Mpd/Music_database/index.html index 5da3825..a98b088 100644 --- a/docs/Mpd/Music_database/index.html +++ b/docs/Mpd/Music_database/index.html @@ -1,2 +1,30 @@ -Music_database (libmpdclient.Mpd.Music_database)

Module Mpd.Music_database

val find : Client.t -> (Tags.search_tags * string) list -> ?⁠sort:Tags.t -> ?⁠window:(int * int) -> unit -> (Song.t list, Protocol.ack_error * int * string * string) Stdlib.result

Find songs in the db that match exactly the a list of pairs (tag, exact_pattern). The exact_pattern is a string and the tah can be any tag supported by MPD, or one of the special parameters:

  • any checks all tag values
  • file checks the full path (relative to the music directory)
  • base restricts the search to songs in the given directory (also relative to the music directory)
  • modified-since compares the file's time stamp with the given value (ISO 8601 or UNIX time stamp)
val findadd : Client.t -> (Tags.search_tags * string) list -> Protocol.response

Find songs in the db that and adds them to current playlist. Parameters have the same meaning as for find.

Search for any song that contains WHAT. Parameters have the same meaning as for find, except that search is not case sensitive.

val searchadd : Client.t -> (Tags.search_tags * string) list -> Protocol.response

Search for any song that contains WHAT in tag TYPE and adds them to current playlist. Parameters have the same meaning as for findadd, except that search is not case sensitive.

val searchaddpl : Client.t -> string -> (Tags.search_tags * string) list -> Protocol.response

Search for any song that contains WHAT in tag TYPE and adds them to the playlist named NAME. If a playlist by that name doesn't exist it is created. Parameters have the same meaning as for find, except that search is not case sensitive.

type song_count = {
songs : int;
playtime : float;
misc : string;
}

basic type for the response of the count command.

val count : Client.t -> (Tags.t * string) list -> ?⁠group:Tags.t -> unit -> (song_count list, string) Stdlib.result

Get a count of songs with filters. For examples: count group artist will return for each artist the number of sons, the total playtime and the name of the artist in misc. Counts the number of songs and their total playtime in the db matching TAG exactly. The group keyword may be used to group the results by a tag. The following prints per-artist counts: count group artist count genre metal date 2016 group artist

val list : Client.t -> Tags.t -> (Tags.t * string) list -> (string list, string) Stdlib.result

Get a list based on some filer. For example "list album artist "Elvis Presley"" will return a list of the album names of Elvis Presley that exists in the music database.

val update : Client.t -> string option -> Protocol.response

Updates the music database: find new files, remove deleted files, update modified files. URI is a particular directory or song/file to update. If you do not specify it, everything is updated. Prints "updating_db: JOBID" where JOBID is a positive number identifying the update job. You can read the current job id in the status response.

val rescan : Client.t -> string option -> Protocol.response

Same as update, but also rescans unmodified files.

\ No newline at end of file +Music_database (libmpdclient.Mpd.Music_database)

Module Mpd.Music_database

Music_database module: regroups data base related commands.

val find : + Client.t -> + (Tags.search_tags * string) list -> + ?sort:Tags.t -> + ?window:(int * int) -> + unit -> + (Song.t list, Protocol.ack_error * int * string * string) Stdlib.result

Find songs in the db that match exactly the a list of pairs (tag, exact_pattern). The exact_pattern is a string and the tah can be any tag supported by MPD, or one of the special parameters:

  • any checks all tag values
  • file checks the full path (relative to the music directory)
  • base restricts the search to songs in the given directory (also relative to the music directory)
  • modified-since compares the file's time stamp with the given value (ISO 8601 or UNIX time stamp)
val findadd : Client.t -> (Tags.search_tags * string) list -> Protocol.response

Find songs in the db that and adds them to current playlist. Parameters have the same meaning as for find.

Search for any song that contains WHAT. Parameters have the same meaning as for find, except that search is not case sensitive.

val searchadd : + Client.t -> + (Tags.search_tags * string) list -> + Protocol.response

Search for any song that contains WHAT in tag TYPE and adds them to current playlist. Parameters have the same meaning as for findadd, except that search is not case sensitive.

val searchaddpl : + Client.t -> + string -> + (Tags.search_tags * string) list -> + Protocol.response

Search for any song that contains WHAT in tag TYPE and adds them to the playlist named NAME. If a playlist by that name doesn't exist it is created. Parameters have the same meaning as for find, except that search is not case sensitive.

type song_count = {
  1. songs : int;
  2. playtime : float;
  3. misc : string;
}

basic type for the response of the count command.

val count : + Client.t -> + (Tags.t * string) list -> + ?group:Tags.t -> + unit -> + (song_count list, string) Stdlib.result

Get a count of songs with filters. For examples: count group artist will return for each artist the number of sons, the total playtime and the name of the artist in misc. Counts the number of songs and their total playtime in the db matching TAG exactly. The group keyword may be used to group the results by a tag. The following prints per-artist counts: count group artist count genre metal date 2016 group artist

val list : + Client.t -> + Tags.t -> + (Tags.t * string) list -> + (string list, string) Stdlib.result

Get a list based on some filer. For example "list album artist "Elvis Presley"" will return a list of the album names of Elvis Presley that exists in the music database.

val update : Client.t -> string option -> Protocol.response

Updates the music database: find new files, remove deleted files, update modified files. URI is a particular directory or song/file to update. If you do not specify it, everything is updated. Prints "updating_db: JOBID" where JOBID is a positive number identifying the update job. You can read the current job id in the status response.

val rescan : Client.t -> string option -> Protocol.response

Same as update, but also rescans unmodified files.

\ No newline at end of file diff --git a/docs/Mpd/Music_database_lwt/index.html b/docs/Mpd/Music_database_lwt/index.html index df9a3a7..8e58837 100644 --- a/docs/Mpd/Music_database_lwt/index.html +++ b/docs/Mpd/Music_database_lwt/index.html @@ -1,2 +1,33 @@ -Music_database_lwt (libmpdclient.Mpd.Music_database_lwt)

Module Mpd.Music_database_lwt

val find : Client_lwt.t -> (Tags.search_tags * string) list -> ?⁠sort:Tags.t -> ?⁠window:(int * int) -> unit -> (Song.t list, Protocol.ack_error * int * string * string) Stdlib.result Lwt.t

Find songs in the db that match exactly the a list of pairs (tag, exact_pattern). The exact_pattern is a string and the tah can be any tag supported by MPD, or one of the special parameters:

  • any checks all tag values
  • file checks the full path (relative to the music directory)
  • base restricts the search to songs in the given directory (also relative to the music directory)
  • modified-since compares the file's time stamp with the given value (ISO 8601 or UNIX time stamp)
val findadd : Client_lwt.t -> (Tags.search_tags * string) list -> Protocol.response Lwt.t

Search for any song that contains WHAT. Parameters have the same meaning as for find, except that search is not case sensitive.

val searchadd : Client_lwt.t -> (Tags.search_tags * string) list -> Protocol.response Lwt.t

Search for any song that contains WHAT in tag TYPE and adds them to current playlist. Parameters have the same meaning as for findadd, except that search is not case sensitive.

val searchaddpl : Client_lwt.t -> string -> (Tags.search_tags * string) list -> Protocol.response Lwt.t

Search for any song that contains WHAT in tag TYPE and adds them to the playlist named NAME. If a playlist by that name doesn't exist it is created. Parameters have the same meaning as for find, except that search is not case sensitive.

type song_count = {
songs : int;
playtime : float;
misc : string;
}

basic type for the response of the count command.

val count : Client_lwt.t -> (Tags.t * string) list -> ?⁠group:Tags.t -> unit -> (song_count list, string) Stdlib.result Lwt.t

Get a count of songs with filters. For examples: count group artist will return for each artist the number of sons, the total playtime and the name of the artist in misc. Counts the number of songs and their total playtime in the db matching TAG exactly. The group keyword may be used to group the results by a tag. The following prints per-artist counts: count group artist count genre metal date 2016 group artist

val list : Client_lwt.t -> Tags.t -> (Tags.t * string) list -> (string list, string) Stdlib.result Lwt.t

Get a list based on some filer. For example "list album artist "Elvis Presley"" will return a list of the album names of Elvis Presley that exists in the music database.

val update : Client_lwt.t -> string option -> Protocol.response Lwt.t

Update the music database: find new files, remove deleted files, update modified files. URI is a particular directory or song/file to update. If you do not specify it, everything is updated. Prints "updating_db: JOBID" where JOBID is a positive number identifying the update job. You can read the current job id in the status response.

val rescan : Client_lwt.t -> string option -> Protocol.response Lwt.t

Same as update, but also rescans unmodified files.

\ No newline at end of file +Music_database_lwt (libmpdclient.Mpd.Music_database_lwt)

Module Mpd.Music_database_lwt

Music_database module with Lwt: regroups data base related commands.

val find : + Client_lwt.t -> + (Tags.search_tags * string) list -> + ?sort:Tags.t -> + ?window:(int * int) -> + unit -> + (Song.t list, Protocol.ack_error * int * string * string) Stdlib.result Lwt.t

Find songs in the db that match exactly the a list of pairs (tag, exact_pattern). The exact_pattern is a string and the tah can be any tag supported by MPD, or one of the special parameters:

  • any checks all tag values
  • file checks the full path (relative to the music directory)
  • base restricts the search to songs in the given directory (also relative to the music directory)
  • modified-since compares the file's time stamp with the given value (ISO 8601 or UNIX time stamp)
val findadd : + Client_lwt.t -> + (Tags.search_tags * string) list -> + Protocol.response Lwt.t

Search for any song that contains WHAT. Parameters have the same meaning as for find, except that search is not case sensitive.

val searchadd : + Client_lwt.t -> + (Tags.search_tags * string) list -> + Protocol.response Lwt.t

Search for any song that contains WHAT in tag TYPE and adds them to current playlist. Parameters have the same meaning as for findadd, except that search is not case sensitive.

val searchaddpl : + Client_lwt.t -> + string -> + (Tags.search_tags * string) list -> + Protocol.response Lwt.t

Search for any song that contains WHAT in tag TYPE and adds them to the playlist named NAME. If a playlist by that name doesn't exist it is created. Parameters have the same meaning as for find, except that search is not case sensitive.

type song_count = {
  1. songs : int;
  2. playtime : float;
  3. misc : string;
}

basic type for the response of the count command.

val count : + Client_lwt.t -> + (Tags.t * string) list -> + ?group:Tags.t -> + unit -> + (song_count list, string) Stdlib.result Lwt.t

Get a count of songs with filters. For examples: count group artist will return for each artist the number of sons, the total playtime and the name of the artist in misc. Counts the number of songs and their total playtime in the db matching TAG exactly. The group keyword may be used to group the results by a tag. The following prints per-artist counts: count group artist count genre metal date 2016 group artist

val list : + Client_lwt.t -> + Tags.t -> + (Tags.t * string) list -> + (string list, string) Stdlib.result Lwt.t

Get a list based on some filer. For example "list album artist "Elvis Presley"" will return a list of the album names of Elvis Presley that exists in the music database.

val update : Client_lwt.t -> string option -> Protocol.response Lwt.t

Update the music database: find new files, remove deleted files, update modified files. URI is a particular directory or song/file to update. If you do not specify it, everything is updated. Prints "updating_db: JOBID" where JOBID is a positive number identifying the update job. You can read the current job id in the status response.

val rescan : Client_lwt.t -> string option -> Protocol.response Lwt.t

Same as update, but also rescans unmodified files.

\ No newline at end of file diff --git a/docs/Mpd/Playback/index.html b/docs/Mpd/Playback/index.html index 7e49013..fef35d4 100644 --- a/docs/Mpd/Playback/index.html +++ b/docs/Mpd/Playback/index.html @@ -1,2 +1,2 @@ -Playback (libmpdclient.Mpd.Playback)

Module Mpd.Playback

val next : Client.t -> Protocol.response

Play next song in the playlist.

val previous : Client.t -> Protocol.response

Play previous song in the playlist.

val stop : Client.t -> Protocol.response

Stop playing.

val pause : Client.t -> bool -> Protocol.response

Toggle pause/resumers playing

val play : Client.t -> int -> Protocol.response

Begin playing the playlist at song number.

val playid : Client.t -> int -> Protocol.response

Begin playing the playlist at song id.

val seek : Client.t -> int -> float -> Protocol.response

Seek to the position time of entry songpos in the playlist.

val seekid : Client.t -> int -> float -> Protocol.response

Seek to the position time of song id.

val seekcur : Client.t -> float -> Protocol.response

Seek to the position time within the current song. TODO : If prefixed by '+' or '-', then the time is relative to the current playing position

\ No newline at end of file +Playback (libmpdclient.Mpd.Playback)

Module Mpd.Playback

Controlling playback functions. https://www.musicpd.org/doc/protocol/playback_commands.html

Play next song in the playlist.

val previous : Client.t -> Protocol.response

Play previous song in the playlist.

Stop playing.

val pause : Client.t -> bool -> Protocol.response

Toggle pause/resumers playing

val play : Client.t -> int -> Protocol.response

Begin playing the playlist at song number.

val playid : Client.t -> int -> Protocol.response

Begin playing the playlist at song id.

val seek : Client.t -> int -> float -> Protocol.response

Seek to the position time of entry songpos in the playlist.

val seekid : Client.t -> int -> float -> Protocol.response

Seek to the position time of song id.

val seekcur : Client.t -> float -> Protocol.response

Seek to the position time within the current song. TODO : If prefixed by '+' or '-', then the time is relative to the current playing position

\ No newline at end of file diff --git a/docs/Mpd/Playback_lwt/index.html b/docs/Mpd/Playback_lwt/index.html index c14fff6..3abd832 100644 --- a/docs/Mpd/Playback_lwt/index.html +++ b/docs/Mpd/Playback_lwt/index.html @@ -1,2 +1,2 @@ -Playback_lwt (libmpdclient.Mpd.Playback_lwt)

Module Mpd.Playback_lwt

val next : Client_lwt.t -> Protocol.response Lwt.t

Play next song in the playlist.

val previous : Client_lwt.t -> Protocol.response Lwt.t

Play previous song in the playlist.

val stop : Client_lwt.t -> Protocol.response Lwt.t

Stop playing.

val pause : Client_lwt.t -> bool -> Protocol.response Lwt.t

Toggle pause/resumers playing

val play : Client_lwt.t -> int -> Protocol.response Lwt.t

Begin playing the playlist at song number.

val playid : Client_lwt.t -> int -> Protocol.response Lwt.t

Begin playing the playlist at song id.

val seek : Client_lwt.t -> int -> float -> Protocol.response Lwt.t

Seek to the position time of entry songpos in the playlist.

val seekid : Client_lwt.t -> int -> float -> Protocol.response Lwt.t

Seek to the position time of song id.

val seekcur : Client_lwt.t -> float -> Protocol.response Lwt.t

Seek to the position time within the current song. TODO : If prefixed by '+' or '-', then the time is relative to the current playing position

\ No newline at end of file +Playback_lwt (libmpdclient.Mpd.Playback_lwt)

Module Mpd.Playback_lwt

Controlling playback functions in Lwt thread. https://www.musicpd.org/doc/protocol/playback_commands.html

val next : Client_lwt.t -> Protocol.response Lwt.t

Play next song in the playlist.

val previous : Client_lwt.t -> Protocol.response Lwt.t

Play previous song in the playlist.

val stop : Client_lwt.t -> Protocol.response Lwt.t

Stop playing.

val pause : Client_lwt.t -> bool -> Protocol.response Lwt.t

Toggle pause/resumers playing

val play : Client_lwt.t -> int -> Protocol.response Lwt.t

Begin playing the playlist at song number.

val playid : Client_lwt.t -> int -> Protocol.response Lwt.t

Begin playing the playlist at song id.

val seek : Client_lwt.t -> int -> float -> Protocol.response Lwt.t

Seek to the position time of entry songpos in the playlist.

val seekid : Client_lwt.t -> int -> float -> Protocol.response Lwt.t

Seek to the position time of song id.

val seekcur : Client_lwt.t -> float -> Protocol.response Lwt.t

Seek to the position time within the current song. TODO : If prefixed by '+' or '-', then the time is relative to the current playing position

\ No newline at end of file diff --git a/docs/Mpd/Playback_options/index.html b/docs/Mpd/Playback_options/index.html index 0af76f9..27e35a2 100644 --- a/docs/Mpd/Playback_options/index.html +++ b/docs/Mpd/Playback_options/index.html @@ -1,2 +1,2 @@ -Playback_options (libmpdclient.Mpd.Playback_options)

Module Mpd.Playback_options

val consume : Client.t -> bool -> Protocol.response

Sets consume state to STATE, STATE should be false or true. When consume is activated, each song played is removed from playlist.

val crossfade : Client.t -> int -> Protocol.response

Sets crossfading between songs.

val mixrampdb : Client.t -> int -> Protocol.response

Sets the threshold at which songs will be overlapped. Like crossfading but doesn't fade the track volume, just overlaps. The songs need to have MixRamp tags added by an external tool. 0dB is the normalized maximum volume so use negative values, I prefer -17dB. In the absence of mixramp tags crossfading will be used. See http://sourceforge.net/projects/mixramp

type mixrampd_t =
| Nan
| Seconds of float

Type for the command mixrampdelay, it can be float number for seconds or nan.

val mixrampdelay : Client.t -> mixrampd_t -> Protocol.response

Additional time subtracted from the overlap calculated by mixrampdb. A value of "nan" disables MixRamp overlapping and falls back to crossfading.

val random : Client.t -> bool -> Protocol.response

Sets random state to STATE, STATE should be true or false

val repeat : Client.t -> bool -> Protocol.response

Sets repeat state to STATE, STATE should be false or true.

val setvol : Client.t -> int -> Protocol.response

Sets volume to VOL, the range of volume is 0-100.

val single : Client.t -> bool -> Protocol.response

Sets single state to STATE, STATE should be 0 or 1. When single is activated, playback is stopped after current song, or song is repeated if the 'repeat' mode is enabled.

type gain_mode_t =
| Off
| Track
| Album
| Auto

gain_mode type for the command replay_gain_mode.

val replay_gain_mode : Client.t -> gain_mode_t -> Protocol.response

Sets the replay gain mode. One of off, track, album, auto. Changing the mode during playback may take several seconds, because the new settings does not affect the buffered data. This command triggers the options idle event.

\ No newline at end of file +Playback_options (libmpdclient.Mpd.Playback_options)

Module Mpd.Playback_options

functions that configure all the playbackoptions

val consume : Client.t -> bool -> Protocol.response

Sets consume state to STATE, STATE should be false or true. When consume is activated, each song played is removed from playlist.

val crossfade : Client.t -> int -> Protocol.response

Sets crossfading between songs.

val mixrampdb : Client.t -> int -> Protocol.response

Sets the threshold at which songs will be overlapped. Like crossfading but doesn't fade the track volume, just overlaps. The songs need to have MixRamp tags added by an external tool. 0dB is the normalized maximum volume so use negative values, I prefer -17dB. In the absence of mixramp tags crossfading will be used. See http://sourceforge.net/projects/mixramp

type mixrampd_t =
  1. | Nan
  2. | Seconds of float
    (*

    Type for the command mixrampdelay, it can be float number for seconds or nan.

    *)
val mixrampdelay : Client.t -> mixrampd_t -> Protocol.response

Additional time subtracted from the overlap calculated by mixrampdb. A value of "nan" disables MixRamp overlapping and falls back to crossfading.

val random : Client.t -> bool -> Protocol.response

Sets random state to STATE, STATE should be true or false

val repeat : Client.t -> bool -> Protocol.response

Sets repeat state to STATE, STATE should be false or true.

val setvol : Client.t -> int -> Protocol.response

Sets volume to VOL, the range of volume is 0-100.

val single : Client.t -> bool -> Protocol.response

Sets single state to STATE, STATE should be 0 or 1. When single is activated, playback is stopped after current song, or song is repeated if the 'repeat' mode is enabled.

type gain_mode_t =
  1. | Off
  2. | Track
  3. | Album
  4. | Auto
    (*

    gain_mode type for the command replay_gain_mode.

    *)
val replay_gain_mode : Client.t -> gain_mode_t -> Protocol.response

Sets the replay gain mode. One of off, track, album, auto. Changing the mode during playback may take several seconds, because the new settings does not affect the buffered data. This command triggers the options idle event.

\ No newline at end of file diff --git a/docs/Mpd/Playback_options_lwt/index.html b/docs/Mpd/Playback_options_lwt/index.html index bfa2363..be98742 100644 --- a/docs/Mpd/Playback_options_lwt/index.html +++ b/docs/Mpd/Playback_options_lwt/index.html @@ -1,2 +1,2 @@ -Playback_options_lwt (libmpdclient.Mpd.Playback_options_lwt)

Module Mpd.Playback_options_lwt

val consume : Client_lwt.t -> bool -> Protocol.response Lwt.t

Sets consume state to STATE, STATE should be false or true. When consume is activated, each song played is removed from playlist.

val crossfade : Client_lwt.t -> int -> Protocol.response Lwt.t

Sets crossfading between songs.

val mixrampdb : Client_lwt.t -> int -> Protocol.response Lwt.t

Sets the threshold at which songs will be overlapped. Like crossfading but doesn't fade the track volume, just overlaps. The songs need to have MixRamp tags added by an external tool. 0dB is the normalized maximum volume so use negative values, I prefer -17dB. In the absence of mixramp tags crossfading will be used. See http://sourceforge.net/projects/mixramp

type mixrampd_t =
| Nan
| Seconds of float

Type for the command mixrampdelay, it can be float for seconds or nan.

val mixrampdelay : Client_lwt.t -> mixrampd_t -> Protocol.response Lwt.t

Additional time subtracted from the overlap calculated by mixrampdb. A value of "nan" disables MixRamp overlapping and falls back to crossfading.

val random : Client_lwt.t -> bool -> Protocol.response Lwt.t

Sets random state to STATE, STATE should be true or false

val repeat : Client_lwt.t -> bool -> Protocol.response Lwt.t

Sets repeat state to STATE, STATE should be false or true.

val setvol : Client_lwt.t -> int -> Protocol.response Lwt.t

Sets volume to VOL, the range of volume is 0-100.

val single : Client_lwt.t -> bool -> Protocol.response Lwt.t

Sets single state to STATE, STATE should be 0 or 1. When single is activated, playback is stopped after current song, or song is repeated if the 'repeat' mode is enabled.

type gain_mode_t =
| Off
| Track
| Album
| Auto

gain_mode type for the command replay_gain_mode.

val replay_gain_mode : Client_lwt.t -> gain_mode_t -> Protocol.response Lwt.t

Sets the replay gain mode. One of off, track, album, auto. Changing the mode during playback may take several seconds, because the new settings does not affect the buffered data. This command triggers the options idle event.

\ No newline at end of file +Playback_options_lwt (libmpdclient.Mpd.Playback_options_lwt)

Module Mpd.Playback_options_lwt

functions that configure all the playbackoptions in a Lwt thread.

val consume : Client_lwt.t -> bool -> Protocol.response Lwt.t

Sets consume state to STATE, STATE should be false or true. When consume is activated, each song played is removed from playlist.

val crossfade : Client_lwt.t -> int -> Protocol.response Lwt.t

Sets crossfading between songs.

val mixrampdb : Client_lwt.t -> int -> Protocol.response Lwt.t

Sets the threshold at which songs will be overlapped. Like crossfading but doesn't fade the track volume, just overlaps. The songs need to have MixRamp tags added by an external tool. 0dB is the normalized maximum volume so use negative values, I prefer -17dB. In the absence of mixramp tags crossfading will be used. See http://sourceforge.net/projects/mixramp

type mixrampd_t =
  1. | Nan
  2. | Seconds of float
    (*

    Type for the command mixrampdelay, it can be float for seconds or nan.

    *)
val mixrampdelay : Client_lwt.t -> mixrampd_t -> Protocol.response Lwt.t

Additional time subtracted from the overlap calculated by mixrampdb. A value of "nan" disables MixRamp overlapping and falls back to crossfading.

val random : Client_lwt.t -> bool -> Protocol.response Lwt.t

Sets random state to STATE, STATE should be true or false

val repeat : Client_lwt.t -> bool -> Protocol.response Lwt.t

Sets repeat state to STATE, STATE should be false or true.

val setvol : Client_lwt.t -> int -> Protocol.response Lwt.t

Sets volume to VOL, the range of volume is 0-100.

val single : Client_lwt.t -> bool -> Protocol.response Lwt.t

Sets single state to STATE, STATE should be 0 or 1. When single is activated, playback is stopped after current song, or song is repeated if the 'repeat' mode is enabled.

type gain_mode_t =
  1. | Off
  2. | Track
  3. | Album
  4. | Auto
    (*

    gain_mode type for the command replay_gain_mode.

    *)
val replay_gain_mode : Client_lwt.t -> gain_mode_t -> Protocol.response Lwt.t

Sets the replay gain mode. One of off, track, album, auto. Changing the mode during playback may take several seconds, because the new settings does not affect the buffered data. This command triggers the options idle event.

\ No newline at end of file diff --git a/docs/Mpd/Protocol/index.html b/docs/Mpd/Protocol/index.html index 5543221..98bd12f 100644 --- a/docs/Mpd/Protocol/index.html +++ b/docs/Mpd/Protocol/index.html @@ -1,2 +1,2 @@ -Protocol (libmpdclient.Mpd.Protocol)

Module Mpd.Protocol

type ack_error =
| Not_list
| Arg
| Password
| Permission
| Unknown
| No_exist
| Playlist_max
| System
| Playlist_load
| Update_already
| Player_sync
| Exist

Type of error that could occur when a command is sent to the mpd server.

type response =
| Ok of string option
| Error of ack_error * int * string * string

Type of the response of the mpd server.

val error_name : ack_error -> string

Get the error name of the error type.

val str_error_to_val : string -> ack_error

Return the related type for the error returned by the server as a string.

val parse_error_response : string -> ack_error * int * string * string

Parse the error response of the mpd server into the error type.

val parse_response : string -> response

Parse the mpd server response

type mpd_response =
| Incomplete
| Complete of string * int

Type used to describe a data while reading through a socket.

val full_mpd_banner : string -> mpd_response

fetch mpd banner

val request_response : string -> mpd_response

fetch request response.

val command_response : string -> mpd_response

fetch command response.

val full_mpd_idle_event : string -> mpd_response

Get the Mpd response for an idle command.

\ No newline at end of file +Protocol (libmpdclient.Mpd.Protocol)

Module Mpd.Protocol

Define the Mpd response and error types

type ack_error =
  1. | Not_list
  2. | Arg
  3. | Password
  4. | Permission
  5. | Unknown
  6. | No_exist
  7. | Playlist_max
  8. | System
  9. | Playlist_load
  10. | Update_already
  11. | Player_sync
  12. | Exist
    (*

    Type of error that could occur when a command is sent to the mpd server.

    *)
type response =
  1. | Ok of string option
  2. | Error of ack_error * int * string * string
    (*

    Type of the response of the mpd server.

    *)
val error_name : ack_error -> string

Get the error name of the error type.

val str_error_to_val : string -> ack_error

Return the related type for the error returned by the server as a string.

val parse_error_response : string -> ack_error * int * string * string

Parse the error response of the mpd server into the error type.

val parse_response : string -> response

Parse the mpd server response

type mpd_response =
  1. | Incomplete
  2. | Complete of string * int
    (*

    Type used to describe a data while reading through a socket.

    *)
val full_mpd_banner : string -> mpd_response

fetch mpd banner

val request_response : string -> mpd_response

fetch request response.

val command_response : string -> mpd_response

fetch command response.

val full_mpd_idle_event : string -> mpd_response

Get the Mpd response for an idle command.

\ No newline at end of file diff --git a/docs/Mpd/Queue/index.html b/docs/Mpd/Queue/index.html index 4b8f266..93af687 100644 --- a/docs/Mpd/Queue/index.html +++ b/docs/Mpd/Queue/index.html @@ -1,2 +1,13 @@ -Queue (libmpdclient.Mpd.Queue)

Module Mpd.Queue

type t =
| PlaylistError of string
| Playlist of Song.t list

Playlist type.

val add : Client.t -> string -> Protocol.response

Add the file URI to the playlist (directories add recursively). URI can also be a single file.

val addid : Client.t -> string -> int -> int

Add a song to the playlist (non-recursive) and returns the song id. URI is always a single file or URL.

val clear : Client.t -> Protocol.response

Clear the current playlist.

val delete : Client.t -> int -> ?⁠position_end:int -> unit -> Protocol.response

Delete a song or a set of songs from the playlist. The song or the range of songs are identified by the position in the playlist.

val deleteid : Client.t -> int -> Protocol.response

Delete the song SONGID from the playlist.

val move : Client.t -> int -> ?⁠position_end:int -> int -> unit -> Protocol.response

Move the song at FROM or range of songs at START:END to TO in the playlist.

val moveid : Client.t -> int -> int -> Protocol.response

Move the song with FROM (songid) to TO (playlist index) in the playlist. If TO is negative, it is relative to the current song in the playlist (if there is one).

val playlist : Client.t -> t

Get the songs in the playlist

val playlistid : Client.t -> int -> (Song.t, string) Stdlib.result

Get information for one song

val playlistfind : Client.t -> string -> string -> t

Find songs in the current playlist with strict matching.

val playlistsearch : Client.t -> string -> string -> t

Search case-insensitively for partial matches in the current playlist.

val swap : Client.t -> int -> int -> Protocol.response

Swap the positions of SONG1 and SONG2.

val shuffle : Client.t -> ?⁠range:(int * int) -> unit -> Protocol.response

Shuffle the current playlist. START:END is optional and specifies a range of songs.

val prio : Client.t -> int -> ?⁠range:(int * int) -> unit -> Protocol.response

Set the priority of the specified songs. A higher priority means that it will be played first when "random" mode is enabled. A priority is an integer between 0 and 255. The default priority of new songs is 0.

val prioid : Client.t -> int -> int list -> Protocol.response

Same as prio, but address the songs with their id.

val swapid : Client.t -> int -> int -> Protocol.response

Swap the positions of SONG1 and SONG2 (both song ids).

val rangeid : Client.t -> int -> ?⁠range:(float * float) -> unit -> Protocol.response

Specify the portion of the song that shall be played. START and END are offsets in seconds (fractional seconds allowed); both are optional. Omitting both (i.e. sending just ":") means "remove the range, play everything". A song that is currently playing cannot be manipulated this way.

val cleartagid : Client.t -> int -> string -> Protocol.response

Remove tags from the specified song. If TAG is not specified, then all tag values will be removed. Editing song tags is only possible for remote songs.

\ No newline at end of file +Queue (libmpdclient.Mpd.Queue)

Module Mpd.Queue

Module for Mpd current playlist manipulation.

type t =
  1. | PlaylistError of string
  2. | Playlist of Song.t list
    (*

    Playlist type.

    *)
val add : Client.t -> string -> Protocol.response

Add the file URI to the playlist (directories add recursively). URI can also be a single file.

val addid : Client.t -> string -> int -> int

Add a song to the playlist (non-recursive) and returns the song id. URI is always a single file or URL.

Clear the current playlist.

val delete : Client.t -> int -> ?position_end:int -> unit -> Protocol.response

Delete a song or a set of songs from the playlist. The song or the range of songs are identified by the position in the playlist.

val deleteid : Client.t -> int -> Protocol.response

Delete the song SONGID from the playlist.

val move : + Client.t -> + int -> + ?position_end:int -> + int -> + unit -> + Protocol.response

Move the song at FROM or range of songs at START:END to TO in the playlist.

val moveid : Client.t -> int -> int -> Protocol.response

Move the song with FROM (songid) to TO (playlist index) in the playlist. If TO is negative, it is relative to the current song in the playlist (if there is one).

val playlist : Client.t -> t

Get the songs in the playlist

val playlistid : Client.t -> int -> (Song.t, string) Stdlib.result

Get information for one song

val playlistfind : Client.t -> string -> string -> t

Find songs in the current playlist with strict matching.

val playlistsearch : Client.t -> string -> string -> t

Search case-insensitively for partial matches in the current playlist.

val swap : Client.t -> int -> int -> Protocol.response

Swap the positions of SONG1 and SONG2.

val shuffle : Client.t -> ?range:(int * int) -> unit -> Protocol.response

Shuffle the current playlist. START:END is optional and specifies a range of songs.

val prio : Client.t -> int -> ?range:(int * int) -> unit -> Protocol.response

Set the priority of the specified songs. A higher priority means that it will be played first when "random" mode is enabled. A priority is an integer between 0 and 255. The default priority of new songs is 0.

val prioid : Client.t -> int -> int list -> Protocol.response

Same as prio, but address the songs with their id.

val swapid : Client.t -> int -> int -> Protocol.response

Swap the positions of SONG1 and SONG2 (both song ids).

val rangeid : + Client.t -> + int -> + ?range:(float * float) -> + unit -> + Protocol.response

Specify the portion of the song that shall be played. START and END are offsets in seconds (fractional seconds allowed); both are optional. Omitting both (i.e. sending just ":") means "remove the range, play everything". A song that is currently playing cannot be manipulated this way.

val cleartagid : Client.t -> int -> string -> Protocol.response

Remove tags from the specified song. If TAG is not specified, then all tag values will be removed. Editing song tags is only possible for remote songs.

\ No newline at end of file diff --git a/docs/Mpd/Queue_lwt/index.html b/docs/Mpd/Queue_lwt/index.html index 067166e..0da21ac 100644 --- a/docs/Mpd/Queue_lwt/index.html +++ b/docs/Mpd/Queue_lwt/index.html @@ -1,2 +1,27 @@ -Queue_lwt (libmpdclient.Mpd.Queue_lwt)

Module Mpd.Queue_lwt

type t =
| PlaylistError of string
| Playlist of Song.t list

Playlist type

val add : Client_lwt.t -> string -> Protocol.response Lwt.t

Add the file URI to the playlist (directories add recursively). URI can also be a single file.

val addid : Client_lwt.t -> string -> int -> int Lwt.t

Add a song to the playlist (non-recursive) and returns the song id. URI is always a single file or URL. For example:

val clear : Client_lwt.t -> Protocol.response Lwt.t

Clear the current playlist.

val delete : Client_lwt.t -> int -> ?⁠position_end:int -> unit -> Protocol.response Lwt.t

Delete a song or a set of songs from the playlist. The song or the range of songs are identified by the position in the playlist.

val deleteid : Client_lwt.t -> int -> Protocol.response Lwt.t

Delete the song SONGID from the playlist.

val move : Client_lwt.t -> int -> ?⁠position_end:int -> int -> unit -> Protocol.response Lwt.t

Move the song at FROM or range of songs at START:END to TO in the playlist.

val moveid : Client_lwt.t -> int -> int -> Protocol.response Lwt.t

Move the song with FROM (songid) to TO (playlist index) in the playlist. If TO is negative, it is relative to the current song in the playlist (if there is one).

val playlist : Client_lwt.t -> t Lwt.t

Get a list of Song.s that represents all the songs in the current playlist.

val playlistid : Client_lwt.t -> int -> (Song.t, string) Stdlib.result Lwt.t

Get a list with the Song.s of the song id in the playlist

val playlistfind : Client_lwt.t -> string -> string -> t Lwt.t

Find songs in the current playlist with strict matching.

val playlistsearch : Client_lwt.t -> string -> string -> t Lwt.t

Search case-insensitively for partial matches in the current playlist.

val swap : Client_lwt.t -> int -> int -> Protocol.response Lwt.t

Swap the positions of SONG1 and SONG2.

val shuffle : Client_lwt.t -> ?⁠range:(int * int) -> unit -> Protocol.response Lwt.t

Shuffle the current playlist. START:END is optional and specifies a range of songs.

val prio : Client_lwt.t -> int -> ?⁠range:(int * int) -> unit -> Protocol.response Lwt.t

Set the priority of the specified songs. A higher priority means that it will be played first when "random" mode is enabled. A priority is an integer between 0 and 255. The default priority of new songs is 0.

val prioid : Client_lwt.t -> int -> int list -> Protocol.response Lwt.t

Same as prio, but address the songs with their id.

val swapid : Client_lwt.t -> int -> int -> Protocol.response Lwt.t

Swap the positions of SONG1 and SONG2 (both song ids).

val rangeid : Client_lwt.t -> int -> ?⁠range:(float * float) -> unit -> Protocol.response Lwt.t

Specify the portion of the song that shall be played. START and END are offsets in seconds (fractional seconds allowed); both are optional. Omitting both (i.e. sending just ":") means "remove the range, play everything". A song that is currently playing cannot be manipulated this way.

val cleartagid : Client_lwt.t -> int -> string -> Protocol.response Lwt.t

Remove tags from the specified song. If TAG is not specified, then all tag values will be removed. Editing song tags is only possible for remote songs.

\ No newline at end of file +Queue_lwt (libmpdclient.Mpd.Queue_lwt)

Module Mpd.Queue_lwt

Module for Mpd current playlist manipulation in Lwt threads.

type t =
  1. | PlaylistError of string
  2. | Playlist of Song.t list
    (*

    Playlist type

    *)
val add : Client_lwt.t -> string -> Protocol.response Lwt.t

Add the file URI to the playlist (directories add recursively). URI can also be a single file.

val addid : Client_lwt.t -> string -> int -> int Lwt.t

Add a song to the playlist (non-recursive) and returns the song id. URI is always a single file or URL. For example:

val clear : Client_lwt.t -> Protocol.response Lwt.t

Clear the current playlist.

val delete : + Client_lwt.t -> + int -> + ?position_end:int -> + unit -> + Protocol.response Lwt.t

Delete a song or a set of songs from the playlist. The song or the range of songs are identified by the position in the playlist.

val deleteid : Client_lwt.t -> int -> Protocol.response Lwt.t

Delete the song SONGID from the playlist.

val move : + Client_lwt.t -> + int -> + ?position_end:int -> + int -> + unit -> + Protocol.response Lwt.t

Move the song at FROM or range of songs at START:END to TO in the playlist.

val moveid : Client_lwt.t -> int -> int -> Protocol.response Lwt.t

Move the song with FROM (songid) to TO (playlist index) in the playlist. If TO is negative, it is relative to the current song in the playlist (if there is one).

val playlist : Client_lwt.t -> t Lwt.t

Get a list of Song.s that represents all the songs in the current playlist.

val playlistid : Client_lwt.t -> int -> (Song.t, string) Stdlib.result Lwt.t

Get a list with the Song.s of the song id in the playlist

val playlistfind : Client_lwt.t -> string -> string -> t Lwt.t

Find songs in the current playlist with strict matching.

val playlistsearch : Client_lwt.t -> string -> string -> t Lwt.t

Search case-insensitively for partial matches in the current playlist.

val swap : Client_lwt.t -> int -> int -> Protocol.response Lwt.t

Swap the positions of SONG1 and SONG2.

val shuffle : + Client_lwt.t -> + ?range:(int * int) -> + unit -> + Protocol.response Lwt.t

Shuffle the current playlist. START:END is optional and specifies a range of songs.

val prio : + Client_lwt.t -> + int -> + ?range:(int * int) -> + unit -> + Protocol.response Lwt.t

Set the priority of the specified songs. A higher priority means that it will be played first when "random" mode is enabled. A priority is an integer between 0 and 255. The default priority of new songs is 0.

val prioid : Client_lwt.t -> int -> int list -> Protocol.response Lwt.t

Same as prio, but address the songs with their id.

val swapid : Client_lwt.t -> int -> int -> Protocol.response Lwt.t

Swap the positions of SONG1 and SONG2 (both song ids).

val rangeid : + Client_lwt.t -> + int -> + ?range:(float * float) -> + unit -> + Protocol.response Lwt.t

Specify the portion of the song that shall be played. START and END are offsets in seconds (fractional seconds allowed); both are optional. Omitting both (i.e. sending just ":") means "remove the range, play everything". A song that is currently playing cannot be manipulated this way.

val cleartagid : Client_lwt.t -> int -> string -> Protocol.response Lwt.t

Remove tags from the specified song. If TAG is not specified, then all tag values will be removed. Editing song tags is only possible for remote songs.

\ No newline at end of file diff --git a/docs/Mpd/Song/index.html b/docs/Mpd/Song/index.html index 694094c..0c1d09c 100644 --- a/docs/Mpd/Song/index.html +++ b/docs/Mpd/Song/index.html @@ -1,2 +1,2 @@ -Song (libmpdclient.Mpd.Song)

Module Mpd.Song

type t

Song type

val empty : t

Empty song type

val parse : string list -> t

Parse a list of song attributes to a Song.s type

val album : t -> string
val albumsort : t -> string
val albumartist : t -> string
val albumartistsort : t -> string
val artist : t -> string
val artistsort : t -> string
val comment : t -> string
val composer : t -> string
val date : t -> string
val disc : t -> string
val duration : t -> float
val file : t -> string
val genre : t -> string
val id : t -> int
val last_modified : t -> string
val name : t -> string
val performer : t -> string
val pos : t -> int
val rate : t -> int
val time : t -> int
val title : t -> string
val track : t -> string
\ No newline at end of file +Song (libmpdclient.Mpd.Song)

Module Mpd.Song

Song module used to store and retrieve information of a song based on * mpd tags.

type t

Song type

val empty : t

Empty song type

val parse : string list -> t

Parse a list of song attributes to a Song.s type

val album : t -> string
val albumsort : t -> string
val albumartist : t -> string
val albumartistsort : t -> string
val artist : t -> string
val artistsort : t -> string
val comment : t -> string
val composer : t -> string
val date : t -> string
val disc : t -> string
val duration : t -> float
val file : t -> string
val genre : t -> string
val id : t -> int
val last_modified : t -> string
val name : t -> string
val performer : t -> string
val pos : t -> int
val rate : t -> int
val time : t -> int
val title : t -> string
val track : t -> string
\ No newline at end of file diff --git a/docs/Mpd/Status/index.html b/docs/Mpd/Status/index.html index 68cccfb..abcabfe 100644 --- a/docs/Mpd/Status/index.html +++ b/docs/Mpd/Status/index.html @@ -1,2 +1,2 @@ -Status (libmpdclient.Mpd.Status)

Module Mpd.Status

type t

Main status type that contains all the status information of the server.

type state =
| Play
| Pause
| Stop
| ErrState

Current state (playing, pause or stopped) of the mpd server.

val string_of_state : state -> string

Get the string representation of a state.

val parse : string list -> t

Parse list of strings into a Mpd Status type

val volume : t -> int

Get the volume level from a Mpd Status

val repeat : t -> bool

Find out if the player is in repeat mode

val random : t -> bool

Find out if the player is in random mode

val single : t -> bool

Find out if the player is in single mode

val consume : t -> bool

Find out if the player is in consume mode

val playlist : t -> int

Get the current playlist id

val playlistlength : t -> int

Get the current playlist length

val state : t -> state

Get the state of the player : Play / Pause / Stop

val song : t -> int

Get the song number of the current song stopped on or playing

val songid : t -> int

Get the song id of the current song stopped on or playing

val nextsong : t -> int

Get the next song number based on the current song stopped on or playing

val nextsongid : t -> int

Get the next song id based on the current song stopped on or playing

val time : t -> string

Get the total time elapsed (of current playing/paused song)

val elapsed : t -> float

Get the total time elapsed within the current song, but with higher resolution

val duration : t -> float

Returns the totatl duration of the current song in seconds

val bitrate : t -> int

Get the instantaneous bitrate in kbps

val xfade : t -> int

Get the crossfade in seconds of the current song

val mixrampdb : t -> float

Get the mixramp threshold in dB

val mixrampdelay : t -> float

Get the mixrampdelay in seconds

val audio : t -> string

Get information of the audio file of the current song (sampleRate:bits:channels)

val updating_db : t -> int

Get the job id

val error : t -> string

Get the error message if there is one

\ No newline at end of file +Status (libmpdclient.Mpd.Status)

Module Mpd.Status

Status : get informations on the current status of the Mpd server.

type t

Main status type that contains all the status information of the server.

type state =
  1. | Play
  2. | Pause
  3. | Stop
  4. | ErrState
    (*

    Current state (playing, pause or stopped) of the mpd server.

    *)
val string_of_state : state -> string

Get the string representation of a state.

val parse : string list -> t

Parse list of strings into a Mpd Status type

val volume : t -> int

Get the volume level from a Mpd Status

val repeat : t -> bool

Find out if the player is in repeat mode

val random : t -> bool

Find out if the player is in random mode

val single : t -> bool

Find out if the player is in single mode

val consume : t -> bool

Find out if the player is in consume mode

val playlist : t -> int

Get the current playlist id

val playlistlength : t -> int

Get the current playlist length

val state : t -> state

Get the state of the player : Play / Pause / Stop

val song : t -> int

Get the song number of the current song stopped on or playing

val songid : t -> int

Get the song id of the current song stopped on or playing

val nextsong : t -> int

Get the next song number based on the current song stopped on or playing

val nextsongid : t -> int

Get the next song id based on the current song stopped on or playing

val time : t -> string

Get the total time elapsed (of current playing/paused song)

val elapsed : t -> float

Get the total time elapsed within the current song, but with higher resolution

val duration : t -> float

Returns the totatl duration of the current song in seconds

val bitrate : t -> int

Get the instantaneous bitrate in kbps

val xfade : t -> int

Get the crossfade in seconds of the current song

val mixrampdb : t -> float

Get the mixramp threshold in dB

val mixrampdelay : t -> float

Get the mixrampdelay in seconds

val audio : t -> string

Get information of the audio file of the current song (sampleRate:bits:channels)

val updating_db : t -> int

Get the job id

val error : t -> string

Get the error message if there is one

\ No newline at end of file diff --git a/docs/Mpd/Stored_playlists/index.html b/docs/Mpd/Stored_playlists/index.html index 37d57d7..04b0ae1 100644 --- a/docs/Mpd/Stored_playlists/index.html +++ b/docs/Mpd/Stored_playlists/index.html @@ -1,2 +1,7 @@ -Stored_playlists (libmpdclient.Mpd.Stored_playlists)

Module Mpd.Stored_playlists

val listplaylists : Client.t -> (string list, string) Stdlib.result

Print a list of the playlist names.

val load : Client.t -> string -> ?⁠range:(int * int) -> unit -> Protocol.response

Load the playlist into the current queue. Playlist plugins are supported. A range may be specified to load only a part of the playlist.

val playlistadd : Client.t -> string -> string -> Protocol.response

Add URI to the playlist NAME.m3u. NAME.m3u will be created if it does not exist.

val playlistclear : Client.t -> string -> Protocol.response

Clear the playlist NAME.m3u.

val playlistdelete : Client.t -> string -> int -> Protocol.response

Delete SONGPOS from the playlist NAME.m3u.

val playlistmove : Client.t -> string -> int -> int -> Protocol.response

Move the song at position FROM in the playlist NAME.m3u to the position TO.

val rename : Client.t -> string -> string -> Protocol.response

Rename the playlist NAME.m3u to NEW_NAME.m3u.

val rm : Client.t -> string -> Protocol.response

Remove the playlist NAME.m3u from the playlist directory.

val save : Client.t -> string -> Protocol.response

Save the current playlist to NAME.m3u in the playlist directory.

\ No newline at end of file +Stored_playlists (libmpdclient.Mpd.Stored_playlists)

Module Mpd.Stored_playlists

Stored_playlists : Playlists are stored inside the configured playlist directory. They are addressed with their file name (without the directory and without the .m3u suffix).

val listplaylists : Client.t -> (string list, string) Stdlib.result

Print a list of the playlist names.

val load : + Client.t -> + string -> + ?range:(int * int) -> + unit -> + Protocol.response

Load the playlist into the current queue. Playlist plugins are supported. A range may be specified to load only a part of the playlist.

val playlistadd : Client.t -> string -> string -> Protocol.response

Add URI to the playlist NAME.m3u. NAME.m3u will be created if it does not exist.

val playlistclear : Client.t -> string -> Protocol.response

Clear the playlist NAME.m3u.

val playlistdelete : Client.t -> string -> int -> Protocol.response

Delete SONGPOS from the playlist NAME.m3u.

val playlistmove : Client.t -> string -> int -> int -> Protocol.response

Move the song at position FROM in the playlist NAME.m3u to the position TO.

val rename : Client.t -> string -> string -> Protocol.response

Rename the playlist NAME.m3u to NEW_NAME.m3u.

val rm : Client.t -> string -> Protocol.response

Remove the playlist NAME.m3u from the playlist directory.

val save : Client.t -> string -> Protocol.response

Save the current playlist to NAME.m3u in the playlist directory.

\ No newline at end of file diff --git a/docs/Mpd/Stored_playlists_lwt/index.html b/docs/Mpd/Stored_playlists_lwt/index.html index 5585ac7..da1b3de 100644 --- a/docs/Mpd/Stored_playlists_lwt/index.html +++ b/docs/Mpd/Stored_playlists_lwt/index.html @@ -1,2 +1,12 @@ -Stored_playlists_lwt (libmpdclient.Mpd.Stored_playlists_lwt)

Module Mpd.Stored_playlists_lwt

val listplaylists : Client_lwt.t -> (string list, string) Stdlib.result Lwt.t

Print a list of the playlist names.

val load : Client_lwt.t -> string -> ?⁠range:(int * int) -> unit -> Protocol.response Lwt.t

Load the playlist into the current queue. Playlist plugins are supported. A range may be specified to load only a part of the playlist.

val playlistadd : Client_lwt.t -> string -> string -> Protocol.response Lwt.t

Add URI to the playlist NAME.m3u. NAME.m3u will be created if it does not exist.

val playlistclear : Client_lwt.t -> string -> Protocol.response Lwt.t

Clear the playlist NAME.m3u.

val playlistdelete : Client_lwt.t -> string -> int -> Protocol.response Lwt.t

Delete SONGPOS from the playlist NAME.m3u.

val playlistmove : Client_lwt.t -> string -> int -> int -> Protocol.response Lwt.t

Move the song at position FROM in the playlist NAME.m3u to the position TO.

val rename : Client_lwt.t -> string -> string -> Protocol.response Lwt.t

Rename the playlist NAME.m3u to NEW_NAME.m3u.

val rm : Client_lwt.t -> string -> Protocol.response Lwt.t

Remove the playlist NAME.m3u from the playlist directory.

val save : Client_lwt.t -> string -> Protocol.response Lwt.t

Save the current playlist to NAME.m3u in the playlist directory.

\ No newline at end of file +Stored_playlists_lwt (libmpdclient.Mpd.Stored_playlists_lwt)

Module Mpd.Stored_playlists_lwt

LwtStoredPlaylists : Playlists are stored inside the configured playlist directory. They are addressed with their file name (without the directory and without the .m3u suffix). This is module is based on Lwt.

val listplaylists : Client_lwt.t -> (string list, string) Stdlib.result Lwt.t

Print a list of the playlist names.

val load : + Client_lwt.t -> + string -> + ?range:(int * int) -> + unit -> + Protocol.response Lwt.t

Load the playlist into the current queue. Playlist plugins are supported. A range may be specified to load only a part of the playlist.

val playlistadd : Client_lwt.t -> string -> string -> Protocol.response Lwt.t

Add URI to the playlist NAME.m3u. NAME.m3u will be created if it does not exist.

val playlistclear : Client_lwt.t -> string -> Protocol.response Lwt.t

Clear the playlist NAME.m3u.

val playlistdelete : Client_lwt.t -> string -> int -> Protocol.response Lwt.t

Delete SONGPOS from the playlist NAME.m3u.

val playlistmove : + Client_lwt.t -> + string -> + int -> + int -> + Protocol.response Lwt.t

Move the song at position FROM in the playlist NAME.m3u to the position TO.

val rename : Client_lwt.t -> string -> string -> Protocol.response Lwt.t

Rename the playlist NAME.m3u to NEW_NAME.m3u.

val rm : Client_lwt.t -> string -> Protocol.response Lwt.t

Remove the playlist NAME.m3u from the playlist directory.

val save : Client_lwt.t -> string -> Protocol.response Lwt.t

Save the current playlist to NAME.m3u in the playlist directory.

\ No newline at end of file diff --git a/docs/Mpd/Tags/index.html b/docs/Mpd/Tags/index.html index d6d0577..2bc8bd0 100644 --- a/docs/Mpd/Tags/index.html +++ b/docs/Mpd/Tags/index.html @@ -1,2 +1,2 @@ -Tags (libmpdclient.Mpd.Tags)

Module Mpd.Tags

type t =
| Unknown
| Artist
| Album
| Album_artist
| Title
| Track
| Name
| Genre
| Date
| Composer
| Performer
| Comment
| Disc
| Musicbrainz_artistid
| Musicbrainz_albumid
| Musicbrainz_albumartistid
| Musicbrainz_trackid
| Musicbrainz_releasetrackid
| Original_date
| Artist_sort
| Album_artist_sort
| Album_sort
| Count
val tag_to_string : t -> string
type search_tags =
| Any
| File
| Base
| Modified_since
| Mpd_tag of t
val search_tag_to_string : search_tags -> string
val build_tag_parameter : ('a -> string) -> ('a * string) list -> string
\ No newline at end of file +Tags (libmpdclient.Mpd.Tags)

Module Mpd.Tags

type t =
  1. | Unknown
  2. | Artist
  3. | Album
  4. | Album_artist
  5. | Title
  6. | Track
  7. | Name
  8. | Genre
  9. | Date
  10. | Composer
  11. | Performer
  12. | Comment
  13. | Disc
  14. | Musicbrainz_artistid
  15. | Musicbrainz_albumid
  16. | Musicbrainz_albumartistid
  17. | Musicbrainz_trackid
  18. | Musicbrainz_releasetrackid
  19. | Original_date
  20. | Artist_sort
  21. | Album_artist_sort
  22. | Album_sort
  23. | Count
val tag_to_string : t -> string
type search_tags =
  1. | Any
  2. | File
  3. | Base
  4. | Modified_since
  5. | Mpd_tag of t
val search_tag_to_string : search_tags -> string
val build_tag_parameter : ('a -> string) -> ('a * string) list -> string
\ No newline at end of file diff --git a/docs/Mpd/Utils/index.html b/docs/Mpd/Utils/index.html index 32c11bd..54fa78f 100644 --- a/docs/Mpd/Utils/index.html +++ b/docs/Mpd/Utils/index.html @@ -1,2 +1,5 @@ -Utils (libmpdclient.Mpd.Utils)

Module Mpd.Utils

val remove_trailing_new_line : string -> string

Remove new line char at the end of a string.

val remove_new_lines : string -> string

Remove all new line characters in a string.

val split_lines : string -> string list

Split multiline string into a list of strings

type item_id =
| Simple of int
| Num_on_num of int * int

Type that can save the id of an element which can be an int or two int

val num_on_num_parse : string -> item_id

Split string like "8/14" to 8 and 14, returns (-1, -1) if it fails. * is used in track and disc tab of the song data

type pair = {
key : string;
value : string;
}

Create a type used when splitting a line which has the form key: value . * This type is used by Mpd.Utils.read_key_val.

val read_key_val : string -> pair

Split a line with the form "k: v" in the value of type pair

val values_of_pairs : string list -> string list

Returns all the values of a list of strings that have the key/value form.

val bool_of_int_str : string -> bool

Get a boolean value from a string number. The string "0" is false while all * other string is true.

val read_file_paths : string -> string list

Get the file path from the ouput of the command "listplaylist name"

val read_list_playlists : string -> string list

Get playlists list from output of the command "listplaylists".

exception EMusic_database of string
val parse_count_response : string -> string option -> (int * float * string) list

Get the count list from the Mpd count command.

val print_data : string -> unit
val print_data_lwt : string -> unit Lwt.t
\ No newline at end of file +Utils (libmpdclient.Mpd.Utils)

Module Mpd.Utils

Set of helpers for the mpdlibclient library.

val remove_trailing_new_line : string -> string

Remove new line char at the end of a string.

val remove_new_lines : string -> string

Remove all new line characters in a string.

val split_lines : string -> string list

Split multiline string into a list of strings

type item_id =
  1. | Simple of int
  2. | Num_on_num of int * int

Type that can save the id of an element which can be an int or two int

val num_on_num_parse : string -> item_id

Split string like "8/14" to 8 and 14, returns (-1, -1) if it fails. * is used in track and disc tab of the song data

type pair = {
  1. key : string;
  2. value : string;
}

Create a type used when splitting a line which has the form key: value . * This type is used by Mpd.Utils.read_key_val.

val read_key_val : string -> pair

Split a line with the form "k: v" in the value of type pair

val values_of_pairs : string list -> string list

Returns all the values of a list of strings that have the key/value form.

val bool_of_int_str : string -> bool

Get a boolean value from a string number. The string "0" is false while all * other string is true.

val read_file_paths : string -> string list

Get the file path from the ouput of the command "listplaylist name"

val read_list_playlists : string -> string list

Get playlists list from output of the command "listplaylists".

exception EMusic_database of string
val parse_count_response : + string -> + string option -> + (int * float * string) list

Get the count list from the Mpd count command.

val print_data : string -> unit
val print_data_lwt : string -> unit Lwt.t
\ No newline at end of file diff --git a/docs/Mpd/index.html b/docs/Mpd/index.html index 0227ca3..6e2e67f 100644 --- a/docs/Mpd/index.html +++ b/docs/Mpd/index.html @@ -1,2 +1,2 @@ -Mpd (libmpdclient.Mpd)

Module Mpd

module Client : sig ... end
module Client_lwt : sig ... end
module Connection : sig ... end
module Connection_lwt : sig ... end
module Loggin : sig ... end
module Music_database : sig ... end
module Music_database_lwt : sig ... end
module Playback : sig ... end
module Playback_lwt : sig ... end
module Playback_options : sig ... end
module Playback_options_lwt : sig ... end
module Protocol : sig ... end
module Queue : sig ... end
module Queue_lwt : sig ... end
module Song : sig ... end
module Status : sig ... end
module Stored_playlists : sig ... end
module Stored_playlists_lwt : sig ... end
module Tags : sig ... end
module Utils : sig ... end
\ No newline at end of file +Mpd (libmpdclient.Mpd)

Module Mpd

module Client : sig ... end

Provides functions and type in order to communicate to the mpd server with commands and requests.

module Client_lwt : sig ... end

Provides functions and type in order to communicate to the mpd server with commands and requests in Lwt threads.

module Connection : sig ... end

Offer functions and type in order to handle connections to the mpd server at the socket level.

module Connection_lwt : sig ... end

Offer functions and type in order to handle connections to the mpd server at the socket level in Lwt thread.

module Loggin : sig ... end
module Music_database : sig ... end

Music_database module: regroups data base related commands.

module Music_database_lwt : sig ... end

Music_database module with Lwt: regroups data base related commands.

module Playback : sig ... end

Controlling playback functions. https://www.musicpd.org/doc/protocol/playback_commands.html

module Playback_lwt : sig ... end

Controlling playback functions in Lwt thread. https://www.musicpd.org/doc/protocol/playback_commands.html

module Playback_options : sig ... end

functions that configure all the playbackoptions

module Playback_options_lwt : sig ... end

functions that configure all the playbackoptions in a Lwt thread.

module Protocol : sig ... end

Define the Mpd response and error types

module Queue : sig ... end

Module for Mpd current playlist manipulation.

module Queue_lwt : sig ... end

Module for Mpd current playlist manipulation in Lwt threads.

module Song : sig ... end

Song module used to store and retrieve information of a song based on * mpd tags.

module Status : sig ... end

Status : get informations on the current status of the Mpd server.

module Stored_playlists : sig ... end

Stored_playlists : Playlists are stored inside the configured playlist directory. They are addressed with their file name (without the directory and without the .m3u suffix).

module Stored_playlists_lwt : sig ... end

LwtStoredPlaylists : Playlists are stored inside the configured playlist directory. They are addressed with their file name (without the directory and without the .m3u suffix). This is module is based on Lwt.

module Tags : sig ... end
module Utils : sig ... end

Set of helpers for the mpdlibclient library.

\ No newline at end of file diff --git a/docs/Mpd__Client/.dune-keep b/docs/Mpd__Client/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Client/index.html b/docs/Mpd__Client/index.html deleted file mode 100644 index d21f08d..0000000 --- a/docs/Mpd__Client/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Client (libmpdclient.Mpd__Client)

Module Mpd__Client

Provides functions and type in order to communicate to the mpd server with commands and requests.

type t

Client type

val initialize : Mpd.Connection.t -> t

Initialize the client with a connection.

val send_request : t -> string -> Mpd.Protocol.response
val send_command : t -> string -> Mpd.Protocol.response
val mpd_banner : t -> string

Return the mpd banner that the server send at the first connection of the client.

val status : t -> (Mpd.Status.t, string) Stdlib.result

Create a status request and returns the status under a Mpd.Status.t type if no error occurs.

val ping : t -> Mpd.Protocol.response

Does nothing but return "OK".

val password : t -> string -> Mpd.Protocol.response

This is used for authentication with the server. PASSWORD is simply the plaintext password.

val close : t -> unit

Close the connection to MPD. MPD will try to send the remaining output buffer before it actually closes the connection, but that cannot be guaranteed. This command will not generate a response. This function is a wrapper to the "close" command of the Mpd protocol, this means that it first send the "close" command and it close the connection at the socket level.

val tagtypes : t -> string list

Show a list of available tag types. It is an intersection of the metadata_to_use setting and this client's tag mask. About the tag mask: each client can decide to disable any number of tag types, which will be omitted from responses to this client. That is a good idea, because it makes responses smaller. The following tagtypes sub commands configure this list.

\ No newline at end of file diff --git a/docs/Mpd__Client_lwt/.dune-keep b/docs/Mpd__Client_lwt/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Client_lwt/index.html b/docs/Mpd__Client_lwt/index.html deleted file mode 100644 index 2f564f6..0000000 --- a/docs/Mpd__Client_lwt/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Client_lwt (libmpdclient.Mpd__Client_lwt)

Module Mpd__Client_lwt

Provides functions and type in order to communicate to the mpd server with commands and requests in Lwt threads.

type t

Type for a Mpd Client to be used with Lwt promises.

val initialize : Mpd.Connection_lwt.t -> t Lwt.t

Initialize the client with a connection.

val mpd_banner : t -> string Lwt.t

Return the mpd banner that the server send at the first connection of the client.

val idle : t -> (string, string) Stdlib.Pervasives.result Lwt.t

Wait for an event to occur in order to return. When a Client send this * command to the Mpd server throught its connection, the Mpd server do * not answer to any other command except the noidle command. The idea is * to first cancel the promise that has send the "idle" command with * Lwt.cancel and then send the noidle command to the Mpd server. An * example can be found in samples/mpd_lwt_client_idle_noidle.ml.

val idle_loop : t -> (string -> bool Lwt.t) -> unit Lwt.t

Loop on mpd event with the "idle" command the on_event function take the event response as argument and return true to stop or false to continue the loop

val send : t -> string -> Mpd.Protocol.response Lwt.t

Send to the mpd server a command. The response of the server is returned under the form of a Protocol.response type.

val request : t -> string -> Mpd.Protocol.response Lwt.t

Send to the mpd server a request. The response of the server is returned under the form of a Protocol.response type. A request is different from a command because a command generate an action from Mpd and returns "OK" or an error while a request does not generate an action from Mpd and returns "some data to analyse"OK or an error.

val status : t -> (Mpd.Status.t, string) Stdlib.Pervasives.result Lwt.t

Create a status request and returns the status under a Mpd.Status.s Lwt.t type.

val ping : t -> Mpd.Protocol.response Lwt.t

Does nothing but return "OK".

val password : t -> string -> Mpd.Protocol.response Lwt.t

This is used for authentication with the server. PASSWORD is simply the plaintext password.

val noidle : t -> Mpd.Protocol.response Lwt.t

This command is needed to stop listening after a Client.idle command. An example of usage can be seen in samples/mpd_lwt_client_idle_noidle.exe.

val close : t -> unit Lwt.t

Close the client. MPD will try to send the remaining output buffer before it actually closes the connection, but that cannot be guaranteed. This command will not generate a response. This function is a wrapper to the "close" command of the Mpd protocol, this means that it first send the "close" command and it close the connection at the socket level.

\ No newline at end of file diff --git a/docs/Mpd__Connection/.dune-keep b/docs/Mpd__Connection/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Connection/index.html b/docs/Mpd__Connection/index.html deleted file mode 100644 index 48b52b2..0000000 --- a/docs/Mpd__Connection/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Connection (libmpdclient.Mpd__Connection)

Module Mpd__Connection

Offer functions and type in order to handle connections to the mpd server at the socket level.

type t

connection type

val initialize : string -> int -> t

Create the connection, exit if the connection can not be initialized.

val hostname : t -> string

Retrieve the host's string of the initialized connection.

val port : t -> int

Retrieve the port of the connection of the initialized connection.

val close : t -> unit

Close the connection

val write : t -> string -> unit

Write to an Mpd connection

val read_mpd_banner : t -> string

Read in an Mpd connection

val read_request_response : t -> string

Read a Mpd response to a request.

val read_command_response : t -> string

Read a Mpd response to a command.

\ No newline at end of file diff --git a/docs/Mpd__Connection_lwt/.dune-keep b/docs/Mpd__Connection_lwt/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Connection_lwt/index.html b/docs/Mpd__Connection_lwt/index.html deleted file mode 100644 index dd3dda5..0000000 --- a/docs/Mpd__Connection_lwt/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Connection_lwt (libmpdclient.Mpd__Connection_lwt)

Module Mpd__Connection_lwt

Offer functions and type in order to handle connections to the mpd server at the socket level in Lwt thread.

type t

Lwt connection type for thread usage

exception Lwt_unix_exn of string

Custom exception.

val initialize : string -> int -> t Lwt.t

Create the connection in a Lwt thread, throws an exception Mpd_Lwt_unix_exn of string when an error occurs.

val hostname : t -> string Lwt.t

Get the hostname of the current connection.

val port : t -> int Lwt.t

Get the port of the current connection.

val buffer : t -> string Lwt.t

Get the buffer used by the connection.

val recvbytes : t -> Stdlib.Bytes.t Lwt.t

Read from the connection.

val write : t -> string -> int Lwt.t

Write in a Mpd connection throught a Lwt thread. It fails with an exception Mpd_Lwt_unix_exn of string.

val close : t -> unit Lwt.t

Close the connection.

\ No newline at end of file diff --git a/docs/Mpd__Loggin/.dune-keep b/docs/Mpd__Loggin/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Loggin/index.html b/docs/Mpd__Loggin/index.html deleted file mode 100644 index 0d20de9..0000000 --- a/docs/Mpd__Loggin/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Loggin (libmpdclient.Mpd__Loggin)

Module Mpd__Loggin

val reporter : string -> Logs.reporter
val file_exists : string -> bool
val setup : unit -> unit Lwt.t
val debuf : string -> unit Lwt.t
val err : string -> unit Lwt.t
\ No newline at end of file diff --git a/docs/Mpd__Music_database/.dune-keep b/docs/Mpd__Music_database/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Music_database/index.html b/docs/Mpd__Music_database/index.html deleted file mode 100644 index 7834ebb..0000000 --- a/docs/Mpd__Music_database/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Music_database (libmpdclient.Mpd__Music_database)

Module Mpd__Music_database

Music_database module: regroups data base related commands.

val find : Mpd.Client.t -> (Mpd.Tags.search_tags * string) list -> ?⁠sort:Mpd.Tags.t -> ?⁠window:(int * int) -> unit -> (Mpd.Song.t list, Mpd.Protocol.ack_error * int * string * string) Stdlib.result

Find songs in the db that match exactly the a list of pairs (tag, exact_pattern). The exact_pattern is a string and the tah can be any tag supported by MPD, or one of the special parameters:

  • any checks all tag values
  • file checks the full path (relative to the music directory)
  • base restricts the search to songs in the given directory (also relative to the music directory)
  • modified-since compares the file's time stamp with the given value (ISO 8601 or UNIX time stamp)
val findadd : Mpd.Client.t -> (Mpd.Tags.search_tags * string) list -> Mpd.Protocol.response

Find songs in the db that and adds them to current playlist. Parameters have the same meaning as for find.

Search for any song that contains WHAT. Parameters have the same meaning as for find, except that search is not case sensitive.

val searchadd : Mpd.Client.t -> (Mpd.Tags.search_tags * string) list -> Mpd.Protocol.response

Search for any song that contains WHAT in tag TYPE and adds them to current playlist. Parameters have the same meaning as for findadd, except that search is not case sensitive.

val searchaddpl : Mpd.Client.t -> string -> (Mpd.Tags.search_tags * string) list -> Mpd.Protocol.response

Search for any song that contains WHAT in tag TYPE and adds them to the playlist named NAME. If a playlist by that name doesn't exist it is created. Parameters have the same meaning as for find, except that search is not case sensitive.

type song_count = {
songs : int;
playtime : float;
misc : string;
}

basic type for the response of the count command.

val count : Mpd.Client.t -> (Mpd.Tags.t * string) list -> ?⁠group:Mpd.Tags.t -> unit -> (song_count list, string) Stdlib.result

Get a count of songs with filters. For examples: count group artist will return for each artist the number of sons, the total playtime and the name of the artist in misc. Counts the number of songs and their total playtime in the db matching TAG exactly. The group keyword may be used to group the results by a tag. The following prints per-artist counts: count group artist count genre metal date 2016 group artist

val list : Mpd.Client.t -> Mpd.Tags.t -> (Mpd.Tags.t * string) list -> (string list, string) Stdlib.result

Get a list based on some filer. For example "list album artist "Elvis Presley"" will return a list of the album names of Elvis Presley that exists in the music database.

val update : Mpd.Client.t -> string option -> Mpd.Protocol.response

Updates the music database: find new files, remove deleted files, update modified files. URI is a particular directory or song/file to update. If you do not specify it, everything is updated. Prints "updating_db: JOBID" where JOBID is a positive number identifying the update job. You can read the current job id in the status response.

val rescan : Mpd.Client.t -> string option -> Mpd.Protocol.response

Same as update, but also rescans unmodified files.

\ No newline at end of file diff --git a/docs/Mpd__Music_database_lwt/.dune-keep b/docs/Mpd__Music_database_lwt/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Music_database_lwt/index.html b/docs/Mpd__Music_database_lwt/index.html deleted file mode 100644 index 7bfe59e..0000000 --- a/docs/Mpd__Music_database_lwt/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Music_database_lwt (libmpdclient.Mpd__Music_database_lwt)

Module Mpd__Music_database_lwt

Music_database module with Lwt: regroups data base related commands.

val find : Mpd.Client_lwt.t -> (Mpd.Tags.search_tags * string) list -> ?⁠sort:Mpd.Tags.t -> ?⁠window:(int * int) -> unit -> (Mpd.Song.t list, Mpd.Protocol.ack_error * int * string * string) Stdlib.result Lwt.t

Find songs in the db that match exactly the a list of pairs (tag, exact_pattern). The exact_pattern is a string and the tah can be any tag supported by MPD, or one of the special parameters:

  • any checks all tag values
  • file checks the full path (relative to the music directory)
  • base restricts the search to songs in the given directory (also relative to the music directory)
  • modified-since compares the file's time stamp with the given value (ISO 8601 or UNIX time stamp)
val findadd : Mpd.Client_lwt.t -> (Mpd.Tags.search_tags * string) list -> Mpd.Protocol.response Lwt.t

Search for any song that contains WHAT. Parameters have the same meaning as for find, except that search is not case sensitive.

val searchadd : Mpd.Client_lwt.t -> (Mpd.Tags.search_tags * string) list -> Mpd.Protocol.response Lwt.t

Search for any song that contains WHAT in tag TYPE and adds them to current playlist. Parameters have the same meaning as for findadd, except that search is not case sensitive.

val searchaddpl : Mpd.Client_lwt.t -> string -> (Mpd.Tags.search_tags * string) list -> Mpd.Protocol.response Lwt.t

Search for any song that contains WHAT in tag TYPE and adds them to the playlist named NAME. If a playlist by that name doesn't exist it is created. Parameters have the same meaning as for find, except that search is not case sensitive.

type song_count = {
songs : int;
playtime : float;
misc : string;
}

basic type for the response of the count command.

val count : Mpd.Client_lwt.t -> (Mpd.Tags.t * string) list -> ?⁠group:Mpd.Tags.t -> unit -> (song_count list, string) Stdlib.result Lwt.t

Get a count of songs with filters. For examples: count group artist will return for each artist the number of sons, the total playtime and the name of the artist in misc. Counts the number of songs and their total playtime in the db matching TAG exactly. The group keyword may be used to group the results by a tag. The following prints per-artist counts: count group artist count genre metal date 2016 group artist

val list : Mpd.Client_lwt.t -> Mpd.Tags.t -> (Mpd.Tags.t * string) list -> (string list, string) Stdlib.result Lwt.t

Get a list based on some filer. For example "list album artist "Elvis Presley"" will return a list of the album names of Elvis Presley that exists in the music database.

val update : Mpd.Client_lwt.t -> string option -> Mpd.Protocol.response Lwt.t

Update the music database: find new files, remove deleted files, update modified files. URI is a particular directory or song/file to update. If you do not specify it, everything is updated. Prints "updating_db: JOBID" where JOBID is a positive number identifying the update job. You can read the current job id in the status response.

val rescan : Mpd.Client_lwt.t -> string option -> Mpd.Protocol.response Lwt.t

Same as update, but also rescans unmodified files.

\ No newline at end of file diff --git a/docs/Mpd__Playback/.dune-keep b/docs/Mpd__Playback/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Playback/index.html b/docs/Mpd__Playback/index.html deleted file mode 100644 index 004b118..0000000 --- a/docs/Mpd__Playback/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Playback (libmpdclient.Mpd__Playback)

Module Mpd__Playback

Controlling playback functions. https://www.musicpd.org/doc/protocol/playback_commands.html

val next : Mpd.Client.t -> Mpd.Protocol.response

Play next song in the playlist.

val previous : Mpd.Client.t -> Mpd.Protocol.response

Play previous song in the playlist.

val stop : Mpd.Client.t -> Mpd.Protocol.response

Stop playing.

val pause : Mpd.Client.t -> bool -> Mpd.Protocol.response

Toggle pause/resumers playing

val play : Mpd.Client.t -> int -> Mpd.Protocol.response

Begin playing the playlist at song number.

val playid : Mpd.Client.t -> int -> Mpd.Protocol.response

Begin playing the playlist at song id.

val seek : Mpd.Client.t -> int -> float -> Mpd.Protocol.response

Seek to the position time of entry songpos in the playlist.

val seekid : Mpd.Client.t -> int -> float -> Mpd.Protocol.response

Seek to the position time of song id.

val seekcur : Mpd.Client.t -> float -> Mpd.Protocol.response

Seek to the position time within the current song. TODO : If prefixed by '+' or '-', then the time is relative to the current playing position

\ No newline at end of file diff --git a/docs/Mpd__Playback_lwt/.dune-keep b/docs/Mpd__Playback_lwt/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Playback_lwt/index.html b/docs/Mpd__Playback_lwt/index.html deleted file mode 100644 index 9585f7b..0000000 --- a/docs/Mpd__Playback_lwt/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Playback_lwt (libmpdclient.Mpd__Playback_lwt)

Module Mpd__Playback_lwt

Controlling playback functions in Lwt thread. https://www.musicpd.org/doc/protocol/playback_commands.html

val next : Mpd.Client_lwt.t -> Mpd.Protocol.response Lwt.t

Play next song in the playlist.

val previous : Mpd.Client_lwt.t -> Mpd.Protocol.response Lwt.t

Play previous song in the playlist.

val stop : Mpd.Client_lwt.t -> Mpd.Protocol.response Lwt.t

Stop playing.

val pause : Mpd.Client_lwt.t -> bool -> Mpd.Protocol.response Lwt.t

Toggle pause/resumers playing

val play : Mpd.Client_lwt.t -> int -> Mpd.Protocol.response Lwt.t

Begin playing the playlist at song number.

val playid : Mpd.Client_lwt.t -> int -> Mpd.Protocol.response Lwt.t

Begin playing the playlist at song id.

val seek : Mpd.Client_lwt.t -> int -> float -> Mpd.Protocol.response Lwt.t

Seek to the position time of entry songpos in the playlist.

val seekid : Mpd.Client_lwt.t -> int -> float -> Mpd.Protocol.response Lwt.t

Seek to the position time of song id.

val seekcur : Mpd.Client_lwt.t -> float -> Mpd.Protocol.response Lwt.t

Seek to the position time within the current song. TODO : If prefixed by '+' or '-', then the time is relative to the current playing position

\ No newline at end of file diff --git a/docs/Mpd__Playback_options/.dune-keep b/docs/Mpd__Playback_options/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Playback_options/index.html b/docs/Mpd__Playback_options/index.html deleted file mode 100644 index b954c27..0000000 --- a/docs/Mpd__Playback_options/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Playback_options (libmpdclient.Mpd__Playback_options)

Module Mpd__Playback_options

functions that configure all the playbackoptions

val consume : Mpd.Client.t -> bool -> Mpd.Protocol.response

Sets consume state to STATE, STATE should be false or true. When consume is activated, each song played is removed from playlist.

val crossfade : Mpd.Client.t -> int -> Mpd.Protocol.response

Sets crossfading between songs.

val mixrampdb : Mpd.Client.t -> int -> Mpd.Protocol.response

Sets the threshold at which songs will be overlapped. Like crossfading but doesn't fade the track volume, just overlaps. The songs need to have MixRamp tags added by an external tool. 0dB is the normalized maximum volume so use negative values, I prefer -17dB. In the absence of mixramp tags crossfading will be used. See http://sourceforge.net/projects/mixramp

type mixrampd_t =
| Nan
| Seconds of float

Type for the command mixrampdelay, it can be float number for seconds or nan.

val mixrampdelay : Mpd.Client.t -> mixrampd_t -> Mpd.Protocol.response

Additional time subtracted from the overlap calculated by mixrampdb. A value of "nan" disables MixRamp overlapping and falls back to crossfading.

val random : Mpd.Client.t -> bool -> Mpd.Protocol.response

Sets random state to STATE, STATE should be true or false

val repeat : Mpd.Client.t -> bool -> Mpd.Protocol.response

Sets repeat state to STATE, STATE should be false or true.

val setvol : Mpd.Client.t -> int -> Mpd.Protocol.response

Sets volume to VOL, the range of volume is 0-100.

val single : Mpd.Client.t -> bool -> Mpd.Protocol.response

Sets single state to STATE, STATE should be 0 or 1. When single is activated, playback is stopped after current song, or song is repeated if the 'repeat' mode is enabled.

type gain_mode_t =
| Off
| Track
| Album
| Auto

gain_mode type for the command replay_gain_mode.

val replay_gain_mode : Mpd.Client.t -> gain_mode_t -> Mpd.Protocol.response

Sets the replay gain mode. One of off, track, album, auto. Changing the mode during playback may take several seconds, because the new settings does not affect the buffered data. This command triggers the options idle event.

\ No newline at end of file diff --git a/docs/Mpd__Playback_options_lwt/.dune-keep b/docs/Mpd__Playback_options_lwt/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Playback_options_lwt/index.html b/docs/Mpd__Playback_options_lwt/index.html deleted file mode 100644 index 56b44a7..0000000 --- a/docs/Mpd__Playback_options_lwt/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Playback_options_lwt (libmpdclient.Mpd__Playback_options_lwt)

Module Mpd__Playback_options_lwt

functions that configure all the playbackoptions in a Lwt thread.

val consume : Mpd.Client_lwt.t -> bool -> Mpd.Protocol.response Lwt.t

Sets consume state to STATE, STATE should be false or true. When consume is activated, each song played is removed from playlist.

val crossfade : Mpd.Client_lwt.t -> int -> Mpd.Protocol.response Lwt.t

Sets crossfading between songs.

val mixrampdb : Mpd.Client_lwt.t -> int -> Mpd.Protocol.response Lwt.t

Sets the threshold at which songs will be overlapped. Like crossfading but doesn't fade the track volume, just overlaps. The songs need to have MixRamp tags added by an external tool. 0dB is the normalized maximum volume so use negative values, I prefer -17dB. In the absence of mixramp tags crossfading will be used. See http://sourceforge.net/projects/mixramp

type mixrampd_t =
| Nan
| Seconds of float

Type for the command mixrampdelay, it can be float for seconds or nan.

val mixrampdelay : Mpd.Client_lwt.t -> mixrampd_t -> Mpd.Protocol.response Lwt.t

Additional time subtracted from the overlap calculated by mixrampdb. A value of "nan" disables MixRamp overlapping and falls back to crossfading.

val random : Mpd.Client_lwt.t -> bool -> Mpd.Protocol.response Lwt.t

Sets random state to STATE, STATE should be true or false

val repeat : Mpd.Client_lwt.t -> bool -> Mpd.Protocol.response Lwt.t

Sets repeat state to STATE, STATE should be false or true.

val setvol : Mpd.Client_lwt.t -> int -> Mpd.Protocol.response Lwt.t

Sets volume to VOL, the range of volume is 0-100.

val single : Mpd.Client_lwt.t -> bool -> Mpd.Protocol.response Lwt.t

Sets single state to STATE, STATE should be 0 or 1. When single is activated, playback is stopped after current song, or song is repeated if the 'repeat' mode is enabled.

type gain_mode_t =
| Off
| Track
| Album
| Auto

gain_mode type for the command replay_gain_mode.

val replay_gain_mode : Mpd.Client_lwt.t -> gain_mode_t -> Mpd.Protocol.response Lwt.t

Sets the replay gain mode. One of off, track, album, auto. Changing the mode during playback may take several seconds, because the new settings does not affect the buffered data. This command triggers the options idle event.

\ No newline at end of file diff --git a/docs/Mpd__Protocol/.dune-keep b/docs/Mpd__Protocol/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Protocol/index.html b/docs/Mpd__Protocol/index.html deleted file mode 100644 index afecb59..0000000 --- a/docs/Mpd__Protocol/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Protocol (libmpdclient.Mpd__Protocol)

Module Mpd__Protocol

Define the Mpd response and error types

type ack_error =
| Not_list
| Arg
| Password
| Permission
| Unknown
| No_exist
| Playlist_max
| System
| Playlist_load
| Update_already
| Player_sync
| Exist

Type of error that could occur when a command is sent to the mpd server.

type response =
| Ok of string option
| Error of ack_error * int * string * string

Type of the response of the mpd server.

val error_name : ack_error -> string

Get the error name of the error type.

val str_error_to_val : string -> ack_error

Return the related type for the error returned by the server as a string.

val parse_error_response : string -> ack_error * int * string * string

Parse the error response of the mpd server into the error type.

val parse_response : string -> response

Parse the mpd server response

type mpd_response =
| Incomplete
| Complete of string * int

Type used to describe a data while reading through a socket.

val full_mpd_banner : string -> mpd_response

fetch mpd banner

val request_response : string -> mpd_response

fetch request response.

val command_response : string -> mpd_response

fetch command response.

val full_mpd_idle_event : string -> mpd_response

Get the Mpd response for an idle command.

\ No newline at end of file diff --git a/docs/Mpd__Queue/.dune-keep b/docs/Mpd__Queue/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Queue/index.html b/docs/Mpd__Queue/index.html deleted file mode 100644 index d3e257e..0000000 --- a/docs/Mpd__Queue/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Queue (libmpdclient.Mpd__Queue)

Module Mpd__Queue

Module for Mpd current playlist manipulation.

type t =
| PlaylistError of string
| Playlist of Mpd.Song.t list

Playlist type.

val add : Mpd.Client.t -> string -> Mpd.Protocol.response

Add the file URI to the playlist (directories add recursively). URI can also be a single file.

val addid : Mpd.Client.t -> string -> int -> int

Add a song to the playlist (non-recursive) and returns the song id. URI is always a single file or URL.

val clear : Mpd.Client.t -> Mpd.Protocol.response

Clear the current playlist.

val delete : Mpd.Client.t -> int -> ?⁠position_end:int -> unit -> Mpd.Protocol.response

Delete a song or a set of songs from the playlist. The song or the range of songs are identified by the position in the playlist.

val deleteid : Mpd.Client.t -> int -> Mpd.Protocol.response

Delete the song SONGID from the playlist.

val move : Mpd.Client.t -> int -> ?⁠position_end:int -> int -> unit -> Mpd.Protocol.response

Move the song at FROM or range of songs at START:END to TO in the playlist.

val moveid : Mpd.Client.t -> int -> int -> Mpd.Protocol.response

Move the song with FROM (songid) to TO (playlist index) in the playlist. If TO is negative, it is relative to the current song in the playlist (if there is one).

val playlist : Mpd.Client.t -> t

Get the songs in the playlist

val playlistid : Mpd.Client.t -> int -> (Mpd.Song.t, string) Stdlib.result

Get information for one song

val playlistfind : Mpd.Client.t -> string -> string -> t

Find songs in the current playlist with strict matching.

val playlistsearch : Mpd.Client.t -> string -> string -> t

Search case-insensitively for partial matches in the current playlist.

val swap : Mpd.Client.t -> int -> int -> Mpd.Protocol.response

Swap the positions of SONG1 and SONG2.

val shuffle : Mpd.Client.t -> ?⁠range:(int * int) -> unit -> Mpd.Protocol.response

Shuffle the current playlist. START:END is optional and specifies a range of songs.

val prio : Mpd.Client.t -> int -> ?⁠range:(int * int) -> unit -> Mpd.Protocol.response

Set the priority of the specified songs. A higher priority means that it will be played first when "random" mode is enabled. A priority is an integer between 0 and 255. The default priority of new songs is 0.

val prioid : Mpd.Client.t -> int -> int list -> Mpd.Protocol.response

Same as prio, but address the songs with their id.

val swapid : Mpd.Client.t -> int -> int -> Mpd.Protocol.response

Swap the positions of SONG1 and SONG2 (both song ids).

val rangeid : Mpd.Client.t -> int -> ?⁠range:(float * float) -> unit -> Mpd.Protocol.response

Specify the portion of the song that shall be played. START and END are offsets in seconds (fractional seconds allowed); both are optional. Omitting both (i.e. sending just ":") means "remove the range, play everything". A song that is currently playing cannot be manipulated this way.

val cleartagid : Mpd.Client.t -> int -> string -> Mpd.Protocol.response

Remove tags from the specified song. If TAG is not specified, then all tag values will be removed. Editing song tags is only possible for remote songs.

\ No newline at end of file diff --git a/docs/Mpd__Queue_lwt/.dune-keep b/docs/Mpd__Queue_lwt/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Queue_lwt/index.html b/docs/Mpd__Queue_lwt/index.html deleted file mode 100644 index 5cf5380..0000000 --- a/docs/Mpd__Queue_lwt/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Queue_lwt (libmpdclient.Mpd__Queue_lwt)

Module Mpd__Queue_lwt

Module for Mpd current playlist manipulation in Lwt threads.

type t =
| PlaylistError of string
| Playlist of Mpd.Song.t list

Playlist type

val add : Mpd.Client_lwt.t -> string -> Mpd.Protocol.response Lwt.t

Add the file URI to the playlist (directories add recursively). URI can also be a single file.

val addid : Mpd.Client_lwt.t -> string -> int -> int Lwt.t

Add a song to the playlist (non-recursive) and returns the song id. URI is always a single file or URL. For example:

val clear : Mpd.Client_lwt.t -> Mpd.Protocol.response Lwt.t

Clear the current playlist.

val delete : Mpd.Client_lwt.t -> int -> ?⁠position_end:int -> unit -> Mpd.Protocol.response Lwt.t

Delete a song or a set of songs from the playlist. The song or the range of songs are identified by the position in the playlist.

val deleteid : Mpd.Client_lwt.t -> int -> Mpd.Protocol.response Lwt.t

Delete the song SONGID from the playlist.

val move : Mpd.Client_lwt.t -> int -> ?⁠position_end:int -> int -> unit -> Mpd.Protocol.response Lwt.t

Move the song at FROM or range of songs at START:END to TO in the playlist.

val moveid : Mpd.Client_lwt.t -> int -> int -> Mpd.Protocol.response Lwt.t

Move the song with FROM (songid) to TO (playlist index) in the playlist. If TO is negative, it is relative to the current song in the playlist (if there is one).

val playlist : Mpd.Client_lwt.t -> t Lwt.t

Get a list of Song.s that represents all the songs in the current playlist.

val playlistid : Mpd.Client_lwt.t -> int -> (Mpd.Song.t, string) Stdlib.result Lwt.t

Get a list with the Song.s of the song id in the playlist

val playlistfind : Mpd.Client_lwt.t -> string -> string -> t Lwt.t

Find songs in the current playlist with strict matching.

val playlistsearch : Mpd.Client_lwt.t -> string -> string -> t Lwt.t

Search case-insensitively for partial matches in the current playlist.

val swap : Mpd.Client_lwt.t -> int -> int -> Mpd.Protocol.response Lwt.t

Swap the positions of SONG1 and SONG2.

val shuffle : Mpd.Client_lwt.t -> ?⁠range:(int * int) -> unit -> Mpd.Protocol.response Lwt.t

Shuffle the current playlist. START:END is optional and specifies a range of songs.

val prio : Mpd.Client_lwt.t -> int -> ?⁠range:(int * int) -> unit -> Mpd.Protocol.response Lwt.t

Set the priority of the specified songs. A higher priority means that it will be played first when "random" mode is enabled. A priority is an integer between 0 and 255. The default priority of new songs is 0.

val prioid : Mpd.Client_lwt.t -> int -> int list -> Mpd.Protocol.response Lwt.t

Same as prio, but address the songs with their id.

val swapid : Mpd.Client_lwt.t -> int -> int -> Mpd.Protocol.response Lwt.t

Swap the positions of SONG1 and SONG2 (both song ids).

val rangeid : Mpd.Client_lwt.t -> int -> ?⁠range:(float * float) -> unit -> Mpd.Protocol.response Lwt.t

Specify the portion of the song that shall be played. START and END are offsets in seconds (fractional seconds allowed); both are optional. Omitting both (i.e. sending just ":") means "remove the range, play everything". A song that is currently playing cannot be manipulated this way.

val cleartagid : Mpd.Client_lwt.t -> int -> string -> Mpd.Protocol.response Lwt.t

Remove tags from the specified song. If TAG is not specified, then all tag values will be removed. Editing song tags is only possible for remote songs.

\ No newline at end of file diff --git a/docs/Mpd__Song/.dune-keep b/docs/Mpd__Song/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Song/index.html b/docs/Mpd__Song/index.html deleted file mode 100644 index 82c8d3e..0000000 --- a/docs/Mpd__Song/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Song (libmpdclient.Mpd__Song)

Module Mpd__Song

Song module used to store and retrieve information of a song based on * mpd tags.

type t

Song type

val empty : t

Empty song type

val parse : string list -> t

Parse a list of song attributes to a Song.s type

val album : t -> string
val albumsort : t -> string
val albumartist : t -> string
val albumartistsort : t -> string
val artist : t -> string
val artistsort : t -> string
val comment : t -> string
val composer : t -> string
val date : t -> string
val disc : t -> string
val duration : t -> float
val file : t -> string
val genre : t -> string
val id : t -> int
val last_modified : t -> string
val name : t -> string
val performer : t -> string
val pos : t -> int
val rate : t -> int
val time : t -> int
val title : t -> string
val track : t -> string
\ No newline at end of file diff --git a/docs/Mpd__Status/.dune-keep b/docs/Mpd__Status/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Status/index.html b/docs/Mpd__Status/index.html deleted file mode 100644 index 10407cb..0000000 --- a/docs/Mpd__Status/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Status (libmpdclient.Mpd__Status)

Module Mpd__Status

Status : get informations on the current status of the Mpd server.

type t

Main status type that contains all the status information of the server.

type state =
| Play
| Pause
| Stop
| ErrState

Current state (playing, pause or stopped) of the mpd server.

val string_of_state : state -> string

Get the string representation of a state.

val parse : string list -> t

Parse list of strings into a Mpd Status type

val volume : t -> int

Get the volume level from a Mpd Status

val repeat : t -> bool

Find out if the player is in repeat mode

val random : t -> bool

Find out if the player is in random mode

val single : t -> bool

Find out if the player is in single mode

val consume : t -> bool

Find out if the player is in consume mode

val playlist : t -> int

Get the current playlist id

val playlistlength : t -> int

Get the current playlist length

val state : t -> state

Get the state of the player : Play / Pause / Stop

val song : t -> int

Get the song number of the current song stopped on or playing

val songid : t -> int

Get the song id of the current song stopped on or playing

val nextsong : t -> int

Get the next song number based on the current song stopped on or playing

val nextsongid : t -> int

Get the next song id based on the current song stopped on or playing

val time : t -> string

Get the total time elapsed (of current playing/paused song)

val elapsed : t -> float

Get the total time elapsed within the current song, but with higher resolution

val duration : t -> float

Returns the totatl duration of the current song in seconds

val bitrate : t -> int

Get the instantaneous bitrate in kbps

val xfade : t -> int

Get the crossfade in seconds of the current song

val mixrampdb : t -> float

Get the mixramp threshold in dB

val mixrampdelay : t -> float

Get the mixrampdelay in seconds

val audio : t -> string

Get information of the audio file of the current song (sampleRate:bits:channels)

val updating_db : t -> int

Get the job id

val error : t -> string

Get the error message if there is one

\ No newline at end of file diff --git a/docs/Mpd__Stored_playlists/.dune-keep b/docs/Mpd__Stored_playlists/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Stored_playlists/index.html b/docs/Mpd__Stored_playlists/index.html deleted file mode 100644 index 0516863..0000000 --- a/docs/Mpd__Stored_playlists/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Stored_playlists (libmpdclient.Mpd__Stored_playlists)

Module Mpd__Stored_playlists

Stored_playlists : Playlists are stored inside the configured playlist directory. They are addressed with their file name (without the directory and without the .m3u suffix).

val listplaylists : Mpd.Client.t -> (string list, string) Stdlib.result

Print a list of the playlist names.

val load : Mpd.Client.t -> string -> ?⁠range:(int * int) -> unit -> Mpd.Protocol.response

Load the playlist into the current queue. Playlist plugins are supported. A range may be specified to load only a part of the playlist.

val playlistadd : Mpd.Client.t -> string -> string -> Mpd.Protocol.response

Add URI to the playlist NAME.m3u. NAME.m3u will be created if it does not exist.

val playlistclear : Mpd.Client.t -> string -> Mpd.Protocol.response

Clear the playlist NAME.m3u.

val playlistdelete : Mpd.Client.t -> string -> int -> Mpd.Protocol.response

Delete SONGPOS from the playlist NAME.m3u.

val playlistmove : Mpd.Client.t -> string -> int -> int -> Mpd.Protocol.response

Move the song at position FROM in the playlist NAME.m3u to the position TO.

val rename : Mpd.Client.t -> string -> string -> Mpd.Protocol.response

Rename the playlist NAME.m3u to NEW_NAME.m3u.

val rm : Mpd.Client.t -> string -> Mpd.Protocol.response

Remove the playlist NAME.m3u from the playlist directory.

val save : Mpd.Client.t -> string -> Mpd.Protocol.response

Save the current playlist to NAME.m3u in the playlist directory.

\ No newline at end of file diff --git a/docs/Mpd__Stored_playlists_lwt/.dune-keep b/docs/Mpd__Stored_playlists_lwt/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Stored_playlists_lwt/index.html b/docs/Mpd__Stored_playlists_lwt/index.html deleted file mode 100644 index 639b775..0000000 --- a/docs/Mpd__Stored_playlists_lwt/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Stored_playlists_lwt (libmpdclient.Mpd__Stored_playlists_lwt)

Module Mpd__Stored_playlists_lwt

LwtStoredPlaylists : Playlists are stored inside the configured playlist directory. They are addressed with their file name (without the directory and without the .m3u suffix). This is module is based on Lwt.

val listplaylists : Mpd.Client_lwt.t -> (string list, string) Stdlib.result Lwt.t

Print a list of the playlist names.

val load : Mpd.Client_lwt.t -> string -> ?⁠range:(int * int) -> unit -> Mpd.Protocol.response Lwt.t

Load the playlist into the current queue. Playlist plugins are supported. A range may be specified to load only a part of the playlist.

val playlistadd : Mpd.Client_lwt.t -> string -> string -> Mpd.Protocol.response Lwt.t

Add URI to the playlist NAME.m3u. NAME.m3u will be created if it does not exist.

val playlistclear : Mpd.Client_lwt.t -> string -> Mpd.Protocol.response Lwt.t

Clear the playlist NAME.m3u.

val playlistdelete : Mpd.Client_lwt.t -> string -> int -> Mpd.Protocol.response Lwt.t

Delete SONGPOS from the playlist NAME.m3u.

val playlistmove : Mpd.Client_lwt.t -> string -> int -> int -> Mpd.Protocol.response Lwt.t

Move the song at position FROM in the playlist NAME.m3u to the position TO.

val rename : Mpd.Client_lwt.t -> string -> string -> Mpd.Protocol.response Lwt.t

Rename the playlist NAME.m3u to NEW_NAME.m3u.

val rm : Mpd.Client_lwt.t -> string -> Mpd.Protocol.response Lwt.t

Remove the playlist NAME.m3u from the playlist directory.

val save : Mpd.Client_lwt.t -> string -> Mpd.Protocol.response Lwt.t

Save the current playlist to NAME.m3u in the playlist directory.

\ No newline at end of file diff --git a/docs/Mpd__Tags/.dune-keep b/docs/Mpd__Tags/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Tags/index.html b/docs/Mpd__Tags/index.html deleted file mode 100644 index 167aeeb..0000000 --- a/docs/Mpd__Tags/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Tags (libmpdclient.Mpd__Tags)

Module Mpd__Tags

type t =
| Unknown
| Artist
| Album
| Album_artist
| Title
| Track
| Name
| Genre
| Date
| Composer
| Performer
| Comment
| Disc
| Musicbrainz_artistid
| Musicbrainz_albumid
| Musicbrainz_albumartistid
| Musicbrainz_trackid
| Musicbrainz_releasetrackid
| Original_date
| Artist_sort
| Album_artist_sort
| Album_sort
| Count
val tag_to_string : t -> string
type search_tags =
| Any
| File
| Base
| Modified_since
| Mpd_tag of t
val search_tag_to_string : search_tags -> string
val build_tag_parameter : ('a -> string) -> ('a * string) list -> string
\ No newline at end of file diff --git a/docs/Mpd__Utils/.dune-keep b/docs/Mpd__Utils/.dune-keep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/Mpd__Utils/index.html b/docs/Mpd__Utils/index.html deleted file mode 100644 index b432f2b..0000000 --- a/docs/Mpd__Utils/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Mpd__Utils (libmpdclient.Mpd__Utils)

Module Mpd__Utils

Set of helpers for the mpdlibclient library.

val remove_trailing_new_line : string -> string

Remove new line char at the end of a string.

val remove_new_lines : string -> string

Remove all new line characters in a string.

val split_lines : string -> string list

Split multiline string into a list of strings

type item_id =
| Simple of int
| Num_on_num of int * int

Type that can save the id of an element which can be an int or two int

val num_on_num_parse : string -> item_id

Split string like "8/14" to 8 and 14, returns (-1, -1) if it fails. * is used in track and disc tab of the song data

type pair = {
key : string;
value : string;
}

Create a type used when splitting a line which has the form key: value . * This type is used by Mpd.Utils.read_key_val.

val read_key_val : string -> pair

Split a line with the form "k: v" in the value of type pair

val values_of_pairs : string list -> string list

Returns all the values of a list of strings that have the key/value form.

val bool_of_int_str : string -> bool

Get a boolean value from a string number. The string "0" is false while all * other string is true.

val read_file_paths : string -> string list

Get the file path from the ouput of the command "listplaylist name"

val read_list_playlists : string -> string list

Get playlists list from output of the command "listplaylists".

exception EMusic_database of string
val parse_count_response : string -> string option -> (int * float * string) list

Get the count list from the Mpd count command.

val print_data : string -> unit
val print_data_lwt : string -> unit Lwt.t
\ No newline at end of file diff --git a/docs/index.html b/docs/index.html index d53537e..773aab0 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,2 +1,2 @@ -index (libmpdclient.index)

Library libmpdclient

The entry point of this library is the module: Mpd.

\ No newline at end of file +index (libmpdclient.index)

libmpdclient index

Library libmpdclient

The entry point of this library is the module: Mpd.

\ No newline at end of file diff --git a/docs/odoc.css b/docs/odoc.css index 3d60b5d..8b0ed5a 100644 --- a/docs/odoc.css +++ b/docs/odoc.css @@ -1,27 +1,134 @@ @charset "UTF-8"; -/* Copyright (c) 2016 Daniel C. Bünzli. All rights reserved. +/* Copyright (c) 2016 The odoc contributors. All rights reserved. Distributed under the ISC license, see terms at the end of the file. - odoc 1.3.0 */ + odoc 2.2.0 */ /* Fonts */ @import url('https://fonts.googleapis.com/css?family=Fira+Mono:400,500'); @import url('https://fonts.googleapis.com/css?family=Noticia+Text:400,400i,700'); @import url('https://fonts.googleapis.com/css?family=Fira+Sans:400,400i,500,500i,600,600i,700,700i'); +:root, +.light:root { + --main-background: #FFFFFF; + + --color: #333333; + --link-color: #2C94BD; + --anchor-hover: #555; + --anchor-color: #d5d5d5; + --xref-shadow: #cc6666; + --header-shadow: #ddd; + --by-name-version-color: #aaa; + --by-name-nav-link-color: #222; + --target-background: rgba(187, 239, 253, 0.3); + --target-shadow: rgba(187, 239, 253, 0.8); + --pre-border-color: #eee; + --code-background: #f6f8fa; + + --li-code-background: #f6f8fa; + --li-code-color: #0d2b3e; + --toc-color: #1F2D3D; + --toc-before-color: #777; + --toc-background: #f6f8fa; + --toc-list-border: #ccc; + + --spec-summary-border-color: #5c9cf5; + --spec-summary-background: var(--code-background); + --spec-summary-hover-background: #ebeff2; + --spec-details-after-background: rgba(0, 4, 15, 0.05); + --spec-details-after-shadow: rgba(204, 204, 204, 0.53); +} + +.dark:root { + --main-background: #202020; + --code-background: #222; + --line-numbers-background: rgba(0, 0, 0, 0.125); + --navbar-background: #202020; + + --color: #bebebe; + --dirname-color: #666; + --underline-color: #444; + --visited-color: #002800; + --visited-number-color: #252; + --unvisited-color: #380000; + --unvisited-number-color: #622; + --somevisited-color: #303000; + --highlight-color: #303e3f; + --line-number-color: rgba(230, 230, 230, 0.3); + --unvisited-margin-color: #622; + --border: #333; + --navbar-border: #333; + --code-color: #ccc; + + --li-code-background: #373737; + --li-code-color: #999; + --toc-color: #777; + --toc-background: #252525; + + --hljs-link: #999; + --hljs-keyword: #cda869; + --hljs-regexp: #f9ee98; + --hljs-title: #dcdcaa; + --hljs-type: #ac885b; + --hljs-meta: #82aaff; + --hljs-variable: #cf6a4c; +} + +@media (prefers-color-scheme: dark) { + :root { + --main-background: #202020; + --code-background: #333; + --line-numbers-background: rgba(0, 0, 0, 0.125); + --navbar-background: #202020; + + --meter-unvisited-color: #622; + --meter-visited-color: #252; + --meter-separator-color: black; + + --color: #bebebe; + --dirname-color: #666; + --underline-color: #444; + --visited-color: #002800; + --visited-number-color: #252; + --unvisited-color: #380000; + --unvisited-number-color: #622; + --somevisited-color: #303000; + --highlight-color: #303e3f; + --line-number-color: rgba(230, 230, 230, 0.3); + --unvisited-margin-color: #622; + --border: #333; + --navbar-border: #333; + --code-color: #ccc; + --by-name-nav-link-color: var(--color); + + --li-code-background: #373737; + --li-code-color: #999; + --toc-color: #777; + --toc-before-color: #777; + --toc-background: #252525; + --toc-list-border: #ccc; + --spec-summary-hover-background: #ebeff2; + --spec-details-after-background: rgba(0, 4, 15, 0.05); + --spec-details-after-shadow: rgba(204, 204, 204, 0.53); + + --hljs-link: #999; + --hljs-keyword: #cda869; + --hljs-regexp: #f9ee98; + --hljs-title: #dcdcaa; + --hljs-type: #ac885b; + --hljs-meta: #82aaff; + --hljs-variable: #cf6a4c; + } +} /* Reset a few things. */ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { - margin: 0; padding: 0; border: 0; - font-size: inherit; font: inherit; - line-height: inherit; vertical-align: baseline; - text-align: inherit; - color: inherit; - background: transparent; + } table { @@ -38,14 +145,14 @@ html { } body { - font-family: "Fira Sans", Helvetica, Arial, sans-serif; text-align: left; - color: #333; background: #FFFFFF; + color: var(--color); + background-color: var(--main-background); } -.content { - max-width: 90ex; +body { + max-width: 100ex; margin-left: calc(10vw + 20ex); margin-right: 4ex; margin-top: 20px; @@ -54,24 +161,32 @@ body { line-height: 1.5; } -.content>header { +header { margin-bottom: 30px; } -.content>header nav { +nav { font-family: "Fira Sans", Helvetica, Arial, sans-serif; } /* Basic markup elements */ b, strong { - font-weight: 500; + font-weight: bold; +} + +i { + font-style: italic; } -i, em { +em, i em.odd{ font-style: italic; } +em.odd, i em { + font-style: normal; +} + sup { vertical-align: super; } @@ -86,15 +201,6 @@ sup, sub { margin-left: 0.2ex; } -pre { - margin-top: 0.8em; - margin-bottom: 1.2em; -} - -p, ul, ol { - margin-top: 0.5em; - margin-bottom: 1em; -} ul, ol { list-style-position: outside } @@ -129,32 +235,32 @@ li>*:first-child { a { text-decoration: none; - color: #2C5CBD; + color: var(--link-color); } a:hover { - box-shadow: 0 1px 0 0 #2C5CBD; + box-shadow: 0 1px 0 0 var(--link-color); } /* Linked highlight */ *:target { - background-color: rgba(187,239,253,0.3) !important; - box-shadow: 0 0px 0 1px rgba(187,239,253,0.8) !important; + background-color: var(--target-background) !important; + box-shadow: 0 0px 0 1px var(--target-shadow) !important; border-radius: 1px; } -*:hover>a.anchor { +*:hover > a.anchor { visibility: visible; } a.anchor:before { - content: "#" + content: "#"; } a.anchor:hover { box-shadow: none; text-decoration: none; - color: #555; + color: var(--anchor-hover); } a.anchor { @@ -168,7 +274,7 @@ a.anchor { padding-right: 0.4em; padding-left: 0.4em; /* To remain selectable */ - color: #d5d5d5; + color: var(--anchor-color); } .spec > a.anchor { @@ -177,10 +283,10 @@ a.anchor { } .xref-unresolved { - color: #2C5CBD; + color: #2C94BD; } .xref-unresolved:hover { - box-shadow: 0 1px 0 0 #CC6666; + box-shadow: 0 1px 0 0 var(--xref-shadow); } /* Section and document divisions. @@ -190,7 +296,6 @@ a.anchor { h1, h2, h3, h4, h5, h6, .h7, .h8, .h9, .h10 { font-family: "Fira Sans", Helvetica, Arial, sans-serif; font-weight: 400; - margin: 0.5em 0 0.5em 0; padding-top: 0.1em; line-height: 1.2; overflow-wrap: break-word; @@ -199,20 +304,19 @@ h1, h2, h3, h4, h5, h6, .h7, .h8, .h9, .h10 { h1 { font-weight: 500; font-size: 2.441em; - margin-top: 1.214em; } -h2 { +h1 { font-weight: 500; font-size: 1.953em; - box-shadow: 0 1px 0 0 #ddd; + box-shadow: 0 1px 0 0 var(--header-shadow); } -h3 { +h2 { font-size: 1.563em; } -h4 { +h3 { font-size: 1.25em; } @@ -235,34 +339,60 @@ h3 code, h3 tt { font-weight: inherit; } -h4 code, h4 tt { +h3 code, h3 tt { font-size: inherit; font-weight: inherit; } +h4 { + font-size: 1.12em; +} + +/* Comment delimiters, hidden but accessible to screen readers and + selected for copy/pasting */ + +/* Taken from bootstrap */ +/* See also https://stackoverflow.com/a/27769435/4220738 */ +.comment-delim { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + /* Preformatted and code */ tt, code, pre { - font-family: "Fira Code", "Fira Mono", courier; + font-family: "Fira Mono", courier; font-weight: 400; } pre { padding: 0.1em; - border: 1px solid #eee; + border: 1px solid var(--pre-border-color); border-radius: 5px; overflow-x: auto; } -p code, li code { - background-color: #f6f8fa; - color: #0d2b3e; +p code, +li code { + background-color: var(--li-code-background); + color: var(--li-code-color); border-radius: 3px; padding: 0 0.3ex; } p a > code { - color: #2C5CBD; + color: var(--link-color); +} + +code { + white-space: pre-wrap; } /* Code blocks (e.g. Examples) */ @@ -274,64 +404,59 @@ pre code { /* Code lexemes */ .keyword { - font-weight: 700; + font-weight: 500; } +.arrow { white-space: nowrap } + /* Module member specification */ -.spec:not(.include), .spec.include details summary { - background-color: #f6f8fa; +.spec { + background-color: var(--spec-summary-background); border-radius: 3px; - border-left: 4px solid #5c9cf5; + border-left: 4px solid var(--spec-summary-border-color); border-right: 5px solid transparent; padding: 0.35em 0.5em; } -.spec.include details summary:hover { - background-color: #ebeff2; +li:not(:last-child) > .def-doc { + margin-bottom: 15px; } -dl, div.spec, .doc, aside { - margin-bottom: 20px; +/* Spacing between items */ +div.odoc-spec,.odoc-include { + margin-bottom: 2em; } -/* Indent the second line in multiline spec definitions. */ -.spec:not(.type) > code { - display: block; - padding-left: 4ex; - text-indent: -4ex; +.spec.type .variant p, .spec.type .record p { + margin: 5px; } -.spec.exception > code { - display: inline-block; +.spec.type .variant, .spec.type .record { + margin-left: 2ch; + list-style: none; + display: flex; + flex-wrap: wrap; + row-gap: 4px; } -dl > dd { - padding: 0.5em; +.spec.type .record > code, .spec.type .variant > code { + min-width: 40%; } -dd> :first-child { +.spec.type > ol { margin-top: 0; -} - -dl:last-child, dd> :last-child, aside:last-child, article:last-child { margin-bottom: 0; } -dt+dt { - margin-top: 15px; -} - -section+section, section > header + dl { - margin-top: 25px; -} - -.spec.type .variant { - margin-left: 2ch; -} -.spec.type .variant p { - margin: 0; - font-style: italic; +.spec.type .record > .def-doc, .spec.type .variant > .def-doc { + min-width:50%; + padding: 0.25em 0.5em; + margin-left: 10%; + border-radius: 3px; + flex-grow:1; + background: var(--main-background); + box-shadow: 2px 2px 4px lightgrey; } div.def { @@ -340,27 +465,21 @@ div.def { padding-left: 2ex; } -div.def+div.doc { - margin-left: 1ex; - margin-top: 2.5px -} - -div.doc>*:first-child { +div.def-doc>*:first-child { margin-top: 0; } -/* The elements other than heading should be wrapped in