Skip to content

Commit

Permalink
Reformat updated Stream files
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewkaney committed Feb 1, 2025
1 parent 36ea2ec commit 77a6c28
Show file tree
Hide file tree
Showing 8 changed files with 658 additions and 569 deletions.
46 changes: 24 additions & 22 deletions src/Sound/Tidal/Stream/Config.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
module Sound.Tidal.Stream.Config where

import Control.Monad (when)

import Control.Monad (when)
import qualified Sound.Tidal.Clock as Clock

{-
Expand All @@ -22,28 +21,31 @@ import qualified Sound.Tidal.Clock as Clock
along with this library. If not, see <http://www.gnu.org/licenses/>.
-}

data Config = Config {cCtrlListen :: Bool,
cCtrlAddr :: String,
cCtrlPort :: Int,
cCtrlBroadcast :: Bool,
-- cTempoAddr :: String,
-- cTempoPort :: Int,
-- cTempoClientPort :: Int,
cVerbose :: Bool,
cClockConfig :: Clock.ClockConfig
}
data Config = Config
{ cCtrlListen :: Bool,
cCtrlAddr :: String,
cCtrlPort :: Int,
cCtrlBroadcast :: Bool,
-- cTempoAddr :: String,
-- cTempoPort :: Int,
-- cTempoClientPort :: Int,
cVerbose :: Bool,
cClockConfig :: Clock.ClockConfig
}

defaultConfig :: Config
defaultConfig = Config {cCtrlListen = True,
cCtrlAddr ="127.0.0.1",
cCtrlPort = 6010,
cCtrlBroadcast = False,
-- cTempoAddr = "127.0.0.1",
-- cTempoPort = 9160,
-- cTempoClientPort = 0, -- choose at random
cVerbose = True,
cClockConfig = Clock.defaultConfig
}
defaultConfig =
Config
{ cCtrlListen = True,
cCtrlAddr = "127.0.0.1",
cCtrlPort = 6010,
cCtrlBroadcast = False,
-- cTempoAddr = "127.0.0.1",
-- cTempoPort = 9160,
-- cTempoClientPort = 0, -- choose at random
cVerbose = True,
cClockConfig = Clock.defaultConfig
}

verbose :: Config -> String -> IO ()
verbose c s = when (cVerbose c) $ putStrLn s
138 changes: 71 additions & 67 deletions src/Sound/Tidal/Stream/Listen.hs
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
module Sound.Tidal.Stream.Listen where

import Control.Concurrent.MVar
import qualified Control.Exception as E
import Control.Monad (when)
import qualified Data.Map as Map
import Data.Maybe (fromJust)
import qualified Network.Socket as N
import qualified Sound.Osc.Fd as O
import System.IO (hPutStrLn, stderr)

import Sound.Tidal.ID
import Sound.Tidal.Pattern

import Sound.Tidal.Stream.Config
import Sound.Tidal.Stream.Types
import Sound.Tidal.Stream.UI
import Control.Concurrent.MVar
import qualified Control.Exception as E
import Control.Monad (when)
import qualified Data.Map as Map
import Data.Maybe (fromJust)
import qualified Network.Socket as N
import qualified Sound.Osc.Fd as O
import Sound.Tidal.ID
import Sound.Tidal.Pattern
import Sound.Tidal.Stream.Config
import Sound.Tidal.Stream.Types
import Sound.Tidal.Stream.UI
import System.IO (hPutStrLn, stderr)

{-
Listen.hs - logic for listening and acting on incoming OSC messages
Expand All @@ -34,63 +32,69 @@ import Sound.Tidal.Stream.UI
along with this library. If not, see <http://www.gnu.org/licenses/>.
-}


openListener :: Config -> IO (Maybe O.Udp)
openListener c
| cCtrlListen c = catchAny run (\_ -> do verbose c "That port isn't available, perhaps another Tidal instance is already listening on that port?"
return Nothing
)
| otherwise = return Nothing
| cCtrlListen c =
catchAny
run
( \_ -> do
verbose c "That port isn't available, perhaps another Tidal instance is already listening on that port?"
return Nothing
)
| otherwise = return Nothing
where
run = do sock <- O.udpServer (cCtrlAddr c) (cCtrlPort c)
when (cCtrlBroadcast c) $ N.setSocketOption (O.udpSocket sock) N.Broadcast 1
return $ Just sock
catchAny :: IO a -> (E.SomeException -> IO a) -> IO a
catchAny = E.catch
run = do
sock <- O.udpServer (cCtrlAddr c) (cCtrlPort c)
when (cCtrlBroadcast c) $ N.setSocketOption (O.udpSocket sock) N.Broadcast 1
return $ Just sock
catchAny :: IO a -> (E.SomeException -> IO a) -> IO a
catchAny = E.catch

