gpt4 book ai didi

haskell - xmonad 的 logHook 可以按设定的时间间隔运行,而不是(仅仅)响应布局事件吗?

转载 作者:行者123 更新时间:2023-12-02 17:20:02 28 4
gpt4 key购买 nike

我将 XMonad.Hooks.DynamicLog 中的 dynamicLogWithPP 与 dzen2 一起用作 xmonad 下的状态栏。我想在栏中显示的内容之一是当前播放轨道的剩余时间(如果有的话)。获取此信息很容易:

audStatus :: Player -> X (Maybe String)
audStatus p = do
info <- liftIO $ tryS $ withPlayer p $ do
ispaused <- paused
md <- getMetadataString
timeleftmillis <- (-) <$> (getCurrentTrack >>= songFrames) <*> time
let artist = md ! "artist"
title = md ! "title"
timeleft = timeleftmillis `quot` 1000
(minutes, seconds) = timeleft `quotRem` 60
disp = artist ++ " - " ++ title ++ " (-"++(show minutes)++":"++(show seconds)++")" -- will be wrong if seconds < 10
audcolor False = dzenColor base0 base03
audcolor True = dzenColor base1 base02
return $ wrap "^ca(1, pms p)" "^ca()" (audcolor ispaused disp)
return $ either (const Nothing) Just info

所以我可以将其放在 ppExtras 中,并且它工作正常 -除了它仅在 logHook 运行时运行,并且这种情况发生只有当合适的事件发生时。因此,显示可能会长时间保持静态,直到我(例如)切换工作空间。

似乎有些人只运行两个 dzen bar,其中一个从 shell 脚本获取输出。这是定期更新的唯一方法吗?或者这可以从 xmonad 内部完成(不会变得太疯狂/hacky)?

预计到达时间:我尝试了这个,似乎它应该比实际效果更好:

  1. 创建一个 TChan 用于来自 XMonad 的更新,另一个用于来自轮询 Audacious 的函数的更新;
  2. DynamicLogPP 结构中的 ppOutput 字段设置为写入第一个 TChan;
  3. fork audacious-polling 函数并将其写入第二个 TChan;
  4. 创建一个函数来从两个 TChan 中读取数据(首先检查它们是否为空),然后组合输出。

来自 XMonad 的更新是从 channel 中读取并及时处理的,但来自 Audacious 的更新几乎根本不会注册——最多每五秒左右一次。不过,似乎沿着这些思路的一些方法应该有效。

最佳答案

我知道这是一个老问题,但几天前我来这里寻找这个问题的答案,我想我应该分享我解决这个问题的方法。实际上,您完全可以通过 xmonad 来完成此操作。这有点老套,但我认为它比我遇到的任何替代方案都要好得多。

基本上,我使用了 XMonad.Util.Timer库,它将在指定时间段(在本例中为一秒)后发送 X 事件。然后我就为它写了一个事件钩子(Hook),它再次启动计时器,然后手动运行日志钩子(Hook)。

我还必须使用 XMonad.Util.ExtensibleState库,因为 Timer 使用 id 变量来确保它响应正确的事件,所以我必须在事件之间存储该变量。

这是我的代码:

{-# LANGUAGE DeriveDataTypeable #-}

import qualified XMonad.Util.ExtensibleState as XS
import XMonad.Util.Timer

...

-- wrapper for the Timer id, so it can be stored as custom mutable state
data TidState = TID TimerId deriving Typeable

instance ExtensionClass TidState where
initialValue = TID 0

...

-- put this in your startupHook
-- start the initial timer, store its id
clockStartupHook = startTimer 1 >>= XS.put . TID

-- put this in your handleEventHook
clockEventHook e = do -- e is the event we've hooked
(TID t) <- XS.get -- get the recent Timer id
handleTimer t e $ do -- run the following if e matches the id
startTimer 1 >>= XS.put . TID -- restart the timer, store the new id
ask >>= logHook.config -- get the loghook and run it
return Nothing -- return required type
return $ All True -- return required type

非常简单。我希望这对某人有帮助。

关于haskell - xmonad 的 logHook 可以按设定的时间间隔运行,而不是(仅仅)响应布局事件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11045239/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com