packages feed

alsa-seq 0.5.1.1 → 0.6

raw patch · 63 files changed

+3255/−1944 lines, 63 filesdep +bytestringdep +polldep +transformersdep ~data-accessordep ~enumsetnew-component:exe:alsa-seq-beatnew-component:exe:alsa-seq-list-portsnew-component:exe:alsa-seq-sysexPVP ok

version bump matches the API change (PVP)

Dependencies added: bytestring, poll, transformers

Dependency ranges changed: data-accessor, enumset

API changes (from Hackage documentation)

- Sound.ALSA.Sequencer: connectFrom :: AllowInput mode => T mode -> T -> T -> IO ()
- Sound.ALSA.Sequencer: connectTo :: AllowOutput mode => T mode -> T -> T -> IO ()
- Sound.ALSA.Sequencer: disconnectFrom :: AllowInput mode => T mode -> T -> T -> IO ()
- Sound.ALSA.Sequencer: disconnectTo :: AllowOutput mode => T mode -> T -> T -> IO ()
- Sound.ALSA.Sequencer.Client: data T
- Sound.ALSA.Sequencer.Client.Info: modify :: T mode -> (T -> IO T) -> IO ()
- Sound.ALSA.Sequencer.Client.Info: type T = ClientInfo
- Sound.ALSA.Sequencer.Event: Cluster :: InstrCluster -> Cluster
- Sound.ALSA.Sequencer.Event: Instr :: !InstrCluster -> !Word32 -> !Word16 -> !Word16 -> Instr
- Sound.ALSA.Sequencer.Event: RealTime :: !T -> TimeStamp
- Sound.ALSA.Sequencer.Event: Sample :: !Word32 -> !Word16 -> !Word16 -> Sample
- Sound.ALSA.Sequencer.Event: TickTime :: !Word32 -> TimeStamp
- Sound.ALSA.Sequencer.Event: Volume :: !Int16 -> !Int16 -> !Int16 -> !Int16 -> Volume
- Sound.ALSA.Sequencer.Event: clusterCluster :: Cluster -> InstrCluster
- Sound.ALSA.Sequencer.Event: data Connect
- Sound.ALSA.Sequencer.Event: data Instr
- Sound.ALSA.Sequencer.Event: data InstrCluster
- Sound.ALSA.Sequencer.Event: data Sample
- Sound.ALSA.Sequencer.Event: data TimeStamp
- Sound.ALSA.Sequencer.Event: data Volume
- Sound.ALSA.Sequencer.Event: instrBank :: Instr -> !Word16
- Sound.ALSA.Sequencer.Event: instrCluster :: Instr -> !InstrCluster
- Sound.ALSA.Sequencer.Event: instrPrg :: Instr -> !Word16
- Sound.ALSA.Sequencer.Event: instrStd :: Instr -> !Word32
- Sound.ALSA.Sequencer.Event: newtype Cluster
- Sound.ALSA.Sequencer.Event: sampleBank :: Sample -> !Word16
- Sound.ALSA.Sequencer.Event: samplePrg :: Sample -> !Word16
- Sound.ALSA.Sequencer.Event: sampleStd :: Sample -> !Word32
- Sound.ALSA.Sequencer.Event: timestamp :: T -> !TimeStamp
- Sound.ALSA.Sequencer.Event: volumeDU :: Volume -> !Int16
- Sound.ALSA.Sequencer.Event: volumeFR :: Volume -> !Int16
- Sound.ALSA.Sequencer.Event: volumeLR :: Volume -> !Int16
- Sound.ALSA.Sequencer.Event: volumeSame :: Int16
- Sound.ALSA.Sequencer.Event: volumeVolume :: Volume -> !Int16
- Sound.ALSA.Sequencer.Event.Accessor: timestamp :: T T TimeStamp
- Sound.ALSA.Sequencer.Port: data T
- Sound.ALSA.Sequencer.Port.Info: type T = PortInfo
- Sound.ALSA.Sequencer.Queue.Info: type T = QueueInfo
- Sound.ALSA.Sequencer.Queue.Status: type T = QueueStatus
- Sound.ALSA.Sequencer.Queue.Tempo: type T = QueueTempo
- Sound.ALSA.Sequencer.Queue.Timer: type T = QueueTimer
- Sound.ALSA.Sequencer.Subscribe.Query: type T = QuerySubscribe
+ Sound.ALSA.Sequencer: openDefault :: OpenMode mode => BlockMode -> IO (T mode)
+ Sound.ALSA.Sequencer: withDefault :: OpenMode mode => BlockMode -> (T mode -> IO a) -> IO a
+ Sound.ALSA.Sequencer.Address: broadcast :: T
+ Sound.ALSA.Sequencer.Address: systemAnnounce :: T
+ Sound.ALSA.Sequencer.Address: systemTimer :: T
+ Sound.ALSA.Sequencer.Address: unknown :: T
+ Sound.ALSA.Sequencer.Client: Cons :: Word8 -> T
+ Sound.ALSA.Sequencer.Client: newtype T
+ Sound.ALSA.Sequencer.Client.Info: data T
+ Sound.ALSA.Sequencer.Client.Info: queryLoop :: T mode -> (T -> IO a) -> IO [a]
+ Sound.ALSA.Sequencer.Client.Info: queryLoop_ :: T mode -> (T -> IO ()) -> IO ()
+ Sound.ALSA.Sequencer.Client.InfoMonad: data T a
+ Sound.ALSA.Sequencer.Client.InfoMonad: get :: T mode -> T a -> IO a
+ Sound.ALSA.Sequencer.Client.InfoMonad: getBroadcastFilter :: T Bool
+ Sound.ALSA.Sequencer.Client.InfoMonad: getClient :: T T
+ Sound.ALSA.Sequencer.Client.InfoMonad: getErrorBounce :: T Bool
+ Sound.ALSA.Sequencer.Client.InfoMonad: getEventLost :: T Word
+ Sound.ALSA.Sequencer.Client.InfoMonad: getName :: T String
+ Sound.ALSA.Sequencer.Client.InfoMonad: getNumPorts :: T Word
+ Sound.ALSA.Sequencer.Client.InfoMonad: getType :: T Type
+ Sound.ALSA.Sequencer.Client.InfoMonad: instance Applicative T
+ Sound.ALSA.Sequencer.Client.InfoMonad: instance Functor T
+ Sound.ALSA.Sequencer.Client.InfoMonad: instance Monad T
+ Sound.ALSA.Sequencer.Client.InfoMonad: modify :: T mode -> T a -> IO a
+ Sound.ALSA.Sequencer.Client.InfoMonad: run :: T a -> T -> IO a
+ Sound.ALSA.Sequencer.Client.InfoMonad: setBroadcastFilter :: Bool -> T ()
+ Sound.ALSA.Sequencer.Client.InfoMonad: setClient :: T -> T ()
+ Sound.ALSA.Sequencer.Client.InfoMonad: setErrorBounce :: Bool -> T ()
+ Sound.ALSA.Sequencer.Client.InfoMonad: setName :: String -> T ()
+ Sound.ALSA.Sequencer.Concurrent: drainOutput :: AllowOutput mode => T mode -> IO ()
+ Sound.ALSA.Sequencer.Concurrent: input :: AllowInput mode => T mode -> IO T
+ Sound.ALSA.Sequencer.Concurrent: output :: AllowOutput mode => T mode -> T -> IO Word
+ Sound.ALSA.Sequencer.Concurrent: threadWaitDuplex :: (AllowInput mode, AllowOutput mode) => T mode -> IO ()
+ Sound.ALSA.Sequencer.Concurrent: threadWaitInput :: AllowInput mode => T mode -> IO ()
+ Sound.ALSA.Sequencer.Concurrent: threadWaitOutput :: AllowOutput mode => T mode -> IO ()
+ Sound.ALSA.Sequencer.Connect: Cons :: !T -> !T -> T
+ Sound.ALSA.Sequencer.Connect: createFrom :: AllowInput mode => T mode -> T -> T -> IO T
+ Sound.ALSA.Sequencer.Connect: createTo :: AllowOutput mode => T mode -> T -> T -> IO T
+ Sound.ALSA.Sequencer.Connect: data T
+ Sound.ALSA.Sequencer.Connect: deleteFrom :: AllowInput mode => T mode -> T -> T -> IO ()
+ Sound.ALSA.Sequencer.Connect: deleteTo :: AllowOutput mode => T mode -> T -> T -> IO ()
+ Sound.ALSA.Sequencer.Connect: dest :: T -> !T
+ Sound.ALSA.Sequencer.Connect: fromSubscribers :: T -> T
+ Sound.ALSA.Sequencer.Connect: reverse :: T -> T
+ Sound.ALSA.Sequencer.Connect: source :: T -> !T
+ Sound.ALSA.Sequencer.Connect: toSubscribers :: T -> T
+ Sound.ALSA.Sequencer.Connect: withFrom :: AllowInput mode => T mode -> T -> T -> (T -> IO a) -> IO a
+ Sound.ALSA.Sequencer.Connect: withTo :: AllowOutput mode => T mode -> T -> T -> (T -> IO a) -> IO a
+ Sound.ALSA.Sequencer.Event: Bounce :: ExtEv
+ Sound.ALSA.Sequencer.Event: Channel :: Word8 -> Channel
+ Sound.ALSA.Sequencer.Event: Duration :: Word32 -> Duration
+ Sound.ALSA.Sequencer.Event: ExtEv :: ExtEv -> ByteString -> Data
+ Sound.ALSA.Sequencer.Event: Parameter :: Word32 -> Parameter
+ Sound.ALSA.Sequencer.Event: Pitch :: Word8 -> Pitch
+ Sound.ALSA.Sequencer.Event: QueueEv :: QueueEv -> T -> Data
+ Sound.ALSA.Sequencer.Event: SysEx :: ExtEv
+ Sound.ALSA.Sequencer.Event: Tag :: Word8 -> Tag
+ Sound.ALSA.Sequencer.Event: Tempo :: Int32 -> Tempo
+ Sound.ALSA.Sequencer.Event: UserVar0 :: ExtEv
+ Sound.ALSA.Sequencer.Event: UserVar1 :: ExtEv
+ Sound.ALSA.Sequencer.Event: UserVar2 :: ExtEv
+ Sound.ALSA.Sequencer.Event: UserVar3 :: ExtEv
+ Sound.ALSA.Sequencer.Event: UserVar4 :: ExtEv
+ Sound.ALSA.Sequencer.Event: Value :: Int32 -> Value
+ Sound.ALSA.Sequencer.Event: Velocity :: Word8 -> Velocity
+ Sound.ALSA.Sequencer.Event: class Type e
+ Sound.ALSA.Sequencer.Event: customZero :: Custom
+ Sound.ALSA.Sequencer.Event: data ExtEv
+ Sound.ALSA.Sequencer.Event: forConnection :: T -> Data -> T
+ Sound.ALSA.Sequencer.Event: forSourcePort :: T -> Data -> T
+ Sound.ALSA.Sequencer.Event: newtype Channel
+ Sound.ALSA.Sequencer.Event: newtype Duration
+ Sound.ALSA.Sequencer.Event: newtype Parameter
+ Sound.ALSA.Sequencer.Event: newtype Pitch
+ Sound.ALSA.Sequencer.Event: newtype Tag
+ Sound.ALSA.Sequencer.Event: newtype Tempo
+ Sound.ALSA.Sequencer.Event: newtype Value
+ Sound.ALSA.Sequencer.Event: newtype Velocity
+ Sound.ALSA.Sequencer.Event: normalVelocity, offVelocity :: Velocity
+ Sound.ALSA.Sequencer.Event: time :: T -> !T
+ Sound.ALSA.Sequencer.Event: unChannel :: Channel -> Word8
+ Sound.ALSA.Sequencer.Event: unDuration :: Duration -> Word32
+ Sound.ALSA.Sequencer.Event: unParameter :: Parameter -> Word32
+ Sound.ALSA.Sequencer.Event: unPitch :: Pitch -> Word8
+ Sound.ALSA.Sequencer.Event: unTag :: Tag -> Word8
+ Sound.ALSA.Sequencer.Event: unTempo :: Tempo -> Int32
+ Sound.ALSA.Sequencer.Event: unValue :: Value -> Int32
+ Sound.ALSA.Sequencer.Event: unVelocity :: Velocity -> Word8
+ Sound.ALSA.Sequencer.Event.Accessor: time :: T T T
+ Sound.ALSA.Sequencer.Event.Accessor: timeStamp :: T T Stamp
+ Sound.ALSA.Sequencer.Event.RemoveMonad: data T a
+ Sound.ALSA.Sequencer.Event.RemoveMonad: getChannel :: T (Maybe Channel)
+ Sound.ALSA.Sequencer.Event.RemoveMonad: getDest :: T (Maybe (T, T))
+ Sound.ALSA.Sequencer.Event.RemoveMonad: getIgnoreOff :: T Bool
+ Sound.ALSA.Sequencer.Event.RemoveMonad: getInput :: T Bool
+ Sound.ALSA.Sequencer.Event.RemoveMonad: getOutput :: T Bool
+ Sound.ALSA.Sequencer.Event.RemoveMonad: getTag :: T (Maybe Tag)
+ Sound.ALSA.Sequencer.Event.RemoveMonad: getTime :: T (Maybe Ordering, Stamp)
+ Sound.ALSA.Sequencer.Event.RemoveMonad: instance Applicative T
+ Sound.ALSA.Sequencer.Event.RemoveMonad: instance Functor T
+ Sound.ALSA.Sequencer.Event.RemoveMonad: instance Monad T
+ Sound.ALSA.Sequencer.Event.RemoveMonad: putChannel :: Maybe Channel -> T ()
+ Sound.ALSA.Sequencer.Event.RemoveMonad: putDest :: Maybe (T, T) -> T ()
+ Sound.ALSA.Sequencer.Event.RemoveMonad: putEventType :: Type e => Maybe e -> T ()
+ Sound.ALSA.Sequencer.Event.RemoveMonad: putIgnoreOff :: Bool -> T ()
+ Sound.ALSA.Sequencer.Event.RemoveMonad: putInput :: Bool -> T ()
+ Sound.ALSA.Sequencer.Event.RemoveMonad: putOutput :: Bool -> T ()
+ Sound.ALSA.Sequencer.Event.RemoveMonad: putTag :: Maybe Tag -> T ()
+ Sound.ALSA.Sequencer.Event.RemoveMonad: putTime :: Maybe Ordering -> Stamp -> T ()
+ Sound.ALSA.Sequencer.Event.RemoveMonad: run :: T mode -> T a -> IO a
+ Sound.ALSA.Sequencer.Event.RemoveMonad: setChannel :: Channel -> T ()
+ Sound.ALSA.Sequencer.Event.RemoveMonad: setDest :: (T, T) -> T ()
+ Sound.ALSA.Sequencer.Event.RemoveMonad: setEventType :: Type e => e -> T ()
+ Sound.ALSA.Sequencer.Event.RemoveMonad: setIgnoreOff :: T ()
+ Sound.ALSA.Sequencer.Event.RemoveMonad: setInput :: T ()
+ Sound.ALSA.Sequencer.Event.RemoveMonad: setOutput :: T ()
+ Sound.ALSA.Sequencer.Event.RemoveMonad: setTag :: Tag -> T ()
+ Sound.ALSA.Sequencer.Event.RemoveMonad: setTime :: Ordering -> Stamp -> T ()
+ Sound.ALSA.Sequencer.Poll: descriptors :: T mode -> Events -> IO [Fd]
+ Sound.ALSA.Sequencer.Port: Cons :: Word8 -> T
+ Sound.ALSA.Sequencer.Port: newtype T
+ Sound.ALSA.Sequencer.Port.Info: data T
+ Sound.ALSA.Sequencer.Port.Info: queryLoop :: T mode -> T -> (T -> IO a) -> IO [a]
+ Sound.ALSA.Sequencer.Port.Info: queryLoop_ :: T mode -> T -> (T -> IO ()) -> IO ()
+ Sound.ALSA.Sequencer.Port.InfoMonad: data T a
+ Sound.ALSA.Sequencer.Port.InfoMonad: get :: T mode -> T -> T a -> IO a
+ Sound.ALSA.Sequencer.Port.InfoMonad: getAddr :: T T
+ Sound.ALSA.Sequencer.Port.InfoMonad: getCapability :: T Cap
+ Sound.ALSA.Sequencer.Port.InfoMonad: getClient :: T T
+ Sound.ALSA.Sequencer.Port.InfoMonad: getMidiChannels :: T Word
+ Sound.ALSA.Sequencer.Port.InfoMonad: getMidiVoices :: T Word
+ Sound.ALSA.Sequencer.Port.InfoMonad: getName :: T String
+ Sound.ALSA.Sequencer.Port.InfoMonad: getPort :: T T
+ Sound.ALSA.Sequencer.Port.InfoMonad: getPortSpecified :: T Bool
+ Sound.ALSA.Sequencer.Port.InfoMonad: getReadUse :: T Word
+ Sound.ALSA.Sequencer.Port.InfoMonad: getSynthVoices :: T Word
+ Sound.ALSA.Sequencer.Port.InfoMonad: getTimestampQueue :: T T
+ Sound.ALSA.Sequencer.Port.InfoMonad: getTimestampReal :: T Bool
+ Sound.ALSA.Sequencer.Port.InfoMonad: getTimestamping :: T Bool
+ Sound.ALSA.Sequencer.Port.InfoMonad: getWriteUse :: T Word
+ Sound.ALSA.Sequencer.Port.InfoMonad: instance Applicative T
+ Sound.ALSA.Sequencer.Port.InfoMonad: instance Functor T
+ Sound.ALSA.Sequencer.Port.InfoMonad: instance Monad T
+ Sound.ALSA.Sequencer.Port.InfoMonad: modify :: T mode -> T -> T a -> IO a
+ Sound.ALSA.Sequencer.Port.InfoMonad: run :: T a -> T -> IO a
+ Sound.ALSA.Sequencer.Port.InfoMonad: setAddr :: T -> T ()
+ Sound.ALSA.Sequencer.Port.InfoMonad: setCapability :: Cap -> T ()
+ Sound.ALSA.Sequencer.Port.InfoMonad: setClient :: T -> T ()
+ Sound.ALSA.Sequencer.Port.InfoMonad: setMidiChannels :: Word -> T ()
+ Sound.ALSA.Sequencer.Port.InfoMonad: setMidiVoices :: Word -> T ()
+ Sound.ALSA.Sequencer.Port.InfoMonad: setName :: String -> T ()
+ Sound.ALSA.Sequencer.Port.InfoMonad: setPort :: T -> T ()
+ Sound.ALSA.Sequencer.Port.InfoMonad: setPortSpecified :: Bool -> T ()
+ Sound.ALSA.Sequencer.Port.InfoMonad: setSynthVoices :: Word -> T ()
+ Sound.ALSA.Sequencer.Port.InfoMonad: setTimestampQueue :: T -> T ()
+ Sound.ALSA.Sequencer.Port.InfoMonad: setTimestampReal :: Bool -> T ()
+ Sound.ALSA.Sequencer.Port.InfoMonad: setTimestamping :: Bool -> T ()
+ Sound.ALSA.Sequencer.Query: class C info => C info
+ Sound.ALSA.Sequencer.Query: first :: C info => T mode -> IO info
+ Sound.ALSA.Sequencer.Query: init :: C info => info -> IO ()
+ Sound.ALSA.Sequencer.Query: loop :: C info => T mode -> (info -> IO ()) -> (info -> IO a) -> IO [a]
+ Sound.ALSA.Sequencer.Query: loop_ :: C info => T mode -> (info -> IO ()) -> (info -> IO ()) -> IO ()
+ Sound.ALSA.Sequencer.Query: next :: C info => T mode -> info -> IO Bool
+ Sound.ALSA.Sequencer.Queue.Info: data T
+ Sound.ALSA.Sequencer.Queue.Info: instance C T
+ Sound.ALSA.Sequencer.Queue.Status: data T
+ Sound.ALSA.Sequencer.Queue.Status: instance C T
+ Sound.ALSA.Sequencer.Queue.Tempo: data T
+ Sound.ALSA.Sequencer.Queue.Tempo: instance C T
+ Sound.ALSA.Sequencer.Queue.Timer: data T
+ Sound.ALSA.Sequencer.Queue.Timer: instance C T
+ Sound.ALSA.Sequencer.Queue.Timer: instance Enum Type
+ Sound.ALSA.Sequencer.Queue.Timer: instance Eq Type
+ Sound.ALSA.Sequencer.Queue.Timer: instance Ord Type
+ Sound.ALSA.Sequencer.Queue.Timer: instance Show Type
+ Sound.ALSA.Sequencer.RealTime: fromFractional :: RealFrac a => a -> T
+ Sound.ALSA.Sequencer.RealTime: toFractional :: RealFrac a => T -> a
+ Sound.ALSA.Sequencer.Subscribe: clone :: T -> IO T
+ Sound.ALSA.Sequencer.Subscribe: copy :: T -> T -> IO ()
+ Sound.ALSA.Sequencer.Subscribe: create :: T -> T -> Bool -> Maybe (T, Bool) -> IO T
+ Sound.ALSA.Sequencer.Subscribe: data T
+ Sound.ALSA.Sequencer.Subscribe: getDest :: T -> IO T
+ Sound.ALSA.Sequencer.Subscribe: getExclusive :: T -> IO Bool
+ Sound.ALSA.Sequencer.Subscribe: getQueue :: T -> IO T
+ Sound.ALSA.Sequencer.Subscribe: getSender :: T -> IO T
+ Sound.ALSA.Sequencer.Subscribe: getTimeReal :: T -> IO Bool
+ Sound.ALSA.Sequencer.Subscribe: getTimeUpdate :: T -> IO Bool
+ Sound.ALSA.Sequencer.Subscribe: instance C T
+ Sound.ALSA.Sequencer.Subscribe: malloc :: IO T
+ Sound.ALSA.Sequencer.Subscribe: setDest :: T -> T -> IO ()
+ Sound.ALSA.Sequencer.Subscribe: setExclusive :: T -> Bool -> IO ()
+ Sound.ALSA.Sequencer.Subscribe: setQueue :: T -> T -> IO ()
+ Sound.ALSA.Sequencer.Subscribe: setSender :: T -> T -> IO ()
+ Sound.ALSA.Sequencer.Subscribe: setTimeReal :: T -> Bool -> IO ()
+ Sound.ALSA.Sequencer.Subscribe: setTimeUpdate :: T -> Bool -> IO ()
+ Sound.ALSA.Sequencer.Subscribe: subscribePort :: T mode -> T -> IO ()
+ Sound.ALSA.Sequencer.Subscribe: unsubscribePort :: T mode -> T -> IO ()
+ Sound.ALSA.Sequencer.Subscribe.Query: clone :: T -> IO T
+ Sound.ALSA.Sequencer.Subscribe.Query: copy :: T -> T -> IO ()
+ Sound.ALSA.Sequencer.Subscribe.Query: data T
+ Sound.ALSA.Sequencer.Subscribe.Query: instance C T
+ Sound.ALSA.Sequencer.Subscribe.Query: instance Enum Type
+ Sound.ALSA.Sequencer.Subscribe.Query: instance Eq Type
+ Sound.ALSA.Sequencer.Subscribe.Query: instance Ord Type
+ Sound.ALSA.Sequencer.Subscribe.Query: instance Show Type
+ Sound.ALSA.Sequencer.Subscribe.Query: malloc :: IO T
+ Sound.ALSA.Sequencer.Subscribe.Query: setClient :: T -> T -> IO ()
+ Sound.ALSA.Sequencer.Subscribe.Query: setIndex :: T -> Word -> IO ()
+ Sound.ALSA.Sequencer.Subscribe.Query: setPort :: T -> T -> IO ()
+ Sound.ALSA.Sequencer.Subscribe.Query: setType :: T -> Type -> IO ()
+ Sound.ALSA.Sequencer.Time: Absolute :: Mode
+ Sound.ALSA.Sequencer.Time: Cons :: Mode -> Stamp -> T
+ Sound.ALSA.Sequencer.Time: Real :: !T -> Stamp
+ Sound.ALSA.Sequencer.Time: Relative :: Mode
+ Sound.ALSA.Sequencer.Time: Tick :: !Tick -> Stamp
+ Sound.ALSA.Sequencer.Time: consAbs :: Stamp -> T
+ Sound.ALSA.Sequencer.Time: consRel :: Stamp -> T
+ Sound.ALSA.Sequencer.Time: data Mode
+ Sound.ALSA.Sequencer.Time: data Stamp
+ Sound.ALSA.Sequencer.Time: data T
+ Sound.ALSA.Sequencer.Time: mode :: T -> Mode
+ Sound.ALSA.Sequencer.Time: stamp :: T -> Stamp
- Sound.ALSA.Sequencer.Event: ConnEv :: ConnEv -> Connect -> Data
+ Sound.ALSA.Sequencer.Event: ConnEv :: ConnEv -> T -> Data
- Sound.ALSA.Sequencer.Event: Cons :: !Bool -> !Word8 -> !T -> !TimeStamp -> !T -> !T -> !Data -> T
+ Sound.ALSA.Sequencer.Event: Cons :: !Bool -> !Tag -> !T -> !T -> !T -> !T -> !Data -> T
- Sound.ALSA.Sequencer.Event: Ctrl :: !Word8 -> !Word32 -> !Int32 -> Ctrl
+ Sound.ALSA.Sequencer.Event: Ctrl :: !Channel -> !Parameter -> !Value -> Ctrl
- Sound.ALSA.Sequencer.Event: Note :: !Word8 -> !Word8 -> !Word8 -> !Word8 -> !Word32 -> Note
+ Sound.ALSA.Sequencer.Event: Note :: !Channel -> !Pitch -> !Velocity -> !Velocity -> !Duration -> Note
- Sound.ALSA.Sequencer.Event: QueueSetPosTick :: QueueEv
+ Sound.ALSA.Sequencer.Event: QueueSetPosTick :: !Tick -> QueueEv
- Sound.ALSA.Sequencer.Event: QueueSetPosTime :: QueueEv
+ Sound.ALSA.Sequencer.Event: QueueSetPosTime :: !T -> QueueEv
- Sound.ALSA.Sequencer.Event: QueueSkew :: QueueEv
+ Sound.ALSA.Sequencer.Event: QueueSkew :: !Skew -> QueueEv
- Sound.ALSA.Sequencer.Event: QueueSyncPos :: QueueEv
+ Sound.ALSA.Sequencer.Event: QueueSyncPos :: !Position -> QueueEv
- Sound.ALSA.Sequencer.Event: QueueTempo :: QueueEv
+ Sound.ALSA.Sequencer.Event: QueueTempo :: !Tempo -> QueueEv
- Sound.ALSA.Sequencer.Event: ctrlChannel :: Ctrl -> !Word8
+ Sound.ALSA.Sequencer.Event: ctrlChannel :: Ctrl -> !Channel
- Sound.ALSA.Sequencer.Event: ctrlParam :: Ctrl -> !Word32
+ Sound.ALSA.Sequencer.Event: ctrlParam :: Ctrl -> !Parameter
- Sound.ALSA.Sequencer.Event: ctrlValue :: Ctrl -> !Int32
+ Sound.ALSA.Sequencer.Event: ctrlValue :: Ctrl -> !Value
- Sound.ALSA.Sequencer.Event: noteChannel :: Note -> !Word8
+ Sound.ALSA.Sequencer.Event: noteChannel :: Note -> !Channel
- Sound.ALSA.Sequencer.Event: noteDuration :: Note -> !Word32
+ Sound.ALSA.Sequencer.Event: noteDuration :: Note -> !Duration
- Sound.ALSA.Sequencer.Event: noteNote :: Note -> !Word8
+ Sound.ALSA.Sequencer.Event: noteNote :: Note -> !Pitch
- Sound.ALSA.Sequencer.Event: noteOffVelocity :: Note -> !Word8
+ Sound.ALSA.Sequencer.Event: noteOffVelocity :: Note -> !Velocity
- Sound.ALSA.Sequencer.Event: noteVelocity :: Note -> !Word8
+ Sound.ALSA.Sequencer.Event: noteVelocity :: Note -> !Velocity
- Sound.ALSA.Sequencer.Event: simpleNote :: Word8 -> Word8 -> Word8 -> Note
+ Sound.ALSA.Sequencer.Event: simpleNote :: Channel -> Pitch -> Velocity -> Note
- Sound.ALSA.Sequencer.Event: tag :: T -> !Word8
+ Sound.ALSA.Sequencer.Event: tag :: T -> !Tag
- Sound.ALSA.Sequencer.Event.Accessor: connect :: T T Connect
+ Sound.ALSA.Sequencer.Event.Accessor: connect :: T T T
- Sound.ALSA.Sequencer.Event.Accessor: tag :: T T Word8
+ Sound.ALSA.Sequencer.Event.Accessor: tag :: T T Tag
- Sound.ALSA.Sequencer.Port: create :: T mode -> PortInfo -> IO ()
+ Sound.ALSA.Sequencer.Port: create :: T mode -> T -> IO ()
- Sound.ALSA.Sequencer.Port.Info: queryNext :: T mode -> T -> IO ()
+ Sound.ALSA.Sequencer.Port.Info: queryNext :: T mode -> T -> IO Bool
- Sound.ALSA.Sequencer.Queue: control :: T mode -> T -> QueueEv -> Int -> Maybe T -> IO ()
+ Sound.ALSA.Sequencer.Queue: control :: T mode -> T -> QueueEv -> Maybe T -> IO ()
- Sound.ALSA.Sequencer.Queue.Status: getTickTime :: T -> IO Word32
+ Sound.ALSA.Sequencer.Queue.Status: getTickTime :: T -> IO Tick

Files

alsa-seq.cabal view
@@ -1,12 +1,12 @@ Name:           alsa-seq-Version:        0.5.1.1-Copyright:      Bjorn Bringert, Iavor S. Diatchki, Henning Thielemann-Maintainer:     Henning Thielemann <alsa@henning-thielemann.de>+Version:        0.6 Author:   Henning Thielemann <alsa@henning-thielemann.de>,   Dylan Simon <dylan@dylex.net>,   Bjorn Bringert <bjorn@bringert.net>,   Iavor S. Diatchki <iavor.diatchki@gmail.com>+Maintainer:     Henning Thielemann <alsa@henning-thielemann.de>+Copyright:      Bjorn Bringert, Iavor S. Diatchki, Dylan Simon, Henning Thielemann Category:       Sound, Music License:        BSD3 License-file:   LICENSE@@ -23,15 +23,12 @@ Extra-Source-Files:   filter/modify/Sound/ALSA/Sequencer/Client/Info/EventFilter.hs   filter/setget/Sound/ALSA/Sequencer/Client/Info/EventFilter.hs+  src/Sound/ALSA/Sequencer/Marshal/Template.h+  src/Sound/ALSA/Sequencer/Area.h  Source-Repository head   type:     darcs-  location: http://code.haskell.org/~thielema/alsa-seq/--Source-Repository this-  type:     darcs-  location: http://code.haskell.org/~thielema/alsa-seq/-  tag:      0.5.1.1+  location: http://code.haskell.org/alsa/seq/  Flag buildExamples   description: Build example executables@@ -44,12 +41,15 @@ Library   Build-depends:     alsa-core >=0.5 && <0.6,-    enumset >= 0.0.2 && <0.1,-    array >= 0.1 && <0.5,-    data-accessor >=0.2.1 && <0.3,-    utility-ht >= 0.0.7 && <0.1,+    enumset >=0.0.3 && <0.1,+    transformers >=0.2 && <0.4,+    array >=0.1 && <0.5,+    bytestring >=0.9 && <0.10,+    data-accessor >=0.2.2 && <0.3,+    utility-ht >=0.0.7 && <0.1,+    poll >=0.0 && <0.1,     extensible-exceptions >=0.1.1 && <0.2,-    base >= 3 && <5+    base >=3 && <5    GHC-Options: -Wall   Extensions:@@ -58,6 +58,7 @@     EmptyDataDecls    Hs-Source-Dirs: src+  Include-Dirs: src   If flag(modifyFilter)     PkgConfig-Depends: alsa >= 1.0.17     Hs-Source-Dirs: filter/modify@@ -70,29 +71,40 @@     Sound.ALSA.Sequencer.Address     Sound.ALSA.Sequencer.Client     Sound.ALSA.Sequencer.Client.Info+    Sound.ALSA.Sequencer.Client.InfoMonad+    Sound.ALSA.Sequencer.Connect     Sound.ALSA.Sequencer.Port     Sound.ALSA.Sequencer.Port.Info+    Sound.ALSA.Sequencer.Port.InfoMonad     Sound.ALSA.Sequencer.Event     Sound.ALSA.Sequencer.Event.Accessor-    Sound.ALSA.Sequencer.RealTime+    Sound.ALSA.Sequencer.Event.RemoveMonad+    Sound.ALSA.Sequencer.Query     Sound.ALSA.Sequencer.Queue     Sound.ALSA.Sequencer.Queue.Info     Sound.ALSA.Sequencer.Queue.Status     Sound.ALSA.Sequencer.Queue.Tempo     Sound.ALSA.Sequencer.Queue.Timer+    Sound.ALSA.Sequencer.RealTime+    Sound.ALSA.Sequencer.Time+    Sound.ALSA.Sequencer.Concurrent     Sound.ALSA.Sequencer.Subscribe     Sound.ALSA.Sequencer.Subscribe.Query+    Sound.ALSA.Sequencer.Poll    Other-modules:+    Sound.ALSA.Sequencer.Event.Remove     Sound.ALSA.Sequencer.Marshal.Sequencer     Sound.ALSA.Sequencer.Marshal.Address     Sound.ALSA.Sequencer.Marshal.Client+    Sound.ALSA.Sequencer.Marshal.ClientInfo+    Sound.ALSA.Sequencer.Marshal.Connect     Sound.ALSA.Sequencer.Marshal.Port+    Sound.ALSA.Sequencer.Marshal.PortInfo     Sound.ALSA.Sequencer.Marshal.Queue-    Sound.ALSA.Sequencer.Marshal.QueueTimer     Sound.ALSA.Sequencer.Marshal.Event     Sound.ALSA.Sequencer.Marshal.RealTime-    Sound.ALSA.Sequencer.Marshal.QuerySubscribe+    Sound.ALSA.Sequencer.Marshal.Time     Sound.ALSA.Sequencer.Client.Info.EventFilter     Sound.ALSA.Sequencer.Area     Sound.ALSA.Sequencer.Sequencer@@ -105,11 +117,12 @@   If !flag(buildExamples)     Buildable: False   Hs-Source-Dirs: src, examples+  Include-Dirs: src   If flag(modifyFilter)     Hs-Source-Dirs: filter/modify   Else     Hs-Source-Dirs: filter/setget-  GHC-Options: -Wall -threaded+  GHC-Options: -Wall   Extensions:     ForeignFunctionInterface     GeneralizedNewtypeDeriving@@ -118,19 +131,24 @@     Sound.ALSA.Sequencer.Marshal.Sequencer     Sound.ALSA.Sequencer.Marshal.Address     Sound.ALSA.Sequencer.Marshal.Client+    Sound.ALSA.Sequencer.Marshal.ClientInfo+    Sound.ALSA.Sequencer.Marshal.Connect     Sound.ALSA.Sequencer.Marshal.Port+    Sound.ALSA.Sequencer.Marshal.PortInfo     Sound.ALSA.Sequencer.Marshal.Queue-    Sound.ALSA.Sequencer.Marshal.QueueTimer     Sound.ALSA.Sequencer.Marshal.Event     Sound.ALSA.Sequencer.Marshal.RealTime-    Sound.ALSA.Sequencer.Marshal.QuerySubscribe+    Sound.ALSA.Sequencer.Marshal.Time     Sound.ALSA.Sequencer.Area     Sound.ALSA.Sequencer.Sequencer   Build-Depends:     alsa-core >=0.5 && <0.6,-    enumset >= 0.0.2 && <0.1,-    array >= 0.1 && <0.5,-    utility-ht >= 0.0.7 && <0.1,+    enumset >=0.0.3 && <0.1,+    transformers >=0.2 && <0.4,+    array >=0.1 && <0.5,+    bytestring >=0.9 && <0.10,+    data-accessor >=0.2.2 && <0.3,+    utility-ht >=0.0.7 && <0.1,     base >=3 && <5  Executable alsa-seq-send-note@@ -138,11 +156,12 @@   If !flag(buildExamples)     Buildable: False   Hs-Source-Dirs: src, examples+  Include-Dirs: src   If flag(modifyFilter)     Hs-Source-Dirs: filter/modify   Else     Hs-Source-Dirs: filter/setget-  GHC-Options: -Wall -threaded+  GHC-Options: -Wall   Extensions:     ForeignFunctionInterface     GeneralizedNewtypeDeriving@@ -151,19 +170,25 @@     Sound.ALSA.Sequencer.Marshal.Sequencer     Sound.ALSA.Sequencer.Marshal.Address     Sound.ALSA.Sequencer.Marshal.Client+    Sound.ALSA.Sequencer.Marshal.ClientInfo+    Sound.ALSA.Sequencer.Marshal.Connect     Sound.ALSA.Sequencer.Marshal.Port+    Sound.ALSA.Sequencer.Marshal.PortInfo     Sound.ALSA.Sequencer.Marshal.Queue-    Sound.ALSA.Sequencer.Marshal.QueueTimer     Sound.ALSA.Sequencer.Marshal.Event     Sound.ALSA.Sequencer.Marshal.RealTime-    Sound.ALSA.Sequencer.Marshal.QuerySubscribe+    Sound.ALSA.Sequencer.Marshal.Time     Sound.ALSA.Sequencer.Area     Sound.ALSA.Sequencer.Sequencer+    Common   Build-Depends:     alsa-core >=0.5 && <0.6,-    enumset >= 0.0.2 && <0.1,-    array >= 0.1 && <0.5,-    utility-ht >= 0.0.7 && <0.1,+    enumset >=0.0.3 && <0.1,+    transformers >=0.2 && <0.4,+    array >=0.1 && <0.5,+    bytestring >=0.9 && <0.10,+    data-accessor >=0.2.2 && <0.3,+    utility-ht >=0.0.7 && <0.1,     base >=3 && <5  Executable alsa-seq-broadcast@@ -171,11 +196,12 @@   If !flag(buildExamples)     Buildable: False   Hs-Source-Dirs: src, examples+  Include-Dirs: src   If flag(modifyFilter)     Hs-Source-Dirs: filter/modify   Else     Hs-Source-Dirs: filter/setget-  GHC-Options: -Wall -threaded+  GHC-Options: -Wall   Extensions:     ForeignFunctionInterface     GeneralizedNewtypeDeriving@@ -184,31 +210,37 @@     Sound.ALSA.Sequencer.Marshal.Sequencer     Sound.ALSA.Sequencer.Marshal.Address     Sound.ALSA.Sequencer.Marshal.Client+    Sound.ALSA.Sequencer.Marshal.ClientInfo+    Sound.ALSA.Sequencer.Marshal.Connect     Sound.ALSA.Sequencer.Marshal.Port+    Sound.ALSA.Sequencer.Marshal.PortInfo     Sound.ALSA.Sequencer.Marshal.Queue-    Sound.ALSA.Sequencer.Marshal.QueueTimer     Sound.ALSA.Sequencer.Marshal.Event     Sound.ALSA.Sequencer.Marshal.RealTime-    Sound.ALSA.Sequencer.Marshal.QuerySubscribe+    Sound.ALSA.Sequencer.Marshal.Time     Sound.ALSA.Sequencer.Area     Sound.ALSA.Sequencer.Sequencer   Build-Depends:     alsa-core >=0.5 && <0.6,-    enumset >= 0.0.2 && <0.1,-    array >= 0.1 && <0.5,-    utility-ht >= 0.0.7 && <0.1,+    enumset >=0.0.3 && <0.1,+    transformers >=0.2 && <0.4,+    array >=0.1 && <0.5,+    bytestring >=0.9 && <0.10,+    data-accessor >=0.2.2 && <0.3,+    utility-ht >=0.0.7 && <0.1,     base >=3 && <5 -Executable alsa-seq-list-clients-  Main-Is: list-clients.hs+Executable alsa-seq-list-ports+  Main-Is: list-ports.hs   If !flag(buildExamples)     Buildable: False   Hs-Source-Dirs: src, examples+  Include-Dirs: src   If flag(modifyFilter)     Hs-Source-Dirs: filter/modify   Else     Hs-Source-Dirs: filter/setget-  GHC-Options: -Wall -threaded+  GHC-Options: -Wall   Extensions:     ForeignFunctionInterface     GeneralizedNewtypeDeriving@@ -217,19 +249,24 @@     Sound.ALSA.Sequencer.Marshal.Sequencer     Sound.ALSA.Sequencer.Marshal.Address     Sound.ALSA.Sequencer.Marshal.Client+    Sound.ALSA.Sequencer.Marshal.ClientInfo+    Sound.ALSA.Sequencer.Marshal.Connect     Sound.ALSA.Sequencer.Marshal.Port+    Sound.ALSA.Sequencer.Marshal.PortInfo     Sound.ALSA.Sequencer.Marshal.Queue-    Sound.ALSA.Sequencer.Marshal.QueueTimer     Sound.ALSA.Sequencer.Marshal.Event     Sound.ALSA.Sequencer.Marshal.RealTime-    Sound.ALSA.Sequencer.Marshal.QuerySubscribe+    Sound.ALSA.Sequencer.Marshal.Time     Sound.ALSA.Sequencer.Area     Sound.ALSA.Sequencer.Sequencer   Build-Depends:     alsa-core >=0.5 && <0.6,-    enumset >= 0.0.2 && <0.1,-    array >= 0.1 && <0.5,-    utility-ht >= 0.0.7 && <0.1,+    enumset >=0.0.3 && <0.1,+    transformers >=0.2 && <0.4,+    array >=0.1 && <0.5,+    bytestring >=0.9 && <0.10,+    data-accessor >=0.2.2 && <0.3,+    utility-ht >=0.0.7 && <0.1,     base >=3 && <5  Executable alsa-seq-melody@@ -237,11 +274,12 @@   If !flag(buildExamples)     Buildable: False   Hs-Source-Dirs: src, examples+  Include-Dirs: src   If flag(modifyFilter)     Hs-Source-Dirs: filter/modify   Else     Hs-Source-Dirs: filter/setget-  GHC-Options: -Wall -threaded+  GHC-Options: -Wall   Extensions:     ForeignFunctionInterface     GeneralizedNewtypeDeriving@@ -250,19 +288,25 @@     Sound.ALSA.Sequencer.Marshal.Sequencer     Sound.ALSA.Sequencer.Marshal.Address     Sound.ALSA.Sequencer.Marshal.Client+    Sound.ALSA.Sequencer.Marshal.ClientInfo+    Sound.ALSA.Sequencer.Marshal.Connect     Sound.ALSA.Sequencer.Marshal.Port+    Sound.ALSA.Sequencer.Marshal.PortInfo     Sound.ALSA.Sequencer.Marshal.Queue-    Sound.ALSA.Sequencer.Marshal.QueueTimer     Sound.ALSA.Sequencer.Marshal.Event     Sound.ALSA.Sequencer.Marshal.RealTime-    Sound.ALSA.Sequencer.Marshal.QuerySubscribe+    Sound.ALSA.Sequencer.Marshal.Time     Sound.ALSA.Sequencer.Area     Sound.ALSA.Sequencer.Sequencer+    Common   Build-Depends:     alsa-core >=0.5 && <0.6,-    enumset >= 0.0.2 && <0.1,-    array >= 0.1 && <0.5,-    utility-ht >= 0.0.7 && <0.1,+    enumset >=0.0.3 && <0.1,+    transformers >=0.2 && <0.4,+    array >=0.1 && <0.5,+    bytestring >=0.9 && <0.10,+    data-accessor >=0.2.2 && <0.3,+    utility-ht >=0.0.7 && <0.1,     base >=3 && <5  Executable alsa-seq-list-subscribers@@ -270,11 +314,12 @@   If !flag(buildExamples)     Buildable: False   Hs-Source-Dirs: src, examples+  Include-Dirs: src   If flag(modifyFilter)     Hs-Source-Dirs: filter/modify   Else     Hs-Source-Dirs: filter/setget-  GHC-Options: -Wall -threaded+  GHC-Options: -Wall   Extensions:     ForeignFunctionInterface     GeneralizedNewtypeDeriving@@ -283,17 +328,105 @@     Sound.ALSA.Sequencer.Marshal.Sequencer     Sound.ALSA.Sequencer.Marshal.Address     Sound.ALSA.Sequencer.Marshal.Client+    Sound.ALSA.Sequencer.Marshal.ClientInfo+    Sound.ALSA.Sequencer.Marshal.Connect     Sound.ALSA.Sequencer.Marshal.Port+    Sound.ALSA.Sequencer.Marshal.PortInfo     Sound.ALSA.Sequencer.Marshal.Queue-    Sound.ALSA.Sequencer.Marshal.QueueTimer     Sound.ALSA.Sequencer.Marshal.Event     Sound.ALSA.Sequencer.Marshal.RealTime-    Sound.ALSA.Sequencer.Marshal.QuerySubscribe+    Sound.ALSA.Sequencer.Marshal.Time     Sound.ALSA.Sequencer.Area     Sound.ALSA.Sequencer.Sequencer+    Sound.ALSA.Sequencer.Subscribe.Query   Build-Depends:     alsa-core >=0.5 && <0.6,-    enumset >= 0.0.2 && <0.1,-    array >= 0.1 && <0.5,-    utility-ht >= 0.0.7 && <0.1,+    enumset >=0.0.3 && <0.1,+    transformers >=0.2 && <0.4,+    array >=0.1 && <0.5,+    bytestring >=0.9 && <0.10,+    data-accessor >=0.2.2 && <0.3,+    utility-ht >=0.0.7 && <0.1,+    base >=3 && <5++Executable alsa-seq-beat+  Main-Is: beat.hs+  If !flag(buildExamples)+    Buildable: False+  Hs-Source-Dirs: src, examples+  Include-Dirs: src+  If flag(modifyFilter)+    Hs-Source-Dirs: filter/modify+  Else+    Hs-Source-Dirs: filter/setget+  GHC-Options: -Wall+  Extensions:+    ForeignFunctionInterface+    GeneralizedNewtypeDeriving+    EmptyDataDecls+  Other-modules:+    Sound.ALSA.Sequencer.Marshal.Sequencer+    Sound.ALSA.Sequencer.Marshal.Address+    Sound.ALSA.Sequencer.Marshal.Client+    Sound.ALSA.Sequencer.Marshal.ClientInfo+    Sound.ALSA.Sequencer.Marshal.Connect+    Sound.ALSA.Sequencer.Marshal.Port+    Sound.ALSA.Sequencer.Marshal.PortInfo+    Sound.ALSA.Sequencer.Marshal.Queue+    Sound.ALSA.Sequencer.Marshal.Event+    Sound.ALSA.Sequencer.Marshal.RealTime+    Sound.ALSA.Sequencer.Marshal.Time+    Sound.ALSA.Sequencer.Area+    Sound.ALSA.Sequencer.Sequencer+    Sound.ALSA.Sequencer.Event.Remove+    Common+  Build-Depends:+    alsa-core >=0.5 && <0.6,+    enumset >=0.0.3 && <0.1,+    transformers >=0.2 && <0.4,+    array >=0.1 && <0.5,+    bytestring >=0.9 && <0.10,+    data-accessor >=0.2.2 && <0.3,+    utility-ht >=0.0.7 && <0.1,+    base >=3 && <5++Executable alsa-seq-sysex+  Main-Is: sysex.hs+  If !flag(buildExamples)+    Buildable: False+  Hs-Source-Dirs: src, examples+  Include-Dirs: src+  If flag(modifyFilter)+    Hs-Source-Dirs: filter/modify+  Else+    Hs-Source-Dirs: filter/setget+  GHC-Options: -Wall+  Extensions:+    ForeignFunctionInterface+    GeneralizedNewtypeDeriving+    EmptyDataDecls+  Other-modules:+    Sound.ALSA.Sequencer.Marshal.Sequencer+    Sound.ALSA.Sequencer.Marshal.Address+    Sound.ALSA.Sequencer.Marshal.Client+    Sound.ALSA.Sequencer.Marshal.ClientInfo+    Sound.ALSA.Sequencer.Marshal.Connect+    Sound.ALSA.Sequencer.Marshal.Port+    Sound.ALSA.Sequencer.Marshal.PortInfo+    Sound.ALSA.Sequencer.Marshal.Queue+    Sound.ALSA.Sequencer.Marshal.Event+    Sound.ALSA.Sequencer.Marshal.RealTime+    Sound.ALSA.Sequencer.Marshal.Time+    Sound.ALSA.Sequencer.Area+    Sound.ALSA.Sequencer.Sequencer+    Sound.ALSA.Sequencer.Subscribe.Query+    Common+  Build-Depends:+    alsa-core >=0.5 && <0.6,+    enumset >=0.0.3 && <0.1,+    transformers >=0.2 && <0.4,+    array >=0.1 && <0.5,+    bytestring >=0.9 && <0.10,+    data-accessor >=0.2.2 && <0.3,+    utility-ht >=0.0.7 && <0.1,     base >=3 && <5
+ examples/Common.hs view
@@ -0,0 +1,35 @@+module Common where++import qualified Sound.ALSA.Sequencer.Connect as Connect+import qualified Sound.ALSA.Sequencer.Address as Addr+import qualified Sound.ALSA.Sequencer.Port as Port+import qualified Sound.ALSA.Sequencer as SndSeq++import qualified System.Exit as Exit+import qualified System.IO as IO+++parseAndConnect ::+   (SndSeq.AllowOutput mode) =>+   SndSeq.T mode -> Port.T -> String -> IO Connect.T+parseAndConnect h p dest =+   Connect.createTo h p =<< Addr.parse h dest++parseDestArgs ::+   (SndSeq.AllowOutput mode) =>+   SndSeq.T mode -> Addr.T -> [String] -> IO Connect.T+parseDestArgs h me args = do+   let p = Addr.port me+   case args of+      [] -> do+         putStrLn "Enter destination or connect to a synthesizer and hit ENTER"+         destStr <- getLine+         if null destStr+           then return (Connect.toSubscribers me)+           else parseAndConnect h p destStr+      [destStr] ->+         parseAndConnect h p destStr+      _ ->+         IO.hPutStrLn IO.stderr "too many arguments"+         >>+         Exit.exitFailure
+ examples/beat.hs view
@@ -0,0 +1,201 @@+{- |+Play two precisely timed beats simultaneously+where the speed can be controlled by MIDI controllers.++Whenever the speed is changed we have to cancel+the events that are already scheduled.+So we use this example to demonstrate removing output events.+-}+import qualified Sound.ALSA.Sequencer.Connect as Connect+import qualified Sound.ALSA.Sequencer.Address as Addr+import qualified Sound.ALSA.Sequencer.Client as Client+import qualified Sound.ALSA.Sequencer.Port.InfoMonad as PortInfo+import qualified Sound.ALSA.Sequencer.Port as Port+import qualified Sound.ALSA.Sequencer.Event.RemoveMonad as Remove+import qualified Sound.ALSA.Sequencer.Event as Event+import qualified Sound.ALSA.Sequencer.Queue as Queue+import qualified Sound.ALSA.Sequencer.RealTime as RealTime+import qualified Sound.ALSA.Sequencer.Time as Time+import qualified Sound.ALSA.Sequencer as SndSeq+import qualified Sound.ALSA.Exception as AlsaExc++import System.Environment (getArgs, )+import qualified System.Exit as Exit+import qualified System.IO as IO++import Control.Monad (mplus, )+import Data.Maybe.HT (toMaybe, )+++data Message = Echo Event.Tag | Tempo Event.Tag Event.Value Double+  deriving (Show)+++data Track =+  Track {+    tag :: Event.Tag,+    pitch :: Event.Pitch,+    defaultPeriod, range :: Double,+    cc :: Event.Parameter+  }+++trackA, trackB :: Track++trackA =+  Track {+    tag = Event.Tag 0,+    pitch = Event.Pitch 60,+    defaultPeriod = 1,+    range = 2,+    cc = Event.Parameter 16+  }++trackB =+  Track {+    tag = Event.Tag 1,+    pitch = Event.Pitch 64,+    defaultPeriod = 1/7,+    range = 2,+    cc = Event.Parameter 17+  }+++data State = State { _lastTime, _remainingPortion, _period :: Double }++initState :: Track -> State+initState track = State 0 0 (defaultPeriod track)+++main :: IO ()+main = (do+  SndSeq.withDefault SndSeq.Block $ \h -> do+  Client.setName (h :: SndSeq.T SndSeq.DuplexMode) "Haskell-Beat"+  Port.withSimple h "inout"+     (Port.caps [Port.capRead, Port.capSubsRead,+                 Port.capWrite, Port.capSubsWrite])+     (Port.types [Port.typeMidiGeneric, Port.typeApplication]) $ \public -> do+  Port.withSimple h "private"+     (Port.caps [Port.capRead, Port.capWrite])+     (Port.types [Port.typeMidiGeneric]) $ \private -> do+  Queue.with h $ \q -> do++  PortInfo.modify h public $ do+     PortInfo.setTimestamping True+     PortInfo.setTimestampReal True+     PortInfo.setTimestampQueue q++  c <- Client.getId h+  let publicAddr  = Addr.Cons c public+      privateAddr = Addr.Cons c private+  args <- getArgs+  case args of+     [input, output] ->+        (Connect.createFrom h public =<< Addr.parse h input)+        >>+        (Connect.createTo   h public =<< Addr.parse h output)+        >>+        return ()+     _ ->+       IO.hPutStrLn IO.stderr "need arguments: input-client output-client"+       >>+       Exit.exitFailure++  let mkEv tg t e =+         (Event.simple publicAddr e) {+             Event.tag = tg,+             Event.queue = q,+             Event.time = Time.consAbs $ Time.Real $ RealTime.fromDouble t+          }++      play tg t onoff p =+         (Event.output h $ mkEv tg t $ Event.NoteEv onoff $+          Event.simpleNote (Event.Channel 0) p Event.normalVelocity)+         >>+         return ()++      echo tg t =+         Event.output h+            ((mkEv tg t $ Event.CustomEv Event.Echo $ Event.Custom 0 0 0) {+               Event.dest = privateAddr+            })+         >>+         return ()++  Queue.control h q Event.QueueStart Nothing++  let start track = do+         play (tag track) 0 Event.NoteOn (pitch track)+         echo (tag track) 0++  start trackA+  start trackB+  _ <- Event.drainOutput h++  let checkCC ctrl track =+         toMaybe (Event.ctrlParam ctrl == cc track) (tag track)++      wait = do+         ev <- Event.input h+         case Event.body ev of+            Event.CustomEv Event.Echo _ ->+               if Event.dest ev == privateAddr+                 then return $ Echo $ Event.tag ev+                 else wait+            Event.CtrlEv Event.Controller ctrl ->+               case mplus (checkCC ctrl trackA) (checkCC ctrl trackB) of+                  Just tg ->+                     case Event.time ev of+                        Time.Cons Time.Absolute (Time.Real t) ->+                           return $ Tempo tg (Event.ctrlValue ctrl) $+                              RealTime.toDouble t+                        _ -> error "got time in a format that we did not request"+                  Nothing -> wait+            _ -> wait++  let schedule track t = do+         play (tag track) t Event.NoteOff (pitch track)+         play (tag track) t Event.NoteOn  (pitch track)+         echo (tag track) t+         _ <- Event.drainOutput h+         return ()++  {-+  Cancel the Echo and Notes we already sent,+  and replace them by ones with updated timestamp.+  -}+  let tempo track val t1 (State t0 r0 p0) = do+         Remove.run h $ do+            Remove.setOutput+            Remove.setTag $ tag track+         let r1 = r0 - (t1-t0) / p0+         let p1 = defaultPeriod track *+                     range track ** ((fromIntegral val - 64) / 64)+         schedule track $ t1 + r1 * p1+         return (State t1 r1 p1)++  let next track (State t0 r p) =+         let {-+             t1 should be the current time.+             In principle we could use the timestamp from the Echo message,+             but this will be slightly later than the reference time.+             -}+             t1 = t0 + r*p+         in  schedule track (t1+p) >> return (State t1 1 p)++  let go (sa, sb) = do+         msg <- wait+         case msg of+            Echo tg ->+               if tg == tag trackA+                 then next trackA sa >>= \s -> go (s, sb)+                 else next trackB sb >>= \s -> go (sa, s)+            Tempo tg (Event.Value val) t ->+               if tg == tag trackA+                 then tempo trackA val t sa >>= \s -> go (s, sb)+                 else tempo trackB val t sb >>= \s -> go (sa, s)++  go (initState trackA, initState trackB))++  `AlsaExc.catch` \e ->+     putStrLn $ "alsa_exception: " ++ AlsaExc.show e
examples/broadcast.hs view
@@ -8,18 +8,19 @@ main :: IO () main = (do   putStrLn "Starting."-  SndSeq.with SndSeq.defaultName SndSeq.Block $ \h -> do+  SndSeq.withDefault SndSeq.Block $ \h -> do   Client.setName (h :: SndSeq.T SndSeq.OutputMode) "Haskell-Broadcast"   c <- Client.getId h   putStrLn ("Created sequencer with id: " ++ show c)-  -- tgt_addr <- Addr.parse h "HS1:255"-  let tgt_addr = Addr.Cons Client.broadcast Port.unknown-  print tgt_addr+  -- dst <- Addr.parse h "HS1:255"+  let dst = Addr.broadcast+  print dst   let ev n =          (Event.simple             (Addr.Cons c Port.unknown)-            (Event.NoteEv n $ Event.simpleNote 0 60 64))-         {Event.dest = tgt_addr}+            (Event.NoteEv n $+             Event.simpleNote (Event.Channel 0) (Event.Pitch 60) Event.normalVelocity))+         {Event.dest = dst}   _ <- Event.outputDirect h $ ev Event.NoteOn   _ <- getChar   _ <- Event.outputDirect h $ ev Event.NoteOff
examples/dump.hs view
@@ -8,7 +8,7 @@ main :: IO () main = (do   putStrLn "Starting."-  SndSeq.with SndSeq.defaultName SndSeq.Block $ \h -> do+  SndSeq.withDefault SndSeq.Block $ \h -> do   Client.setName (h :: SndSeq.T SndSeq.InputMode) "Haskell-Dump"   putStrLn "Created sequencer."   Port.withSimple h "primary"
− examples/list-clients.hs
@@ -1,13 +0,0 @@-import qualified Sound.ALSA.Sequencer.Client.Info as ClientInfo-import qualified Sound.ALSA.Sequencer as SndSeq--import Control.Monad (when, )--main :: IO ()-main =-  SndSeq.with SndSeq.defaultName SndSeq.Block $ \h -> do-  i <- ClientInfo.queryFirst (h :: SndSeq.T SndSeq.OutputMode)-  let loop = do putStrLn =<< ClientInfo.getName i-                more <- ClientInfo.queryNext h i-                when more loop-  loop
+ examples/list-ports.hs view
@@ -0,0 +1,31 @@+import qualified Sound.ALSA.Sequencer.Client.Info as ClientInfo+import qualified Sound.ALSA.Sequencer.Port.Info as PortInfo+import qualified Sound.ALSA.Sequencer.Client as Client+import qualified Sound.ALSA.Sequencer.Port as Port+import qualified Sound.ALSA.Sequencer as SndSeq+import qualified Data.EnumSet as EnumSet+import Text.Printf (printf, )+import Control.Monad (liftM5, join, )++main :: IO ()+main = do+  putStrLn " Port    Client name                      Port name                Caps"+  SndSeq.withDefault SndSeq.Block $ \h ->+    ClientInfo.queryLoop_ (h :: SndSeq.T SndSeq.OutputMode) $ \cinfo -> do+      client <- ClientInfo.getClient cinfo+      PortInfo.queryLoop_ h client $ \pinfo -> do+        join $ liftM5 (printf "%3d:%-3d  %-32.32s %-24.24s %s\n")+          (fmap (\(Client.Cons p) -> p) $ PortInfo.getClient pinfo)+          (fmap (\(Port.Cons p) -> p) $ PortInfo.getPort pinfo)+          (ClientInfo.getName cinfo)+          (PortInfo.getName pinfo)+          (do+             caps <- PortInfo.getCapability pinfo+             let disp (cap, char) =+                    if EnumSet.disjoint caps cap then ' ' else char+             return $ map disp $+               (Port.capRead, 'r') :+               (Port.capSubsRead, 'R') :+               (Port.capWrite, 'w') :+               (Port.capSubsWrite, 'W') :+               [])
examples/list-subscribers.hs view
@@ -8,7 +8,7 @@ main :: IO () main = (do   args <- getArgs-  SndSeq.with SndSeq.defaultName SndSeq.Block $ \h -> forM_ args $ \arg -> do+  SndSeq.withDefault SndSeq.Block $ \h -> forM_ args $ \arg -> do   a <- Addr.parse (h :: SndSeq.T SndSeq.InputMode) arg   let showQ q = do 	ad <- Query.getAddr q
examples/melody.hs view
@@ -3,67 +3,45 @@ Demonstrate how to wait on the end of a performance of events, by sending an Echo message to ourselves. -}+import Common (parseDestArgs, )+ import qualified Sound.ALSA.Sequencer.Address as Addr import qualified Sound.ALSA.Sequencer.Client as Client import qualified Sound.ALSA.Sequencer.Port as Port import qualified Sound.ALSA.Sequencer.Event as Event import qualified Sound.ALSA.Sequencer.Queue as Queue+import qualified Sound.ALSA.Sequencer.Time as Time import qualified Sound.ALSA.Sequencer as SndSeq import qualified Sound.ALSA.Exception as AlsaExc -import qualified System.Exit as Exit-import qualified System.IO as IO import System.Environment (getArgs, )  import Control.Monad (zipWithM_, )  -parseAndConnect ::-   (SndSeq.AllowOutput mode) =>-   SndSeq.T mode -> Port.T -> String -> IO Addr.T-parseAndConnect h p destStr = do-  dest <- Addr.parse h destStr-  SndSeq.connectTo h p dest-  return dest- main :: IO () main = (do-  SndSeq.with SndSeq.defaultName SndSeq.Block $ \h -> do+  SndSeq.withDefault SndSeq.Block $ \h -> do   Client.setName (h :: SndSeq.T SndSeq.DuplexMode) "Haskell-Melody"   Port.withSimple h "out"      (Port.caps [Port.capRead, Port.capSubsRead, Port.capWrite])      (Port.types [Port.typeMidiGeneric, Port.typeApplication]) $ \p -> do   Queue.with h $ \q -> do-  args <- getArgs-  dest <--     case args of-        [] -> do-           putStrLn "Enter destination or connect to a synthesizer and hit ENTER"-           destStr <- getLine-           if null destStr-             then return Addr.subscribers-             else parseAndConnect h p destStr-        [destStr] ->-           parseAndConnect h p destStr-        _ ->-           IO.hPutStrLn IO.stderr "too many arguments"-           >>-           Exit.exitFailure-   c <- Client.getId h   let me = Addr.Cons c p-      ev t e =-         (Event.simple me e) {+  conn <- parseDestArgs h me =<< getArgs++  let ev t e =+         (Event.forConnection conn e) {              Event.queue = q,-             Event.dest = dest,-             Event.timestamp = Event.TickTime t+             Event.time = Time.consAbs $ Time.Tick t           }-      play t chan pitch vel =+      play t chan pitch =          Event.output h (ev t $-            Event.NoteEv Event.NoteOn $ Event.simpleNote chan pitch vel)+            Event.NoteEv Event.NoteOn $ Event.simpleNote chan pitch Event.normalVelocity)          >>          Event.output h (ev (t+1) $-            Event.NoteEv Event.NoteOn $ Event.simpleNote chan pitch 0)+            Event.NoteEv Event.NoteOff $ Event.simpleNote chan pitch Event.normalVelocity)          >>          return () @@ -73,12 +51,13 @@                Event.dest = me             }) -  Queue.control h q Event.QueueStart 0 Nothing-  Queue.control h q Event.QueueTempo 10000000 Nothing+  Queue.control h q Event.QueueStart Nothing+  Queue.control h q (Event.QueueTempo (Event.Tempo 10000000)) Nothing   zipWithM_ (\t ->-        maybe (echo t) (\n -> play t 0 n 64)) [0..] $+        maybe (echo t) (play t (Event.Channel 0))) [0..] $      (++[Nothing]) $      concat $ concatMap (replicate 4 . map Just) $+     map (map Event.Pitch) $         [57, 59, 60, 64] :         [57, 59, 60, 65] :         [57, 62, 64, 65] :
examples/send-note.hs view
@@ -1,3 +1,5 @@+import Common (parseDestArgs, )+ import qualified Sound.ALSA.Sequencer.Address as Addr import qualified Sound.ALSA.Sequencer.Client as Client import qualified Sound.ALSA.Sequencer.Port as Port@@ -5,48 +7,23 @@ import qualified Sound.ALSA.Sequencer as SndSeq import qualified Sound.ALSA.Exception as AlsaExc -import qualified System.Exit as Exit-import qualified System.IO as IO import System.Environment (getArgs, ) -parseAndConnect ::-   (SndSeq.AllowOutput mode) =>-   SndSeq.T mode -> Port.T -> String -> IO Addr.T-parseAndConnect h p destStr = do-  dest <- Addr.parse h destStr-  SndSeq.connectTo h p dest-  return dest  main :: IO () main = (do   putStrLn "Starting."-  SndSeq.with SndSeq.defaultName SndSeq.Block $ \h -> do+  SndSeq.withDefault SndSeq.Block $ \h -> do   Client.setName (h :: SndSeq.T SndSeq.OutputMode) "Haskell-Send-Note"   c <- Client.getId h   putStrLn ("Created sequencer with id: " ++ show c)   Port.withSimple h "out"      (Port.caps [Port.capRead, Port.capSubsRead]) Port.typeMidiGeneric $ \ p -> do   putStrLn "Created port."-  args <- getArgs-  dest <--     case args of-        [] -> do-           putStrLn "Enter destination or connect to a synthesizer and hit ENTER"-           destStr <- getLine-           if null destStr-             then return Addr.subscribers-             else parseAndConnect h p destStr-        [destStr] ->-           parseAndConnect h p destStr-        _ ->-           IO.hPutStrLn IO.stderr "too many arguments"-           >>-           Exit.exitFailure-+  conn <- parseDestArgs h (Addr.Cons c p) =<< getArgs   let ev n =-         (Event.simple (Addr.Cons c p) $-            Event.NoteEv n $ Event.simpleNote 0 60 64)-         {Event.dest = dest}+         Event.forConnection conn $ Event.NoteEv n $+            Event.simpleNote (Event.Channel 0) (Event.Pitch 60) Event.normalVelocity   _ <- Event.outputDirect h $ ev Event.NoteOn   putStrLn "press Enter for stopping the note"   _ <- getChar
+ examples/sysex.hs view
@@ -0,0 +1,46 @@+import Common (parseDestArgs, )++import qualified Sound.ALSA.Sequencer.Connect as Connect+import qualified Sound.ALSA.Sequencer.Address as Addr+import qualified Sound.ALSA.Sequencer.Client as Client+import qualified Sound.ALSA.Sequencer.Port as Port+import qualified Sound.ALSA.Sequencer.Event as Event+import qualified Sound.ALSA.Sequencer as SndSeq+import qualified Sound.ALSA.Exception as AlsaExc++import qualified Data.ByteString as B++import System.Environment (getArgs, )+++main :: IO ()+main = (do+  putStrLn "Starting."+  SndSeq.withDefault SndSeq.Block $ \h -> do+  Client.setName (h :: SndSeq.T SndSeq.DuplexMode) "Haskell-SysEx"+  c <- Client.getId h+  putStrLn ("Created sequencer with id: " ++ show c)+  Port.withSimple h "out"+     (Port.caps [Port.capRead, Port.capSubsRead,+                 Port.capWrite, Port.capSubsWrite]) Port.typeMidiGeneric $ \ p -> do+  putStrLn "Created port."+  let me = Addr.Cons c p+  conn <- parseDestArgs h me =<< getArgs++  putStrLn "enter a text line for submission as SysEx message"+  text <- getLine+  let dat =+         Event.ExtEv Event.SysEx $+         B.pack $ map (fromIntegral . fromEnum) text+  _ <- Event.outputDirect h $ Event.forConnection conn dat+  _ <- Event.outputDirect h $ Event.forConnection (Connect.Cons me me) dat+  let waitForSysEx = do+         ev <- Event.input h+         case Event.body ev of+            Event.ExtEv Event.SysEx str ->+               putStrLn $ "got: " ++ show str+            _ -> waitForSysEx+  waitForSysEx+  return ())+  `AlsaExc.catch` \e ->+     putStrLn $ "alsa_exception: " ++ AlsaExc.show e
filter/modify/Sound/ALSA/Sequencer/Client/Info/EventFilter.hs view
@@ -1,42 +1,41 @@ module Sound.ALSA.Sequencer.Client.Info.EventFilter where -import qualified Sound.ALSA.Sequencer.Area as Area+import Sound.ALSA.Sequencer.Marshal.ClientInfo (T, T_, with, ) import qualified Sound.ALSA.Sequencer.Marshal.Event as Event -import Foreign.C.Types(CInt, )+import qualified Foreign.C.Types as C import Foreign.Ptr(Ptr, )  -type T  = Area.ClientInfo-type T_ = Area.ClientInfo_-- clear :: T -> IO () add :: Event.Type e => T -> e -> IO () delete :: Event.Type e => T -> e -> IO () check :: Event.Type e => T -> e -> IO Bool  -clear i =-  Area.with_client_info i snd_seq_client_info_event_filter_clear+clear i = with i clear_  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_client_info_event_filter_clear"-  snd_seq_client_info_event_filter_clear :: Ptr T_ -> IO ()+  clear_ :: Ptr T_ -> IO ()  add i e =-  Area.with_client_info i (`snd_seq_client_info_event_filter_add` fromIntegral (Event.expEv e))+  with i (flip add_ $ unpackEType e)  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_client_info_event_filter_add"-  snd_seq_client_info_event_filter_add :: Ptr T_ -> CInt -> IO ()+  add_ :: Ptr T_ -> C.CInt -> IO ()  delete i e =-  Area.with_client_info i (`snd_seq_client_info_event_filter_del` fromIntegral (Event.expEv e))+  with i (flip del_ $ unpackEType e)  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_client_info_event_filter_del"-  snd_seq_client_info_event_filter_del :: Ptr T_ -> CInt -> IO ()+  del_ :: Ptr T_ -> C.CInt -> IO ()  check i e =-  fmap (/= 0) $ Area.with_client_info i (`snd_seq_client_info_event_filter_check` fromIntegral (Event.expEv e))+  fmap (/= 0) $ with i (flip check_ $ unpackEType e)  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_client_info_event_filter_check"-  snd_seq_client_info_event_filter_check :: Ptr T_ -> CInt -> IO CInt+  check_ :: Ptr T_ -> C.CInt -> IO C.CInt+++unpackEType :: Event.Type e => e -> C.CInt+unpackEType e = fromIntegral $ Event.unEType $ Event.expEv e
filter/setget/Sound/ALSA/Sequencer/Client/Info/EventFilter.hs view
@@ -1,7 +1,7 @@ -- | Emulate new api using the old functions module Sound.ALSA.Sequencer.Client.Info.EventFilter where -import qualified Sound.ALSA.Sequencer.Area as Area+import Sound.ALSA.Sequencer.Marshal.ClientInfo (T, T_, with, ) import qualified Sound.ALSA.Sequencer.Marshal.Event as Event  import Foreign.C.Types (CUInt, )@@ -11,9 +11,6 @@ import Data.Bits (testBit, setBit, clearBit, )  -type T  = Area.ClientInfo-type T_ = Area.ClientInfo_- {- | Although alsa/seq.h says CUChar, that's not true, because internally it uses CUInt and@@ -28,13 +25,12 @@ delete :: Event.Type e => T -> e -> IO () check :: Event.Type e => T -> e -> IO Bool -clear i =-  Area.with_client_info i (`snd_seq_client_info_set_event_filter` nullPtr)+clear i = with i (flip set_ nullPtr)  bit :: Event.Type e => e -> (Int, Int) bit e =   divMod-    (fromIntegral $ Event.expEv e)+    (fromIntegral $ Event.unEType $ Event.expEv e)     (8 * sizeOf (undefined :: EventTypeSubset))  size :: Int@@ -42,7 +38,7 @@   -- succ $ fst $ bit Event.maxEventType  get :: T -> IO EventTypeSet-get i = Area.with_client_info i snd_seq_client_info_get_event_filter+get i = with i get_  check i e = do   ef <- get i@@ -51,8 +47,7 @@   return $ testBit w b  set :: T -> EventTypeSet -> IO ()-set i ef =-  Area.with_client_info i (`snd_seq_client_info_set_event_filter` ef)+set i ef = with i (flip set_ ef)  modify :: T -> (EventTypeSet -> IO ()) -> IO () modify i f =@@ -74,7 +69,7 @@ delete = modifyByte clearBit  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_client_info_get_event_filter"-  snd_seq_client_info_get_event_filter :: Ptr T_ -> IO EventTypeSet+  get_ :: Ptr T_ -> IO EventTypeSet  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_client_info_set_event_filter"-  snd_seq_client_info_set_event_filter :: Ptr T_ -> EventTypeSet -> IO ()+  set_ :: Ptr T_ -> EventTypeSet -> IO ()
src/Sound/ALSA/Sequencer.hs view
@@ -26,8 +26,10 @@   , BlockMode(..)    , open+  , openDefault   , close   , with+  , withDefault   , defaultName   , getName   , setBlocking@@ -44,20 +46,7 @@   , resetPoolOutput   , setPoolInput   , resetPoolInput---  -- ** Connections-  , connectFrom-  , connectTo-  , disconnectFrom-  , disconnectTo   ) where  import Sound.ALSA.Sequencer.Marshal.Sequencer as Seq import Sound.ALSA.Sequencer.Sequencer------ | This is the name that should be passed to 'open' in most cases.-defaultName :: String-defaultName = "default"
src/Sound/ALSA/Sequencer/Address.hs view
@@ -1,20 +1,39 @@ module Sound.ALSA.Sequencer.Address   ( Addr.T(Addr.Cons, Addr.client, Addr.port)+  , Addr.unknown   , Addr.subscribers+  , Addr.broadcast+  , Addr.systemTimer+  , Addr.systemAnnounce   , parse   ) where  import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr-import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as MSeq-import qualified Sound.ALSA.Sequencer.Sequencer as Seq+import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified Sound.ALSA.Exception as Exc +import qualified Foreign.C.Types as C+import Foreign.C.String (CString, withCAString, )+import Foreign.Ptr (Ptr, )+import Foreign.Marshal.Alloc (alloca, )+import Foreign.Storable (peek, )++ {- | Parse the given string into sequencer address. The client and port are separated by either colon or period, e.g. 128:1.-The function also accepts client names.+The function also accepts client names or prefixes thereof.+Throws @(Errno 2)@ exception if no client name matches. -} parse-  :: MSeq.T mode  -- ^ Sequencer handle.+  :: Seq.T mode  -- ^ Sequencer handle.   -> String       -- ^ String to be parsed.   -> IO Addr.T    -- ^ The parsed address.-parse = Seq.parseAddress+parse (Seq.Cons h) s =+  alloca $ \pa ->+  withCAString s $ \ps ->+    do Exc.checkResult_ "Address.parse" =<< snd_seq_parse_address h pa ps+       peek pa++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_parse_address"+  snd_seq_parse_address :: Ptr Seq.Core -> Ptr Addr.T -> CString -> IO C.CInt
+ src/Sound/ALSA/Sequencer/Area.h view
@@ -0,0 +1,188 @@+#include <stdio.h>++#define hsc_alignment(t) \+    printf("(%ld)", (unsigned long)offsetof(struct {char x__; t (y__); }, y__));++char *area_name = NULL;++#define hsc_area(y) \+    area_name = ""y""; \+    puts( \+        "data T_\n" \+        "newtype T = Cons (Area.ForeignPtr T_)\n" \+        "\n" \+        "with :: T -> (Area.Ptr T_ -> IO a) -> IO a\n" \+        "with (Cons p) f = Area.withForeignPtr p f\n" \+        "\n" \+        "-- | Allocate an uninitialized object. (Not exported)\n" \+        "malloc :: IO T\n" \+        "malloc = Area.alloca $ \\p ->\n" \+        "  do Exc.checkResult_ \"Sequencer."y"\" =<< malloc_ p\n" \+        "     fmap Cons (Area.newForeignPtr free =<< Area.peek p)\n" \+        "\n" \+        "foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_"y"_malloc\"\n" \+        "  malloc_ :: Area.Ptr (Area.Ptr T_) -> IO C.CInt\n" \+        "\n" \+        "foreign import ccall unsafe \"alsa/asoundlib.h &snd_seq_"y"_free\"\n" \+        "  free :: Area.FunPtr (Area.Ptr T_ -> IO ())\n" \+        "\n" \+        "-- | Copy the content of one object into another.\n" \+        "copy\n" \+        "  :: T     -- ^ Destination\n" \+        "  -> T     -- ^ Source\n" \+        "  -> IO ()\n" \+        "\n" \+        "copy to from =\n" \+        "  with to $ \\p1 ->\n" \+        "  with from $ \\p2 ->\n" \+        "    copy_ p1 p2\n" \+        "\n" \+        "foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_"y"_copy\"\n" \+        "  copy_ :: Area.Ptr T_ -> Area.Ptr T_ -> IO ()\n" \+        "\n" \+        "-- | Copy the content of an object to a newly created object.\n" \+        "clone :: T -> IO T\n" \+        "clone from =\n" \+        "  do to <- malloc\n" \+        "     copy to from\n" \+        "     return to\n" \+        "\n" \+        "instance Area.C T where\n" \+        "  malloc = malloc\n" \+        "  copy = copy\n" \+        "  clone = clone\n" \+        "\n" \+    );++#define hsc_get_area(x) \+    printf( \+        "get :: Seq.T mode -> "x" -> IO T\n" \+        "get h q =\n" \+        "  do status <- malloc\n" \+        "     Exc.checkResult_ \"get_%s\"\n" \+        "       =<< with status (get_ h q)\n" \+        "     return status\n" \+        "\n" \+        "foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_get_%s\"\n" \+        "  get_ :: Seq.T mode -> "x" -> Area.Ptr T_ -> IO C.CInt\n" \+    , area_name, area_name);++#define hsc_set_area(x) \+    printf( \+        "set :: Seq.T mode -> "x" -> T -> IO ()\n" \+        "set h q info =\n" \+        "  Exc.checkResult_ \"set_%s\" =<< with info (set_ h q)\n" \+        "\n" \+        "foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_set_%s\"\n" \+        "  set_ :: Seq.T mode -> "x" -> Area.Ptr T_ -> IO C.CInt\n" \+    , area_name, area_name);++++#define hsc_get_set_name() \+    printf( \+        "getName :: T -> IO String\n" \+        "getName i = Area.peekCString =<< with i getName_\n" \+        "\n" \+        "foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_%s_get_name\"\n" \+        "  getName_ :: Area.Ptr T_ -> IO Area.CString\n" \+        "\n" \+        "setName :: T -> String -> IO ()\n" \+        "setName i c =\n" \+        "  Area.withCAString c $ \\p -> with i (flip setName_ p)\n" \+        "\n" \+        "foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_%s_set_name\"\n" \+        "  setName_ :: Area.Ptr T_ -> Area.CString -> IO ()\n" \+        "\n" \+    , area_name, area_name);++#define hsc_get_bool(z,nm) \+    printf( \+        "get"nm" :: T -> IO Bool\n" \+        "get"nm" i =\n" \+        "  fmap (0 /=) $ with i get"nm"_\n" \+        "\n" \+        "foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_%s_get_"z"\"\n" \+        "  get"nm"_ :: Area.Ptr T_ -> IO C.CInt\n" \+        "\n" \+    , area_name);++#define hsc_set_bool(z,nm) \+    printf( \+        "set"nm" :: T -> Bool -> IO ()\n" \+        "set"nm" i c =\n" \+        "  let x = if c then 1 else 0\n" \+        "  in  with i (flip set"nm"_ x)\n" \+        "\n" \+        "foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_%s_set_"z"\"\n" \+        "  set"nm"_ :: Area.Ptr T_ -> C.CInt -> IO ()\n" \+        "\n" \+    , area_name);++#define hsc_get_set_bool(z,nm) \+    hsc_get_bool(z,nm) \+    hsc_set_bool(z,nm)++#define hsc_get_int_gen(z,nm,t,mk,int) \+    printf( \+        "get"nm" :: T -> IO "t"\n" \+        "get"nm" i =\n" \+        "  fmap "mk" $ with i get"nm"_\n" \+        "\n" \+        "foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_%s_get_"z"\"\n" \+        "  get"nm"_ :: Area.Ptr T_ -> IO "int"\n" \+        "\n" \+    , area_name);++#define hsc_set_int_gen(z,nm,t,brk,int) \+    printf( \+        "set"nm" :: T -> "t" -> IO ()\n" \+        "set"nm" i c =\n" \+        "  with i (flip set"nm"_ ("brk" c))\n" \+        "\n" \+        "foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_%s_set_"z"\"\n" \+        "  set"nm"_  :: Area.Ptr T_ -> "int" -> IO ()\n" \+        "\n" \+    , area_name);++#define hsc_get_set_int_gen(z,nm,t,mk,brk,int) \+    hsc_get_int_gen(z,nm,t,mk,int) \+    hsc_set_int_gen(z,nm,t,brk,int)+++#define hsc_get_int(z,nm,t,mk) \+    hsc_get_int_gen(z,nm,t,mk,"C.CInt")++#define hsc_set_int(z,nm,t,brk) \+    hsc_set_int_gen(z,nm,t,brk,"C.CInt")++#define hsc_get_set_int(z,nm,t,mk,brk) \+    hsc_get_int(z,nm,t,mk) \+    hsc_set_int(z,nm,t,brk)+++#define hsc_get_ptr(z,nm,t) \+    printf( \+        "get"nm" :: T -> IO "t"\n" \+        "get"nm" i =\n" \+        "  Area.peek =<< with i get"nm"_\n" \+        "\n" \+        "foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_%s_get_"z"\"\n" \+        "  get"nm"_ :: Area.Ptr T_ -> IO (Area.Ptr "t")\n" \+        "\n" \+    , area_name);++#define hsc_set_ptr(z,nm,t) \+    printf( \+        "set"nm" :: T -> "t" -> IO ()\n" \+        "set"nm" i c =\n" \+        "  with i (\\iptr -> Area.with c (set"nm"_ iptr))\n" \+        "\n" \+        "foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_%s_set_"z"\"\n" \+        "  set"nm"_  :: Area.Ptr T_ -> (Area.Ptr "t") -> IO ()\n" \+        "\n" \+    , area_name);++#define hsc_get_set_ptr(z,nm,t) \+    hsc_get_ptr(z,nm,t) \+    hsc_set_ptr(z,nm,t)
+ src/Sound/ALSA/Sequencer/Area.hs view
@@ -0,0 +1,38 @@+--------------------------------------------------------------------------------+-- |+-- Module    : Sound.ALSA.Sequencer.Area+-- Copyright : (c) Henning Thielemann, 2010-2012+--             (c) Iavor S. Diatchki, 2007+-- License   : BSD3+--+-- Maintainer: Henning Thielemann+-- Stability : provisional+--+-- PRIVATE MODULE.+--+-- Here we have macros to deal with the various information+-- areas present in the library.+--------------------------------------------------------------------------------++module Sound.ALSA.Sequencer.Area (+  C(..),+  MU.with,+  MA.alloca,+  St.peek,+  Ptr.Ptr, Ptr.FunPtr,+  FPtr.ForeignPtr, FPtr.newForeignPtr, FPtr.withForeignPtr,+  CStr.CString, CStr.peekCString, CStr.withCAString,+  ) where++import qualified Foreign.Marshal.Utils as MU+import qualified Foreign.Marshal.Alloc as MA+import qualified Foreign.C.String as CStr+import qualified Foreign.Storable as St+import qualified Foreign.ForeignPtr as FPtr+import qualified Foreign.Ptr as Ptr+++class C area where+   malloc :: IO area+   copy :: area -> area -> IO ()+   clone :: area -> IO area
− src/Sound/ALSA/Sequencer/Area.hsc
@@ -1,315 +0,0 @@------------------------------------------------------------------------------------ |--- Module    : Sound.ALSA.Sequencer.Area--- Copyright : (c) Henning Thielemann, 2010---             (c) Iavor S. Diatchki, 2007--- License   : BSD3------ Maintainer: Henning Thielemann--- Stability : provisional------ PRIVATE MODULE.------ Here we have macros to deal with the various information--- areas present in the library.-----------------------------------------------------------------------------------module Sound.ALSA.Sequencer.Area where--import qualified Sound.ALSA.Sequencer.Marshal.Client as Client-import qualified Sound.ALSA.Sequencer.Marshal.Port as Port-import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue-import qualified Sound.ALSA.Sequencer.Marshal.QueueTimer as QueueTimer-import qualified Sound.ALSA.Sequencer.Marshal.QuerySubscribe as QuerySubscribe-import qualified Sound.ALSA.Exception as Exc--import qualified Data.EnumSet as EnumSet-import Foreign.C.Types (CInt, )-import Foreign.C.String (CString, peekCString, withCAString, )-import Foreign.Storable (Storable, peek, )-import Foreign.Marshal.Alloc (alloca, )-import Foreign.ForeignPtr (ForeignPtr, newForeignPtr, withForeignPtr, )-import Foreign.Ptr (Ptr, FunPtr, )-import Data.Word (Word, )---class C area where-   malloc :: IO area-   copy :: area -> area -> IO ()-   clone :: area -> IO area--#{let area x,y =-"data "x"_\n"-"newtype "x" = "x" (ForeignPtr "x"_)\n"-"\n"-"with_"y" :: "x" -> (Ptr "x"_ -> IO a) -> IO a\n"-"with_"y" ("x" p) f = withForeignPtr p f\n"-"\n"-"-- | Allocate an uninitialized object. (Not exported)\n"-y"_malloc :: IO "x"\n"-y"_malloc = alloca $ \\p ->\n"-"  do Exc.checkResult_ \"Sequencer."y"\" =<< snd_seq_"y"_malloc p\n"-"     "x" `fmap` (newForeignPtr snd_seq_"y"_free =<< peek p)\n"-"\n"-"foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_"y"_malloc\"\n"-"  snd_seq_"y"_malloc :: Ptr (Ptr "x"_) -> IO CInt\n"-"\n"-"foreign import ccall unsafe \"alsa/asoundlib.h &snd_seq_"y"_free\"\n"-"   snd_seq_"y"_free :: FunPtr (Ptr "x"_ -> IO ())\n"-"\n"-"-- | Copy the content of one object into another.\n"-y"_copy\n"-"  :: "x"     -- ^ Destination\n"-"  -> "x"     -- ^ Source\n"-"  -> IO ()\n"-"\n"-y"_copy to from =\n"-"  with_"y" to $ \\p1 ->\n"-"  with_"y" from $ \\p2 ->\n"-"    snd_seq_"y"_copy p1 p2\n"-"\n"-"foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_"y"_copy\"\n"-"  snd_seq_"y"_copy :: Ptr "x"_ -> Ptr "x"_ -> IO ()\n"-"\n"-"-- | Copy the content of an object to a newly created object.\n"-y"_clone :: "x" -> IO "x"\n"-y"_clone from =\n"-"  do to <- "y"_malloc\n"-"     "y"_copy to from\n"-"     return to\n"-"\n"-"instance C "x" where\n"-"  malloc = "y"_malloc\n"-"  copy = "y"_copy\n"-"  clone = "y"_clone\n"-}--#{let get_set_name x,y =-y"_get_name :: "x" -> IO String\n"-y"_get_name i = peekCString =<< with_"y" i snd_seq_"y"_get_name\n"-"\n"-"foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_"y"_get_name\"\n"-"  snd_seq_"y"_get_name :: Ptr "x"_ -> IO CString\n"-"\n"-y"_set_name :: "x" -> String -> IO ()\n"-y"_set_name i c =\n"-"  withCAString c $ \\p -> with_"y" i (`snd_seq_"y"_set_name` p)\n"-"\n"-"foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_"y"_set_name\"\n"-"  snd_seq_"y"_set_name :: Ptr "x"_ -> CString -> IO ()\n"-}--#{let get_bool x,y,z =-y"_get_"z" :: "x" -> IO Bool\n"-y"_get_"z" i =\n"-"  (0 /=) `fmap` with_"y" i snd_seq_"y"_get_"z"\n"-"\n"-"foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_"y"_get_"z"\"\n"-"  snd_seq_"y"_get_"z" :: Ptr "x"_ -> IO CInt\n"-}--#{let get_set_bool x,y,z =-y"_get_"z" :: "x" -> IO Bool\n"-y"_get_"z" i =\n"-"  (0 /=) `fmap` with_"y" i snd_seq_"y"_get_"z"\n"-"\n"-"foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_"y"_get_"z"\"\n"-"  snd_seq_"y"_get_"z" :: Ptr "x"_ -> IO CInt\n"-"\n"-y"_set_"z" :: "x" -> Bool -> IO ()\n"-y"_set_"z" i c =\n"-"  let x = if c then 1 else 0\n"-"  in with_"y" i (`snd_seq_"y"_set_"z"` x)\n"-"\n"-"foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_"y"_set_"z"\"\n"-"  snd_seq_"y"_set_"z" :: Ptr "x"_ -> CInt -> IO ()\n"-}--#{let get_int x,y,z,t,mk =-y"_get_"z" :: "x" -> IO "t"\n"-y"_get_"z" i =\n"-"  "mk"\n"-"      `fmap` with_"y" i snd_seq_"y"_get_"z"\n"-"\n"-"foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_"y"_get_"z"\"\n"-"  snd_seq_"y"_get_"z" :: Ptr "x"_ -> IO CInt\n"-}--#{let set_int x,y,z,t,brk =-y"_set_"z" :: "x" -> "t" -> IO ()\n"-y"_set_"z" i c =\n"-"  with_"y" i (`snd_seq_"y"_set_"z"` "brk" c)\n"-"\n"-"foreign import ccall unsafe \"alsa/asoundlib.h snd_seq_"y"_set_"z"\"\n"-"  snd_seq_"y"_set_"z"  :: Ptr "x"_ -> CInt -> IO ()\n"-}------ Client.T Info ------------------------------------------------------------------#area "ClientInfo",  "client_info"---- read/write-#get_set_name "ClientInfo", "client_info"-#get_set_bool "ClientInfo", "client_info", "broadcast_filter"-#get_set_bool "ClientInfo", "client_info", "error_bounce"-#{get_int "ClientInfo", "client_info", "client",-          "Client.T", "Client.imp"}-#{set_int "ClientInfo", "client_info", "client",-          "Client.T", "Client.exp"}---- read only-#{get_int "ClientInfo", "client_info", "type",-          "Client.Type", "Client.impType"}-#{get_int "ClientInfo", "client_info", "num_ports",-          "Word", "fromIntegral"}-#{get_int "ClientInfo", "client_info", "event_lost",-          "Word", "fromIntegral"}----- Port Info --------------------------------------------------------------------#area "PortInfo",    "port_info"---- read/write-#get_set_name "PortInfo", "port_info"--#get_set_bool "PortInfo", "port_info", "port_specified"-#get_set_bool "PortInfo", "port_info", "timestamping"-#get_set_bool "PortInfo", "port_info", "timestamp_real"--#{get_int "PortInfo", "port_info", "port",-          "Port.T", "Port.imp"}-#{set_int "PortInfo", "port_info", "port",-          "Port.T", "Port.exp"}-#{get_int "PortInfo", "port_info", "client",-          "Client.T","Client.imp"}-#{set_int "PortInfo", "port_info", "client",-          "Client.T","Client.exp"}-#{get_int "PortInfo", "port_info", "capability",-          "Port.Cap","(EnumSet.Cons . fromIntegral)"}-#{set_int "PortInfo", "port_info", "capability",-          "Port.Cap","(fromIntegral . EnumSet.decons)"}--#{get_int "PortInfo", "port_info", "midi_channels",-          "Word","fromIntegral"}-#{set_int "PortInfo", "port_info", "midi_channels",-          "Word","fromIntegral"}-#{get_int "PortInfo", "port_info", "midi_voices",-          "Word","fromIntegral"}-#{set_int "PortInfo", "port_info", "midi_voices",-          "Word","fromIntegral"}-#{get_int "PortInfo", "port_info", "synth_voices",-          "Word","fromIntegral"}-#{set_int "PortInfo", "port_info", "synth_voices",-          "Word","fromIntegral"}--#{get_int "PortInfo", "port_info", "timestamp_queue",-          "Queue.T","Queue.imp"}-#{set_int "PortInfo", "port_info", "timestamp_queue",-          "Queue.T","Queue.exp"}---- read only-#{get_int "PortInfo", "port_info", "read_use",-          "Word","fromIntegral"}-#{get_int "PortInfo", "port_info", "write_use",-          "Word","fromIntegral"}---- Subscribe Port -----------------------------------------------------------------#area "PortSubscribe",	"port_subscribe"--#{get_int "PortSubscribe", "port_subscribe", "queue",-           "Queue.T","Queue.imp"}-#{set_int "PortSubscribe", "port_subscribe", "queue",-           "Queue.T","Queue.exp"}-#get_set_bool "PortSubscribe", "port_subscribe", "exclusive"-#get_set_bool "PortSubscribe", "port_subscribe", "time_update"-#get_set_bool "PortSubscribe", "port_subscribe", "time_real"---- Subscribe Query ----------------------------------------------------------------#area "QuerySubscribe", "query_subscribe"--#{get_int "QuerySubscribe", "query_subscribe", "client",-          "Client.T", "Client.imp"}-#{set_int "QuerySubscribe", "query_subscribe", "client",-          "Client.T", "Client.exp"}-#{get_int "QuerySubscribe", "query_subscribe", "port",-          "Port.T", "Port.imp"}-#{set_int "QuerySubscribe", "query_subscribe", "port",-          "Port.T", "Port.exp"}-#{get_int "QuerySubscribe", "query_subscribe", "type",-          "QuerySubscribe.Type", "QuerySubscribe.impType"}-#{set_int "QuerySubscribe", "query_subscribe", "type",-          "QuerySubscribe.Type", "QuerySubscribe.expType"}-#{get_int "QuerySubscribe", "query_subscribe", "index",-          "Word", "fromIntegral"}-#{set_int "QuerySubscribe", "query_subscribe", "index",-          "Word", "fromIntegral"}---- RO-#{get_int "QuerySubscribe", "query_subscribe", "num_subs",-          "Word", "fromIntegral"}-#{get_int "QuerySubscribe", "query_subscribe", "queue",-          "Queue.T", "Queue.imp"}-#get_bool "QuerySubscribe", "query_subscribe", "exclusive"-#get_bool "QuerySubscribe", "query_subscribe", "time_update"-#get_bool "QuerySubscribe", "query_subscribe", "time_real"---- Queue.T Info -------------------------------------------------------------------#area "QueueInfo",   "queue_info"-#get_set_name "QueueInfo", "queue_info"-#get_set_bool "QueueInfo", "queue_info", "locked"--#{get_int "QueueInfo", "queue_info", "owner",-          "Client.T", "Client.imp"}-#{set_int "QueueInfo", "queue_info", "owner",-          "Client.T", "Client.exp"}-#{get_int "QueueInfo", "queue_info", "flags",-          "Word", "fromIntegral"}-#{set_int "QueueInfo", "queue_info", "flags",-          "Word", "fromIntegral"}---- RO-#{get_int "QueueInfo", "queue_info", "queue",-           "Queue.T","Queue.imp"}---- Queue.T Status -----------------------------------------------------------------#area "QueueStatus", "queue_status"---- Queue.T Tempo ------------------------------------------------------------------#area "QueueTempo",  "queue_tempo"---- RO-#{get_int "QueueTempo", "queue_tempo", "queue",-           "Queue.T","Queue.imp"}---- RW-#{get_int "QueueTempo", "queue_tempo", "tempo", "Word", "fromIntegral"}-#{set_int "QueueTempo", "queue_tempo", "tempo", "Word", "fromIntegral"}--#{get_int "QueueTempo", "queue_tempo", "ppq", "Int", "fromIntegral"}-#{set_int "QueueTempo", "queue_tempo", "ppq", "Int", "fromIntegral"}--#{get_int "QueueTempo", "queue_tempo", "skew", "Word", "fromIntegral"}-#{set_int "QueueTempo", "queue_tempo", "skew", "Word", "fromIntegral"}--#{get_int "QueueTempo", "queue_tempo", "skew_base", "Word", "fromIntegral"}-#{set_int "QueueTempo", "queue_tempo", "skew_base", "Word", "fromIntegral"}---- Queue.T Timer ------------------------------------------------------------------#area "QueueTimer",  "queue_timer"----- RO-#{get_int "QueueTimer", "queue_timer", "queue",-           "Queue.T","Queue.imp"}---- RW--#{get_int "QueueTimer", "queue_timer", "type",-            "QueueTimer.Type", "QueueTimer.impType"}-#{set_int "QueueTimer", "queue_timer", "type",-            "QueueTimer.Type", "QueueTimer.expType"}--#{get_int "QueueTimer", "queue_timer", "resolution", "Word", "fromIntegral"}-#{set_int "QueueTimer", "queue_timer", "resolution", "Word", "fromIntegral"}-
src/Sound/ALSA/Sequencer/Client.hs view
@@ -14,7 +14,7 @@ --------------------------------------------------------------------------------  module Sound.ALSA.Sequencer.Client-  ( Client.T+  ( Client.T(Client.Cons)   , Client.unknown   , Client.system   , Client.subscribers@@ -26,7 +26,7 @@   , Client.Type(..)   ) where -import qualified Sound.ALSA.Sequencer.Client.Info as ClientInfo+import qualified Sound.ALSA.Sequencer.Client.InfoMonad as ClientInfo  import qualified Sound.ALSA.Sequencer.Marshal.Client as Client import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq@@ -41,12 +41,9 @@ -- | Get the client identifier for the sequencer. -- A convinience function. getId :: Seq.T mode -> IO Client.T-getId h = ClientInfo.getClient =<< ClientInfo.get h+getId h = ClientInfo.get h ClientInfo.getClient  -- | Set the name for the sequencer client. -- A convinience function. setName :: Seq.T mode -> String -> IO ()-setName h s =-  do i <- ClientInfo.get h-     ClientInfo.setName i s-     ClientInfo.set h i+setName h s = ClientInfo.modify h $ ClientInfo.setName s
src/Sound/ALSA/Sequencer/Client/Info.hs view
@@ -1,7 +1,7 @@ -------------------------------------------------------------------------------- -- | -- Module    : Sound.ALSA.Sequencer.Client--- Copyright : (c) Henning Thielemann, 2010+-- Copyright : (c) Henning Thielemann, 2010-2012 --             (c) Iavor S. Diatchki, 2007 -- License   : BSD3 --@@ -20,8 +20,9 @@   , getAny   , queryFirst   , queryNext+  , queryLoop_+  , queryLoop   , set-  , modify    , copy   , clone@@ -45,84 +46,23 @@   , filterCheck   ) where +import Sound.ALSA.Sequencer.Marshal.ClientInfo+ import qualified Sound.ALSA.Sequencer.Client.Info.EventFilter as Filter -import qualified Sound.ALSA.Sequencer.Marshal.Client as Client import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq-import qualified Sound.ALSA.Sequencer.Area as Area import qualified Sound.ALSA.Sequencer.Marshal.Event as Event-import qualified Sound.ALSA.Exception as Exc--import Foreign.C.Types(CInt, )-import Foreign.Ptr(Ptr, )-import Data.Word (Word, )--import Control.Monad (guard, )-------------------------------------------------------------------------------------type T  = Area.ClientInfo-type T_ = Area.ClientInfo_---- | Create a new information area filled with data about the sequencer client.-get :: Seq.T mode -> IO T-get (Seq.Cons h) =-  do info <- Area.client_info_malloc-     Exc.checkResult_ "get_client_info" =<< Area.with_client_info info (snd_seq_get_client_info h)-     return info--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_get_client_info"-  snd_seq_get_client_info :: Ptr Seq.Core -> Ptr T_ -> IO CInt----- | Create a new information area filled with data about an arbitrary client.-getAny :: Seq.T mode -> Client.T -> IO T-getAny (Seq.Cons h) c =-  do info <- Area.client_info_malloc-     Exc.checkResult_ "get_any_client_info" =<< Area.with_client_info info-                        (snd_seq_get_any_client_info h (Client.exp c))-     return info--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_get_any_client_info"-  snd_seq_get_any_client_info-    :: Ptr Seq.Core -> CInt -> Ptr T_ -> IO CInt-+import qualified Sound.ALSA.Sequencer.Query as Query   queryFirst :: Seq.T mode -> IO T-queryFirst h =-  do x <- Area.client_info_malloc-     Area.with_client_info x (`Area.snd_seq_client_info_set_client` (-1))-     _b <- queryNext h x-     -- XXX: check that we did get the first client (should be System)-     return x----- | Get information about the client with the next biggest identifier.-queryNext :: Seq.T mode -> T-                    -> IO Bool  -- ^ Was there a next client?-queryNext (Seq.Cons h) info =-  Exc.checkResultMaybe "query_next_client"-         (const True) (\x -> guard (x == -2) >> return False)-      =<< Area.with_client_info info (snd_seq_query_next_client h)--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_query_next_client"-  snd_seq_query_next_client :: Ptr Seq.Core -> Ptr T_ -> IO CInt----- | Set the information for the sequencer client based on the data--- in the given information area.-set :: Seq.T mode -> T -> IO ()-set (Seq.Cons h) info =-  Exc.checkResult_ "set_client_info" =<< Area.with_client_info info (snd_seq_set_client_info h)--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_set_client_info"-  snd_seq_set_client_info :: Ptr Seq.Core -> Ptr T_ -> IO CInt+queryFirst = Query.first +queryLoop_ :: Seq.T mode -> (T -> IO ()) -> IO ()+queryLoop_ h = Query.loop_ h (const $ return ()) -modify :: Seq.T mode -> (T -> IO T) -> IO ()-modify ss f = set ss =<< f =<< get ss+queryLoop :: Seq.T mode -> (T -> IO a) -> IO [a]+queryLoop h = Query.loop h (const $ return ())   filterClear :: T -> IO ()@@ -134,32 +74,3 @@ filterAdd   = Filter.add filterDel   = Filter.delete filterCheck = Filter.check---copy :: T -> T -> IO ()-clone :: T -> IO T-getClient :: T -> IO Client.T-getType :: T -> IO Client.Type-getName :: T -> IO String-getBroadcastFilter :: T -> IO Bool-getErrorBounce :: T -> IO Bool-getNumPorts :: T -> IO Word-getEventLost :: T -> IO Word-setClient :: T -> Client.T -> IO ()-setName :: T -> String -> IO ()-setBroadcastFilter :: T -> Bool -> IO ()-setErrorBounce :: T -> Bool -> IO ()--copy               = Area.client_info_copy-clone              = Area.client_info_clone-getClient          = Area.client_info_get_client-getType            = Area.client_info_get_type-getName            = Area.client_info_get_name-getBroadcastFilter = Area.client_info_get_broadcast_filter-getErrorBounce     = Area.client_info_get_error_bounce-getNumPorts        = Area.client_info_get_num_ports-getEventLost       = Area.client_info_get_event_lost-setClient          = Area.client_info_set_client-setName            = Area.client_info_set_name-setBroadcastFilter = Area.client_info_set_broadcast_filter-setErrorBounce     = Area.client_info_set_error_bounce
+ src/Sound/ALSA/Sequencer/Client/InfoMonad.hs view
@@ -0,0 +1,82 @@+module Sound.ALSA.Sequencer.Client.InfoMonad (+  T,++  run,+  get,+  modify,++  getClient,+  getType,+  getName,+  getBroadcastFilter,+  getErrorBounce,+  getNumPorts,+  getEventLost,++  setClient,+  setName,+  setBroadcastFilter,+  setErrorBounce,+  ) where++import qualified Sound.ALSA.Sequencer.Marshal.ClientInfo as ClientInfo+import qualified Sound.ALSA.Sequencer.Marshal.Client as Client+import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq++import qualified Control.Monad.Trans.Reader as MR+import Control.Applicative (Applicative, )++import Data.Word (Word, )+++newtype T a = Cons (MR.ReaderT ClientInfo.T IO a)+   deriving (Functor, Applicative, Monad)+++run :: T a -> ClientInfo.T -> IO a+run (Cons m) = MR.runReaderT m++get :: Seq.T mode -> T a -> IO a+get h m = run m =<< ClientInfo.get h++modify :: Seq.T mode -> T a -> IO a+modify h m = do+  i <- ClientInfo.get h+  a <- run m i+  ClientInfo.set h i+  return a+++liftGet :: (ClientInfo.T -> IO a) -> T a+liftGet f = Cons $ MR.ReaderT f++liftSet :: (ClientInfo.T -> b -> IO a) -> b -> T a+liftSet f x = Cons $ MR.ReaderT $ flip f x+++getClient :: T Client.T+getType :: T Client.Type+getName :: T String+getBroadcastFilter :: T Bool+getErrorBounce :: T Bool+getNumPorts :: T Word+getEventLost :: T Word++getClient          = liftGet ClientInfo.getClient+getType            = liftGet ClientInfo.getType+getName            = liftGet ClientInfo.getName+getBroadcastFilter = liftGet ClientInfo.getBroadcastFilter+getErrorBounce     = liftGet ClientInfo.getErrorBounce+getNumPorts        = liftGet ClientInfo.getNumPorts+getEventLost       = liftGet ClientInfo.getEventLost+++setClient :: Client.T -> T ()+setName :: String -> T ()+setBroadcastFilter :: Bool -> T ()+setErrorBounce :: Bool -> T ()++setClient          = liftSet ClientInfo.setClient+setName            = liftSet ClientInfo.setName+setBroadcastFilter = liftSet ClientInfo.setBroadcastFilter+setErrorBounce     = liftSet ClientInfo.setErrorBounce
+ src/Sound/ALSA/Sequencer/Concurrent.hs view
@@ -0,0 +1,107 @@+module Sound.ALSA.Sequencer.Concurrent+  ( threadWaitInput+  , threadWaitOutput+  , threadWaitDuplex++  , input+  , output+  , drainOutput+  ) where++import qualified Sound.ALSA.Sequencer.Poll as AlsaPoll+import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified Sound.ALSA.Sequencer.Event as Event+import Sound.ALSA.Exception (code, )++import Control.Concurrent (yield, threadWaitRead, threadWaitWrite, forkIO, killThread, )+import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar, )+import Control.Exception (catchJust, catch, )+import Control.Monad (guard, when, )+import Data.Function (fix, )+import Data.Word (Word, )+import Foreign.C.Error (eINTR, )+import System.IO.Error (isFullError, )+import System.Posix.Types (Fd, )+import qualified System.Posix.Poll as Poll+import qualified Data.EnumSet as EnumSet++import Prelude hiding (catch, )+++data WaitFd+  = WaitRead Fd+  | WaitWrite Fd++pollWaits :: Poll.Fd -> [WaitFd]+pollWaits (Poll.Fd f e _) =+  (if EnumSet.subset Poll.inp e then [WaitRead  f] else []) +++  (if EnumSet.subset Poll.out e then [WaitWrite f] else [])++-- | Wait for any of the given events, like poll, and return the one that is ready+threadWaitPolls :: [WaitFd] -> IO WaitFd+threadWaitPolls [] = yield >> return undefined+threadWaitPolls [p@(WaitRead f)] = threadWaitRead f >> return p+threadWaitPolls [p@(WaitWrite f)] = threadWaitWrite f >> return p+threadWaitPolls l = do+  w <- newEmptyMVar+  let poll1 p = catch (threadWaitPolls [p] >>= putMVar w . Right) (putMVar w . Left)+  t <- mapM (forkIO . poll1) l+  r <- takeMVar w+  mapM_ killThread t+  either ioError return r++threadWaitEvents :: Poll.Events -> Seq.T mode -> IO ()+threadWaitEvents e sh =+  AlsaPoll.descriptors sh e >>=+  threadWaitPolls . concatMap pollWaits >>+  return ()++-- | Wait for new input to be available from the sequencer (even if there is already input in the buffer)+threadWaitInput :: Seq.AllowInput mode => Seq.T mode -> IO ()+threadWaitInput = threadWaitEvents Poll.inp++-- | Wait until new output may be drained from the buffer to the sequencer (even if the output buffer is already empty)+threadWaitOutput :: Seq.AllowOutput mode => Seq.T mode -> IO ()+threadWaitOutput = threadWaitEvents Poll.out++-- | Wait until new input is available or new output may be drained+threadWaitDuplex :: (Seq.AllowInput mode, Seq.AllowOutput mode) => Seq.T mode -> IO ()+threadWaitDuplex = threadWaitEvents (Poll.inp EnumSet..|. Poll.out)++catchFull :: IO a -> IO a -> IO a+catchFull f e = catchJust (guard . isFullError) f (\() -> e)++catchIntr :: IO a -> IO a+catchIntr f = catchJust (guard . (eINTR ==) . code) f (\() -> catchIntr f)++-- | A thread-compatible version of @Sound.ALSA.Sequencer.Event.input@.+-- This call is always blocking (unless there are already event in the input+-- buffer) but will not block other threads.  The sequencer, however, must be+-- set non-blocking or this will not work as expected.+input :: Seq.AllowInput mode => Seq.T mode -> IO Event.T+input sh = do+  n <- catchIntr $ Event.inputPending sh True+  when (n == 0) $ threadWaitInput sh+  fix $ catchFull (Event.input sh) . (threadWaitInput sh >>)++-- | A thread-compatible version of @Sound.ALSA.Sequencer.Event.output@.+-- This call is always blocking (unless there is space in the output+-- buffer) but will not block other threads.  The sequencer, however, must be+-- set non-blocking or this will not work as expected.+output :: Seq.AllowOutput mode => Seq.T mode -> Event.T -> IO Word+output sh ev =+  Event.outputBuffer sh ev `catchFull` do+    threadWaitOutput sh+    _ <- Event.drainOutput sh `catchFull` return (-1)+    output sh ev++-- | A thread-compatible version of @Sound.ALSA.Sequencer.Event.drainBuffer@.+-- This call is always blocking but will not block other threads.  The+-- sequencer, however, must be set non-blocking or this will not work as+-- expected.+drainOutput :: Seq.AllowOutput mode => Seq.T mode -> IO ()+drainOutput sh = do+  n <- Event.drainOutput sh `catchFull` return (-1)+  when (n /= 0) $ do+    threadWaitOutput sh+    drainOutput sh
+ src/Sound/ALSA/Sequencer/Connect.hs view
@@ -0,0 +1,86 @@+module Sound.ALSA.Sequencer.Connect (+   Connect.T(Connect.Cons, Connect.source, Connect.dest),+   reverse,+   toSubscribers, fromSubscribers,++   createFrom, deleteFrom, withFrom,+   createTo,   deleteTo,   withTo,+   ) where++import qualified Sound.ALSA.Sequencer.Marshal.Connect as Connect+import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr+import qualified Sound.ALSA.Sequencer.Marshal.Port as Port+import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified Sound.ALSA.Sequencer.Client as Client+import qualified Sound.ALSA.Exception as Exc++import qualified Foreign.C.Types as C+import Foreign.Ptr (Ptr, )++import Control.Exception (bracket, )++import Prelude hiding (reverse, )+++reverse :: Connect.T -> Connect.T+reverse (Connect.Cons src dst) = Connect.Cons dst src++toSubscribers :: Addr.T -> Connect.T+toSubscribers src = Connect.Cons src Addr.subscribers++fromSubscribers :: Addr.T -> Connect.T+fromSubscribers dst = Connect.Cons Addr.subscribers dst+++-- | Simple subscription (w\/o exclusive & time conversion).+createFrom :: Seq.AllowInput mode => Seq.T mode -> Port.T -> Addr.T -> IO Connect.T+createFrom s@(Seq.Cons h) me a =+  do Exc.checkResult_ "connect_from" =<<+        uncurry (snd_seq_connect_from h (Port.exp me)) (Addr.exp a)+     mec <- Client.getId s+     return $ Connect.Cons a (Addr.Cons mec me)++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_connect_from"+  snd_seq_connect_from :: Ptr Seq.Core -> C.CInt -> C.CInt -> C.CInt -> IO C.CInt+++-- | Simple subscription (w\/o exclusive & time conversion).+createTo :: Seq.AllowOutput mode => Seq.T mode -> Port.T -> Addr.T -> IO Connect.T+createTo s@(Seq.Cons h) me a =+  do Exc.checkResult_ "connect_to" =<<+        uncurry (snd_seq_connect_to h (Port.exp me)) (Addr.exp a)+     mec <- Client.getId s+     return $ Connect.Cons (Addr.Cons mec me) a++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_connect_to"+  snd_seq_connect_to :: Ptr Seq.Core -> C.CInt -> C.CInt -> C.CInt -> IO C.CInt+++-- | Simple disconnection.+deleteFrom :: Seq.AllowInput mode => Seq.T mode -> Port.T -> Addr.T -> IO ()+deleteFrom (Seq.Cons h) me a =+  Exc.checkResult_ "disconnect_from" =<< snd_seq_disconnect_from h (Port.exp me) c p+  where (c,p) = Addr.exp a++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_disconnect_from"+  snd_seq_disconnect_from :: Ptr Seq.Core -> C.CInt -> C.CInt -> C.CInt -> IO C.CInt++-- | Simple disconnection.+deleteTo :: Seq.AllowOutput mode => Seq.T mode -> Port.T -> Addr.T -> IO ()+deleteTo (Seq.Cons h) me a =+  Exc.checkResult_ "disconnect_to" =<< snd_seq_disconnect_to h (Port.exp me) c p+  where (c,p) = Addr.exp a++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_disconnect_to"+  snd_seq_disconnect_to :: Ptr Seq.Core -> C.CInt -> C.CInt -> C.CInt -> IO C.CInt+++-- | Temporary subscription.+withFrom :: Seq.AllowInput mode => Seq.T mode -> Port.T -> Addr.T -> (Connect.T -> IO a) -> IO a+withFrom h me a =+  bracket (createFrom h me a) (const $ deleteFrom h me a)++-- | Temporary subscription.+withTo :: Seq.AllowOutput mode => Seq.T mode -> Port.T -> Addr.T -> (Connect.T -> IO a) -> IO a+withTo h me a =+  bracket (createTo h me a) (const $ deleteTo h me a)
src/Sound/ALSA/Sequencer/Event.hs view
@@ -1,11 +1,11 @@ -------------------------------------------------------------------------------- -- | -- Module    : Sound.ALSA.Sequencer.Event--- Copyright : (c) Henning Thielemann, 2010+-- Copyright : (c) Henning Thielemann, 2011 --             (c) Iavor S. Diatchki, 2007 -- License   : BSD3 ----- Maintainer: Iavor S. Diatchki+-- Maintainer: Henning Thielemann -- Stability : provisional -- -- This module contains functions for working with events.@@ -13,63 +13,125 @@ -- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_event.html> -------------------------------------------------------------------------------- -module Sound.ALSA.Sequencer.Event-  ( syncOutputQueue-  , input-  , inputPending-  , output-  , outputBuffer-  , outputDirect-  , outputPending-  , extractOutput-  , removeOutput-  , drainOutput-  , dropOutput-  , dropOutputBuffer-  , dropInput-  , dropInputBuffer+module Sound.ALSA.Sequencer.Event (+  -- * Output -  , TimeStamp(..)-  , InstrCluster-  , Instr(..)-  , Sample(..)-  , Cluster(..)-  , Volume(..), volumeSame+  -- $trouble -  , Event.T(..), simple-  , Event.Data(..)-  , NoteEv(..), Note(..), simpleNote-  , CtrlEv(..), Ctrl(..)-  , CustomEv(..), Custom(..)-  , QueueEv(..)-  , AddrEv(..)-  , ConnEv(..), Connect-  , EmptyEv(..)+  output,+  outputBuffer,+  outputDirect,+  outputPending,+  extractOutput,+  removeOutput,+  drainOutput,+  dropOutput,+  dropOutputBuffer,+  syncOutputQueue,++  -- * Input++  input,+  inputPending,+  dropInput,+  dropInputBuffer,++  -- * Data types++  Event.T(..), simple, forSourcePort, forConnection,+  Event.Data(..),+  Event.Type,+  NoteEv(..), Note(..), simpleNote,+  CtrlEv(..), Ctrl(..),+  CustomEv(..), Custom(..), customZero,+  ExtEv(..),+  QueueEv(..),+  AddrEv(..),+  ConnEv(..),+  EmptyEv(..),++  Tag(..),+  Tempo(..),++  Parameter(..),+  Value(..),+  Channel(..),+  Pitch(..),+  Velocity(..), normalVelocity, offVelocity,+  Duration(..),++{- available in alsa-1.0.14, but gone in 1.0.22+  Instr(..),+  Sample(..),+  Cluster(..),+  VolumeControl(..),++  InstrCluster(..),+  StandardId(..),+  Bank(..),+  Program(..),+  Volume(..), volumeSame,+  Balance(..),+-}   ) where +import Sound.ALSA.Sequencer.Marshal.Event as Event  import qualified Sound.ALSA.Sequencer.Address as Addr+import qualified Sound.ALSA.Sequencer.Port as Port+import qualified Sound.ALSA.Sequencer.Client as Client+import qualified Sound.ALSA.Sequencer.Connect as Connect import qualified Sound.ALSA.Sequencer.Queue as Queue import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq-import Sound.ALSA.Sequencer.Marshal.Event as Event+import qualified Sound.ALSA.Sequencer.Marshal.Time as Time import qualified Sound.ALSA.Exception as Exc -import Foreign.C.Types (CInt, )+import qualified Foreign.C.Types as C import Foreign.Ptr (Ptr, nullPtr, ) import Foreign.Marshal.Alloc (alloca, ) import Foreign.Storable (peek, ) -import Data.Word (Word, Word8, )-import Data.Int (Int16, )+import Data.Word (Word, )  +{- $trouble+If you send an event but you do not hear something,+then check the following conditions:++* Check whether your event was actually delivered.+  E.g. use the event monitor @aseqdump@ in order to see sent messages.++* If the message was not delivered,+  maybe you quit the program too early+  and thus destroyed pending messages.+  Use 'syncOutputQueue' at the end of the program+  in order to wait for all messages to be sent.++* Make sure the sequencer supports output+  and the target port supports input.++* Make sure to setup a connection to the receiver.++* Make sure to have called 'drainOutput' after 'output'.++* If you use a timestamp in an event,+  make sure you also declare a queue (and create one before).++* Make sure you started the queue you used for sending.++* Be aware of that 'Event.QueueStart' clears the queue before running the queue.+  That is, events sent before 'Event.QueueStart' are deleted.+  If you want to keep these events, then use 'Event.QueueContinue' instead.+-}++ -- | Wait until all events of the client are processed. syncOutputQueue :: Seq.T mode -> IO () syncOutputQueue (Seq.Cons h) =   Exc.checkResult_ "syncOutputQueue" =<< snd_seq_sync_output_queue h  foreign import ccall safe "alsa/asoundlib.h snd_seq_sync_output_queue"-  snd_seq_sync_output_queue :: Ptr Seq.Core -> IO CInt+  snd_seq_sync_output_queue :: Ptr Seq.Core -> IO C.CInt   -- | Get an event from the input buffer.@@ -88,10 +150,10 @@      peek =<< peek p  foreign import ccall safe "alsa/asoundlib.h snd_seq_event_input"-  snd_seq_event_input :: Ptr Seq.Core -> Ptr (Ptr Event.T) -> IO CInt+  snd_seq_event_input :: Ptr Seq.Core -> Ptr (Ptr Event.T) -> IO C.CInt  -checkResult :: String -> CInt -> IO Word+checkResult :: String -> C.CInt -> IO Word checkResult loc n =    fmap fromIntegral $ Exc.checkResult loc n @@ -110,7 +172,7 @@   checkResult "inputPending" =<< snd_seq_event_input_pending h (if fill then 1 else 0)  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_event_input_pending"-  snd_seq_event_input_pending :: Ptr Seq.Core -> Int -> IO CInt+  snd_seq_event_input_pending :: Ptr Seq.Core -> Int -> IO C.CInt   @@ -118,17 +180,17 @@ -- Throws exceptions. -- See also: 'outputDirect', 'outputBuffer', --           'outputPending', 'drainOutput', 'dropOutput',---           'extractOutput', 'removeEvents'+--           'extractOutput', 'removeOutput'  output :: Seq.AllowOutput mode              => Seq.T mode              -> Event.T              -> IO Word   -- ^ the number of remaining events (or bytes?) output (Seq.Cons h) e =-  Event.allocaEv e $ \p -> checkResult "output" =<< snd_seq_event_output h p+  Event.with e $ \p -> checkResult "output" =<< snd_seq_event_output h p  foreign import ccall safe "alsa/asoundlib.h snd_seq_event_output"-  snd_seq_event_output :: Ptr Seq.Core -> Ptr Event.T -> IO CInt+  snd_seq_event_output :: Ptr Seq.Core -> Ptr Event.T -> IO C.CInt   @@ -142,10 +204,10 @@                     -> IO Word  -- ^ the byte size of remaining events  outputBuffer (Seq.Cons h) e =-  Event.allocaEv e $ \p -> checkResult "outputBuffer" =<< snd_seq_event_output_buffer h p+  Event.with e $ \p -> checkResult "outputBuffer" =<< snd_seq_event_output_buffer h p  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_event_output_buffer"-  snd_seq_event_output_buffer :: Ptr Seq.Core -> Ptr Event.T -> IO CInt+  snd_seq_event_output_buffer :: Ptr Seq.Core -> Ptr Event.T -> IO C.CInt   -- | Output an event directly to the sequencer, NOT through the output buffer.@@ -159,10 +221,10 @@   -> IO Word  -- ^ number of bytes sent to the sequencer  outputDirect (Seq.Cons h) e =-  Event.allocaEv e $ \p -> checkResult "outputDirect" =<< snd_seq_event_output_direct h p+  Event.with e $ \p -> checkResult "outputDirect" =<< snd_seq_event_output_direct h p  foreign import ccall safe "alsa/asoundlib.h snd_seq_event_output_direct"-  snd_seq_event_output_direct :: Ptr Seq.Core -> Ptr Event.T -> IO CInt+  snd_seq_event_output_direct :: Ptr Seq.Core -> Ptr Event.T -> IO C.CInt   -- | Return the size (in bytes) of pending events on output buffer.@@ -175,11 +237,11 @@   fromIntegral `fmap` snd_seq_event_output_pending h  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_event_output_pending"-  snd_seq_event_output_pending :: Ptr Seq.Core -> IO CInt+  snd_seq_event_output_pending :: Ptr Seq.Core -> IO C.CInt   -- | Extract the first event in output buffer.--- Throws an exception on error.+-- Throws @(Errno 2)@ exception if output buffer is empty. -- See also 'output'. extractOutput   :: Seq.AllowOutput mode@@ -197,7 +259,7 @@ removeOutput (Seq.Cons h) = Exc.checkResult_ "removeOutput" =<< snd_seq_extract_output h nullPtr  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_extract_output"-  snd_seq_extract_output :: Ptr Seq.Core -> Ptr (Ptr Event.T) -> IO CInt+  snd_seq_extract_output :: Ptr Seq.Core -> Ptr (Ptr Event.T) -> IO C.CInt   -- | Drain output buffer to sequencer.@@ -217,19 +279,19 @@ drainOutput (Seq.Cons h) = checkResult "drainOutput" =<< snd_seq_drain_output h  foreign import ccall safe "alsa/asoundlib.h snd_seq_drain_output"-  snd_seq_drain_output :: Ptr Seq.Core -> IO CInt+  snd_seq_drain_output :: Ptr Seq.Core -> IO C.CInt   -- | Remove events from both the user-space output buffer, -- and the kernel-space sequencer queue.--- See also: 'drainOutput', 'dropOutputBuffer', 'removeEvents'.+-- See also: 'drainOutput', 'dropOutputBuffer', 'removeOutput'. dropOutput   :: Seq.AllowOutput mode   => Seq.T mode -> IO () dropOutput (Seq.Cons h) = Exc.checkResult_ "dropOutput" =<< snd_seq_drop_output h  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_drop_output"-  snd_seq_drop_output :: Ptr Seq.Core -> IO CInt+  snd_seq_drop_output :: Ptr Seq.Core -> IO C.CInt   -- | Remove events from the user-space output buffer.@@ -240,19 +302,19 @@ dropOutputBuffer (Seq.Cons h) = Exc.checkResult_ "dropOutputBuffer" =<< snd_seq_drop_output_buffer h  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_drop_output_buffer"-  snd_seq_drop_output_buffer :: Ptr Seq.Core -> IO CInt+  snd_seq_drop_output_buffer :: Ptr Seq.Core -> IO C.CInt   -- | Remove events from both the user-space input buffer, -- and the kernel-space sequencer queue.--- See also: 'dropInputBuffer', 'removeEvents'.+-- See also: 'dropInputBuffer', 'removeOutput'. dropInput   :: Seq.AllowInput mode   => Seq.T mode -> IO () dropInput (Seq.Cons h) = Exc.checkResult_ "dropInput" =<< snd_seq_drop_input h  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_drop_input"-  snd_seq_drop_input :: Ptr Seq.Core -> IO CInt+  snd_seq_drop_input :: Ptr Seq.Core -> IO C.CInt   -- | Remove events from the user-space input buffer.@@ -263,43 +325,58 @@ dropInputBuffer (Seq.Cons h) = Exc.checkResult_ "dropInputBuffer" =<< snd_seq_drop_input_buffer h  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_drop_input_buffer"-  snd_seq_drop_input_buffer :: Ptr Seq.Core -> IO CInt+  snd_seq_drop_input_buffer :: Ptr Seq.Core -> IO C.CInt    -- | Make a note whose unspecified fields contain 0.-simpleNote-  :: Word8  -- ^ Channel.-  -> Word8  -- ^ Note.-  -> Word8  -- ^ Velocity.-  -> Event.Note+simpleNote :: Channel -> Pitch -> Velocity -> Event.Note simpleNote c n v =    Event.Note {       Event.noteChannel = c,       Event.noteNote = n,       Event.noteVelocity = v,-      Event.noteOffVelocity = 0,-      Event.noteDuration = 0+      Event.noteOffVelocity = offVelocity,+      Event.noteDuration = Duration 0    } +normalVelocity, offVelocity :: Velocity+normalVelocity = Velocity 64+offVelocity = Velocity 0+ {- | Construct an ALSA sequencer event from very few information. Most fields are initialized with sensible defaults. You may use this as a start and alter its fields for your special needs. -> (Event.simple myAddr (Event.simpleNote 0 60 64)) {Event.dest = destAddr}+> (Event.simple myAddr (Event.simpleNote (Event.Channel 0) (Event.Pitch 60) Event.normalVelocity)) {Event.dest = destAddr} -} simple :: Addr.T -> Event.Data -> Event.T simple src bdy = Cons   { Event.highPriority = False-  , Event.tag = 0+  , Event.tag = Tag 0   , Event.queue = Queue.direct-  , Event.timestamp = Event.TickTime 0+  , Event.time = Time.consAbs $ Time.Tick 0   , Event.source = src   , Event.dest = Addr.subscribers   , Event.body = bdy   } +forSourcePort :: Port.T -> Event.Data -> Event.T+forSourcePort port =+   simple (Addr.Cons Client.unknown port)++forConnection :: Connect.T -> Event.Data -> Event.T+forConnection (Connect.Cons src dst) bdy =+   (simple src bdy) { Event.dest = dst }+++customZero :: Event.Custom+customZero = Event.Custom 0 0 0+++{- available in alsa-1.0.14, but gone in 1.0.22 -- | Used for volume control: means do not change the volume.-volumeSame :: Int16-volumeSame = -1+volumeSame :: Volume+volumeSame = Volume (-1)+-}
src/Sound/ALSA/Sequencer/Event/Accessor.hs view
@@ -2,29 +2,31 @@    highPriority,    tag,    queue,-   timestamp,+   time,+   timeStamp,    source,    dest,    connect,    body,    ) where +import qualified Sound.ALSA.Sequencer.Connect as Connect import qualified Sound.ALSA.Sequencer.Address as Addr import qualified Sound.ALSA.Sequencer.Queue as Queue+import qualified Sound.ALSA.Sequencer.Marshal.Time as Time import qualified Sound.ALSA.Sequencer.Marshal.Event as Event  import qualified Data.Accessor.Basic as Acc -import Data.Word (Word8, ) - highPriority :: Acc.T Event.T Bool-tag :: Acc.T Event.T Word8+tag :: Acc.T Event.T Event.Tag queue :: Acc.T Event.T Queue.T-timestamp :: Acc.T Event.T Event.TimeStamp+time :: Acc.T Event.T Time.T+timeStamp :: Acc.T Event.T Time.Stamp source :: Acc.T Event.T Addr.T dest :: Acc.T Event.T Addr.T-connect :: Acc.T Event.T Event.Connect+connect :: Acc.T Event.T Connect.T body :: Acc.T Event.T Event.Data  highPriority =@@ -33,15 +35,18 @@    Acc.fromSetGet (\x ev -> ev{Event.tag = x}) Event.tag queue =    Acc.fromSetGet (\x ev -> ev{Event.queue = x}) Event.queue-timestamp =-   Acc.fromSetGet (\x ev -> ev{Event.timestamp = x}) Event.timestamp+time =+   Acc.fromSetGet (\x ev -> ev{Event.time = x}) Event.time+timeStamp = time Acc..> Time.stampAcc source =    Acc.fromSetGet (\x ev -> ev{Event.source = x}) Event.source dest =    Acc.fromSetGet (\x ev -> ev{Event.dest = x}) Event.dest connect =-   Acc.fromSetGet-      (\(Event.Connect src dst) ev -> ev{Event.source = src, Event.dest = dst})-      (\ev -> Event.Connect (Event.source ev) (Event.dest ev))+   Acc.fromWrapper+      (\(Connect.Cons src dst) -> (src, dst))+      (uncurry Connect.Cons)+   Acc.<.+   Acc.merge source dest body =    Acc.fromSetGet (\x ev -> ev{Event.body = x}) Event.body
+ src/Sound/ALSA/Sequencer/Event/Remove.hsc view
@@ -0,0 +1,94 @@+module Sound.ALSA.Sequencer.Event.Remove (+  T,+  malloc,+  run,++  Condition,+  getCondition,+  setCondition,++  condInput,+  condOutput,+  condDest,+  condDestChannel,+  condTimeBefore,+  condTimeAfter,+  condTimeTick,+  condEventType,+  condIgnoreOff,+  condTagMatch,++  getQueue,+  getChannel,+  getEventType,+  getTag,+  getDest,+  getRealTime,+  getTickTime,++  setQueue,+  setChannel,+  setEventType,+  setTag,+  setDest,+  setRealTime,+  setTickTime,+  ) where++#include <alsa/asoundlib.h>+#include <Sound/ALSA/Sequencer/Area.h>++import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr+import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue+import qualified Sound.ALSA.Sequencer.Marshal.Event as Event+import qualified Sound.ALSA.Sequencer.Marshal.RealTime as RealTime+import qualified Sound.ALSA.Sequencer.Marshal.Time as Time+import qualified Sound.ALSA.Sequencer.Area as Area+import qualified Sound.ALSA.Exception as Exc++import qualified Data.EnumSet as EnumSet+import qualified Foreign.C.Types as C+import Foreign.Ptr (Ptr, )+++#area "remove_events"++-- | Remove events according to the given conditions+run :: Seq.T mode -> T -> IO ()+run (Seq.Cons h) info =+  Exc.checkResult_ "EventRemove.run" =<< with info (run_ h)++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_remove_events"+  run_ :: Ptr Seq.Core -> Ptr T_ -> IO C.CInt+++#{get_set_int_gen "condition", "Condition", "Condition", "EnumSet.Cons", "EnumSet.decons", "C.CUInt"}++#{get_set_int "queue", "Queue", "Queue.T", "Queue.imp", "Queue.exp"}+#{get_set_int "channel", "Channel", "Event.Channel", "(Event.Channel . fromIntegral)", "(fromIntegral . Event.unChannel)"}+#{get_set_int "event_type", "EventType", "Event.EType", "(Event.EType . fromIntegral)", "(fromIntegral . Event.unEType)"}+#{get_set_int "tag", "Tag", "Event.Tag", "(Event.Tag . fromIntegral)", "(fromIntegral . Event.unTag)"}+#{get_set_ptr "dest", "Dest", "Addr.T"}+#{get_set_ptr "time", "RealTime", "RealTime.T"}+#{get_set_ptr "time", "TickTime", "Time.Tick"}+++newtype ConditionFlag = ConditionFlag Int+   deriving (Eq, Ord, Enum)++type Condition = EnumSet.T C.CUInt ConditionFlag+++#{enum Condition, EnumSet.Cons+ , condInput       = SND_SEQ_REMOVE_INPUT        /* Flush input queues */+ , condOutput      = SND_SEQ_REMOVE_OUTPUT       /* Flush output queues */+ , condDest        = SND_SEQ_REMOVE_DEST         /* Restrict by destination q:client:port */+ , condDestChannel = SND_SEQ_REMOVE_DEST_CHANNEL /* Restrict by channel */+ , condTimeBefore  = SND_SEQ_REMOVE_TIME_BEFORE  /* Restrict to before time */+ , condTimeAfter   = SND_SEQ_REMOVE_TIME_AFTER   /* Restrict to time or after */+ , condTimeTick    = SND_SEQ_REMOVE_TIME_TICK    /* Time is in ticks */+ , condEventType   = SND_SEQ_REMOVE_EVENT_TYPE   /* Restrict to event type */+ , condIgnoreOff   = SND_SEQ_REMOVE_IGNORE_OFF   /* Do not flush off events */+ , condTagMatch    = SND_SEQ_REMOVE_TAG_MATCH    /* Restrict to events with given tag */+ }
+ src/Sound/ALSA/Sequencer/Event/RemoveMonad.hs view
@@ -0,0 +1,241 @@+{- |+This module allows to cancel events according to some criteria.+In all cases other than 'setInput' and 'setOutput'+the criteria are combined by logical AND.+For every criterion we provide three kinds of accessors:++* @set@: enable a criterion++* @put@: enable or disable a criterion++* @get@: query, whether the criterion is enabled or disabled.++Currently only the @set@ functions are really usable.+The @put@ and @get@ functions would become useful+for manipulating the remove criterion record, that ALSA maintains.+-}+module Sound.ALSA.Sequencer.Event.RemoveMonad (+  T,+  run,+  -- no need to export this, since Event.Remove is not exported as well+  -- apply,++  setInput,     putInput,     getInput,+  setOutput,    putOutput,    getOutput,+  setChannel,   putChannel,   getChannel,+  setEventType, putEventType,+  setTag,       putTag,       getTag,+  setDest,      putDest,      getDest,+  setTime,      putTime,      getTime,+  setIgnoreOff, putIgnoreOff, getIgnoreOff,+  ) where++import qualified Sound.ALSA.Sequencer.Event.Remove as Remove++import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr+import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue+import qualified Sound.ALSA.Sequencer.Marshal.Event as Event+import qualified Sound.ALSA.Sequencer.Marshal.Time as Time++import qualified Control.Monad.Trans.Reader as MR+import qualified Control.Monad.Trans.State as MS+import qualified Control.Monad.Trans.Class as MT+import Control.Applicative (Applicative, )++import qualified Data.EnumSet as EnumSet+import Data.EnumSet ((.-.), (.|.), )++import Control.Monad (liftM2, )+import Data.Monoid (mempty, mappend, )+++newtype T a = Cons (MR.ReaderT Remove.T (MS.StateT Remove.Condition IO) a)+   deriving (Functor, Applicative, Monad)+++unpack :: T a -> Remove.T -> Remove.Condition -> IO (a, Remove.Condition)+unpack (Cons m) r = MS.runStateT (MR.runReaderT m r)++-- | apply the changes in the Remove monad to the Remove record+_apply :: T a -> Remove.T -> IO a+_apply m r = do+  c0 <- Remove.getCondition r+  (a,c1) <- unpack m r c0+  Remove.setCondition r c1+  return a++-- | Remove events according to the given conditions+run :: Seq.T mode -> T a -> IO a+run h m = do+  r <- Remove.malloc+  (a,c) <- unpack m r EnumSet.empty+  Remove.setCondition r c+  Remove.run h r+  return a++++liftGet :: (Remove.T -> IO a) -> T a+liftGet f = Cons $ MR.ReaderT $ MT.lift . f++liftGetCond :: (Remove.T -> IO a) -> Remove.Condition -> T (Maybe a)+liftGetCond f cond = do+   b <- getCond cond+   if b+     then fmap Just $ liftGet f+     else return Nothing++liftSet :: (Remove.T -> b -> IO a) -> b -> T a+liftSet f x = Cons $ MR.ReaderT $ MT.lift . flip f x++liftSetCond :: (Remove.T -> a -> IO b) -> Remove.Condition -> a -> T b+liftSetCond f cond x = do+   modifyCond $ mappend cond+   liftSet f x++liftPutCond :: (Remove.T -> a -> IO ()) -> Remove.Condition -> Maybe a -> T ()+liftPutCond f cond mx =+   case mx of+      Nothing -> modifyCond $ (.-. cond)+      Just x -> liftSetCond f cond x++getCond :: Remove.Condition -> T Bool+getCond cond =+   Cons $ MT.lift $ MS.gets $ EnumSet.subset cond++setCond :: Remove.Condition -> T ()+setCond cond =+   modifyCond $ mappend cond++putCond :: Remove.Condition -> Bool -> T ()+putCond cond b =+   modifyCond $ (if b then (.|.) else flip (.-.)) cond++modifyCond :: (Remove.Condition -> Remove.Condition) -> T ()+modifyCond f =+   Cons $ MT.lift $ MS.modify f++{- |+All events in the local input buffer are removed.+The conditions are not checked for these events.+This is equivalent to 'Event.dropInputBuffer'.+-}+setInput :: T ()+putInput :: Bool -> T ()+getInput :: T Bool++{- |+Matching events in the local output buffer are removed, too.+Matching events in the kernel buffer are removed in any case.+If there are no further conditions,+then this is equivalent to 'Event.dropOutputBuffer'.+-}+setOutput :: T ()+putOutput :: Bool -> T ()+getOutput :: T Bool++setChannel :: Event.Channel -> T ()+putChannel :: Maybe Event.Channel -> T ()+getChannel :: T (Maybe Event.Channel)++_setEventType :: Event.EType -> T ()+_getEventType :: T Event.EType+setEventType :: Event.Type e => e -> T ()+putEventType :: Event.Type e => Maybe e -> T ()++setTag :: Event.Tag -> T ()+putTag :: Maybe Event.Tag -> T ()+getTag :: T (Maybe Event.Tag)++{- |+ALSA maintainers say, that destination address and queue are checked together,+at least in the kernel buffer.+However up to ALSA-1.0.22 the check for the queue is missing in libasound+for the local buffer.+-}+setDest :: (Addr.T, Queue.T) -> T ()+putDest :: Maybe (Addr.T, Queue.T) -> T ()+getDest :: T (Maybe (Addr.T, Queue.T))++{- |+NoteOff events are kept in any case.+-}+setIgnoreOff :: T ()+putIgnoreOff :: Bool -> T ()+getIgnoreOff :: T Bool+++getInput = getCond Remove.condInput+setInput = setCond Remove.condInput+putInput = putCond Remove.condInput++getOutput = getCond Remove.condOutput+setOutput = setCond Remove.condOutput+putOutput = putCond Remove.condOutput++getChannel = liftGetCond Remove.getChannel Remove.condDestChannel+setChannel = liftSetCond Remove.setChannel Remove.condDestChannel+putChannel = liftPutCond Remove.setChannel Remove.condDestChannel++_getEventType = liftGet Remove.getEventType+_setEventType = liftSetCond Remove.setEventType Remove.condEventType+setEventType =+   liftSetCond Remove.setEventType Remove.condEventType . Event.expEv+putEventType =+   liftPutCond Remove.setEventType Remove.condEventType . fmap Event.expEv++getTag = liftGetCond Remove.getTag Remove.condTagMatch+setTag = liftSetCond Remove.setTag Remove.condTagMatch+putTag = liftPutCond Remove.setTag Remove.condTagMatch++getDestQueue :: Remove.T -> IO (Addr.T, Queue.T)+getDestQueue r = liftM2 (,) (Remove.getDest r) (Remove.getQueue r)+setDestQueue :: Remove.T -> (Addr.T, Queue.T) -> IO ()+setDestQueue r (a,q) = Remove.setDest r a >> Remove.setQueue r q++getDest = liftGetCond getDestQueue Remove.condDest+setDest = liftSetCond setDestQueue Remove.condDest+putDest = liftPutCond setDestQueue Remove.condDest++getIgnoreOff = getCond Remove.condIgnoreOff+setIgnoreOff = setCond Remove.condIgnoreOff+putIgnoreOff = putCond Remove.condIgnoreOff+++getTime :: T (Maybe Ordering, Time.Stamp)+getTime = do+   ticks <- getCond Remove.condTimeTick+   stamp <-+      if ticks+        then fmap Time.Tick $ liftGet Remove.getTickTime+        else fmap Time.Real $ liftGet Remove.getRealTime+   after  <- getCond Remove.condTimeAfter+   before <- getCond Remove.condTimeBefore+   let mo =+          case (after, before) of+             (False, False) -> Nothing+             (True,  False) -> Just GT+             (False, True ) -> Just LT+             (True,  True ) -> Just EQ+   return (mo, stamp)++setTime :: Ordering -> Time.Stamp -> T ()+setTime o = putTime $ Just o++putTime :: Maybe Ordering -> Time.Stamp -> T ()+putTime mo t = do+   modifyCond ( .-. (Remove.condTimeAfter .|. Remove.condTimeBefore))+   modifyCond $ mappend $+      case mo of+         Nothing -> mempty+         Just LT -> Remove.condTimeBefore+         Just GT -> Remove.condTimeAfter+         Just EQ -> mappend Remove.condTimeBefore Remove.condTimeAfter+   case t of+      Time.Tick x -> do+         modifyCond $ (.-. Remove.condTimeTick)+         liftSet Remove.setTickTime x+      Time.Real x -> do+         modifyCond $ (.|. Remove.condTimeTick)+         liftSet Remove.setRealTime x
src/Sound/ALSA/Sequencer/Marshal/Address.hsc view
@@ -1,13 +1,14 @@ module Sound.ALSA.Sequencer.Marshal.Address where  #include <alsa/asoundlib.h>+#include <Sound/ALSA/Sequencer/Marshal/Template.h>  import qualified Sound.ALSA.Sequencer.Marshal.Client as Client import qualified Sound.ALSA.Sequencer.Marshal.Port as Port  import qualified Sound.ALSA.Sequencer.Utility as U -import Foreign.C.Types (CInt, )+import qualified Foreign.C.Types as C import Foreign.Storable           (Storable, sizeOf, alignment, peek, poke, pokeByteOff, peekByteOff, ) @@ -22,13 +23,13 @@       U.showsRecord prec "Address" [U.showsField c, U.showsField p]  -exp :: T -> (CInt,CInt)+exp :: T -> (C.CInt,C.CInt) exp a = (Client.exp (client a), Port.exp (port a))   instance Storable T where-  sizeOf _    = #size snd_seq_real_time_t-  alignment _ = 4 -- XXX+  sizeOf _    = #{size snd_seq_real_time_t}+  alignment _ = #{alignment snd_seq_real_time_t}   peek p      = do cl <- #{peek snd_seq_addr_t, client} p                    po <- #{peek snd_seq_addr_t, port} p                    return Cons { client = cl, port = po }@@ -36,10 +37,38 @@              >> #{poke snd_seq_addr_t, port}   p (port v)  +unknown :: T+unknown =+   Cons {+      client = Client.unknown,+      port   = Port.unknown+   }+ -- | The address of all subscribed ports. subscribers :: T subscribers =    Cons {       client = Client.subscribers,       port   = Port.unknown+   }++broadcast :: T+broadcast =+   Cons {+      client = Client.broadcast,+      port   = Port.unknown+   }++systemTimer :: T+systemTimer =+   Cons {+      client = Client.system,+      port   = Port.systemTimer+   }++systemAnnounce :: T+systemAnnounce =+   Cons {+      client = Client.system,+      port   = Port.systemAnnounce    }
src/Sound/ALSA/Sequencer/Marshal/Client.hsc view
@@ -13,24 +13,28 @@ -- Here we have the various types used by the library, -- and how they are imported\/exported to C. ----- NOTE: In the translations bellow we make the following assumptions--- about the sizes of C types.--- CChar  = 8 bits--- CShort = 16 bit--- CInt   = 32 bits+-- We use Hsc for expanding C types to Haskell types like Word32.+-- However if a C type is translated to Word32+-- you should not assume that it is translated to Word32 on every platform.+-- On a 64bit machine it may well be Word64.+-- Thus you should use our wrapper types whereever possible. --------------------------------------------------------------------------------  module Sound.ALSA.Sequencer.Marshal.Client where  #include <alsa/asoundlib.h>+#include <Sound/ALSA/Sequencer/Marshal/Template.h>+ import qualified Sound.ALSA.Sequencer.Utility as U-import Foreign.C.Types (CInt, )+import qualified Foreign.C.Types as C+import qualified Data.Word as Word import Foreign.Storable (Storable, )-import Data.Word (Word8, )   -- | The type of client identifiers.-newtype T = Cons Word8 deriving (Eq, Ord, Storable)+newtype T =+   Cons #{intfieldtype snd_seq_addr_t, client}+      deriving (Eq, Ord, Storable)  instance Show T where    showsPrec prec (Cons x) =@@ -46,16 +50,16 @@   -exp :: T -> CInt+exp :: T -> C.CInt exp (Cons c) = fromIntegral c -imp :: CInt -> T+imp :: C.CInt -> T imp p = Cons (fromIntegral p)  -- | The different types of clients. data Type = User | Kernel -impType :: CInt -> Type+impType :: C.CInt -> Type impType x =    if x == #{const SND_SEQ_USER_CLIENT}      then User
+ src/Sound/ALSA/Sequencer/Marshal/ClientInfo.hsc view
@@ -0,0 +1,104 @@+--------------------------------------------------------------------------------+-- |+-- Module    : Sound.ALSA.Sequencer.Client+-- Copyright : (c) Henning Thielemann, 2010-2012+--             (c) Iavor S. Diatchki, 2007+-- License   : BSD3+--+-- Maintainer: Henning Thielemann+-- Stability : provisional+--+-- This module contains functions for working with sequencer clients.+-- Reference:+-- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_client.html>+--------------------------------------------------------------------------------++module Sound.ALSA.Sequencer.Marshal.ClientInfo where++#include <Sound/ALSA/Sequencer/Area.h>++import qualified Sound.ALSA.Sequencer.Marshal.Client as Client+import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified Sound.ALSA.Sequencer.Area as Area+import qualified Sound.ALSA.Sequencer.Query as Query+import qualified Sound.ALSA.Sequencer.Utility as U+import qualified Sound.ALSA.Exception as Exc++import qualified Foreign.C.Types as C+import Foreign.Ptr (Ptr, )+import Data.Word (Word, )+++#area "client_info"++-- read/write+#get_set_name+#get_set_bool "broadcast_filter", "BroadcastFilter"+#get_set_bool "error_bounce", "ErrorBounce"+#{get_set_int "client", "Client",+          "Client.T", "Client.imp", "Client.exp"}++-- read only+#{get_int "type", "Type",+          "Client.Type", "Client.impType"}+#{get_int "num_ports", "NumPorts",+          "Word", "fromIntegral"}+#{get_int "event_lost", "EventLost",+          "Word", "fromIntegral"}++++-- | Create a new information area filled with data about the sequencer client.+get :: Seq.T mode -> IO T+get (Seq.Cons h) =+  do info <- malloc+     Exc.checkResult_ "ClientInfo.get" =<< with info (get_ h)+     return info++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_get_client_info"+  get_ :: Ptr Seq.Core -> Ptr T_ -> IO C.CInt+++-- | Create a new information area filled with data about an arbitrary client.+getAny :: Seq.T mode -> Client.T -> IO T+getAny (Seq.Cons h) c =+  do info <- malloc+     Exc.checkResult_ "ClientInfo.getAny" =<<+       with info (getAny_ h (Client.exp c))+     return info++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_get_any_client_info"+  getAny_+    :: Ptr Seq.Core -> C.CInt -> Ptr T_ -> IO C.CInt+++-- | Set the information for the sequencer client based on the data+-- in the given information area.+set :: Seq.T mode -> T -> IO ()+set (Seq.Cons h) info =+  Exc.checkResult_ "set_client_info" =<< with info (set_ h)++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_set_client_info"+  set_ :: Ptr Seq.Core -> Ptr T_ -> IO C.CInt++++queryInit :: T -> IO ()+queryInit x =+  {-+  we cannot use setClient here,+  since Client uses an unsigned type and thus cannot represent -1+  -}+  with x (flip setClient_ (-1))++-- | Get information about the client with the next biggest identifier.+queryNext :: Seq.T mode -> T -> IO Bool  -- ^ Was there a next client?+queryNext (Seq.Cons h) info =+  U.checkResultQuery "ClientInfo.queryNext" =<< with info (queryNext_ h)++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_query_next_client"+  queryNext_ :: Ptr Seq.Core -> Ptr T_ -> IO C.CInt++instance Query.C T where+  init = queryInit+  next = queryNext
+ src/Sound/ALSA/Sequencer/Marshal/Connect.hsc view
@@ -0,0 +1,24 @@+module Sound.ALSA.Sequencer.Marshal.Connect where++#include <alsa/asoundlib.h>+#include <Sound/ALSA/Sequencer/Marshal/Template.h>++import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr++import Foreign.Storable+          (Storable, sizeOf, alignment, peek, poke, pokeByteOff, peekByteOff, )+++data T = Cons+   { source :: !Addr.T+   , dest   :: !Addr.T+   } deriving (Show,Eq,Ord)++instance Storable T where+  sizeOf _    = #{size snd_seq_connect_t}+  alignment _ = #{alignment snd_seq_connect_t}+  peek p      = do s <- #{peek snd_seq_connect_t, sender} p+                   d <- #{peek snd_seq_connect_t, dest} p+                   return Cons { source = s, dest = d }+  poke p v    = #{poke snd_seq_connect_t, sender} p (source v)+             >> #{poke snd_seq_connect_t, dest}   p (dest v)
src/Sound/ALSA/Sequencer/Marshal/Event.hsc view
@@ -1,7 +1,7 @@ -------------------------------------------------------------------------------- -- | -- Module    : Sound.ALSA.Sequencer.Marshal.Event--- Copyright : (c) Henning Thielemann, 2011+-- Copyright : (c) Henning Thielemann, 2011-2012 --             (c) Iavor S. Diatchki, 2007 -- License   : BSD3 --@@ -13,58 +13,46 @@ -- Here we have the various types used by the library, -- and how they are imported\/exported to C. ----- NOTE: In the translations bellow we make the following assumptions--- about the sizes of C types.--- CChar  = 8 bits--- CShort = 16 bit--- CInt   = 32 bits+-- We use Hsc for expanding C types to Haskell types like Word32.+-- However if a C type is translated to Word32+-- you should not assume that it is translated to Word32 on every platform.+-- On a 64bit machine it may well be Word64.+-- Thus you should use our wrapper types whereever possible. --------------------------------------------------------------------------------  module Sound.ALSA.Sequencer.Marshal.Event where  #include <alsa/asoundlib.h>+#include <Sound/ALSA/Sequencer/Marshal/Template.h> +import qualified Sound.ALSA.Sequencer.Marshal.Connect as Connect import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue import qualified Sound.ALSA.Sequencer.Marshal.RealTime as RealTime+import qualified Sound.ALSA.Sequencer.Marshal.Time as Time -import Foreign.C.Types (CUInt, )+import qualified Data.ByteString.Unsafe as BU+import qualified Data.ByteString as B++import qualified Foreign.Marshal.Alloc as MA+import qualified Foreign.C.Types as C+import qualified Data.Int as Int+import qualified Data.Word as Word import Foreign.Storable           (Storable, sizeOf, alignment, peek, poke, pokeByteOff, peekByteOff, ) import Foreign.Ptr (Ptr, castPtr, nullPtr, plusPtr, )-import Foreign.Marshal.Alloc (alloca, )+import Control.Monad (liftM2, ) import Data.Monoid (mappend, ) import qualified Data.FlagSet as FlagSet-import Data.Int (Int16, Int32, )-import Data.Word (Word8, Word16, Word32, )-import Data.Array (Array, (!), accumArray, )+import Data.Array (Ix, Array, (!), accumArray, )+import Data.Tuple.HT (mapFst, )   data Flag-type Flags     = FlagSet.T Word8 Flag-type FlagValue = FlagSet.MaskedValue Word8 Flag---timeStampTick, timeStampReal :: FlagValue-timeStampTick =-   FlagSet.MaskedValue-      #{const SND_SEQ_TIME_STAMP_MASK}-      #{const SND_SEQ_TIME_STAMP_TICK}-timeStampReal =-   FlagSet.MaskedValue-      #{const SND_SEQ_TIME_STAMP_MASK}-      #{const SND_SEQ_TIME_STAMP_REAL}-+type Flags     = FlagSet.T #{intfieldtype snd_seq_event_t, flags} Flag+type FlagValue = FlagSet.MaskedValue #{intfieldtype snd_seq_event_t, flags} Flag -timeModeAbs, timeModeRel :: FlagValue-timeModeAbs =-   FlagSet.MaskedValue-      #{const SND_SEQ_TIME_MODE_MASK}-      #{const SND_SEQ_TIME_MODE_ABS}-timeModeRel =-   FlagSet.MaskedValue-      #{const SND_SEQ_TIME_MODE_MASK}-      #{const SND_SEQ_TIME_MODE_REL}+instance Time.Flag Flag where   eventLengthFixed, eventLengthVariable, eventLengthVarUser :: FlagValue@@ -93,81 +81,58 @@       #{const SND_SEQ_PRIORITY_NORMAL}  -data Connect = Connect-   { connSource :: !Addr.T-   , connDest   :: !Addr.T-   } deriving (Show,Eq,Ord) -instance Storable Connect where-  sizeOf _    = #size snd_seq_connect_t-  alignment _ = 4 -- XXX-  peek p      = do s <- #{peek snd_seq_connect_t, sender} p-                   d <- #{peek snd_seq_connect_t, dest} p-                   return Connect { connSource = s, connDest = d }-  poke p v    = #{poke snd_seq_connect_t, sender} p (connSource v)-             >> #{poke snd_seq_connect_t, dest}   p (connDest v)---data TimeStamp      = TickTime !Word32-                    | RealTime !RealTime.T-                      deriving Show--peekTimestamp :: Flags -> Ptr TimeStamp -> IO TimeStamp-peekTimestamp flags p =-  if FlagSet.match flags timeStampTick-    then fmap TickTime $ peek $ castPtr p-    else fmap RealTime $ peek $ castPtr p--pokeTimestamp :: Ptr TimeStamp -> TimeStamp -> IO FlagValue-pokeTimestamp p ts = case ts of-  TickTime t -> poke (castPtr p) t >> return timeStampTick-  RealTime t -> poke (castPtr p) t >> return timeStampReal--+{- available in alsa-1.0.14, but gone in 1.0.22+#{newinttype "InstrCluster", snd_seq_instr_cluster_t} -newtype InstrCluster = InstrCluster CUInt-  deriving (Show,Eq,Ord,Num,Enum,Storable)+#{newintfieldtype "StandardId", snd_seq_instr_t, std}+#{newintfieldtype "Bank",       snd_seq_instr_t, bank}+#{newintfieldtype "Program",    snd_seq_instr_t, prg}  data Instr = Instr    { instrCluster :: !InstrCluster     -- XXX: perhaps use Sample?-   , instrStd     :: !Word32-   , instrBank    :: !Word16-   , instrPrg     :: !Word16+   , instrStd     :: !StandardId+   , instrBank    :: !Bank+   , instrPrg     :: !Program    } deriving (Show) -{- instance Storable Instr where   sizeOf _    = #{size snd_seq_instr_t}-  alignment _ = 4 -- XXX+  alignment _ = #{alignment snd_seq_instr_t}   peek p      = do cl <- #{peek snd_seq_instr_t, cluster} p                    st <- #{peek snd_seq_instr_t, std} p                    ba <- #{peek snd_seq_instr_t, bank} p                    pr <- #{peek snd_seq_instr_t, prg} p-                   return Instr { instr_cluster = cl-                                , instr_std     = st-                                , instr_bank    = ba-                                , instr_prg     = pr+                   return Instr { instrCluster = cl+                                , instrStd     = st+                                , instrBank    = ba+                                , instrPrg     = pr                                 }-  poke p v    = #{poke snd_seq_instr_t, cluster} p (instr_cluster v)-             >> #{poke snd_seq_instr_t, std}     p (instr_std v)-             >> #{poke snd_seq_instr_t, bank}    p (instr_bank v)-             >> #{poke snd_seq_instr_t, prg}     p (instr_prg v)+  poke p v    = #{poke snd_seq_instr_t, cluster} p (instrCluster v)+             >> #{poke snd_seq_instr_t, std}     p (instrStd v)+             >> #{poke snd_seq_instr_t, bank}    p (instrBank v)+             >> #{poke snd_seq_instr_t, prg}     p (instrPrg v) -}  +#{newintfieldtype "Channel",  snd_seq_ev_note_t, channel}+#{newintfieldtype "Pitch",    snd_seq_ev_note_t, note}+#{newintfieldtype "Velocity", snd_seq_ev_note_t, velocity}+#{newintfieldtype "Duration", snd_seq_ev_note_t, duration}+ data Note = Note-   { noteChannel      :: !Word8-   , noteNote         :: !Word8-   , noteVelocity     :: !Word8-   , noteOffVelocity  :: !Word8-   , noteDuration     :: !Word32+   { noteChannel      :: !Channel+   , noteNote         :: !Pitch+   , noteVelocity     :: !Velocity+   , noteOffVelocity  :: !Velocity+   , noteDuration     :: !Duration    } deriving (Show)   instance Storable Note where   sizeOf _    = #{size snd_seq_ev_note_t}-  alignment _ = 4 -- XXX+  alignment _ = #{alignment snd_seq_ev_note_t}   peek p      = do c  <- #{peek snd_seq_ev_note_t, channel} p                    n  <- #{peek snd_seq_ev_note_t, note} p                    v  <- #{peek snd_seq_ev_note_t, velocity} p@@ -186,15 +151,18 @@              >> #{poke snd_seq_ev_note_t, duration}     p (noteDuration v)  +#{newintfieldtype "Parameter", snd_seq_ev_ctrl_t, param}+#{newintfieldtype "Value",     snd_seq_ev_ctrl_t, value}+ data Ctrl = Ctrl-   { ctrlChannel  :: !Word8-   , ctrlParam    :: !Word32-   , ctrlValue    :: !Int32+   { ctrlChannel  :: !Channel+   , ctrlParam    :: !Parameter+   , ctrlValue    :: !Value    } deriving (Show)  instance Storable Ctrl where   sizeOf _    = #{size snd_seq_ev_ctrl_t}-  alignment _ = 4 -- XXX+  alignment _ = #{alignment snd_seq_ev_ctrl_t}   peek p      = do ct <- #{peek snd_seq_ev_ctrl_t, channel} p                    pa <- #{peek snd_seq_ev_ctrl_t, param} p                    va <- #{peek snd_seq_ev_ctrl_t, value} p@@ -207,28 +175,40 @@              >> #{poke snd_seq_ev_ctrl_t, value}   p (ctrlValue v)  +pokeQueue ::+  Ptr Data -> QueueEv -> Queue.T -> IO EType+pokeQueue p e q = do+  poke (castPtr p) q+  case e of+    QueueSetPosTick t -> #{poke snd_seq_ev_queue_control_t, param.time.tick} p t+    QueueSetPosTime t -> #{poke snd_seq_ev_queue_control_t, param.time.time} p t+    QueueTempo      t -> #{poke snd_seq_ev_queue_control_t, param.value} p t+    QueueSkew       s -> #{poke snd_seq_ev_queue_control_t, param.skew} p s+    QueueSyncPos    s -> #{poke snd_seq_ev_queue_control_t, param.position} p s+    _ -> return ()+  return (expEv e) ++{- available in alsa-1.0.14, but gone in 1.0.22 data Sample = Sample-   { sampleStd  :: !Word32-   , sampleBank :: !Word16-   , samplePrg  :: !Word16+   { sampleStd  :: !StandardId+   , sampleBank :: !Bank+   , samplePrg  :: !Program    } deriving (Show) -{- instance Storable Sample where   sizeOf _    = #{size snd_seq_ev_sample_t}-  alignment _ = 4 -- XXX+  alignment _ = #{alignment snd_seq_ev_sample_t}   peek p      = do st <- #{peek snd_seq_ev_sample_t, std} p                    ba <- #{peek snd_seq_ev_sample_t, bank} p                    pr <- #{peek snd_seq_ev_sample_t, prg} p-                   return Sample { sample_std     = st-                                 , sample_bank    = ba-                                 , sample_prg     = pr+                   return Sample { sampleStd     = st+                                 , sampleBank    = ba+                                 , samplePrg     = pr                                  }   poke p v    = #{poke snd_seq_ev_sample_t, std}     p (sampleStd v)              >> #{poke snd_seq_ev_sample_t, bank}    p (sampleBank v)              >> #{poke snd_seq_ev_sample_t, prg}     p (samplePrg v)--}   newtype Cluster = Cluster@@ -236,26 +216,29 @@    } deriving (Show, Eq, Storable)  +#{newintfieldtype "Volume",  snd_seq_ev_volume_t, volume}+#{newintfieldtype "Balance", snd_seq_ev_volume_t, lr}+ -- | These are all 14 bit values.-data Volume = Volume-   { volumeVolume  :: !Int16-   , volumeLR      :: !Int16-   , volumeFR      :: !Int16-   , volumeDU      :: !Int16+data VolumeControl = VolumeControl+   { volumeVolume  :: !Volume+   , volumeLR      :: !Balance+   , volumeFR      :: !Balance+   , volumeDU      :: !Balance    } deriving (Show) -{--instance Storable Volume where+instance Storable VolumeControl where   sizeOf _    = #{size snd_seq_ev_volume_t}-  alignment _ = 4 -- XXX+  alignment _ = #{alignment snd_seq_ev_volume_t}   peek p      = do v <- #{peek snd_seq_ev_volume_t, volume} p                    l <- #{peek snd_seq_ev_volume_t, lr} p                    f <- #{peek snd_seq_ev_volume_t, fr} p                    d <- #{peek snd_seq_ev_volume_t, du} p-                   return Volume { volume_volume  = v-                                 , volume_lr      = l-                                 , volume_fr      = f-                                 , volume_du      = d+                   return VolumeControl+                                 { volumeVolume  = v+                                 , volumeLR      = l+                                 , volumeFR      = f+                                 , volumeDU      = d                                  }   poke p v    = #{poke snd_seq_ev_volume_t, volume} p (volumeVolume v)              >> #{poke snd_seq_ev_volume_t, lr}     p (volumeLR v)@@ -264,12 +247,14 @@ -}  -data Custom = Custom { custom0, custom1, custom2 :: !Word32 }-                      deriving (Show)+data Custom =+  Custom {+    custom0, custom1, custom2 :: ! #{intfieldtype snd_seq_ev_raw32_t, d[0]}+  } deriving (Show)  instance Storable Custom where   sizeOf _    = #{size snd_seq_ev_raw32_t}-  alignment _ = 4 -- XXX+  alignment _ = #{alignment snd_seq_ev_raw32_t}   peek p      = do d0 <- #{peek snd_seq_ev_raw32_t, d[0]} p                    d1 <- #{peek snd_seq_ev_raw32_t, d[1]} p                    d2 <- #{peek snd_seq_ev_raw32_t, d[2]} p@@ -282,12 +267,13 @@              >> #{poke snd_seq_ev_raw32_t, d[2]} p (custom2 v)  +#{newintfieldtype "Tag", snd_seq_event_t, tag}  data T = Cons    { highPriority   :: !Bool-   , tag            :: !Word8+   , tag            :: !Tag    , queue          :: !Queue.T-   , timestamp      :: !TimeStamp+   , time           :: !Time.T    , source         :: !Addr.T    , dest           :: !Addr.T    , body           :: !Data@@ -295,13 +281,13 @@  instance Storable T where   sizeOf _    = #{size snd_seq_event_t}-  alignment _ = 4 -- XXX+  alignment _ = #{alignment snd_seq_event_t}   peek p =     do ty    <- #{peek snd_seq_event_t, type} p        flags <- #{peek snd_seq_event_t, flags} p        tg    <- #{peek snd_seq_event_t, tag} p        q     <- #{peek snd_seq_event_t, queue} p-       time  <- peekTimestamp flags (#{ptr snd_seq_event_t, time} p)+       t     <- Time.peek flags (#{ptr snd_seq_event_t, time} p)        src   <- #{peek snd_seq_event_t, source} p        dst   <- #{peek snd_seq_event_t, dest} p        d     <- (peekData ! ty) (#{ptr snd_seq_event_t, data} p)@@ -309,53 +295,78 @@          { highPriority = not $ FlagSet.match flags priorityNormal          , tag = tg          , queue = q-         , timestamp = time+         , time = t          , source = src          , dest = dst          , body = d          }-  poke p e = do-    { ty <- pokeData (#{ptr snd_seq_event_t, data} p) (body e)-    ; #{poke snd_seq_event_t, type} p ty-    ; #{poke snd_seq_event_t, tag} p (tag e)-    ; #{poke snd_seq_event_t, queue} p (queue e)-    ; real <- pokeTimestamp (#{ptr snd_seq_event_t, time} p) (timestamp e)-    ; #{poke snd_seq_event_t, source} p (source e)-    ; #{poke snd_seq_event_t, dest} p (dest e)-    ; let flags =-             (if highPriority e-                then priorityHigh-                else priorityNormal)-             `mappend` real-             `mappend` eventLengthFixed-    ; #{poke snd_seq_event_t, flags} p (FlagSet.fromMaskedValue flags)-    }+  poke p e =+    pokeHeader p e eventLengthFixed+      =<< pokeData (#{ptr snd_seq_event_t, data} p) (body e) -allocaEv :: T -> (Ptr T -> IO a) -> IO a-allocaEv e h = alloca (\p -> poke p e >> h p)+withMaybe :: Maybe T -> (Ptr T -> IO a) -> IO a+withMaybe me f =+  maybe (f nullPtr) (flip with f) me -allocaMaybeEv :: Maybe T -> (Ptr T -> IO a) -> IO a-allocaMaybeEv me h =-  maybe (h nullPtr) (\e -> allocaEv e h) me+with :: T -> (Ptr T -> IO a) -> IO a+with ev f =+  MA.alloca $ \p ->+    case body ev of+      ExtEv e d -> do+        let lengthFlag =+              case e of+                SysEx -> eventLengthVariable+                Bounce -> eventLengthVariable+                _ -> eventLengthVarUser+        pokeHeader p ev lengthFlag (expEv e)+        BU.unsafeUseAsCString d $ \ptr -> do+          #{poke snd_seq_event_t, data.ext.len} p (B.length d)+          #{poke snd_seq_event_t, data.ext.ptr} p ptr+          f p+      b -> do+        pokeHeader p ev eventLengthFixed+          =<< pokeData (#{ptr snd_seq_event_t, data} p) b+        f p + pokeBody ::   (Storable d, Type e) =>-  Ptr Data -> e -> d -> IO Word8+  Ptr Data -> e -> d -> IO EType pokeBody p e d =   poke (castPtr p) d >> return (expEv e) -pokeData :: Ptr Data -> Data -> IO Word8+pokeData :: Ptr Data -> Data -> IO EType pokeData p dt = case dt of   NoteEv   e d -> pokeBody p e d   CtrlEv   e d -> pokeBody p e d+  QueueEv  e d -> pokeQueue p e d   AddrEv   e d -> pokeBody p e d   ConnEv   e d -> pokeBody p e d   CustomEv e d -> pokeBody p e d+  ExtEv    _ _ -> error "cannot simply poke ExtEv, because it needs allocation - use Event.with instead"   EmptyEv  e   -> return (expEv e) +pokeHeader :: Ptr T -> T -> FlagValue -> EType -> IO ()+pokeHeader p e lengthFlag ty = do+  #{poke snd_seq_event_t, type} p ty+  #{poke snd_seq_event_t, tag} p (tag e)+  #{poke snd_seq_event_t, queue} p (queue e)+  real <- Time.poke (#{ptr snd_seq_event_t, time} p) (time e)+  #{poke snd_seq_event_t, source} p (source e)+  #{poke snd_seq_event_t, dest} p (dest e)+  let flags =+         (if highPriority e+            then priorityHigh+            else priorityNormal)+         `mappend` real+         `mappend` lengthFlag+  #{poke snd_seq_event_t, flags} p (FlagSet.fromMaskedValue flags) -peekData :: Array Word8 (Ptr Data -> IO Data)-peekData = accumArray (const id) unknown (0,255)++peekData :: Array EType (Ptr Data -> IO Data)+peekData =+  accumArray (const id) unknown (EType 0, EType 255) $+  map (mapFst EType) $   [ -- result events (2)     (#{const SND_SEQ_EVENT_SYSTEM}, unknown)   , (#{const SND_SEQ_EVENT_RESULT}, unknown)@@ -381,16 +392,16 @@   , (#{const SND_SEQ_EVENT_KEYSIGN},     peekCtrlEv KeySign)    -- queue control (10)-  , (#{const SND_SEQ_EVENT_START}, unknown)-  , (#{const SND_SEQ_EVENT_CONTINUE}, unknown)-  , (#{const SND_SEQ_EVENT_STOP}, unknown)-  , (#{const SND_SEQ_EVENT_SETPOS_TICK}, unknown)-  , (#{const SND_SEQ_EVENT_SETPOS_TIME}, unknown)-  , (#{const SND_SEQ_EVENT_TEMPO}, unknown)-  , (#{const SND_SEQ_EVENT_CLOCK}, unknown)-  , (#{const SND_SEQ_EVENT_TICK}, unknown)-  , (#{const SND_SEQ_EVENT_QUEUE_SKEW}, unknown)-  , (#{const SND_SEQ_EVENT_SYNC_POS}, unknown)+  , (#{const SND_SEQ_EVENT_START},       peekQueueEv  QueueStart)+  , (#{const SND_SEQ_EVENT_CONTINUE},    peekQueueEv  QueueContinue)+  , (#{const SND_SEQ_EVENT_STOP},        peekQueueEv  QueueStop)+  , (#{const SND_SEQ_EVENT_SETPOS_TICK}, peekQueueExt QueueSetPosTick #{peek snd_seq_ev_queue_control_t, param.time.tick})+  , (#{const SND_SEQ_EVENT_SETPOS_TIME}, peekQueueExt QueueSetPosTime #{peek snd_seq_ev_queue_control_t, param.time.time})+  , (#{const SND_SEQ_EVENT_TEMPO},       peekQueueExt QueueTempo      #{peek snd_seq_ev_queue_control_t, param.value})+  , (#{const SND_SEQ_EVENT_CLOCK},       peekQueueEv  QueueClock)+  , (#{const SND_SEQ_EVENT_TICK},        peekQueueEv  QueueTick)+  , (#{const SND_SEQ_EVENT_QUEUE_SKEW},  peekQueueExt QueueSkew       #{peek snd_seq_ev_queue_control_t, param.skew})+  , (#{const SND_SEQ_EVENT_SYNC_POS},    peekQueueExt QueueSyncPos    #{peek snd_seq_ev_queue_control_t, param.position})    -- misc (3)   , (#{const SND_SEQ_EVENT_TUNE_REQUEST}, peekEmptyEv TuneRequest)@@ -410,7 +421,7 @@   , (#{const SND_SEQ_EVENT_PORT_SUBSCRIBED},   peekConnEv PortSubscribed)   , (#{const SND_SEQ_EVENT_PORT_UNSUBSCRIBED}, peekConnEv PortUnsubscribed) -{-+{- available in alsa-1.0.14, but gone in 1.0.22   , (#{const SND_SEQ_EVENT_SAMPLE}, unknown)   , (#{const SND_SEQ_EVENT_SAMPLE_CLUSTER}, unknown)   , (#{const SND_SEQ_EVENT_SAMPLE_START}, unknown)@@ -432,7 +443,7 @@   , (#{const SND_SEQ_EVENT_USR8}, peekCustomEv User8)   , (#{const SND_SEQ_EVENT_USR9}, peekCustomEv User9) -{-+{- available in alsa-1.0.14, but gone in 1.0.22   , (#{const SND_SEQ_EVENT_INSTR_BEGIN}, unknown)   , (#{const SND_SEQ_EVENT_INSTR_END}, unknown)   , (#{const SND_SEQ_EVENT_INSTR_INFO}, unknown)@@ -454,14 +465,13 @@   , (#{const SND_SEQ_EVENT_INSTR_CHANGE}, unknown) -} -  , (#{const SND_SEQ_EVENT_SYSEX}, unknown)-  , (#{const SND_SEQ_EVENT_BOUNCE}, unknown)--  , (#{const SND_SEQ_EVENT_USR_VAR0}, unknown)-  , (#{const SND_SEQ_EVENT_USR_VAR1}, unknown)-  , (#{const SND_SEQ_EVENT_USR_VAR2}, unknown)-  , (#{const SND_SEQ_EVENT_USR_VAR3}, unknown)-  , (#{const SND_SEQ_EVENT_USR_VAR3}, unknown)+  , (#{const SND_SEQ_EVENT_SYSEX},    peekExtEv SysEx   )+  , (#{const SND_SEQ_EVENT_BOUNCE},   peekExtEv Bounce  )+  , (#{const SND_SEQ_EVENT_USR_VAR0}, peekExtEv UserVar0)+  , (#{const SND_SEQ_EVENT_USR_VAR1}, peekExtEv UserVar1)+  , (#{const SND_SEQ_EVENT_USR_VAR2}, peekExtEv UserVar2)+  , (#{const SND_SEQ_EVENT_USR_VAR3}, peekExtEv UserVar3)+  , (#{const SND_SEQ_EVENT_USR_VAR3}, peekExtEv UserVar4)    , (#{const SND_SEQ_EVENT_NONE}, peekEmptyEv None)   ]@@ -480,17 +490,19 @@               | TimeSign | KeySign                 deriving (Show, Eq, Ord, Enum, Bounded) +#{newintfieldtype "Tempo", snd_seq_ev_queue_control_t, param.value}+ data QueueEv  = QueueStart               | QueueContinue               | QueueStop-              | QueueSetPosTick-              | QueueSetPosTime-              | QueueTempo+              | QueueSetPosTick !Time.Tick+              | QueueSetPosTime !RealTime.T+              | QueueTempo      !Tempo               | QueueClock               | QueueTick-              | QueueSkew-              | QueueSyncPos-                deriving (Show, Eq, Ord, Enum, Bounded)+              | QueueSkew       !Queue.Skew+              | QueueSyncPos    !Queue.Position+                deriving (Show, Eq)  data EmptyEv  = TuneRequest | Reset | Sensing | None | Unknown                 deriving (Show, Eq, Ord, Enum, Bounded)@@ -500,6 +512,10 @@               | User5 | User6 | User7 | User8 | User9                 deriving (Show, Eq, Ord, Enum, Bounded) +data ExtEv    = SysEx | Bounce+              | UserVar0 | UserVar1 | UserVar2 | UserVar3 | UserVar4+                deriving (Show, Eq, Ord, Enum, Bounded)+ data AddrEv   = ClientStart | ClientExit | ClientChange               | PortStart | PortExit | PortChange                 deriving (Show, Eq, Ord, Enum, Bounded)@@ -508,18 +524,23 @@                 deriving (Show, Eq, Ord, Enum, Bounded)  +#{newinttype "EType", snd_seq_event_type_t}++-- type EType = #{inttype snd_seq_event_type_t}++ class Type e where-  expEv :: e -> Word8+  expEv :: e -> EType -instance Type NoteEv where - expEv e = case e of+instance Type NoteEv where+ expEv e = EType $ case e of   ANote    -> #{const SND_SEQ_EVENT_NOTE}   NoteOn   -> #{const SND_SEQ_EVENT_NOTEON}   NoteOff  -> #{const SND_SEQ_EVENT_NOTEOFF}   KeyPress -> #{const SND_SEQ_EVENT_KEYPRESS} -instance Type CtrlEv where - expEv e = case e of+instance Type CtrlEv where+ expEv e = EType $ case e of   Controller  -> #{const SND_SEQ_EVENT_CONTROLLER}   PgmChange   -> #{const SND_SEQ_EVENT_PGMCHANGE}   ChanPress   -> #{const SND_SEQ_EVENT_CHANPRESS}@@ -533,29 +554,34 @@   TimeSign    -> #{const SND_SEQ_EVENT_TIMESIGN}   KeySign     -> #{const SND_SEQ_EVENT_KEYSIGN} -instance Type QueueEv where - expEv e = case e of-  QueueStart      -> #{const SND_SEQ_EVENT_START}-  QueueContinue   -> #{const SND_SEQ_EVENT_CONTINUE}-  QueueStop       -> #{const SND_SEQ_EVENT_STOP}-  QueueSetPosTick -> #{const SND_SEQ_EVENT_SETPOS_TICK}-  QueueSetPosTime -> #{const SND_SEQ_EVENT_SETPOS_TIME}-  QueueTempo      -> #{const SND_SEQ_EVENT_TEMPO}-  QueueClock      -> #{const SND_SEQ_EVENT_CLOCK}-  QueueTick       -> #{const SND_SEQ_EVENT_TICK}-  QueueSkew       -> #{const SND_SEQ_EVENT_QUEUE_SKEW}-  QueueSyncPos    -> #{const SND_SEQ_EVENT_SYNC_POS}+instance Type QueueEv where+  expEv = fst . expQueueEv -instance Type EmptyEv where - expEv e = case e of+-- setPosTick should be an error+expQueueEv :: QueueEv -> (EType, C.CInt)+expQueueEv e = mapFst EType $ case e of+  QueueStart        -> (#{const SND_SEQ_EVENT_START}       , 0)+  QueueContinue     -> (#{const SND_SEQ_EVENT_CONTINUE}    , 0)+  QueueStop         -> (#{const SND_SEQ_EVENT_STOP}        , 0)+  QueueSetPosTick _ -> (#{const SND_SEQ_EVENT_SETPOS_TICK} , error "expQueueEv.QueueSetPosTick: cannot represent position as int")+  QueueSetPosTime _ -> (#{const SND_SEQ_EVENT_SETPOS_TIME} , error "expQueueEv.QueueSetPosTime: cannot represent position as int")+  QueueTempo      x -> (#{const SND_SEQ_EVENT_TEMPO}       , fromIntegral $ unTempo x)+  QueueClock        -> (#{const SND_SEQ_EVENT_CLOCK}       , 0)+  QueueTick         -> (#{const SND_SEQ_EVENT_TICK}        , 0)+  QueueSkew       _ -> (#{const SND_SEQ_EVENT_QUEUE_SKEW}  , error "expQueueEv.QueueSkew: cannot represent skew record as int")+  QueueSyncPos    x -> (#{const SND_SEQ_EVENT_SYNC_POS}    , fromIntegral $ Queue.unPosition x)+++instance Type EmptyEv where+ expEv e = EType $ case e of   TuneRequest -> #{const SND_SEQ_EVENT_TUNE_REQUEST}   Reset       -> #{const SND_SEQ_EVENT_RESET}   Sensing     -> #{const SND_SEQ_EVENT_SENSING}   None        -> #{const SND_SEQ_EVENT_NONE}   Unknown     -> #{const SND_SEQ_EVENT_NONE} -instance Type CustomEv where - expEv e = case e of+instance Type CustomEv where+ expEv e = EType $ case e of   Echo  -> #{const SND_SEQ_EVENT_ECHO}   OSS   -> #{const SND_SEQ_EVENT_OSS}   User0 -> #{const SND_SEQ_EVENT_USR0}@@ -569,8 +595,18 @@   User8 -> #{const SND_SEQ_EVENT_USR8}   User9 -> #{const SND_SEQ_EVENT_USR9} -instance Type AddrEv where -  expEv e = case e of+instance Type ExtEv where+ expEv e = EType $ case e of+  SysEx    -> #{const SND_SEQ_EVENT_SYSEX}+  Bounce   -> #{const SND_SEQ_EVENT_BOUNCE}+  UserVar0 -> #{const SND_SEQ_EVENT_USR_VAR0}+  UserVar1 -> #{const SND_SEQ_EVENT_USR_VAR1}+  UserVar2 -> #{const SND_SEQ_EVENT_USR_VAR2}+  UserVar3 -> #{const SND_SEQ_EVENT_USR_VAR3}+  UserVar4 -> #{const SND_SEQ_EVENT_USR_VAR4}++instance Type AddrEv where+  expEv e = EType $ case e of     ClientStart -> #{const SND_SEQ_EVENT_CLIENT_START}     ClientExit -> #{const SND_SEQ_EVENT_CLIENT_EXIT}     ClientChange -> #{const SND_SEQ_EVENT_CLIENT_CHANGE}@@ -578,8 +614,8 @@     PortExit -> #{const SND_SEQ_EVENT_PORT_EXIT}     PortChange -> #{const SND_SEQ_EVENT_PORT_CHANGE} -instance Type ConnEv where - expEv e = case e of+instance Type ConnEv where+ expEv e = EType $ case e of   PortSubscribed   -> #{const SND_SEQ_EVENT_PORT_SUBSCRIBED}   PortUnsubscribed -> #{const SND_SEQ_EVENT_PORT_UNSUBSCRIBED} @@ -600,6 +636,13 @@ peekCtrlEv :: CtrlEv -> Ptr Data -> IO Data peekCtrlEv e = peekBody (CtrlEv e) +peekQueueEv :: QueueEv -> Ptr Data -> IO Data+peekQueueEv e = peekBody (QueueEv e)++peekQueueExt :: (a -> QueueEv) -> (Ptr Data -> IO a) -> Ptr Data -> IO Data+peekQueueExt makeQ peekParam p =+  liftM2 (QueueEv . makeQ) (peekParam p) (peek (castPtr p))+ peekAddrEv :: AddrEv -> Ptr Data -> IO Data peekAddrEv e = peekBody (AddrEv e) @@ -612,12 +655,20 @@ peekCustomEv :: CustomEv -> Ptr Data -> IO Data peekCustomEv e = peekBody (CustomEv e) +peekExtEv :: ExtEv -> Ptr Data -> IO Data+peekExtEv e p = do+  len <- #{peek snd_seq_ev_ext_t, len} p+  ptr <- #{peek snd_seq_ev_ext_t, ptr} p+  fmap (ExtEv e) $ B.packCStringLen (ptr,len) + data Data   = NoteEv NoteEv Note   | CtrlEv CtrlEv Ctrl+  | QueueEv QueueEv Queue.T   | AddrEv AddrEv Addr.T-  | ConnEv ConnEv Connect+  | ConnEv ConnEv Connect.T   | EmptyEv EmptyEv   | CustomEv CustomEv Custom+  | ExtEv ExtEv B.ByteString     deriving Show
src/Sound/ALSA/Sequencer/Marshal/Port.hsc view
@@ -1,6 +1,6 @@ -------------------------------------------------------------------------------- -- |--- Module    : Sound.ALSA.Sequencer.Marshal+-- Module    : Sound.ALSA.Sequencer.Marshal.Port -- Copyright : (c) Henning Thielemann, 2011 --             (c) Iavor S. Diatchki, 2007 -- License   : BSD3@@ -13,38 +13,42 @@ -- Here we have the various types used by the library, -- and how they are imported\/exported to C. ----- NOTE: In the translations bellow we make the following assumptions--- about the sizes of C types.--- CChar  = 8 bits--- CShort = 16 bit--- CInt   = 32 bits+-- We use Hsc for expanding C types to Haskell types like Word32.+-- However if a C type is translated to Word32+-- you should not assume that it is translated to Word32 on every platform.+-- On a 64bit machine it may well be Word64.+-- Thus you should use our wrapper types whereever possible. --------------------------------------------------------------------------------  module Sound.ALSA.Sequencer.Marshal.Port where  #include <alsa/asoundlib.h>+#include <Sound/ALSA/Sequencer/Marshal/Template.h>+ import qualified Sound.ALSA.Sequencer.Utility as U-import Foreign.C.Types (CInt, CUInt, )+import qualified Foreign.C.Types as C+import qualified Data.Word as Word import Foreign.Storable (Storable, ) import Data.Ix (Ix, range, index, inRange, rangeSize, )-import Data.Word (Word8, ) import Data.Maybe (fromMaybe, ) import qualified Data.Ix.Enum as IxEnum import qualified Data.EnumSet as EnumSet   -- The type of client ports.-newtype T = Cons Word8 deriving (Eq, Ord, Storable)+newtype T =+   Cons #{intfieldtype snd_seq_addr_t, port}+      deriving (Eq, Ord, Storable)  instance Show T where    showsPrec prec (Cons x) =       U.showsRecord prec "Port" [U.showsField x]  -exp :: T -> CInt+exp :: T -> C.CInt exp (Cons p) = fromIntegral p -imp :: CInt -> T+imp :: C.CInt -> T imp p = Cons (fromIntegral p)  @@ -194,10 +198,10 @@   -- | Port capabilities.-type Cap = EnumSet.T CUInt CapabilityFlag+type Cap = EnumSet.T C.CUInt CapabilityFlag  -- | Port types.-type Type = EnumSet.T CUInt TypeFlag+type Type = EnumSet.T C.CUInt TypeFlag  #{enum T, Cons  , systemTimer    = SND_SEQ_PORT_SYSTEM_TIMER
+ src/Sound/ALSA/Sequencer/Marshal/PortInfo.hsc view
@@ -0,0 +1,126 @@+--------------------------------------------------------------------------------+-- |+-- Module    : Sound.ALSA.Sequencer.Marshal.PortInfo+-- Copyright : (c) Henning Thielemann, 2010-2012+--             (c) Iavor S. Diatchki, 2007+-- License   : BSD3+--+-- Maintainer: Henning Thielemann+-- Stability : provisional+--+-- This module contains functions for working with ports.+-- Reference:+-- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_port.html>+--------------------------------------------------------------------------------++module Sound.ALSA.Sequencer.Marshal.PortInfo where++#include <Sound/ALSA/Sequencer/Area.h>++import qualified Sound.ALSA.Sequencer.Marshal.Client as Client+import qualified Sound.ALSA.Sequencer.Marshal.Port as Port+import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue+import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr+import qualified Sound.ALSA.Sequencer.Area as Area+import qualified Sound.ALSA.Sequencer.Query as Query+import qualified Sound.ALSA.Sequencer.Utility as U+import qualified Sound.ALSA.Exception as Exc++import qualified Data.EnumSet as EnumSet++import qualified Foreign.C.Types as C+import Foreign.Ptr (Ptr, )+import Data.Word (Word, )+++#area "port_info"++{- |+Create a new information area filled with data+about a specific port on our client.+-}+#get_area "Port.T"+{- |+Set the information for the sequencer port+based on the data in the given information area.+-}+#set_area "Port.T"++-- read/write+#get_set_name++#get_set_bool "port_specified", "PortSpecified"+#get_set_bool "timestamping", "Timestamping"+#get_set_bool "timestamp_real", "TimestampReal"++#{get_set_int "port", "Port",+          "Port.T", "Port.imp", "Port.exp"}+#{get_set_int "client", "Client",+          "Client.T", "Client.imp", "Client.exp"}+#{get_set_int "capability", "Capability",+          "Port.Cap", "(EnumSet.Cons . fromIntegral)", "(fromIntegral . EnumSet.decons)"}++#{get_set_int "midi_channels", "MidiChannels",+          "Word", "fromIntegral", "fromIntegral"}+#{get_set_int "midi_voices", "MidiVoices",+          "Word", "fromIntegral", "fromIntegral"}+#{get_set_int "synth_voices", "SynthVoices",+          "Word", "fromIntegral", "fromIntegral"}++#{get_set_int "timestamp_queue", "TimestampQueue",+          "Queue.T", "Queue.imp", "Queue.exp"}+++-- | Get the address of the information area.+#{get_ptr "addr", "Addr", "Addr.T"}++-- | Set the port address.+#{set_ptr "addr", "Addr", "Addr.T"}+++-- read only+#{get_int "read_use", "ReadUse", "Word", "fromIntegral"}+#{get_int "write_use", "WriteUse", "Word", "fromIntegral"}++++-- | Create a new information area filled with data about an given+-- port on a given client.+getAny :: Seq.T mode -> Client.T -> Port.T -> IO T+getAny (Seq.Cons h) c p =+  do info <- malloc+     Exc.checkResult_ "getAny" =<<+       with info (getAny_ h (Client.exp c) (Port.exp p))+     return info++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_get_any_port_info"+  getAny_+    :: Ptr Seq.Core -> C.CInt -> C.CInt -> Ptr T_ -> IO C.CInt++queryInit :: T -> IO ()+queryInit x =+  {-+  we cannot use setPort here,+  since Port uses an unsigned type and thus cannot represent -1+  -}+  with x (flip setPort_ (-1))++-- | Get information about the first port on our client.+queryFirst :: Seq.T mode -> IO T+queryFirst = Query.first++-- | Get information about the port with the next biggest identifier.+-- If a matching port is found, then its information is stored in the+-- given area and 'True' is returned.+queryNext :: Seq.T mode -> T -> IO Bool+queryNext (Seq.Cons h) info =+  U.checkResultQuery "PortInfo.queryNext" =<< with info (queryNext_ h)++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_query_next_port"+  queryNext_ :: Ptr Seq.Core -> Ptr T_ -> IO C.CInt+++instance Query.C T where+  init = queryInit+  next = queryNext
− src/Sound/ALSA/Sequencer/Marshal/QuerySubscribe.hsc
@@ -1,21 +0,0 @@-module Sound.ALSA.Sequencer.Marshal.QuerySubscribe where--#include <alsa/asoundlib.h>-import Foreign.C.Types (CInt, )---data Type =-     Read-   | Write-   deriving (Show, Eq, Ord, Enum)--expType :: Type -> CInt-expType t  = case t of-  Read  -> #{const SND_SEQ_QUERY_SUBS_READ}-  Write	-> #{const SND_SEQ_QUERY_SUBS_WRITE}--impType :: CInt -> Type-impType t  = case t of-  #{const SND_SEQ_QUERY_SUBS_READ}  -> Read-  #{const SND_SEQ_QUERY_SUBS_WRITE} -> Write-  _ -> error ("QuerySubscribe.impType: unknown subscription type (" ++ show t ++ ")")
src/Sound/ALSA/Sequencer/Marshal/Queue.hsc view
@@ -13,37 +13,66 @@ -- Here we have the various types used by the library, -- and how they are imported\/exported to C. ----- NOTE: In the translations bellow we make the following assumptions--- about the sizes of C types.--- CChar  = 8 bits--- CShort = 16 bit--- CInt   = 32 bits+-- We use Hsc for expanding C types to Haskell types like Word32.+-- However if a C type is translated to Word32+-- you should not assume that it is translated to Word32 on every platform.+-- On a 64bit machine it may well be Word64.+-- Thus you should use our wrapper types whereever possible. --------------------------------------------------------------------------------  module Sound.ALSA.Sequencer.Marshal.Queue where  #include <alsa/asoundlib.h>+#include <Sound/ALSA/Sequencer/Marshal/Template.h>+ import qualified Sound.ALSA.Sequencer.Utility as U-import Foreign.C.Types (CInt, )-import Foreign.Storable (Storable, )-import Data.Word (Word8, ) +import qualified Foreign.C.Types as C+import Foreign.Storable (Storable, sizeOf, alignment, peek, peekByteOff, poke, pokeByteOff, ) +import Data.Array (Ix, ) +import qualified Data.Word as Word +++ -- | The type of queue identifiers.-newtype T = Cons Word8 deriving (Eq, Ord, Storable)+newtype T =+   Cons #{intfieldtype snd_seq_event_t, queue}+      deriving (Eq, Ord, Storable)  instance Show T where    showsPrec prec (Cons x) =       U.showsRecord prec "Queue" [U.showsField x] -imp :: CInt -> T+imp :: C.CInt -> T imp x = Cons (fromIntegral x) -exp :: T -> CInt+exp :: T -> C.CInt exp (Cons x) = fromIntegral x  #{enum T, Cons  , direct = SND_SEQ_QUEUE_DIRECT  }+++data Skew =+   Skew {+      skewValue :: ! #{intfieldtype snd_seq_queue_skew_t, value},+      skewBase  :: ! #{intfieldtype snd_seq_queue_skew_t, base}+   } deriving (Show, Eq)++instance Storable Skew where+  sizeOf _    = #{size snd_seq_queue_skew_t}+  alignment _ = #{alignment snd_seq_queue_skew_t}+  peek p      = do v <- #{peek snd_seq_queue_skew_t, value} p+                   b <- #{peek snd_seq_queue_skew_t, base}  p+                   return Skew { skewValue = v+                               , skewBase  = b+                               }+  poke p v    = #{poke snd_seq_queue_skew_t, value} p (skewValue v)+             >> #{poke snd_seq_queue_skew_t, base}  p (skewBase  v)+++#{newintfieldtype "Position", snd_seq_ev_queue_control_t, param.position}
− src/Sound/ALSA/Sequencer/Marshal/QueueTimer.hsc
@@ -1,46 +0,0 @@------------------------------------------------------------------------------------ |--- Module    : Sound.ALSA.Sequencer.Marshal.QueueTimer--- Copyright : (c) Henning Thielemann, 2010---             (c) Iavor S. Diatchki, 2007--- License   : BSD3------ Maintainer: Henning Thielemann--- Stability : provisional------ PRIVATE MODULE.------ Here we have the various types used by the library,--- and how they are imported\/exported to C.------ NOTE: In the translations bellow we make the following assumptions--- about the sizes of C types.--- CChar  = 8 bits--- CShort = 16 bit--- CInt   = 32 bits-----------------------------------------------------------------------------------module Sound.ALSA.Sequencer.Marshal.QueueTimer where--#include <alsa/asoundlib.h>-import Foreign.C.Types (CInt, )---data Type =-     Alsa-   | MidiClock-   | MidiTick-   deriving (Show, Eq, Ord, Enum)--expType :: Type -> CInt-expType t  = case t of-  Alsa       -> #{const SND_SEQ_TIMER_ALSA}-  MidiClock  -> #{const SND_SEQ_TIMER_MIDI_CLOCK}-  MidiTick   -> #{const SND_SEQ_TIMER_MIDI_TICK}--impType :: CInt -> Type-impType t  = case t of-  #{const SND_SEQ_TIMER_ALSA}         -> Alsa-  #{const SND_SEQ_TIMER_MIDI_CLOCK}   -> MidiClock-  #{const SND_SEQ_TIMER_MIDI_TICK}    -> MidiTick-  _ -> error ("QueueTimer.impType: unknown timer type (" ++ show t ++ ")")
src/Sound/ALSA/Sequencer/Marshal/RealTime.hsc view
@@ -1,18 +1,20 @@ module Sound.ALSA.Sequencer.Marshal.RealTime where  #include <alsa/asoundlib.h>+#include <Sound/ALSA/Sequencer/Marshal/Template.h>  import qualified Sound.ALSA.Sequencer.Utility as U +import qualified Data.Word as Word import Foreign.Storable           (Storable, sizeOf, alignment, peek, poke, pokeByteOff, peekByteOff, )-import Data.Word (Word32, )   data T = Cons-   { secs :: !Word32-   , nano :: !Word32+   { secs :: ! #{intfieldtype snd_seq_real_time_t, tv_sec}+   , nano :: ! #{intfieldtype snd_seq_real_time_t, tv_nsec}    }+   deriving (Eq)  instance Show T where    showsPrec prec (Cons s n) =@@ -21,7 +23,7 @@  instance Storable T where   sizeOf _    = #{size snd_seq_real_time_t}-  alignment _ = 4 -- XXX+  alignment _ = #{alignment snd_seq_real_time_t}   peek p      = do s <- #{peek snd_seq_real_time_t, tv_sec} p                    n <- #{peek snd_seq_real_time_t, tv_nsec} p                    return Cons { secs = s, nano = n }
src/Sound/ALSA/Sequencer/Marshal/Sequencer.hsc view
@@ -12,25 +12,19 @@ -- -- Here we have the various types used by the library, -- and how they are imported\/exported to C.------ NOTE: In the translations bellow we make the following assumptions--- about the sizes of C types.--- CChar  = 8 bits--- CShort = 16 bit--- CInt   = 32 bits --------------------------------------------------------------------------------  module Sound.ALSA.Sequencer.Marshal.Sequencer where  #include <alsa/asoundlib.h>-import Foreign.C.Types (CInt, )+import qualified Foreign.C.Types as C import Foreign.Ptr (Ptr, )   -- | Read\/Write permissions for the sequencer device. -- This way we prevent the ALSA exception 22 "Invalid argument" -- when calling @event_output@ on an input-only sequencer.-class OpenMode mode where expOpenMode :: mode -> CInt+class OpenMode mode where expOpenMode :: mode -> C.CInt  class OpenMode mode => AllowInput  mode where class OpenMode mode => AllowOutput mode where@@ -54,7 +48,7 @@                     | Nonblock  -- ^ Throw exceptions instead of blocking.                       deriving (Show,Eq) -expBlockMode      :: BlockMode -> CInt+expBlockMode      :: BlockMode -> C.CInt expBlockMode x     = case x of   Block     -> 0   Nonblock  -> #{const SND_SEQ_NONBLOCK}
+ src/Sound/ALSA/Sequencer/Marshal/Template.h view
@@ -0,0 +1,31 @@+#include <stdio.h>++#define hsc_alignment(t) \+    printf("(%ld)", (unsigned long)offsetof(struct {char x__; t (y__); }, y__));++#define hsc_inttype(t) \+    printf ("%s%lu",                                    \+            (t)(-1) < (t)0 ? "Int.Int" : "Word.Word",   \+            (unsigned long)sizeof (t) * 8);             \++#define hsc_intfieldtype(r,f) \+    { \+        r x, y;    \+        x.f = -1;  \+        y.f = 0;   \+        printf ("%s%lu",                               \+                x.f < y.f ? "Int.Int" : "Word.Word",   \+                (unsigned long)sizeof (x.f) * 8);      \+    }++#define hsc_newinttype(nm,t) \+    printf ("newtype "nm" = "nm" { un"nm" :: "); \+    hsc_inttype(t); \+    printf (" }\n"); \+    printf (" deriving (Show, Eq, Ord, Ix, Storable)\n");++#define hsc_newintfieldtype(nm,r,f) \+    printf ("newtype "nm" = "nm" { un"nm" :: "); \+    hsc_intfieldtype(r,f); \+    printf (" }\n"); \+    printf (" deriving (Show, Eq, Ord, Ix, Storable)\n");
+ src/Sound/ALSA/Sequencer/Marshal/Time.hsc view
@@ -0,0 +1,107 @@+module Sound.ALSA.Sequencer.Marshal.Time where++#include <alsa/asoundlib.h>+#include <Sound/ALSA/Sequencer/Marshal/Template.h>++import qualified Sound.ALSA.Sequencer.Marshal.RealTime as RealTime++import qualified Sound.ALSA.Sequencer.Utility as U+import qualified Foreign.Storable as St+-- import qualified Foreign.C.Types as C+import Foreign.Ptr (Ptr, castPtr, )+import qualified Data.FlagSet as FlagSet+import qualified Data.Word as Word+import Data.Monoid (mappend, )++import qualified Data.Accessor.Basic as Acc+++data T = Cons {mode :: Mode, stamp :: Stamp}++instance Show T where+   showsPrec prec (Cons m st) =+      U.showsRecord prec "Time"+         [U.showsField m, U.showsField st]+++consAbs :: Stamp -> T+consAbs = Cons Absolute++consRel :: Stamp -> T+consRel = Cons Relative+++modeAcc :: Acc.T T Mode+modeAcc =+   Acc.fromSetGet (\x ev -> ev{mode = x}) mode++stampAcc :: Acc.T T Stamp+stampAcc =+   Acc.fromSetGet (\x ev -> ev{stamp = x}) stamp+++type Tick = #{inttype snd_seq_tick_time_t}++data Mode = Absolute | Relative+   deriving (Eq, Show, Enum)++data Stamp =+     Tick !Tick+   | Real !RealTime.T+     deriving Show+++class Flag flag where++type FlagContainer = #{intfieldtype snd_seq_event_t, flags}++stampTick, stampReal :: Flag flag => FlagSet.MaskedValue FlagContainer flag+stampTick =+   FlagSet.MaskedValue+      #{const SND_SEQ_TIME_STAMP_MASK}+      #{const SND_SEQ_TIME_STAMP_TICK}+stampReal =+   FlagSet.MaskedValue+      #{const SND_SEQ_TIME_STAMP_MASK}+      #{const SND_SEQ_TIME_STAMP_REAL}+++modeAbs, modeRel :: Flag flag => FlagSet.MaskedValue FlagContainer flag+modeAbs =+   FlagSet.MaskedValue+      #{const SND_SEQ_TIME_MODE_MASK}+      #{const SND_SEQ_TIME_MODE_ABS}+modeRel =+   FlagSet.MaskedValue+      #{const SND_SEQ_TIME_MODE_MASK}+      #{const SND_SEQ_TIME_MODE_REL}+++peek :: Flag flag => FlagSet.T FlagContainer flag -> Ptr T -> IO T+peek flags p =+   fmap+      (Cons+         (if FlagSet.match flags modeAbs+            then Absolute+            else Relative)) $+   peekStamp flags $ castPtr p++poke :: Flag flag => Ptr T -> T -> IO (FlagSet.MaskedValue FlagContainer flag)+poke p (Cons m st) =+   fmap (mappend+      (case m of+         Absolute -> modeAbs+         Relative -> modeRel)) $+   pokeStamp (castPtr p) st+++peekStamp :: Flag flag => FlagSet.T FlagContainer flag -> Ptr Stamp -> IO Stamp+peekStamp flags p =+   if FlagSet.match flags stampTick+     then fmap Tick $ St.peek $ castPtr p+     else fmap Real $ St.peek $ castPtr p++pokeStamp :: Flag flag => Ptr Stamp -> Stamp -> IO (FlagSet.MaskedValue FlagContainer flag)+pokeStamp p ts = case ts of+   Tick t -> St.poke (castPtr p) t >> return stampTick+   Real t -> St.poke (castPtr p) t >> return stampReal
+ src/Sound/ALSA/Sequencer/Poll.hs view
@@ -0,0 +1,29 @@+module Sound.ALSA.Sequencer.Poll+  ( descriptors+  ) where++import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified System.Posix.Poll as Poll++import qualified Foreign.C.Types as C+import Foreign.Marshal.Array (peekArray, allocaArray, )+import Foreign.Ptr (Ptr, )++-- expose EnumSet.Cons for foreign call+import qualified Data.EnumSet as EnumSet++_dummyEnumSet :: EnumSet.T Int Bool+_dummyEnumSet = undefined+++descriptors :: Seq.T mode -> Poll.Events -> IO [Poll.Fd]+descriptors (Seq.Cons h) e = do+  n <- snd_seq_poll_descriptors_count h e+  allocaArray (fromIntegral n) $ \p ->+    flip peekArray p . fromIntegral =<< snd_seq_poll_descriptors h p n e++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_poll_descriptors_count"+  snd_seq_poll_descriptors_count :: Ptr Seq.Core -> Poll.Events -> IO C.CInt++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_poll_descriptors"+  snd_seq_poll_descriptors :: Ptr Seq.Core -> Ptr Poll.Fd -> C.CInt -> Poll.Events -> IO C.CInt
src/Sound/ALSA/Sequencer/Port.hs view
@@ -14,7 +14,7 @@ --------------------------------------------------------------------------------  module Sound.ALSA.Sequencer.Port-  ( Port.T+  ( Port.T(Port.Cons)   , create   , createSimple   , delete@@ -60,14 +60,16 @@   ) where  import qualified Sound.ALSA.Sequencer.Marshal.Port as Port+import qualified Sound.ALSA.Sequencer.Marshal.PortInfo as PortInfo import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq import qualified Sound.ALSA.Exception as Exc-import Sound.ALSA.Sequencer.Area -import Foreign.C.Types (CInt, )+import qualified Foreign.C.Types as C import Foreign.C.String (CString, withCAString, ) import Foreign.Ptr (Ptr, ) +import qualified Data.EnumSet as EnumSet -- expose EnumSet.Cons for foreign call+ import Control.Exception (bracket, )  @@ -82,7 +84,7 @@  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_create_simple_port"   snd_seq_create_simple_port :: Ptr Seq.Core -> CString -> Port.Cap -> Port.Type-                                -> IO CInt+                                -> IO C.CInt   -- | Delete the port.@@ -91,7 +93,7 @@   Exc.checkResult_ "delete_simple_port" =<< snd_seq_delete_simple_port h (fromIntegral p)  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_delete_simple_port"-  snd_seq_delete_simple_port :: Ptr Seq.Core -> CInt -> IO CInt+  snd_seq_delete_simple_port :: Ptr Seq.Core -> C.CInt -> IO C.CInt   withSimple ::@@ -106,12 +108,12 @@ --------------------------------------------------------------------------------  -- | Create a new port, as described by the info structure.-create :: Seq.T mode -> PortInfo -> IO ()+create :: Seq.T mode -> PortInfo.T -> IO () create (Seq.Cons h) p =-  Exc.checkResult_ "create_port" =<< with_port_info p (snd_seq_create_port h)+  Exc.checkResult_ "create_port" =<< PortInfo.with p (snd_seq_create_port h)  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_create_port"-  snd_seq_create_port :: Ptr Seq.Core -> Ptr PortInfo_ -> IO CInt+  snd_seq_create_port :: Ptr Seq.Core -> Ptr PortInfo.T_ -> IO C.CInt  -- | Delete the port. delete :: Seq.T mode -> Port.T -> IO ()@@ -119,4 +121,9 @@   Exc.checkResult_ "delete_port" =<< snd_seq_delete_port h (fromIntegral p)  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_delete_port"-  snd_seq_delete_port :: Ptr Seq.Core -> CInt -> IO CInt+  snd_seq_delete_port :: Ptr Seq.Core -> C.CInt -> IO C.CInt++++_dummyEnumSet :: EnumSet.T Int Bool+_dummyEnumSet = undefined
src/Sound/ALSA/Sequencer/Port/Info.hs view
@@ -1,7 +1,7 @@ -------------------------------------------------------------------------------- -- |--- Module    : Sound.ALSA.Sequencer.Port--- Copyright : (c) Henning Thielemann, 2010+-- Module    : Sound.ALSA.Sequencer.Port.Info+-- Copyright : (c) Henning Thielemann, 2010-2012 --             (c) Iavor S. Diatchki, 2007 -- License   : BSD3 --@@ -20,6 +20,8 @@   , getAny   , queryFirst   , queryNext+  , queryLoop_+  , queryLoop   , set    , copy@@ -55,152 +57,16 @@   , setTimestampQueue   ) where +import Sound.ALSA.Sequencer.Marshal.PortInfo+ import qualified Sound.ALSA.Sequencer.Marshal.Client as Client-import qualified Sound.ALSA.Sequencer.Marshal.Port as Port-import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq-import qualified Sound.ALSA.Sequencer.Area as Area-import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr-import qualified Sound.ALSA.Exception as Exc -import Foreign.C.Types (CInt, )-import Foreign.Ptr (Ptr, )-import Foreign.Marshal.Alloc (alloca, )-import Foreign.Storable (poke, peek, )-import Data.Word (Word, )---type T = Area.PortInfo-type T_ = Area.PortInfo_----- | Create a new information area filled with data about a specific--- port on our client.-get :: Seq.T mode -> Port.T -> IO T-get (Seq.Cons h) p =-  do info <- Area.port_info_malloc-     Exc.checkResult_ "get_port_info" =<< Area.with_port_info info (snd_seq_get_port_info h (Port.exp p))-     return info--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_get_port_info"-  snd_seq_get_port_info :: Ptr Seq.Core -> CInt -> Ptr T_ -> IO CInt----- | Create a new information area filled with data about an given--- port on a given client.-getAny :: Seq.T mode -> Client.T -> Port.T -> IO T-getAny (Seq.Cons h) c p =-  do info <- Area.port_info_malloc-     Exc.checkResult_ "get_any_port_info" =<< Area.with_port_info info-                       (snd_seq_get_any_port_info h (Client.exp c) (Port.exp p))-     return info--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_get_any_port_info"-  snd_seq_get_any_port_info-    :: Ptr Seq.Core -> CInt -> CInt -> Ptr T_ -> IO CInt---- | Get information about the first port on our client.-queryFirst  :: Seq.T mode -> IO T-queryFirst s =-  do x <- Area.port_info_malloc-     Area.with_port_info x (`Area.snd_seq_port_info_set_port` (-1))-     queryNext s x-     return x----- | Get information about the port with the next biggest identifier.--- If a matching port is found, then its information is stored in the--- given area, otherwise we throw an error.-queryNext :: Seq.T mode -> T -> IO ()-queryNext (Seq.Cons h) info =-   Exc.checkResult_ "query_next_port" =<< Area.with_port_info info (snd_seq_query_next_port h)--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_query_next_port"-  snd_seq_query_next_port :: Ptr Seq.Core -> Ptr T_ -> IO CInt---- | Set the information for the sequencer port based on the data--- in the given information area.-set :: Seq.T mode -> Port.T -> T -> IO ()-set (Seq.Cons h) p info =-  Exc.checkResult_ "set_port_info" =<< Area.with_port_info info (snd_seq_set_port_info h (Port.exp p))--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_set_port_info"-  snd_seq_set_port_info :: Ptr Seq.Core -> CInt -> Ptr T_ -> IO CInt------ | Get the address of the information area.-getAddr :: T -> IO Addr.T-getAddr i =-  peek =<< Area.with_port_info i snd_seq_port_info_get_addr--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_port_info_get_addr"-  snd_seq_port_info_get_addr :: Ptr T_ -> IO (Ptr Addr.T)----- | Set the port address.-setAddr :: T -> Addr.T -> IO ()-setAddr i c =-  alloca $ \p -> poke p c >> Area.with_port_info i (`snd_seq_port_info_set_addr` p)--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_port_info_set_addr"-  snd_seq_port_info_set_addr :: Ptr T_ -> Ptr Addr.T -> IO ()-+import qualified Sound.ALSA.Sequencer.Query as Query  -copy :: T -> T -> IO ()-clone :: T -> IO T-getPort :: T -> IO Port.T-getClient :: T -> IO Client.T-getName :: T -> IO String-getCapability :: T -> IO Port.Cap-getMidiChannels :: T -> IO Word-getMidiVoices :: T -> IO Word-getSynthVoices :: T -> IO Word-getPortSpecified :: T -> IO Bool-getTimestamping :: T -> IO Bool-getTimestampReal :: T -> IO Bool-getTimestampQueue :: T -> IO Queue.T-getReadUse :: T -> IO Word-getWriteUse :: T -> IO Word-setPort :: T -> Port.T -> IO ()-setClient :: T -> Client.T -> IO ()-setName :: T -> String -> IO ()-setCapability :: T -> Port.Cap -> IO ()-setMidiChannels :: T -> Word -> IO ()-setSynthVoices :: T -> Word -> IO ()-setMidiVoices :: T -> Word -> IO ()-setPortSpecified :: T -> Bool -> IO ()-setTimestamping :: T -> Bool -> IO ()-setTimestampReal :: T -> Bool -> IO ()-setTimestampQueue :: T -> Queue.T -> IO ()--copy              = Area.port_info_copy-clone             = Area.port_info_clone--getPort           = Area.port_info_get_port-getClient         = Area.port_info_get_client-getName           = Area.port_info_get_name-getCapability     = Area.port_info_get_capability-getMidiChannels   = Area.port_info_get_midi_channels-getMidiVoices     = Area.port_info_get_midi_voices-getSynthVoices    = Area.port_info_get_synth_voices-getPortSpecified  = Area.port_info_get_port_specified-getTimestamping   = Area.port_info_get_timestamping-getTimestampReal  = Area.port_info_get_timestamp_real-getTimestampQueue = Area.port_info_get_timestamp_queue--getReadUse        = Area.port_info_get_read_use-getWriteUse       = Area.port_info_get_write_use+queryLoop_ :: Seq.T mode -> Client.T -> (T -> IO ()) -> IO ()+queryLoop_ h c = Query.loop_ h (flip setClient c) -setPort           = Area.port_info_set_port-setClient         = Area.port_info_set_client-setName           = Area.port_info_set_name-setCapability     = Area.port_info_set_capability-setMidiChannels   = Area.port_info_set_midi_channels-setSynthVoices    = Area.port_info_set_synth_voices-setMidiVoices     = Area.port_info_set_midi_voices-setPortSpecified  = Area.port_info_set_port_specified-setTimestamping   = Area.port_info_set_timestamping-setTimestampReal  = Area.port_info_set_timestamp_real-setTimestampQueue = Area.port_info_set_timestamp_queue+queryLoop :: Seq.T mode -> Client.T -> (T -> IO a) -> IO [a]+queryLoop h c = Query.loop h (flip setClient c)
+ src/Sound/ALSA/Sequencer/Port/InfoMonad.hs view
@@ -0,0 +1,147 @@+--------------------------------------------------------------------------------+-- |+-- Module    : Sound.ALSA.Sequencer.Port.Info+-- Copyright : (c) Henning Thielemann, 2010-2012+--             (c) Iavor S. Diatchki, 2007+-- License   : BSD3+--+-- Maintainer: Henning Thielemann+-- Stability : provisional+--+-- This module contains functions for working with ports.+-- Reference:+-- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_port.html>+--------------------------------------------------------------------------------++module Sound.ALSA.Sequencer.Port.InfoMonad (+  T,++  run,+  get,+  modify,++  getPort,+  getClient,+  getAddr,+  getName,+  getCapability,+  getMidiChannels,+  getMidiVoices,+  getSynthVoices,+  getPortSpecified,+  getTimestamping,+  getTimestampReal,+  getTimestampQueue,++  getReadUse,+  getWriteUse,++  setPort,+  setClient,+  setAddr,+  setName,+  setCapability,+  setMidiChannels,+  setSynthVoices,+  setMidiVoices,+  setPortSpecified,+  setTimestamping,+  setTimestampReal,+  setTimestampQueue,+  ) where++import qualified Sound.ALSA.Sequencer.Marshal.PortInfo as PortInfo+import qualified Sound.ALSA.Sequencer.Marshal.Port as Port+import qualified Sound.ALSA.Sequencer.Marshal.Client as Client+import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue+import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr+import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq++import qualified Control.Monad.Trans.Reader as MR+import Control.Applicative (Applicative, )++import Data.Word (Word, )+++newtype T a = Cons (MR.ReaderT PortInfo.T IO a)+   deriving (Functor, Applicative, Monad)+++run :: T a -> PortInfo.T -> IO a+run (Cons m) = MR.runReaderT m++get :: Seq.T mode -> Port.T -> T a -> IO a+get h p m = run m =<< PortInfo.get h p++modify :: Seq.T mode -> Port.T -> T a -> IO a+modify h p m = do+  i <- PortInfo.get h p+  a <- run m i+  PortInfo.set h p i+  return a+++liftGet :: (PortInfo.T -> IO a) -> T a+liftGet f = Cons $ MR.ReaderT f++liftSet :: (PortInfo.T -> b -> IO a) -> b -> T a+liftSet f x = Cons $ MR.ReaderT $ flip f x+++getPort :: T Port.T+getClient :: T Client.T+getAddr :: T Addr.T+getName :: T String+getCapability :: T Port.Cap+getMidiChannels :: T Word+getMidiVoices :: T Word+getSynthVoices :: T Word+getPortSpecified :: T Bool+getTimestamping :: T Bool+getTimestampReal :: T Bool+getTimestampQueue :: T Queue.T+getReadUse :: T Word+getWriteUse :: T Word++getPort           = liftGet PortInfo.getPort+getClient         = liftGet PortInfo.getClient+getAddr           = liftGet PortInfo.getAddr+getName           = liftGet PortInfo.getName+getCapability     = liftGet PortInfo.getCapability+getMidiChannels   = liftGet PortInfo.getMidiChannels+getMidiVoices     = liftGet PortInfo.getMidiVoices+getSynthVoices    = liftGet PortInfo.getSynthVoices+getPortSpecified  = liftGet PortInfo.getPortSpecified+getTimestamping   = liftGet PortInfo.getTimestamping+getTimestampReal  = liftGet PortInfo.getTimestampReal+getTimestampQueue = liftGet PortInfo.getTimestampQueue++getReadUse        = liftGet PortInfo.getReadUse+getWriteUse       = liftGet PortInfo.getWriteUse+++setPort :: Port.T -> T ()+setClient :: Client.T -> T ()+setAddr :: Addr.T -> T ()+setName :: String -> T ()+setCapability :: Port.Cap -> T ()+setMidiChannels :: Word -> T ()+setSynthVoices :: Word -> T ()+setMidiVoices :: Word -> T ()+setPortSpecified :: Bool -> T ()+setTimestamping :: Bool -> T ()+setTimestampReal :: Bool -> T ()+setTimestampQueue :: Queue.T -> T ()++setPort           = liftSet PortInfo.setPort+setClient         = liftSet PortInfo.setClient+setAddr           = liftSet PortInfo.setAddr+setName           = liftSet PortInfo.setName+setCapability     = liftSet PortInfo.setCapability+setMidiChannels   = liftSet PortInfo.setMidiChannels+setSynthVoices    = liftSet PortInfo.setSynthVoices+setMidiVoices     = liftSet PortInfo.setMidiVoices+setPortSpecified  = liftSet PortInfo.setPortSpecified+setTimestamping   = liftSet PortInfo.setTimestamping+setTimestampReal  = liftSet PortInfo.setTimestampReal+setTimestampQueue = liftSet PortInfo.setTimestampQueue
+ src/Sound/ALSA/Sequencer/Query.hs view
@@ -0,0 +1,47 @@+module Sound.ALSA.Sequencer.Query (+  C,+  init,+  next,+  first,+  loop_,+  loop,+  ) where++import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified Sound.ALSA.Sequencer.Area as Area++import Control.Monad (liftM2, when, )++import Prelude hiding (init, )+++class Area.C info => C info where+  init :: info -> IO ()+  next :: Seq.T mode -> info -> IO Bool++first :: (C info) => Seq.T mode -> IO info+first h = do+  i <- Area.malloc+  init i+  _b <- next h i+  return i++loop_ :: (C info) => Seq.T mode -> (info -> IO ()) -> (info -> IO ()) -> IO ()+loop_ h start f = do+  i <- Area.malloc+  start i+  init i+  let go = do+         b <- next h i+         when b $ f i >> go+  go++loop :: (C info) => Seq.T mode -> (info -> IO ()) -> (info -> IO a) -> IO [a]+loop h start f = do+  i <- Area.malloc+  start i+  init i+  let go = do+         b <- next h i+         if b then liftM2 (:) (f i) go else return []+  go
src/Sound/ALSA/Sequencer/Queue.hs view
@@ -1,7 +1,7 @@ -------------------------------------------------------------------------------- -- | -- Module    : Sound.ALSA.Sequencer.Queue--- Copyright : (c) Henning Thielemann, 2010+-- Copyright : (c) Henning Thielemann, 2010-2012 --             (c) Iavor S. Diatchki, 2007 -- License   : BSD3 --@@ -27,23 +27,26 @@   ) where  import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr import qualified Sound.ALSA.Sequencer.Marshal.Event as Event import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue+import qualified Sound.ALSA.Sequencer.Marshal.Time as Time import qualified Sound.ALSA.Exception as Exc -import Foreign.Ptr (Ptr, )-import Foreign.C.Types (CInt, )+import qualified Foreign.C.Types as C import Foreign.C.String (CString, withCAString, )+import Foreign.Ptr (Ptr, )  import Control.Exception (bracket, )+import Control.Functor.HT (void, )   alloc :: Seq.T mode -> IO Queue.T -- ^ Queue.T identifier. alloc (Seq.Cons h) =-  Queue.imp `fmap` (Exc.checkResult "alloc_queue" =<< snd_seq_alloc_queue h)+  fmap Queue.imp $ Exc.checkResult "Queue.alloc" =<< alloc_ h  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_alloc_queue"-  snd_seq_alloc_queue :: Ptr Seq.Core -> IO CInt+  alloc_ :: Ptr Seq.Core -> IO C.CInt  with :: Seq.T mode -> (Queue.T -> IO a) -> IO a with s = bracket (alloc s) (free s)@@ -51,10 +54,10 @@  allocNamed :: Seq.T mode -> String -> IO Queue.T allocNamed (Seq.Cons h) x = withCAString x $ \s ->-  Queue.imp `fmap` (Exc.checkResult "alloc_named_queue" =<< snd_seq_alloc_named_queue h s)+  fmap Queue.imp $ Exc.checkResult "Queue.allocNamed" =<< allocNamed_ h s  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_alloc_named_queue"-  snd_seq_alloc_named_queue :: Ptr Seq.Core -> CString -> IO CInt+  allocNamed_ :: Ptr Seq.Core -> CString -> IO C.CInt  withNamed :: Seq.T mode -> String -> (Queue.T -> IO a) -> IO a withNamed s nm = bracket (allocNamed s nm) (free s)@@ -66,22 +69,72 @@   -> Queue.T    -- ^ Queue.T identifier.   -> IO () free (Seq.Cons h) q =-  Exc.checkResult_ "free_queue" =<< snd_seq_free_queue h (Queue.exp q)+  Exc.checkResult_ "Queue.free" =<< free_ h (Queue.exp q)  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_free_queue"-  snd_seq_free_queue :: Ptr Seq.Core -> CInt -> IO CInt+  free_ :: Ptr Seq.Core -> C.CInt -> IO C.CInt  --- | Queue.T controls - start/stop/continue+{- |+start/stop/continue a queue++In the prototype event you can provide additional information.+The prototype event does not need to be a queue control event,+this part is ignored anyway.+In the prototype event you may also specify a queue.+This is the queue that the timestamp of the prototype event refers to.+This way you can control the target queue using timing from another queue.+-} control-  :: Seq.T mode   -- ^ Sequencer handle.-  -> Queue.T         -- ^ Queue.T identifier.+  :: Seq.T mode    -- ^ Sequencer handle.+  -> Queue.T       -- ^ target Queue.T.   -> Event.QueueEv-  -> Int-  -> Maybe Event.T+  -> Maybe Event.T -- ^ prototype event that may provide timestamp, source queue   -> IO ()-control (Seq.Cons h) q a b me =-  Event.allocaMaybeEv me $ \p -> Exc.checkResult_ "control_queue" =<< snd_seq_control_queue h (Queue.exp q) (fromIntegral $ Event.expEv a) (fromIntegral b) p+control h q cmd me =+  case cmd of+    Event.QueueSetPosTick _ -> controlCustom h q cmd me+    Event.QueueSetPosTime _ -> controlCustom h q cmd me+    Event.QueueSkew _       -> controlCustom h q cmd me+    _ -> controlPlain h q cmd me +controlCustom, controlPlain ::+  Seq.T mode -> Queue.T -> Event.QueueEv -> Maybe Event.T -> IO ()+controlCustom h q cmd me =+  eventOutput h $+    case me of+      Nothing ->+        -- cf. Event.simple+        Event.Cons {+          Event.highPriority = False,+          Event.tag = Event.Tag 0,+          Event.queue = Queue.direct,+          Event.time = Time.consAbs $ Time.Tick 0,+          Event.source = Addr.unknown,+          Event.dest = Addr.systemTimer,+          Event.body = Event.QueueEv cmd q+        }+      Just ev ->+        ev {+          Event.dest = Addr.systemTimer,+          Event.body = Event.QueueEv cmd q+        }++eventOutput :: Seq.T mode -> Event.T -> IO ()+eventOutput h e =+  void $+  Event.with e $ \p ->+     Exc.checkResult "Queue.control.eventOutput" =<< eventOutput_ h p++foreign import ccall safe "alsa/asoundlib.h snd_seq_event_output"+  eventOutput_ :: Seq.T mode -> Ptr Event.T -> IO C.CInt++controlPlain h q cmd me =+  Event.withMaybe me $ \p ->+    let (c,v) = Event.expQueueEv cmd+    in  Exc.checkResult_ "Queue.control"+          =<< control_ h (Queue.exp q)+                 (fromIntegral $ Event.unEType c) v p+ foreign import ccall unsafe "alsa/asoundlib.h snd_seq_control_queue"-  snd_seq_control_queue :: Ptr Seq.Core -> CInt -> CInt -> CInt -> Ptr Event.T -> IO CInt+  control_ :: Seq.T mode -> C.CInt -> C.CInt -> C.CInt -> Ptr Event.T -> IO C.CInt
− src/Sound/ALSA/Sequencer/Queue/Info.hs
@@ -1,95 +0,0 @@------------------------------------------------------------------------------------ |--- Module    : Sound.ALSA.Sequencer.Queue.Info--- Copyright : (c) Henning Thielemann, 2010---             (c) Iavor S. Diatchki, 2007--- License   : BSD3------ Maintainer: Henning Thielemann--- Stability : provisional------ This module contains functions for working with sequencer queue.--- Reference:--- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_queue.html>-----------------------------------------------------------------------------------module Sound.ALSA.Sequencer.Queue.Info-  ( T-  , get-  , set-  , copy-  , clone--  , getQueue-  , getName-  , getLocked-  , getOwner-  , getFlags--  , setName-  , setLocked-  , setOwner-  , setFlags-  ) where--import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq-import qualified Sound.ALSA.Sequencer.Marshal.Client as Client-import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue-import qualified Sound.ALSA.Sequencer.Area as Area-import qualified Sound.ALSA.Exception as Exc--import Foreign.Ptr (Ptr, )-import Foreign.C.Types (CInt, )-import Data.Word (Word, )---type T = Area.QueueInfo-type T_ = Area.QueueInfo_----- XXX: Lots of duplication.--get :: Seq.T mode -> Queue.T -> IO T-get (Seq.Cons h) q =-  do info <- Area.queue_info_malloc-     Exc.checkResult_ "get_queue_info" =<< Area.with_queue_info info-                                     (snd_seq_get_queue_info h (Queue.exp q))-     return info--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_get_queue_info"-  snd_seq_get_queue_info :: Ptr Seq.Core -> CInt -> Ptr T_ -> IO CInt---set :: Seq.T mode -> Queue.T -> T -> IO ()-set (Seq.Cons h) p info =-  Exc.checkResult_ "set_queue_info" =<< Area.with_queue_info info (snd_seq_set_queue_info h (Queue.exp p))--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_set_queue_info"-  snd_seq_set_queue_info :: Ptr Seq.Core -> CInt -> Ptr T_ -> IO CInt---copy :: T -> T -> IO ()-clone :: T -> IO T-getQueue :: T -> IO Queue.T-getName :: T -> IO String-getLocked :: T -> IO Bool-getOwner :: T -> IO Client.T-getFlags :: T -> IO Word-setName :: T -> String -> IO ()-setLocked :: T -> Bool -> IO ()-setOwner :: T -> Client.T -> IO ()-setFlags :: T -> Word -> IO ()--copy       = Area.queue_info_copy-clone      = Area.queue_info_clone--getQueue   = Area.queue_info_get_queue-getName    = Area.queue_info_get_name-getLocked  = Area.queue_info_get_locked-getOwner   = Area.queue_info_get_owner-getFlags   = Area.queue_info_get_flags--setName    = Area.queue_info_set_name-setLocked  = Area.queue_info_set_locked-setOwner   = Area.queue_info_set_owner-setFlags   = Area.queue_info_set_flags
+ src/Sound/ALSA/Sequencer/Queue/Info.hsc view
@@ -0,0 +1,61 @@+--------------------------------------------------------------------------------+-- |+-- Module    : Sound.ALSA.Sequencer.Queue.Info+-- Copyright : (c) Henning Thielemann, 2010-2012+--             (c) Iavor S. Diatchki, 2007+-- License   : BSD3+--+-- Maintainer: Henning Thielemann+-- Stability : provisional+--+-- This module contains functions for working with sequencer queue.+-- Reference:+-- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_queue.html>+--------------------------------------------------------------------------------++module Sound.ALSA.Sequencer.Queue.Info+  ( T+  , get+  , set+  , copy+  , clone++  , getQueue+  , getName+  , getLocked+  , getOwner+  , getFlags++  , setName+  , setLocked+  , setOwner+  , setFlags+  ) where++#include <Sound/ALSA/Sequencer/Area.h>++import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified Sound.ALSA.Sequencer.Marshal.Client as Client+import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue+import qualified Sound.ALSA.Sequencer.Area as Area+import qualified Sound.ALSA.Exception as Exc++import qualified Foreign.C.Types as C+import Data.Word (Word, )+++#area "queue_info"++#{get_area "Queue.T"}+#{set_area "Queue.T"}+++#{get_set_name}+#{get_set_bool "locked", "Locked"}++#{get_set_int "owner", "Owner", "Client.T", "Client.imp", "Client.exp"}+#{get_set_int "flags", "Flags", "Word", "fromIntegral", "fromIntegral"}+++-- RO+#{get_int "queue", "Queue", "Queue.T", "Queue.imp"}
− src/Sound/ALSA/Sequencer/Queue/Status.hs
@@ -1,106 +0,0 @@------------------------------------------------------------------------------------ |--- Module    : Sound.ALSA.Sequencer.Queue.Status--- Copyright : (c) Henning Thielemann, 2010---             (c) Iavor S. Diatchki, 2007--- License   : BSD3------ Maintainer: Henning Thielemann--- Stability : provisional------ This module contains functions for working with sequencer queue.--- Reference:--- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_queue.html>-----------------------------------------------------------------------------------module Sound.ALSA.Sequencer.Queue.Status-  ( T-  , get-  , copy-  , clone--  , getQueue-  , getEvents-  , getTickTime-  , getRealTime-  ) where--import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq-import qualified Sound.ALSA.Sequencer.Marshal.RealTime as RealTime-import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue-import qualified Sound.ALSA.Sequencer.Area as Area-import qualified Sound.ALSA.Exception as Exc--import Foreign.Ptr (Ptr, )-import Foreign.C.Types (CInt, CUInt, )-import Foreign.Storable (peek, )-import Data.Word (Word32, )---type T = Area.QueueStatus-type T_ = Area.QueueStatus_---get :: Seq.T mode -> Queue.T -> IO T-get (Seq.Cons h) q =-  do status <- Area.queue_status_malloc-     Exc.checkResult_ "get_queue_status" =<< Area.with_queue_status status-                                     (snd_seq_get_queue_status h (Queue.exp q))-     return status--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_get_queue_status"-  snd_seq_get_queue_status :: Ptr Seq.Core -> CInt -> Ptr T_ -> IO CInt----copy :: T -> T -> IO ()-clone :: T -> IO T--copy  = Area.queue_status_copy-clone = Area.queue_status_clone---foreign import ccall unsafe "alsa/asoundlib.h"-   snd_seq_queue_status_get_queue-      :: Ptr T_ -> IO CInt-foreign import ccall unsafe "alsa/asoundlib.h"-   snd_seq_queue_status_get_events-      :: Ptr T_ -> IO CInt-foreign import ccall unsafe "alsa/asoundlib.h"-   snd_seq_queue_status_get_tick_time-      :: Ptr T_ -> IO Word32-foreign import ccall unsafe "alsa/asoundlib.h"-   snd_seq_queue_status_get_real_time-      :: Ptr T_ -> IO (Ptr RealTime.T)-foreign import ccall unsafe "alsa/asoundlib.h"-   snd_seq_queue_status_get_status-      :: Ptr T_ -> IO CUInt---getQueue :: T -> IO Queue.T-getQueue status =-   fmap Queue.imp $-   Area.with_queue_status status snd_seq_queue_status_get_queue--getEvents :: T -> IO Int-getEvents status =-   fmap fromIntegral $-   Area.with_queue_status status snd_seq_queue_status_get_events--getTickTime :: T -> IO Word32-getTickTime status =-   Area.with_queue_status status snd_seq_queue_status_get_tick_time--getRealTime :: T -> IO RealTime.T-getRealTime status =-   peek =<<-   Area.with_queue_status status snd_seq_queue_status_get_real_time--{--This function shall return status bits of the queue,-but the ALSA headers do not define any bits.-I would prefer a data type that handles this bitfield.--}-_getStatus :: T -> IO CUInt-_getStatus status =-   Area.with_queue_status status snd_seq_queue_status_get_status
+ src/Sound/ALSA/Sequencer/Queue/Status.hsc view
@@ -0,0 +1,56 @@+--------------------------------------------------------------------------------+-- |+-- Module    : Sound.ALSA.Sequencer.Queue.Status+-- Copyright : (c) Henning Thielemann, 2010-2012+--             (c) Iavor S. Diatchki, 2007+-- License   : BSD3+--+-- Maintainer: Henning Thielemann+-- Stability : provisional+--+-- This module contains functions for working with sequencer queue.+-- Reference:+-- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_queue.html>+--------------------------------------------------------------------------------++module Sound.ALSA.Sequencer.Queue.Status+  ( T+  , get+  , copy+  , clone++  , getQueue+  , getEvents+  , getTickTime+  , getRealTime+  ) where++#include <Sound/ALSA/Sequencer/Area.h>++import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified Sound.ALSA.Sequencer.Marshal.RealTime as RealTime+import qualified Sound.ALSA.Sequencer.Marshal.Time as Time+import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue+import qualified Sound.ALSA.Sequencer.Area as Area+import qualified Sound.ALSA.Exception as Exc++import qualified Foreign.C.Types as C+++#area "queue_status"+++#{get_area "Queue.T"}++#{get_int "tick_time", "TickTime", "Time.Tick", "fromIntegral"}+#{get_ptr "real_time", "RealTime", "RealTime.T"}+#{get_int "queue", "Queue", "Queue.T", "Queue.imp"}+#{get_int "events", "Events", "Int", "fromIntegral"}++{-+This function shall return status bits of the queue,+but the ALSA headers do not define any bits.+I would prefer a data type that handles this bitfield.++#{get_int "status", "Status", "C.CUInt", "fromIntegral"}+-}
− src/Sound/ALSA/Sequencer/Queue/Tempo.hs
@@ -1,91 +0,0 @@------------------------------------------------------------------------------------ |--- Module    : Sound.ALSA.Sequencer.Queue.Tempo--- Copyright : (c) Henning Thielemann, 2010---             (c) Iavor S. Diatchki, 2007--- License   : BSD3------ Maintainer: Henning Thielemann--- Stability : provisional------ This module contains functions for working with sequencer queue.--- Reference:--- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_queue.html>-----------------------------------------------------------------------------------module Sound.ALSA.Sequencer.Queue.Tempo-  ( T-  , get-  , set-  , copy-  , clone--  , getQueue-  , getTempo-  , getPPQ-  , getSkew-  , getSkewBase--  , setTempo-  , setPPQ-  , setSkew-  , setSkewBase-  ) where--import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue-import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq-import qualified Sound.ALSA.Sequencer.Area as Area-import qualified Sound.ALSA.Exception as Exc--import Foreign.Ptr (Ptr, )-import Foreign.C.Types (CInt, )-import Data.Word (Word, )---type T = Area.QueueTempo-type T_ = Area.QueueTempo_--get :: Seq.T mode -> Queue.T -> IO T-get (Seq.Cons h) q =-  do tempo <- Area.queue_tempo_malloc-     Exc.checkResult_ "get_queue_tempo" =<< Area.with_queue_tempo tempo-                                     (snd_seq_get_queue_tempo h (Queue.exp q))-     return tempo--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_get_queue_tempo"-  snd_seq_get_queue_tempo :: Ptr Seq.Core -> CInt -> Ptr T_ -> IO CInt---set :: Seq.T mode -> Queue.T -> T -> IO ()-set (Seq.Cons h) p tempo =-  Exc.checkResult_ "set_queue_tempo" =<< Area.with_queue_tempo tempo (snd_seq_set_queue_tempo h (Queue.exp p))--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_set_queue_tempo"-  snd_seq_set_queue_tempo :: Ptr Seq.Core -> CInt -> Ptr T_ -> IO CInt---copy :: T -> T -> IO ()-clone :: T -> IO T-getQueue :: T -> IO Queue.T-getTempo :: T -> IO Word-getPPQ :: T -> IO Int-getSkew :: T -> IO Word-getSkewBase :: T -> IO Word-setTempo :: T -> Word -> IO ()-setPPQ :: T -> Int -> IO ()-setSkew :: T -> Word -> IO ()-setSkewBase :: T -> Word -> IO ()--copy        = Area.queue_tempo_copy-clone       = Area.queue_tempo_clone--getQueue    = Area.queue_tempo_get_queue-getTempo    = Area.queue_tempo_get_tempo-getPPQ      = Area.queue_tempo_get_ppq-getSkew     = Area.queue_tempo_get_skew-getSkewBase = Area.queue_tempo_get_skew_base--setTempo    = Area.queue_tempo_set_tempo-setPPQ      = Area.queue_tempo_set_ppq-setSkew     = Area.queue_tempo_set_skew-setSkewBase = Area.queue_tempo_set_skew_base
+ src/Sound/ALSA/Sequencer/Queue/Tempo.hsc view
@@ -0,0 +1,59 @@+--------------------------------------------------------------------------------+-- |+-- Module    : Sound.ALSA.Sequencer.Queue.Tempo+-- Copyright : (c) Henning Thielemann, 2010-2012+--             (c) Iavor S. Diatchki, 2007+-- License   : BSD3+--+-- Maintainer: Henning Thielemann+-- Stability : provisional+--+-- This module contains functions for working with sequencer queue.+-- Reference:+-- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_queue.html>+--------------------------------------------------------------------------------++module Sound.ALSA.Sequencer.Queue.Tempo+  ( T+  , get+  , set+  , copy+  , clone++  , getQueue+  , getTempo+  , getPPQ+  , getSkew+  , getSkewBase++  , setTempo+  , setPPQ+  , setSkew+  , setSkewBase+  ) where++#include <Sound/ALSA/Sequencer/Area.h>++import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue+import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified Sound.ALSA.Sequencer.Area as Area+import qualified Sound.ALSA.Exception as Exc++import qualified Foreign.C.Types as C+import Data.Word (Word, )+++#area "queue_tempo"++#{get_area "Queue.T"}+#{set_area "Queue.T"}+++-- RO+#{get_int "queue", "Queue", "Queue.T", "Queue.imp"}++-- RW+#{get_set_int "tempo", "Tempo", "Word", "fromIntegral", "fromIntegral"}+#{get_set_int "ppq", "PPQ", "Int", "fromIntegral", "fromIntegral"}+#{get_set_int "skew", "Skew", "Word", "fromIntegral", "fromIntegral"}+#{get_set_int "skew_base", "SkewBase", "Word", "fromIntegral", "fromIntegral"}
− src/Sound/ALSA/Sequencer/Queue/Timer.hs
@@ -1,80 +0,0 @@------------------------------------------------------------------------------------ |--- Module    : Sound.ALSA.Sequencer.Queue.Timer--- Copyright : (c) Henning Thielemann, 2010---             (c) Iavor S. Diatchki, 2007--- License   : BSD3------ Maintainer: Henning Thielemann--- Stability : provisional------ This module contains functions for working with sequencer queue.--- Reference:--- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_queue.html>-----------------------------------------------------------------------------------module Sound.ALSA.Sequencer.Queue.Timer-  ( T-  , get-  , set-  , copy-  , clone--  , getQueue-  , getType-  , getResolution--  , setType-  , setResolution--  , QueueTimer.Type(..)-  ) where--import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue-import qualified Sound.ALSA.Sequencer.Marshal.QueueTimer as QueueTimer-import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq-import qualified Sound.ALSA.Sequencer.Area as Area-import qualified Sound.ALSA.Exception as Exc--import Foreign.Ptr (Ptr, )-import Foreign.C.Types (CInt, )-import Data.Word (Word, )---type T = Area.QueueTimer-type T_ = Area.QueueTimer_--get :: Seq.T mode -> Queue.T -> IO T-get (Seq.Cons h) q =-  do timer <- Area.queue_timer_malloc-     Exc.checkResult_ "get_queue_timer" =<< Area.with_queue_timer timer-                                     (snd_seq_get_queue_timer h (Queue.exp q))-     return timer--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_get_queue_timer"-  snd_seq_get_queue_timer :: Ptr Seq.Core -> CInt -> Ptr T_ -> IO CInt---set :: Seq.T mode -> Queue.T -> T -> IO ()-set (Seq.Cons h) p timer =-  Exc.checkResult_ "set_queue_timer" =<< Area.with_queue_timer timer (snd_seq_set_queue_timer h (Queue.exp p))--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_set_queue_timer"-  snd_seq_set_queue_timer :: Ptr Seq.Core -> CInt -> Ptr T_ -> IO CInt---copy :: T -> T -> IO ()-clone :: T -> IO T-getQueue :: T -> IO Queue.T-getType :: T -> IO QueueTimer.Type-getResolution :: T -> IO Word-setType :: T -> QueueTimer.Type -> IO ()-setResolution :: T -> Word -> IO ()--copy          = Area.queue_timer_copy-clone         = Area.queue_timer_clone-getQueue      = Area.queue_timer_get_queue-getType       = Area.queue_timer_get_type-getResolution = Area.queue_timer_get_resolution-setType       = Area.queue_timer_set_type-setResolution = Area.queue_timer_set_resolution
+ src/Sound/ALSA/Sequencer/Queue/Timer.hsc view
@@ -0,0 +1,80 @@+--------------------------------------------------------------------------------+-- |+-- Module    : Sound.ALSA.Sequencer.Queue.Timer+-- Copyright : (c) Henning Thielemann, 2010-2012+--             (c) Iavor S. Diatchki, 2007+-- License   : BSD3+--+-- Maintainer: Henning Thielemann+-- Stability : provisional+--+-- This module contains functions for working with sequencer queue.+-- Reference:+-- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_queue.html>+--------------------------------------------------------------------------------++module Sound.ALSA.Sequencer.Queue.Timer+  ( T+  , get+  , set+  , copy+  , clone++  , getQueue+  , getType+  , getResolution++  , setType+  , setResolution++  , Type(..)+  ) where++#include <alsa/asoundlib.h>+#include <Sound/ALSA/Sequencer/Area.h>++import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue+import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified Sound.ALSA.Sequencer.Area as Area+import qualified Sound.ALSA.Exception as Exc++import qualified Foreign.C.Types as C+import Data.Word (Word, )+++#area "queue_timer"++#{get_area "Queue.T"}+#{set_area "Queue.T"}+++-- RO+#{get_int "queue", "Queue", "Queue.T", "Queue.imp"}++-- RW++#{get_set_int "type", "Type",+            "Type", "impType", "expType"}++#{get_set_int "resolution", "Resolution",+            "Word", "fromIntegral", "fromIntegral"}+++data Type =+     Alsa+   | MidiClock+   | MidiTick+   deriving (Show, Eq, Ord, Enum)++expType :: Type -> C.CInt+expType t  = case t of+  Alsa       -> #{const SND_SEQ_TIMER_ALSA}+  MidiClock  -> #{const SND_SEQ_TIMER_MIDI_CLOCK}+  MidiTick   -> #{const SND_SEQ_TIMER_MIDI_TICK}++impType :: C.CInt -> Type+impType t  = case t of+  #{const SND_SEQ_TIMER_ALSA}         -> Alsa+  #{const SND_SEQ_TIMER_MIDI_CLOCK}   -> MidiClock+  #{const SND_SEQ_TIMER_MIDI_TICK}    -> MidiTick+  _ -> error ("QueueTimer.impType: unknown timer type (" ++ show t ++ ")")
src/Sound/ALSA/Sequencer/RealTime.hs view
@@ -1,7 +1,7 @@ module Sound.ALSA.Sequencer.RealTime   ( RealTime.T(..)-  , fromDouble, fromInteger-  , toDouble, toInteger+  , fromDouble, fromFractional, fromInteger+  , toDouble, toFractional, toInteger   ) where  import qualified Sound.ALSA.Sequencer.Marshal.RealTime as RealTime@@ -18,9 +18,15 @@    let (s,n) = divMod t nanoPerSecond    in  RealTime.Cons (fromIntegral s) (fromIntegral n) --- | Convert fractional number of seconds to 'RealTime.T'+{- |+Convert fractional number of seconds to 'RealTime.T'+Time must be non-negative.+-} fromDouble :: Double -> RealTime.T-fromDouble t =+fromDouble = fromFractional++fromFractional :: (RealFrac a) => a -> RealTime.T+fromFractional t =    let (s,n) = properFraction t    in  RealTime.Cons s (floor $ n * nanoPerSecond) @@ -31,5 +37,8 @@  -- | Convert fractional number of seconds to 'RealTime.T' toDouble :: RealTime.T -> Double-toDouble (RealTime.Cons s n) =+toDouble = toFractional++toFractional :: (RealFrac a) => RealTime.T -> a+toFractional (RealTime.Cons s n) =    fromIntegral s + fromIntegral n / nanoPerSecond
src/Sound/ALSA/Sequencer/Sequencer.hs view
@@ -5,12 +5,11 @@  module Sound.ALSA.Sequencer.Sequencer where -import qualified Sound.ALSA.Sequencer.Marshal.Port as Port import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq-import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr import qualified Sound.ALSA.Exception as Exc -import Foreign.C.Types (CInt, CSize, )+import qualified Foreign.C.Types as C+import Foreign.C.Types (CSize, ) import Foreign.C.String (CString, withCAString, peekCString, ) import Foreign.Ptr (Ptr, ) import Foreign.Marshal.Alloc (alloca, )@@ -30,20 +29,32 @@  open   :: Seq.OpenMode mode-                -- Read\/Write permissions-  => String     -- ^ The sequencer's \"name\". This is not a name that you-                -- make up for your own purposes; it has special significance-                -- to the ALSA library. Usually you need to pass 'default_name'-                -- here.-  -> Seq.BlockMode  -- Blocking behavior-  -> IO (Seq.T mode)  -- Handle to the sequencer.+        -- Read\/Write permissions+  => String+        {- ^+        The sequencer's \"name\".+        This is not a name that you make up for your own purposes;+        it has special significance to the ALSA library.+        Usually you need to pass 'defaultName' here+        or simply use 'openDefault'.+        -}+  -> Seq.BlockMode    -- ^ Blocking behavior+  -> IO (Seq.T mode)  -- ^ Handle to the sequencer.  open t bm = withOpenMode $ \om -> alloca $ \p -> withCAString t $ \s ->   do Exc.checkResult_ "open" =<< snd_seq_open p s (Seq.expOpenMode om) (Seq.expBlockMode bm)      fmap Seq.Cons $ peek p +openDefault+  :: Seq.OpenMode mode+        -- Read\/Write permissions+  => Seq.BlockMode    -- ^ Blocking behavior+  -> IO (Seq.T mode)  -- ^ Handle to the sequencer.+openDefault = open defaultName++ foreign import ccall unsafe "alsa/asoundlib.h snd_seq_open"-  snd_seq_open :: Ptr (Ptr Seq.Core) -> CString -> CInt -> CInt -> IO CInt+  snd_seq_open :: Ptr (Ptr Seq.Core) -> CString -> C.CInt -> C.CInt -> IO C.CInt  withOpenMode :: (mode -> IO (Seq.T mode)) -> IO (Seq.T mode) withOpenMode f = f undefined@@ -61,30 +72,46 @@ close (Seq.Cons h) = Exc.checkResult_ "close" =<< snd_seq_close h  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_close"-  snd_seq_close :: Ptr Seq.Core -> IO CInt+  snd_seq_close :: Ptr Seq.Core -> IO C.CInt   with   :: Seq.OpenMode mode-                -- Read\/Write permissions-  => String     -- ^ The sequencer's \"name\". This is not a name that you-                -- make up for your own purposes; it has special significance-                -- to the ALSA library. Usually you need to pass 'default_name'-                -- here.+        -- Read\/Write permissions+  => String+        {- ^+        The sequencer's \"name\".+        This is not a name that you make up for your own purposes;+        it has special significance to the ALSA library.+        Usually you need to pass 'defaultName' here+        or simply use 'withDefault'.+        -}   -> Seq.BlockMode-                -- Blocking behavior+        -- ^ Blocking behavior   -> (Seq.T mode -> IO a)-                -- Action on the sequencer, the result must be computed strictly.+        -- ^ Action on the sequencer, the result must be computed strictly.   -> IO a with t bm =    bracket (open t bm) close +withDefault+  :: Seq.OpenMode mode+  => Seq.BlockMode+  -> (Seq.T mode -> IO a)+  -> IO a+withDefault = with defaultName ++-- | This is the name that should be passed to 'open' in most cases.+defaultName :: String+defaultName = "default"++ -- | Get identifier of a sequencer handle. -- It is the same identifier specified in the call to 'open'. getName-  :: Seq.T mode     -- ^ sequencer handle-  -> IO String  -- ^ ALSA identifier for the handel+  :: Seq.T mode  -- ^ sequencer handle+  -> IO String   -- ^ ALSA identifier for the handle getName (Seq.Cons h) = peekCString =<< snd_seq_name h  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_name"@@ -104,7 +131,7 @@ setBlocking (Seq.Cons h) m = Exc.checkResult_ "set_blocking" =<< snd_seq_nonblock h(Seq.expBlockMode m)  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_nonblock"-  snd_seq_nonblock :: Ptr Seq.Core -> CInt -> IO CInt+  snd_seq_nonblock :: Ptr Seq.Core -> C.CInt -> IO C.CInt   @@ -133,7 +160,7 @@   Exc.checkResult_ "set_output_buffer_size" =<< snd_seq_set_output_buffer_size h (fromIntegral x)  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_set_output_buffer_size"-  snd_seq_set_output_buffer_size :: Ptr Seq.Core -> CSize -> IO CInt+  snd_seq_set_output_buffer_size :: Ptr Seq.Core -> CSize -> IO C.CInt   -- | Return the byte size of input buffer.@@ -159,7 +186,7 @@   Exc.checkResult_ "set_input_buffer_size" =<< snd_seq_set_input_buffer_size h (fromIntegral x)  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_set_input_buffer_size"-  snd_seq_set_input_buffer_size :: Ptr Seq.Core -> CSize -> IO CInt+  snd_seq_set_input_buffer_size :: Ptr Seq.Core -> CSize -> IO C.CInt   @@ -175,7 +202,7 @@   Exc.checkResult_ "set_pool_output" =<< snd_seq_set_client_pool_output h (fromIntegral x)  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_set_client_pool_output"-  snd_seq_set_client_pool_output :: Ptr Seq.Core -> CSize -> IO CInt+  snd_seq_set_client_pool_output :: Ptr Seq.Core -> CSize -> IO C.CInt   -- | Specify how much space should become free before waking clients@@ -189,7 +216,7 @@   Exc.checkResult_ "set_pool_output_room" =<< snd_seq_set_client_pool_output_room h (fromIntegral x)  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_set_client_pool_output_room"-  snd_seq_set_client_pool_output_room :: Ptr Seq.Core -> CSize -> IO CInt+  snd_seq_set_client_pool_output_room :: Ptr Seq.Core -> CSize -> IO C.CInt   -- | Reset the output pool.@@ -201,7 +228,7 @@   Exc.checkResult_ "reset_pool_output" =<< snd_seq_reset_pool_output h  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_reset_pool_output"-  snd_seq_reset_pool_output :: Ptr Seq.Core -> IO CInt+  snd_seq_reset_pool_output :: Ptr Seq.Core -> IO C.CInt   @@ -215,7 +242,7 @@   Exc.checkResult_ "set_pool_input" =<< snd_seq_set_client_pool_input h (fromIntegral x)  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_set_client_pool_input"-  snd_seq_set_client_pool_input :: Ptr Seq.Core -> CSize -> IO CInt+  snd_seq_set_client_pool_input :: Ptr Seq.Core -> CSize -> IO C.CInt   -- | Reset the input pool.@@ -227,71 +254,4 @@   Exc.checkResult_ "reset_pool_input" =<< snd_seq_reset_pool_input h  foreign import ccall unsafe "alsa/asoundlib.h snd_seq_reset_pool_input"-  snd_seq_reset_pool_input :: Ptr Seq.Core -> IO CInt------------Middle Level Interface ------------------------------------------------------------ | Simple subscription (w\/o exclusive & time conversion).-connectFrom :: Seq.AllowInput mode => Seq.T mode -> Port.T -> Addr.T -> IO ()-connectFrom (Seq.Cons h) me a =-  Exc.checkResult_ "connect_from" =<< snd_seq_connect_from h (Port.exp me) c p-  where (c,p) = Addr.exp a--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_connect_from"-  snd_seq_connect_from :: Ptr Seq.Core -> CInt -> CInt -> CInt -> IO CInt----- | Simple subscription (w\/o exclusive & time conversion).-connectTo :: Seq.AllowOutput mode => Seq.T mode -> Port.T -> Addr.T -> IO ()-connectTo (Seq.Cons h) me a =-  Exc.checkResult_ "connect_to" =<< snd_seq_connect_to h (Port.exp me) c p-  where (c,p) = Addr.exp a--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_connect_to"-  snd_seq_connect_to :: Ptr Seq.Core -> CInt -> CInt -> CInt -> IO CInt----- | Simple disconnection.-disconnectFrom :: Seq.AllowInput mode => Seq.T mode -> Port.T -> Addr.T -> IO ()-disconnectFrom (Seq.Cons h) me a =-  Exc.checkResult_ "disconnect_from" =<< snd_seq_disconnect_from h (Port.exp me) c p-  where (c,p) = Addr.exp a--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_disconnect_from"-  snd_seq_disconnect_from :: Ptr Seq.Core -> CInt -> CInt -> CInt -> IO CInt---- | Simple disconnection.-disconnectTo :: Seq.AllowOutput mode => Seq.T mode -> Port.T -> Addr.T -> IO ()-disconnectTo (Seq.Cons h) me a =-  Exc.checkResult_ "disconnect_to" =<< snd_seq_disconnect_to h (Port.exp me) c p-  where (c,p) = Addr.exp a--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_disconnect_to"-  snd_seq_disconnect_to :: Ptr Seq.Core -> CInt -> CInt -> CInt -> IO CInt----- | Parse the given string into sequencer address.--- The client and port are separated by either colon or period, e.g. 128:1.--- The function also accepts client names.-parseAddress-  :: Seq.T mode   -- ^ Sequencer handle.-  -> String       -- ^ String to be parsed.-  -> IO Addr.T    -- ^ The parsed address.--parseAddress (Seq.Cons h) s =-  alloca $ \pa ->-  withCAString s $ \ps ->-    do Exc.checkResult_ "parse_address" =<< snd_seq_parse_address h pa ps-       peek pa--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_parse_address"-  snd_seq_parse_address :: Ptr Seq.Core -> Ptr Addr.T -> CString -> IO CInt+  snd_seq_reset_pool_input :: Ptr Seq.Core -> IO C.CInt
− src/Sound/ALSA/Sequencer/Subscribe.hs
@@ -1,147 +0,0 @@------------------------------------------------------------------------------------ |--- Module    : Sound.ALSA.Sequencer.Subscribe--- Copyright : (c) Dylan Simon, 2011--- License   : BSD3------ Stability : provisional------ This module contains functions for working with subscriptions.--- Reference:--- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_subscribe.html>-----------------------------------------------------------------------------------module Sound.ALSA.Sequencer.Subscribe-  ( {- T--  , alloc-  , copy-  , clone--  , getSender-  , getDest-  , getQueue-  , getExclusive-  , getTimeUpdate-  , getTimeReal-  -  , setSender-  , setDest-  , setQueue-  , setExclusive-  , setTimeUpdate-  , setTimeReal--  , subscribePort-  , unsubscribePort--  , create-  , -} subscribe-  , unsubscribe-  ) where--import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq-import qualified Sound.ALSA.Sequencer.Area as Area-import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr-import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue-import qualified Sound.ALSA.Exception as Exc--import Foreign.C.Types (CInt, )-import Foreign.Ptr (Ptr, )-import Foreign.Marshal.Alloc (alloca, )-import Foreign.Storable (peek, poke, )--type T = Area.PortSubscribe-type T_ = Area.PortSubscribe_--alloc	      :: IO T-_copy	      :: T -> T -> IO ()-_clone	      :: T -> IO T-_getQueue     :: T -> IO Queue.T-_getExclusive :: T -> IO Bool-_getTimeUpdate:: T -> IO Bool-_getTimeReal  :: T -> IO Bool-setQueue     :: T -> Queue.T -> IO ()-setExclusive  :: T -> Bool -> IO ()-setTimeUpdate :: T -> Bool -> IO ()-setTimeReal   :: T -> Bool -> IO ()--alloc	      = Area.port_subscribe_malloc-_copy	      = Area.port_subscribe_copy-_clone	      = Area.port_subscribe_clone-_getQueue     = Area.port_subscribe_get_queue-_getExclusive = Area.port_subscribe_get_exclusive-_getTimeUpdate= Area.port_subscribe_get_time_update-_getTimeReal  = Area.port_subscribe_get_time_real-setQueue      = Area.port_subscribe_set_queue-setExclusive  = Area.port_subscribe_set_exclusive-setTimeUpdate = Area.port_subscribe_set_time_update-setTimeReal   = Area.port_subscribe_set_time_real---- | Get sender address of a port subscription-_getSender :: T -> IO Addr.T-_getSender s = -  peek =<< Area.with_port_subscribe s snd_seq_port_subscribe_get_sender--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_port_subscribe_get_sender"-  snd_seq_port_subscribe_get_sender :: Ptr T_ -> IO (Ptr Addr.T)---- | Get destination address of a port subscription-_getDest :: T -> IO Addr.T-_getDest s = -  peek =<< Area.with_port_subscribe s snd_seq_port_subscribe_get_dest--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_port_subscribe_get_dest"-  snd_seq_port_subscribe_get_dest :: Ptr T_ -> IO (Ptr Addr.T)---- | Set sender address of a port subscription-setSender :: T -> Addr.T -> IO ()-setSender s c =-  alloca $ \p -> poke p c >> Area.with_port_subscribe s (`snd_seq_port_subscribe_set_sender` p)--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_port_subscribe_set_sender"-  snd_seq_port_subscribe_set_sender :: Ptr T_ -> Ptr Addr.T -> IO ()---- | Set destination address of a port subscription-setDest :: T -> Addr.T -> IO ()-setDest s c =-  alloca $ \p -> poke p c >> Area.with_port_subscribe s (`snd_seq_port_subscribe_set_dest` p)--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_port_subscribe_set_dest"-  snd_seq_port_subscribe_set_dest :: Ptr T_ -> Ptr Addr.T -> IO ()---- | Subscribe a port connection-subscribePort :: Seq.T mode -> T -> IO ()-subscribePort (Seq.Cons h) s =-  Exc.checkResult_ "subscribe_port" =<< Area.with_port_subscribe s (snd_seq_subscribe_port h)--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_subscribe_port"-  snd_seq_subscribe_port :: Ptr Seq.Core -> Ptr T_ -> IO CInt---- | Unsubscribe a connection between ports-unsubscribePort :: Seq.T mode -> T -> IO ()-unsubscribePort (Seq.Cons h) s =-  Exc.checkResult_ "unsubscribe_port" =<< Area.with_port_subscribe s (snd_seq_unsubscribe_port h)--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_unsubscribe_port"-  snd_seq_unsubscribe_port :: Ptr Seq.Core -> Ptr T_ -> IO CInt--create :: Addr.T -> Addr.T -> Bool -> Maybe (Queue.T, Bool) -> IO T-create sender dest excl time = do-  s <- alloc-  setSender s sender-  setDest s dest-  setExclusive s excl-  maybe (return ()) (\(queue, realtime) -> do-    setTimeUpdate s True-    setQueue s queue-    setTimeReal s realtime) time-  return s---- | Subscribe a port connection: @'subscribeSimple' sender dest exclusive (Just (updatequeue, realtime))@-subscribe :: Seq.T mode -> Addr.T -> Addr.T -> Bool -> Maybe (Queue.T, Bool) -> IO ()-subscribe ss sender dest excl time = subscribePort ss =<< create sender dest excl time---- | Unsubscribe a port connection: @'unsubscribeSimple' sender dest@-unsubscribe :: Seq.T mode -> Addr.T -> Addr.T -> IO ()-unsubscribe ss sender dest = unsubscribePort ss =<< create sender dest False Nothing
+ src/Sound/ALSA/Sequencer/Subscribe.hsc view
@@ -0,0 +1,115 @@+--------------------------------------------------------------------------------+-- |+-- Module    : Sound.ALSA.Sequencer.Subscribe+-- Copyright : (c) Henning Thielemann, 2012+--             (c) Dylan Simon, 2011+-- License   : BSD3+--+-- Stability : provisional+--+-- This module contains functions for working with subscriptions.+-- Reference:+-- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_subscribe.html>+--------------------------------------------------------------------------------++module Sound.ALSA.Sequencer.Subscribe+  ( T++  , malloc+  , copy+  , clone++  , getSender+  , getDest+  , getQueue+  , getExclusive+  , getTimeUpdate+  , getTimeReal++  , setSender+  , setDest+  , setQueue+  , setExclusive+  , setTimeUpdate+  , setTimeReal++  , subscribePort+  , unsubscribePort++  , create+  , subscribe+  , unsubscribe+  ) where++#include <Sound/ALSA/Sequencer/Area.h>++import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr+import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue+import qualified Sound.ALSA.Sequencer.Area as Area+import qualified Sound.ALSA.Exception as Exc++import Data.Foldable (forM_, )++import qualified Foreign.C.Types as C+import Foreign.Ptr (Ptr, )+++#area "port_subscribe"++#{get_set_int "queue", "Queue",+           "Queue.T", "Queue.imp", "Queue.exp"}+#get_set_bool "exclusive", "Exclusive"+#get_set_bool "time_update", "TimeUpdate"+#get_set_bool "time_real", "TimeReal"+++-- | Get sender address of a port subscription+#{get_ptr "sender", "Sender", "Addr.T"}++-- | Get destination address of a port subscription+#{get_ptr "dest", "Dest", "Addr.T"}++-- | Set sender address of a port subscription+#{set_ptr "sender", "Sender", "Addr.T"}++-- | Set destination address of a port subscription+#{set_ptr "dest", "Dest", "Addr.T"}++-- | Subscribe a port connection+subscribePort :: Seq.T mode -> T -> IO ()+subscribePort (Seq.Cons h) s =+  Exc.checkResult_ "subscribePort" =<< with s (subscribePort_ h)++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_subscribe_port"+  subscribePort_ :: Ptr Seq.Core -> Ptr T_ -> IO C.CInt++-- | Unsubscribe a connection between ports+unsubscribePort :: Seq.T mode -> T -> IO ()+unsubscribePort (Seq.Cons h) s =+  Exc.checkResult_ "unsubscribePort" =<< with s (unsubscribePort_ h)++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_unsubscribe_port"+  unsubscribePort_ :: Ptr Seq.Core -> Ptr T_ -> IO C.CInt++create :: Addr.T -> Addr.T -> Bool -> Maybe (Queue.T, Bool) -> IO T+create sender dest excl time = do+  s <- malloc+  setSender s sender+  setDest s dest+  setExclusive s excl+  forM_ time $ \(queue, realtime) -> do+    setTimeUpdate s True+    setQueue s queue+    setTimeReal s realtime+  return s++-- | Subscribe a port connection: @'subscribeSimple' sender dest exclusive (Just (updatequeue, realtime))@+subscribe :: Seq.T mode -> Addr.T -> Addr.T -> Bool -> Maybe (Queue.T, Bool) -> IO ()+subscribe ss sender dest excl time =+  subscribePort ss =<< create sender dest excl time++-- | Unsubscribe a port connection: @'unsubscribeSimple' sender dest@+unsubscribe :: Seq.T mode -> Addr.T -> Addr.T -> IO ()+unsubscribe ss sender dest =+  unsubscribePort ss =<< create sender dest False Nothing
− src/Sound/ALSA/Sequencer/Subscribe/Query.hs
@@ -1,150 +0,0 @@------------------------------------------------------------------------------------ |--- Module    : Sound.ALSA.Sequencer.Subscribe.Query--- Copyright : (c) Dylan Simon, 2011--- License   : BSD3------ Stability : provisional------ This module contains functions for working with subscriptions.--- Reference:--- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_subscribe.html>-----------------------------------------------------------------------------------module Sound.ALSA.Sequencer.Subscribe.Query-  ( T-  , Query.Type(..)--  {--  , alloc-  , copy-  , clone-  -}--  , getClient-  , getPort-  , getRoot-  , getType-  , getIndex-  , getNumSubs-  , getAddr-  , getQueue-  , getExclusive-  , getTimeUpdate-  , getTimeReal--  {--  , setClient-  , setPort-  , setType-  , setIndex-  -}--  , query-  , queryAll-  ) where--import qualified Sound.ALSA.Sequencer.Marshal.QuerySubscribe as Query-import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq-import qualified Sound.ALSA.Sequencer.Area as Area-import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr-import qualified Sound.ALSA.Sequencer.Marshal.Client as Client-import qualified Sound.ALSA.Sequencer.Marshal.Port as Port-import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue-import qualified Sound.ALSA.Exception as Exc--import Foreign.C.Error (Errno(Errno), eNOENT, )-import Foreign.C.Types (CInt, )-import Foreign.Ptr (Ptr, )-import Foreign.Marshal.Alloc (alloca, )-import Foreign.Storable (peek, poke, )-import Data.Word (Word, )--type T = Area.QuerySubscribe-type T_ = Area.QuerySubscribe_--alloc	      :: IO T-_copy	      :: T -> T -> IO ()-_clone	      :: T -> IO T-getClient     :: T -> IO Client.T-getPort	      :: T -> IO Port.T-getType	      :: T -> IO Query.Type-getIndex      :: T -> IO Word-getNumSubs    :: T -> IO Word-getQueue      :: T -> IO Queue.T-getExclusive  :: T -> IO Bool-getTimeUpdate :: T -> IO Bool-getTimeReal   :: T -> IO Bool-_setClient    :: T -> Client.T -> IO ()-_setPort      :: T -> Port.T -> IO ()-setType	      :: T -> Query.Type -> IO ()-setIndex      :: T -> Word -> IO ()--alloc	      = Area.query_subscribe_malloc-_copy	      = Area.query_subscribe_copy-_clone	      = Area.query_subscribe_clone-getClient     = Area.query_subscribe_get_client-getPort	      = Area.query_subscribe_get_port-getType	      = Area.query_subscribe_get_type-getIndex      = Area.query_subscribe_get_index-getNumSubs    = Area.query_subscribe_get_num_subs-getQueue      = Area.query_subscribe_get_queue-getExclusive  = Area.query_subscribe_get_exclusive-getTimeUpdate = Area.query_subscribe_get_time_update-getTimeReal   = Area.query_subscribe_get_time_real-_setClient    = Area.query_subscribe_set_client-_setPort      = Area.query_subscribe_set_port-setType       = Area.query_subscribe_set_type-setIndex      = Area.query_subscribe_set_index---- | Get the client/port address of a query-getRoot :: T -> IO Addr.T-getRoot q = -  peek =<< Area.with_query_subscribe q snd_seq_query_subscribe_get_root--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_query_subscribe_get_root"-  snd_seq_query_subscribe_get_root :: Ptr T_ -> IO (Ptr Addr.T)---- | Get the address of subscriber of query-getAddr :: T -> IO Addr.T-getAddr q = -  peek =<< Area.with_query_subscribe q snd_seq_query_subscribe_get_addr--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_query_subscribe_get_addr"-  snd_seq_query_subscribe_get_addr :: Ptr T_ -> IO (Ptr Addr.T)----- | Set the client/port address of a query-setRoot :: T -> Addr.T -> IO ()-setRoot q c = -  alloca $ \p -> poke p c >> Area.with_query_subscribe q (`snd_seq_query_subscribe_set_root` p)--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_query_subscribe_set_root"-  snd_seq_query_subscribe_set_root :: Ptr T_ -> Ptr Addr.T -> IO ()----- | Query port subscriber list-queryPort :: Seq.T mode -> T -> IO Bool-queryPort (Seq.Cons h) q =-  Exc.checkResultMaybe "query_port_subscribers" (const True) (\e -> if Errno (negate e) == eNOENT then Just False else Nothing) =<<-    Area.with_query_subscribe q (snd_seq_query_port_subscribers h)--foreign import ccall unsafe "alsa/asoundlib.h snd_seq_query_port_subscribers"-  snd_seq_query_port_subscribers :: Ptr Seq.Core -> Ptr T_ -> IO CInt---- | Queries a subscriber connected to (Write) or from (Read) a given address: @'query' seq addr typ index@-query :: Seq.T mode -> Addr.T -> Query.Type -> Word -> IO (Maybe T)-query ss root t i = do-  q <- alloc-  setRoot q root-  setType q t-  setIndex q i-  r <- queryPort ss q-  return $ if r then Just q else Nothing---- | Queries the list of subscribers accessing a port-queryAll :: Seq.T mode -> Addr.T -> Query.Type -> IO [T]-queryAll ss root t = queryRest 0 where-  queryRest i = query ss root t i >>=-    maybe (return []) (\q -> (q:) `fmap` queryRest (succ i))-
+ src/Sound/ALSA/Sequencer/Subscribe/Query.hsc view
@@ -0,0 +1,128 @@+--------------------------------------------------------------------------------+-- |+-- Module    : Sound.ALSA.Sequencer.Subscribe.Query+-- Copyright : (c) Henning Thielemann, 2012+--             (c) Dylan Simon, 2011+-- License   : BSD3+--+-- Stability : provisional+--+-- This module contains functions for working with subscriptions.+-- Reference:+-- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_subscribe.html>+--------------------------------------------------------------------------------++module Sound.ALSA.Sequencer.Subscribe.Query+  ( T+  , Type(..)++  , malloc+  , copy+  , clone++  , getClient+  , getPort+  , getRoot+  , getType+  , getIndex+  , getNumSubs+  , getAddr+  , getQueue+  , getExclusive+  , getTimeUpdate+  , getTimeReal++  , setClient+  , setPort+  , setType+  , setIndex++  , query+  , queryAll+  ) where++#include <alsa/asoundlib.h>+#include <Sound/ALSA/Sequencer/Area.h>++import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq+import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr+import qualified Sound.ALSA.Sequencer.Marshal.Client as Client+import qualified Sound.ALSA.Sequencer.Marshal.Port as Port+import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue+import qualified Sound.ALSA.Sequencer.Area as Area+import qualified Sound.ALSA.Sequencer.Utility as U+import qualified Sound.ALSA.Exception as Exc++import qualified Foreign.C.Types as C+import Foreign.Ptr (Ptr, )+import Data.Word (Word, )+import Data.Maybe.HT (toMaybe, )+++#area "query_subscribe"++#{get_set_int "client", "Client",+          "Client.T", "Client.imp", "Client.exp"}+#{get_set_int "port", "Port",+          "Port.T", "Port.imp", "Port.exp"}+#{get_set_int "type", "Type",+          "Type", "impType", "expType"}+#{get_set_int "index", "Index",+          "Word", "fromIntegral", "fromIntegral"}++-- RO+#{get_int "num_subs", "NumSubs", "Word", "fromIntegral"}+#{get_int "queue", "Queue", "Queue.T", "Queue.imp"}+#get_bool "exclusive", "Exclusive"+#get_bool "time_update", "TimeUpdate"+#get_bool "time_real", "TimeReal"+++-- | Get the client/port address of a query+#{get_ptr "root", "Root", "Addr.T"}+-- | Set the client/port address of a query+#{set_ptr "root", "Root", "Addr.T"}+-- | Get the address of subscriber of query+#{get_ptr "addr", "Addr", "Addr.T"}+++-- | Query port subscriber list+queryPort :: Seq.T mode -> T -> IO Bool+queryPort (Seq.Cons h) q =+  U.checkResultQuery "Subscribe.queryPort" =<< with q (queryPort_ h)++foreign import ccall unsafe "alsa/asoundlib.h snd_seq_query_port_subscribers"+  queryPort_ :: Ptr Seq.Core -> Ptr T_ -> IO C.CInt++-- | Queries a subscriber connected to (Write) or from (Read) a given address: @'query' seq addr typ index@+query :: Seq.T mode -> Addr.T -> Type -> Word -> IO (Maybe T)+query ss root t i = do+  q <- malloc+  setRoot q root+  setType q t+  setIndex q i+  r <- queryPort ss q+  return $ toMaybe r q++-- | Queries the list of subscribers accessing a port+queryAll :: Seq.T mode -> Addr.T -> Type -> IO [T]+queryAll ss root t = queryRest 0 where+  queryRest i = query ss root t i >>=+    maybe (return []) (\q -> (q:) `fmap` queryRest (succ i))+++data Type =+     Read+   | Write+   deriving (Show, Eq, Ord, Enum)++expType :: Type -> C.CInt+expType t  = case t of+  Read  -> #{const SND_SEQ_QUERY_SUBS_READ}+  Write	-> #{const SND_SEQ_QUERY_SUBS_WRITE}++impType :: C.CInt -> Type+impType t  = case t of+  #{const SND_SEQ_QUERY_SUBS_READ}  -> Read+  #{const SND_SEQ_QUERY_SUBS_WRITE} -> Write+  _ -> error ("QuerySubscribe.impType: unknown subscription type (" ++ show t ++ ")")
+ src/Sound/ALSA/Sequencer/Time.hs view
@@ -0,0 +1,7 @@+module Sound.ALSA.Sequencer.Time (+   T(Cons, mode, stamp), consAbs, consRel,+   Mode(Absolute, Relative), Stamp (Tick, Real),+   ) where++import Sound.ALSA.Sequencer.Marshal.Time as Time+
src/Sound/ALSA/Sequencer/Utility.hs view
@@ -1,5 +1,13 @@ module Sound.ALSA.Sequencer.Utility where +import qualified Sound.ALSA.Exception as Exc++import qualified Foreign.C.Types as C+import Foreign.C.Error (Errno(Errno), eNOENT, )++import Data.Maybe.HT (toMaybe, )++ showsField :: Show a => a -> ShowS showsField = showsPrec 11 @@ -8,3 +16,10 @@    showParen (prec >= 10) $    showString name . showString ".Cons" .    foldr (.) id (map (\f -> showChar ' ' . f) fields)++-- might be moved to Sound.ALSA.Exception+checkResultQuery :: String -> C.CInt -> IO Bool+checkResultQuery name =+   Exc.checkResultMaybe name+      (const True)+      (\e -> toMaybe (Errno (negate e) == eNOENT) False)