packages feed

Hmpf-0.1: src/Main.hs

module Main where


import qualified Hmpf.Monitor as M
import Hmpf.ApplicationTypes
import Hmpf.LCDProc
import Hmpf.Control
import Hmpf.Tree
import Hmpf.MPDSession
import Hmpf.LIRC 
import Hmpf.Keys
import Hmpf.AudioScrobbler
import Hmpf.Util (pick)
import Hmpf.RelatedArtist
import Hmpf.Config
-----------------
import Control.Concurrent.MVar
import Control.Concurrent
import Data.List -- ( elemIndex )
import Data.Char ( toLower )
import Data.Time
import System.IO
import Control.Exception ( finally )
import qualified Control.Monad.State as S


main :: IO ()
main = do
 hSetBuffering stdin NoBuffering
 hSetBuffering stdout NoBuffering
 runSession programme

programme = do
 load ""
 Hmpf.LIRC.clear
 sm <- lower songMonitor
 scrm <- lower scrobblermonitor
 gen <- lower generation
 lc <- lower loadCache
 lift ( forkIO lc ) -- start thread to load cache
 lift ( forkIO (finally sm (putStrLn "Song monitor has failed"))) -- start thread to update play screen
 lift ( forkIO scrm ) -- start thread to send songs to Last.fm
 lift ( forkIO gen ) -- start thread to add auto-generated songs
 input


input :: Session ()
input = do
 showMusic
 k <- lirc
 case k of 
  TaskSwitcher -> randomAlbum
  Eject -> do
            b <- toggleAutogeneration 
	    let sw = ( toEnum . fromEnum $ b ) :: Switch
	    alert "Auto-generated" ( "playlist :" ++ (show sw) )
  Play -> play>>return()
  Stop -> stop>>return()
  Pause -> pause>>return()
  Timer -> sleep
  NextChapter -> nextSong >> return()
  PrevChapter -> previousSong >> return()
  FastForward -> fastforward >> return()
  Rewind -> rewind >> return()
  VolUp -> vol 10 >>= percent "Vol" >> return()
  VolDown -> vol (-10) >>= percent "Vol" >> return()
  Purple -> updatedb >> alert "Updating the" "music database"
  Enter -> selectFromPlaylist >> return ()
  Red -> do 
          alb <- selectAlbumByTrack
	  case alb of
	   Nothing-> return ()
	   Just alb' -> playAlbum alb'
  AppLauncher -> do
                  alb <- selectAlbum
		  case alb of
		   Nothing -> return ()
		   Just alb' -> playAlbum alb'
  MultiMon -> do
               a <- selectArtist -- choose the artist
	       case a of 
	        Nothing -> return ()
		Just a' -> do 
		  alb <- selectAlbumByArtist a' -- choose the album
		  maybe (return ()) playAlbum alb -- play the album
  _ -> return ()
 input

runSession :: Session a -> IO a
runSession fn = do
 mv <- empty
 S.runStateT ( initialize >> M.initialize >> fn >>= closeSession ) mv >>= ( return . fst )

--Select an artist
selectArtist :: Session (Maybe String)
selectArtist = do
 as <- artists
 let ls = map (map toLower) $ as
 l <- selector ls
 -- Use the Maybe monad here just to be funky
 return ( do
           x <- l
	   i <- elemIndex x ls
	   return ( as !! i )
	)

--Select an album
selectAlbum :: Session (Maybe String)
selectAlbum = do
 as <- albums
 let ls = map (map toLower) $ as
 l <- selector ls
 -- Use the Maybe monad here just to be funky
 return ( do
           x <- l
	   i <- elemIndex x ls
	   return ( as !! i )
	)

--Select an album by artist
selectAlbumByArtist :: String -> Session (Maybe String)
selectAlbumByArtist artist = do
 as <- albumByArtist artist
 let ls = map (map toLower) $ as
 l <- selector ls
 -- Use the Maybe monad here just to be funky
 return ( do
           x <- l
	   i <- elemIndex x ls
	   return ( as !! i )
	)


--Select an album by track
selectAlbumByTrack:: Session (Maybe String)
selectAlbumByTrack = do
 ts <- getTracks
 let ls = map (map toLower) $ ts
 l <- selector ls
 let l' =        ( do
                    x <- l
	            i <- elemIndex x ls
	            return ( ts !! i )
	         )
 case l' of 
  Nothing -> return Nothing
  Just l'' -> do
               albs <- ( Hmpf.MPDSession.albumByTrack l'')
               case albs of
                [] -> return Nothing
                (x:xs) -> return (Just x)


randomAlbum :: Session ()
randomAlbum = do
 alb <- albums >>= (lift . pick)
 playAlbum alb
 Just sng <- currentsong
 alert alb (artist sng)
 lift (putStr $ (artist sng) ++ " -- ")
 lift (putStrLn alb)
 return ()


selectFromPlaylist :: Session ()
selectFromPlaylist = do
 sngs <- playlistinfo
 st <- status
 let ns = map (\(i,t) -> (show i) ++ ". " ++ t ) . zip [1..] . map title $ sngs
     c = case ( song st ) of 
          Nothing -> 0
	  Just i -> i
     xs = (drop c ns) ++ ( take c ns)
 r <- selectByList xs
 case r  of 
  Nothing -> return ()
  Just i' -> (command ( "play " ++ (show $ i' + c ) ) >> return () )




getTracks :: Session [String] 
getTracks = do
 ts <- tracks
 lift ( putStrLn . show . length $ ts)
 let ts' = filter badchars $ ts
 lift ( putStrLn . show . length $ ts')
 return ts'
 where
  badchars = foldr (\c -> \b -> (fromEnum c > 35) && b ) True


sleep :: Session ()
sleep = do
 st <- get
 let t = (timer st + 10) `mod` 70
 put (st { timer = t })
 M.unscheduleAction "sleep"
 if t > 0 
  then    M.scheduleAction "sleep" 
                           ( t * 60 ) 
			   (do command "stop" 
			       st' <- get
			       put st' { timer = 0 } ) >> alert "Timer set" ( (show t) ++ " min" )
  else alert "Timer off" ""