This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

sound on Win/PC and Android/Tablet
#1
Hi all,

for users' interface, I use some PC and an Android Tablet.

I have to alert users with sound (wav/mp3) or simple beep through Lua (and JS developpements if necessary) : It's works fine on Windows, but my Android 5.1.1 machine refuse to issue any sound (I obtain a simple "crack").

Is there an "universal" method for this ? 

I know it should be very complex...

Have a good end of monday !

Dominique
Reply
#2
Hi,

You could use this custom JS for that: (note that iOS devices needs to be touch once before audio works, Apple crazy policy)

Note that the audio files are uploaded in the Apps FTP user folder, otherwise you have to adjust the path. 
Code:
// Closing current script section to add elements
</script>
<audio id="SE_Audio" style="display: none;"></audio>
<script type="text/javascript"> // Starting new script section after adding elements  

$(function(){

  // Table with parameters
  var AudioTable = [
    { address:"32/2/0", url:"/user/audio1.mp3"},
    { address:"32/2/1", url:"/user/audio2.mp3" },
    { address:"32/2/2", url:"/user/audio3.mp3" },
  ];
        
  var ctx = new(window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.oAudioContext || window.msAudioContext), request = new XMLHttpRequest();
  var snd = document.getElementById("SE_Audio");
 
 function getMobileOperatingSystem() {
   var userAgent = navigator.userAgent || navigator.vendor || window.opera;
   //console.log(userAgent)
   if (userAgent.match(/iPad/i) || userAgent.match(/iPhone/i) || userAgent.match(/iPod/i)) {
     return 'iOS';
   } else if ( userAgent.match(/Android/i)) {
     return 'Android';
   } else if ( userAgent.match(/iKonWebTouch/i)) {
     return 'U.Motion';
   } else {
     return 'PC';
   }
 }

 var OS_Version = getMobileOperatingSystem();
 
 // Fix iOS Audio Context
 (function() {
   var fixAudioContext = function (e) {
     if (ctx) {
       // Create empty buffer
       var buffer = ctx.createBuffer(1, 1, 22050);
       var source = ctx.createBufferSource();
       source.buffer = buffer;
       // Connect to output
       source.connect(ctx.destination);
       // Play sound
       if (source.start) {
         source.start(0);
       } else if (source.play) {
         source.play(0);
       } else if (source.noteOn) {
         source.noteOn(0);
       }
     }
     // Check if document is loaded in iframe
     if (window.frameElement){
       // Remove event listeners from parent
       var thisparent = window.parent;
       thisparent.document.removeEventListener('touchstart', fixAudioContext);
       thisparent.document.removeEventListener('touchend', fixAudioContext);
     }
     // Remove events
     document.removeEventListener('touchstart', fixAudioContext);
     document.removeEventListener('touchend', fixAudioContext);
   };
   // Check if document is loaded in iframe
   if (window.frameElement){
     // Add event listeners to parent
     var thisparent = window.parent;
     // Event listener for iOS 6-8 (was previous touchstart event)
     thisparent.document.addEventListener('touchstart', fixAudioContext);
     // Event listener for iOS 9+ (is now touchend event)
     thisparent.document.addEventListener('touchend', fixAudioContext);
   }
   // Event listener for iOS 6-8 (was previous touchstart event)
   document.addEventListener('touchstart', fixAudioContext);
   // Event listener for iOS 9+ (is now touchend event)
   document.addEventListener('touchend', fixAudioContext);
 })();
 
 // Function to play audio by URL
 function Play_Audio(url){
   //console.log(OS_Version)
   if (OS_Version === 'Android' || OS_Version === 'U.Motion' ){
       //alert(OS_Version);
     snd.src = url;
       snd.pause();
       sndcurrentTime = 0;
     //snd.load();
     snd.play();
   } else {
     request.open("GET", url, true);
     request.responseType = "arraybuffer";
     request.onload = function(){
         ctx.decodeAudioData(request.response, onDecoded);
     }
     function onDecoded(buffer){
         var bufferSource = ctx.createBufferSource();
         bufferSource.buffer = buffer;
         bufferSource.connect(ctx.destination);
         bufferSource.start();
     }
     request.send();
   }
 };
 
 // Function to create event listeners
 function CreateListeners(groupaddr,url){
   // Make event listener to object
   if (typeof grp != 'undefined') {
     grp.listen(groupaddr, function(object, state) {
       var value = object.value;
       if (state == 'value') {
         if (value == 1) {
           Play_Audio(url);
         }
       }
     }, true);
   }
    }
 
 // Start creating listeners
 for (var i in AudioTable) {
   CreateListeners(AudioTable[i].address,AudioTable[i].url);
 }
 
});
BR,

