vision-0.0.2.2: src/Playback.hs
-- -*-haskell-*-
-- Vision (for the Voice): an XMMS2 client.
--
-- Author: Oleg Belozeorov
-- Created: 20 Jun. 2010
--
-- Copyright (C) 2010 Oleg Belozeorov
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License as
-- published by the Free Software Foundation; either version 3 of
-- the License, or (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- General Public License for more details.
--
module Playback
( initPlayback
, onPlaybackStatus
, onPlaybackStatusAdd
, onCurrentTrack
, getPlaybackStatus
, getCurrentTrack
, startPlayback
, pausePlayback
, stopPlayback
, restartPlayback
, prevTrack
, nextTrack
, requestCurrentTrack
) where
import Control.Concurrent.MVar
import Control.Monad.Trans
import XMMS2.Client
import XMMS
import Handler
import Context
import Utils
data State
= State { sCurrentTrack :: Maybe (Int, String)
, sStatus :: Maybe PlaybackStatus
}
data Playback
= Playback { pState :: MVar State
, pOnPlaybackStatus :: HandlerMVar (Maybe PlaybackStatus)
, pOnCurrentTrack :: HandlerMVar (Maybe (Int, String))
}
state = pState context
onPlaybackStatus = onHandler (pOnPlaybackStatus context)
onPlaybackStatusAdd f = do
id <- onPlaybackStatus . add $ f
f =<< getPlaybackStatus
return id
onCurrentTrack = onHandler (pOnCurrentTrack context)
getPlaybackStatus =
withMVar state $ return . sStatus
getCurrentTrack =
withMVar state $ return . sCurrentTrack
initPlayback = do
context <- initContext
let ?context = context
onServerConnectionAdd . ever $ \conn ->
if conn
then do
broadcastPlaybackStatus xmms >>* do
liftIO requestStatus
return True
requestStatus
broadcastPlaylistCurrentPos xmms >>* do
liftIO $ requestCurrentTrack
return True
requestCurrentTrack
else
resetState
return ?context
initContext = do
state <- newMVar makeState
onPlaybackStatus <- makeHandlerMVar
onCurrentTrack <- makeHandlerMVar
return $ augmentContext
Playback { pState = state
, pOnPlaybackStatus = onPlaybackStatus
, pOnCurrentTrack = onCurrentTrack
}
makeState =
State { sCurrentTrack = Nothing
, sStatus = Nothing
}
resetState = do
modifyMVar_ state $ const $ return makeState
invokeOnPlaybackStatus
setStatus s = do
modifyMVar_ state $ \state ->
return state { sStatus = s }
invokeOnPlaybackStatus
requestStatus =
playbackStatus xmms >>* do
status <- result
liftIO . setStatus $ Just status
return False
requestCurrentTrack =
playlistCurrentPos xmms Nothing >>* do
new <- catchResult Nothing (Just . mapFst fromIntegral)
liftIO $ do
old <- modifyMVar state $ \state ->
return (state { sCurrentTrack = new }, sCurrentTrack state)
onCurrentTrack $ invoke old
return False
startPlayback False = do
playbackStart xmms
return ()
startPlayback True = do
ps <- getPlaybackStatus
case ps of
Just StatusPlay ->
playbackTickle xmms
Just StatusPause -> do
playbackTickle xmms
playbackStart xmms
playbackTickle xmms
_ ->
playbackStart xmms
return ()
pausePlayback = do
playbackPause xmms
return ()
stopPlayback = do
playbackStop xmms
return ()
nextTrack = do
playlistSetNextRel xmms 1
playbackTickle xmms
return ()
prevTrack = do
playlistSetNextRel xmms (-1)
playbackTickle xmms
return ()
invokeOnPlaybackStatus =
onPlaybackStatus . invoke =<< getPlaybackStatus
restartPlayback = do
playbackTickle xmms
return ()