Random posts about coding

Mostly blogging about dart.

How to Communicate With Chrome.* API in Dart

| Comments

I had the privilege to attend Chrome Apps Accelerated MTV hackathon. The goal set out for my self was to create a bluetooth scanner via chrome.bluetooth api.

First I started off by reviewing the Chrome app developer guide. From a previous post, a patch for 7228 was needed at the time.

Second was too communicate with the js defined context which Chrome Apps execute in. Some setup ceremony is needed such as a manifest file and background window. Creating the manifest file was easy, mostly choosing permissions and adding the entry Javascript background entry.

{
"manifest_version": 2,
"name": "Bluetooth sample",
"version": "1",
"minimum_chrome_version": "23",
"icons": {"128": "dart_icon.png"},
"permissions": [
"unlimitedStorage",
"storage",
"notifications",
"bluetooth"
],
"app": {
"background": {
"scripts": ["main.js"]
}
}
}
view raw manifest.json hosted with ❤ by GitHub

For dart we will need to create the background javascript that loads our dart application.

/**
* Listens for the app launching then creates the window
*
* @see http://developer.chrome.com/trunk/apps/app.runtime.html
* @see http://developer.chrome.com/trunk/apps/app.window.html
*/
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('bluetooth_example.html',
{id: 'bluetooth_example', width: 800, height: 800});
});
view raw main.js hosted with ❤ by GitHub

I stumbled with the communications between dart generated javascript and js-interop for some time. The first part of the stumbling blocks was CSP (Content Security Policy) and how dart2js apps are loaded. Thanks to Vijay Menon and Renato Mangini, I was able to create successful call and callback from dart to javascript. This was non trivial since it required knowledge of dart.js and loading of dart_interop.js/js.dart.

The diff file below removes the reference to localStorage and replaces it with a map.

