Skip to content

Commit d87c76a

Browse files
Progress and clock boundary cases.
1 parent ff058cb commit d87c76a

2 files changed

Lines changed: 36 additions & 55 deletions

File tree

Core.hs

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,7 @@ errorLoop = runForever $
236236

237237
------------------------------------------------------------------------
238238

239-
-- | Handle messages arriving over a pipe from the decoder process. When
240-
-- shutdown kills the other end of the pipe, hGetLine will fail, so we
241-
-- take that chance to exit.
242-
--
239+
-- | Handle messages arriving over a pipe from the decoder process.
243240
mpgInput :: IO ()
244241
mpgInput = runForever $ do
245242
line <- P.hGetLine =<< readh <$> readMVar mpg
@@ -266,28 +263,24 @@ shutdown ms = do
266263
_ -> pure ExitSuccess
267264

268265
------------------------------------------------------------------------
269-
--
270-
-- Write incoming messages from the encoder to the global state in the
271-
-- right pigeon hole.
272-
--
266+
-- Handle messages from mpg123.
273267
handleMsg :: Msg -> IO ()
274-
275-
handleMsg (S i) = modifyHS_ $ \s -> s { info = Just i }
276-
277-
handleMsg (I id3) = modifyHS_ $ \s -> s { id3 = Just id3 }
278-
268+
handleMsg (S i) = modifyHS_ $ \st -> st { info = Just i }
269+
handleMsg (I id3) = modifyHS_ $ \st -> st { id3 = Just id3 }
279270
handleMsg (P t) = do
280271
modifyHS_ $ \s -> s { status = t }
281-
when (t == Stopped) playNext -- transition to next song
282-
272+
when (t == Stopped) do
273+
modifyHS_ \st -> st { -- force clock to end if near
274+
clock = (\c -> c {
275+
timeLeft = if timeLeft c < 0.1 then 0 else timeLeft c
276+
}) <$> clock st }
277+
playNext
283278
handleMsg (F f) = do
284279
silentlyModifyHS \st -> st { clock = Just f }
285280
UI.refreshClock
286281

287282
------------------------------------------------------------------------
288-
--
289283
-- Basic operations
290-
--
291284

