Conflicts:
	midp/media.js
	tests/automation.js
This commit is contained in:
Marco Castelluccio 2014-11-27 02:41:15 +01:00
Родитель 1c33f91fb8 72751c03d5
Коммит 34f5cab845
9 изменённых файлов: 324 добавлений и 17 удалений

Просмотреть файл

@ -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>

28
midp/device_control.js Normal file
Просмотреть файл

@ -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);
});

Просмотреть файл

@ -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();
});

Просмотреть файл

@ -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();
}
}
}