         [overtone.sc.machinery.synthdef]
         [overtone.helpers seq lib]))
 
+(defn- control-ugen-name?
+  [ug-n]
+  (or (= "trig-control" ug-n)
+      (= "audio-control" ug-n)
+      (= "control" ug-n)))
+
+(defn- control-ugen?
+  [ug]
+  (control-ugen-name? (:name ug)))
+
+(defn- mk-control-id
+  [ug-id output-idx]
+  (str "control_" ug-id "_" output-idx))
+
 (defn- unify-input
   [input ugens constants]
   (if (= -1 (:src input))
     (nth constants (:index input))
-    (let [idx (:src input)]
-      {:name (:name (nth ugens idx))
-       :id idx})))
+    (let [idx (:src input)
+          n (:name (nth ugens idx))
+          id (if (control-ugen-name? (overtone-ugen-name n))
+               (mk-control-id idx (:index input))
+               idx)]
+      {:name n
+       :id id})))
 
 (defn- unify-ugen-name
   [ugen]


(defn- unify-ugen
  [ugen ugens sdef]
  {:name (unify-ugen-name ugen)
   :rate (REVERSE-RATES (:rate ugen))
   :special (:special ugen)
   :inputs (map #(unify-input % ugens (:constants sdef)) (:inputs ugen))
   :n-outputs (count (:outputs ugen))
   :outputs (:outputs ugen)
   :id (:id ugen)})

(defn- fix-input-refs
  [inputs ugens]
  (map (fn [input]
         (if (number? input)
           input
           {:name (overtone-ugen-name (:name input))
            :id (index-of ugens (find-first #(= (:id %) (:id input)) ugens))}))
       inputs))

(defn- unify-ugens
  [orig-ugens sdef]
  (let [ugens (map (fn [ug idx] (assoc ug :id idx)) orig-ugens (range))
        ugens (map #(unify-ugen % ugens sdef) ugens)
        ugens (map (fn [ug o-ug idx]
                     (let [inputs      (fix-input-refs (:inputs ug) ugens )
                           input-specs (or (:args (get-ugen-spec (:name ug)))
                                           [{:name "a"}
                                            {:name "b"}]) ]
                       (assoc ug
                         :id idx
                         :inputs (loop [res {}
                                        inputs inputs
                                        input-specs input-specs]
                                   (if (empty? input-specs)
                                     res
                                     (if (ugen-sequence-mode? (:mode (first input-specs)))
                                       (let [arg-seq (drop (dec (count input-specs)) inputs)
                                             inputs  (drop-last (count arg-seq) inputs)]
                                         (recur (assoc res (keyword (:name (first input-specs))) (vec arg-seq))
                                                inputs
                                                (rest input-specs)))

                                       (recur (assoc res (keyword (:name (first input-specs))) (first inputs))
                                              (rest inputs)
                                              (rest input-specs))))))))
                   ugens
                   orig-ugens
                   (range))]
    (sort #(compare (:name %1) (:name %2)) ugens)))

(defn- unify-synthdef-sdef
  [sdef]
  {:name    (:name sdef)
   :params  (:params sdef)
   :pnames  (:pnames sdef)
   :n-ugens (count (:ugens sdef))
   :ugens   (unify-ugens (:ugens sdef) sdef)})

(defmulti unify-synthdef
  "Munge synthdef into a readable 'unified' format - ensures that two

  [sdef]
  (unify-synthdef (:sdef sdef)))

(defmethod unify-synthdef overtone.studio.inst.Inst
  [sdef]
  (unify-synthdef (:sdef sdef)))

(defmethod unify-synthdef :default
  [sdef]
  (throw (IllegalArgumentException. (str "Unknown synthdef type to unify: " (type sdef)))))
