5

dynamicLogWithPPxmonad のステータス バーとしてfromXMonad.Hooks.DynamicLogを dzen2 と共に使用しています。バーに表示したいことの 1 つは、現在再生中のトラックの残り時間 (ある場合) です。この情報は簡単に取得できます。

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そのため、(たとえば) ワークスペースを切り替えるまで、ディスプレイは長時間静的になる可能性があります。

一部の人々は 2 つの dzen バーを実行し、そのうちの 1 つがシェル スクリプトからパイプで出力されているようです。それが定期的な更新を行う唯一の方法ですか?それとも、これを xmonad 内から行うことができますか?

ETA: 私はこれを試しまし

  1. XMonad からの更新用に TChannel を作成し、Audacious をポーリングする関数からの更新用に別の TChannel を作成します。
  2. 最初の TChannel に書き込みを行うfrom 構造体のppOutputフィールドを設定します。PPDynamicLog
  3. audacious-polling 関数を fork し、2 番目の TChannel に書き込みます。
  4. 両方の TChans から読み取る関数を fork し (最初にそれらが空でないことを確認します)、出力を結合します。

XMonad からの更新はチャネルから読み取られ、タイムリーに処理されますが、Audacious からの更新はほとんど登録されません。せいぜい 5 秒ごとです。ただし、これらの線に沿ったいくつかのアプローチが機能するはずのようです。

4

2 に答える 2

6

これは古い質問であることは知っていますが、数日前にこれに対する答えを探してここに来ました。解決方法を共有したいと思いました。実際には、xmonad から完全に実行できます。少しハックですが、私が出会ったどの代替案よりもはるかに優れていると思います.

基本的に、指定した時間 (この場合は 1 秒) 後に X イベントを送信するXMonad.Util.Timerライブラリを使用しました。次に、タイマーを再度開始するイベント フックを作成し、ログ フックを手動で実行します。

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

かなり簡単です。これが誰かの役に立てば幸いです。

于 2013-01-12T20:52:25.300 に答える
2

xmonad内からは実行できません。xmonadの現在のスレッドモデルは少し欠けています(そしてdzenもそうです)。ただし、音楽プレーヤーを定期的にポーリングする別のプロセスを開始してから、dzenマルチプレクサーの1つ(dmplexなど)を使用して、2つのプロセスからの出力を組み合わせることができます。

また、 xmobartaffybarを調べてみることもできます。どちらも、dzenよりも優れたスレッドストーリーを備えています。

提案されたTChanソリューションが正しく機能しない理由については、FFIとgtkのクラッシュコースの「コンベンション」、「外部インポート」、「非スレッドランタイム」のセクションを読んでください。そのxmonadは現在GHCの非スレッドランタイムを使用しています。簡単な答えは、xmonadのメインループがXlibへのFFI呼び出しを行い、Xイベントを待機することです。この呼び出しは、他のすべてのHaskellスレッドが戻るまで実行をブロックします。

于 2012-06-15T06:01:57.130 に答える