-- Listen to and act on OSC control messages
ctrlResponder :: Config -> Stream -> IO ()
ctrlResponder _ (stream@(Stream {sListen = Just sock})) = loop
where
loop :: IO ()
loop = do O.recvMessages sock >>= mapM_ act
loop
-- External controller commands
act :: O.Message -> IO ()
act (O.Message "/ctrl" (O.Int32 k:v:[]))
= act (O.Message "/ctrl" [O.string $ show k,v])
act (O.Message "/ctrl" (O.AsciiString k:v@(O.Float _):[]))
= add (O.ascii_to_string k) (VF (fromJust $ O.datum_floating v))
act (O.Message "/ctrl" (O.AsciiString k:O.AsciiString v:[]))
= add (O.ascii_to_string k) (VS (O.ascii_to_string v))
act (O.Message "/ctrl" (O.AsciiString k:O.Int32 v:[]))
= add (O.ascii_to_string k) (VI (fromIntegral v))
-- Stream playback commands
act (O.Message "/mute" (k:[]))
= withID k $ streamMute stream
act (O.Message "/unmute" (k:[]))
= withID k $ streamUnmute stream
act (O.Message "/solo" (k:[]))
= withID k $ streamSolo stream
act (O.Message "/unsolo" (k:[]))
= withID k $ streamUnsolo stream
act (O.Message "/muteAll" [])
= streamMuteAll stream
act (O.Message "/unmuteAll" [])
= streamUnmuteAll stream
act (O.Message "/unsoloAll" [])
= streamUnsoloAll stream
act (O.Message "/hush" [])
= streamHush stream
act (O.Message "/silence" (k:[]))
= withID k $ streamSilence stream
act m = hPutStrLn stderr $ "Unhandled OSC: " ++ show m
add :: String -> Value -> IO ()
add k v = do sMap <- takeMVar (sStateMV stream)
putMVar (sStateMV stream) $ Map.insert k v sMap
return ()
withID :: O.Datum -> (ID -> IO ()) -> IO ()
withID (O.AsciiString k) func = func $ (ID . O.ascii_to_string) k
withID (O.Int32 k) func = func $ (ID . show) k
withID _ _ = return ()
where
loop :: IO ()
loop = do
O.recvMessages sock >>= mapM_ act
loop
-- External controller commands
act :: O.Message -> IO ()
act (O.Message "/ctrl" (O.Int32 k : v : [])) =
act (O.Message "/ctrl" [O.string $ show k, v])
act (O.Message "/ctrl" (O.AsciiString k : v@(O.Float _) : [])) =
add (O.ascii_to_string k) (VF (fromJust $ O.datum_floating v))
act (O.Message "/ctrl" (O.AsciiString k : O.AsciiString v : [])) =
add (O.ascii_to_string k) (VS (O.ascii_to_string v))
act (O.Message "/ctrl" (O.AsciiString k : O.Int32 v : [])) =
add (O.ascii_to_string k) (VI (fromIntegral v))
-- Stream playback commands
act (O.Message "/mute" (k : [])) =
withID k $ streamMute stream
act (O.Message "/unmute" (k : [])) =
withID k $ streamUnmute stream
act (O.Message "/solo" (k : [])) =
withID k $ streamSolo stream
act (O.Message "/unsolo" (k : [])) =
withID k $ streamUnsolo stream
act (O.Message "/muteAll" []) =
streamMuteAll stream
act (O.Message "/unmuteAll" []) =
streamUnmuteAll stream
act (O.Message "/unsoloAll" []) =
streamUnsoloAll stream
act (O.Message "/hush" []) =
streamHush stream
act (O.Message "/silence" (k : [])) =
withID k $ streamSilence stream
act m = hPutStrLn stderr $ "Unhandled OSC: " ++ show m
add :: String -> Value -> IO ()
add k v = do
sMap <- takeMVar (sStateMV stream)
putMVar (sStateMV stream) $ Map.insert k v sMap
return ()
withID :: O.Datum -> (ID -> IO ()) -> IO ()
withID (O.AsciiString k) func = func $ (ID . O.ascii_to_string) k
withID (O.Int32 k) func = func $ (ID . show) k
withID _ _ = return ()
ctrlResponder _ _ = return ()
79 changes: 39 additions & 40 deletions src/Sound/Tidal/Stream/Main.hs
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
module Sound.Tidal.Stream.Main where

import Control.Concurrent
import Control.Concurrent.MVar
import qualified Data.Map as Map
import qualified Sound.Tidal.Clock as Clock
import System.IO (hPutStrLn, stderr)


