hmp3-ng 2.14.3 → 2.15.0
raw patch · 10 files changed
+57/−62 lines, 10 files
Files
- Base.hs +2/−5
- Core.hs +18/−19
- Keymap.hs +3/−3
- Lexer.hs +5/−5
- Main.hs +2/−2
- README.md +15/−14
- State.hs +3/−3
- Syntax.hs +3/−5
- UI.hs +4/−5
- hmp3-ng.cabal +2/−1
Base.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE CPP #-} ----- Copyright (c) 2020, 2021 Galen Huntington+-- Copyright (c) 2020-2024 Galen Huntington -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as@@ -33,7 +33,7 @@ import Data.Char as X import Data.Fixed as X import Data.Foldable as X-import Data.Functor as X+import Data.Functor as X hiding (unzip) import Data.IORef as X import Data.List as X ((\\), group, groupBy, isPrefixOf, sort, sortBy, intersperse) import Data.Maybe as X@@ -53,9 +53,6 @@ discardErrors :: IO () -> IO () discardErrors = X.handle @SomeException (\_ -> pure ())--whenJust :: Monad m => Maybe a -> (a -> m ()) -> m ()-whenJust mval f = case mval of Nothing -> pure (); Just v -> f v getMonoTime :: IO TimeSpec getMonoTime = getTime
Core.hs view
@@ -2,7 +2,7 @@ -- -- Copyright (c) 2005-2008 Don Stewart - http://www.cse.unsw.edu.au/~dons--- Copyright (c) 2008, 2019-2022 Galen Huntington+-- Copyright (c) 2008, 2019-2024 Galen Huntington -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as@@ -49,7 +49,7 @@ import State import Style import FastIO (send, FiltHandle(..), newFiltHandle)-import Tree hiding (File,Dir)+import Tree hiding (File, Dir) import qualified Tree (File,Dir) import qualified UI @@ -77,10 +77,10 @@ mp3Tool :: String mp3Tool =-#ifdef MPG123- "mpg123"-#else+#ifdef MPG321 "mpg321"+#else+ "mpg123" #endif ------------------------------------------------------------------------@@ -88,7 +88,7 @@ start :: Bool -> FileListSource -> IO () start playNow ms = handle @SomeException (shutdown . Just . show) do - t0 <- forkIO mpgLoop -- start this off early, to give mpg321 time to settle+ t0 <- forkIO mpgLoop -- start this off early, to give mpg123 time to settle c <- UI.start -- initialise curses @@ -156,7 +156,7 @@ ------------------------------------------------------------------------ --- | Process loop, launch mpg321, set the handles in the state+-- | Process loop, launch mpg123, set the handles in the state -- and then wait for the process to die. If it does, restart it. -- -- If we're unable to start at all, we should say something sensible@@ -167,18 +167,17 @@ mmpg <- findExecutable mp3Tool case mmpg of Nothing -> quit (Just $ "Cannot find " ++ mp3Tool ++ " in path")- Just mpg321 -> do+ Just mppath -> do - -- if we're never able to start mpg321, do something sensible+ -- if we're never able to start mpg123, do something sensible -- TODO no need for this Maybe unpacking, just catch and rerun loop- mv <- catch (pure <$> runInteractiveProcess mpg321 ["-R","-"] Nothing Nothing)+ mv <- catch (pure <$> runInteractiveProcess mppath ["-R", "-"] Nothing Nothing) (\ (e :: SomeException) -> do warnA ("Unable to start " ++ mp3Tool ++ ": " ++ show e) pure Nothing)- case mv of- Nothing -> threadDelay (1000 * 500) >> mpgLoop- Just (hw, r, e, pid) -> do + flip (maybe (threadDelay 1_000_000)) mv \ (hw, r, e, pid) -> do+ mhw <- newMVar hw mew <- newMVar =<< newFiltHandle e mfilep <- newMVar =<< newFiltHandle r@@ -195,7 +194,7 @@ catch @SomeException (void $ waitForProcess pid) (\_ -> pure ()) stop <- getsST doNotResuscitate when stop exitSuccess- warnA $ "Restarting " ++ mpg321 ++ " ..."+ warnA $ "Restarting " ++ mppath ++ " ..." ------------------------------------------------------------------------ @@ -247,7 +246,7 @@ ------------------------------------------------------------------------ --- | Handle, and display errors produced by mpg321+-- | Handle, and display errors produced by mpg123 errorLoop :: IO () errorLoop = runForever $ do s <- getsST errh >>= readMVar >>= hGetLine . filtHandle@@ -519,14 +518,14 @@ jumpToMatchFile :: Maybe String -> Bool -> IO () jumpToMatchFile re sw = genericJumpToMatch re sw k sel- where k = \st -> (music st, if size st == 0 then -1 else cursor st, size st)+ where k st = (music st, if size st == 0 then -1 else cursor st, size st) sel i _ = i jumpToMatch :: Maybe String -> Bool -> IO () jumpToMatch re sw = genericJumpToMatch re sw k sel- where k = \st -> (folders st- ,if size st == 0 then -1 else fdir (music st ! cursor st)- ,1 + (snd . bounds $ folders st))+ where k st = (folders st+ , if size st == 0 then -1 else fdir (music st ! cursor st)+ , 1 + (snd . bounds $ folders st)) sel i st = dlo (folders st ! i) genericJumpToMatch :: Lookup a
Keymap.hs view
@@ -1,6 +1,6 @@ -- -- Copyright (c) 2004-2008 Don Stewart - http://www.cse.unsw.edu.au/~dons--- Copyright (c) 2008, 2019-2022 Galen Huntington+-- Copyright (c) 2008, 2019-2024 Galen Huntington -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as@@ -169,7 +169,7 @@ handleKey base off cs st = (with do ph <- getsST playHist- whenJust+ for_ do ph Seq.!? (fromEnum (head cs) - (fromEnum base - off)) do jump . snd hideHist@@ -191,7 +191,7 @@ -- "Key"s seem to be inscrutable and incomparable. -- So, add an orphan instance to help translate to chars. -deriving instance Ord Key+deriving stock instance Ord Key charToKey :: Char -> Key charToKey = decodeKey . toEnum . fromEnum
Lexer.hs view
@@ -1,6 +1,6 @@ -- -- Copyright (c) 2005-2008 Don Stewart - http://www.cse.unsw.edu.au/~dons--- Copyright (c) 2008, 2019, 2020 Galen Huntington+-- Copyright (c) 2008, 2019-2024 Galen Huntington -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as@@ -18,7 +18,7 @@ -- 02111-1307, USA. -- --- Lexer for mpg321 messages+-- Lexer for mpg123 messages module Lexer ( parser ) where @@ -45,7 +45,7 @@ '0' -> Stopped '1' -> Paused '2' -> Playing- '3' -> Stopped -- used by mpg321+ '3' -> Stopped -- used by mpg123 _ -> Playing -- _ -> error "Invalid Status" @@ -95,7 +95,7 @@ in case P.take 4 f of cs | cs == "ID3:" -> F . File $ let ttl = toId id3 . splitUp . P.drop 4 $ f- -- mpg321 sometimes returns null titles+ -- mpg123 sometimes returns null titles in if P.null (id3title ttl) then Left f else Right ttl | otherwise -> F . File . Left $ f where@@ -162,6 +162,6 @@ b <- lift $ checkF h if b then pure $ doF m else skip 'P' -> pure $ doP m- 'E' -> throwError $ Just $ "mpg321 error: " ++ P.unpack m+ 'E' -> throwError $ Just $ "mpg123 error: " ++ P.unpack m _ -> skip
Main.hs view
@@ -1,7 +1,7 @@ -- -- Copyright (c) Don Stewart 2004-2008. -- Copyright (c) Tuomo Valkonen 2004.--- Copyright (c) 2019-2021 Galen Huntington+-- Copyright (c) 2019-2024 Galen Huntington -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as@@ -101,7 +101,7 @@ -- main :: IO () main = do- (playNow, files) <- doArgs =<< map fromString <$> getArgs+ (playNow, files) <- doArgs . map fromString =<< getArgs initSignals start playNow files -- never returns
README.md view
@@ -20,11 +20,12 @@ versions, which were only minor changes, mostly the automated regeneration of a `configure` file (now gone). -* The code has been updated to compile under recent GHC (currently-8.6, 8.8, 8.10, 9.0, and 9.2) and libraries. This required rewriting-or entirely replacing large sections, mainly low-level optimizations.+* The code has been updated to compile under recent GHC (tested+through 9.10) and libraries. This required rewriting or entirely+replacing large sections, mainly low-level optimizations. -* I added support for building with Stack.+* I added support for building with Stack. It can also be installed+from Nix. * There is a public GitHub issue tracker, and a GitHub action to continuously test builds.@@ -55,15 +56,15 @@ ## Installation Either `cabal install` or `stack install` will build a binary.-You will need to have `mpg321` installed, which is free software-and widely available in package managers. Alternatively, `mpg123`-can be used by compiling with the `-DMPG123` option, but, while your-mileage may vary, in my experience it doesn’t work as well.+You will need to have `mpg123` installed, which is free software and+widely available in package managers. Alternatively, `mpg321` can+be used by compiling with the `-DMPG321` option. In my experience,+the latter worked better, but it has not been updated since 2012 and+is no longer available on many systems. The build depends on the package `hscurses`, which in turn requires-curses dev files. In Ubuntu/Debian, for example, these can be-obtained by installing `libncurses5-dev`. You probably also need-`libncursesw5-dev`.+curses dev files. In Ubuntu/Debian, for example, these can be obtained+by installing `libncurses-dev`. ## Use@@ -83,9 +84,9 @@ message with command line options. A color scheme can be specified by writing out a `Config { .. }`-value in `~/.config/hmp3/style.conf` or the equivalent in your-XDG config directory. See `Style.hs` for the definition. The `l`-command hot-reloads this configuration.+value in `~/.config/hmp3/style.conf` (or wherever your XDG config is).+See `Style.hs` for the definition. The `l` command hot-reloads this+configuration. ## Original authorship list
State.hs view
@@ -1,6 +1,6 @@ -- -- Copyright (c) 2004-2008 Don Stewart - http://www.cse.unsw.edu.au/~dons--- Copyright (c) 2019, 2020 Galen Huntington+-- Copyright (c) 2019-2024 Galen Huntington -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as@@ -72,7 +72,7 @@ ,boottime :: !TimeSpec ,regex :: !(Maybe (Regex,Bool)) -- most recent search pattern and direction ,xterm :: !Bool- ,doNotResuscitate :: !Bool -- should we just let mpg321 die?+ ,doNotResuscitate :: !Bool -- should we just let mpg123 die? ,playHist :: Seq (TimeSpec, Int) -- limited history of songs played ,config :: !UIStyle -- config values @@ -113,7 +113,7 @@ ,exitVisible = False ,miniFocused = False ,xterm = False- ,doNotResuscitate = False -- mpg321 should be restarted+ ,doNotResuscitate = False -- mpg123 should be restarted ,playHist = mempty ,config = Config.defaultStyle
Syntax.hs view
@@ -1,6 +1,6 @@ -- -- Copyright (c) 2005-2008 Don Stewart - http://www.cse.unsw.edu.au/~dons--- Copyright (c) 2019, 2020 Galen Huntington+-- Copyright (c) 2019-2024 Galen Huntington -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as@@ -22,8 +22,6 @@ -- abstract syntax for mpg123/321 'remote control' commands, so we get -- type safe messaging, and parsing of results ----- See 'README.remote' distributed with mpg321.--- module Syntax where @@ -56,7 +54,7 @@ instance Pretty Pause where ppr Pause = "PAUSE" --- Quits mpg321.+-- Quits mpg123. data Quit = Quit instance Pretty Quit where@@ -142,7 +140,7 @@ deriving stock (Eq, Show) data Mode = Normal | Loop | Random- deriving stock (Eq,Bounded,Enum)+ deriving stock (Eq, Bounded, Enum) ------------------------------------------------------------------------
UI.hs view
@@ -54,7 +54,6 @@ import Data.Array ((!), bounds, Array, listArray) import Data.Array.Base (unsafeAt)-import Data.List (intercalate) import System.IO (stderr, hFlush) import System.Posix.Signals (raiseSignal, sigTSTP, installHandler, Handler(..)) @@ -262,7 +261,7 @@ PId3 a = draw dd PInfo b = draw dd s = UTF8.toString a- line | gap >= 0 = U s : (B $ spaces gap) : right+ line | gap >= 0 = U s : B (spaces gap) : right | True = U (ellipsize lim s) : right where lim = x - 5 - (if showId3 then P.length b else -1) gap = lim - displayWidth s@@ -308,7 +307,7 @@ f cs ps = UTF8.fromString $ forceWidth wd $ forceWidth clen cmds <> ps where clen = max 4 $ round $ fromIntegral wd * (0.2::Float)- cmds = intercalate " " $ "" : map pprIt cs+ cmds = unwords $ "" : map pprIt cs pprIt c = case c of '\n' -> "Enter" '\f' -> "^L"@@ -346,7 +345,7 @@ blank = Fast (UTF8.fromString $ forceWidth wd "") sty padl = replicate ((wd - 9) `div` 2) ' ' msg = forceWidth wd $ padl ++ "Exit (y)?"- pure $ (wd, [blank, Fast (UTF8.fromString msg) sty, blank])+ pure (wd, [blank, Fast (UTF8.fromString msg) sty, blank]) ------------------------------------------------------------------------ @@ -600,7 +599,7 @@ -- renderModal :: forall me. ModalElement me => HState -> Size -> IO () renderModal st (Size h w) = do- whenJust (drawModal @me (modals $ config st) w st) \(mw, modal') -> do+ for_ (drawModal @me (modals $ config st) w st) \(mw, modal') -> do let hoffset = max 0 $ (w - mw) `div` 2 mlines = min h $ length modal' voffset = (h - mlines) `div` 2
hmp3-ng.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.2 name: hmp3-ng-version: 2.14.3+version: 2.15.0 synopsis: A 2019 fork of an ncurses mp3 player written in Haskell description: An mp3 player with a curses frontend. Playlists are populated by passing file and directory names on the command line. 'h' displays@@ -54,6 +54,7 @@ LambdaCase MultiWayIf StandaloneDeriving+ NumericUnderscores ghc-options: -Wall -funbox-strict-fields -threaded -Wno-unused-do-bind extra-libraries: ncursesw