;; Copyright (C) 2006 Stefan Westerfeld
;;
;; This software is provided "as is"; redistribution and modification
;; is permitted, provided that the following disclaimer is retained.
;;
;; This software is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
;; In no event shall the authors or contributors be liable for any
;; direct, indirect, incidental, special, exemplary, or consequential
;; damages (including, but not limited to, procurement of substitute
;; goods or services; loss of use, data, or profits; or business
;; interruption) however caused and on any theory of liability, whether
;; in contract, strict liability, or tort (including negligence or
;; otherwise) arising in any way out of the use of this software, even
;; if advised of the possibility of such damage.

;; (bse-script-register <func> <options> <category> <blurb> <author> <license> ARGS...)
(bse-script-register 'stability-canvas
		     ""
		     (N_ "/SNet/QA/Canvas Stability Test")
		     (N_ "Performs some canvas operations repeatedly "
			 "to check that the canvas code is stable")
		     "Stefan Westerfeld"
		     "Provided \"as is\", WITHOUT ANY WARRANTY;"
		     (bse-param-snet (N_ "Synth Net"))
		     (bse-param-irange (N_ "N Iterations") '(512 0 65536 128))
		     (bse-param-irange (N_ "Tree depth") '(4 1 10 1))
		     (bse-param-irange (N_ "Time to sleep between steps") '(10 0 100 1)))

(define (stability-canvas snet iterations depth sleep-time)
  (if (not (bse-is-snet snet))
    (bse-exit-error 'text1 (_"No valid synthesis network supplied")))
  (bse-item-group-undo (bse-item-get-project snet) "stability-canvas")      ; group for tree creation
  (let
    ((nodes (create-tree snet depth 0 0))
     (project (bse-item-get-project snet))
     (uname-path (bse-item-get-uname-path snet)))
    (sleep sleep-time)
    ;(remove-tree-nodes snet nodes)  <-  we use undo/redo instead to destroy the tree
    (bse-item-ungroup-undo project)
    (sleep sleep-time)
    (bse-project-remove-snet project snet)
    (sleep sleep-time)
    (bse-item-undo project)        ; restore snet and tree
    (sleep sleep-time)
    (bse-item-undo project)        ; undo tree creation: we're in tho initial state now
    (if (> iterations 1)
      (stability-canvas (bse-project-find-item project uname-path) (1- iterations) depth sleep-time))))

;; creates a binary tree of connected summation sources
;; returns a node list: topmost tree node is first element in list
(define (create-tree snet depth x y)
  (if (> depth 0)
    (let
      ((source (bse-snet-create-source snet "BseSummation")))
      (bse-source-set-pos source x y)
      (cons
	source
	(if (> depth 1)
	  (let
	    ((left  (create-tree snet (1- depth) (- x 2) (- y (expt 2 (- depth 3)))))
	     (right (create-tree snet (1- depth) (- x 2) (+ y (expt 2 (- depth 3))))))
	    (bse-source-set-input source "audio-in1" (car left) "audio-out1")
	    (bse-source-set-input source "audio-in2" (car left) "audio-out2")
	    (bse-source-set-input source "audio-in1" (car right) "audio-out1")
	    (bse-source-set-input source "audio-in2" (car right) "audio-out2")
	    (append left right))
	  '())))))

;; removes a list of nodes from an snet
(define (remove-tree-nodes snet nodes)
  (if (not (null? nodes))
    (begin
      (bse-snet-remove-source snet (car nodes))
      (remove-tree-nodes snet (cdr nodes)))))