Erwin

PS: Not complex at all (:
Reply
#3
Erwin...

...you are a genius

Many thank's again for all.
Dominique, a fan of LM
Reply
#4
(27.03.2018, 18:01)Erwin van der Zwart Wrote: Hi,

You could use this custom JS for that: (note that iOS devices needs to be touch once before audio works, Apple crazy policy)

Hi,

Same for Android Chrome !!

JMM
Jean-Marc
Reply
#5
Hi,

I was try this script add file in ftp but for me is not working sound. I was try from windows PC on the button need to add function in Additional class?
Reply
#6
Hi,

No there are no additional classes needed, the events are attached to grp addr.

Are you sure the ftp files are correct located? In Apps ‘user’ folder? 

Can you try in your browser http://192.168.0.10/user/audio1.mp3 and see if the file get played?

BR,

Erwin
Reply
#7
Check console.log() in Browser console, maybe there are some errors.
Done is better than perfect
Reply
#8
Is there a decent way to create a "mute" button for this script?
Reply
#9
You can use an additional object to control whether to play the sound or not. In this example the sound will play only when 1/1/1 value is true.
Code:
function CreateListeners(groupaddr,url){
    // Make event listener to object
    if (typeof grp != 'undefined') {
      grp.listen(groupaddr, function(object, state) {
        var value = object.value;
        var enabled = grp.getvalue('1/1/1');
        if (state == 'value' && value == 1 && enabled) {
          Play_Audio(url);
        }
      }, true);
    }
   }
Reply
#10
Hello Erwin,

I am working on an android based system and am having some trouble with where the audio files go.
If I place them in e.g. /user/audio1.mp3 (where /user/ is the absolute path, ie. a subfolder of the filesystem root folder) per your code below, then that is the wrong location.
Therefor it looks like /user/ should be a interpreted as being a relative path, ie. a sub-folder of some other folder.
But which one? What do you mean by the "Apps FTP user folder"? How do I modify the path to point to an absolute path within the filesystem's root folder?

Many thanks!

Quote:Hi,

You could use this custom JS for that: (note that iOS devices needs to be touch once before audio works, Apple crazy policy)

Note that the audio files are uploaded in the Apps FTP user folder, otherwise you have to adjust the path. 

Code:
(....)

$(function(){

  // Table with parameters
  var AudioTable = [
    { address:"32/2/0", url:"/user/audio1.mp3"},
    { address:"32/2/1", url:"/user/audio2.mp3" },
    { address:"32/2/2", url:"/user/audio3.mp3" },
  ];
        
(....)
Reply
#11
Enable FTP and use apps login. There you will see user directory where files that can be accessed from HTTP /user/ path should be placed.
Reply
#12
(07.12.2020, 13:08)admin Wrote: Enable FTP and use apps login. There you will see user directory where files that can be accessed from HTTP /user/ path should be placed.

Thanks, admin! This clarified sufficiently to solve the problem. For the benefit of any future visitors to this post:

The file /user/audio1.mp3 should be under the home ftp folder of user 'apps' (on the visualisation server).  In my case, the first FTP client I used did not show the contents of my home ftp folder. But the second client which I tried (due to a hunch) did.
Reply
#13
(27.03.2018, 18:01)Erwin van der Zwart Wrote: Hi,

You could use this custom JS for that: (note that iOS devices needs to be touch once before audio works, Apple crazy policy)

Note that the audio files are uploaded in the Apps FTP user folder, otherwise you have to adjust the path. 
Code:
// Closing current script section to add elements
</script>
<audio id="SE_Audio" style="display: none;"></audio>
<script type="text/javascript"> // Starting new script section after adding elements  

$(function(){

  // Table with parameters
  var AudioTable = [
    { address:"32/2/0", url:"/user/audio1.mp3"},
    { address:"32/2/1", url:"/user/audio2.mp3" },
    { address:"32/2/2", url:"/user/audio3.mp3" },
  ];
        
  var ctx = new(window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.oAudioContext || window.msAudioContext), request = new XMLHttpRequest();
  var snd = document.getElementById("SE_Audio");
 
 function getMobileOperatingSystem() {
   var userAgent = navigator.userAgent || navigator.vendor || window.opera;
   //console.log(userAgent)
   if (userAgent.match(/iPad/i) || userAgent.match(/iPhone/i) || userAgent.match(/iPod/i)) {
     return 'iOS';
   } else if ( userAgent.match(/Android/i)) {
     return 'Android';
   } else if ( userAgent.match(/iKonWebTouch/i)) {
     return 'U.Motion';
   } else {
     return 'PC';
   }
 }

 var OS_Version = getMobileOperatingSystem();
 
 // Fix iOS Audio Context
 (function() {
   var fixAudioContext = function (e) {
     if (ctx) {
       // Create empty buffer
       var buffer = ctx.createBuffer(1, 1, 22050);
       var source = ctx.createBufferSource();
       source.buffer = buffer;
       // Connect to output
       source.connect(ctx.destination);
       // Play sound
       if (source.start) {
         source.start(0);
       } else if (source.play) {
         source.play(0);
       } else if (source.noteOn) {
         source.noteOn(0);
       }
     }
     // Check if document is loaded in iframe
     if (window.frameElement){
       // Remove event listeners from parent
       var thisparent = window.parent;
       thisparent.document.removeEventListener('touchstart', fixAudioContext);
       thisparent.document.removeEventListener('touchend', fixAudioContext);
     }
     // Remove events
     document.removeEventListener('touchstart', fixAudioContext);
     document.removeEventListener('touchend', fixAudioContext);
   };
   // Check if document is loaded in iframe
   if (window.frameElement){
     // Add event listeners to parent
     var thisparent = window.parent;
     // Event listener for iOS 6-8 (was previous touchstart event)
     thisparent.document.addEventListener('touchstart', fixAudioContext);
     // Event listener for iOS 9+ (is now touchend event)
     thisparent.document.addEventListener('touchend', fixAudioContext);
   }
   // Event listener for iOS 6-8 (was previous touchstart event)
   document.addEventListener('touchstart', fixAudioContext);
   // Event listener for iOS 9+ (is now touchend event)
   document.addEventListener('touchend', fixAudioContext);
 })();
 
 // Function to play audio by URL
 function Play_Audio(url){
   //console.log(OS_Version)
   if (OS_Version === 'Android' || OS_Version === 'U.Motion' ){
       //alert(OS_Version);
     snd.src = url;
       snd.pause();
       sndcurrentTime = 0;
     //snd.load();
     snd.play();
   } else {
     request.open("GET", url, true);
     request.responseType = "arraybuffer";
     request.onload = function(){
         ctx.decodeAudioData(request.response, onDecoded);
     }
     function onDecoded(buffer){
         var bufferSource = ctx.createBufferSource();
         bufferSource.buffer = buffer;
         bufferSource.connect(ctx.destination);
         bufferSource.start();
     }
     request.send();
   }
 };
 
 // Function to create event listeners
 function CreateListeners(groupaddr,url){
   // Make event listener to object
   if (typeof grp != 'undefined') {
     grp.listen(groupaddr, function(object, state) {
       var value = object.value;
       if (state == 'value') {
         if (value == 1) {
           Play_Audio(url);
         }
       }
     }, true);
   }
    }
 
 // Start creating listeners
 for (var i in AudioTable) {
   CreateListeners(AudioTable[i].address,AudioTable[i].url);
 }
 
});
BR,

Erwin

PS: Not complex at all (:


is there a simple way to adapt it to make a sound for every alert,  regardless the object address?
Reply
#14
You can override the built-in alert function:
Code:
// Start creating listeners
  for (var i in AudioTable) {
    CreateListeners(AudioTable[i].address,AudioTable[i].url);
  }
  
  var alertfn = alert;
  alert = function(text) {
    Play_Audio("/user/audio1.mp3");
    alertfn(text);
  };
});
Reply
#15
(17.12.2020, 11:46)admin Wrote: You can override the built-in alert function:
Code:
  // Start creating listeners
  for (var i in AudioTable) {
    CreateListeners(AudioTable[i].address,AudioTable[i].url);
  }
 
  var alertfn = alert;
  alert = function(text) {
    Play_Audio("/user/audio1.mp3");
    alertfn(text);
  };
});

