mirror of
https://github.com/Drezil/dear-implot.hs.git
synced 2024-11-14 17:07:01 +00:00
109 lines
2.9 KiB
Haskell
109 lines
2.9 KiB
Haskell
{-# LANGUAGE BlockArguments #-}
|
|
{-# LANGUAGE LambdaCase #-}
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
{-# LANGUAGE RankNTypes #-}
|
|
|
|
module Main (main) where
|
|
|
|
import Control.Exception
|
|
import Control.Monad.IO.Class
|
|
import Control.Monad.Managed
|
|
import Data.Binary.Get (getInt16le, isEmpty, runGet)
|
|
import qualified Data.ByteString as BS
|
|
import Data.ByteString.Lazy (fromStrict)
|
|
import Data.List (iterate')
|
|
import DearImGui
|
|
import DearImGui.OpenGL2
|
|
import qualified DearImGui.Plot as ImPlot
|
|
import DearImGui.SDL
|
|
import DearImGui.SDL.OpenGL
|
|
import GHC.Float (int2Float)
|
|
import GHC.Int (Int16)
|
|
import Graphics.GL
|
|
import Pipes
|
|
import Pipes.PulseSimple
|
|
import Pipes.Safe (runSafeT)
|
|
import SDL
|
|
|
|
main :: IO ()
|
|
main = do
|
|
-- Initialize SDL
|
|
initializeAll
|
|
|
|
runManaged do
|
|
-- Create a window using SDL. As we're using OpenGL, we need to enable OpenGL too.
|
|
win <- do
|
|
let title = "Hello, Dear ImGui!"
|
|
let config = defaultWindow {windowGraphicsContext = OpenGLContext defaultOpenGL}
|
|
managed $ bracket (createWindow title config) destroyWindow
|
|
|
|
-- Create an OpenGL context
|
|
glContext <- managed $ bracket (glCreateContext win) glDeleteContext
|
|
|
|
-- Create an ImGui context
|
|
_ <- managed $ bracket createContext destroyContext
|
|
|
|
-- Create an ImPlot context
|
|
_ <- managed $ bracket ImPlot.createContext ImPlot.destroyContext
|
|
|
|
-- Initialize ImGui's SDL2 backend
|
|
_ <- managed_ $ bracket_ (sdl2InitForOpenGL win glContext) sdl2Shutdown
|
|
|
|
-- Initialize ImGui's OpenGL backend
|
|
_ <- managed_ $ bracket_ openGL2Init openGL2Shutdown
|
|
|
|
liftIO $ runSafeT (runEffect (readPulse "dear-pulse" Nothing 25 >-> mainLoop win))
|
|
|
|
-- | Binary decoder
|
|
decodeSampleList :: BS.ByteString -> [Int16]
|
|
decodeSampleList = runGet get . fromStrict
|
|
where
|
|
get = do
|
|
empty <- isEmpty
|
|
if empty
|
|
then return []
|
|
else do
|
|
sample <- getInt16le
|
|
rest <- get
|
|
return (sample : rest)
|
|
|
|
mainLoop :: MonadIO m => Window -> Consumer' BS.ByteString m ()
|
|
mainLoop win = do
|
|
-- Process the event loop
|
|
untilNothingM pollEventWithImGui
|
|
|
|
-- Get audio buffer
|
|
buf <- await
|
|
let maxInt16 :: Int16
|
|
maxInt16 = maxBound
|
|
maxInt16f = int2Float $ fromIntegral maxInt16
|
|
samples :: [Float]
|
|
samples = map (\x' -> int2Float (fromIntegral x') / maxInt16f) $ decodeSampleList buf
|
|
|
|
-- Tell ImGui we're starting a new frame
|
|
openGL2NewFrame
|
|
sdl2NewFrame win
|
|
newFrame
|
|
|
|
-- Build the GUI
|
|
ImPlot.setNextPlotLimits (0, 1) (-1, 1)
|
|
liftIO $ bracket_ (ImPlot.beginPlot "Audio") ImPlot.endPlot do
|
|
ImPlot.plotLine "pulse-input" xs samples
|
|
|
|
-- Render
|
|
glClear GL_COLOR_BUFFER_BIT
|
|
|
|
render
|
|
openGL2RenderDrawData =<< getDrawData
|
|
|
|
glSwapWindow win
|
|
|
|
mainLoop win
|
|
where
|
|
untilNothingM m = m >>= maybe (return ()) (\_ -> untilNothingM m)
|
|
xs = range
|
|
range :: [Float]
|
|
range = take 1764 $ iterate' (+ step) 0.0
|
|
step :: Float
|
|
step = 1 / 1764
|