{- |
Copyright  : Will Thompson, Iñaki García Etxebarria and Jonas Platte
License    : LGPL-2.1
Maintainer : Iñaki García Etxebarria (garetxe@gmail.com)

\<refsect2>
\<para>
This interface is implemented by elements that provide a stream volume. Examples for
such elements are @/volume/@ and @/playbin/@.
\<\/para>
\<para>
Applications can use this interface to get or set the current stream volume. For this
the \"volume\" 'GI.GObject.Objects.Object.Object' property can be used or the helper functions 'GI.GstAudio.Interfaces.StreamVolume.streamVolumeSetVolume'
and 'GI.GstAudio.Interfaces.StreamVolume.streamVolumeGetVolume'. This volume is always a linear factor, i.e. 0.0 is muted
1.0 is 100%. For showing the volume in a GUI it might make sense to convert it to
a different format by using 'GI.GstAudio.Functions.streamVolumeConvertVolume'. Volume sliders should usually
use a cubic volume.

Separate from the volume the stream can also be muted by the \"mute\" 'GI.GObject.Objects.Object.Object' property or
'GI.GstAudio.Interfaces.StreamVolume.streamVolumeSetMute' and 'GI.GstAudio.Interfaces.StreamVolume.streamVolumeGetMute'.
\<\/para>
\<para>
Elements that provide some kind of stream volume should implement the \"volume\" and
\"mute\" 'GI.GObject.Objects.Object.Object' properties and handle setting and getting of them properly.
The volume property is defined to be a linear volume factor.
\<\/para>
\<\/refsect2>
-}

module GI.GstAudio.Interfaces.StreamVolume
    ( 

-- * Exported types
    StreamVolume(..)                        ,
    noStreamVolume                          ,
    IsStreamVolume                          ,
    toStreamVolume                          ,


 -- * Methods
-- ** convertVolume #method:convertVolume#
    streamVolumeConvertVolume               ,


-- ** getMute #method:getMute#
    StreamVolumeGetMuteMethodInfo           ,
    streamVolumeGetMute                     ,


-- ** getVolume #method:getVolume#
    StreamVolumeGetVolumeMethodInfo         ,
    streamVolumeGetVolume                   ,


-- ** setMute #method:setMute#
    StreamVolumeSetMuteMethodInfo           ,
    streamVolumeSetMute                     ,


-- ** setVolume #method:setVolume#
    StreamVolumeSetVolumeMethodInfo         ,
    streamVolumeSetVolume                   ,




 -- * Properties
-- ** mute #attr:mute#
    StreamVolumeMutePropertyInfo            ,
    constructStreamVolumeMute               ,
    getStreamVolumeMute                     ,
    setStreamVolumeMute                     ,
    streamVolumeMute                        ,


-- ** volume #attr:volume#
    StreamVolumeVolumePropertyInfo          ,
    constructStreamVolumeVolume             ,
    getStreamVolumeVolume                   ,
    setStreamVolumeVolume                   ,
    streamVolumeVolume                      ,




    ) where

import Data.GI.Base.ShortPrelude
import qualified Data.GI.Base.ShortPrelude as SP
import qualified Data.GI.Base.Overloading as O
import qualified Prelude as P

import qualified Data.GI.Base.Attributes as GI.Attributes
import qualified Data.GI.Base.ManagedPtr as B.ManagedPtr
import qualified Data.GI.Base.GError as B.GError
import qualified Data.GI.Base.GVariant as B.GVariant
import qualified Data.GI.Base.GParamSpec as B.GParamSpec
import qualified Data.GI.Base.CallStack as B.CallStack
import qualified Data.Text as T
import qualified Data.ByteString.Char8 as B
import qualified Data.Map as Map
import qualified Foreign.Ptr as FP