I can get no sound when an alert occours.... Undecided   anyway I think would be more useful  to use with tagged objects... is it possible?
Reply
#16
You can use grp.taglisten(tag_name, callback_function, all_events) instead of grp.listen(group_address, callback_function, all_events) for this
Reply
#17
Code:
// alert sound
 
// Closing current script section to add elements
</script>
<audio id="SE_Audio" style="display: none;"></audio>
<script type="text/javascript"> // Starting new script section after adding elements 

$(function(){

   // Table with parameters
   var AudioTable = [
     { address:"32/2/12", url:"/scada/resources/img/beep.mp3"},
    // { address:"32/2/1", url:"/user/audio2.mp3" },
     //{ address:"32/2/2", url:"/user/audio3.mp3" },
   ];
        
   var ctx = new(window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.oAudioContext || window.msAudioContext), request = new XMLHttpRequest();
   var snd = document.getElementById("SE_Audio");
 
  function getMobileOperatingSystem() {
    var userAgent = navigator.userAgent || navigator.vendor || window.opera;
    //console.log(userAgent)
    if (userAgent.match(/iPad/i) || userAgent.match(/iPhone/i) || userAgent.match(/iPod/i)) {
      return 'iOS';
    } else if ( userAgent.match(/Android/i)) {
      return 'Android';
    } else if ( userAgent.match(/iKonWebTouch/i)) {
      return 'U.Motion';
    } else {
      return 'PC';
    }
  }

  var OS_Version = getMobileOperatingSystem();
 
  // Fix iOS Audio Context
  (function() {
    var fixAudioContext = function (e) {
      if (ctx) {
        // Create empty buffer
        var buffer = ctx.createBuffer(1, 1, 22050);
        var source = ctx.createBufferSource();
        source.buffer = buffer;
        // Connect to output
        source.connect(ctx.destination);
        // Play sound
        if (source.start) {
          source.start(0);
        } else if (source.play) {
          source.play(0);
        } else if (source.noteOn) {
          source.noteOn(0);
        }
      }
      // Check if document is loaded in iframe
      if (window.frameElement){
        // Remove event listeners from parent
        var thisparent = window.parent;
        thisparent.document.removeEventListener('touchstart', fixAudioContext);
        thisparent.document.removeEventListener('touchend', fixAudioContext);
      }
      // Remove events
      document.removeEventListener('touchstart', fixAudioContext);
      document.removeEventListener('touchend', fixAudioContext);
    };
    // Check if document is loaded in iframe
    if (window.frameElement){
      // Add event listeners to parent
      var thisparent = window.parent;
      // Event listener for iOS 6-8 (was previous touchstart event)
      thisparent.document.addEventListener('touchstart', fixAudioContext);
      // Event listener for iOS 9+ (is now touchend event)
      thisparent.document.addEventListener('touchend', fixAudioContext);
    }
    // Event listener for iOS 6-8 (was previous touchstart event)
    document.addEventListener('touchstart', fixAudioContext);
    // Event listener for iOS 9+ (is now touchend event)
    document.addEventListener('touchend', fixAudioContext);
  })();
 
  // Function to play audio by URL
  function Play_Audio(url){
    //console.log(OS_Version)
    if (OS_Version === 'Android' || OS_Version === 'U.Motion' ){
        //alert(OS_Version);
      snd.src = url;
        snd.pause();
        sndcurrentTime = 0;
      //snd.load();
      snd.play();
    } else {
      request.open("GET", url, true);
      request.responseType = "arraybuffer";
      request.onload = function(){
          ctx.decodeAudioData(request.response, onDecoded);
      }
      function onDecoded(buffer){
          var bufferSource = ctx.createBufferSource();
          bufferSource.buffer = buffer;
          bufferSource.connect(ctx.destination);
          bufferSource.start();
      }
      request.send();
    }
  };
 
  // Function to create event listeners
  function CreateListeners(groupaddr,url){
    // Make event listener to object
    if (typeof grp != 'undefined') {
      grp.listen(groupaddr, function(object, state) {
        var value = object.value;
        var enabled = grp.getvalue('32/2/1');
        if (state == 'value' && value == 1 && enabled) {
          Play_Audio(url);
        }
      }, true);
    }
   
  // Start creating listeners
  for (var i in AudioTable) {
    CreateListeners(AudioTable[i].address,AudioTable[i].url);
  }
 

 
  });
That's my Custom JS....  I loaded beep.mp3 file in /scada/resources/img/ (I guess it's ok?) and set '32/2/1' as enable/disable alarm sound. Then I try to put on and off the object '32/2/12' from visualization on my Windows 10 PC, but I can get no sound. 
what's wrong?   Thanks