diff --git a/web/dart.js b/web/dart.js
index 1c8b333..d69e50e 100644
--- a/web/dart.js
+++ b/web/dart.js
@@ -157,13 +157,20 @@ function ReceivePortSync() {
return result;
}
+window._localStorage = {};
+
window.registerPort = function(name, port) {
var stringified = JSON.stringify(serialize(port));
var attrName = 'dart-port:' + name;
document.documentElement.setAttribute(attrName, stringified);
- // TODO(vsm): Phase out usage of localStorage. We're leaving it in
- // temporarily for backwards compatibility.
- window.localStorage[attrName] = stringified;
+ // TODO(vsm): Phase out usage of localStorage and delete the
+ // below. We're leaving it in temporarily for backwards
+ // compatibility.
+ try {
+ window._localStorage[attrName] = stringified;
+ } catch (e) {
+ // Swallow errors (e.g., Chrome apps disallow this access).
+ }
};
window.lookupPort = function(name) {
@@ -172,7 +179,7 @@ function ReceivePortSync() {
// TODO(vsm): Phase out usage of localStorage. We're leaving it in
// temporarily for backwards compatibility.
if (!stringified) {
- stringified = window.localStorage[attrName];
+ stringified = window._localStorage[attrName];
}
return deserialize(JSON.parse(stringified));
};
view raw dart.js.diff hosted with ❤ by GitHub

dart_interop.js and js.dart needed to be copied into the root folder of the project. Not sure exactly why this is, very possible that only dart_interop.js is needed since were compiling to js.

04:47:27-adam@Adams-MacBook-Air:~/dart/bluetooth_example/web
$ ls -l
total 1304
-rw-r--r-- 1 adam staff 376 Dec 10 10:29 bluetooth_example.css
-rw-r--r-- 1 adam staff 1253 Dec 10 14:18 bluetooth_example.dart
-rw-r--r-- 1 adam staff 437928 Dec 10 14:19 bluetooth_example.dart.js
-rw-r--r-- 1 adam staff 6825 Dec 10 14:19 bluetooth_example.dart.js.deps
-rw-r--r-- 1 adam staff 102617 Dec 10 14:19 bluetooth_example.dart.js.map
-rw-r--r-- 1 adam staff 410 Dec 10 13:18 bluetooth_example.html
-rwxr-xr-x 1 adam staff 139 Dec 10 10:30 compile.sh
-rw-r--r-- 1 adam staff 8815 Dec 10 13:43 dart.js
-rw-r--r-- 1 adam staff 7294 Dec 10 10:31 dart_icon.png
-rw-r--r-- 1 adam staff 17105 Dec 10 11:29 dart_interop.js
-rw-r--r-- 1 adam staff 42233 Dec 10 11:29 js.dart
-rw-r--r-- 1 adam staff 364 Dec 10 10:32 main.js
-rw-r--r-- 1 adam staff 320 Dec 10 10:36 manifest.json
lrwxr-xr-x 1 adam staff 43 Dec 10 11:28 packages -> /Users/adam/dart/bluetooth_example/packages
view raw files.txt hosted with ❤ by GitHub

The first sanity check of being able to communicate with dart in a Chrome App was printing out the permissions from chrome.permissions.getAll

import 'dart:html';
import 'package:js/js.dart' as js;
void main() {
js.scoped(() {
void permissionsCallback(var result) {
print("permissions = $result");
for (int i = 0; i < result.permissions.length; i++) {
print(result.permissions[i]);
}
};
var chrome = js.context.chrome;
print("chrome = ${chrome.runtime.id}");
var permissionsCallbackHandler = new js.Callback.many(permissionsCallback);
js.context.permissionsCallbackHandler = permissionsCallbackHandler;
chrome.permissions.getAll(js.context.permissionsCallbackHandler);
});
print("finished main");
}

Google searches lead me to the wrong api docs for accessing the bluetooth device. Managed to land on chrome.experimental.bluetooth from extensions api, which is different from the Chrome Apps chrome.* api. Bug was filed about how easy it was to land on the wrong api pages.

Now that I’ve got the right context too loaded, calling the chrome.bluetooth api produced errors with bluetooth support on MacOSX. doh! Bluetooth is currently only supported on ChromeOS and Windows. This was not mentioned in any of the docs and bug was filed on that.

1
2
Error during bluetooth.isAvailable: This operation is not supported on your platform 
chromeHidden.handleResponse

At this point I was glad to be able to make calls on chrome.* api, in a following post I will go over a more complete sample from start to finish. Feel free to browse code and project structure bluetooth_example_chrome_app. Please note this is not a fully working sample and has bugs!

By the end of the hackathon I decided my best bet was to package something that did not rely on the chrome.* api so heavily. An ASCII camera capture app was created and demoed. The application accesses the client’s video input device and converts images capture to ascii images based on a ascii art formula. “videoCapture” permissions are required for accessing video input, this was set in the manifest file. The ASCII camera capture app code is available on the following branch chrome_app_example.

Turning Solar3d Into a Chrome App

| Comments

Ventured tonight with creating an installable Chrome App in #dartlang.

I was compiling to javascript and ran into problems with dart2js using unsafe evals, there not allowed in Chrome Apps.

unsafeevals

dart2js provides the ability to disallow them using dart2js --disallow-unsafe-eval.

After another try loading up the app some funky business was going on, filed a bug at dartbug and within minutes someone had looked at the issue and pointed me to a patch.

Luckily the way dart2js is laid out in the dart-sdk a patch could be applied without side effects. Great design by the dart2js team, reducing the ability of needing to build from bleeding_edge.

22:37:10-adam@Adams-MacBook-Air:/Applications/dart/dart-sdk
$ curl https://codereview.chromium.org/download/issue11491005_1.diff | patch -p2
patching file lib/_internal/compiler/implementation/js_backend/emitter.dart
patching file lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart

Note you must remove the snapshot build of dart2js. The snapshot build of dart2js providers faster load times by the VM.

23:14:57-adam@Adams-MacBook-Air:~/dart/solar3d/web
$ rm -rf /Applications/dart/dart-sdk/lib/_internal/compiler/implementation/dart2js.dart.snapshot

Rebuilt and reloaded the application and solar3d worked as a Chrome App!

00:47:16-adam@Adams-MacBook-Air:~/dart/solar3d/web
$ dart2js --disallow-unsafe-eval -osolar.dart.js solar.dart

unsafeevals

Your welcome to checkout the minior modifications of solar3d on github. Follow the instructions Getting Started with Chrome Apps on loading unpacked extentions.

Using Canvas 2d to Create Pattern in Dart

| Comments

This simple example displays how to use a CanvasPattern in Dart.

Canvas Pattern Example

view raw README.md hosted with ❤ by GitHub
body {
margin: 0px;
padding: 0px;
}
canvas {
border: 2px solid black;
}
import 'dart:html';
void main() {
var canvas = new CanvasElement(width: 600, height: 600);
var ctx = canvas.context2d;
var img = new ImageElement();
img.on.load.add((event) {
// When the image is loaded create a pattern
// from the ImageElement
CanvasPattern pattern = ctx.createPattern(img, 'repeat');
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = pattern;
ctx.fill();
});
img.src = "http://www.dartlang.org/hackathons/2012/happy-hour/img/dart-logo.png";
document.body.elements.add(canvas);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Canvas pattern example in dart</title>
<link rel="stylesheet" href="canvas_pattern_example.css">
</head>
<body>
<script type="application/dart" src="web/canvas_pattern_example.dart"></script>
<script src="https://dart.googlecode.com/svn/branches/bleeding_edge/dart/client/dart.js"></script>
</body>
</html>
name: canvas_pattern_example
description: A Canvas Pattern Example
view raw pubspec.yaml hosted with ❤ by GitHub

Using Canvas 2d to Create Gradient in Dart

| Comments

This simple example displays how to use a CanvasGradient in Dart.

Canvas Gradient Example

view raw README.md hosted with ❤ by GitHub
import 'dart:html';
void main() {
var canvas = new CanvasElement(width: 600, height: 600);
var ctx = canvas.context2d;
ctx.clearRect(0, 0, 600, 600);
ctx.save();
// Create radial gradient
CanvasGradient gradient = ctx.createRadialGradient(0, 0, 0, 0, 0, 600);
gradient.addColorStop(0, '#000');
gradient.addColorStop(1, 'rgb(255, 255, 255)');
// assign gradients to fill
ctx.fillStyle = gradient;
// draw 600x600 fill
ctx.fillRect(0,0,600,600);
ctx.save();
document.body.elements.add(canvas);
}
<!DOCTYPE html>
<html>
<head>
<title>Canvas gradient example</title>
</head>
<body>
<script type="application/dart" src="web/canvas_gradient_example.dart"></script>
<script src="https://dart.googlecode.com/svn/branches/bleeding_edge/dart/client/dart.js"></script>
</body>
</html>
name: canvas_gradient_example
description: A simple example of creating a canvas gradient in dart
view raw pubspec.yaml hosted with ❤ by GitHub

How to Use CanvasElement.toDataURL in Dart

| Comments

When looking to create an ImageElement from a CanvasElement’s context, toDataURL is your friend. An example use case of this would be creating screen shots of a canvas after some routine has ended. Another could be taking a screen shot when a playing a game that was developed with context 2d or webgl. toDataURL returns a data: URL containing a representation of the image in the format specified by type (defaults to PNG).

The following example shows the use of canvas 2d for creating a jpeg image and inserting it into the body of a document. If you run this example you might notice the loss of the alpha channel, that would be a good reason to switch to png format when calling toDataURL.

Example

How to use CanvasElement.toDataURL(String type, [num quality]) in Dart

view raw README.md hosted with ❤ by GitHub
import 'dart:html';
/**
* Example of how to use CanvasElement.toDataURL for exporting URL containing
* a representation of an image in jpeg format with quality 95%.
*/
void main() {
CanvasElement canvas = new CanvasElement();
var ctx = canvas.context2d;
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect (10, 10, 55, 50);
ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
ctx.fillRect (30, 30, 55, 50);
var dataUrl = canvas.toDataURL("image/jpeg", 0.95);
var img = new ImageElement();
img.src = dataUrl;
document.body.elements.add(img);
}
view raw example.dart hosted with ❤ by GitHub
<!DOCTYPE html>
<html>
<head>
<title>Example CanvasElement.toDataURL</title>
</head>
<body>
<script type="application/dart" src="web/example.dart"></script>
<script src="https://dart.googlecode.com/svn/branches/bleeding_edge/dart/client/dart.js"></script>
</body>
</html>
view raw example.html hosted with ❤ by GitHub
name: example
description: Example of CanvasElement.toDataURL
view raw pubspec.yaml hosted with ❤ by GitHub

Ways to Solve the N Doors N Passes Question

| Comments

Question

1000 doors in a row that are initially closed. 1000 passes on the doors. Each time you visit a door you toggle it. If open->close, if close->open. First time you visit every door, second time you visit every other door, third time you visit every 3rd door, etc.. until visiting all 1000 doors. How many doors are left open at the end? Which are open, which are closed? What is unique about the sequence left open?

Solutions

The O(n2) solution to the problem which presents interesting results in its output.

/*
1000 doors in a row that are initially closed. 1000 passes on the doors. Each time you visit a door you toggle it. If open->close, if close->open. First time you visit every door, second time you visit every other door, third time you visit every 3rd door, etc.. until visiting all 1000 doors.
How many doors are left open at the end? Which are open, which are closed? What is unique about the sequence left open?
Doors that are open [1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961].
Count 31.
All numbers are perfect squares.
*/
import 'dart:math';
void main() {
List<bool> doors = new List<bool>(1001);
for(int i=0; i<doors.length; i++) doors[i] = false;
for (int pass = 1; pass <= 1000; pass++) {
for (int current = pass; current <= 1000; current += pass) {
doors[current] = !doors[current];
}
}
List<int> doorsOpen = new List<int>();
for (int i = 0; i <= 1000; i++) {
if (doors[i]) {
doorsOpen.add(i);
}
print("Door ${(doors[i] ? 'Open' : 'Closed')} ${i}");
}
print("Doors that are open ${doorsOpen}");
print("count ${doorsOpen.length}");
}

The O(n) solution that takes advantage of a known identity of perfect squares found in the problem.

/*
* 1000 doors in a row that are initially closed.
* 1000 passes on the doors. Each time you visit
* a door you toggle it. If open->close, if close->open.
* First time you visit every door, second time
* you visit every other door, third time you visit
* every 3rd door, etc.. until visiting all 1000 doors.
* How many doors are left open at the end? Which are open,
* which are closed? What is unique about the sequence left open?
*
* Doors that are open [1, 4, 9, 16, 25, 36, 49, 64, 81,
* 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400,
* 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961].
*
* Count 31.
*
* All the number of times a door will be toggled is based
* on the number of divisors the number has. Example, door
* #6 will be toggled on pass 1, 2, 3, and 6. Most numbers
* have an even number of divisors. Since each divisor must
* have a matching one to make a pair to yield the product.
* Example, 1*6=6, 2*3=6. The only numbers that do not
* have an even number of divisors are th square numbers,
* since one of their divisors is paired with itself.
* Example, door #9 is toggled an odd number of times on passes
* 1, 3, and 9 since 1*9=9 and 3*3=9. All non-square numbered
* doors will end up closed and all square numbered doors
* will end up open. All numbers are perfect squares.
*/
main() {
int o = 0;
for (int i=1; i*i<=1000; i++) {
print("Door ${i*i} is open!");
o++;
}
print("Number of open doors $o");
}

Joining Solvr.io

Pleased to announce that I’m joining #solvr.io full time to work with Lars Tackmann in #dart. Solvr is dedicated for creating modern math tools on the web. We find dart as the perfect opportunity to accomplish our goals, please follow and sign up for an alpha release at http://solvr.io. I feel dartlang has the potential to succeed in commercial opportunities. That helped me in the choice of leaving casino industry for math education tools. A second driver for me is the web ecosystem is ever more important these days, it needs to be in every developer’s toolbox. Finally, math is fun!

I would like to thank all the open source #dartlang developers/hackers/friends for creating the rich community around dart. The community effort has been accelerating at a wonderful speed, the new frameworks and libraries keep on evolving with the dart language. That will help us all in the long haul. This is a great time for startups, smaller companies and enterprises to get in now and create what we want to use over the next years.   


One of the first libraries I will be working on is dart-bignum to help with development that depends on fast implementation of BigInteger across dart and dart2js.

adam@solvr.io
http://solvr.io

Joining Solvr.io

| Comments

Pleased to announce that I’m joining #solvr.io full time to work with Lars Tackmann in #dart. Solvr is dedicated for creating modern math tools on the web. We find dart as the perfect opportunity to accomplish our goals, please follow and sign up for an alpha release at http://solvr.io. I feel dartlang has the potential to succeed in commercial opportunities. That helped me in the choice of leaving casino industry for math education tools. A second driver for me is the web ecosystem is ever more important these days, it needs to be in every developer’s toolbox. Finally, math is fun!

I would like to thank all the open source #dartlang developers/hackers/friends for creating the rich community around dart. The community effort has been accelerating at a wonderful speed, the new frameworks and libraries keep on evolving with the dart language. That will help us all in the long haul. This is a great time for startups, smaller companies and enterprises to get in now and create what we want to use over the next years.   

One of the first libraries I will be working on is dart-bignum to help with development that depends on fast implementation of BigInteger across dart and dart2js.

adam@solvr.io http://solvr.io