Use the HTML5 web MIDI API - javascript

I'm trying to make a simple synth web-app using the web audio API and I want to use it with my MIDI keyboard through the web MIDI API, so I tried these instructions both on Chrome and Chrome Canary but always I get the "navigator.getMIDIAccess is not a function" error, the version is 40 for Chrome and 42 for Chrome Canary, both on Mac OS X (10.10.2) and the experimental flag has been enabled.
The code for now is very simple (this is a test):
<script type="text/javascript">
try{
//navigator.getMIDIAccess = ( navigator.getMIDIAccess || navigator.webkitGetMIDIAccess || navigator.mozGetMIDIAccess || navigator.msGetMIDIAccess);
navigator.getMIDIAccess(_event_success, function(){
alert("ERROR");
});
}catch(ex){
console.log(ex);
alert("NOT SUPPORTED");
}
function _event_success(){
console.log("OK");
}
</script>
Where is the error?
If may be helpful I'm using a M-AUDIO Keystation88 keyboard on USB.
Is Chrome the only one that suport this feature?

The api call is "requestMIDIAccess". (It is not prefixed.)

Related

How do you obtain permissions from web-nfc API?

I'm trying to get Web NFC to work through the Web NFC API, but I can't get it past an error message of NotAllowedError: NFC permission request denied.
I'm using this on Chrome 89 Dev on a Windows 10 computer, and the source code is being run locally.
I have tried the examples posted on the Internet also, including the Google sample but it returns the same error. I'm not concerned with it being experimental at this point as referring to this does show it has successfully passed the necessary tests, including permissions.
The HTML/JS code I'm using is below, and I've read the specification point 9.3, but I can't make sense of it to write it as code, so is there a guideline algorithm that would be helpful here to resolve this?
async function readTag() {
if ("NDEFReader" in window) {
const reader = new NDEFReader();
try {
await reader.scan();
reader.onreading = event => {
const decoder = new TextDecoder();
for (const record of event.message.records) {
consoleLog("Record type: " + record.recordType);
consoleLog("MIME type: " + record.mediaType);
consoleLog("=== data ===\n" + decoder.decode(record.data));
}
}
} catch(error) {
consoleLog(error);
}
} else {
consoleLog("Web NFC is not supported.");
}
}
async function writeTag() {
if ("NDEFWriter" in window) {
const writer = new NDEFWriter();
try {
await writer.write("helloworld");
consoleLog("NDEF message written!");
} catch(error) {
consoleLog(error);
}
} else {
consoleLog("Web NFC is not supported.");
}
}
function consoleLog(data) {
var logElement = document.getElementById('log');
logElement.innerHTML += data + '\n';
};
<!DOCTYPE html>
<html>
<head>
<script src="webnfc.js"></script>
</head>
<body>
<p>
<button onclick="readTag()">Test NFC Read</button>
<button onclick="writeTag()">Test NFC Write</button>
</p>
<pre id="log"></pre>
</body>
</html>
From https://web.dev/nfc/#security-and-permissions
Web NFC is only available to top-level frames and secure browsing contexts (HTTPS only). Origins must first request the "nfc" permission while handling a user gesture (e.g a button click). The NDEFReader scan() and write() methods trigger a user prompt, if access was not previously granted.
I guess you are running from a file:// URL as you said "locally" which is not supported.
You need to host it from a local web server using a https:// URL
Once in the right scope trying to scan or write should trigger a user prompt.
You can also check permissions see https://web.dev/nfc/#check-for-permission
Update:
So I tried the sample page https://googlechrome.github.io/samples/web-nfc/
And this works for me on Android Chrome 87 with "Experimental Web Platform features" enabled
When you hit the scan button A dialog asking for permission pops up.
Comparing the code in this sample to yours I notice that does:-
ndef.addEventListener("reading" , ({ message, serialNumber }) => { ...
Where as yours does:-
ndef.onreading = event => { ...
I don't know if it is the style setting what happens on the Event or something else (Hey this is all experimental)
Update2
To answer the question from the comments of Desktop support.
So you should be some of the desktop/browser combinations at the moment and may be in the future there will be wider support as this is no longer experimental standards. Obviously as your test link suggest Chrome on a Linux Desktop should work as this is really similar to Android Support, with all the NFC device handling done by libnfc and the browser just has to know about this library instead of every type usb or other device than can do NFC.
From what seen of NFC support on Windows, most of this is focussed on direct controlling the NFC reader via USB as just another USB device, while there is a libnfc equivalent in Windows.Networking.Proximity API's I've not come across any NFC reader saying they support this or anybody using it.
For Mac Deskstop, given that Apple are behind the curve with NFC support in iOS, I feel their desktop support will be even further behind even though it could be similar to Linux.
As you can read at https://web.dev/nfc/#browser-support, Web NFC only supports Android for now which is why you get "NotAllowedError: NFC permission request denied." error on Windows.

Twilio video fails in Chrome on Android and Safari on iOS, works on desktop

The support matrix seems to say it should be supported:
https://www.twilio.com/docs/video/javascript#supported-browsers
I can't find that it is NOT supported, but what works on my desktop is not working on any of 3 mobile devices.
I'm using the JS quickstart for video that has the code located here https://github.com/twilio/video-quickstart-js . The rest of the app works, but trying to preview the video gives a failure on all the mobile platforms.
The example at https://mdn-samples.mozilla.org/s/webrtc-capturestill/ works as expected in Chrome on Android and Safari on iOS, so this looks like it has to be a Twilio bug.
The error is "Unable to access Camera and Microphone"
which is coming from here:
// Preview LocalParticipant's Tracks.
document.getElementById('button-preview').onclick = function() {
var localTracksPromise = previewTracks
? Promise.resolve(previewTracks)
: Video.createLocalTracks();
localTracksPromise.then(function(tracks) {
window.previewTracks = previewTracks = tracks;
var previewContainer = document.getElementById('local-media');
if (!previewContainer.querySelector('video')) {
attachTracks(tracks, previewContainer);
}
}, function(error) {
console.error('Unable to access local media', error);
log('Unable to access Camera and Microphone');
});
};
To use video on a phone or tablet (either iOS or Android) you have to serve the page via https. If you don't do that, you get these results. Sooooo, put in a reverse proxy and a cert from certbot...

Accessing microphone with the help of getUsermedia on iOS Safari

I'm attempting to access the microphone on iOS Safari with the help of the getUserMedia. Below you can find a snippet of my code.
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
if (navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = function(constraints) {
// First get ahold of the legacy getUserMedia, if present
let getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
// Some browsers just don't implement it - return a rejected promise with an error
// to keep a consistent interface
if (!getUserMedia) {
return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
}
// Otherwise, wrap the call to the old navigator.getUserMedia with a Promise
return new Promise(function(resolve, reject) {
getUserMedia.call(navigator, constraints, resolve, reject);
});
}
}
navigator.mediaDevices.getUserMedia({
audio: true
}).then(function(stream) {
successCallBack(.......);
}).catch(function(error) {
debug.log(error);
..........
});
Yet the promise always catches an error, to be more specific an OverConstraintError.
{message: "Invalid constraint", constraint: ""}
This behaviour is unique for iOS Safari, on all other browsers (Chrome, Firefox, Safari osX) it works without any problem. Actually my issue ressembles a lot like this one => How to resolve iOS 11 Safari getUserMedia "Invalid constraint" issue, yet I'm not trying to use the camera. The only thing that interests me is the microphone.
I'm testing with a real iPhone (a 5 and X, both updated to the latest version), so it is not linked to the iPhone Simulator.
The access to the microphone is granted and the popup requesting permissions is also showing, so it is not an permissions issue.
This issue may be related to this bug report titled getUserMedia fails with an OverConstrainedError when no devices are found:
https://bugs.webkit.org/show_bug.cgi?id=177126
Here is your code running in Codepen. As you stated, audio is enabled and works. Note the enumerateDevices() call returns an empty array. As the bug states, this causes the error in your question:
.catch(function(error) {
navigator.mediaDevices.enumerateDevices().then(devices=>{console.log(devices)});
console.log('error: ',error);
});
https://codepen.io/anon/pen/rQWRyZ?editors=0011
web rtc or getusermedia has some issues and it is not working on all platforms as u expect - have same problems with camera detection like in samsung s5 same code is working fine but under newer device it was failing.
My advice is to use webrtc adapter js.
Try simply include this script:
<script src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/6.4.0/adapter.js" type="text/javascript"></script>
before u use getusermedia api. I think that 99% of issues just disappear.

HTML5 Notification not working in Mobile Chrome

I'm using the HTML5 notification API to notify the user in Chrome or Firefox. On desktop browsers, it works. However in Chrome 42 for Android, the permission is requested but the notification itself is not displayed.
The request code, works on all devices:
if ('Notification' in window) {
Notification.requestPermission();
}
The sending code, works on desktop browser but not on mobile:
if ('Notification' in window) {
new Notification('Notify you');
}
Try the following:
navigator.serviceWorker.register('sw.js');
Notification.requestPermission(function(result) {
if (result === 'granted') {
navigator.serviceWorker.ready.then(function(registration) {
registration.showNotification('Notification with ServiceWorker');
});
}
});
That is, use ServiceWorkerRegistration»showNotification() not new Notification().
That should work on Android both in Chrome and in Firefox — and on iOS in Safari, too.
(The sw.js file can just be a zero-byte file.)
One caveat is that you must run it from a secure origin (an https URL, not an http URL).
See https://developer.mozilla.org/docs/Web/API/ServiceWorkerRegistration/showNotification.
If you already have a service worker registered, use this:
navigator.serviceWorker.getRegistrations().then(function(registrations) {
registrations[0].showNotification(title, options);
});
Running this code:
if ('Notification' in window) {
Notification.requestPermission();
}
Console in Chrome DevTools shows this error:
Uncaught TypeError: Failed to construct ‘Notification’: Illegal
constructor. Use ServiceWorkerRegistration.showNotification() instead
A better approach might be:
function isNewNotificationSupported() {
if (!window.Notification || !Notification.requestPermission)
return false;
if (Notification.permission == 'granted')
throw new Error('You must only call this \*before\* calling
Notification.requestPermission(), otherwise this feature detect would bug the
user with an actual notification!');
try {
new Notification('');
} catch (e) {
if (e.name == 'TypeError')
return false;
}
return true;
}
Function Source: HTML5Rocks
I had no trouble with the Notification API on Windows Desktop. It even worked without issues on Mobile FF. I found documentation that seemed to indicate Chrome for Android was supported too, but it didn't work for me. I really wanted to prove the API could work for me on my current (2019) version of Chrome (70) for Android. After much investigation, I can easily see why many people have had mixed results. The answer above simply didn't work for me when I pasted it into a barebones page, but I discovered why. According to the Chrome debugger, the Notification API is only allowed in response to a user gesture. That means that you can't simply invoke the notification when the document loads. Rather, you have to invoke the code in response to user interactivity like a click.
So, here is a barebones and complete solution proving that you can get notifications to work on current (2019) Chrome for Android (Note: I used jQuery simply for brevity):
<html>
<head>
<script type="text/javascript" src="libs/jquery/jquery-1.12.4.min.js"></script>
<script>
$( function()
{
navigator.serviceWorker.register('sw.js');
$( "#mynotify" ).click( function()
{
Notification.requestPermission().then( function( permission )
{
if ( permission != "granted" )
{
alert( "Notification failed!" );
return;
}
navigator.serviceWorker.ready.then( function( registration )
{
registration.showNotification( "Hello world", { body:"Here is the body!" } );
} );
} );
} );
} );
</script>
</head>
<body>
<input id="mynotify" type="button" value="Trigger Notification" />
</body>
</html>
In summary, the important things to know about notifications on current (2019) Chrome for Android:
Must be using HTTPS
Must use Notification API in response to user interactivity
Must use Notification API to request permission for notifications
Must use ServiceWorker API to trigger the actual notification
new Notification('your arguments'); This way of creating notification is only supported on desktop browsers, not on mobile browsers. According to the link below. (scroll down to the compatibility part)
https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API
For mobile browsers below is the way you create a notification (this also works on desktop browsers)
navigator.serviceWorker.ready.then( reg => { reg.showNotification("your arguments goes here")});
Tested on browsers using webkit engine.
For more information please visit below links:
https://developers.google.com/web/updates/2015/05/notifying-you-of-changes-to-notifications
https://developers.google.com/web/fundamentals/push-notifications/display-a-notification

Can't access the camera from the app on Lumia 520 (running Windows Phone 8.1 Preview)

I am a WP dev beginner and learning how to write a simple video recorder app. I am using javascript and HTML on VS Pro 2013 and debugging on my actual device Lumia 520 (running Windows Phone 8.1 Preview). I read through a body of documentations and found that the MediaCapture class was the core class for this purpose. So I started following some tutorials and wrote up some functions to access the camera and display a preview in a HTML5 video tag. However, I wasn't successful in getting the MediaCapture object initialized, not even displaying the preview. Below are the major functions of which the first one was problematic:
function initCapture() {
findRearFacingCamera().then(function (cameraId) {
try {
if (cameraId != null && cameraId != "") {
// Initialize the settings
captureInitSettings = null;
captureInitSettings = new Windows.Media.Capture.MediaCaptureInitializationSettings();
captureInitSettings.videoDeviceId = cameraId;
captureInitSettings.streamingCaptureMode = Windows.Media.Capture.StreamingCaptureMode.video;
captureInitSettings.photoCaptureSource = Windows.Media.Capture.PhotoCaptureSource.videoPreview;
captureInitSettings.realTimeModeEnabled = true;
// Initialize the capture
oMediaCapture = null;
oMediaCapture = new Windows.Media.Capture.MediaCapture();
oMediaCapture.initializeAsync(captureInitSettings).then(preview, errorHandler);
}
} catch (e) { }
});
}
function preview() {
var preview = document.getElementById("PreviewScreen");
preview.msZoom = true;
if (preview != null) {
preview.src = URL.createObjectURL(oMediaCapture);
preview.play();
}
}
function errorHandler(e) {
var information = document.getElementById("message");
information.innerHTML = e.message;
}
During debugging, I paused at the statement oMediaCapture = new Windows.Media.Capture.MediaCapture(); in the initCapture() function. At this point, captureInitSettings.videoDeviceId has the value: "\\?\DISPLAY#QCOM_AVStream#3&25691128&0&UID32768#{e5323777-f976-4f5b-9b55-b94699c46e44}\Back Sensor", which I believed was a correct identification of the rear camera that I intended to use. Then, when I continued with a break point set at var preview = document.getElementById("PreviewScreen"); in function preview(), which was supposed to be called upon successful initialization of the MediaCapture object, the program was trapped into the errorHandler() function instead, with the error message being "Access is denied" with error number "-2147024891". So I guess the problem rose from the .initializeAsync() function, which was unsuccessful. Deeper causes might also be related to the permission to access the camera. BTW, I have enabled the webcam and microphone capabilities for this app, which was not the issue.
I believe I was missing something either in the code or in the big picture of the development settings. Please help me identify the issue and let me know if any additional information is needed. Much appreciated!
Did you make sure you added the Rear Camera requirement in your Package Manifest?
Turned out the problem was really with my device. Recall that I was testing on a Lumia 520 with Windows Phone 8.1 preview, the firmware stayed at Lumia Black. After upgrading the firmware to Lumia Cyan (parallel to Windows Phone 8.1) using the Nokia Recovery Software Tool, the problem disappeared.

Categories

Resources