import Sound.Tidal.Stream.Config
import Sound.Tidal.Stream.Listen
import Sound.Tidal.Stream.Process
import Sound.Tidal.Stream.Target
import Sound.Tidal.Stream.Types
import Sound.Tidal.Version (tidal_status_string)
import Control.Concurrent
import Control.Concurrent.MVar

Check warning on line 4 in src/Sound/Tidal/Stream/Main.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.6.5

The import of ‘Control.Concurrent.MVar’ is redundant

Check warning on line 4 in src/Sound/Tidal/Stream/Main.hs

View workflow job for this annotation

GitHub Actions / cabal latest - ghc latest

The import of ‘Control.Concurrent.MVar’ is redundant

Check warning on line 4 in src/Sound/Tidal/Stream/Main.hs

View workflow job for this annotation

GitHub Actions / cabal 3.8.1.0 - ghc 9.4.1

The import of ‘Control.Concurrent.MVar’ is redundant

Check warning on line 4 in src/Sound/Tidal/Stream/Main.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.8.3

The import of ‘Control.Concurrent.MVar’ is redundant

Check warning on line 4 in src/Sound/Tidal/Stream/Main.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 8.10.1

The import of ‘Control.Concurrent.MVar’ is redundant

Check warning on line 4 in src/Sound/Tidal/Stream/Main.hs

View workflow job for this annotation

GitHub Actions / cabal 3.4.0.0 - ghc 9.0.1

The import of ‘Control.Concurrent.MVar’ is redundant
import qualified Data.Map as Map
import qualified Sound.Tidal.Clock as Clock
import Sound.Tidal.Stream.Config
import Sound.Tidal.Stream.Listen
import Sound.Tidal.Stream.Process
import Sound.Tidal.Stream.Target
import Sound.Tidal.Stream.Types
import Sound.Tidal.Version (tidal_status_string)
import System.IO (hPutStrLn, stderr)

{-
Main.hs - Start tidals stream, listen and act on incoming messages
Expand All @@ -32,7 +30,6 @@ import Sound.Tidal.Version (tidal_status_string)
along with this library. If not, see <http://www.gnu.org/licenses/>.
-}


-- Start an instance of Tidal with superdirt OSC
startTidal :: Target -> Config -> IO Stream
startTidal target config = startStream config [(target, [superdirtShape])]
Expand All @@ -42,32 +39,34 @@ startTidal target config = startStream config [(target, [superdirtShape])]
-- Spawns a thread that listens to and acts on OSC control messages
startStream :: Config -> [(Target, [OSC])] -> IO Stream
startStream config oscmap = do
sMapMV <- newMVar Map.empty
pMapMV <- newMVar Map.empty
globalFMV <- newMVar id

tidal_status_string >>= verbose config
verbose config $ "Listening for external controls on " ++ cCtrlAddr config ++ ":" ++ show (cCtrlPort config)
listen <- openListener config

cxs <- getCXs config oscmap

clockRef <- Clock.clocked (cClockConfig config) (doTick sMapMV pMapMV globalFMV cxs)

let stream = Stream {sConfig = config,
sStateMV = sMapMV,
sClockRef = clockRef,
-- sLink = abletonLink,
sListen = listen,
sPMapMV = pMapMV,
-- sActionsMV = actionsMV,
sGlobalFMV = globalFMV,
sCxs = cxs
}

-- Spawn a thread to handle OSC control messages
_ <- forkIO $ ctrlResponder config stream
return stream
sMapMV <- newMVar Map.empty
pMapMV <- newMVar Map.empty
globalFMV <- newMVar id

tidal_status_string >>= verbose config
verbose config $ "Listening for external controls on " ++ cCtrlAddr config ++ ":" ++ show (cCtrlPort config)
listen <- openListener config

cxs <- getCXs config oscmap

clockRef <- Clock.clocked (cClockConfig config) (doTick sMapMV pMapMV globalFMV cxs)

let stream =
Stream
{ sConfig = config,
sStateMV = sMapMV,
sClockRef = clockRef,
-- sLink = abletonLink,
sListen = listen,
sPMapMV = pMapMV,
-- sActionsMV = actionsMV,
sGlobalFMV = globalFMV,
sCxs = cxs
}

-- Spawn a thread to handle OSC control messages
_ <- forkIO $ ctrlResponder config stream
return stream

startMulti :: [Target] -> Config -> IO ()
startMulti _ _ = hPutStrLn stderr $ "startMulti has been removed, please check the latest documentation on tidalcycles.org"
Loading

0 comments on commit 77a6c28

Please sign in to comment.