vision-0.0.5.0: src/Playlist/Update.hs
-- -*-haskell-*-
-- Vision (for the Voice): an XMMS2 client.
--
-- Author: Oleg Belozeorov
-- Created: 20 Jun. 2010
--
-- Copyright (C) 2010, 2011 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 Playlist.Update
( initUpdate
) where
import Control.Applicative
import Control.Monad
import Control.Monad.Trans
import Data.Maybe
import Control.Concurrent
import Control.Concurrent.STM
import Control.Concurrent.STM.TWatch
import Control.Concurrent.STM.TGVar
import Graphics.UI.Gtk hiding (add)
import XMMS2.Client hiding (playbackStatus)
import XMMS
import Playback
import Utils
import Playlist.Model
import Playlist.Index
initUpdate = do
xcW <- atomically $ newTGWatch connectedV
forkIO $ forever $ do
conn <- atomically $ watch xcW
setPlaylistName Nothing
postGUISync clearModel
when conn $ do
playlistCurrentActive xmms >>* do
setupPlaylist
liftIO $ broadcastPlaylistChanged xmms >>* handleChange
broadcastPlaylistLoaded xmms >>* do
setupPlaylist
persist
psW <- atomically $ newTWatch playbackStatus Nothing
forkIO $ forever $ do
void $ atomically $ watch psW
postGUISync $ do
maybeCT <- getCurrentTrack
name <- fromMaybe "" <$> getPlaylistName
size <- getPlaylistSize
case maybeCT of
Just (ct, cname) | cname == name && ct < size ->
touchPlaylist ct
_ ->
return ()
ctW <- atomically $ newEmptyTWatch currentTrack
let monCT old = do
new <- atomically $ watch ctW
postGUISync $ do
name <- fromMaybe "" <$> getPlaylistName
size <- getPlaylistSize
withJust old $ \(ot, oname) ->
when (oname == name && ot < size) $
touchPlaylist ot
withJust new $ \(nt, nname) ->
when (nname == name && nt < size) $
touchPlaylist nt
monCT new
forkIO $ monCT Nothing
return ?context
setupPlaylist = do
name <- result
liftIO $ do
setPlaylistName $ Just name
requestPlaylist name
requestPlaylist name =
playlistListEntries xmms (Just name) >>* handlePlaylist
handlePlaylist = do
ids <- result
len <- resultLength
liftIO $ do
clearModel
mapM_ addToPlaylist ids
atomically $ modPlaylistSize $ const $ fromIntegral len
requestCurrentTrack
addToPlaylist id = do
n <- listStoreAppend playlistStore id
addToIndex id n
handleChange = do
change <- result
liftIO $ do
name <- fromMaybe "" <$> getPlaylistName
when (name == playlist change) $
case change of
PlaylistRemove { position = p } -> do
listStoreRemove playlistStore p
atomically $ modPlaylistSize pred
PlaylistAdd { mlibId = id } -> do
n <- listStoreAppend playlistStore id
addToIndex id n
atomically $ modPlaylistSize succ
PlaylistInsert { mlibId = id, position = n } -> do
listStoreInsert playlistStore n id
addToIndex id n
atomically $ modPlaylistSize succ
PlaylistMove { mlibId = id, position = o, newPosition = n } -> do
listStoreRemove playlistStore o
listStoreInsert playlistStore n id
addToIndex id n
PlaylistClear {} -> do
clearModel
atomically $ modPlaylistSize $ const 0
_ ->
requestPlaylist name
persist