summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2015-12-04 11:12:17 -0500
committerAndrew Cady <d@jerkface.net>2015-12-04 11:12:17 -0500
commit2c7fa00813d51cf5a8436b459b62f2d343b75cde (patch)
tree3dbc2e26f5c4eeb8f1a872680e153a673729263f
parenta65931fd13a4c7f50b3bc5f99a8d80aacd3503d0 (diff)
Change database schema
Start and end times, and leading silence duration, are all available through SQL.
-rw-r--r--midi-dump.hs43
1 files changed, 31 insertions, 12 deletions
diff --git a/midi-dump.hs b/midi-dump.hs
index e950653..c47e8bf 100644
--- a/midi-dump.hs
+++ b/midi-dump.hs
@@ -1,4 +1,5 @@
1{-# LANGUAGE FlexibleContexts #-} 1{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE FlexibleInstances #-}
2{-# LANGUAGE OverloadedStrings #-} 3{-# LANGUAGE OverloadedStrings #-}
3 4
4import AlsaSeq 5import AlsaSeq
@@ -40,6 +41,8 @@ data Recording = Recording {
40 _recordingEvents :: RecordedEvents 41 _recordingEvents :: RecordedEvents
41} 42}
42 43
44data FinishedRecording = FinishedRecording Recording TimeSpec
45
43recordEvents :: Recording -> RecordedEvents -> Recording 46recordEvents :: Recording -> RecordedEvents -> Recording
44recordEvents (Recording s orig) new = Recording s (new ++ orig) 47recordEvents (Recording s orig) new = Recording s (new ++ orig)
45 48
@@ -53,7 +56,7 @@ data LoopState = LoopState {
53initializeState now = LoopState False Set.empty (emptyRecording now) now 56initializeState now = LoopState False Set.empty (emptyRecording now) now
54 57
55data LoopEnv = LoopEnv { 58data LoopEnv = LoopEnv {
56 _saver :: Chan Recording, 59 _saver :: Chan FinishedRecording,
57 _sqlite :: Connection, 60 _sqlite :: Connection,
58 _startTime :: TimeSpec, 61 _startTime :: TimeSpec,
59 _startTimeReal :: TimeSpec, 62 _startTimeReal :: TimeSpec,
@@ -73,6 +76,16 @@ getAbsTime = do
73 now <- liftIO $ getTime Monotonic 76 now <- liftIO $ getTime Monotonic
74 return $ now - startTime + startTimeReal 77 return $ now - startTime + startTimeReal
75 78
79createTable = fromString $ concat
80 ["CREATE TABLE IF NOT EXISTS axis_input",
81 " (id INTEGER PRIMARY KEY,",
82 " start_sec INTEGER,",
83 " start_nsec INTEGER,",
84 " end_sec INTEGER,",
85 " end_nsec INTEGER,",
86 " leading_silence INTEGER,",
87 " midi BLOB)"]
88
76main' = withAlsaInit $ \h public private q publicAddr privateAddr -> do 89main' = withAlsaInit $ \h public private q publicAddr privateAddr -> do
77 cmdlineAlsaConnect h public 90 cmdlineAlsaConnect h public
78 91
@@ -81,7 +94,7 @@ main' = withAlsaInit $ \h public private q publicAddr privateAddr -> do
81 startTimeReal <- getTime Realtime 94 startTimeReal <- getTime Realtime
82 95
83 sqlite <- open "test.db" 96 sqlite <- open "test.db"
84 execute_ sqlite "CREATE TABLE IF NOT EXISTS axis_input (id INTEGER PRIMARY KEY, sec INTEGER, nsec INTEGER, silence INTEGER, midi BLOB)" 97 execute_ sqlite createTable
85 saver <- startSaver sqlite 98 saver <- startSaver sqlite
86 lineReader <- startLineReader 99 lineReader <- startLineReader
87 100
@@ -134,16 +147,23 @@ startLineReader = do
134 thread <- liftIO $ forkIO (forever $ getLine >>= putMVar mv) 147 thread <- liftIO $ forkIO (forever $ getLine >>= putMVar mv)
135 return mv 148 return mv
136 149
137data Chunk = Chunk Int64 Int64 Int64 {- duration of silence in nanoseconds -} BS.ByteString 150data Chunk = Chunk Int64 Int64 Int64 Int64 Int64 BS.ByteString
138instance FromRow Chunk where 151instance FromRow Chunk where
139 fromRow = Chunk <$> field <*> field <*> field <*> field 152 fromRow = Chunk <$> field <*> field <*> field <*> field <*> field <*> field
140instance ToRow Chunk where 153instance ToRow Chunk where
141 toRow (Chunk s ns b pre) = toRow (s, ns, b, pre) 154 toRow (Chunk s ns s' ns' d m) = toRow (s, ns, s', ns', d, m)
155
156data Chunkable = MkChunk FinishedRecording TimeSpec
157instance ToRow Chunkable where
158 toRow (MkChunk reco ts) = toRow (s, ns, s', ns', leadingSilence :: Int64, pack $ show midi)
159 where
160 (FinishedRecording (Recording start@(TimeSpec s ns) midi) (TimeSpec s' ns')) = reco
161 leadingSilence = fromIntegral $ timeSpecAsNanoSecs $ ts - start
142 162
143saveMidi recording = do 163saveMidi recording = do
144 saver <- asks _saver 164 saver <- asks _saver
145 (TimeSpec s ns) <- gets lastTick 165 end <- gets lastTick
146 liftIO $ writeChan saver recording 166 liftIO $ writeChan saver $ FinishedRecording recording end
147 167
148startSaver sqlite = do 168startSaver sqlite = do
149 chan <- liftIO newChan 169 chan <- liftIO newChan
@@ -151,11 +171,10 @@ startSaver sqlite = do
151 return chan 171 return chan
152 where 172 where
153 saver chan = forever $ do 173 saver chan = forever $ do
154 (Recording silenceStart events) <- readChan chan 174 reco@(FinishedRecording (Recording _ events) _) <- readChan chan
155 let bytes = pack $ show events 175 let start = fst $ head events
156 ts@(TimeSpec s ns) = fst $ head events 176 sqlInsert = "INSERT INTO axis_input (start_sec, start_nsec, end_sec, end_nsec, leading_silence, midi) VALUES (?,?,?,?,?,?)"
157 silence = fromIntegral $ timeSpecAsNanoSecs $ ts - silenceStart 177 liftIO $ execute sqlite sqlInsert (MkChunk reco start)
158 liftIO $ execute sqlite "INSERT INTO axis_input (sec, nsec, silence, midi) VALUES (?,?,?,?)" (Chunk s ns silence bytes)
159 return () 178 return ()
160 179
161 180