Peppe
Reply
#18
You are missing a closing } for the CreateListeners function. It should be like this:
Code:
// Function to create event listeners
  function CreateListeners(groupaddr,url){
    // Make event listener to object
    if (typeof grp != 'undefined') {
      grp.listen(groupaddr, function(object, state) {
        var value = object.value;
        var enabled = grp.getvalue('32/2/1');
        if (state == 'value' && value == 1 && enabled) {
          Play_Audio(url);
        }
      }, true);
    }
  } // missing closing "}"
    
  // Start creating listeners
  for (var i in AudioTable) {
    CreateListeners(AudioTable[i].address,AudioTable[i].url);
  }

Next time if Custom JS is not working check browser console (F12) for any error messages.
Reply
#19
(23.12.2020, 06:54)admin Wrote: You are missing a closing } for the CreateListeners function. It should be like this:
Code:
// Function to create event listeners
  function CreateListeners(groupaddr,url){
    // Make event listener to object
    if (typeof grp != 'undefined') {
      grp.listen(groupaddr, function(object, state) {
        var value = object.value;
        var enabled = grp.getvalue('32/2/1');
        if (state == 'value' && value == 1 && enabled) {
          Play_Audio(url);
        }
      }, true);
    }
  } // missing closing "}"
   
  // Start creating listeners
  for (var i in AudioTable) {
    CreateListeners(AudioTable[i].address,AudioTable[i].url);
  }

