module JSDOM.Custom.Navigator (
    module Generated
  , getUserMedia
) where

import Data.Maybe (fromJust)

import Control.Monad.IO.Class (MonadIO(..))
import Control.Concurrent.MVar (takeMVar, putMVar, newEmptyMVar)

import JSDOM.Types
       (withCallback, Callback(..), MediaStream(..), NavigatorUserMediaError(..),
        MediaStreamConstraints(..), MonadDOM, NavigatorUserMediaSuccessCallback(..),
        NavigatorUserMediaErrorCallback(..))

import JSDOM.Custom.NavigatorUserMediaError (throwUserMediaException)

import JSDOM.Generated.NavigatorUserMediaSuccessCallback
       (newNavigatorUserMediaSuccessCallback)
import JSDOM.Generated.NavigatorUserMediaErrorCallback
       (newNavigatorUserMediaErrorCallback)

import JSDOM.Generated.Navigator as Generated hiding (getUserMedia)
import qualified JSDOM.Generated.Navigator
       as Generated (getUserMedia)

-- | <https://developer.mozilla.org/en-US/docs/Web/API/Navigator.webkitGetUserMedia Mozilla Navigator.webkitGetUserMedia documentation>
getUserMedia' :: MonadDOM m => Navigator -> MediaStreamConstraints -> m (Either NavigatorUserMediaError MediaStream)
getUserMedia' :: forall (m :: * -> *).
MonadDOM m =>
Navigator
-> MediaStreamConstraints
-> m (Either NavigatorUserMediaError MediaStream)
getUserMedia' Navigator
self MediaStreamConstraints
constraints = do
    MVar (Either NavigatorUserMediaError MediaStream)
result <- IO (MVar (Either NavigatorUserMediaError MediaStream))
-> m (MVar (Either NavigatorUserMediaError MediaStream))
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO (MVar (Either NavigatorUserMediaError MediaStream))
forall a. IO (MVar a)
newEmptyMVar
    JSM NavigatorUserMediaSuccessCallback
-> (NavigatorUserMediaSuccessCallback
    -> JSM (Either NavigatorUserMediaError MediaStream))
-> m (Either NavigatorUserMediaError MediaStream)
forall (m :: * -> *) c a.
(MonadDOM m, Coercible c Function) =>
JSM c -> (c -> JSM a) -> m a
withCallback ((MediaStream -> JSM ()) -> JSM NavigatorUserMediaSuccessCallback
forall (m :: * -> *).
MonadDOM m =>
(MediaStream -> JSM ()) -> m NavigatorUserMediaSuccessCallback
newNavigatorUserMediaSuccessCallback (IO () -> JSM ()
forall a. IO a -> JSM a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> JSM ())
-> (MediaStream -> IO ()) -> MediaStream -> JSM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MVar (Either NavigatorUserMediaError MediaStream)
-> Either NavigatorUserMediaError MediaStream -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar (Either NavigatorUserMediaError MediaStream)
result (Either NavigatorUserMediaError MediaStream -> IO ())
-> (MediaStream -> Either NavigatorUserMediaError MediaStream)
-> MediaStream
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MediaStream -> Either NavigatorUserMediaError MediaStream
forall a b. b -> Either a b
Right)) ((NavigatorUserMediaSuccessCallback
  -> JSM (Either NavigatorUserMediaError MediaStream))
 -> m (Either NavigatorUserMediaError MediaStream))
-> (NavigatorUserMediaSuccessCallback
    -> JSM (Either NavigatorUserMediaError MediaStream))
-> m (Either NavigatorUserMediaError MediaStream)
forall a b. (a -> b) -> a -> b
$ \NavigatorUserMediaSuccessCallback
success ->
        JSM NavigatorUserMediaErrorCallback
-> (NavigatorUserMediaErrorCallback
    -> JSM (Either NavigatorUserMediaError MediaStream))
