diff --git a/README b/README
--- a/README
+++ b/README
@@ -5,9 +5,8 @@
 Build
 -----
 
-    $ ghc -O2 -Wall --make bowntz.hs
-
-    Bowntz requires hsc3 >= 0.8 (newer than Hackage, as of 2010-03-12).
+    $ cabal sandbox init
+    $ cabal install
 
 
 Usage
diff --git a/bowntz.cabal b/bowntz.cabal
--- a/bowntz.cabal
+++ b/bowntz.cabal
@@ -1,12 +1,12 @@
 name:                bowntz
-version:             1
+version:             2
 synopsis:            audio-visual pseudo-physical simulation of colliding circles
 homepage:            https://code.mathr.co.uk/bowntz
 license:             GPL-3
 license-file:        COPYING
 author:              Claude Heiland-Allen
 maintainer:          claude@mathr.co.uk
-copyright:           2010,2013,2015,2016 Claude Heiland-Allen
+copyright:           2010,2013,2015,2016,2019 Claude Heiland-Allen
 category:            Demo
 build-type:          Simple
 extra-source-files:  README
@@ -14,11 +14,11 @@
 
 executable bowntz
   main-is:             bowntz.hs
-  build-depends:       base >=4.8 && <4.10
-                     , containers >= 0.5 && <0.6
+  build-depends:       base >=4.8 && <4.14
+                     , containers >= 0.5 && <0.7
                      , GLUT >=2.7 && <2.8
-                     , hosc >=0.15 && <0.16
-                     , hsc3 >=0.15 && <0.16
+                     , hosc >=0.17 && <0.18
+                     , hsc3 >=0.17 && <0.18
                      , random >=1.1 && <1.2
   default-language:    Haskell2010
 
@@ -29,4 +29,4 @@
 source-repository this
   type:     git
   location: https://code.mathr.co.uk/bowntz.git
-  tag:      v1
+  tag:      v2
diff --git a/bowntz.hs b/bowntz.hs
--- a/bowntz.hs
+++ b/bowntz.hs
@@ -266,7 +266,7 @@
   initialWindowSize $= Size 788 576
   initialDisplayMode $= [RGBAMode, DoubleBuffered]
   _ <- createWindow "bowntz"
-  withSC3 (send (g_new [(1, AddToTail, 0)])) -- new group 1 under root 0 group
+  withSC3 (sendMessage (g_new [(1, AddToTail, 0)])) -- new group 1 under root 0 group
   _ <- withSC3 ballSynth
   t0 <- time
   w <- insertBall (Ball{ mass = 1e6, radius = 1, position = V 0 0, velocity = V 0 0, ring = 0 }) $ initialWorld (realToFrac t0)
@@ -279,7 +279,7 @@
   mainLoop
 
 createBall :: ID -> Ball -> IO ()
-createBall i b = withSC3 (send (s_new "Ball" (fromIntegral i) AddToTail 1 [("freq", realToFrac $ 50 / radius b)]))
+createBall i b = withSC3 (sendMessage (s_new "Ball" (fromIntegral i) AddToTail 1 [("freq", realToFrac $ 50 / radius b)]))
 
 triggerBall :: R -> ID -> Double -> IO ()
 triggerBall t i v = withSC3 (sendBundle (bundle (realToFrac (t + latency)) [n_set1 (fromIntegral i) "t_amp" v]))
@@ -288,7 +288,7 @@
 ballSynth = do let f = control IR "freq" 0
                    a = tr_control "t_amp" 0
                    d = out 0 (fSinOsc AR (mce [f, f]) 0 * (SC.decay a 0.7))
-               send (d_recv (synthdef "Ball" d))
+               sendMessage (d_recv (synthdef "Ball" d))
                waitAddress "/done"
 
 minSize, maxSize, minDensity, maxDensity, spawnThreshold, spawnEnergy, decay, elasticity, latency :: R
