-- | scsynth server command-line options.
module Sound.SC3.Server.Options where

import Data.List {- base -}

-- | (SHORT-OPTION,LONG-OPTION,DEFAULT-VALUE)
type SC3_OPT i = (Char,String,i)

-- | Get value from option.
sc3_opt_value :: SC3_OPT i -> i
sc3_opt_value :: SC3_OPT i -> i
sc3_opt_value (Char
_,String
_,i
v) = i
v

-- | Default address string.
sc3_addr_def :: String
sc3_addr_def :: String
sc3_addr_def = String
"127.0.0.1"

-- | Default port number, either a 'u' or a 't' option is required.
sc3_port_def :: Num i => i
sc3_port_def :: i
sc3_port_def = i
57110

-- | Protocol is either UDP or TCP.
data SC3_PROTOCOL = SC3_UDP | SC3_TCP

-- | Default port option.
sc3_opt_port_def :: Num i => SC3_PROTOCOL -> SC3_OPT i
sc3_opt_port_def :: SC3_PROTOCOL -> SC3_OPT i
sc3_opt_port_def SC3_PROTOCOL
p =
  case SC3_PROTOCOL
p of
    SC3_PROTOCOL
SC3_UDP -> (Char
'u',String
"udp-port-number",i
forall i. Num i => i
sc3_port_def)
    SC3_PROTOCOL
SC3_TCP -> (Char
't',String
"tcp-port-number",i
forall i. Num i => i
sc3_port_def)

-- | SC3 default options.
sc3_opt_def :: Num i => SC3_PROTOCOL -> [SC3_OPT i]
sc3_opt_def :: SC3_PROTOCOL -> [SC3_OPT i]
sc3_opt_def SC3_PROTOCOL
p =
  SC3_PROTOCOL -> SC3_OPT i
forall i. Num i => SC3_PROTOCOL -> SC3_OPT i
sc3_opt_port_def SC3_PROTOCOL
p SC3_OPT i -> [SC3_OPT i] -> [SC3_OPT i]
forall a. a -> [a] -> [a]
:
  [(Char
'a',String
"number-of-audio-bus-channels",i
1024)
  ,(Char
'b',String
"number-of-sample-buffers",i
1024)
  --,('B',"bind-to-address","127.0.0.1")
  ,(Char
'c',String
"number-of-control-bus-channels",i
16384)
  ,(Char
'D',String
"load-synthdefs?",i
1)
  ,(Char
'd',String
"max-number-of-synth-defs",i
1024)
  ,(Char
'i',String
"number-of-input-bus-channels",i
8)
  ,(Char
'l',String
"max-logins",i
64)
  ,(Char
'm',String
"real-time-memory-size",i
8192)
  ,(Char
'n',String
"max-number-of-nodes",i
1024)
  ,(Char
'o',String
"number-of-output-bus-channels",i
8)
  ,(Char
'r',String
"number-of-random-seeds",i
64)
  ,(Char
'R',String
"publish-to-rendezvous?",i
1)
  ,(Char
'S',String
"hardware-sample-rate",i
0)
  ,(Char
'V',String
"verbosity",i
0)
  ,(Char
'w',String
"number-of-wire-buffers",i
64)
  ,(Char
'z',String
"block-size",i
64)
  ,(Char
'Z',String
"hardware-buffer-size",i
0)]

-- | SC3 default options for UDP.
sc3_opt_def_udp :: Num i => [SC3_OPT i]
sc3_opt_def_udp :: [SC3_OPT i]
sc3_opt_def_udp = SC3_PROTOCOL -> [SC3_OPT i]
forall i. Num i => SC3_PROTOCOL -> [SC3_OPT i]
sc3_opt_def SC3_PROTOCOL
SC3_UDP

-- | Is option boolean, ie. 0=FALSE and 1=TRUE.
--
-- > filter sc3_opt_bool sc3_opt_def_udp
sc3_opt_bool :: SC3_OPT i -> Bool
sc3_opt_bool :: SC3_OPT i -> Bool
sc3_opt_bool (Char
_,String
s,i
_) = String -> Char
forall a. [a] -> a
last String
s Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'?'

-- | Lookup option given either short or long name.
sc3_opt_get :: [SC3_OPT i] -> Either Char String -> Maybe i
sc3_opt_get :: [SC3_OPT i] -> Either Char String -> Maybe i
sc3_opt_get [SC3_OPT i]
opt Either Char String
k =
  case Either Char String
k of
    Left Char
c -> (SC3_OPT i -> i) -> Maybe (SC3_OPT i) -> Maybe i
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SC3_OPT i -> i
forall i. SC3_OPT i -> i
sc3_opt_value ((SC3_OPT i -> Bool) -> [SC3_OPT i] -> Maybe (SC3_OPT i)
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (\(Char
o,String
_,i
_) -> Char
o Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
c) [SC3_OPT i]
opt)
    Right String
s -> (SC3_OPT i -> i) -> Maybe (SC3_OPT i) -> Maybe i
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SC3_OPT i -> i
forall i. SC3_OPT i -> i
sc3_opt_value ((SC3_OPT i -> Bool) -> [SC3_OPT i] -> Maybe (SC3_OPT i)
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (\(Char
_,String
o,i
_) -> String
o String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
s) [SC3_OPT i]
opt)

-- | Set option given either short or long name.
--
-- > sc3_opt_set sc3_opt_def_udp (Left 'w',256)
sc3_opt_set :: [SC3_OPT i] -> (Either Char String,i) -> [SC3_OPT i]
sc3_opt_set :: [SC3_OPT i] -> (Either Char String, i) -> [SC3_OPT i]
sc3_opt_set [SC3_OPT i]
opt (Either Char String
k,i
v) =
  case Either Char String
k of
    Left Char
x -> (SC3_OPT i -> SC3_OPT i) -> [SC3_OPT i] -> [SC3_OPT i]
forall a b. (a -> b) -> [a] -> [b]
map (\(Char
c,String
s,i
y) -> if Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
x then (Char
c,String
s,i
v) else (Char
c,String
s,i
y)) [SC3_OPT i]
opt
    Right String
x -> (SC3_OPT i -> SC3_OPT i) -> [SC3_OPT i] -> [SC3_OPT i]
forall a b. (a -> b) -> [a] -> [b]
map (\(Char
c,String
s,i
y) -> if String
s String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
x then (Char
c,String
s,i
v) else (Char
c,String
s,i
y)) [SC3_OPT i]
opt

-- | Apply set of edits to options.
--
-- > sc3_opt_edit sc3_opt_def_udp [(Left 'w',256),(Left 'm',2 ^ 16)]
sc3_opt_edit :: [SC3_OPT i] -> [(Either Char String,i)] -> [SC3_OPT i]
sc3_opt_edit :: [SC3_OPT i] -> [(Either Char String, i)] -> [SC3_OPT i]
sc3_opt_edit [SC3_OPT i]
opt [(Either Char String, i)]
edt =
  case [(Either Char String, i)]
edt of
    [] -> [SC3_OPT i]
opt
    (Either Char String, i)
x:[(Either Char String, i)]
rst -> [SC3_OPT i] -> [(Either Char String, i)] -> [SC3_OPT i]
forall i. [SC3_OPT i] -> [(Either Char String, i)] -> [SC3_OPT i]
sc3_opt_edit ([SC3_OPT i] -> (Either Char String, i) -> [SC3_OPT i]
forall i. [SC3_OPT i] -> (Either Char String, i) -> [SC3_OPT i]
sc3_opt_set [SC3_OPT i]
opt (Either Char String, i)
x) [(Either Char String, i)]
rst

-- | Generate scsynth argument list.
--
-- > unwords (sc3_opt_arg sc3_opt_def_udp)
sc3_opt_arg :: Show i => [SC3_OPT i] -> [String]
sc3_opt_arg :: [SC3_OPT i] -> [String]
sc3_opt_arg = (SC3_OPT i -> [String]) -> [SC3_OPT i] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\(Char
c,String
_,i
v) -> [[Char
'-',Char
c],i -> String
forall a. Show a => a -> String
show i
v])

-- | Generate arguments for 'System.Process.callProcess' or related functions.
--
-- > sc3_opt_cmd sc3_opt_def_udp
sc3_opt_cmd :: Show i => [SC3_OPT i] -> (FilePath,[String])
sc3_opt_cmd :: [SC3_OPT i] -> (String, [String])
sc3_opt_cmd [SC3_OPT i]
opt = (String
"scsynth",[SC3_OPT i] -> [String]
forall i. Show i => [SC3_OPT i] -> [String]
sc3_opt_arg [SC3_OPT i]
opt)