0

I have a rather long running task in sbt and would like to be notified audibly after it finished, even it if failed. I got partially there with this crudeness:

lazy val ding = taskKey[Unit]("plays a ding sound")
ding := {
  Seq("play", "-q", "/…/SmallGlockA.wav").run
}

I invoke aforementioned task like such:

sbt> ;test;ding

And while this works well if the task succeeded, it will of course not play the sound if the task failed, which – given that it's tests – is likely.

Any ideas how I can work around this? It doesn't have to be pretty or super robust – this will not get committed, it will just be a local thing for me.

Ivan Stanislavciuc
  • 7,140
  • 15
  • 18
phdoerfler
  • 470
  • 6
  • 19

1 Answers1

1

The solution I came up with is to create an AutoPlugin for sbt that does what you need.

Create a new file in project folder named DingPlugin.scala with following content

import sbt.Keys._
import sbt.PluginTrigger.AllRequirements
import sbt._

object DingPlugin extends AutoPlugin {

  private def wavPath = "/path/to/wav"
  private def playSound(wav: String) = ???

  override def trigger = AllRequirements

  override def projectSettings: Seq[Def.Setting[_]] = Seq(
    Test / test := (Test / test).andFinally(playSound(wavPath)).value
  )
}

The main point is the method andFinally that

defines a new task that runs the original task and evaluates a side effect regardless of whether the original task succeeded. The result of the task is the result of the original task

The implementation of playSound is derived from this question with the following code

  private def playSound(wav: String): Unit = {
    import java.io.BufferedInputStream
    import java.io.FileInputStream
    import javax.sound.sampled.AudioSystem
    val clip = AudioSystem.getClip
    val inputStream =
      AudioSystem.getAudioInputStream(
        new BufferedInputStream(new FileInputStream(wav))
      )
    clip.open(inputStream)
    clip.start()
    Thread.sleep(clip.getMicrosecondLength / 1000)
  }

Now, you can just run sbt test and it will play a sound regardless of whether test succeeded or not.

Ivan Stanislavciuc
  • 7,140
  • 15
  • 18