packages feed

haskell-player 0.1.3.1 → 0.1.3.2

raw patch · 3 files changed

+73/−38 lines, 3 files

Files

haskell-player.cabal view
@@ -1,7 +1,8 @@ name:                haskell-player-version:             0.1.3.1+version:             0.1.3.2 synopsis:            A terminal music player based on afplay-description:         Please see README.md+description:         A minimal graphical interface on top of afplay and afinfo+                     built using brick. homepage:            https://github.com/potomak/haskell-player license:             BSD3 license-file:        LICENSE
src/Sound/Player.hs view
@@ -24,7 +24,6 @@ import Data.List (isPrefixOf, stripPrefix) import Data.Maybe (fromMaybe) import qualified Data.Vector as Vec-import GHC.Float (double2Float) import qualified Graphics.Vty as V import Lens.Micro ((^.)) import System.Directory (doesDirectoryExist, getDirectoryContents)@@ -37,41 +36,13 @@ import Sound.Player.Types (Song(Song, songStatus), PlayerApp(PlayerApp,   songsList, playerStatus, playback), Playback(Playback, playhead),   Status(Play, Pause, Stop), PlayerEvent(VtyEvent, PlayheadAdvance))-import Sound.Player.Widgets (songWidget)+import Sound.Player.Widgets (songWidget, playbackProgressBar)   -- | Draws application UI. drawUI :: PlayerApp -> [Widget] drawUI (PlayerApp l _ _ mPlayback)  = [ui]   where-    playheadWidget Nothing = str " "-    playheadWidget (Just pb@(Playback _ _ ph d _)) = str $-      "Duration: " ++ show d ++-      " - Position: " ++ show (d - ph) ++-      " - Progress: " ++ show (playheadProgress pb)-    playheadProgressBar Nothing = str " "-    playheadProgressBar (Just pb@(Playback playPos _ ph _ _)) =-      P.progressBar (Just title) (playheadProgress pb)-      where-        title = path ++ " (" ++ humanDuration ph ++ ")"-        songs = l ^. L.listElementsL-        (Song _ path _) = songs Vec.! playPos-        secondsDuration :: Double -> Int-        secondsDuration d = round d `mod` 60-        minutesDuration :: Double -> Int-        minutesDuration d = round d `div` 60-        humanDuration :: Double -> String-        humanDuration d =-          show (minutesDuration d) ++ ":" ++ padSeconds (secondsDuration d)-        padSeconds :: Int -> String-        padSeconds s-            | length secs < 2 = "0" ++ secs-            | otherwise = secs-          where-            secs = show s-    -- A number between 0 and 1 that is current song's progress-    playheadProgress (Playback _ _ ph d _) =-      1 - (double2Float ph / double2Float d)     label = str "Item " <+> cur <+> str " of " <+> total     cur =       case l ^. L.listSelectedL of@@ -80,8 +51,7 @@     total = str $ show $ Vec.length $ l ^. L.listElementsL     box = B.borderWithLabel label $ L.renderList l (const songWidget)     ui = vBox [ box-              , playheadProgressBar mPlayback-              , playheadWidget mPlayback+              , playbackProgressBar mPlayback l               , str $ "Press enter to play/stop, spacebar to pause/resume, " ++                       "left/right to play prev/next song, " ++                       "q to exit."
src/Sound/Player/Widgets.hs view
@@ -1,17 +1,81 @@ module Sound.Player.Widgets (-  songWidget+  songWidget,+  playbackProgressBar ) where  import Brick.Types (Widget)-import Brick.Widgets.Core ((<+>), str, fill, vLimit)+import Brick.Widgets.Core ((<+>), str, fill, vLimit, vBox)+import qualified Brick.Widgets.List as L+import qualified Brick.Widgets.ProgressBar as P+import qualified Data.Vector as Vec+import GHC.Float (double2Float)+import Lens.Micro ((^.)) -import Sound.Player.Types (Song(Song), Status(Play, Pause))+import Sound.Player.Types (Song(Song), Status(Play, Pause), Playback(Playback))  +-- | A song 'Widget', one of the items in the songs list. songWidget :: Song -> Widget songWidget (Song _ path status) =     vLimit 1 $ str (statusSymbol status) <+> str " " <+> str path <+> fill ' '   where     statusSymbol Play = "♫"-    statusSymbol Pause = "►"+    statusSymbol Pause = "•"     statusSymbol _ = " "+++-- | A 'Widget' that shows two progress bars, the top bar shows the path of+-- the playing song, the bottom bar shows the playhead position, song duration+-- and playback percentage.+playbackProgressBar :: Maybe Playback -> L.List Song -> Widget+playbackProgressBar mPlayback l =+  vBox [ titlePlaybackProgressBar mPlayback l+       , infoPlaybackProgressBar mPlayback+       ]+++-- | A 'Widget' that shows a progress bar with the path of the song.+titlePlaybackProgressBar :: Maybe Playback -> L.List Song -> Widget+titlePlaybackProgressBar Nothing _ = str " "+titlePlaybackProgressBar (Just pb@(Playback playPos _ _ _ _)) l =+    P.progressBar (Just path) (playbackProgress pb)+  where+    songs = l ^. L.listElementsL+    (Song _ path _) = songs Vec.! playPos+++-- | A 'Widget' that shows a progress bar with the playhead position, song+-- duration and playback percentage.+infoPlaybackProgressBar :: Maybe Playback -> Widget+infoPlaybackProgressBar Nothing = str " "+infoPlaybackProgressBar (Just pb@(Playback _ _ ph d _)) =+    P.progressBar (Just title) progress+  where+    progress = playbackProgress pb+    percentage :: Integer+    percentage = round (progress * 100)+    title =+      formatSeconds (d - ph) ++ " / " +++      formatSeconds d ++ " ~ " +++      show percentage ++ "%"+++-- | A 'Float' number between 0 and 1 that is playing song's progress.+playbackProgress :: Playback -> Float+playbackProgress (Playback _ _ ph d _) = 1 - (double2Float ph / double2Float d)+++-- | Returns a string that is a time formatted as /mm:ss/+formatSeconds :: Double -> String+formatSeconds s = pad (minutes s) ++ ":" ++ pad (seconds s)+  where+    seconds :: Double -> Int+    seconds n = round n `mod` 60+    minutes :: Double -> Int+    minutes n = round n `div` 60+    pad :: Int -> String+    pad n+        | length ns < 2 = "0" ++ ns+        | otherwise = ns+      where+        ns = show n