;nyquist plug-in
;version 4
;type tool
;name "Loop Processing"
;author "Steve Daulton"
;release 2.4.2
;copyright "GPLv2+."

;control num "Number of sections" int "" 5 2 20
;control mode "Mode" choice "Analyze,Select" 0


; A unique ID for this plug-in
(setf id "loop_processing_04012022_13:26")

;;; Generate property symbol names
(defun propgen (id prop)
  (eval (read (make-string-input-stream 
      (format nil "'~a_~a" id prop)))))

;; Properties:
;; startpoints. A list of selection start points
;; counter = 0. The index of the next start point
;; selnum. Overrides the "Number of sections" control when selecting.
(setf counter (propgen id "counter"))
(setf startpoints (propgen id "startpoints"))
(setf selnum (propgen id "selnum"))


(defun start-end ()
   ;;; Return list(track-start-time track-end-time)
   ;;; for focused track.
   (let ((tracks (aud-get-info "tracks"))
         start end)
      (dolist (trk tracks)
         (when (= (second (assoc 'focused trk)) 1)
            (return-from start-end
               (list (second (assoc 'start trk))
                     (second (assoc 'end trk))))))))


(defun sel-range (t0 t1)
   ;;; Select from t0 to t1.
  (aud-do-command "select" :start t0 :end t1))

(defun sel-final (t0)
   ;;; Select from t0 to end of track.
  (aud-do-command "select" :start t0 :end t0)
  (aud-do "SelCursorToTrackEnd")
  (reset))

(defun sel-first (t1)
   ;;; Select from start of track to t1.
  (aud-do-command "select" :start t1 :end t1)
  (aud-do "SelTrackStartToCursor"))

(defun select()
  (let ((count (get '*scratch* counter))
        (starts (get '*scratch* startpoints))
        (num (get '*scratch* selnum)))
    (cond
      ((= count 0)
          (sel-first (first starts)))
      ((< count (- num 1))
          (sel-range (nth (1- count) starts) (nth count starts)))
      (t (sel-final (nth (1- count) starts))))
   (putprop '*scratch* (1+ count) counter)))


(defun reset()
  (remprop '*scratch* counter)
  (remprop '*scratch* startpoints)
  (remprop '*scratch* selnum))


(defun analyze()
  (reset)
  (putprop '*scratch* 0 counter)
  (putprop '*scratch* num selnum)
  (let ((ends (start-end))
        (points ()))
    (setf start (float (first ends)))
    (setf end (float (second ends)))
    (setf step (/ (- end start) num))
    (dotimes (i (- num 1))
      (setf start (+ start step))
      (push start points))
    (putprop '*scratch* (reverse points) startpoints)))


(if (= mode 0)
    (analyze)
    (select))
""  ;no-op
