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

de.sciss.proc.gui.impl.ScopeBaseImpl.scala Maven / Gradle / Ivy

/*
 *  ScopeBaseImpl.scala
 *  (SoundProcesses)
 *
 *  Copyright (c) 2010-2024 Hanns Holger Rutz. All rights reserved.
 *
 *	This software is published under the GNU Affero General Public License v3+
 *
 *
 *  For further information, please contact Hanns Holger Rutz at
 *  [email protected]
 */

package de.sciss.proc.gui.impl

import de.sciss.lucre.Txn.peer
import de.sciss.lucre.swing.LucreSwing.{deferTx, requireEDT}
import de.sciss.lucre.synth.{AudioBus, Buffer, Bus, ControlBus, Group, RT, Server, Synth}
import de.sciss.proc.gui.ScopeBase
import de.sciss.synth.swing.j.JScopeView.Config
import de.sciss.synth.{AddAction, SynthGraph, addToTail, AudioBus => SAudioBus, Bus => SBus, ControlBus => SControlBus}

import javax.swing.JComponent
import scala.concurrent.stm.Ref

abstract class ScopeBaseImpl[P <: ScopePanelBaseImpl[P]](server: Server) extends ScopeBase
  with AudioBus   .User
  with ControlBus .User {

  private[this] val busRef  = Ref.make[Bus]()
  private[this] val tgtRef  = Ref.make[Group]()
  private[this] val aaRef   = Ref[AddAction](addToTail)
  private[this] val synRef  = Ref(Option.empty[Synth])
  private[this] var _panel: JComponent with P = _

  protected def mkPanel(): JComponent with P

  protected def panel: JComponent with P = _panel

  def initGUI(channelStyle: Int, bufSize: Int, xZoom: Double, yZoom: Double, logAmp: Boolean, logAmpMin: Double): Unit = {
    requireEDT()
    val p           = mkPanel() // new PanelImpl(this)
    p.channelStyle  = channelStyle
    p.bufferSize    = bufSize
    p.xZoom         = xZoom.toFloat
    p.yZoom         = yZoom.toFloat
    p.logAmp        = logAmp
    p.logAmpMin     = logAmpMin.toFloat
    _panel          = p
  }

  def target(implicit tx: RT): Group = {
    val _bus    = bus
    val _target = tgtRef()
    if (_target != null || _bus == null) _target else _bus.server.rootNode
  }

  def target_=(value: Group)(implicit tx: RT): Unit = {
    //    val old = target
    tgtRef() = value
    //    if (value != old) {
    //    }
  }

  def addAction(implicit tx: RT): AddAction = aaRef()

  def addAction_=(value: AddAction)(implicit tx: RT): Unit =
    aaRef() = value

  def bus(implicit tx: RT): Bus = busRef()

  def bus_=(b: Bus)(implicit tx: RT): Unit = {
    val old = busRef.swap(b)
    if (old != null) old match {
      case ab: AudioBus   => ab.removeReader(this)
      case cb: ControlBus => cb.removeReader(this)
    }
    if (b != null) {
      require (b.server == server)
      b match {
        case ab: AudioBus   => ab.addReader(this)
        case cb: ControlBus => cb.addReader(this)
      }
    }
  }

  def start()(implicit tx: RT): Unit =
    deferTx {
      component.start()
    }

  def stop()(implicit tx: RT): Unit =
    deferTx {
      component.stop()
    }

  def dispose()(implicit tx: RT): Unit = {
    bus = null
    synRef.swap(None).foreach(_.free())
    deferTx {
      component.dispose()
    }
  }

  def busChanged(peer: SAudioBus, isDummy: Boolean)(implicit tx: RT): Unit = if (!isDummy) {
    deferTx {
      _panel.bus = peer
    }
  }

  def busChanged(peer: SControlBus)(implicit tx: RT): Unit = {
    deferTx {
      _panel.bus = peer
    }
  }

  def mkBusSynthTx(_bus: SBus)(implicit tx: RT): Unit = {
    val numChannels = _bus.numChannels
    val oldSyn      = synRef()

    if (numChannels > 0) {
      val gr = SynthGraph {
        _panel.mkSynthGraphImpl(_bus)
      }
      val useFrames = _panel.bufferSize
      val s         = _bus.server
      // this is a bit tricky; we don't know the buffer and node at this point, so we have to copy the object
      val cfg0      = Config.default(s, bufId = -1, useFrames = useFrames, numChannels = numChannels, nodeId = -1)
      val bufFrames = cfg0.bufFrames
      val b         = Buffer(server)(numFrames = bufFrames, numChannels = numChannels)
      val trFreq    = Config.defaultTrigFreq(s)
      val syn       = Synth.play(gr, nameHint = Some("scope"))(target = target,
        args = List("out" -> _bus.index, "buf" -> b.id, "freq" -> trFreq),
        addAction = addAction, dependencies = b :: Nil)
      val cfg       = cfg0.copy(bufId = b.id, nodeId = syn.peer.id)
      syn.onEndTxn { implicit tx => b.dispose() }
      synRef()      = Some(syn)

      deferTx {
        _panel.config = cfg
      }

    } else {
      deferTx {
        _panel.config = Config.Empty
      }
    }
    oldSyn.foreach(_.dispose())
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy