diff --git a/csound-expression.cabal b/csound-expression.cabal
--- a/csound-expression.cabal
+++ b/csound-expression.cabal
@@ -1,5 +1,5 @@
 Name:          csound-expression
-Version:       3.0.1
+Version:       3.1.0
 Cabal-Version: >= 1.6
 License:       BSD3
 License-file:  LICENSE
@@ -79,8 +79,17 @@
 
     examples/Midi.hs
     examples/Events.hs
-    examples/Guis.hs
+    examples/DubBass.hs
 
+    examples/Gui/Button.hs      
+    examples/Gui/Envelope.hs  
+    examples/Gui/Harmonics.hs  
+    examples/Gui/Osc.hs
+    examples/Gui/EnvelopeAndHarmonics.hs  
+    examples/Gui/Filter.hs    
+    examples/Gui/Key.hs        
+    examples/Gui/Waves.hs
+
 Homepage:        https://github.com/anton-k/csound-expression
 Bug-Reports:     https://github.com/anton-k/csound-expression/issues
 
@@ -93,7 +102,7 @@
   Ghc-Options:    -Wall
   Build-Depends:
         base >= 4, base < 5, process, data-default, Boolean >= 0.1.0,
-        csound-expression-typed, csound-expression-opcodes
+        csound-expression-typed >= 0.0.1, csound-expression-opcodes
   Hs-Source-Dirs:      src/
   Exposed-Modules:
         Csound.Base
@@ -111,11 +120,10 @@
         Csound.Control.Instr
         Csound.Control.SE
 
-
---        Csound.Gui
---        Csound.Gui.Widget
---        Csound.Gui.Props
---        Csound.Gui.Layout
+        Csound.Control.Gui
+        Csound.Control.Gui.Widget
+        Csound.Control.Gui.Props
+        Csound.Control.Gui.Layout
 
 --        Csound.LowLevel
   Other-Modules:
