All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.sciss.synth.Node.scala Maven / Gradle / Ivy

/*
 *  Node.scala
 *  (ScalaCollider)
 *
 *  Copyright (c) 2008-2019 Hanns Holger Rutz. All rights reserved.
 *
 *  This software is published under the GNU Lesser General Public License v2.1+
 *
 *
 *  For further information, please contact Hanns Holger Rutz at
 *  [email protected]
 */

package de.sciss.synth

import de.sciss.model.Model
import de.sciss.model.impl.ModelImpl

/** A representation for a node on the server's tree. A `Node` is either a `Synth` or a `Group`.
  *
  * '''Note''' that if the node is a group, all messages send to the node which are not specific to a
  * `Synth` or `Group`, i.e. all messages found in this class, will affect all child nodes of the group.
  * For example, if `release()` is called on a `Group`, the underlying `setMsg` is propagated to all
  * `Synth`s in the tree whose root is this group.
  */
object Node {
  type Listener = Model.Listener[NodeManager.NodeChange]
}
abstract class Node extends ModelImpl[NodeManager.NodeChange] {

  // ---- abstract ----
  def server: Server

  def id: Int

  final def register(): Unit = server.nodeManager.register(this)

  final def onGo(thunk: => Unit): Unit = {
    register()
    lazy val l: Node.Listener = {
      case NodeManager.NodeGo(_, _) =>
        removeListener(l)
        thunk
    }
    addListener(l)
  }

  final def onEnd(thunk: => Unit): Unit = {
    register()
    lazy val l: Node.Listener = {
      case NodeManager.NodeEnd(_, _) =>
        removeListener(l)
        thunk
    }
    addListener(l)
  }

  final protected[synth] def updated(change: NodeManager.NodeChange): Unit =
    dispatch(change) // XXX need to update isPlaying, isRunning etc.

  def freeMsg = message.NodeFree(id)

  /** Returns an OSC message to resume the node if it was paused.
    *
    * @see [[de.sciss.synth.message.NodeRun]]
    */
  def runMsg: message.NodeRun = runMsg(flag = true)

  /** Returns an OSC message to resume the node if it was paused.
    *
    * @param flag if `true` the node is resumed, if `false` it is paused.
    *
    * @see [[de.sciss.synth.message.NodeRun]]
    */
  def runMsg(flag: Boolean) = message.NodeRun(id -> flag)

  def setMsg(pairs: ControlSet*) = message.NodeSet(id, pairs: _*)

  def setnMsg(pairs: ControlSet*) = message.NodeSetn(id, pairs: _*)

  def traceMsg = message.NodeTrace(id)

  // def releaseMsg: message.NodeSet = releaseMsg(None)

  /** A utility method which calls `setMsg` assuming a control named `gate`. The release time
    * argument is modified to correspond with the interpretation of the `gate` argument in
    * an `EnvGen` UGen. This is the case for synths created with the package method `play`.
    *
    * @param   releaseTime the optional release time in seconds within which the synth should fade out,
    *                      or `-1` (default) if the envelope should be released at its nominal release time.
    *                      If the `EnvGen` has a `doneAction` of `freeSelf`, the synth will be freed after
    *                      the release phase.
    *
    * @see  [[de.sciss.synth.ugen.EnvGen]]
    * @see  [[de.sciss.synth.message.NodeSet]]
    */
  def releaseMsg(releaseTime: Double = -1.0): message.NodeSet = {
    val gate = if (releaseTime < 0) 0.0 else -1.0 - releaseTime
    setMsg("gate" -> gate)
  }

  def mapMsg(pairs: ControlKBusMap.Single*) = message.NodeMap(id, pairs: _*)

  def mapnMsg(mappings: ControlKBusMap*) = message.NodeMapn(id, mappings: _*)

  /** Returns an OSC message to map from an mono-channel audio bus to one of the node's controls.
    *
    * Note that a mapped control acts similar to an `InFeedback` UGen in that it does not matter
    * whether the audio bus was written before the execution of the synth whose control is mapped or not.
    * If it was written before, no delay is introduced, otherwise a delay of one control block is introduced.
    *
    * @see  [[de.sciss.synth.ugen.InFeedback]]
    */
  def mapaMsg(pairs: ControlABusMap.Single*) = message.NodeMapa(id, pairs: _*)

  /** Returns an OSC message to map from an mono- or multi-channel audio bus to one of the node's controls.
    *
    * Note that a mapped control acts similar to an `InFeedback` UGen in that it does not matter
    * whether the audio bus was written before the execution of the synth whose control is mapped or not.
    * If it was written before, no delay is introduced, otherwise a delay of one control block is introduced.
    *
    * @see  [[de.sciss.synth.ugen.InFeedback]]
    */
  def mapanMsg(mappings: ControlABusMap*) =
    message.NodeMapan(id, mappings: _*)

  //  def fillMsg(control: Any, numChannels: Int, value: Float) =
  //    message.NodeFill(id, message.NodeFill.Data(control, numChannels, value))

  def fillMsg(data: ControlFillRange*) = message.NodeFill(id, data: _*)

  /** Creates an OSC message to move this node before another node
    *
    * @param   node  the node before which to move this node
    *
    * @see  [[de.sciss.synth.message.NodeBefore]]
    */
  def moveBeforeMsg(node: Node) = message.NodeBefore(id -> node.id)

  /** Creates an OSC message to move this node after another node
    *
    * @param   node  the node after which to move this node
    *
    * @see  [[de.sciss.synth.message.NodeAfter]]
    */
  def moveAfterMsg(node: Node) = message.NodeAfter(id -> node.id)

  def moveToHeadMsg(group: Group): message.GroupHead = group.moveNodeToHeadMsg(this)

  def moveToTailMsg(group: Group): message.GroupTail = group.moveNodeToTailMsg(this)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy