2012-06-15 6 views
5

dynamicLogWithPPXMonad.Hooks.DynamicLog에서 xzenad의 상태 표시 줄과 함께 dzen2와 함께 사용하고 있습니다. 바에 표시하고 싶은 것들 중 하나는 현재 재생중인 트랙에 남아있는 시간 (대담한 경우)입니다. 이 정보를 얻는 것은 쉽다 :xmonad의 logHook은 (단지) 레이아웃 이벤트에 대한 응답이 아니라 설정된 간격으로 실행될 수 있습니까?

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 실행됩니다 때만 실행됩니다, 그리고 적절한 이벤트가 파이크 내려 오면 그에만 발생합니다 제외 . 따라서 I (예 :) 작업 영역을 전환 할 때까지 디스플레이가 오랫동안 정적 일 수 있습니다.

일부 사람들은 단지 두 개의 dzen bar를 실행하는 것처럼 보이는데, 하나는 출력을 쉘 스크립트에서 파이프하는 것입니다. 이것이 정기적 인 업데이트를받는 유일한 방법입니까? 또는 xmonad에서 (너무 미친/해키하지 않고)이 작업을 수행 할 수 있습니까?

ETA : 나는 그것보다 더 나은 작동합니다 것처럼 보인다 ,이 시도 :

  1. XMonad에서 업데이트에 대한 TChan를 작성하고 대담한 함수 폴링에서 업데이트를 다른;
  2. DynamicLogPP 구조의 ppOutput 필드를 첫 번째 TChan에 쓰도록 설정하십시오.
  3. 대담한 폴링 기능을 포크하여 두 번째 TChan에 쓰도록합니다.
  4. 두 TChans에서 읽는 함수를 fork (먼저 비어 있지 않은지 확인)하고 출력을 결합합니다. XMonad에서

업데이트 채널에서 읽고 적시에 처리했지만 대담한에서 업데이트는 거의 매 5 정도 초 기껏 모든 —에 등록되지 않은 있습니다. 비록 이러한 라인을 따라 접근하는 것이 효과가있는 것처럼 보입니다.

+0

제안 된'TChan' 솔루션 및 다중 스레드 기반의 다른 솔루션이 제대로 작동하지 않는 이유에 대한 설명으로 내 대답을 업데이트했습니다. –

+0

감사합니다. –

답변

6

나는 이것이 낡은 질문이라는 것을 알고 있지만, 며칠 전에 이것에 대한 답을 찾기 위해 여기에 왔는데, 나는 그것을 해결하는 방법을 나누겠다고 생각했다. 당신은 실제로 xmonad에서 그것을 완전히 할 수 있습니다. 그것은 조금 해키지만, 내가 본 모든 대안보다 훨씬 좋다고 생각합니다.

기본적으로 나는 XMonad.Util.Timer 라이브러리를 사용했으며이 라이브러리는 지정된 기간 (이 경우 1 초) 후에 X 이벤트를 보냅니다.그런 다음 타이머 훅을 다시 작성하여 타이머를 다시 시작한 다음 수동으로 로그 훅을 실행합니다.

또한 Timer가 id 변수를 사용하여 올바른 이벤트에 응답하는지 확인하기 때문에 XMonad.Util.ExtensibleState 라이브러리를 사용해야하므로 이벤트 사이에 해당 변수를 저장해야합니다. 매우 간단

{-# 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 

:

여기 내 코드입니다. 나는 이것이 누군가에게 도움이되기를 바랍니다.

+0

이 코드를 사용하는 다른 사용자는'import Data.Monoid'도 입력해야합니다 – user316146

+0

이렇게하면 xmonad를 다시 시작하는 기능이 중단됩니다. 다시 시작한 프로세스가 이전 프로세스의 이벤트를 처리 할 수 ​​없다고 가정합니다. 프로세스 재시작). 종료가 시작되면 종료를 실행하고 종료하는 동안 마지막 이벤트가 처리 될 때까지 대기해야합니다. – akosch

+0

@akosch 오 와우, 나는이 질문을 잊어 버렸다. 예, 다시 시작하지 못하게하고이 대답을 올린 후 개인 설정을 변경했습니다. 요즘에는 매 xmonad에 X 이벤트를 보내는 Conky 인스턴스가 있습니다. 이벤트에는 하드웨어 정보가 포함되어 있습니다.이 정보도 dzen에 표시됩니다.하지만 요점은 지금 외부 프로그램을 사용하여 업데이트를 트리거하고 있다는 것입니다. 하지만 재시작이 필요하다면 어쩌면 답이 코드로 업데이트되어야합니까? – DarthFennec

2

xmonad에서 실행할 수 없습니다. xmonad의 현재 스레딩 모델은 약간 부족합니다 (그래서 dzen입니다). 그러나 음악 플레이어를 주기적으로 폴링하는 별도의 프로세스를 시작한 다음 dzen 멀티플렉서 중 하나 (예 : dmplex)를 사용하여 두 프로세스의 출력을 결합 할 수 있습니다.

xmobartaffybar을 살펴볼 수도 있습니다. 둘 다 dzen보다 더 좋은 스레딩 스토리를 가지고 있습니다. xmonad 염두에두고

my crash course on the FFI and gtk에서 "비 스레드 런타임을"당신의 제안 TChan 솔루션이 제대로 작동하지 않습니다, 당신은 섹션 "규칙", "외국 수입"을 읽어보십시오, 그리고 왜에 관해서

, 현재 GHC의 비 스레드 런타임을 사용합니다. 짧은 대답은 xmonad의 메인 루프가 X 이벤트를 기다리는 Xlib에 대한 FFI 호출을 만든다는 것입니다. 이 호출은 다른 Haskell 쓰레드가 돌아올 때까지 실행을 차단한다.