module Sound.Freesound.Sound.Type where
import Control.Monad (mzero)
import Data.Aeson (FromJSON(..), Value(..), (.:), (.:?))
import qualified Data.ByteString.Char8 as BS
import Data.Text (Text)
import Network.HTTP.Types.QueryLike (QueryValueLike(..))
import Prelude hiding (id)
import Sound.Freesound.API (Resource, URI)
import Sound.Freesound.List (List, Elem(..))
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative
#endif
newtype SoundId = SoundId Integer
deriving (Eq, Ord, Show)
soundIdToInteger :: SoundId -> Integer
soundIdToInteger (SoundId i) = i
instance FromJSON SoundId where
parseJSON (Number i) = return $ SoundId (truncate i)
parseJSON _ = mzero
data FileType = WAV | AIFF | OGG | MP3 | FLAC
deriving (Eq, Show)
instance QueryValueLike FileType where
toQueryValue WAV = toQueryValue $ BS.pack "wav"
toQueryValue AIFF = toQueryValue $ BS.pack "aif"
toQueryValue OGG = toQueryValue $ BS.pack "ogg"
toQueryValue MP3 = toQueryValue $ BS.pack "mp3"
toQueryValue FLAC = toQueryValue $ BS.pack "flac"
instance FromJSON FileType where
parseJSON (String v) =
case v of
"wav" -> return WAV
"aiff" -> return AIFF
"aif" -> return AIFF
"ogg" -> return OGG
"mp3" -> return MP3
"flac" -> return FLAC
_ -> mzero
parseJSON _ = mzero
class Sound a where
id :: a -> SoundId
name :: a -> Text
tags :: a -> [Text]
username :: a -> Text
license :: a -> License
data License =
Attribution
| AttributionNoncommercial
| CreativeCommons0
| License Text
deriving (Eq, Show)
instance FromJSON License where
parseJSON (String x) =
case x of
"Attribution" -> pure Attribution
"Attribution Noncommercial" -> pure AttributionNoncommercial
"Creative Commons 0" -> pure CreativeCommons0
u -> pure $ License u
parseJSON _ = fail "Invalid license"
data Previews = Previews {
preview_hq_mp3 :: URI
, preview_lq_mp3 :: URI
, preview_hq_ogg :: URI
, preview_lq_ogg :: URI
} deriving (Eq, Show)
instance FromJSON Previews where
parseJSON (Object v) =
Previews
<$> v .: "preview-hq-mp3"
<*> v .: "preview-lq-mp3"
<*> v .: "preview-hq-ogg"
<*> v .: "preview-lq-ogg"
parseJSON _ = fail "Couldn't parse Previews"
data Images = Images {
waveform_m :: URI
, waveform_l :: URI
, spectral_m :: URI
, spectral_l :: URI
} deriving (Eq, Show)
instance FromJSON Images where
parseJSON (Object v) =
Images
<$> v .: "waveform_m"
<*> v .: "waveform_l"
<*> v .: "spectral_m"
<*> v .: "spectral_l"
parseJSON _ = fail "Couldn't parse Images"
data Detail = Detail {
sound_id :: SoundId
, url :: URI
, sound_name :: Text
, sound_tags :: [Text]
, description :: Text
, geotag :: Maybe GeoTag
, created :: Text
, sound_license :: License
, fileType :: FileType
, channels :: Int
, filesize :: Integer
, bitrate :: Int
, bitdepth :: Int
, duration :: Double
, samplerate :: Int
, sound_username :: Text
, pack :: Maybe (Resource ())
, download :: URI
, bookmark :: URI
, previews :: Previews
, images :: Images
, numDownloads :: Integer
, avgRating :: Double
, numRatings :: Integer
, rate :: URI
, comments :: Resource ()
, numComments :: Integer
, comment :: URI
, similarSounds :: Resource (List Summary)
, analysisStats :: Resource ()
, analysisFrames :: Resource ()
} deriving (Eq, Show)
instance FromJSON Detail where
parseJSON (Object v) =
Detail
<$> v .: "id"
<*> v .: "url"
<*> v .: "name"
<*> v .: "tags"
<*> v .: "description"
<*> v .:? "geotag"
<*> v .: "created"
<*> v .: "license"
<*> v .: "type"
<*> v .: "channels"
<*> v .: "filesize"
<*> v .: "bitrate"
<*> v .: "bitdepth"
<*> v .: "duration"
<*> v .: "samplerate"
<*> v .: "username"
<*> v .:? "pack"
<*> v .: "download"
<*> v .: "bookmark"
<*> v .: "previews"
<*> v .: "images"
<*> v .: "num_downloads"
<*> v .: "avg_rating"
<*> v .: "num_ratings"
<*> v .: "rate"
<*> v .: "comments"
<*> v .: "num_comments"
<*> v .: "comment"
<*> v .: "similar_sounds"
<*> v .: "analysis_stats"
<*> v .: "analysis_frames"
parseJSON _ = fail "Couldn't parse Sound"
instance Sound Detail where
id = sound_id
name = sound_name
tags = sound_tags
username = sound_username
license = sound_license
data Summary = Summary {
summary_id :: SoundId
, summary_name :: Text
, summary_tags :: [Text]
, summary_username :: Text
, summary_license :: License
} deriving (Eq, Show)
instance FromJSON Summary where
parseJSON (Object v) =
Summary
<$> v .: "id"
<*> v .: "name"
<*> v .: "tags"
<*> v .: "username"
<*> v .: "license"
parseJSON _ = fail "Couldn't parse Sound"
instance Sound Summary where
id = summary_id
name = summary_name
tags = summary_tags
username = summary_username
license = summary_license
instance Elem Summary where
elemsFieldName _ = "sounds"
data GeoTag = GeoTag {
latitude :: Double
, longitude :: Double
} deriving (Eq, Show)
instance FromJSON GeoTag where
parseJSON (String _) = pure (GeoTag 0 0)
parseJSON _ = fail "Couldn't parse GeoTag"