зеркало из https://github.com/mozilla/pluotsorbet.git
Merge branch 'master' of https://github.com/andreasgal/j2me.js into get_Duration
Conflicts: midp/media.js tests/automation.js
This commit is contained in:
Коммит
34f5cab845
74
index.js
74
index.js
|
@ -341,3 +341,77 @@ DumbPipe.registerOpener("audiorecorder", function(message, sender) {
|
|||
};
|
||||
});
|
||||
|
||||
DumbPipe.registerOpener("camera", function(message, sender) {
|
||||
var mediaStream = null;
|
||||
|
||||
var video = document.createElement("video");
|
||||
document.body.appendChild(video);
|
||||
video.style.position = "absolute";
|
||||
video.style.visibility = "hidden";
|
||||
|
||||
var curW = 0, curH = 0;
|
||||
|
||||
video.addEventListener('canplay', function(ev) {
|
||||
// We should use videoWidth and videoHeight, but they are unavailable (https://bugzilla.mozilla.org/show_bug.cgi?id=926753)
|
||||
sender({ type: "gotstream", width: 320, height: 320 });
|
||||
}, false);
|
||||
|
||||
navigator.mozGetUserMedia({
|
||||
video: true,
|
||||
audio: false,
|
||||
}, function(localMediaStream) {
|
||||
mediaStream = localMediaStream;
|
||||
|
||||
video.src = URL.createObjectURL(localMediaStream);
|
||||
video.play();
|
||||
}, function(err) {
|
||||
console.log("Error: " + err);
|
||||
});
|
||||
|
||||
return function(message) {
|
||||
switch (message.type) {
|
||||
case "setPosition":
|
||||
video.style.left = message.x + "px";
|
||||
video.style.top = message.y + "px";
|
||||
video.style.width = message.w + "px";
|
||||
video.style.height = message.h + "px";
|
||||
|
||||
curW = message.w;
|
||||
curH = message.h;
|
||||
break;
|
||||
|
||||
case "setVisible":
|
||||
video.style.visibility = message.visible ? "visible" : "hidden";
|
||||
break;
|
||||
|
||||
case "snapshot":
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.width = curW;
|
||||
canvas.height = curH;
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(video, 0, 0, curW, curH);
|
||||
|
||||
canvas.toBlob(function(blob) {
|
||||
var fileReader = new FileReader();
|
||||
|
||||
fileReader.onload = function(data) {
|
||||
sender({ type: "snapshot", data: fileReader.result });
|
||||
}
|
||||
|
||||
fileReader.readAsArrayBuffer(blob);
|
||||
}, message.imageType);
|
||||
break;
|
||||
|
||||
case "close":
|
||||
if (mediaStream) {
|
||||
mediaStream.stop();
|
||||
}
|
||||
|
||||
if (video.parentNode) {
|
||||
document.body.removeChild(video);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
@ -14,13 +14,9 @@ public class DeviceControl {
|
|||
throw new RuntimeException("DeviceControl::flashLights(long) not implemented");
|
||||
}
|
||||
|
||||
public static void startVibra(int freq, long duration) {
|
||||
System.out.println("DeviceControl::startVibra(int,long) not implemented");
|
||||
}
|
||||
public static native void startVibra(int freq, long duration);
|
||||
|
||||
public static void stopVibra() {
|
||||
System.out.println("DeviceControl::stopVibra() not implemented");
|
||||
}
|
||||
public static native void stopVibra();
|
||||
|
||||
public static int getUserInactivityTime() {
|
||||
throw new RuntimeException("DeviceControl::getUserInactivityTime() not implemented");
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
<script type="text/javascript" src="midp/sms.js" defer></script>
|
||||
<script type="text/javascript" src="midp/codec.js" defer></script>
|
||||
<script type="text/javascript" src="midp/pim.js" defer></script>
|
||||
<script type="text/javascript" src="midp/device_control.js" defer></script>
|
||||
<script type="text/javascript" src="game-ui.js" defer></script>
|
||||
<script type="text/javascript" src="desktop-ui.js" defer></script>
|
||||
<script type="text/javascript" src="main.js" defer></script>
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
Native.create("com/nokia/mid/ui/DeviceControl.startVibra.(IJ)V", function(freq, longDuration, _) {
|
||||
// If method is called during a previously called vibration that has been
|
||||
// activated from this method, the previous vibration is stopped and the new
|
||||
// one is activated using the new set of parameters.
|
||||
navigator.vibrate(0);
|
||||
|
||||
// Value 0 can be used for detecting whether or not there is a vibration device.
|
||||
if (freq === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var duration = longDuration.toNumber();
|
||||
|
||||
if (freq < 0 || freq > 100 || duration < 0) {
|
||||
throw new JavaException("java/lang/IllegalArgumentException");
|
||||
}
|
||||
|
||||
navigator.vibrate(duration);
|
||||
});
|
||||
|
||||
Native.create("com/nokia/mid/ui/DeviceControl.stopVibra.()V", function() {
|
||||
navigator.vibrate(0);
|
||||
});
|
149
midp/media.js
149
midp/media.js
|
@ -80,6 +80,8 @@ Media.contentTypeToFormat = new Map([
|
|||
Media.supportedAudioFormats = ["MPEG_layer_3", "wav", "amr", "ogg"];
|
||||
Media.supportedImageFormats = ["JPEG", "PNG"];
|
||||
|
||||
Media.EVENT_MEDIA_SNAPSHOT_FINISHED = 11;
|
||||
|
||||
Native.create("com/sun/mmedia/DefaultConfiguration.nListContentTypesOpen.(Ljava/lang/String;)I", function(jProtocol) {
|
||||
var protocol = util.fromJavaString(jProtocol);
|
||||
var types = [];
|
||||
|
@ -400,6 +402,103 @@ ImagePlayer.prototype.setVisible = function(visible) {
|
|||
this.image.style.visibility = visible ? "visible" : "hidden";
|
||||
}
|
||||
|
||||
function ImageRecorder(playerContainer) {
|
||||
this.playerContainer = playerContainer;
|
||||
|
||||
this.sender = null;
|
||||
|
||||
this.width = -1;
|
||||
this.height = -1;
|
||||
|
||||
this.isVideoControlSupported = true;
|
||||
this.isAudioControlSupported = false;
|
||||
|
||||
this.realizeResolver = null;
|
||||
|
||||
this.snapshotData = null;
|
||||
}
|
||||
|
||||
ImageRecorder.prototype.realize = function() {
|
||||
return new Promise((function(resolve, reject) {
|
||||
this.realizeResolver = resolve;
|
||||
this.sender = DumbPipe.open("camera", {}, this.recipient.bind(this));
|
||||
}).bind(this));
|
||||
}
|
||||
|
||||
ImageRecorder.prototype.recipient = function(message) {
|
||||
switch (message.type) {
|
||||
case "gotstream":
|
||||
this.width = message.width;
|
||||
this.height = message.height;
|
||||
this.realizeResolver(true);
|
||||
this.realizeResolver = null;
|
||||
break;
|
||||
|
||||
case "snapshot":
|
||||
this.snapshotData = new Int8Array(message.data);
|
||||
|
||||
MIDP.sendNativeEvent({
|
||||
type: MIDP.MMAPI_EVENT,
|
||||
intParam1: this.playerContainer.handle,
|
||||
intParam2: 0,
|
||||
intParam3: 0,
|
||||
intParam4: Media.EVENT_MEDIA_SNAPSHOT_FINISHED,
|
||||
}, MIDP.foregroundIsolateId);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ImageRecorder.prototype.start = function() {
|
||||
}
|
||||
|
||||
ImageRecorder.prototype.pause = function() {
|
||||
}
|
||||
|
||||
ImageRecorder.prototype.close = function() {
|
||||
this.sender({ type: "close" });
|
||||
}
|
||||
|
||||
ImageRecorder.prototype.getMediaTime = function() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ImageRecorder.prototype.getWidth = function() {
|
||||
return this.width;
|
||||
}
|
||||
|
||||
ImageRecorder.prototype.getHeight = function() {
|
||||
return this.height;
|
||||
}
|
||||
|
||||
ImageRecorder.prototype.setLocation = function(x, y, w, h) {
|
||||
var displayElem = document.getElementById("display");
|
||||
this.sender({
|
||||
type: "setPosition",
|
||||
x: x + displayElem.offsetLeft,
|
||||
y: y + displayElem.offsetTop,
|
||||
w: w,
|
||||
h: h,
|
||||
});
|
||||
}
|
||||
|
||||
ImageRecorder.prototype.setVisible = function(visible) {
|
||||
this.sender({ type: "setVisible", visible: visible });
|
||||
}
|
||||
|
||||
ImageRecorder.prototype.startSnapshot = function(imageType) {
|
||||
var type = imageType ? this.playerContainer.getEncodingParam(imageType) : "image/jpeg";
|
||||
if (type === "jpeg") {
|
||||
type = "image/jpeg";
|
||||
}
|
||||
|
||||
this.sender({ type: "snapshot", imageType: type });
|
||||
}
|
||||
|
||||
ImageRecorder.prototype.getSnapshotData = function(imageType) {
|
||||
return this.snapshotData;
|
||||
}
|
||||
|
||||
function PlayerContainer(url) {
|
||||
this.url = url;
|
||||
|
||||
|
@ -416,25 +515,39 @@ function PlayerContainer(url) {
|
|||
// default buffer size 1 MB
|
||||
PlayerContainer.DEFAULT_BUFFER_SIZE = 1024 * 1024;
|
||||
|
||||
PlayerContainer.prototype.isImageCapture = function() {
|
||||
return !!(this.url && this.url.startsWith("capture://image"));
|
||||
};
|
||||
|
||||
PlayerContainer.prototype.isAudioCapture = function() {
|
||||
return !!(this.url && this.url.startsWith("capture://audio"));
|
||||
};
|
||||
|
||||
PlayerContainer.prototype.getEncodingParam = function(url) {
|
||||
var encoding = null;
|
||||
|
||||
var idx = url.indexOf("encoding=");
|
||||
if (idx > 0) {
|
||||
var encodingKeyPair = url.substring(idx).split("&")[0].split("=");
|
||||
encoding = encodingKeyPair.length == 2 ? encodingKeyPair[1] : encoding;
|
||||
}
|
||||
|
||||
return encoding;
|
||||
};
|
||||
|
||||
PlayerContainer.prototype.guessFormatFromURL = function() {
|
||||
if (this.isAudioCapture()) {
|
||||
var encoding = "audio/ogg"; // Same as system property |audio.encodings|
|
||||
|
||||
var idx = this.url.indexOf("encoding=");
|
||||
if (idx > 0) {
|
||||
var encodingKeyPair = this.url.substring(idx).split("&")[0].split("=");
|
||||
encoding = encodingKeyPair.length == 2 ? encodingKeyPair[1] : encoding;
|
||||
}
|
||||
var encoding = "audio/ogg" || this.getEncodingParam(this.url); // Same as system property |audio.encodings|
|
||||
|
||||
var format = Media.contentTypeToFormat.get(encoding);
|
||||
|
||||
return format || "UNKNOWN";
|
||||
}
|
||||
|
||||
if (this.isImageCapture()) {
|
||||
return "JPEG";
|
||||
}
|
||||
|
||||
return Media.extToFormat.get(this.url.substr(this.url.lastIndexOf(".") + 1)) || "UNKNOWN";
|
||||
}
|
||||
|
||||
|
@ -457,7 +570,11 @@ PlayerContainer.prototype.realize = function(contentType) {
|
|||
}
|
||||
this.player.realize().then(resolve);
|
||||
} else if (Media.supportedImageFormats.indexOf(this.mediaFormat) !== -1) {
|
||||
this.player = new ImagePlayer(this);
|
||||
if (this.isImageCapture()) {
|
||||
this.player = new ImageRecorder(this);
|
||||
} else {
|
||||
this.player = new ImagePlayer(this);
|
||||
}
|
||||
this.player.realize().then(resolve);
|
||||
} else {
|
||||
console.warn("Unsupported media format (" + this.mediaFormat + ") for " + this.url);
|
||||
|
@ -599,6 +716,14 @@ PlayerContainer.prototype.getRecordedData = function(offset, size, buffer) {
|
|||
this.audioRecorder.data = new Uint8Array(this.audioRecorder.data.buffer.slice(toRead));
|
||||
};
|
||||
|
||||
PlayerContainer.prototype.startSnapshot = function(imageType) {
|
||||
this.player.startSnapshot(imageType);
|
||||
}
|
||||
|
||||
PlayerContainer.prototype.getSnapshotData = function() {
|
||||
return this.player.getSnapshotData();
|
||||
}
|
||||
|
||||
PlayerContainer.prototype.getDuration = function() {
|
||||
return this.player.getDuration();
|
||||
}
|
||||
|
@ -1029,3 +1154,11 @@ Native.create("com/sun/mmedia/NativeTonePlayer.nStopTone.(I)Z", function(appId)
|
|||
console.warn("com/sun/mmedia/NativeTonePlayer.nStopTone.(I)Z not implemented.");
|
||||
return true;
|
||||
});
|
||||
|
||||
Native.create("com/sun/mmedia/DirectPlayer.nStartSnapshot.(ILjava/lang/String;)V", function(handle, imageType) {
|
||||
Media.PlayerCache[handle].startSnapshot(util.fromJavaString(imageType));
|
||||
});
|
||||
|
||||
Native.create("com/sun/mmedia/DirectPlayer.nGetSnapshotData.(I)[B", function(handle) {
|
||||
return Media.PlayerCache[handle].getSnapshotData();
|
||||
});
|
||||
|
|
30
midp/midp.js
30
midp/midp.js
|
@ -622,14 +622,23 @@ MIDP.Context2D = (function() {
|
|||
// both. A distance threshold ensures that touches with an "intent
|
||||
// to tap" will likely result in a tap.
|
||||
|
||||
var LONG_PRESS_TIMEOUT = 1000;
|
||||
var MIN_DRAG_DISTANCE_SQUARED = 5 * 5;
|
||||
var mouseDownInfo = null;
|
||||
var longPressTimeoutID = null;
|
||||
var longPressDetected = false;
|
||||
|
||||
c.addEventListener(supportsTouch ? "touchstart" : "mousedown", function(event) {
|
||||
event.preventDefault(); // Prevent unnecessary fake mouse events.
|
||||
var pt = getEventPoint(event);
|
||||
sendPenEvent(pt, MIDP.PRESSED);
|
||||
mouseDownInfo = pt;
|
||||
|
||||
longPressDetected = false;
|
||||
longPressTimeoutID = setTimeout(function() {
|
||||
longPressDetected = true;
|
||||
sendGestureEvent(pt, null, MIDP.GESTURE_LONG_PRESS);
|
||||
}, LONG_PRESS_TIMEOUT);
|
||||
});
|
||||
|
||||
c.addEventListener(supportsTouch ? "touchmove" : "mousemove", function(event) {
|
||||
|
@ -637,6 +646,12 @@ MIDP.Context2D = (function() {
|
|||
return; // Mousemove on desktop; ignored.
|
||||
}
|
||||
event.preventDefault();
|
||||
|
||||
if (longPressTimeoutID) {
|
||||
clearTimeout(longPressTimeoutID);
|
||||
longPressTimeoutID = null;
|
||||
}
|
||||
|
||||
var pt = getEventPoint(event);
|
||||
sendPenEvent(pt, MIDP.DRAGGED);
|
||||
var distance = {
|
||||
|
@ -651,7 +666,9 @@ MIDP.Context2D = (function() {
|
|||
mouseDownInfo.isDragging = true;
|
||||
mouseDownInfo.x = pt.x;
|
||||
mouseDownInfo.y = pt.y;
|
||||
sendGestureEvent(pt, distance, MIDP.GESTURE_DRAG);
|
||||
if (!longPressDetected) {
|
||||
sendGestureEvent(pt, distance, MIDP.GESTURE_DRAG);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -662,9 +679,17 @@ MIDP.Context2D = (function() {
|
|||
}
|
||||
event.preventDefault();
|
||||
|
||||
if (longPressTimeoutID) {
|
||||
clearTimeout(longPressTimeoutID);
|
||||
longPressTimeoutID = null;
|
||||
}
|
||||
|
||||
var pt = getEventPoint(event);
|
||||
sendPenEvent(pt, MIDP.RELEASED);
|
||||
sendGestureEvent(pt, null, mouseDownInfo.isDragging ? MIDP.GESTURE_DROP : MIDP.GESTURE_TAP);
|
||||
|
||||
if (!longPressDetected) {
|
||||
sendGestureEvent(pt, null, mouseDownInfo.isDragging ? MIDP.GESTURE_DROP : MIDP.GESTURE_TAP);
|
||||
}
|
||||
|
||||
mouseDownInfo = null; // Clear the way for the next gesture.
|
||||
});
|
||||
|
@ -867,6 +892,7 @@ MIDP.RELEASED = 2;
|
|||
MIDP.DRAGGED = 3;
|
||||
MIDP.COMMAND_EVENT = 3;
|
||||
MIDP.EVENT_QUEUE_SHUTDOWN = 31;
|
||||
MIDP.MMAPI_EVENT = 45;
|
||||
MIDP.GESTURE_EVENT = 71;
|
||||
MIDP.GESTURE_TAP = 0x1;
|
||||
MIDP.GESTURE_LONG_PRESS = 0x2;
|
||||
|
|
|
@ -186,6 +186,9 @@ Native.create("java/lang/System.getProperty0.(Ljava/lang/String;)Ljava/lang/Stri
|
|||
case "audio.encodings":
|
||||
value = "audio/ogg";
|
||||
break;
|
||||
case "video.snapshot.encodings":
|
||||
value = "encoding=jpeg";
|
||||
break;
|
||||
default:
|
||||
console.warn("UNKNOWN PROPERTY (java/lang/System): " + util.fromJavaString(key));
|
||||
value = null;
|
||||
|
|
|
@ -41,7 +41,7 @@ var gfxTests = [
|
|||
];
|
||||
|
||||
var expectedUnitTestResults = [
|
||||
{ name: "pass", number: 71128 },
|
||||
{ name: "pass", number: 71132 },
|
||||
{ name: "fail", number: 0 },
|
||||
{ name: "known fail", number: 180 },
|
||||
{ name: "unknown pass", number: 0 }
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package com.nokia.mid.ui;
|
||||
|
||||
import gnu.testlet.TestHarness;
|
||||
import gnu.testlet.Testlet;
|
||||
|
||||
public class TestDeviceControl implements Testlet {
|
||||
public void test(TestHarness th) {
|
||||
try {
|
||||
DeviceControl.stopVibra();
|
||||
|
||||
DeviceControl.startVibra(0, 0);
|
||||
DeviceControl.stopVibra();
|
||||
|
||||
try {
|
||||
DeviceControl.startVibra(-1, 100);
|
||||
th.fail("IllegalArgumentException expected");
|
||||
} catch (IllegalArgumentException e) {
|
||||
th.check(true);
|
||||
}
|
||||
|
||||
try {
|
||||
DeviceControl.startVibra(200, 100);
|
||||
th.fail("IllegalArgumentException expected");
|
||||
} catch (IllegalArgumentException e) {
|
||||
th.check(true);
|
||||
}
|
||||
|
||||
try {
|
||||
DeviceControl.startVibra(50, -1);
|
||||
th.fail("IllegalArgumentException expected");
|
||||
} catch (IllegalArgumentException e) {
|
||||
th.check(true);
|
||||
}
|
||||
|
||||
DeviceControl.startVibra(100, 100);
|
||||
Thread.sleep(50);
|
||||
DeviceControl.stopVibra();
|
||||
|
||||
// All done.
|
||||
th.check(true);
|
||||
} catch (Exception e) {
|
||||
th.fail("Unexpected exception: " + e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче