hmp3-ng-2.18.1: app/Main.hs
-- Copyright (c) Don Stewart 2004-2008.
-- Copyright (c) Tuomo Valkonen 2004.
-- Copyright (c) 2019-2026 Galen Huntington
-- SPDX-License-Identifier: GPL-2.0-or-later
module Main where
import Base
import Core (start, shutdown, Options(..))
import qualified Config
import Keymap (keyLoop)
import Tree (buildTree, isEmpty)
import System.IO (hPrint, stderr)
import System.Posix.Signals (installHandler, sigTERM, sigPIPE, sigINT, sigHUP
,sigALRM, sigABRT, Handler(Ignore, Default, Catch))
import qualified Data.ByteString.UTF8 as UTF8
import Options.Applicative
-- ---------------------------------------------------------------------
-- | Set up the signal handlers
initSignals :: IO ()
initSignals = do
-- ignore
for_ [sigPIPE, sigALRM] \sig ->
installHandler sig Ignore Nothing
-- and exit if we get the following
for_ [sigINT, sigHUP, sigABRT, sigTERM] \sig ->
installHandler sig (Catch exitHandler) Nothing
exitHandler :: IO ()
exitHandler = do
releaseSignals -- in case shutdown itself gets stuck
catch @SomeException (shutdown Nothing) (hPrint stderr)
exitWith $ ExitFailure 1
releaseSignals :: IO ()
releaseSignals =
for_ [sigINT, sigPIPE, sigHUP, sigABRT, sigTERM] \sig ->
installHandler sig Default Nothing
------------------------------------------------------------------------
-- | Command-line parsing.
-- | The options together with the file/directory arguments.
invocation :: Parser (Options, [ByteString])
invocation = (,) <$> opts <*> files
where
opts = Options
<$> switch
(long "paused" <> short 'P' <> help "Start in a paused state")
<*> optional (strOption -- temporarily internal since feature needs work
(long "config" <> short 'c' <> metavar "FILE" <> internal
<> help "Read this config file instead of the XDG default"))
files = some $ argument (UTF8.fromString <$> str) (metavar "FILE|DIR...")
parserInfo :: ParserInfo (Options, [ByteString])
parserInfo = info (invocation <**> versionOpt <**> helper) $
fullDesc
<> header Config.versinfo
<> progDesc "Play mp3 files in a curses interface."
where
versionOpt = infoOption Config.versinfo
(hidden <> long "version" <> short 'V' <> help "Show version information")
------------------------------------------------------------------------
main :: IO ()
main = do
(opts, args) <- customExecParser (prefs showHelpOnEmpty) parserInfo
tree <- buildTree args
when (isEmpty tree) $
errorWithoutStackTrace "Error: No music files found."
initSignals
err <- either id absurd <$> try @SomeException do
start opts tree
keyLoop
shutdown $ Just $ "Error: " ++ show err