diff options
author | Andrew Cady <d@jerkface.net> | 2014-01-17 05:42:53 -0500 |
---|---|---|
committer | Andrew Cady <d@jerkface.net> | 2014-01-17 05:42:53 -0500 |
commit | 4d4f7d74c370040ee102367d1c06953aa33896b9 (patch) | |
tree | c3fd93505280194f8bc0f87722f3565bf7ba36cd | |
parent | 5736ae0a30c2a4844c0f26d6847356193482ee61 (diff) |
live playback works! connect via aplaymidi to play midi files
-rw-r--r-- | axis.hs | 92 |
1 files changed, 67 insertions, 25 deletions
@@ -16,6 +16,8 @@ import Graphics.UI.SDL.Primitives as SDL.Primitive | |||
16 | import Data.Int (Int16) | 16 | import Data.Int (Int16) |
17 | import qualified System.Exit as Exit | 17 | import qualified System.Exit as Exit |
18 | import Data.List (elemIndex, elemIndices) | 18 | import Data.List (elemIndex, elemIndices) |
19 | import GHC.Word | ||
20 | import Data.Bits | ||
19 | 21 | ||
20 | netwireIsCool :: (Monad m) => Wire (Timed NominalDiffTime ()) () m a String | 22 | netwireIsCool :: (Monad m) => Wire (Timed NominalDiffTime ()) () m a String |
21 | netwireIsCool = | 23 | netwireIsCool = |
@@ -30,6 +32,44 @@ netwireIsCool = | |||
30 | holdFor 0.5 . periodic 1 . pure "Hoo..." <|> | 32 | holdFor 0.5 . periodic 1 . pure "Hoo..." <|> |
31 | pure "...ray!" | 33 | pure "...ray!" |
32 | 34 | ||
35 | smartShowPitch p = showPitch p -- TODO: use flat for Eb, Bb; use unicode flat/sharp chars | ||
36 | |||
37 | _USE_HEXAGONS = True | ||
38 | |||
39 | _drawHexircle f v x y s c = | ||
40 | if _USE_HEXAGONS | ||
41 | then _drawHexagonSDL f v x y s c | ||
42 | else (if f then SDL.Primitive.filledCircle else SDL.Primitive.circle) v x y (s * 7 `div` 8) c | ||
43 | |||
44 | drawHexircle = _drawHexircle False | ||
45 | drawFilledHexircle = _drawHexircle True | ||
46 | |||
47 | _KEY_COLOR = (SDL.Color 0 0 255) | ||
48 | _KEY_BG_COLOR = (SDL.Color 0 0 0) | ||
49 | _KEY_TEXT_COLOR = (SDL.Color 128 128 0) | ||
50 | |||
51 | _KEY_COLOR_PIXEL = let (SDL.Color r g b) = _KEY_COLOR in (rgbColor r g b) | ||
52 | _KEY_BG_COLOR_PIXEL = let (SDL.Color r g b) = _KEY_BG_COLOR in (rgbColor r g b) | ||
53 | |||
54 | drawKeys pitches videoSurface font axis_key_locations axis_key_size = do | ||
55 | |||
56 | forM_ pitches $ \pitch -> do | ||
57 | forM_ (elemIndices pitch pitchIndex) $ \idx -> do | ||
58 | let (x, y) = axis_key_locations !! idx | ||
59 | drawFilledHexircle videoSurface (fromIntegral x) (fromIntegral y) (fromIntegral axis_key_size) _KEY_COLOR_PIXEL | ||
60 | centerText videoSurface x y font _KEY_TEXT_COLOR _KEY_COLOR (smartShowPitch pitch) | ||
61 | |||
62 | eraseKeys pitches videoSurface font axis_key_locations axis_key_size = do | ||
63 | |||
64 | forM_ pitches $ \pitch -> do | ||
65 | forM_ (elemIndices pitch pitchIndex) $ \idx -> do | ||
66 | let (x, y) = axis_key_locations !! idx | ||
67 | drawFilledHexircle videoSurface (fromIntegral x) (fromIntegral y) (fromIntegral axis_key_size) _KEY_BG_COLOR_PIXEL | ||
68 | drawHexircle videoSurface (fromIntegral x) (fromIntegral y) (fromIntegral axis_key_size) _KEY_COLOR_PIXEL | ||
69 | |||
70 | fi = fromIntegral | ||
71 | rgbColor r g b = SDL.Pixel (shiftL (fi r) 24 .|. shiftL (fi g) 16 .|. shiftL (fi b) 8 .|. (fi 255)) | ||
72 | |||
33 | main = | 73 | main = |
34 | withAlsaInit $ \h public private q publicAddr privateAddr -> do | 74 | withAlsaInit $ \h public private q publicAddr privateAddr -> do |
35 | cmdlineAlsaConnect h public -- fail early if bad command lines | 75 | cmdlineAlsaConnect h public -- fail early if bad command lines |
@@ -51,20 +91,15 @@ main = | |||
51 | _ <- SDL.grabInput True | 91 | _ <- SDL.grabInput True |
52 | warpMouse | 92 | warpMouse |
53 | 93 | ||
54 | let pixelFormat = SDL.surfaceGetPixelFormat videoSurface | 94 | --let pixelFormat = SDL.surfaceGetPixelFormat videoSurface |
55 | blue <- SDL.mapRGB pixelFormat 0 255 255 -- why is it blue??? | 95 | pixelFormat <- SDL.surfaceGetPixelFormat <$> SDL.createRGBSurfaceEndian [] 1 1 24 |
56 | -- _ <- SDL.setRelativeMouseMode True -- SDL2. Should I use it? | 96 | -- _ <- SDL.setRelativeMouseMode True -- SDL2. Should I use it? |
57 | 97 | ||
58 | let (axis_key_size, axis_key_locations) = getKeyLocations videoClipRect | 98 | let (axis_key_size, axis_key_locations) = getKeyLocations videoClipRect |
59 | 99 | ||
60 | forM_ axis_key_locations $ \(x, y) -> do | 100 | let allPitches = map (+ 35) [0 .. 49] |
61 | --SDL.Primitive.filledCircle videoSurface (fromIntegral x) (fromIntegral y) (fromIntegral axis_key_size) blue >>= return | 101 | --drawKeys allPitches videoSurface font blue axis_key_locations axis_key_size |
62 | drawHexagonSDL videoSurface (fromIntegral x) (fromIntegral y) (fromIntegral axis_key_size) blue >>= return | 102 | eraseKeys allPitches videoSurface font axis_key_locations axis_key_size |
63 | |||
64 | forM_ [0 .. length axis_key_locations - 1] $ \i -> do | ||
65 | let (centerx, centery) = axis_key_locations !! i | ||
66 | centerText videoSurface centerx centery font (showPitch $ pitchIndex !! i) | ||
67 | -- centerText videoSurface centerx centery font (show i) | ||
68 | 103 | ||
69 | putStrLn "Initialized." | 104 | putStrLn "Initialized." |
70 | 105 | ||
@@ -77,22 +112,28 @@ main = | |||
77 | let x' = either (const "") id ex | 112 | let x' = either (const "") id ex |
78 | 113 | ||
79 | Control.Monad.when (x /= x' && x' /= "") $ do | 114 | Control.Monad.when (x /= x' && x' /= "") $ do |
80 | textBand videoSurface videoClipRect (SDL.Rect 0 0 0 70) font x' | 115 | -- textBand videoSurface videoClipRect (SDL.Rect 0 0 0 70) font x' |
81 | return () | 116 | return () |
82 | 117 | ||
83 | Control.Monad.when (midiKeysDown' /= midiKeysDown) $ do | 118 | Control.Monad.when (midiKeysDown' /= midiKeysDown) $ do |
84 | --let chord = showChord midiKeysDown' | 119 | --let chord = showChord midiKeysDown' |
85 | --let chord = show $ pitchList midiKeysDown' | 120 | --let chord = show $ pitchList midiKeysDown' |
121 | let ignoreThese = Set.intersection midiKeysDown' midiKeysDown | ||
122 | let drawThese = pitchList $ Set.difference midiKeysDown' ignoreThese | ||
123 | let eraseThese = pitchList $ Set.difference midiKeysDown ignoreThese | ||
124 | |||
86 | let chord = show $ map (\i->elemIndices i pitchIndex) $ pitchList midiKeysDown' | 125 | let chord = show $ map (\i->elemIndices i pitchIndex) $ pitchList midiKeysDown' |
87 | textBand videoSurface videoClipRect (SDL.Rect 0 70 0 70) font chord | 126 | drawKeys drawThese videoSurface font axis_key_locations axis_key_size |
127 | eraseKeys eraseThese videoSurface font axis_key_locations axis_key_size | ||
128 | -- textBand videoSurface videoClipRect (SDL.Rect 0 70 0 70) font chord | ||
88 | return () | 129 | return () |
89 | 130 | ||
90 | Control.Monad.when (keysDown' /= keysDown) $ do | 131 | -- Control.Monad.when (keysDown' /= keysDown) $ do |
91 | let chord = unwords $ map (\k -> drop 5 (show k)) $ Set.toList keysDown' | 132 | -- let chord = unwords $ map (\k -> drop 5 (show k)) $ Set.toList keysDown' |
92 | textBand videoSurface videoClipRect (SDL.Rect 0 210 0 70) font chord | 133 | -- textBand videoSurface videoClipRect (SDL.Rect 0 210 0 70) font chord |
93 | textBand videoSurface videoClipRect (SDL.Rect 0 280 0 70) font $ | 134 | -- textBand videoSurface videoClipRect (SDL.Rect 0 280 0 70) font $ |
94 | if keyDown SDL.SDLK_a keysDown' then "arpeggiate" else "" | 135 | -- if keyDown SDL.SDLK_a keysDown' then "arpeggiate" else "" |
95 | return () | 136 | -- return () |
96 | 137 | ||
97 | Control.Monad.when(False) $ do | 138 | Control.Monad.when(False) $ do |
98 | 139 | ||
@@ -114,24 +155,25 @@ main = | |||
114 | 155 | ||
115 | zipzip ls = if (head ls) == [] then [] else (map head ls) : (zipzip $ map tail ls) | 156 | zipzip ls = if (head ls) == [] then [] else (map head ls) : (zipzip $ map tail ls) |
116 | 157 | ||
117 | drawHexagonSDL videoSurface centerx centery radius pixel = do | 158 | drawHexagonSDL = _drawHexagonSDL False |
159 | drawFilledHexagonSDL = _drawHexagonSDL True | ||
160 | |||
161 | _drawHexagonSDL filled videoSurface centerx centery radius pixel = do | ||
118 | let r = fromIntegral radius | 162 | let r = fromIntegral radius |
119 | --let points = map (\(x, y) -> (centerx + x + radius `div` 2, centery + y + radius `div` 2)) $ | ||
120 | let points = map (\(x, y) -> (centerx + x, centery + y)) $ | 163 | let points = map (\(x, y) -> (centerx + x, centery + y)) $ |
121 | map (\(x, y) -> (round x, round y)) $ | 164 | map (\(x, y) -> (round x, round y)) $ |
122 | map (\i -> (r * cos(pi/3 * (i)), r * sin(pi/3 * (i)))) $ map fromIntegral [0 .. 5] | 165 | map (\i -> (r * cos(pi/3 * (i)), r * sin(pi/3 * (i)))) $ map fromIntegral [0 .. 5] |
123 | --filledPolygon :: Surface -> [(Int16, Int16)] -> Pixel -> IO Bool | 166 | (if not filled then SDL.Primitive.polygon else SDL.Primitive.filledPolygon) videoSurface points pixel |
124 | SDL.Primitive.polygon videoSurface points pixel >>= return | ||
125 | return () | ||
126 | 167 | ||
127 | centerText videoSurface x y font text = do | 168 | centerText videoSurface x y font fgColor bgColor text = do |
128 | --fontSurface <- SDL.TTF.renderUTF8Shaded font text (SDL.Color 0 255 0) (SDL.Color 80 80 80) -- useful for testing | 169 | --fontSurface <- SDL.TTF.renderUTF8Shaded font text (SDL.Color 0 255 0) (SDL.Color 80 80 80) -- useful for testing |
129 | fontSurface <- SDL.TTF.renderUTF8Shaded font text (SDL.Color 0 255 0) (SDL.Color 0 0 0) | 170 | fontSurface <- SDL.TTF.renderUTF8Shaded font text fgColor bgColor |
130 | fontClipRect <- SDL.getClipRect fontSurface | 171 | fontClipRect <- SDL.getClipRect fontSurface |
131 | let (SDL.Rect _ _ w h) = fontClipRect | 172 | let (SDL.Rect _ _ w h) = fontClipRect |
132 | _ <- SDL.blitSurface fontSurface (Just fontClipRect) videoSurface (Just (SDL.Rect (fromIntegral(x) - w `div` 2) (fromIntegral(y) - h `div` 2) w h)) | 173 | _ <- SDL.blitSurface fontSurface (Just fontClipRect) videoSurface (Just (SDL.Rect (fromIntegral(x) - w `div` 2) (fromIntegral(y) - h `div` 2) w h)) |
133 | return () | 174 | return () |
134 | 175 | ||
176 | -- TODO: make this generalize to different grid sizes | ||
135 | colfrom top = map (+ top) $ map (* (-7)) [0 .. 6] | 177 | colfrom top = map (+ top) $ map (* (-7)) [0 .. 6] |
136 | pitchIndex = (\x -> x ++ x) $ concat $ map colfrom [81, 78, 82, 79, 83, 80, 84] | 178 | pitchIndex = (\x -> x ++ x) $ concat $ map colfrom [81, 78, 82, 79, 83, 80, 84] |
137 | 179 | ||