-> JSM (Either NavigatorUserMediaError MediaStream)
forall (m :: * -> *) c a.
(MonadDOM m, Coercible c Function) =>
JSM c -> (c -> JSM a) -> m a
withCallback ((NavigatorUserMediaError -> JSM ())
-> JSM NavigatorUserMediaErrorCallback
forall (m :: * -> *).
MonadDOM m =>
(NavigatorUserMediaError -> JSM ())
-> m NavigatorUserMediaErrorCallback
newNavigatorUserMediaErrorCallback (IO () -> JSM ()
forall a. IO a -> JSM a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> JSM ())
-> (NavigatorUserMediaError -> IO ())
-> NavigatorUserMediaError
-> JSM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MVar (Either NavigatorUserMediaError MediaStream)
-> Either NavigatorUserMediaError MediaStream -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar (Either NavigatorUserMediaError MediaStream)
result (Either NavigatorUserMediaError MediaStream -> IO ())
-> (NavigatorUserMediaError
    -> Either NavigatorUserMediaError MediaStream)
-> NavigatorUserMediaError
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NavigatorUserMediaError
-> Either NavigatorUserMediaError MediaStream
forall a b. a -> Either a b
Left)) ((NavigatorUserMediaErrorCallback
  -> JSM (Either NavigatorUserMediaError MediaStream))
 -> JSM (Either NavigatorUserMediaError MediaStream))
-> (NavigatorUserMediaErrorCallback
    -> JSM (Either NavigatorUserMediaError MediaStream))
-> JSM (Either NavigatorUserMediaError MediaStream)
forall a b. (a -> b) -> a -> b
$ \NavigatorUserMediaErrorCallback
error -> do
            Navigator
-> MediaStreamConstraints
-> NavigatorUserMediaSuccessCallback
-> NavigatorUserMediaErrorCallback
-> JSM ()
forall (m :: * -> *).
MonadDOM m =>
Navigator
-> MediaStreamConstraints
-> NavigatorUserMediaSuccessCallback
-> NavigatorUserMediaErrorCallback
-> m ()
Generated.getUserMedia Navigator
self MediaStreamConstraints
constraints NavigatorUserMediaSuccessCallback
success NavigatorUserMediaErrorCallback
error
            IO (Either NavigatorUserMediaError MediaStream)
-> JSM (Either NavigatorUserMediaError MediaStream)
forall a. IO a -> JSM a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either NavigatorUserMediaError MediaStream)
 -> JSM (Either NavigatorUserMediaError MediaStream))
-> IO (Either NavigatorUserMediaError MediaStream)
-> JSM (Either NavigatorUserMediaError MediaStream)
forall a b. (a -> b) -> a -> b
$ MVar (Either NavigatorUserMediaError MediaStream)
-> IO (Either NavigatorUserMediaError MediaStream)
forall a. MVar a -> IO a
takeMVar MVar (Either NavigatorUserMediaError MediaStream)
result

getUserMedia :: MonadDOM m => Navigator -> MediaStreamConstraints -> m MediaStream
getUserMedia :: forall (m :: * -> *).
MonadDOM m =>
Navigator -> MediaStreamConstraints -> m MediaStream
getUserMedia Navigator
self MediaStreamConstraints
constraints = Navigator
-> MediaStreamConstraints
-> m (Either NavigatorUserMediaError MediaStream)
forall (m :: * -> *).
MonadDOM m =>
Navigator
-> MediaStreamConstraints
-> m (Either NavigatorUserMediaError MediaStream)
getUserMedia' Navigator
self MediaStreamConstraints
constraints m (Either NavigatorUserMediaError MediaStream)
-> (Either NavigatorUserMediaError MediaStream -> m MediaStream)
-> m MediaStream
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (NavigatorUserMediaError -> m MediaStream)
-> (MediaStream -> m MediaStream)
-> Either NavigatorUserMediaError MediaStream
-> m MediaStream
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either NavigatorUserMediaError -> m MediaStream
forall (m :: * -> *) a.
MonadDOM m =>
NavigatorUserMediaError -> m a
throwUserMediaException MediaStream -> m MediaStream
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return