def release(self):
         pass
 
-    def __or__(self, item):
-        return ProcessPipe(self, item)
+    def __or__(self, other):
+        return ProcessPipe(self, other)
 
 def processors(interface=IProcessor, recurse=True):
     """Returns the processors implementing a given interface and, if recurse,
 class ProcessPipe(object):
     """Handle a pipe of processors"""
 
-    def __init__(self, *processors):
-        self.processors = processors
+    def __init__(self, *others):
+        self.processors = []
+        for p in others:
+            self |= p
 
-    def __or__(self, processor):
-        p = []
-        p.extend(self.processors)
-        p.append(processor)
-        return ProcessPipe(*p)
+    def __or__(self, other):
+        return ProcessPipe(self, other)
+
+    def __ior__(self, other):
+        if isinstance(other, Processor):
+            self.processors.append(other)
+        elif isinstance(other, ProcessPipe):
+            self.processors.extend(other.processors)
+        else:
+            raise Error("Piped item is neither a Processor nor a ProcessPipe")
+
+        return self            
 
     def run(self):
         """Setup/reset all processors in cascade and stream audio data along
 
 import os
 source=os.path.dirname(__file__) + "../samples/guitar.wav"
 
+print "Normalizing %s" % source
 decoder  = examples.FileDecoder(source)
 maxlevel = examples.MaxLevel()
 
 gain     = examples.Gain(gain)
 encoder  = examples.WavEncoder("normalized.wav")
 
-(decoder | gain | maxlevel | encoder).run()
+subpipe  = gain | maxlevel
+
+(decoder | subpipe | encoder).run()
 
 print "output maxlevel: %f" % maxlevel.result()
+
+