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

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

/*
 *  NodeManager.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.impl.ModelImpl
import de.sciss.model.Model

object NodeManager {
  type Listener = Model.Listener[NodeManager.Update]

  sealed trait Update

  abstract sealed class NodeChange extends Update {
    def node: Node
    def info: message.NodeInfo.Data
  }

  final case class NodeGo   (node: Node, info: message.NodeInfo.Data) extends NodeChange
  final case class NodeEnd  (node: Node, info: message.NodeInfo.Data) extends NodeChange
  final case class NodeOn   (node: Node, info: message.NodeInfo.Data) extends NodeChange
  final case class NodeOff  (node: Node, info: message.NodeInfo.Data) extends NodeChange
  final case class NodeMove (node: Node, info: message.NodeInfo.Data) extends NodeChange

  case object Cleared extends Update
}

final class NodeManager(val server: Server) extends ModelImpl[NodeManager.Update] {
  import NodeManager._

  private[this] var nodes: Map[Int, Node] = _
  private[this] val sync     = new AnyRef

  // ---- constructor ----
  clear()

  //      if( server.isRunning ) {
  //         val defaultGroup = server.defaultGroup
  //         nodes += defaultGroup.id -> defaultGroup
  //      }

  def nodeChange(e: message.NodeChange): Unit =
    e match {
      case message.NodeGo(nodeId, info) =>
        nodes.get(nodeId) match {
          case Some(node) =>
            dispatchBoth(NodeGo(node, info))

          case None =>
            if ( /* autoAdd && */ nodes.contains(info.parentId)) {
              val created = info match {
                case _: message.NodeInfo.SynthData => Synth(server, nodeId)
                case _: message.NodeInfo.GroupData => Group(server, nodeId)
              }
              register(created)
              dispatchBoth(NodeGo(created, info))
            }
          }

      case message.NodeEnd(nodeId, info) =>
        // println(s"---- NodeEnd: ${nodes.get(nodeId)}")
        nodes.get(nodeId) match {
          case Some(node) =>
            unregister(node)
            dispatchBoth(NodeEnd(node, info))
          case None =>
        }

      case message.NodeOff(nodeId, info) =>
        nodes.get(nodeId) match {
          case Some(node) =>
            dispatchBoth(NodeOff(node, info))
          case None =>
        }

      case message.NodeOn(nodeId, info) =>
        nodes.get(nodeId) match {
          case Some(node) =>
            dispatchBoth(NodeOn(node, info))
          case None =>
        }

      case message.NodeMove(nodeId, info) =>
        nodes.get(nodeId) match {
          case Some(node) =>
            dispatchBoth(NodeMove(node, info))
          case None =>
        }

      case _ =>
    }

  private def dispatchBoth(change: NodeChange): Unit = {
    dispatch(change)
    change.node.updated(change)
  }

  // eventually this should be done automatically
  // by the message dispatch management
  def register(node: Node): Unit =
    sync.synchronized {
      // println(s"---- register node: $node")
      nodes += node.id -> node
    }

  def unregister(node: Node): Unit =
    sync.synchronized {
      // println(s"---- unregister node: $node")
      nodes -= node.id
    }

  def getNode(id: Int): Option[Node] = nodes.get(id)  // sync.synchronized { }

  def clear(): Unit = {
    val rootNode = server.rootNode // new Group( server, 0 )
    sync.synchronized {
      nodes = Map(rootNode.id -> rootNode)
    }
    dispatch(Cleared)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy