module Manatee.Extension.Mplayer.PlaylistBuffer where
import Audio.TagLib.TagLib
import Control.Applicative
import Control.Concurrent.STM
import Control.Monad (liftM, unless)
import DBus.Client hiding (Signal)
import Data.ByteString.UTF8
import Data.Maybe (maybeToList)
import Data.Ord (comparing)
import Data.Time
import Data.Typeable
import Graphics.UI.Gtk.General.Enums
import Graphics.UI.Gtk.ModelView.TreeSortable
import Manatee.Core.Types
import Manatee.Extension.Mplayer.PageMode
import Manatee.Extension.Mplayer.DBus
import Manatee.Toolkit.General.Basic
import Manatee.Toolkit.General.DBus
import Manatee.Toolkit.General.List
import Manatee.Toolkit.General.Maybe
import Manatee.Toolkit.General.Process
import Manatee.Toolkit.Gio.Gio
import System.FilePath
import System.GIO.File.File
import System.GIO.File.FileInfo
import System.Posix.Process
import Text.Regex.TDFA
import qualified Data.Map as M
data PlaylistBuffer =
PlaylistBuffer {playlistBufferName :: TVar String
,playlistBufferClient :: Client
,playlistBufferPageId :: PageId
,playlistBufferMode :: PageMode
,playlistBufferInfos :: TVar [MultimediaInfo]
,playlistBufferOptions :: [(MultimediaOption, SortColumnId)]
,playlistBufferSortStatus :: TVar (MultimediaOption, SortType)
}
deriving Typeable
data MultimediaInfo =
MultimediaInfo {miFilePath :: ByteString
,miArtist :: String
,miTitle :: String
,miAlbum :: String
,miTrack :: Int
,miGenre :: String
,miYear :: Int
,miDuration :: Int
,miBitRate :: Int
,miSampleRate :: Int
,miChannels :: Int
,miComment :: String
}
deriving Show
class MultimediaInfoClass a where
getColumnTitle :: a -> String
getColumnMaxWidth :: a -> Maybe Int
getCellText :: a -> MultimediaInfo -> String
getCellXAlign :: a -> Float
compareRow :: a -> MultimediaInfo -> MultimediaInfo -> IO Ordering
instance MultimediaInfoClass MultimediaOption where
getColumnTitle MOArtist = "Artist"
getColumnTitle MOTitle = "Title"
getColumnTitle MOAlbum = "Album"
getColumnTitle MOTrack = "Track"
getColumnTitle MOGenre = "Genre"
getColumnTitle MOYear = "Year"
getColumnTitle MODuration = "Duration"
getColumnTitle MOBitRate = "Bit Rate"
getColumnTitle MOSampleRate = "Sample Rate"
getColumnTitle MOChannels = "Channels"
getColumnTitle MOComment = "comment"
getColumnMaxWidth MOArtist = Just 200
getColumnMaxWidth MOTitle = Just 400
getColumnMaxWidth MOAlbum = Just 400
getColumnMaxWidth MOTrack = Nothing
getColumnMaxWidth MOGenre = Nothing
getColumnMaxWidth MOYear = Nothing
getColumnMaxWidth MODuration = Nothing
getColumnMaxWidth MOBitRate = Nothing
getColumnMaxWidth MOSampleRate = Nothing
getColumnMaxWidth MOChannels = Nothing
getColumnMaxWidth MOComment = Nothing
getCellText MOArtist info = miArtist info
getCellText MOTitle info = miTitle info
getCellText MOAlbum info = miAlbum info
getCellText MOTrack info = if miTrack info == 0 then "" else show $ miTrack info
getCellText MOGenre info = miGenre info
getCellText MOYear info = if miYear info == 0 then "" else show $ miYear info
getCellText MODuration info = showDuration (miDuration info)
getCellText MOBitRate info = show (miBitRate info) ++ " kb/s"
getCellText MOSampleRate info = show (miSampleRate info) ++ " HZ"
getCellText MOChannels info = show $ miChannels info
getCellText MOComment info = miComment info
getCellXAlign MOArtist = 0.0
getCellXAlign MOTitle = 0.0
getCellXAlign MOAlbum = 0.0
getCellXAlign MOTrack = 1.0
getCellXAlign MOGenre = 0.0
getCellXAlign MOYear = 1.0
getCellXAlign MODuration = 0.0
getCellXAlign MOBitRate = 0.0
getCellXAlign MOSampleRate = 0.0
getCellXAlign MOChannels = 0.0
getCellXAlign MOComment = 0.0
compareRow MOArtist row1 row2 = return $ comparing miArtist row1 row2
compareRow MOTitle row1 row2 = return $ comparing miTitle row1 row2
compareRow MOAlbum row1 row2 = return $ playlistAlbumCompare row1 row2
compareRow MOTrack row1 row2 = return $ comparing miTrack row1 row2
compareRow MOGenre row1 row2 = return $ comparing miGenre row1 row2
compareRow MOYear row1 row2 = return $ comparing miYear row1 row2
compareRow MODuration row1 row2 = return $ comparing miDuration row1 row2
compareRow MOBitRate row1 row2 = return $ comparing miBitRate row1 row2
compareRow MOSampleRate row1 row2 = return $ comparing miSampleRate row1 row2
compareRow MOChannels row1 row2 = return $ comparing miChannels row1 row2
compareRow MOComment row1 row2 = return $ comparing miComment row1 row2
data MultimediaOption = MOArtist
| MOTitle
| MOAlbum
| MOTrack
| MOGenre
| MOYear
| MODuration
| MOBitRate
| MOSampleRate
| MOChannels
| MOComment
deriving (Eq, Show, Read)
playlistBufferNew :: FilePath -> Client -> PageId -> IO PlaylistBuffer
playlistBufferNew path client pageId = do
infos <- playlistBufferGenerateInfos path
let sendPlaySignal = unless (null infos) $ do
let filepath = miFilePath $ head infos
processId <- getProcessID
mkMplayerDaemonSignal client Play (PlayArgs filepath processId)
mkMplayerClientMatchRule client
(DaemonProcessStartup,
\ DaemonProcessStartupArgs -> sendPlaySignal)
ifM (isBusNameExist mplayerDaemonBusName)
sendPlaySignal
(do
processId <- getProcessID
putStrLn "No mplayer daemon process, starting one."
runProcess_ "manatee-mplayer-daemon" [show processId])
PlaylistBuffer <$> newTVarIO path
<*> pure client
<*> pure pageId
<*> pure mplayerMode
<*> newTVarIO infos
<*> pure (pairPred [MOTitle, MOAlbum, MOArtist, MOYear, MOTrack, MOBitRate, MODuration])
<*> newTVarIO (MOAlbum, SortAscending)
playlistBufferGenerateInfos :: FilePath -> IO [MultimediaInfo]
playlistBufferGenerateInfos path
| directoryDoesExist (fromString path)
= directoryGetFilesRecursive (fromString path)
>>= concatMapM filterMultimediaFile
| fileDoesExist (fromString path)
= filterMultimediaFile (fromString path)
where filterMultimediaFile file = do
isMFile <- isMultimediaFile file
if isMFile
then liftM maybeToList $ getMultimediaInfo file
else return []
isMultimediaFile :: ByteString -> IO Bool
isMultimediaFile path = do
let file = fileFromPath path
fileInfo <- fileQueryInfo file "*" [] Nothing
let contentType = fileInfoGetContentType fileInfo
return $
case contentType of
Just ct -> ct =~ ("^(audio|video)/.+" :: String)
Nothing -> False
getMultimediaInfo :: ByteString -> IO (Maybe MultimediaInfo)
getMultimediaInfo path =
tagFileOpen path
>?>=> \tf ->
tagFileGetTag tf
>?>=> \t ->
tagFileGetAudioProperties tf
>?>=> \p -> liftM Just $
MultimediaInfo <$> pure path
<*> tagGetArtist t
<*> getMultimediaTitle (toString path) t
<*> tagGetAlbum t
<*> tagGetTrack t
<*> tagGetGenre t
<*> tagGetYear t
<*> audioPropertiesGetDuration p
<*> audioPropertiesGetBitRate p
<*> audioPropertiesGetSampleRate p
<*> audioPropertiesGetChannels p
<*> tagGetComment t
showDuration :: Int -> String
showDuration =
show . timeToTimeOfDay . secondsToDiffTime . fromIntegral
getMultimediaTitle :: FilePath -> Tag -> IO String
getMultimediaTitle path tag = do
title <- tagGetTitle tag
return $ if null title
then takeBaseName path
else title
playlistAlbumCompare :: MultimediaInfo -> MultimediaInfo -> Ordering
playlistAlbumCompare row1 row2
| mAlbum1 /= mAlbum2
= compare mAlbum1 mAlbum2
| mArtist1 /= mArtist2
= compare mArtist1 mArtist2
| mTrack1 /= mTrack2
= compare mTrack1 mTrack2
| otherwise
= compare mTitle1 mTitle2
where
mAlbum1 = miAlbum row1
mAlbum2 = miAlbum row2
mArtist1 = miArtist row1
mArtist2 = miArtist row2
mTrack1 = miTrack row1
mTrack2 = miTrack row2
mTitle1 = miTitle row1
mTitle2 = miTitle row2