musicScroll-0.1.0.0: src/MusicScroll/MPRIS.hs
{-# language OverloadedStrings, ScopedTypeVariables, NamedFieldPuns #-}
module MusicScroll.MPRIS where
import Control.Concurrent.STM (atomically)
import Control.Concurrent.STM.TBQueue (TBQueue)
import qualified Control.Concurrent.STM.TBQueue as TBQueue
import Control.Concurrent.STM.TMVar (TMVar, takeTMVar,
newEmptyTMVar, putTMVar)
import qualified Control.Exception as Exc
import Control.Monad (when)
import DBus.Client
import MusicScroll.TrackInfo
import MusicScroll.DBusNames
dbusThread :: TBQueue TrackInfo -> IO a
dbusThread outChan =
Exc.bracket connectSession disconnect (flip go Nothing)
where
go :: Client -> Maybe TrackInfo -> IO a
go client lastTrack =
do mtrack <- tryGetInfo client
case mtrack of
Right track ->
do writeIfNotRepeated outChan lastTrack track
waitForChange client
go client (pure track)
Left _ -> waitForChange client >> go client lastTrack
writeIfNotRepeated :: TBQueue TrackInfo -> Maybe TrackInfo -> TrackInfo
-> IO ()
writeIfNotRepeated outChan maybeLast current = do
let query = (/=) <$> maybeLast <*> pure current
when (maybe True id query) $
atomically (TBQueue.writeTBQueue outChan current)
waitForChange :: Client -> IO ()
waitForChange client =
do trigger <- atomically newEmptyTMVar
disarmHandler <- gotSignalOfChange client trigger
_ <- atomically $ takeTMVar trigger
removeMatch client disarmHandler
gotSignalOfChange :: Client -> TMVar () -> IO SignalHandler
gotSignalOfChange client trigger =
let rule = matchAny
{ matchPath = pure mediaObject
, matchInterface = pure "org.freedesktop.DBus.Properties"
, matchMember = pure "PropertiesChanged" }
in addMatch client rule (\_ -> atomically ( putTMVar trigger () ))