All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
de.sciss.mellite.impl.audiocue.AudioCueViewJ.scala Maven / Gradle / Ivy
/*
* AudioCueViewJ.scala
* (Mellite)
*
* Copyright (c) 2012-2023 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.mellite.impl.audiocue
import java.awt.{Color, Graphics2D, RenderingHints}
import de.sciss.audiowidgets.TimelineModel
import de.sciss.audiowidgets.impl.TimelineCanvasImpl
import de.sciss.desktop
import de.sciss.lucre.Txn
import de.sciss.lucre.swing.LucreSwing.defer
import de.sciss.mellite.Mellite.executionContext
import de.sciss.sonogram.{Overview, PaintController}
import de.sciss.proc.{TimeRef, Transport}
import de.sciss.proc.gui.TransportView
import javax.swing.JComponent
import scala.swing.Component
import scala.swing.Swing._
import scala.swing.event.MousePressed
import scala.util.{Failure, Success}
final class AudioCueViewJ[T <: Txn[T]](sonogram: Overview, transportView: TransportView[T])
extends TimelineCanvasImpl {
import TimelineCanvasImpl._
transportView.catchOption = Some(transportCatch)
protected def transportRunning: Boolean = transportView.isPlayingEDT
protected def transport: Transport[T] = transportView.transport
protected def transportPause (): Unit = {
val t = transport
t.scheduler.cursor.step { implicit tx => t.stop() }
}
protected def transportResume(): Unit = {
val t = transport
val p = timelineModel.position
t.scheduler.stepTag { implicit tx =>
t.seek(p)
t.play()
}
}
def timelineModel: TimelineModel = transportView.timelineModel
def visualBoost: Float = canvasComponent.sonogramBoost
def visualBoost_=(value: Float): Unit = {
canvasComponent.sonogramBoost = value
canvasComponent.repaint()
}
object canvasComponent extends Component with PaintController {
private[this] var paintFun: Graphics2D => Unit = paintChecker("Calculating...")
private[this] val srRatio = sonogram.inputSpec.sampleRate / TimeRef.SampleRate
private[AudioCueViewJ] var sonogramBoost: Float = 1f
opaque = true
override def paintComponent(g: Graphics2D): Unit = {
// Warning: there is a strange bug (at least in Linux),
// where the XOR mode breaks if we do not initially fill
// the background, even if the sonogram is painted all
// across the background. The bug manifests itself by
// not drawing the timeline position if it intersects
// with the timeline selection (i.e. if there were
// previous `fillRect` or `drawLine` commands on those pixels.
val w = width
val h = height
g.clearRect(0, 0, w, h)
paintFun(g)
paintPosAndSelection(g, h)
}
@inline def width : Int = peer.getWidth
@inline def height: Int = peer.getHeight
preferredSize = {
val b = desktop.Util.maximumWindowBounds
(b.width >> 1, b.height >> 1)
}
private def paintChecker(message: String)(g: Graphics2D): Unit = {
g.setPaint(pntChecker)
g.fillRect(0, 0, width, height)
g.setColor(Color.white)
g.drawString(message, 10, 20)
}
private def paintReady(g: Graphics2D): Unit = {
val visSpan = timelineModel.visible
val fileStart = visSpan.start * srRatio
val fileStop = visSpan.stop * srRatio
val hintOld0 = g.getRenderingHint(RenderingHints.KEY_INTERPOLATION)
val hintOld = if (hintOld0 == null) RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR else hintOld0
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC)
sonogram.paint(spanStart = fileStart, spanStop = fileStop, g, 0, 0, width, height, this)
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hintOld)
}
def adjustGain(amp: Float, pos: Double): Float = amp * sonogramBoost
def imageObserver: JComponent = peer
private def ready(): Unit = {
paintFun = paintReady
repaint()
}
private def failed(exception: Throwable): Unit = {
val message = s"${exception.getClass.getName} - ${exception.getMessage}"
paintFun = paintChecker(message)
repaint()
}
// ---- constructor ----
sonogram.onComplete {
case Success(_) => /* println("SUCCESS"); */ defer(ready())
case Failure(e) => /* println("FAILURE"); */ defer(failed(e))
}
listenTo(mouse.clicks)
reactions += {
case _: MousePressed => requestFocus()
}
}
// private val meterPane = new BoxPanel(Orientation.Vertical) {
// meters.foreach(m => contents += Component.wrap(m))
// }
}