0

I want a small short beep noise to get the user's attention occasionally in my Vaadin Framework 8 app.

Example usage: Beep when password entered into a user-authentication page fails to authenticate successfully. User clicks "Sign-in" button, beep happens immediately after the password check flunks.

Another example: When an automatically updated chart trends upward significantly, play 3 beeps in ascending frequency (notes). If chart trends downward, play descending frequency (notes).

I would like to avoid downloading a sound file to the web client, unless that has clear advantages. Seems simpler, lightweight, and hopefully higher performance to use JavaScript or HTML5 to generate a beep on the client itself locally.

I found what looks like a modern JavaScript solution in this Answer by Houshalter. And this sibling Answer by CaptainWiz contains a live demo that seems to work well.

  • Is there a way to trigger the client-side execution of this JavaScript code from my server-side Vaadin app’s Java code?
  • Will it be performant? I mean the beep needs to happen very quickly in the context of the user's current action, without an annoying/confusing time delay.

Alternatively, this Answer talks about HTML5 having a new Audio objects feature for playing a sound file. Might that have advantages over invoking a chunk of JavaScript code for sound synthesis?

And another alternative: WebAudio API by W3C as shown in this Answer.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • What is the (class of) "context of the current action"? Should it beep when the user enters a letter in a number field? or should it beep if some new message arrived? – cfrick Jun 30 '17 at 07:06
  • @cfrick Example usage: Beep when password entered into a user-authentication page fails to authenticate successfully. User clicks "Sign-in" button, beep happens immediately after the password check flunks. – Basil Bourque Jun 30 '17 at 07:13

1 Answers1

4

One way to achieve this via an AbstractJavascriptComponent in Vaadin. This gives a rather direct approach to write Javascript components or make JS libs accessible without spending too much time on getting a grasp on GWT etc.

The callFunction from an AbstractJavascriptComponent calls directly into the JS-code in the browser.

Create a Beeper class:

package app.ui
import com.vaadin.annotations.JavaScript
import com.vaadin.ui.AbstractJavaScriptComponent
@JavaScript("js/beeper_connector.js")
class Beeper extends AbstractJavaScriptComponent {
    void beep(Integer duration, Integer frequency) {
        callFunction('beep', duration, frequency)
    }
}

Note the annotation and also create that file in the same package (app.ui), on that path with that name (js/beeper_connector.js). The file needs at least to contain a "class" with the name app_ui_Beeper (FQN of the Java class with the dots replaced by underscores) Add your beep function with params of types, that can be transported via "JSON":

window.app_ui_Beeper = function() {
    var audioCtx = new (window.AudioContext || window.webkitAudioContext || window.audioContext);
    this.beep = function(duration, frequency) {
        var oscillator = audioCtx.createOscillator();
        var gainNode = audioCtx.createGain();
        oscillator.connect(gainNode);
        gainNode.connect(audioCtx.destination);
        if (frequency){oscillator.frequency.value = frequency;}
        oscillator.start();
        setTimeout(function(){oscillator.stop()}, (duration ? duration : 500));
    };
};

This code is lifted from the answer referenced by OP: How do I make Javascript beep?

Now make sure, that you add a Beeper instance somewhere in your main scene graph in the UI, so it can be accessed from everywhere.

A working example can be found here: https://github.com/christoph-frick/vaadin-webaudio-beep

cfrick
  • 35,203
  • 6
  • 56
  • 68