diff --git a/examples/DubBass.hs b/examples/DubBass.hs
new file mode 100644
--- /dev/null
+++ b/examples/DubBass.hs
@@ -0,0 +1,48 @@
+module Main where
+
+import Csound
+
+wobbly :: Sig -> Sig -> Sig -> Sig
+wobbly spb coeff cps = a2
+    where
+        a1 = mean [saw (cps * 1.005), sqr (cps * 0.495)]
+        idivision = 1 / (coeff * spb)
+        klfo = kr $ oscLins [0, 0.5, 1, 0.5, 0] idivision
+
+        -- filter
+        ibase = cps
+        imod  = ibase * 9
+        a2    = moogladder a1 (ibase + imod * klfo) 0.6
+
+spb = double dspb
+dspb = 0.45
+
+instr (coeff, cps) = return $ wobbly (sig spb) (sig coeff) (sig $ cpspch cps)
+
+
+main = dac $ mix $ str (dspb * 2) $ sco instr $ melMap temp $ 
+    [ (2, 6.04)
+    , (1/3, 7.04)
+    , (2, 6.04)
+    , (1/1.5, 7.07)
+    
+    , (2, 5.09)
+    , (1, 6.09)
+    , (1/1.5, 5.09)
+    , (1/3, 6.11)
+
+    , (1, 6.04)
+    , (1/3, 7.04)
+    , (2, 6.04)
+    , (1/1.5, 7.07) 
+    
+    , (2, 6.09)
+    , (1, 7.09)
+    , (1/1.5, 6.11)
+    , (1/3, 6.07) 
+    
+    , (2, 6.04)
+    , (1/3, 7.04)
+    , (2, 6.04)
+    , (1/1.5, 7.07) ]
+
diff --git a/examples/Gui/Button.hs b/examples/Gui/Button.hs
new file mode 100644
--- /dev/null
+++ b/examples/Gui/Button.hs
@@ -0,0 +1,34 @@
+-- | Simple buttons
+module Button where
+
+import Csound.Base
+
+main = dac $ do    
+    -- Let's create a toggle button with label "play".
+    -- The toggle button emmits ones and zeros.
+    (gbut1, evt1)   <- toggle "play"
+
+    -- Let's create a plain button with label "Hi!".
+    (gbut2, evt2)   <- button "Hi!"
+
+    -- It splits the toggle button events on only ones and only zeros.
+    let (evtOn, evtOff) = splitToggle evt1
+
+    -- Let's use a standard method to create a master volume slider.
+    (gvol, vol) <- masterVolume
+
+    -- A simple instrument that plays a single note
+    -- it fades in and out in 0.5 seconds.
+    let instr cps _ = return $ fades 0.5 0.5 * osc cps
+
+    -- Creates a window with our elements vertically aligned.
+    panel $ ver [gvol, gbut1, gbut2]
+
+    -- Plays a note while toggle button is 'on'.
+    let sig1 = schedUntil (instr 440) evtOn evtOff
+    -- Plays a note once.
+        sig2 = sched (instr 330) $ withDur 0.2 $ fmap (const unit) evt2
+
+    -- Sends the sum to the output scaled with given master volume.
+    return $ vol * sum [sig1, sig2]
+      
diff --git a/examples/Gui/Envelope.hs b/examples/Gui/Envelope.hs
new file mode 100644
--- /dev/null
+++ b/examples/Gui/Envelope.hs
@@ -0,0 +1,30 @@
+-- | An ADSR-envelope.
+module Envelope where
+
+import Csound.Base
+
+-- We use `vdac` to activate the virtual midi keyboard.
+-- We can use just `dac` if we have a hardware midi controller.
+main = vdac $ do
+    -- Creates an Attack-decay-sustain-release widget.
+    -- We specify a label, time bounds for attack, decay and release
+    -- and init values. It returns a gui-widget and the signal of
+    -- the envelope.
+    (genv, env) <- linAdsr "" (AdsrBound 1 1 3) (AdsrInit 0.1 0.5 0.5 0.1)
+    
+    -- Creates a master volume widget.
+    (gvol, vol) <- masterVolume 
+
+    -- A simple midi-instrument that plays a triangle wave with
+    -- given amplitude envelope.
+    let instr = onMsg $ \cps -> env * tri cps
+
+    -- Let's place everything on window. Two elements
+    -- are aligned vertically and the master volume slider is
+    -- smaller than the envelope widget (we scale it by 0.25).
+    panel $ ver [genv, sca 0.25 gvol]
+
+    -- Triggers the midi instrument and scales
+    -- the output by given master volume.
+    return $ vol * midi instr
+
diff --git a/examples/Gui/EnvelopeAndHarmonics.hs b/examples/Gui/EnvelopeAndHarmonics.hs
new file mode 100644
--- /dev/null
+++ b/examples/Gui/EnvelopeAndHarmonics.hs
@@ -0,0 +1,28 @@
+-- | Experiments with amplitude envelope and harmonics.
+module EnvelopeAndHarmonics where
+
+import Csound.Base
+
+import Harmonics(harms)
+
+main = vdac $ do
+    -- Creates a bank of 15 sliders. We specify the label
+    -- and initial values for slider (0 is minimum and 1 is maximum 
+    -- for each slider.
+    (gharms, ks) <- sliderBank "harmonics" (1 : replicate 14 0)
+    -- We create an Adsr envelope (see example Envelope.hs)
+    (gadsr, env) <- linAdsr "amplitude envelope" (AdsrBound 1 1 3) (AdsrInit 0.1 0.1 0.5 0.1)
+    -- Creates a master volume slider
+    (gvol, vol)  <- masterVolume
+
+    -- Places everything on window. Elements are aligned vertically.
+    -- The volume slider is smaller than the ADSR-envelope. The element
+    -- for harmonics is the biggest one. We alter the sizes with the function `sca`
+    -- (it's short for scale)
+    panel $ ver [sca 0.1 gvol, sca 0.25 gadsr, gharms]
+
+    -- Let's create a simple instrument with the custom harmonics 
+    -- and amplitude envelope.
+    let instr = onMsg $ \cps -> env * harms ks cps
+    return $ vol * midi instr
+
diff --git a/examples/Gui/Filter.hs b/examples/Gui/Filter.hs
new file mode 100644
--- /dev/null
+++ b/examples/Gui/Filter.hs
@@ -0,0 +1,38 @@
+-- | Development of the example Osc.hs (see it first). 
+-- Now oscillators are equipped with filter.
+module Filter where
+
+import Csound.Base
+
+import Osc(OscInit(..), moogOscs)
+
+data FilterInit = FilterInit 
+    { filterInitResonance :: Double     -- the Q
+    , filterInitFreq      :: Double     -- the minimum of the center frequency
+    , filterInitRange     :: Double }   -- center frequency range
+
+-- | A moog like filter with ADSR-envelope for center frequency.
+moogFilter :: String -> Sig -> FilterInit -> Source (Sig -> Sig)
+moogFilter name env (FilterInit initQ initCfq initRange) = source $ do
+    (gq, q) <- knob "resonance" uspan initQ 
+    (gcfq, cfq) <- knob "freq" (linSpan 0 1000) initCfq  
+    (grange, range) <- knob "range" (linSpan 0 10000) initRange
+    let cfqSig = cfq + env * range
+    gui <- setTitle name $ hor [gq, gcfq, grange]
+    return (gui, mlp cfqSig q)
+
+adsrBound = AdsrBound 3 3 5
+adsrInit  = AdsrInit  0.1 0.1 0.5 0.2
+
+main = vdac $ do
+    (gampEnv, ampEnv) <- linAdsr "amplitude" adsrBound adsrInit
+    (gfiltEnv, filtEnv) <- linAdsr "filter" adsrBound adsrInit
+    (goscs, oscs) <- moogOscs [OscInit 1 1 1, OscInit 0.5 2 2, OscInit 0.125 3 3]
+    (gfilt, filt) <- moogFilter "" filtEnv (FilterInit 0.6 100 3000)
+    (gvol, vol) <- masterVolume 
+
+    let instr cps = vol * ampEnv * (filt $ oscs cps)
+    let gui = hor [goscs, ver [gampEnv, gfiltEnv, gfilt], sca 0.1 gvol]
+    panelBy "" (Just $ Rect 50 50 900 800) gui
+    return $ midi $ onMsg instr
+
diff --git a/examples/Gui/Harmonics.hs b/examples/Gui/Harmonics.hs
new file mode 100644
--- /dev/null
+++ b/examples/Gui/Harmonics.hs
@@ -0,0 +1,22 @@
+-- Experiments with harmonics.
+module Harmonics where
+
+import Csound.Base 
+
+-- a sum of pure tones that form a hormanic series.
+harms :: [Sig] -> Sig -> Sig
+harms ks cps = sum $ zipWith f ks (fmap (sig . double) [1 .. ])
+    where f k n = k * osc (n * cps)
+
+main = vdac $ do
+    -- Let's create a list of coefficients.
+    (g, ks) <- sliderBank "Harmonics"  (1 : replicate 13 0)
+    (gv, v) <- masterVolume
+    -- A simple instrument that plays a harmonic series
+    -- with the given coefficients.
+    let instr = onMsg $ harms ks
+    -- Places elements on window with vertical alignment.
+    panel $ ver [g, sca 0.1 gv]
+    -- Let's trigger the instrument with midi controller.
+    return $ vol * midi instr
+
diff --git a/examples/Gui/Key.hs b/examples/Gui/Key.hs
new file mode 100644
--- /dev/null
+++ b/examples/Gui/Key.hs
@@ -0,0 +1,22 @@
+-- | Keyboard events
+module Main where
+
+import Csound.Base
+
+main = dac $ do     
+    -- Creates a window that listens to keyboard events when in focus.
+    keyPanel =<< box "hi"
+    
+    -- a pure tone instrument that plays a single frequency
+    let instr x = const $ return $ osc x
+    -- triggers the instrument with frequency on the give event stream
+    -- and holds the note wile second stream is silent.
+        asig cps evtOn evtOff = schedUntil (instr cps) evtOn evtOff
+    
+    return $ mean 
+        [ asig 330 (charOn 's') (charOff 's') 
+        , asig 440 (charOn 'a') (charOff 'a') ]
+  
+-- Due to inner limitation only one keyboard event can be 
+-- registered at one control cycle. So if you press 
+-- the two buttons at the same time only one event will be registered.
diff --git a/examples/Gui/Osc.hs b/examples/Gui/Osc.hs
new file mode 100644
--- /dev/null
+++ b/examples/Gui/Osc.hs
@@ -0,0 +1,64 @@
+-- | Simulates a moog-like oscillators.
+-- We create a waveform from the sum of the three oscillators.
+module Osc where
+
+import Csound.Base
+import Control.Monad
+
+-- An oscillator
+data OscInit = OscInit 
+    { oscInitVol   :: Double    -- volume
+    , oscInitRange :: Int       -- integer scale for the frequency
+    , oscInitWave  :: Int }     -- the waveform identifier
+                                -- (0 - osc, 1 - triangle, 2 - square, 3 - saw)
+
+-- A single moog oscillator.
+-- It takes a title and initial values. Produces the waveform function.
+moogOsc1 :: String -> OscInit -> Source (Sig -> Sig)
+moogOsc1 name (OscInit initVol initRange initWave) = source $ do
+    -- Creates a widget to chose between four classic waveforms
+    (gf, f) <- classicWaves "" initWave
+    
+    -- A knob for a volume of the oscillator
+    (gvol, vol) <- knob "vol" uspan initVol 
+
+    -- A knob for a range of the oscillator (scaling of the frequency)
+    -- It's the number of the harmonic.
+    (grange, range) <- knob "range" (linSpan 1 10) (fromIntegral initRange)
+
+    -- Creates a gui element with the given title and horizontal placement.
+    gui <- setTitle name $ hor [setMaterial NoPlastic $ gf, gvol, grange]
+
+    -- Creates a waveform
+    let instr cps = vol * f (floor' range * cps) 
+    return (gui, instr)
+
+-- A list of moog oscillators.
+moogOscs :: [OscInit] -> Source (Sig -> Sig)
+moogOscs xs = source $ do
+    -- Creates a list of single moog oscillators
+    (gfs, fs) <- fmap unzip $ zipWithM 
+        (\n initVal -> moogOsc1 ("osc" ++ show n) initVal) [1 ..] xs 
+
+    -- The final waveform is the sum of all oscillators
+    let instr cps = sum $ fmap ($ cps) fs 
+    -- Alligns all elements vertically
+    let gui = ver gfs
+
+    -- Creates a source widget.
+    return (gui, instr)
+
+main = vdac $ do
+    -- Let's create a stack of three oscillators:
+    (g, f) <- moogOscs [(OscInit 1 1 0), (OscInit 0.2 1 1), (OscInit 0 1 2)]
+    -- Creates a master volume slider.
+    (gvol, vol) <- masterVolume 
+    -- Creates an amplitude envelope (see Envelope.hs).
+    (genv, env) <- linAdsr "amplitude envelope" (AdsrBound 3 3 5) (AdsrInit 0.1 0.5 0.5 0.5) 
+    
+    -- Places all elements on window with given title and sizes.
+    panelBy "" (Just $ Rect 50 50 600 600) (hor [ver [sca 0.25 genv, g], sca 0.1 gvol])
+
+    -- Triggers the instrument with midi controller.
+    return $ midi $ onMsg (mul (vol * env) . f)
+
diff --git a/examples/Gui/Waves.hs b/examples/Gui/Waves.hs
new file mode 100644
--- /dev/null
+++ b/examples/Gui/Waves.hs
@@ -0,0 +1,23 @@
+-- | Plays standard waveforms: pure tone, triangle, square and sawtooth.
+module Waves where
+
+import Csound.Base
+
+main = vdac $ do
+    -- Creates a master volume slider.
+    (gvol, vol) <- masterVolume
+
+    -- We use a standard element to experiment with four classic waveforms.
+    -- The return value of the widget is a function that takes a frequency
+    -- and returns the signal.
+    (gw, f) <- classicWaves "waves" 0
+
+    -- Let's create a simple instrument that uses the waveform.
+    let instr x = fades 0.1 0.1 * f x
+
+    -- Places elements on window aligned horizontally.
+    panel $ hor [sca 0.1 gvol, gw]
+
+    -- Triggers the instrument with midi keyboard.
+    return $ mul vol $ midi $ onMsg instr
+
diff --git a/examples/Guis.hs b/examples/Guis.hs
deleted file mode 100644
--- a/examples/Guis.hs
+++ /dev/null
@@ -1,61 +0,0 @@
--- | Test for GUI-elements. Right now this example is a total mess and shouldn't work.
--- see you in the next version...
-module Main where
-
-import qualified Data.Colour.Names as C
-
-import Control.Applicative
-
-import Csound.Base
-
-
-unit = ValSpan (ValDiap 0 1) Linear
-
-linenWidget :: Source Sig
-linenWidget = do
-    (g1, r1) <- slider unit 0.5
-    (g2, r2) <- slider unit 0.5
-    let out = liftA2 fun r1 r2        
-    source (ver [g1, g2]) out
-    where fun a b = linseg [0, a', 1, idur - a' - b', 1, b', 0]
-                where a' = idur * ir a
-                      b' = idur * ir b  
-
-instr :: SE Sig -> D -> SE Sig
-instr env cps = do
-    e <- env
-    return $ 0.5 * e * osc (sig cps)
-
-pureTone () = 0.7 * osc 440 
-    
-u = fmap (props [SetSliderType Fill] . fst) $ slider unit 0.5
-v = fmap fst $ knob unit 0.5
-r = fmap fst $ roller unit 0.001 0.01
-c1 = fmap fst $ count (ValDiap 0 10) 1 Nothing 2
-c2 = fmap fst $ count (ValDiap 0 10) 1 (Just 2) 4
-b = fmap (setLabel "push me" . fst) button
-bb = fmap fst $ butBank 5 3
-tb = fmap (setLabel "i'm the toggle" . fst) toggle 
-j = fmap fst $ joy unit unit (0.2, 0.2)
-
-d = fmap (setBoxType BorderBox) $ box $ t ++ t ++ t
-    where t = " Hello everybody, let's look at some cool text in the box "
-
-f = setColors C.green C.magenta
-
-main = dac $ do
-    g1 <- u
-    g2 <- u
-    g3 <- u
-    g4 <- r
-    g5 <- c1 
-    g6 <- c2
-    g7 <- b
-    g8 <- bb
-    g9 <- d
-    g10 <- j
-    g11 <- tb
-
-    let g = setTextColor C.azure $ hor [sca 3 $ sca 1.5 $ f $ ver [setLabel "Amplitude" g1, setLabel "Frequency" g2, hor [g5, g6]], setBorder ThinDown $ ver [g7, setTextColor C.azure $ ver [f $ setTextColor C.blue $ setButtonType RoundButton g11], sca 2 space ]]
-   
-    panel (ver [sca 4 g, hor [g7, g7]])
diff --git a/examples/Wind.hs b/examples/Wind.hs
--- a/examples/Wind.hs
+++ b/examples/Wind.hs
@@ -68,5 +68,5 @@
     ]
 
 -- | Let's repeat everything 10 times and add the sustain for 2 seconds per note.
-main = totem $ mix $ sustain 2 $ loop 3 windRes
+main = dac $ mix $ sustain 2 $ loop 3 windRes
 
diff --git a/src/Csound/Air.hs b/src/Csound/Air.hs
--- a/src/Csound/Air.hs
+++ b/src/Csound/Air.hs
@@ -6,7 +6,7 @@
     osc, oscBy, saw, isaw, pulse, sqr, tri, blosc,
 
     -- ** Unipolar
-    unipolar, bipolar, uosc, uoscBy, usaw, uisaw, upulse, usqr, utri, ublosc,
+    unipolar, bipolar, on, uon, uosc, uoscBy, usaw, uisaw, upulse, usqr, utri, ublosc,
 
     -- * Envelopes
 
@@ -32,12 +32,21 @@
     -- | Applies filter and balances the output by the input signal.
     lpb, hpb, bpb, brb, blpb, bhpb, bbpb, bbrb,
 
+    -- ** Specific filters
+    mlp,
+
     -- * Patterns
     mean, vibrate, randomPitch, chorus, resons, resonsBy, modes, dryWet,    
 
     -- ** List functions
     odds, evens,
 
+    -- * Widgets
+    AdsrBound(..), AdsrInit(..),
+    linAdsr, expAdsr, 
+    classicWaves,
+    masterVolume, masterVolumeKnob,
+
     -- * Other
     reverbsc1
 
@@ -47,7 +56,9 @@
 import Data.Boolean
 
 import Csound.Typed
-import Csound.Typed.Opcode
+import Csound.Typed.Opcode hiding (display)
+import Csound.Typed.Gui
+import Csound.Control.Gui(funnyRadio)
 
 import Csound.Tab(sine)
 
@@ -104,6 +115,20 @@
 ublosc :: Tab -> Sig -> Sig
 ublosc tb = unipolar . blosc tb
 
+-- rescaling
+
+-- | Rescaling of the bipolar signal (-1, 1) -> (a, b)
+-- 
+-- > on a b biSig
+on :: Sig -> Sig -> Sig -> Sig
+on a b x = uon a b $ unipolar x 
+
+-- | Rescaling of the unipolar signal (0, 1) -> (a, b)
+-- 
+-- > on a b uniSig
+uon :: Sig -> Sig -> Sig -> Sig
+uon a b x = a + (b - a) * x
+
 --------------------------------------------------------------------------
 -- envelopes
 
@@ -284,6 +309,12 @@
 bbrb :: Sig -> Sig -> Sig -> Sig
 bbrb = balance2 bbr
 
+-- | Moog's low-pass filter.
+--
+-- > mlp centerFrequency qResonance signal
+mlp :: Sig -> Sig -> Sig -> Sig
+mlp cf q asig = moogladder asig cf q
+
 --------------------------------------------------------------------------
 -- patterns
 
@@ -441,4 +472,57 @@
 reverbsc1 :: Sig -> Sig -> Sig -> Sig
 reverbsc1 x k co = 0.5 * (a + b)
     where (a, b) = ar2 $ reverbsc x x k co
+
+
+----------------------------------------------------------------------
+-- Widgets
+
+data AdsrBound = AdsrBound
+    { attBound  :: Double
+    , decBound  :: Double
+    , relBound  :: Double }
+
+data AdsrInit = AdsrInit
+    { attInit   :: Double
+    , decInit   :: Double
+    , susInit   :: Double
+    , relInit   :: Double }
+
+expEps :: Fractional a => a
+expEps = 0.00001
+
+linAdsr :: String -> AdsrBound -> AdsrInit -> Source Sig
+linAdsr = genAdsr $ \a d s r -> linsegr [0, a, 1, d, s] r 0
+
+expAdsr :: String -> AdsrBound -> AdsrInit -> Source Sig
+expAdsr = genAdsr $ \a d s r -> expsegr [double expEps, a, 1, d, s] r (double expEps)
+
+genAdsr :: (D -> D -> D -> D -> Sig)
+    -> String -> AdsrBound -> AdsrInit -> Source Sig
+genAdsr mkAdsr name b inits = source $ do
+    (gatt, att) <- knob "A" (linSpan expEps $ attBound b) (attInit inits)
+    (gdec, dec) <- knob "D" (linSpan expEps $ decBound b) (decInit inits)
+    (gsus, sus) <- knob "S" (linSpan expEps 1)       (susInit inits) 
+    (grel, rel) <- knob "R" (linSpan expEps $ relBound b) (relInit inits)
+    let val   = mkAdsr (ir att) (ir dec) (ir sus) (ir rel)
+    gui <- setTitle name $ hor [gatt, gdec, gsus, grel]
+    return (gui, val)
+
+-- | A widget with four standard waveforms: pure tone, triangle, square and sawtooth.
+-- The last parameter is a default waveform (it's set at init time).
+classicWaves :: String -> Int -> Source (Sig -> Sig)
+classicWaves name initVal = funnyRadio name 
+    [ ("osc", osc)
+    , ("tri", tri)
+    , ("sqr", sqr)
+    , ("saw", saw)]
+    initVal
+
+-- | Slider for master volume
+masterVolume :: Source Sig
+masterVolume = slider "master" uspan 0.5
+
+-- | Knob for master volume
+masterVolumeKnob :: Source Sig
+masterVolumeKnob = knob "master" uspan 0.5
 
diff --git a/src/Csound/Base.hs b/src/Csound/Base.hs
--- a/src/Csound/Base.hs
+++ b/src/Csound/Base.hs
@@ -35,5 +35,5 @@
 import Data.Default
 import Data.Monoid
     
-import Csound.Typed.Opcode
+import Csound.Typed.Opcode hiding (button, display, space)
 
diff --git a/src/Csound/Control.hs b/src/Csound/Control.hs
--- a/src/Csound/Control.hs
+++ b/src/Csound/Control.hs
@@ -9,11 +9,15 @@
     module Csound.Control.Evt,
     -- * Instruments
     -- | Invoking the instruments
-    module Csound.Control.Instr
+    module Csound.Control.Instr,
+    -- * Gui
+    -- | Interactive controllers
+    module Csound.Control.Gui
 ) where
 
 import Csound.Control.SE        
 import Csound.Control.Evt
 import Csound.Control.Instr
+import Csound.Control.Gui
 
 
diff --git a/src/Csound/Control/Evt.hs b/src/Csound/Control/Evt.hs
--- a/src/Csound/Control/Evt.hs
+++ b/src/Csound/Control/Evt.hs
@@ -5,13 +5,14 @@
     -- * Core functions
     boolToEvt, evtToBool, sigToEvt, stepper,
     filterE, filterSE, accumSE, accumE, filterAccumE, filterAccumSE,
-    Snap, snapshot, snaps,
+
+    Snap, snapshot, snaps, sync, syncBpm, 
     
     -- * Opcodes
     metroE, changedE, triggerE, 
 
     -- * Higher-level event functions
-    cycleE, iterateE, repeatE, appendE, mappendE,
+    cycleE, iterateE, repeatE, appendE, mappendE, partitionE, splitToggle,
     oneOf, freqOf, freqAccum, 
     randDs, randInts, randSkip, randSkipBy, 
     range, listAt,   
@@ -19,23 +20,39 @@
 ) where
 
 import Data.Monoid
-
+import Data.Default
 import Data.Boolean
+import Data.Tuple
 
 import Csound.Typed
 import Csound.Typed.Opcode
 
 -- | Behaves like 'Csound.Opcode.Basic.metro', but returns an event stream.
-metroE :: Sig -> Evt ()
+metroE :: Sig -> Evt Unit 
 metroE = sigToEvt . metro
 
 -- | Behaves like 'Csound.Opcode.Basic.changed', but returns an event stream.
-changedE :: [Sig] -> Evt ()
+changedE :: [Sig] ->  Evt Unit
 changedE = sigToEvt . changed
 
 -- | Behaves like 'Csound.Opcode.Basic.trigger', but returns an event stream.
-triggerE :: Sig -> Sig -> Sig -> Evt ()
+triggerE :: Sig -> Sig -> Sig -> Evt Unit 
 triggerE a1 a2 a3 = sigToEvt $ trigger a1 a2 a3
+
+-- | the sync function but time is measured in beats per minute.
+syncBpm :: (Default a, Tuple a) => D -> Evt a -> Evt a
+syncBpm dt = sync (dt / 60)
+
+-- | Splits event stream on two streams with predicate.
+partitionE :: (a -> BoolD) -> Evt a -> (Evt a, Evt a)
+partitionE p evts = (a, b)
+    where 
+        a = filterE p          evts
+        b = filterE (notB . p) evts
+
+-- | Splits a toggle event stream on on-events and off-events.
+splitToggle :: Evt D -> (Evt D, Evt D)
+splitToggle = swap . partitionE (==* 0)
 
 ----------------------------------------------------------------------
 -- higher level evt-funs
diff --git a/src/Csound/Control/Gui.hs b/src/Csound/Control/Gui.hs
new file mode 100644
--- /dev/null
+++ b/src/Csound/Control/Gui.hs
@@ -0,0 +1,70 @@
+-- | GUI (Graphical User Interface) elements are handy to change 
+-- the parameters of the sound in real time. It includes sliders, 
+-- knobs, rollers, buttons and other widgets. 
+--
+-- A GUI element consists of two parts. They are view (how it looks)
+-- and logic (what's going on with it). For example a slider can be
+-- horizontal or vertical or green or yellow or small or big. It's the view 
+-- of the slider. And a slider can produce a continuous signal within the 
+-- given interval. It's a logic of the slider. 
+--
+-- Let's talk about the view. The view is divided on two parts:
+--
+-- * where element is placed or Layout. 
+--
+-- * all other  properties or just Properties. 
+--
+-- The layout is defined with very simple functions. There are vertical and horizontal grouping 
+-- of the elements. We can scale the element within the group and include an empty
+-- space in the group. Everything is aligned (see "Csound.Gui.Layout"). 
+-- Other properties include colors, fonts (size and type), borders, specific properties 
+-- of the widgets (see "Csound.Gui.Props").
+--
+-- Let's consider the logic. The logic consists of three parts:
+--
+-- * what is consumed ('Csound.Gui.Output')
+--
+-- * what is produced ('Csound.Gui.Input')
+--
+-- * what's going on inside ('Csound.Gui.Inner')
+--
+-- A widget can react on values, produce values or do something useful. 
+-- There are special types of widgets:
+--
+-- * 'Csound.Gui.Source'  - they produce values only
+--
+-- * 'Csound.Gui.Sink'    - they consume values only
+--
+-- * 'Csound.Gui.Display' - something is going on inside them (for example, it can show a "hello world" message)
+-- 
+--
+-- Widgets can be simple and compound. Simple widgets are primitive elements
+-- (sliders, knobs, rollers, buttons). We have a special constructors that 
+-- produce simple widgets (see "Csound.Gui.Widget"). Compound widgets glue together
+-- several widgets. That is the view contains several elements and all of them 
+-- involved in the logic of the widget.
+--
+--
+module Csound.Control.Gui (
+    -- * Gui
+    Gui, 
+    Widget, Input, Output, Inner,
+    Sink, Source, Display,
+    widget, sink, source, display,
+    
+    -- * Panels
+    panel, panels, panelBy,
+    keyPanel, keyPanels, keyPanelBy,
+
+    -- * Re-exports
+    module Csound.Control.Gui.Layout,
+    module Csound.Control.Gui.Props,
+    module Csound.Control.Gui.Widget
+) where
+
+import Csound.Typed.Gui
+
+import Csound.Control.Gui.Layout
+import Csound.Control.Gui.Props
+import Csound.Control.Gui.Widget
+
diff --git a/src/Csound/Control/Gui/Layout.hs b/src/Csound/Control/Gui/Layout.hs
new file mode 100644
--- /dev/null
+++ b/src/Csound/Control/Gui/Layout.hs
@@ -0,0 +1,18 @@
+-- | The functions from this module specify the geometry 
+-- of the GUI-elements. They tell where to render the elements.
+--
+-- Every element is rectangular. To know where to place the element is 
+-- to know the parameters of the bounding rectangle. All rectangles are
+-- relative and automatically aligned. 
+--
+-- We have two functions for grouping. They construct horizontal and vertical
+-- groups of the elements. Within the group we can change the relative size 
+-- of the rectangles (by scaling one side of the rectangle). In place of rectangle
+-- we can put an empty space. 
+module Csound.Control.Gui.Layout (
+    hor, ver, space, sca, horSca, verSca, 
+    padding, margin
+) where
+
+import Csound.Typed.Gui
+
diff --git a/src/Csound/Control/Gui/Props.hs b/src/Csound/Control/Gui/Props.hs
new file mode 100644
--- /dev/null
+++ b/src/Csound/Control/Gui/Props.hs
@@ -0,0 +1,22 @@
+-- | Properties that specify the appearance of the GUI elements. 
+-- The specification is inspired by CSS. All properties
+-- are set in the cascade manner. For example, if you want to change the font type
+-- for all elements you should set this property only for the top-most GUI element.
+-- If the property is set on the lower level it wins versus property that is set on the 
+-- higher level. 
+module Csound.Control.Gui.Props (
+    -- * Properties
+    props, forceProps,
+    Prop(..), BorderType(..), Color,
+    Rect(..), FontType(..), Emphasis(..), 
+    Material(..), Orient(..), 
+
+    -- * Setters
+    -- | Handy short-cuts for the function @props@.
+    setBorder, setLabel, setMaterial, 
+    setColor1, setColor2, setColors, setTextColor,
+    setFontSize, setFontType, setEmphasis, setOrient
+) where
+
+import Csound.Typed.Gui
+
diff --git a/src/Csound/Control/Gui/Widget.hs b/src/Csound/Control/Gui/Widget.hs
new file mode 100644
--- /dev/null
+++ b/src/Csound/Control/Gui/Widget.hs
@@ -0,0 +1,100 @@
+-- | Primitive GUI elements.
+--
+-- There is a convention that constructors take only parameters that 
+-- specify the logic of the widget. The view is set for GUI-elements with 
+-- other functions.
+module Csound.Control.Gui.Widget (
+    -- * Common properties 
+    ValDiap(..), ValStep, ValScaleType(..), ValSpan(..),
+    linSpan, expSpan, uspan, bspan, uspanExp,
+    -- * Valuators
+    count, countSig, joy, 
+    knob, KnobType(..), setKnobType,
+    roller, 
+    slider, sliderBank, SliderType(..), setSliderType,
+    numeric, TextType(..), setTextType,
+
+    -- * Other widgets
+    box, BoxType(..), setBoxType,
+    button, ButtonType(..), setButtonType, 
+    toggle, butBank, toggleSig, butBankSig,
+    butBank1, butBankSig1, 
+    radioButton, matrixButton, funnyRadio, funnyMatrix,
+    value, meter,
+    -- * Transformers
+    setTitle,
+    -- * Keyboard
+    KeyEvt(..), Key(..), keyIn, charOn, charOff
+) where
+
+import Data.List(transpose)
+import Data.Boolean
+
+import Csound.Typed.Gui
+import Csound.Typed.Types
+import Csound.Control.Evt(listAt)
+
+--------------------------------------------------------------------
+-- aux widgets
+
+readMatrix :: Int -> Int -> [a] -> [a]
+readMatrix xn yn as = transp $ take (xn * yn) $ as ++ repeat (head as)
+    where 
+        transp xs = concat $ transpose $ parts yn xn xs
+        parts x y qs 
+            | x == 0    = []
+            | otherwise = a : parts (x - 1) y b
+            where (a, b) = splitAt y qs
+
+-- | A radio button. It takes a list of values with labels.
+radioButton :: Arg a => String -> [(String, a)] -> Int -> Source (Evt a)
+radioButton title as initVal = source $ do
+    (g, ind) <- butBank1 "" 1 (length as) (0, initVal)
+    gnames   <- mapM box names
+    let val = listAt vals ind    
+    gui <- setTitle title $ padding 0 $ hor [sca 0.15 g, ver gnames]
+    return (gui, val)
+    where (names, vals) = unzip as
+
+-- | A matrix of values.
+matrixButton :: Arg a => String -> Int -> Int -> [a] -> (Int, Int) -> Source (Evt a)
+matrixButton name xn yn vals initVal = source $ do
+    (gui, ind) <- butBank1 name xn yn initVal
+    let val = listAt allVals ind
+    return (gui, val)
+    where allVals = readMatrix xn yn vals
+
+-- | Radio button that returns functions. Useful for picking a waveform or type of filter.
+funnyRadio :: Tuple b => String -> [(String, a -> b)] -> Int -> Source (a -> b)
+funnyRadio name as initVal = source $ do
+    (gui, ind) <- radioButton name (zip names (fmap int [0 ..])) initVal
+    contInd <- stepper (sig $ int initVal) $ fmap sig ind
+    let instr x = guardedTuple (
+                zipWith (\n f -> (contInd ==* (sig $ int n), f x)) [0 ..] funs
+            ) (head funs x)
+    return (gui, instr)
+    where (names, funs) = unzip as
+
+-- | Matrix of functional values.
+funnyMatrix :: Tuple b => String -> Int -> Int -> [(a -> b)] -> (Int, Int) -> Source (a -> b)
+funnyMatrix name xn yn funs initVal@(x0, y0) = source $ do
+    (gui, ind) <- butBank1 name xn yn initVal
+    contInd <- stepper flattenInitVal $ fmap sig ind
+    let instr x = guardedTuple (
+                zipWith (\n f -> (contInd ==* (sig $ int n), f x)) [0 ..] allFuns
+            ) (head allFuns x)
+    return (gui, instr)
+    where 
+        allFuns = readMatrix xn yn funs
+        flattenInitVal = sig $ int $ y0 + x0 * yn
+
+
+-- | Shortcut for press 'CharKey' events.
+charOn :: Char -> Evt Unit
+charOn  = keyIn . Press   . CharKey
+
+-- | Shortcut for release 'CharKey' events.
+charOff :: Char -> Evt Unit
+charOff = keyIn . Release . CharKey
+
+
diff --git a/src/Csound/Control/Instr.hs b/src/Csound/Control/Instr.hs
--- a/src/Csound/Control/Instr.hs
+++ b/src/Csound/Control/Instr.hs
@@ -83,8 +83,8 @@
     cpsmidi, ampmidi,
 
     -- * Evt            
-    trig, sched, schedHarp,
-    trig_, sched_, 
+    trig, sched, schedHarp, schedUntil, schedToggle,
+    trig_, sched_, schedUntil_, 
     trigBy, schedBy, schedHarpBy,
     withDur,
 
@@ -97,7 +97,7 @@
 import Csound.Typed.Opcode
 import Csound.Control.Overload
 
-import Csound.Control.Evt(metroE, repeatE)
+import Csound.Control.Evt(metroE, repeatE, splitToggle)
 
 --------------------------------------------------------------------------
 -- midi
@@ -129,4 +129,32 @@
         dur   = double $ csdEventListDur notes
 
         instr _ = mix_ notes
+
+
+-- | Invokes an instrument with first event stream and 
+-- holds the note until the second event stream is active.
+schedUntil :: (Arg a, Sigs b) => (a -> SE b) -> Evt a -> Evt c -> b
+schedUntil instr onEvt offEvt = sched instr' $ withDur (-1) onEvt
+    where 
+        instr' x = do 
+            res <- instr x
+            runEvt offEvt $ const $ turnoff
+            return res
+
+-- | Invokes an instrument with toggle event stream (1 stands for on and 0 stands for off).
+schedToggle :: (Sigs b) => SE b -> Evt D -> b
+schedToggle res evt = schedUntil instr on off
+    where 
+        instr = const res
+        (on, off) = splitToggle evt
+
+-- | Invokes an instrument with first event stream and 
+-- holds the note until the second event stream is active.
+schedUntil_ :: (Arg a) => (a -> SE ()) -> Evt a -> Evt c -> SE ()
+schedUntil_ instr onEvt offEvt = sched_ instr' $ withDur (-1) onEvt
+    where 
+        instr' x = do 
+            res <- instr x
+            runEvt offEvt $ const $ turnoff
+            return res
 
