1
1
{-# LANGUAGE OverloadedStrings #-}
2
2
{-# LANGUAGE ForeignFunctionInterface #-}
3
+ {-# LANGUAGE DeriveGeneric #-}
4
+ {-# LANGUAGE GeneralizedNewtypeDeriving #-}
3
5
4
6
module Sound.Tidal.Parse.FFI where
5
7
@@ -10,39 +12,47 @@ import qualified Data.ByteString.Lazy.Char8 as B
10
12
import qualified Data.Map.Strict as Map
11
13
import Data.Maybe (fromMaybe )
12
14
import Text.Read (readMaybe )
13
- import Data.Ratio ( (%) )
15
+ import GHC.Generics ( Generic )
14
16
15
17
import Sound.Tidal.Parse (parseTidal )
16
- import Sound.Tidal.Context
17
- import Sound.Tidal.Pattern (Value )
18
- import Sound.Tidal.Show (show )
19
-
20
- -- Ensure Tidal's `Value` is converted to JSON properly
21
- instance ToJSON Value where
22
- toJSON (VS s) = toJSON s
23
- toJSON (VI i) = toJSON i
24
- toJSON (VF f) = toJSON f
25
- toJSON (VN n) = toJSON $ show n
26
- toJSON (VR r) = toJSON $ show r
27
- toJSON (VB b) = toJSON b
28
- toJSON (VX xs) = toJSON xs
29
- toJSON (VPattern pat) = toJSON $ show pat
30
- toJSON (VState f) = toJSON $ show $ f Map. empty
31
- toJSON (VList vs) = toJSON vs
32
-
33
- -- JSON serialization for ArcF
34
- instance (Real a ) => ToJSON (ArcF a ) where
35
- toJSON (Arc start stop) =
36
- object [" start" .= (realToFrac start :: Double ),
37
- " stop" .= (realToFrac stop :: Double )]
38
-
39
- -- JSON serialization for EventF
40
- instance (ToJSON a , ToJSON b ) => ToJSON (EventF a b ) where
41
- toJSON (Event ctx whole part value) =
42
- object [ " whole" .= whole
43
- , " part" .= part
44
- , " value" .= value
45
- ]
18
+ import Sound.Tidal.Pattern
19
+ import Sound.Tidal.Params ()
20
+ import Sound.Tidal.Show ()
21
+
22
+ -- Newtype wrappers to avoid orphan instances
23
+ newtype JSONValue = JSONValue { unJSONValue :: Value }
24
+ deriving (Generic )
25
+
26
+ instance ToJSON JSONValue where
27
+ toJSON (JSONValue (VS str)) = toJSON str
28
+ toJSON (JSONValue (VI i)) = toJSON i
29
+ toJSON (JSONValue (VF f)) = toJSON f
30
+ toJSON (JSONValue (VN num)) = toJSON $ show num
31
+ toJSON (JSONValue (VR r)) = toJSON $ show r
32
+ toJSON (JSONValue (VB b)) = toJSON b
33
+ toJSON (JSONValue (VX xs)) = toJSON xs
34
+ toJSON (JSONValue (VPattern pat)) = toJSON $ show pat
35
+ toJSON (JSONValue (VState f)) = toJSON $ show $ f Map. empty
36
+ toJSON (JSONValue (VList vs)) = toJSON $ map JSONValue vs
37
+
38
+ newtype JSONArcF = JSONArcF (ArcF Rational )
39
+ deriving (Generic )
40
+
41
+ instance ToJSON JSONArcF where
42
+ toJSON (JSONArcF (Arc arcStart arcStop)) =
43
+ object [" start" .= (realToFrac arcStart :: Double ),
44
+ " stop" .= (realToFrac arcStop :: Double )]
45
+
46
+ newtype JSONEventF = JSONEventF (Event (Map. Map String Value ))
47
+ deriving (Generic )
48
+
49
+ instance ToJSON JSONEventF where
50
+ toJSON (JSONEventF (Event _ctx evWhole evPart evValue)) =
51
+ object [ " whole" .= fmap JSONArcF evWhole -- Handle Maybe
52
+ , " part" .= JSONArcF evPart
53
+ , " value" .= fmap JSONValue evValue ]
54
+
55
+
46
56
47
57
-- Foreign export wrapper function
48
58
foreign export ccall eval_pattern_c :: CString -> CString -> IO CString
@@ -65,7 +75,7 @@ encodeError err = Aeson.object ["error" Aeson..= err]
65
75
66
76
encodeSuccess :: Double -> [Event (Map. Map String Value )] -> Aeson. Value
67
77
encodeSuccess arcLen events =
68
- Aeson. object [" arcLen" .= arcLen, " events" .= events]
78
+ Aeson. object [" arcLen" .= arcLen, " events" .= map JSONEventF events]
69
79
70
80
-- Helper functions to handle parsing and querying
71
81
parseAndQuery :: String -> Double -> Either String [Event (Map. Map String Value )]
0 commit comments