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

de.sciss.synth.proc.Implicits.scala Maven / Gradle / Ivy

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

package de.sciss.synth.proc

import de.sciss.lucre.expr.{BooleanObj, Expr, StringObj}
import de.sciss.lucre.stm.{Obj, Sys}
import de.sciss.span.SpanLike

import scala.language.implicitConversions

object Implicits {
  implicit class SecFrames(val `this`: Double) extends AnyVal { me =>
    import me.{`this` => d}

    /** Interprets the number as a duration in seconds, and converts it to sample frames,
      * based on the standard `Timeline` sample-rate.
      */
    def secondsToFrames: Long = (d * TimeRef.SampleRate + 0.5).toLong
  }
  
  implicit class SpanComparisons(val `this`: SpanLike) extends AnyVal {
    import `this`.{compareStart, compareStop}

    def startsBefore(frame: Long): Boolean = compareStart(frame) <  0
    def startsAt    (frame: Long): Boolean = compareStart(frame) == 0
    def startsAfter (frame: Long): Boolean = compareStart(frame) >  0

    def stopsBefore (frame: Long): Boolean = compareStop (frame) <  0
    def stopsAt     (frame: Long): Boolean = compareStop (frame) == 0
    def stopsAfter  (frame: Long): Boolean = compareStop (frame) >  0
  }

// SCAN
//  implicit class ScanOps[S <: Sys[S]](val `this`: Scan[S]) extends AnyVal {
//    /** Connects this scan as source to that scan as sink. */
//    def ~> (that: Scan[S])(implicit tx: S#Tx): Unit =
//      `this`.add(Scan.Link.Scan(that))
//
//    /** Disconnects this scan as source from that scan as sink. */
//    def ~/> (that: Scan[S])(implicit tx: S#Tx): Unit =
//      `this`.remove(Scan.Link.Scan(that))
//  }

// SCAN
//  // Scala 2.10.4 has a compiler bug that prevents putting this
//  // code inside a value class
//  private def getScanLinks[S <: Sys[S]](in: Iterator[Scan.Link[S]])
//                                             (implicit tx: S#Tx): Set[Scan.Link.Scan[S]] =
//    in.collect {
//      case l @ Scan.Link.Scan(_) => l
//    } .toSet

//  implicit class ProcPairOps[S <: Sys[S]](val `this`: (Proc[S], Proc[S])) extends AnyVal { me =>
//    import me.{`this` => pair}
//
// SCAN
//    private def getLayerIn(implicit tx: S#Tx): Scan[S] = {
//      val inObj = pair._1
//      inObj.inputs.get("in").getOrElse(sys.error(s"Proc ${inObj.name} does not have scan 'in'"))
//    }

// SCAN
//    private def getLayerOut(implicit tx: S#Tx): Scan[S] = {
//      val outObj = pair._2
//      outObj.outputs.get("out").getOrElse(sys.error(s"Proc ${outObj.name} does not have scan 'out'"))
//    }

// SCAN
//    /** Removes the signal chain signified by the input proc pair from its predecessors and successors.
//      * It does so by removing the sources of the `_1` scan named `"in"` and the sinks of the
//      * `_2` scan named `"out"`. It re-connects the predecessors and successors thus found.
//      */
//    def unlink()(implicit tx: S#Tx): Unit = {
//      val layerIn   = getLayerIn
//      val layerOut  = getLayerOut
//
//      val oldLayerIn  = getScanLinks(layerIn .iterator)
//      val oldLayerOut = getScanLinks(layerOut.iterator)
//
//      // disconnect old inputs
//      oldLayerIn .foreach(layerIn .remove)
//      // disconnect old outputs
//      oldLayerOut.foreach(layerOut.remove)
//      // connect old layer inputs to old layer outputs
//      oldLayerIn.foreach { in =>
//        oldLayerOut.foreach { out =>
//          in.peer.add(out)
//        }
//      }
//    }

// SCAN
//    def linkAfter(out: Proc[S])(implicit tx: S#Tx): Unit = {
//      val target = out.outputs.get("out").getOrElse(sys.error(s"Successor ${out.name} does not have scan 'out'"))
//      link1(target, isAfter = true)
//    }

// SCAN
//    def linkBefore(in: Proc[S])(implicit tx: S#Tx): Unit = {
//      val target = in.inputs.get("in").getOrElse(sys.error(s"Predecessor ${in.name} does not have scan 'in'"))
//      link1(target, isAfter = false)
//    }

// SCAN
//    private def link1(target: Scan[S], isAfter: Boolean)(implicit tx: S#Tx): Unit = {
//      val layerIn  = getLayerIn
//      val layerOut = getLayerOut
//
//      val targetIt  = target.iterator
//      val oldTargetLinks = getScanLinks(targetIt)
//      val layerLink = Scan.Link.Scan(if (isAfter) layerIn else layerOut)
//      // only act if we're not there
//      if (!oldTargetLinks.contains(layerLink)) {
//        unlink()
//        if (isAfter) {
//          // disconnect old diff outputs
//          oldTargetLinks.foreach(target.remove)
//          // connect old diff inputs as new layer inputs
//          oldTargetLinks.foreach(layerOut.add)
//          // connect layer output to diff input
//          target.add(layerLink)
//        } else {
//          // disconnect old diff inputs
//          oldTargetLinks.foreach(target.remove)
//          // connect old diff inputs as new layer inputs
//          oldTargetLinks.foreach(layerIn.add  )
//          // connect layer output to diff input
//          target.add(layerLink)
//        }
//      }
//    }
//  }

  implicit class FolderOps[S <: Sys[S]](val `this`: Folder[S]) extends AnyVal { me =>
    import me.{`this` => folder}

    def / (child: String)(implicit tx: S#Tx): Option[Obj[S]] = {
      val res = folder.iterator.filter { obj =>
        obj.name == child
      } .toList.headOption

      // if (res.isEmpty) warn(s"Child $child not found in $folder")
      res
    }
  }

  implicit class EnsembleOps[S <: Sys[S]](val `this`: Ensemble[S]) extends AnyVal { me =>
    import me.{`this` => ensemble}

    def / (child: String)(implicit tx: S#Tx): Option[Obj[S]] = {
      val res = ensemble.folder.iterator.filter { obj =>
        obj.name == child
      }.toList.headOption

      // if (res.isEmpty) warn(s"Child $child not found in ${ensemble.attr.name}")
      res
    }

    def play()(implicit tx: S#Tx): Unit = play1(value = true )
    def stop()(implicit tx: S#Tx): Unit = play1(value = false)

    private def play1(value: Boolean)(implicit tx: S#Tx): Unit = {
      val BooleanObj.Var(vr) = ensemble.playing
      val prev = vr()
      if (!(Expr.isConst(prev) && prev.value == value)) vr() = value
    }

    def isPlaying(implicit tx: S#Tx): Boolean = ensemble.playing.value
  }

  implicit final class ObjOps[S <: Sys[S]](val `this`: Obj[S]) extends AnyVal { me =>
    import me.{`this` => obj}

    /** Short cut for accessing the attribute `"name"`.
      * If their is no value found, a dummy string `"<unnamed>"` is returned.
      */
    def name(implicit tx: S#Tx): String =
      obj.attr.$[StringObj](ObjKeys.attrName).fold("")(_.value)

    /** Short cut for updating the attribute `"name"`. */
    def name_=(value: String)(implicit tx: S#Tx): Unit = {
      val valueC  = StringObj.newConst[S](value)
      val attr    = obj.attr
      attr.$[StringObj](ObjKeys.attrName) match {
        case Some(StringObj.Var(vr)) => vr() = valueC
        case _                  =>
          val valueVr = StringObj.newVar(valueC)
          attr.put(ObjKeys.attrName, valueVr)
      }
    }

    /** Short cut for accessing the attribute `"mute"`. */
    def muted(implicit tx: S#Tx): Boolean =
      obj.attr.$[BooleanObj](ObjKeys.attrMute).exists(_.value)

    /** Short cut for updating the attribute `"mute"`. */
    def muted_=(value: Boolean)(implicit tx: S#Tx): Unit = {
      val valueC  = BooleanObj.newConst[S](value)
      val attr    = obj.attr
      attr.$[BooleanObj](ObjKeys.attrMute) match {
        case Some(BooleanObj.Var(vr)) => vr() = valueC
        case _                  =>
          val valueVr = BooleanObj.newVar(valueC)
          attr.put(ObjKeys.attrMute, valueVr)
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy