-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhmtps.hs
77 lines (67 loc) · 2.79 KB
/
hmtps.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import Control.Monad
import Control.Arrow
import System
import System.IO
import System.Directory
import System.FilePath
import System.Posix
import System.Environment
import System.Console.GetOpt
import System.Cmd
import SendFFI
import qualified Data.Map as M
import qualified Data.List as L
import qualified Data.Char as C
import Data.Maybe
convert src dest = rawSystem "/usr/local/mplayer/bin/ffmpeg" ["-i", src, "-vn", "-sn", "-aq", "0", "-y", dest]
fileFilter path = map C.toLower (takeExtension path) `elem` [".mp3", ".flac"]
listFiles pre dir = do
list <- liftM (map (dir </>) . filter ((/= '.') . head)) $ getDirectoryContents (pre </> dir)
rest <- forM list $ \path ->
doesDirectoryExist (pre </> path) >>= \isdir -> if isdir
then listFiles pre path
else if fileFilter path
then liftM ((:[]) . (,) path . name) $ getFileStatus (pre </> path)
else return []
return $ concat rest
where name stat = show (modificationTime stat) ++ "-" ++ show (fileSize stat)
options =
[ Option ['m'] ["music"] (ReqArg sendSongs "DIR") "sync music with device",
Option ['p'] ["playlist"] (ReqArg sendPlaylists "DIR") "produce playlists, copy to device" ]
main = do
name <- getProgName
args <- liftM (getOpt Permute options) getArgs
case args of
([], [], []) -> putStrLn "Nothing to do"
(o, [], []) -> initMTP >> sequence_ o >> endMTP
(_, _, _) -> putStr $ usageInfo name options
sendPlaylists dir = do
items <- liftM (map $ first (filter (/= '/') . head . splitPath)) $ listFiles dir ""
listPlaylists >>= mapM_ (delete . snd)
let playlists = M.toList $ foldr (\(pl, name) -> M.alter (Just . (name:) . fromMaybe []) pl) M.empty items
tracks <- liftM M.fromList listTracks
putStrLn "Sending playlists"
forM_ playlists $ \(pl, hashes) ->
makePlaylist pl $ mapMaybe (flip M.lookup tracks) hashes
sendSong name path =
if map C.toLower (takeExtension path) == ".mp3"
then sendMP3 path name
else do
tmp <- liftM (\n -> "/tmp/hmtps-" ++ show n ++ ".mp3") getProcessID
convert path tmp
sendMP3 tmp name
removeFile tmp
sendSongs dir = do
items <- liftM (map $ \(a, b) -> (b, a)) $ listFiles dir ""
tracks <- listTracks
let itemsm = M.fromList items
putStrLn "Deleting extra tracks"
mapM_ (delete . snd) $ filter (flip M.notMember itemsm . fst) tracks
let tracksm = M.fromList tracks
let copy = M.toList $ foldr (\(name, path) -> M.alter (Just . (path:) . fromMaybe []) name) M.empty $ filter (flip M.notMember tracksm . fst) items
forM_ copy $ \(name, paths) ->
when (length paths /= 1) $ putStrLn $ "Warning: apparent duplicates " ++ show paths
let amount = length copy
forM_ (zip [1..] copy) $ \(count, (name, path:_)) -> do
putStrLn $ "(" ++ show count ++ "/" ++ show amount ++ ") " ++ path
sendSong name $ dir </> path