Next time if Custom JS is not working check browser console (F12) for any error messages.


ok, thank you. Now it's working!

Another request, be patient    Angel : I would repeat the play of the beep until the condition change. I tried with a while - do loop, but it seems I make something wrong....
Reply
#20
This should do what you want. You can change the interval (it is 2000 milliseconds now) if needed.
Code:
var interval;
  
  // Function to play audio by URL
  function Play_Audio(url){
    //console.log(OS_Version)
    if (OS_Version === 'Android' || OS_Version === 'U.Motion' ){
        //alert(OS_Version);
      snd.src = url;
        snd.pause();
        sndcurrentTime = 0;
      //snd.load();
      snd.play();
    } else {
      request.open("GET", url, true);
      request.responseType = "arraybuffer";
      request.onload = function(){
          ctx.decodeAudioData(request.response, onDecoded);
      }
      function onDecoded(buffer){
          var bufferSource = ctx.createBufferSource();
          bufferSource.buffer = buffer;
          bufferSource.connect(ctx.destination);
          bufferSource.start();
      }
      request.send();
    }
  };
  
  // Function to create event listeners
  function CreateListeners(groupaddr,url){
    // Make event listener to object
    if (typeof grp != 'undefined') {
      grp.listen(groupaddr, function(object, state) {
        var value = object.value;
        var enabled = grp.getvalue('32/2/1');
        clearInterval(interval);
        if (state == 'value' && value == 1 && enabled) {
          Play_Audio(url);
          interval = setInterval(function() {
            Play_Audio(url);
          }, 2000);
        }
      }, true);
    }
  }
    
  // Start creating listeners
  for (var i in AudioTable) {
    CreateListeners(AudioTable[i].address,AudioTable[i].url);
  }
});
Reply


Forum Jump: