diff --git a/Radio.hs b/Radio.hs
--- a/Radio.hs
+++ b/Radio.hs
@@ -26,13 +26,15 @@
 import           Data.Conduit.Binary (sinkFile)
 import           Data.Yaml
 import           Network.HTTP.Conduit hiding (path)
-import           Network.MPD hiding (play, Value)
+import           Network.MPD hiding (play, pause, Value)
 import qualified Network.MPD as MPD
 import           System.Directory (doesFileExist, getHomeDirectory)
 import           System.IO
 import           System.IO.Unsafe (unsafePerformIO)
 import           System.Log.FastLogger
+import           System.Process
 
+
 eof :: MVar ()
 eof = unsafePerformIO newEmptyMVar
 
@@ -40,8 +42,11 @@
     { artist    :: String
     , album     :: String
     , title     :: String
-    }
+    } 
 
+instance Show SongMeta where
+    show meta = artist meta ++ " - " ++ title meta 
+
 class FromJSON a => Radio a where
     data Param a :: *
 
@@ -77,98 +82,128 @@
             Left err -> print err
 
     play :: Logger -> Param a -> [a] -> IO ()
-    play logger reqData [] = getPlaylist reqData >>= play logger reqData
-    play logger reqData (x:xs)
-      | playable x = do
-        surl <- songUrl reqData x
-        print surl
-        when (surl /= "") $ do
-            let song = artist (songMeta x) ++ " - " ++ title (songMeta x)
-            writeLog logger song 
-            getStateFile >>= flip writeFile song
-            -- Report song played if needed
-            when (reportRequired x) $ void (forkIO $ reportLoop reqData x)
-            mpdLoad $ Path $ C.pack surl
-            takeMVar eof                     -- Finished
-        play logger reqData xs
-      | otherwise = do
-        surl <- songUrl reqData x
-        print surl
-        req <- parseUrl surl
-        home <- getLordDir
-        manager <- newManager def
-        forkIO $ E.catch 
-            (do
-                let song = artist (songMeta x) ++ " - " ++ title (songMeta x)
-                writeLog logger song 
-                getStateFile >>= flip writeFile song
-                -- Report song played if needed
-                when (reportRequired x) $ void (forkIO $ reportLoop reqData x)
+    play logger reqData xxs = do
+        st <- withMPD status
+        case st of
+            Right _ -> playWithMPD logger reqData xxs
+            Left  _ -> playWithMplayer logger reqData xxs
 
-                runResourceT $ do 
-                    res <- http req manager
-                    responseBody res $$+- sinkFile (home ++ "/lord.m4a")
-                -- This will block until eof.
+playWithMPD :: Radio a => Logger -> Param a -> [a] -> IO ()
+playWithMPD logger reqData [] = 
+    getPlaylist reqData >>= playWithMPD logger reqData
+playWithMPD logger reqData (x:xs)
+    | playable x = loadAndPlay logger reqData (x:xs)
+    | otherwise = downloadAndPlay logger reqData (x:xs)
 
-                putMVar eof ())
-            (\e -> do
-                print (e :: E.SomeException)
-                writeLog logger $ show e
-                play logger reqData xs
-                )
-        threadDelay (3*1000000)
-        mpdLoad m4a
-        play logger reqData xs
-      where
-        m4a = "lord/lord.m4a"
+loadAndPlay :: Radio a => Logger -> Param a -> [a] -> IO ()
+loadAndPlay logger reqData [] = 
+    getPlaylist reqData >>= loadAndPlay logger reqData
+loadAndPlay logger reqData (x:xs) = do
+    surl <- songUrl reqData x
+    print surl
+    when (surl /= "") $ do
+        logAndReport logger reqData x
+        mpdLoad $ Path $ C.pack surl
+        takeMVar eof                     -- Finished
+    loadAndPlay logger reqData xs
+  where
+    mpdLoad :: Path -> IO ()
+    mpdLoad path = do
+        withMPD $ do
+            clear
+            add path
+        withMPD $ MPD.play Nothing
+        mpdPlay
 
-        mpdLoad :: Path -> IO ()
-        mpdLoad path
-          | playable x = do
-            withMPD $ do
+    mpdPlay :: IO ()
+    mpdPlay = do
+        st <- mpdState
+        if st == Right Stopped 
+            then putMVar eof ()
+            else mpdPlay
+
+downloadAndPlay :: Radio a => Logger -> Param a -> [a] -> IO ()
+downloadAndPlay logger reqData [] = 
+    getPlaylist reqData >>= downloadAndPlay logger reqData
+downloadAndPlay logger reqData (x:xs) = do
+    surl <- songUrl reqData x
+    print surl
+    req <- parseUrl surl
+    home <- getLordDir
+    manager <- newManager def
+    forkIO $ E.catch 
+        (do
+            logAndReport logger reqData x
+
+            runResourceT $ do 
+                res <- http req manager
+                responseBody res $$+- sinkFile (home ++ "/lord.m4a")
+            -- This will block until eof.
+
+            putMVar eof ())
+        (\e -> do
+            print (e :: E.SomeException)
+            writeLog logger $ show e
+            downloadAndPlay logger reqData xs
+            )
+    threadDelay (3*1000000)
+    mpdLoad m4a
+    downloadAndPlay logger reqData xs
+  where
+    m4a = "lord/lord.m4a"
+
+    mpdLoad :: Path -> IO ()
+    mpdLoad path = do
+        s <- withMPD $ do
                 clear
+                update [Path "lord"]
                 add path
-            withMPD $ MPD.play Nothing
-            mpdPlay
-          | otherwise = do
-            s <- withMPD $ do
-                    clear
-                    update [Path "lord"]
-                    add path
-            case s of
-                Right _ -> do
-                    withMPD $ MPD.play Nothing
-                    mpdPlay
-                _                  -> mpdLoad path
+        case s of
+            Right _ -> do
+                withMPD $ MPD.play Nothing
+                mpdPlay
+            _                  -> mpdLoad path
 
-        mpdState :: IO (MPD.Response State)
-        mpdState = do
-            withMPD $ idle [PlayerS]   
-            -- This will block until paused/finished.
+    mpdPlay :: IO ()
+    mpdPlay = do
+        st <- mpdState
+        bd <- isEmptyMVar eof
+        if st == Right Stopped 
+            then if bd 
+                    then do                              -- Slow Network
+                        withMPD $ MPD.play Nothing
+                        mpdPlay
+                    else do
+                        withMPD clear
+                        takeMVar eof                     -- Finished
+            else mpdPlay                                 -- Pause
 
-            st <- liftM stState <$> withMPD status
-            print st
-            return st
+playWithMplayer :: Radio a => Logger -> Param a -> [a] -> IO ()
+playWithMplayer logger reqData [] = 
+    getPlaylist reqData >>= playWithMplayer logger reqData
+playWithMplayer logger reqData (x:xs) = do
+    surl <- songUrl reqData x
+    when (surl /= "") $ do
+        logAndReport logger reqData x
+        let sh = "mplayer -cache 2048 -cache-min 5 -novideo " ++ surl
+        void $ waitForProcess =<< runCommand sh
+    playWithMplayer logger reqData xs
 
-        mpdPlay :: IO ()
-        mpdPlay
-          | playable x = do
-            st <- mpdState
-            if st == Right Stopped 
-                then putMVar eof ()
-                else mpdPlay
-          | otherwise = do
-            st <- mpdState
-            bd <- isEmptyMVar eof
-            if st == Right Stopped 
-                then if bd 
-                        then do                              -- Slow Network
-                            withMPD $ MPD.play Nothing
-                            mpdPlay
-                        else do
-                            withMPD clear
-                            takeMVar eof                     -- Finished
-                else mpdPlay                                 -- Pause
+logAndReport :: Radio a => Logger -> Param a -> a -> IO ()
+logAndReport logger reqData x = do
+    writeLog logger (show $ songMeta x) 
+    getStateFile >>= flip writeFile (show $ songMeta x)
+    -- Report song played if needed
+    when (reportRequired x) $ void (forkIO $ reportLoop reqData x)
+
+mpdState :: IO (MPD.Response State)
+mpdState = do
+    withMPD $ idle [PlayerS]   
+    -- This will block until paused/finished.
+
+    st <- liftM stState <$> withMPD status
+    print st
+    return st
 
 class (Radio a, ToJSON (Param a), ToJSON (Config a)) => NeedLogin a where
     login :: String -> IO (Param a)
diff --git a/Radio/Cmd.hs b/Radio/Cmd.hs
--- a/Radio/Cmd.hs
+++ b/Radio/Cmd.hs
@@ -19,7 +19,6 @@
 
 import qualified Radio
 
-type Param a = Radio.Param Cmd
 
 data Cmd = Cmd
     { sc_id :: Int
@@ -42,7 +41,7 @@
 instance Radio.Radio Cmd where
     data Param Cmd = Genre String
 
-    parsePlaylist val = do
+    parsePlaylist val =
         case fromJSON val of
             Success s -> s
             Error err -> error $ "Parse playlist failed: " ++ show err
@@ -64,8 +63,8 @@
         let req = initReq { method = "GET"
                           , queryString = renderQuery False query
                           }
-        E.catch (do withManager $ \manager -> 
-                        httpLbs req { redirectCount = 0 } manager >> return "")
+        E.catch (withManager $ \manager -> 
+                    httpLbs req { redirectCount = 0 } manager >> return "")
                 (\e -> case e of
                     (StatusCodeException s hdr _) ->
                         if s == status302 then redirect hdr 
@@ -116,4 +115,4 @@
     putStrLn $ foldr1 f (take 4 gs)
     pprGenres $ drop 4 gs
   where
-    f a b = a ++ (concat $ take (20 - length(a)) $ repeat " ") ++ b
+    f a b = a ++ concat (replicate (20 - length a) " ") ++ b
diff --git a/Radio/Douban.hs b/Radio/Douban.hs
--- a/Radio/Douban.hs
+++ b/Radio/Douban.hs
@@ -23,7 +23,6 @@
 
 import qualified Radio
 
-type Param a = Radio.Param Douban
 
 data Douban = Douban 
     { picture :: String
@@ -72,8 +71,8 @@
 
 musicianID :: String -> IO (Maybe String)
 musicianID mname = do
-    let rurl = "http://music.douban.com/search/" ++ 
-              (C.unpack $ urlEncode True (C.pack $ encodeString mname))
+    let rurl = "http://music.douban.com/subject_search/?search_text=" ++ 
+              C.unpack (urlEncode True (C.pack $ encodeString mname))
     rsp <- simpleHttp rurl
     let cursor = fromDocument $ parseLBS rsp
         href = cursor $// element "a" 
@@ -174,7 +173,7 @@
   where 
     rurl = "http://douban.fm/j/explore/search?query=" ++ 
           -- encodeString: encode chinese characters
-          (C.unpack $ urlEncode True (C.pack $ encodeString key))
+          C.unpack (urlEncode True (C.pack $ encodeString key))
 
 
 search' :: String -> IO [Channel]
diff --git a/Radio/EightTracks.hs b/Radio/EightTracks.hs
--- a/Radio/EightTracks.hs
+++ b/Radio/EightTracks.hs
@@ -16,8 +16,10 @@
 import           Data.Maybe (fromJust)
 import           Data.Yaml hiding (decode)
 import           Data.CaseInsensitive (mk)
+import           Data.Char (isDigit)
 import           Data.Conduit (($$+-))
-import           Data.Conduit.Attoparsec (sinkParser)
+import           Data.Conduit.Attoparsec (sinkParser, ParseError)
+import qualified Data.List as L
 import           GHC.Generics (Generic)
 import           Network.HTTP.Types 
 import           Network.HTTP.Conduit
@@ -41,8 +43,10 @@
 verHdr = (mk "X-Api-Version", "3")
 keyHdr = (mk "X-Api-Key", C.pack apiKey)
 
-type Param a = Radio.Param EightTracks
+type ETParam = Radio.Param EightTracks
 
+-- | Response from http://8tracks.com/sets/new.json
+-- `play_token` is the value of interest
 data PlaySession = PlaySession
     { play_token            :: String
     , status                :: String
@@ -50,15 +54,16 @@
     , notices               :: Maybe String
     , api_version           :: Int
     } deriving (Show, Generic)
+instance FromJSON PlaySession
 
-data EightTracks = EightTracks 
-    { id                    :: Int
-    , track_file_stream_url :: String
-    , name                  :: String
-    , performer             :: String
-    , release_name          :: String
-    , url                   :: String
+-- | Response from /play.json /next.json
+-- `track` is the value of interest
+data PlayResponse = PlayResponse
+    { play_set               :: MixSet
+    , play_status            :: String
     } deriving (Show, Generic)
+instance FromJSON PlayResponse where
+    parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = drop 5 }
 
 data MixSet = MixSet
     { at_beginning          :: Bool
@@ -67,18 +72,27 @@
     , skip_allowed          :: Bool
     , track                 :: EightTracks
     } deriving (Show, Generic)
+instance FromJSON MixSet
 
-data MixResponse = MixResponse
-    { mix_set               :: MixSet
-    , mix_status            :: String
+data EightTracks = EightTracks 
+    { id                    :: Int
+    , track_file_stream_url :: String
+    , name                  :: String
+    , performer             :: String
+    , release_name          :: String
+    , url                   :: String
     } deriving (Show, Generic)
-
-instance FromJSON PlaySession
 instance FromJSON EightTracks
-instance FromJSON MixSet
 
-instance FromJSON MixResponse where
-    parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = drop 4 }
+-- | Response from http://8tracks.com/mixes/14.json or
+-- http://8tracks.com/dp/electrominimalicious.json
+-- `info_mix` is the value of interest
+data MixInfo = MixInfo
+    { info_mix               :: Exp.Mix
+    , info_status            :: String
+    } deriving (Show, Generic)
+instance FromJSON MixInfo where
+    parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = drop 5 }
 
 instance Radio.Radio EightTracks where
     data Param EightTracks = Token
@@ -90,7 +104,7 @@
 
     parsePlaylist val =
         case fromJSON val of
-            Success s -> [track $ mix_set s]
+            Success s -> [track $ play_set s]
             Error err -> error $ "Parse playlist failed: " ++ show err
 
     -- Request play.json will record current mix to listening history.
@@ -101,14 +115,14 @@
             rurl <- if justStarted
                 then do
                     putMVar running ()
-                    return $ "http://8tracks.com/sets/" ++ (show $ playToken tok)  ++ "/play.json"
+                    return $ "http://8tracks.com/sets/" ++ show (playToken tok) ++ "/play.json"
                 else
-                    return $ "http://8tracks.com/sets/" ++ (show $ playToken tok)  ++ "/next.json"
+                    return $ "http://8tracks.com/sets/" ++ show (playToken tok) ++ "/next.json"
             getPlaylist' rurl)
         (\e -> do
             -- When reached the last track in this mix. Play it again
             print (e :: E.SomeException) 
-            let rurl = "http://8tracks.com/sets/" ++ (show $ playToken tok)  ++ "/play.json"
+            let rurl = "http://8tracks.com/sets/" ++ show (playToken tok) ++ "/play.json"
             getPlaylist' rurl)
       where
         usrHdr = (mk "X-User-Token", C.pack $ userToken tok)
@@ -143,15 +157,16 @@
         res <- withManager $ \manager -> httpLbs req manager
         print $ responseBody res
       where
-        rurl = "http://8tracks.com/sets/" ++ (show $ playToken tok) ++ "/report.json"
+        rurl = "http://8tracks.com/sets/" ++ show (playToken tok) ++ "/report.json"
         query = [ ("track_id", C.pack $ show $ id x)
                 , ("mix_id", C.pack $ show $ mixId tok) ]
 
-instance FromJSON (Radio.Param EightTracks)
-instance ToJSON (Radio.Param EightTracks)
+instance FromJSON ETParam
+instance ToJSON ETParam
 
 instance NeedLogin EightTracks where
     createSession strMixId email pwd = do
+        mId <- getMixId strMixId
         initReq <- parseUrl rurl
         let req = initReq { method = "POST"
                           , queryString = renderSimpleQuery False query
@@ -166,13 +181,13 @@
       where
         rurl = "http://8tracks.com/sessions.json"
         query = [ ("login", C.pack email), ("password", C.pack pwd) ]
-        mId = read strMixId :: Int
 
-    data Config EightTracks = Config { eight :: Radio.Param EightTracks } deriving Generic
+    data Config EightTracks = Config { eight :: ETParam } deriving Generic
 
-    mkConfig tok = Config tok
+    mkConfig = Config
 
-    readToken mid = do
+    readToken strMixId = do
+        mId <- getMixId strMixId
         home <- Radio.getLordDir
         let yml = home ++ "/lord.yml"
         exist <- doesFileExist yml
@@ -183,7 +198,7 @@
                     Nothing -> error $ "Invalid YAML file: " ++ show conf
                     Just c -> 
                         case fromJSON c of
-                            Success tok -> return $ Just $ (eight tok) { mixId = read mid }
+                            Success tok -> return $ Just $ (eight tok) { mixId = mId }
                             Error err -> do
                                 print $ "Parse token failed: " ++ show err
                                 return Nothing
@@ -200,23 +215,21 @@
   where
     rurl = "http://8tracks.com/sets/new.json?api_version=3&api_key=" ++ apiKey 
 
+smartUrl :: String -> String
+smartUrl smartId = 
+    "http://8tracks.com/mix_sets/" ++ smartId ++ ".json?include=mixes"
+
+smartGet :: String -> IO [Exp.Mix]
+smartGet smartId = get (smartUrl smartId) (Exp.mixes . Exp.mix_set)
+
 search :: String -> IO [Exp.Mix]
 search [] = return []
-search key = search' rurl
-  where 
-    rurl = "http://8tracks.com/mix_sets/keyword:" ++ key ++ ".json?include=mixes"
-
-search' :: String -> IO [Exp.Mix]
-search' rurl = do
-    initReq <- parseUrl rurl
-    let req = initReq { requestHeaders = [verHdr, keyHdr] }
-    val <- withManager $ \manager -> do
-        res <- http req manager
-        responseBody res $$+- sinkParser json
+search key = smartGet $ "keyword:" ++ key
 
-    case fromJSON val of
-        Success v -> return $ Exp.mixes $ Exp.mix_set v
-        Error err -> putStrLn err >> return []
+featured, trending, newest :: IO [Exp.Mix]
+featured = smartGet "collection:homepage"
+trending = smartGet "all"
+newest   = smartGet "all:recent"
 
 pprMixes :: [Exp.Mix] -> IO ()
 pprMixes mixes =
@@ -224,9 +237,47 @@
         setSGR [SetConsoleIntensity BoldIntensity]
         putStr $ "* " ++ Exp.name m 
         setSGR [SetColor Foreground Vivid Green]
-        putStrLn $ " id=" ++ show (Exp.id m)
+        putStr $ " id=" ++ show (Exp.id m)
+        putStr $ "  ▶" ++ show (Exp.plays_count m)
+        putStr $ "  ♥" ++ show (Exp.likes_count m)
+        putStrLn $ "  (" ++ show (Exp.tracks_count m) ++ " tracks)"
         setSGR [Reset]
-        putStrLn $ "    Description: " ++ Exp.description m
+        putStrLn $ "    Description: " ++ 
+                   unlines (map ("    " ++) (lines $ Exp.description m))
         putStrLn $ "    Tags: " ++ Exp.tag_list_cache m
         putStrLn ""
         )
+
+get :: FromJSON a => String -> (a -> b) -> IO b
+get rurl selector = do
+    initReq <- parseUrl rurl
+    let req = initReq { requestHeaders = [verHdr, keyHdr] }
+    val <- E.catches 
+        (withManager $ \manager -> do
+            res <- http req manager
+            responseBody res $$+- sinkParser json)
+        [ E.Handler (\e -> print (e :: ParseError) >>
+           error "The mix you are trying to access may be private.")
+        , E.Handler (\e -> case e of
+                        (StatusCodeException s _ _) ->
+                            error $ show s
+                        otherException ->
+                            error $ show otherException) 
+        ]
+
+    case fromJSON val of
+        Success v -> return $ selector v
+        Error err -> error err
+
+getMixId :: String -> IO Int
+getMixId m
+  | isNumerical m = return $ read m
+  | otherwise = do
+    let mixUrl = if domain `L.isPrefixOf` m
+                     then m
+                     else (domain ++)
+                          (if "/" `L.isPrefixOf` m then m else '/' : m)
+    get (mixUrl ++ ".json") (Exp.id . info_mix)
+  where
+    isNumerical = and . fmap isDigit
+    domain = "http://8tracks.com"
diff --git a/Radio/EightTracks/Explore.hs b/Radio/EightTracks/Explore.hs
--- a/Radio/EightTracks/Explore.hs
+++ b/Radio/EightTracks/Explore.hs
@@ -5,12 +5,16 @@
 import           GHC.Generics (Generic)
 
 data Mix = Mix
-    { id        :: Int
-    , path      :: String
-    , web_path  :: String
-    , name      :: String
-    , description :: String
-    , tag_list_cache :: String
+    { id            :: Int
+    , path          :: String
+    , web_path      :: String
+    , name          :: String
+    , description   :: String
+    , plays_count   :: Int
+    , likes_count   :: Int
+    , tag_list_cache:: String
+    , duration      :: Int
+    , tracks_count  :: Int
     } deriving (Show, Generic)
 
 instance FromJSON Mix
diff --git a/Radio/Jing.hs b/Radio/Jing.hs
--- a/Radio/Jing.hs
+++ b/Radio/Jing.hs
@@ -28,7 +28,7 @@
 
 import Radio
 
-type Param a = Radio.Param Jing
+type JingParam = Radio.Param Jing
 
 data Jing = Jing 
     { abid :: Int       -- album id
@@ -127,8 +127,8 @@
     
     playable _ = False
 
-instance FromJSON (Radio.Param Jing)
-instance ToJSON (Radio.Param Jing)
+instance FromJSON JingParam
+instance ToJSON JingParam
 
 instance NeedLogin Jing where
     createSession keywords email pwd = do
@@ -140,7 +140,7 @@
         let hmap = HM.fromList $ responseHeaders res
             atoken = HM.lookup "Jing-A-Token-Header" hmap
             rtoken = HM.lookup "Jing-R-Token-Header" hmap
-            parseToken :: Value -> Maybe (Radio.Param Jing)
+            parseToken :: Value -> Maybe JingParam
             parseToken (Object hm) = do
                 let user = HM.lookup "result" hm >>= 
                            \(Object hm') -> HM.lookup "usr" hm'
@@ -155,9 +155,9 @@
             parseToken _ = error "Unrecognized token format."
         liftM parseToken (runResourceT $ responseBody res $$+- sinkParser json)
 
-    data Config Jing = Config { jing :: Radio.Param Jing } deriving Generic
+    data Config Jing = Config { jing :: JingParam } deriving Generic
 
-    mkConfig tok = Config tok
+    mkConfig = Config 
 
     readToken keywords = do
         home <- Radio.getLordDir
diff --git a/Radio/Reddit.hs b/Radio/Reddit.hs
--- a/Radio/Reddit.hs
+++ b/Radio/Reddit.hs
@@ -15,8 +15,6 @@
 
 import qualified Radio
 
-type Param a = Radio.Param Reddit
-
 data Reddit = Reddit
     { title         :: String
     , artist        :: String
@@ -61,4 +59,4 @@
     putStrLn $ foldr1 f (take 4 gs)
     pprGenres $ drop 4 gs
   where
-    f a b = a ++ (concat $ take (20 - length(a)) $ repeat " ") ++ b
+    f a b = a ++ concat (replicate (20 - length a) " ") ++ b
diff --git a/lord.cabal b/lord.cabal
--- a/lord.cabal
+++ b/lord.cabal
@@ -1,8 +1,8 @@
 name:                lord
-version:             1.20131130
+version:             2.20131201
 synopsis:            A command line interface to online radios.
 description:         
-    A unified interface to several online radio service providers, use @mpd@ (<http://musicpd.org>) as backend.
+    A unified command line interface to several online radios, use @mpd@ (<http://musicpd.org>) as backend by default. Will fallback to mplayer (http://www.mplayerhq.hu) when mpd is unavailable.
     .
     Supported radios:
     .
@@ -22,16 +22,16 @@
     > lord status
     > lord kill
     >
-    > lord 8tracks listen <mix_id> [--no-daemon]
+    > lord 8tracks listen [<mix_id> | <mix_url>] [--no-daemon]
     > lord 8tracks search <keywords>
+    > lord 8tracks [featured | trending | newest]
     >
     > lord cmd listen <genre> [--no-daemon]
     > lord cmd genres
     >
     > lord douban listen [<channel_id> | <musician>] [--no-daemon]
     > lord douban search <keywords>
-    > lord douban hot
-    > lord douban trending
+    > lord douban [hot | trending]
     >
     > lord jing listen <keywords> [--no-daemon]
     >
@@ -82,6 +82,7 @@
                         http-types >= 0.8, 
                         libmpd >= 0.8, 
                         optparse-applicative >= 0.5,
+                        process >= 1.1,
                         text >= 0.11, 
                         transformers >= 0.3, 
                         unix >= 2.5, 
@@ -115,6 +116,7 @@
                         HUnit >= 1.2,
                         libmpd >= 0.8, 
                         optparse-applicative >= 0.5,
+                        process >= 1.1,
                         text >= 0.11, 
                         transformers >= 0.3, 
                         unix >= 2.5, 
diff --git a/main.hs b/main.hs
--- a/main.hs
+++ b/main.hs
@@ -49,6 +49,9 @@
     deriving (Eq, Show)
 
 data ETSubCommand = ETListen String
+                  | ETFeatured
+                  | ETTrending
+                  | ETNewest
                   | ETSearch String
     deriving (Eq, Show)
 
@@ -82,6 +85,9 @@
 
 main :: IO ()
 main = do
+    -- Make sure ~/.lord exists
+    getLordDir >>= createDirectoryIfMissing False
+
     o <- execParser' $ info (helper <*> optParser) 
                            (fullDesc <> header "Lord: radio commander")
     let nodaemon = optDaemon o
@@ -99,6 +105,9 @@
         EightTracks subCommand ->
             case subCommand of
                 ETListen mId -> etListen nodaemon mId
+                ETFeatured   -> ET.featured >>= ET.pprMixes
+                ETTrending   -> ET.trending >>= ET.pprMixes
+                ETNewest     -> ET.newest   >>= ET.pprMixes
                 ETSearch key -> etSearch key
         JingFM (JingListen key) -> jingListen nodaemon key
         RedditFM subCommand ->
@@ -159,6 +168,9 @@
     ( command "listen"
         (info (helper <*> (ETListen <$> argument str (metavar "mix id")))
               (progDesc "Provide mix id to listen to 8tracks.com"))
+    <> command "featured" (info (pure ETFeatured) (progDesc "Featured mixes"))
+    <> command "trending" (info (pure ETFeatured) (progDesc "Trending mixes"))
+    <> command "newest" (info (pure ETFeatured) (progDesc "Newest mixes"))
     <> command "search"
         (info (helper <*> (ETSearch <$> argument str (metavar "KEYWORDS")))
               (progDesc "search mixes"))
@@ -223,17 +235,22 @@
 
 listen :: Radio a => Bool -> Radio.Param a -> IO ()
 listen nodaemon param = do
-    -- Make sure ~/.lord exists
-    getLordDir >>= createDirectoryIfMissing False
+    -- mplayer backend won't work in daemon mode!
+    st <- withMPD status
+    nodaemon' <- case st of 
+                     Right _ -> return nodaemon
+                     Left  e -> print e >> 
+                                putStrLn "Lord will run in foreground" >>
+                                return True
 
     pid <- getPidFile
-    logger <- if nodaemon then mkLogger True stdout 
+    logger <- if nodaemon' then mkLogger True stdout 
               else getLogFile >>= flip openFile AppendMode >>= mkLogger True
     let listen' = play logger param []
     running <- isRunning pid
     when running $ killAndWait pid 
-    if nodaemon then runInForeground pid listen'
-                else runDetached (Just pid) def listen'
+    if nodaemon' then runInForeground pid listen'
+                 else runDetached (Just pid) def listen'
 
 -- Partially taken from System.Posix.Daemon module
 runInForeground :: FilePath -> IO () -> IO ()
diff --git a/test/main.hs b/test/main.hs
--- a/test/main.hs
+++ b/test/main.hs
@@ -12,34 +12,32 @@
 
 
 main :: IO ()
-main = do
-    hspec spec
+main = hspec spec
 
 spec :: Spec
-spec = do
-    describe "getPlaylist" $ do
-        it "cmd: given genre" $ do
-            ss <- Radio.getPlaylist (Cmd.Genre "Dream Pop")
-            assert $ length ss > 0
+spec = describe "getPlaylist" $ do
+    it "cmd: given genre" $ do
+        ss <- Radio.getPlaylist (Cmd.Genre "Dream Pop")
+        assert $ not $ null ss
 
-        it "douban: given channel id" $ do
-            ss <- Radio.getPlaylist (Cid 6)
-            assert $ length ss > 0
-    
-        it "douban: given musician name" $ do
-            ss <- Radio.getPlaylist (Musician "Sigur RóS")
-            assert $ length ss > 0
+    it "douban: given channel id" $ do
+        ss <- Radio.getPlaylist (Cid 6)
+        assert $ not $ null ss
 
-        it "8tracks: given mix id" $ do
-            tok <- readToken "14" :: IO (Maybe (Radio.Param ET.EightTracks))
-            ss <- Radio.getPlaylist $ fromJust tok
-            assert $ length ss > 0
+    it "douban: given musician name" $ do
+        ss <- Radio.getPlaylist (Musician "Sigur RóS")
+        assert $ not $ null ss
 
-        it "jing: given keywords" $ do
-            tok <- readToken "postrock" :: IO (Maybe (Radio.Param Jing))
-            ss <- Radio.getPlaylist $ fromJust tok
-            assert $ length ss > 0
+    it "8tracks: given mix id" $ do
+        tok <- readToken "14" :: IO (Maybe (Radio.Param ET.EightTracks))
+        ss <- Radio.getPlaylist $ fromJust tok
+        assert $ not $ null ss
 
-        it "reddit: given genre" $ do
-            ss <- Radio.getPlaylist (Reddit.Genre "indie")
-            assert $ length ss > 0
+    it "jing: given keywords" $ do
+        tok <- readToken "postrock" :: IO (Maybe (Radio.Param Jing))
+        ss <- Radio.getPlaylist $ fromJust tok
+        assert $ not $ null ss
+
+    it "reddit: given genre" $ do
+        ss <- Radio.getPlaylist (Reddit.Genre "indie")
+        assert $ not $ null ss