import qualified GI.GObject.Objects.Object as GObject.Object
import {-# SOURCE #-} qualified GI.GstAudio.Enums as GstAudio.Enums

-- interface StreamVolume 
newtype StreamVolume = StreamVolume (ManagedPtr StreamVolume)
noStreamVolume :: Maybe StreamVolume
noStreamVolume = Nothing

type family ResolveStreamVolumeMethod (t :: Symbol) (o :: *) :: * where
    ResolveStreamVolumeMethod "bindProperty" o = GObject.Object.ObjectBindPropertyMethodInfo
    ResolveStreamVolumeMethod "bindPropertyFull" o = GObject.Object.ObjectBindPropertyFullMethodInfo
    ResolveStreamVolumeMethod "forceFloating" o = GObject.Object.ObjectForceFloatingMethodInfo
    ResolveStreamVolumeMethod "freezeNotify" o = GObject.Object.ObjectFreezeNotifyMethodInfo
    ResolveStreamVolumeMethod "isFloating" o = GObject.Object.ObjectIsFloatingMethodInfo
    ResolveStreamVolumeMethod "notify" o = GObject.Object.ObjectNotifyMethodInfo
    ResolveStreamVolumeMethod "notifyByPspec" o = GObject.Object.ObjectNotifyByPspecMethodInfo
    ResolveStreamVolumeMethod "ref" o = GObject.Object.ObjectRefMethodInfo
    ResolveStreamVolumeMethod "refSink" o = GObject.Object.ObjectRefSinkMethodInfo
    ResolveStreamVolumeMethod "replaceData" o = GObject.Object.ObjectReplaceDataMethodInfo
    ResolveStreamVolumeMethod "replaceQdata" o = GObject.Object.ObjectReplaceQdataMethodInfo
    ResolveStreamVolumeMethod "runDispose" o = GObject.Object.ObjectRunDisposeMethodInfo
    ResolveStreamVolumeMethod "stealData" o = GObject.Object.ObjectStealDataMethodInfo
    ResolveStreamVolumeMethod "stealQdata" o = GObject.Object.ObjectStealQdataMethodInfo
    ResolveStreamVolumeMethod "thawNotify" o = GObject.Object.ObjectThawNotifyMethodInfo
    ResolveStreamVolumeMethod "unref" o = GObject.Object.ObjectUnrefMethodInfo
    ResolveStreamVolumeMethod "watchClosure" o = GObject.Object.ObjectWatchClosureMethodInfo
    ResolveStreamVolumeMethod "getData" o = GObject.Object.ObjectGetDataMethodInfo
    ResolveStreamVolumeMethod "getMute" o = StreamVolumeGetMuteMethodInfo
    ResolveStreamVolumeMethod "getProperty" o = GObject.Object.ObjectGetPropertyMethodInfo
    ResolveStreamVolumeMethod "getQdata" o = GObject.Object.ObjectGetQdataMethodInfo
    ResolveStreamVolumeMethod "getVolume" o = StreamVolumeGetVolumeMethodInfo
    ResolveStreamVolumeMethod "setData" o = GObject.Object.ObjectSetDataMethodInfo
    ResolveStreamVolumeMethod "setMute" o = StreamVolumeSetMuteMethodInfo
    ResolveStreamVolumeMethod "setProperty" o = GObject.Object.ObjectSetPropertyMethodInfo
    ResolveStreamVolumeMethod "setVolume" o = StreamVolumeSetVolumeMethodInfo
    ResolveStreamVolumeMethod l o = O.MethodResolutionFailed l o

instance (info ~ ResolveStreamVolumeMethod t StreamVolume, O.MethodInfo info StreamVolume p) => O.IsLabelProxy t (StreamVolume -> p) where
    fromLabelProxy _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)

#if MIN_VERSION_base(4,9,0)
instance (info ~ ResolveStreamVolumeMethod t StreamVolume, O.MethodInfo info StreamVolume p) => O.IsLabel t (StreamVolume -> p) where
    fromLabel _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)
#endif

-- VVV Prop "mute"
   -- Type: TBasicType TBoolean
   -- Flags: [PropertyReadable,PropertyWritable]
   -- Nullable: (Just False,Just False)

getStreamVolumeMute :: (MonadIO m, IsStreamVolume o) => o -> m Bool
getStreamVolumeMute obj = liftIO $ getObjectPropertyBool obj "mute"

setStreamVolumeMute :: (MonadIO m, IsStreamVolume o) => o -> Bool -> m ()
setStreamVolumeMute obj val = liftIO $ setObjectPropertyBool obj "mute" val

constructStreamVolumeMute :: (IsStreamVolume o) => Bool -> IO (GValueConstruct o)
constructStreamVolumeMute val = constructObjectPropertyBool "mute" val

data StreamVolumeMutePropertyInfo
instance AttrInfo StreamVolumeMutePropertyInfo where
    type AttrAllowedOps StreamVolumeMutePropertyInfo = '[ 'AttrSet, 'AttrConstruct, 'AttrGet]
    type AttrSetTypeConstraint StreamVolumeMutePropertyInfo = (~) Bool
    type AttrBaseTypeConstraint StreamVolumeMutePropertyInfo = IsStreamVolume
    type AttrGetType StreamVolumeMutePropertyInfo = Bool
    type AttrLabel StreamVolumeMutePropertyInfo = "mute"
    type AttrOrigin StreamVolumeMutePropertyInfo = StreamVolume
    attrGet _ = getStreamVolumeMute
    attrSet _ = setStreamVolumeMute
    attrConstruct _ = constructStreamVolumeMute
    attrClear _ = undefined

-- VVV Prop "volume"
   -- Type: TBasicType TDouble
   -- Flags: [PropertyReadable,PropertyWritable]
   -- Nullable: (Nothing,Nothing)

getStreamVolumeVolume :: (MonadIO m, IsStreamVolume o) => o -> m Double
getStreamVolumeVolume obj = liftIO $ getObjectPropertyDouble obj "volume"

setStreamVolumeVolume :: (MonadIO m, IsStreamVolume o) => o -> Double -> m ()
setStreamVolumeVolume obj val = liftIO $ setObjectPropertyDouble obj "volume" val

constructStreamVolumeVolume :: (IsStreamVolume o) => Double -> IO (GValueConstruct o)
constructStreamVolumeVolume val = constructObjectPropertyDouble "volume" val

data StreamVolumeVolumePropertyInfo
instance AttrInfo StreamVolumeVolumePropertyInfo where
    type AttrAllowedOps StreamVolumeVolumePropertyInfo = '[ 'AttrSet, 'AttrConstruct, 'AttrGet]
    type AttrSetTypeConstraint StreamVolumeVolumePropertyInfo = (~) Double
    type AttrBaseTypeConstraint StreamVolumeVolumePropertyInfo = IsStreamVolume
    type AttrGetType StreamVolumeVolumePropertyInfo = Double
    type AttrLabel StreamVolumeVolumePropertyInfo = "volume"
    type AttrOrigin StreamVolumeVolumePropertyInfo = StreamVolume
    attrGet _ = getStreamVolumeVolume
    attrSet _ = setStreamVolumeVolume
    attrConstruct _ = constructStreamVolumeVolume
    attrClear _ = undefined

instance O.HasAttributeList StreamVolume
type instance O.AttributeList StreamVolume = StreamVolumeAttributeList
type StreamVolumeAttributeList = ('[ '("mute", StreamVolumeMutePropertyInfo), '("volume", StreamVolumeVolumePropertyInfo)] :: [(Symbol, *)])

streamVolumeMute :: AttrLabelProxy "mute"
streamVolumeMute = AttrLabelProxy

streamVolumeVolume :: AttrLabelProxy "volume"
streamVolumeVolume = AttrLabelProxy

type instance O.SignalList StreamVolume = StreamVolumeSignalList
type StreamVolumeSignalList = ('[ '("notify", GObject.Object.ObjectNotifySignalInfo)] :: [(Symbol, *)])

foreign import ccall "gst_stream_volume_get_type"
    c_gst_stream_volume_get_type :: IO GType

instance GObject StreamVolume where
    gobjectType _ = c_gst_stream_volume_get_type
    

class GObject o => IsStreamVolume o
#if MIN_VERSION_base(4,9,0)
instance {-# OVERLAPPABLE #-} (GObject a, O.UnknownAncestorError StreamVolume a) =>
    IsStreamVolume a
#endif
instance IsStreamVolume StreamVolume
instance GObject.Object.IsObject StreamVolume

toStreamVolume :: IsStreamVolume o => o -> IO StreamVolume
toStreamVolume = unsafeCastTo StreamVolume

-- method StreamVolume::get_mute
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "volume", argType = TInterface (Name {namespace = "GstAudio", name = "StreamVolume"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "#GstStreamVolume that should be used", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TBasicType TBoolean)
-- throws : False
-- Skip return : False

foreign import ccall "gst_stream_volume_get_mute" gst_stream_volume_get_mute :: 
    Ptr StreamVolume ->                     -- volume : TInterface (Name {namespace = "GstAudio", name = "StreamVolume"})
    IO CInt

{- |
/No description available in the introspection data./
-}
streamVolumeGetMute ::
    (B.CallStack.HasCallStack, MonadIO m, IsStreamVolume a) =>
    a
    {- ^ /@volume@/: 'GI.GstAudio.Interfaces.StreamVolume.StreamVolume' that should be used -}
    -> m Bool
    {- ^ __Returns:__ Returns 'True' if the stream is muted -}
streamVolumeGetMute volume = liftIO $ do
    volume' <- unsafeManagedPtrCastPtr volume
    result <- gst_stream_volume_get_mute volume'
    let result' = (/= 0) result
    touchManagedPtr volume
    return result'

data StreamVolumeGetMuteMethodInfo
instance (signature ~ (m Bool), MonadIO m, IsStreamVolume a) => O.MethodInfo StreamVolumeGetMuteMethodInfo a signature where
    overloadedMethod _ = streamVolumeGetMute

-- method StreamVolume::get_volume
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "volume", argType = TInterface (Name {namespace = "GstAudio", name = "StreamVolume"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "#GstStreamVolume that should be used", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "format", argType = TInterface (Name {namespace = "GstAudio", name = "StreamVolumeFormat"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "#GstStreamVolumeFormat which should be returned", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TBasicType TDouble)
-- throws : False
-- Skip return : False

foreign import ccall "gst_stream_volume_get_volume" gst_stream_volume_get_volume :: 
    Ptr StreamVolume ->                     -- volume : TInterface (Name {namespace = "GstAudio", name = "StreamVolume"})
    CUInt ->                                -- format : TInterface (Name {namespace = "GstAudio", name = "StreamVolumeFormat"})
    IO CDouble

{- |
/No description available in the introspection data./
-}
streamVolumeGetVolume ::
    (B.CallStack.HasCallStack, MonadIO m, IsStreamVolume a) =>
    a
    {- ^ /@volume@/: 'GI.GstAudio.Interfaces.StreamVolume.StreamVolume' that should be used -}
    -> GstAudio.Enums.StreamVolumeFormat
    {- ^ /@format@/: 'GI.GstAudio.Enums.StreamVolumeFormat' which should be returned -}
    -> m Double
    {- ^ __Returns:__ The current stream volume as linear factor -}
streamVolumeGetVolume volume format = liftIO $ do
    volume' <- unsafeManagedPtrCastPtr volume
    let format' = (fromIntegral . fromEnum) format
    result <- gst_stream_volume_get_volume volume' format'
    let result' = realToFrac result
    touchManagedPtr volume
    return result'

data StreamVolumeGetVolumeMethodInfo
instance (signature ~ (GstAudio.Enums.StreamVolumeFormat -> m Double), MonadIO m, IsStreamVolume a) => O.MethodInfo StreamVolumeGetVolumeMethodInfo a signature where
    overloadedMethod _ = streamVolumeGetVolume

-- method StreamVolume::set_mute
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "volume", argType = TInterface (Name {namespace = "GstAudio", name = "StreamVolume"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "#GstStreamVolume that should be used", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "mute", argType = TBasicType TBoolean, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "Mute state that should be set", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "gst_stream_volume_set_mute" gst_stream_volume_set_mute :: 
    Ptr StreamVolume ->                     -- volume : TInterface (Name {namespace = "GstAudio", name = "StreamVolume"})
    CInt ->                                 -- mute : TBasicType TBoolean
    IO ()

{- |
/No description available in the introspection data./
-}
streamVolumeSetMute ::
    (B.CallStack.HasCallStack, MonadIO m, IsStreamVolume a) =>
    a
    {- ^ /@volume@/: 'GI.GstAudio.Interfaces.StreamVolume.StreamVolume' that should be used -}
    -> Bool
    {- ^ /@mute@/: Mute state that should be set -}
    -> m ()
streamVolumeSetMute volume mute = liftIO $ do
    volume' <- unsafeManagedPtrCastPtr volume
    let mute' = (fromIntegral . fromEnum) mute
    gst_stream_volume_set_mute volume' mute'
    touchManagedPtr volume
    return ()

data StreamVolumeSetMuteMethodInfo
instance (signature ~ (Bool -> m ()), MonadIO m, IsStreamVolume a) => O.MethodInfo StreamVolumeSetMuteMethodInfo a signature where
    overloadedMethod _ = streamVolumeSetMute

-- method StreamVolume::set_volume
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "volume", argType = TInterface (Name {namespace = "GstAudio", name = "StreamVolume"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "#GstStreamVolume that should be used", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "format", argType = TInterface (Name {namespace = "GstAudio", name = "StreamVolumeFormat"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "#GstStreamVolumeFormat of @val", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "val", argType = TBasicType TDouble, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "Linear volume factor that should be set", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "gst_stream_volume_set_volume" gst_stream_volume_set_volume :: 
    Ptr StreamVolume ->                     -- volume : TInterface (Name {namespace = "GstAudio", name = "StreamVolume"})
    CUInt ->                                -- format : TInterface (Name {namespace = "GstAudio", name = "StreamVolumeFormat"})
    CDouble ->                              -- val : TBasicType TDouble
    IO ()

{- |
/No description available in the introspection data./
-}
streamVolumeSetVolume ::
    (B.CallStack.HasCallStack, MonadIO m, IsStreamVolume a) =>
    a
    {- ^ /@volume@/: 'GI.GstAudio.Interfaces.StreamVolume.StreamVolume' that should be used -}
    -> GstAudio.Enums.StreamVolumeFormat
    {- ^ /@format@/: 'GI.GstAudio.Enums.StreamVolumeFormat' of /@val@/ -}
    -> Double
    {- ^ /@val@/: Linear volume factor that should be set -}
    -> m ()
streamVolumeSetVolume volume format val = liftIO $ do
    volume' <- unsafeManagedPtrCastPtr volume
    let format' = (fromIntegral . fromEnum) format
    let val' = realToFrac val
    gst_stream_volume_set_volume volume' format' val'
    touchManagedPtr volume
    return ()

data StreamVolumeSetVolumeMethodInfo
instance (signature ~ (GstAudio.Enums.StreamVolumeFormat -> Double -> m ()), MonadIO m, IsStreamVolume a) => O.MethodInfo StreamVolumeSetVolumeMethodInfo a signature where
    overloadedMethod _ = streamVolumeSetVolume

-- method StreamVolume::convert_volume
-- method type : MemberFunction
-- Args : [Arg {argCName = "from", argType = TInterface (Name {namespace = "GstAudio", name = "StreamVolumeFormat"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "#GstStreamVolumeFormat to convert from", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "to", argType = TInterface (Name {namespace = "GstAudio", name = "StreamVolumeFormat"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "#GstStreamVolumeFormat to convert to", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "val", argType = TBasicType TDouble, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "Volume in @from format that should be converted", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TBasicType TDouble)
-- throws : False
-- Skip return : False

foreign import ccall "gst_stream_volume_convert_volume" gst_stream_volume_convert_volume :: 
    CUInt ->                                -- from : TInterface (Name {namespace = "GstAudio", name = "StreamVolumeFormat"})
    CUInt ->                                -- to : TInterface (Name {namespace = "GstAudio", name = "StreamVolumeFormat"})
    CDouble ->                              -- val : TBasicType TDouble
    IO CDouble

{- |
/No description available in the introspection data./
-}
streamVolumeConvertVolume ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    GstAudio.Enums.StreamVolumeFormat
    {- ^ /@from@/: 'GI.GstAudio.Enums.StreamVolumeFormat' to convert from -}
    -> GstAudio.Enums.StreamVolumeFormat
    {- ^ /@to@/: 'GI.GstAudio.Enums.StreamVolumeFormat' to convert to -}
    -> Double
    {- ^ /@val@/: Volume in /@from@/ format that should be converted -}
    -> m Double
    {- ^ __Returns:__ the converted volume -}
streamVolumeConvertVolume from to val = liftIO $ do
    let from' = (fromIntegral . fromEnum) from
    let to' = (fromIntegral . fromEnum) to
    let val' = realToFrac val
    result <- gst_stream_volume_convert_volume from' to' val'
    let result' = realToFrac result
    return result'