292285
-- | Seek backward in song
293286
seekLeft :: IO ()
@@ -413,11 +406,12 @@ runPlayOp op = do
413406
f = P.intercalate (P.singleton '/')
414407
[dname $ folders ! fdir fe, fbase fe]
415408
modify' \st -> st
416-
{ current = new
417-
, status = Playing
418-
, cursor = if current == cursor then new else cursor
409+
{ current = new
410+
, status = Playing
411+
, cursor = if current == cursor then new else cursor
419412
, playHist = Seq.take histSize $ (now, new) <| playHist
420-
, id3 = Nothing
413+
, id3 = Nothing
414+
, clock = Nothing
421415
}
422416
pure f
423417
forM_ mfile $ sendMpg . Load

UI.hs

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,8 @@ end = do
9898
screenSize :: IO (Int, Int)
9999
screenSize = Curses.scrSize
100100

101-
--
102101
-- | Rewrite of Curses.getCh to avoid looping on terminal crash
103102
-- | (also no unget support since I don't need it)
104-
--
105103
getCh :: IO Curses.Key
106104
getCh = do
107105
threadWaitRead 0
@@ -113,10 +111,8 @@ getCh = do
113111
exitFailure
114112
k -> pure $ Curses.decodeKey k
115113

116-
--
117114
-- | Read a key. UIs need to define a method for getting events.
118115
-- We only need to refresh if we don't have no SIGWINCH support.
119-
--
120116
getKey :: IO Char
121117
getKey = do
122118
k <- getCh
@@ -260,39 +256,37 @@ showClock t =
260256

261257
-- | The time used and time left
262258
pTimes :: DrawData -> StringA
263-
pTimes DD { drawFrame=Just Frame {..}, drawSize=Size{sizeW=w} } =
259+
pTimes DD { drawFrame, drawSize=Size{sizeW=w} } =
264260
flip Fast defaultSty $ if w - 4 < P.length elapsed
265261
then ""
266262
else mconcat $ [" ", elapsed] ++ [gap <> "-" <> remaining | distance > 0]
267263
where
268-
elapsed = showClock currentTime
269-
remaining = showClock timeLeft
264+
elapsed = showClock (maybe 0 currentTime drawFrame)
265+
remaining = maybe "?:??.?" (showClock . timeLeft) drawFrame
270266
gap = spaces distance
271267
distance = w - 5 - P.length elapsed - P.length remaining
272-
pTimes _ = Fast "" defaultSty
273268

274269
------------------------------------------------------------------------
275270

276271
-- | A progress bar
277272
progressBar :: DrawData -> StringA
278-
progressBar dd@DD{drawSize=Size{sizeW=w}, drawState=st} = case drawFrame dd of
279-
Nothing -> FancyS [(" ", defaultSty), (spaces (w-4), bgs)]
280-
where
281-
Style _ bg = progress (config st)
282-
bgs = Style bg bg
273+
progressBar dd@DD{drawSize=Size{sizeW}, drawState=st} = case drawFrame dd of
274+
Nothing -> FancyS [(" ", defaultSty), (spaces width, bgs)]
283275
Just Frame {..} -> FancyS
284276
[ (" ", defaultSty)
285277
, (spaces distance, fgs)
286278
, (spaces (width - distance), bgs) ]
287279
where
288-
width = w - 4
289-
total = curr + left
290-
distance = round ((curr / total) * fromIntegral width)
291-
curr = realToFrac currentTime :: Float
292-
left = realToFrac timeLeft
293-
Style fg bg = progress (config st)
294-
bgs = Style bg bg
295-
fgs = Style fg fg
280+
total = curr + left - ε
281+
distance = ceiling (curr * fromIntegral (width - 1) / total)
282+
curr = toRational currentTime
283+
left = toRational timeLeft
284+
ε = 1 / 200
285+
where
286+
width = sizeW - 4
287+
Style fg bg = progress (config st)
288+
bgs = Style bg bg
289+
fgs = Style fg fg
296290

297291
------------------------------------------------------------------------
298292

@@ -338,17 +332,16 @@ playInfo dd = mconcat
338332
playTitle :: DrawData -> StringA
339333
playTitle dd =
340334
flip Fast hl $ mconcat if gap >= 2
341-
then [" ", inf, spaces gapl, indic, spaces gapr, time, " ", ver, " "]
335+
then [" ", inf, spaces gapl, u indic, spaces gapr, time, " ", ver, " "]
342336
else let gap' = x - indicl; gapl' = gap' `div` 2
343337
in if gap' >= 2
344-
then [spaces gapl', indic, spaces $ gap' - gapl']
345-
else [" ", P.take (x-2) indic, " "]
338+
then [spaces gapl', u indic, spaces $ gap' - gapl']
339+
else [" ", u $ take (x-2) indic, " "]
346340
where
347341
inf = playInfo dd
348342
time = pTime dd
349-
indic = u $ pState dd ++ ' ' : pMode dd
343+
indic = pState dd ++ ' ' : pMode dd
350344
ver = pVersion
351-
352345
x = sizeW $ drawSize dd
353346
lsize = 1 + P.length inf
354347
rsize = 2 + P.length time + P.length ver
@@ -434,9 +427,9 @@ redrawJustClock = Draw $ discardErrors do
434427
st <- getsHS id
435428
(h, w) <- screenSize
436429
let dd = DD (Size h w) undefined st (clock st)
437-
Curses.wMove Curses.stdScr 1 0 -- hardcoded!
430+
Curses.wMove Curses.stdScr 1 0
438431
drawLine $ progressBar dd
439-
Curses.wMove Curses.stdScr 2 0 -- hardcoded!
432+
Curses.wMove Curses.stdScr 2 0
440433
drawLine $ pTimes dd
441434

442435
------------------------------------------------------------------------
@@ -518,15 +511,11 @@ maybeLineDown _ h y x
518511
lineDown :: Int -> Int -> IO ()
519512
lineDown h y = Curses.wMove Curses.stdScr (min h (y+1)) 0
520513

521-
--
522514
-- | Fill to end of line spaces
523-
--
524515
fillLine :: IO ()
525516
fillLine = discardErrors Curses.clrToEol -- harmless?
526517

527-
--
528518
-- | move cursor to origin of stdScr.
529-
--
530519
gotoTop :: IO ()
531520
gotoTop = Curses.wMove Curses.stdScr 0 0
532521
{-# INLINE gotoTop #-}
@@ -540,9 +529,7 @@ slice i j arr =
540529

541530
------------------------------------------------------------------------
542531

543-
--
544532
-- | magics for setting xterm titles using ansi escape sequences
545-
--
546533
setXtermTitle :: [ByteString] -> IO ()
547534
setXtermTitle strs = do
548535
traverse_ (P.hPut stderr) (before : strs ++ [after])

0 commit comments

Comments
 (0)