Canonical Voices

rvr

Visualino: How to measure voltage with Arduino

Inspired by  Crea un voltímetro tan solo con tu placa Arduino y un par de cables (How to create a multimeter with an Arduino board and a couple of wires), I've created the following tutorial to show how easy and fun is to program with Visualino. Here you'll learn how to measure the voltage a battery with Arduino. For that, a multimeter is often used, but multimeters aren't smart. Arduinos are!

Arduino boards have two set of pins. The digital pins are the ones we usually use to blink a LED. Digital means they only have two states: ON and OFF. But we also have the analog pins, which are able to measure current and convert it from a voltage to a number, that can be read. To build the circuit these components are needed:

• Arduino Uno or Nano (or any other one).
• Two resistors 1K Ohms.
• Some wires.
• A battery: in my case 9V.

Next, place the components like this:

Now, we are ready to program the Arduino board using Visualino. You can see how to do that in the following video. First, we use the blocks to create the program. The program do these:

1. It reads a number from the analog pin #0 and stores it in the "read" variable.
2. It re-scales that number from 0-1023 to 0-900 and stores the result in "voltage". My battery is 9V. If your battery has max 3 volts, then use the appropriate max value (e.g. 300).
3. The measured voltage is printed.
4. After half a second, the measure is repeated.

After the program has been created, we build it and transfer it to the Arduino board.

As we can see in the video, Visualino has a Serial monitor. There we can see the voltage readings. That was easy, uh? :) But to make things easier, Visualino is able to convert those numbers in the Serial monitor to neat real-time chart!

And that's it! Stay tuned as other awesome features will be coming soon to Visualino. Enjoy!

rvr

Visualino: Visual programming for Arduino

To celebrate the 10th anniversary of Arduino, and the Arduino Day, today I am proud to present Visualino. What is it? It's a visual programming environment for Arduino, a project that I begun last year and has been actively developing in the last months, with the help of my friends at Arduino Gran Canaria.

Arduino is a microcontroller board that allows to connect to sensors and other electronic components. It has a companion program called the Arduino IDE, which makes really easy to program the microcontroller. The language is based in C/C++ but the functions are quite easy to learn. This easiness is part of the revolution. Making LEDs blink and moving robots with Arduino is easy and fun. But it can be easier! Kids and adults who don't know programming often struggle with C/C++ coding strictness: commas and brackets must be correctly placed, or the program won't run. How to make it even more intuitive? Visual programming to the rescue!

Scratch is a popular visual programming environment for kits, developed at MIT. Instead of keyboards and codes, kids use the mouse and blocks to create games like a puzzle. And there is an extension called Scratch for Arduino that allows to control the board from Scratch. However, the program runs in Scratch, so the Arduino board must be always connected to the PC.

So, what does Visualino do? It's a Scratch-like program: it allows to create programs for Arduino like a puzzle. But it directly programs the Arduino board, and the PC connection is no longer needed for it to run. Also it generates the code in real time, so the user knows what's happening. The environment is very similar to Arduino IDE, with the same main options: Verify, Build, Save, Load and Monitor. Visualino can be seen at work in this screencast:

Visualino is based in Google Blockly and bq's bitbloqs. It is open source, multiplatform and multilanguage. It just requires Arduino 1.6, which is the actual engine used to program Arduino boards. You can download the beta version right now for Ubuntu, Mac and Windows. The code is available at github.com/vrruiz/visualino. Right now it works out of the box. It needs some documentation and translations to Catalan, Italian and Portuguese will be welcomed.

Visualino was presented this week to a group of educators at an Arduino Workshop, and next month, we'll have a three-hour session to teach how to use it. So I hope it will be used soon at schools here at home.

So, go to download and use it. Feedback is welcome. And stay tuned, as there are some niceties coming very soon :)

rvr

WebKit: Extending Javascript - Seed (V)

In the first post we described what WebKit and JavaScriptCore is, how to program a simple WebKitGTK+ application and how to extend the JavaScript functionality with a dumb (empty) class. In the second post, we extended JavaScript to enable desktop notifications. In the third post,  WebKit/JavaScriptCore were extended to access UPower properties using D-Bus. And in the fourth post, WebKit/JavaScriptCore were extended to use JavaScript callbacks for UPower methods.

In this article we are introducing another way to extend JavaScriptCore: Seed.

Seed: A JavaScriptCore engine

In previous articles we've seen the power of JavaScriptCore. However, its features are tied to the WebKit engine. Wouldn't be great if we could run standalone JavaScript programs using JavaScriptCore? That's exactly what Seed does. Seed is a JavaScript interpreter, able to run pure JavaScript programs. It uses WebKitGTK+, not to browse, but to run JavaScript code.

Indeed, Seed comes in two flavors:

• As a command line interpreter (/usr/bin/seed).
• As a C library (libseed).

As a command line, Seed is like a Python or Perl interpreter: a script is loaded and executed. However, outside the web environment, JavaScript is pretty much useless. That's why, as we did in our previous examples, Seed adds support for some native libraries. And specifically, Seed can be used to program GTK+ applications using JavaScript, thanks to its GObject Introspection/JavaScript bridge.

libseed, the C library, allows third-parties to easily build scripting capabilities for their programs. It adds a thin layer to JavaScriptCore API. The functions and methods available in JSC are usually available in libseed. This mean we can define new features and access JavaScript objects from C.

A simple Seed script

To install Seed in Ubuntu, type:

\$ sudo apt-get install seed libseed-gtk3-dev

This is a simple GTK+ program, which just shows a window with a button.

```#!/usr/bin/seed

/* Imports GTK+ libraries */
Gtk = imports.gi.Gtk;

/* Inits GTK+ */
Gtk.init(null, null);

/* Creates window */
var window = new Gtk.Window();

/* Terminates program if window is closed */
window.signal.hide.connect(Gtk.main_quit);

/* Creates button */
var button = new Gtk.Button();
button.set_label('Hello world');

/* Terminates program if button is clicked */
button.signal.clicked.connect(Gtk.main_quit);

/* Add button to window */

/* Shows */
window.set_default_size(100,100);
window.show_all();

/* Main loop */
Gtk.main();
```

To run it:

\$ seed gtk.js

This shows:

WebViews and Seed

In our previous articles, we've extended JavaScript features manually, programming C methods to create JS classes. Those classes were available to our Web Views. But Seed already provides a lot of libraries. In the next example, we'll see how to use libseed to extend WebKit.

Seed is built upon JavaScriptCore, which is a core element of WebKit. In order to expose libseed features in a browser, we need to connect Seed with WebKit. How to do that? When a WebView is created, a JavaScriptCore's Context Object is created. This Context Object stores the status of the JavaScript engine. Generally, Seed creates is own Context Object, but there is function to use an already created context. Using this function, Seed will populate the WebView's context with Seed's libraries.

This the source code of our program which exposes Seed libraries to a WebKitGTK+ web view.

```#include <stdio.h>
#include <gtk/gtk.h>
#include <webkit/webkit.h>
#include <seed.h>
#include <JavaScriptCore/JavaScript.h>

SeedEngine *engine;

static void window_object_cleared_cb(WebKitWebView  *web_view,
WebKitWebFrame *frame,
gpointer        context,
gpointer        arg3,
gpointer        user_data)

{
JSGlobalContextRef jsContext = webkit_web_frame_get_global_context(frame);
engine = seed_init_with_context (NULL, NULL, jsContext);
}

static void destroy_cb(GtkWidget* widget, gpointer data)
{
g_free (engine);
gtk_main_quit ();
}

static GtkWidget* main_window;
static WebKitWebView* web_view;

static GtkWidget* create_browser()
{
GtkWidget* scrolled_window = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

web_view = WEBKIT_WEB_VIEW (webkit_web_view_new ());

g_signal_connect (G_OBJECT (web_view), "window-object-cleared", G_CALLBACK(window_object_cleared_cb), web_view);

return scrolled_window;
}

static GtkWidget* create_window()
{
GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 500, 500);
g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy_cb), NULL);
return window;
}

int main (int argc, char* argv[]) {
gtk_init (&argc, &argv);

GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), create_browser (), TRUE, TRUE, 0);

main_window = create_window();

gchar* uri = (gchar*) "file://webkit-seed.html";

gtk_widget_grab_focus (GTK_WIDGET (web_view));
gtk_widget_show_all (main_window);
gtk_main ();

return 0;
}
```

To compile it, type:

\$ gcc -o webkit-seed webkit-seed.c `pkg-config --cflags --libs webkitgtk-3.0 seed`

And this is the webkit-seed.html file:

```<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<body>

<script type="text/javascript">
var sqlite = imports.sqlite;
sql = new sqlite.Database('/tmp/webkit_seed_test.db')
sql.exec('CREATE TABLE test (id INTEGER PRIMARY KEY, data TEXT)');
sql.close();
</script>

</body>
</html>
```

To run the program:

\$ webkit-seed

This time, the browser will appear, but the fun action will be in the /tmp directory. There we'll found a new SQLite 3 database, with a two-field table.

Of course, Seed gives access to a lot of sensible libraries. Safety would be at risk if we let any JavaScript program to run this way, but it also opens a whole world of possibilities!

P.S.: Of course, I tried to run the GTK+ example inside the WebView. Unfortunately, it didn't work :-(

rvr

WebKit and Python: A Facebook Authentication Browser

In the previous articles dedicated to WebKit, we've used the WebKitGTK+ in plain C. Thanks to GObject and GLib libraries,  doing bindings for others languages is quite easy. And of course, bindings for WebKitGTK+ exists for Python, one of my favorite programming languages. Python is ideal for rapid prototyping and/or fast development.

To use WebKitGTK+ in Python and Ubuntu, python-webkit library must be installed:

\$ sudo apt-get install python-webkit

This is the source code of a simple WebKit browser in PyGTK+.

```#!/usr/bin/env python
import pygtk
import gtk
import webkit

# Creates the GTK+ app
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.scrolled_window = gtk.ScrolledWindow()
# Creates a WebKit view
self.web_view = webkit.WebView()
# Sets the window size
self.window.set_default_size(1024, 800)
gtk.main()
```

Using Python we get rid of the manual memory management. Now, let's use WebKit and Python to build a tool.

Facebook and desktop applications: OAuth 2.0.

Facebook has a programmable API, so application can interact with user data. Probably you know Farmville, the popular Facebook game. Farmville uses Facebook API to access to our data. For applications to be able to interact with our data, developers must register the application in Facebook and the each user grants permission access to the app.

This protocol to obtain user access is called OAuth 2.0, and is has become a popular standard among many popular web sites. The workflow is:

1. The application launchs a browser and load FB's OAuth dialog, passing as arguments the app key and a redirection URL: https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=...
2. The user authenticates himself in Facebook.

The problem with this workflow is that desktop applications don't usually run a web server, so it's difficult to get this access token. How can we do it? Using WebKit!

`self.web_view.connect('load-committed', self._load_committed_cb) # Load page`

The 'load-commited' signal is emmited by the WebKit view when a page is about to be loaded. In the _load_commited_cb function, the page URL is checked to get Facebook's application access token. This token is finally saved to a file and the browser is closed.

This is the source code:

`#!/usr/bin/env python`
```import pygtk
import gtk
import webkit
import urllib
import urlparse

FB_TOKEN_FILE = 'access_token.txt'

class Browser:
""" Creates a web browser using GTK+ and WebKit to authorize a
desktop application in Facebook. It uses OAuth 2.0.
Requires the Facebook's Application ID. The token is then
saved to FB_TOKEN_FILE.
"""

def __init__(self, app_key, scope='offline_access'):
""" Constructor. Creates the GTK+ app and adds the WebKit widget
@param app_key Application key ID (Public).

@param scope A string list of permissions to ask for. More at
"""
self.token = ''
self.token_expire = ''
self.scope = scope
# Creates the GTK+ app
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.scrolled_window = gtk.ScrolledWindow()
# Creates a WebKit view
self.web_view = webkit.WebView()
# Connects events
self.window.connect('destroy', self._destroy_event_cb) # Close window
self.window.set_default_size(1024, 800)
)

""" Callback. The page is about to be loaded. This event is captured
to intercept the OAuth 2.0 redirection, which includes the

@param web_view A reference to the current WebKitWebView.

@param frame A reference to the main WebKitWebFrame.
"""
# Gets the current URL to check whether is the one of the redirection
uri = frame.get_uri()
parse = urlparse.urlparse(uri)
if (hasattr(parse, 'netloc') and hasattr(parse, 'path') and
hasattr(parse, 'fragment') and parse.netloc == 'www.facebook.com' and
# Get token from URL
params = urlparse.parse_qs(parse.fragment)
self.token = params['access_token'][0]
self.token_expire = params['expires_in'][0] # Should be equal to 0, don't expire
# Save token to file
token_file = open(FB_TOKEN_FILE, 'w')
token_file.write(self.token)
token_file.close()
gtk.main_quit() # Finish

def _destroy_event_cb(self, widget):
""" Callback for close window. Closes the application. """
return gtk.main_quit()

def authorize(self):
""" Runs the app. """
self.window.show_all()
gtk.main()

if (__name__ == '__main__'):
# Creates the browser
# Launch browser window
browser.authorize()
# Token available?
print "Token: %s" % (browser.token)
```

Easy, isn't it?

The complete source code is available at github.com/vrruiz/FacebookAuthBrowser

rvr

WebKit: Extending JavaScript - Signals and Callbacks (IV)

In the first post we described what WebKit and JavaScriptCore is, how to program a simple WebKitGTK+ application and how to extend the JavaScript functionality with a dumb (empty) class. In the second post, we extended JavaScript to enable desktop notifications. In the third post,  WebKit/JavaScriptCore were extended to access UPower properties using D-Bus.

Callbacks

As explained in the previous article, D-Bus is object oriented, and interfaces can expose objects with their methods, properties and events. We used D-Bus to access battery status, and extended WebKit/JavaScript Core to read it. In this post we are going to connect D-Bus signals with JavaScript callback functions. What we want to do is execute custom JavaScript code after a D-Bus signal has been emitted (and received).

D-Bus signals are events that clients can subscribe to. As explained, UDisks interface emits signals everytime a new external drive is attached to the system, and Linux desktops capture this events to launch file managers (and other applications).  UPower.Device also emits signals, and we are going to capture Changed().

It's easy to connect functions using  D-Bus Glib bindings. First, we add a signal to the proxy object, which is a  way to indicate the type of the arguments. Changed() doesn't has any parameter, so the call is this:

`    dbus_g_proxy_add_signal (proxy, "Changed", G_TYPE_INVALID);`

And then we connect the D-Bus signal with a callback function (battery_changed_cb).

```    dbus_g_proxy_connect_signal(proxy,
"Changed",
G_CALLBACK(battery_changed_cb),
ref,
(GClosureNotify) g_free);
```

This callback function will receive two parameters, proxy and ref, with references to its correspondent JavaScriptCore context and global object.

So, when UPower updates the battery status, it emits a Changed() signal. This signal will be received by our JavaScript Battery() objects. What happens then? battery_changed_cb will check whether Battery has a property called onChange and whether is of type function. So, if Battery.onChange stores a function, battery_changed_cb will call it. You'll see it more clearly in the JavaScript file.

Above is the source code of our previous D-Bus program. Remember that is based on that of the previous example.

```#include <stdlib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <gtk/gtk.h>
#include <webkit/webkit.h>
#include <JavaScriptCore/JavaScript.h>

DBusGConnection *conn;
DBusGProxy *proxy;
DBusGProxy *properties_proxy;

typedef struct {
JSContextRef context;
JSObjectRef object;
} RefContextObject;

/* Callback for UPower.Device.Changed() */
static void battery_changed_cb(DBusGProxy *_proxy, RefContextObject *ref)
{
g_message("Battery changed");

/* Get onChange property */
JSStringRef string_onchange;
string_onchange = JSStringCreateWithUTF8CString("onChange");
JSValueRef func = JSObjectGetProperty(ref->context, ref->object, string_onchange, NULL);
JSObjectRef function = JSValueToObject(ref->context, func, NULL);
JSStringRelease(string_onchange);

if (!JSObjectIsFunction(ref->context, function)) {
g_message("JSObject is not function or is not set");
return;
}

JSValueRef result = JSObjectCallAsFunction(ref->context, // The execution context to use
function, // The JSObject to call as a function.
ref->object, // The object to use as "this," or NULL to use the global object as "this."
0, //  An integer count of the number of arguments in arguments.
NULL, // A JSValue array of arguments to pass to the function. Pass NULL if argumentCount is 0.
NULL); // A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.

}

/* Class initialize */
static void battery_init_cb(JSContextRef ctx,
JSObjectRef object)
{
GError *error = NULL;

conn = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);

if (conn == NULL)
{
g_printerr ("Failed to open connection to bus: %s\n", error->message);
g_error_free (error);
return;
}

/* Create a proxy object for "org.freedesktop.UPower" */
proxy = dbus_g_proxy_new_for_name (conn,
"org.freedesktop.UPower",
"/org/freedesktop/UPower/devices/battery_BAT0",
"org.freedesktop.UPower.Device");
if (proxy == NULL)
{
g_printerr ("Failed to create proxy object\n");
return;
}

/* Create a proxy object for "org.freedesktop.UPower.Properties" */
properties_proxy = dbus_g_proxy_new_from_proxy (proxy,
"org.freedesktop.DBus.Properties",
dbus_g_proxy_get_path (proxy));
if (properties_proxy == NULL)
{
g_printerr ("Failed to create proxy object\n");
return;
}

/* Connect callback to signal org.freedestop.UPower.Device.Changed() */
RefContextObject *ref = g_new(RefContextObject, 1);
ref->context = ctx;
ref->object = object;

dbus_g_proxy_connect_signal(proxy,
"Changed",
G_CALLBACK(battery_changed_cb),
ref,
(GClosureNotify) g_free);

error = NULL;
}

/* Class constructor */
static JSObjectRef battery_constructor_cb(JSContextRef context,
JSObjectRef constructor,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef *exception)
{
return constructor;
}

/* Class finalize */
static void battery_destroy_cb(JSObjectRef object)
{
/* Ends Battery */
if (proxy != NULL) g_object_unref (proxy);
if (properties_proxy != NULL) g_object_unref (properties_proxy);
}

static gboolean proxy_property_value(char *property,
GValue *get_value,
GError **error)
{
/* Call ListNames method, wait for reply */
return dbus_g_proxy_call (properties_proxy, "Get", error,
G_TYPE_STRING, "/org/freedesktop/UPower/devices/battery_BAT0",
G_TYPE_STRING, property,
G_TYPE_INVALID,
G_TYPE_VALUE, get_value,
G_TYPE_INVALID);
}

static JSValueRef proxy_double_value(JSContextRef context,
char *property,
size_t argumentCount)
{
GError *error = NULL;
GValue get_value = {0, };

if (argumentCount == 0) {
/* Call method, wait for reply */
if (!proxy_property_value(property, &get_value, &error))
{
g_printerr ("Error: %s\n", error->message);
g_error_free (error);
return JSValueMakeUndefined(context);
}

gdouble value = g_value_get_double(&get_value);
g_value_unset(&get_value);
return JSValueMakeNumber(context, value);
}

return JSValueMakeUndefined(context);
}

static JSValueRef proxy_uint64_value(JSContextRef context,
char *property,
size_t argumentCount)
{
GError *error = NULL;
GValue get_value = {0, };

if (argumentCount == 0) {
/* Call method, wait for reply */
if (!proxy_property_value(property, &get_value, &error))
{
g_printerr ("Error: %s\n", error->message);
g_error_free (error);
return JSValueMakeUndefined(context);
}

guint64 value = g_value_get_uint64(&get_value);
g_value_unset(&get_value);
return JSValueMakeNumber(context, value);
}

return JSValueMakeUndefined(context);
}

static JSValueRef proxy_boolean_value(JSContextRef context,
char *property,
size_t argumentCount)
{
GError *error = NULL;
GValue get_value = {0, };

if (argumentCount == 0) {
/* Call method, wait for reply */
if (!proxy_property_value(property, &get_value, &error))
{
g_printerr ("Error: %s\n", error->message);
g_error_free (error);
return JSValueMakeUndefined(context);
}

gboolean value = g_value_get_boolean(&get_value);
g_value_unset(&get_value);
return JSValueMakeBoolean(context, value);
}

return JSValueMakeUndefined(context);
}

/* Battery.capacity method callback implementation */
static JSValueRef battery_capacity_cb(JSContextRef context,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef *exception)
{
return proxy_double_value(context, "Capacity", argumentCount);
}

/* Battery.percentage method callback implementation */
static JSValueRef battery_percentage_cb(JSContextRef context,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef *exception)
{
return proxy_double_value(context, "Percentage", argumentCount);
}

/* Battery.voltage method callback implementation */
static JSValueRef battery_voltage_cb(JSContextRef context,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef *exception)
{
return proxy_double_value(context, "Voltage", argumentCount);
}

/* Battery.updateTime method callback implementation */
static JSValueRef battery_update_time_cb(JSContextRef context,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef *exception)
{
return proxy_uint64_value(context, "UpdateTime", argumentCount);
}

/* Battery.PowerSupply method callback implementation */
static JSValueRef battery_power_supply_cb(JSContextRef context,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef *exception)
{
return proxy_boolean_value(context, "PowerSupply", argumentCount);
}

/* Class method declarations */
static const JSStaticFunction battery_staticfuncs[] =
{
{ NULL, NULL, 0 }
};

{
0,                     // version
kJSClassAttributeNone, // attributes
"Battery",             // className
NULL,                  // parentClass
NULL,                  // staticValues
battery_staticfuncs,   // staticFunctions
battery_init_cb,       // initialize
battery_destroy_cb,    // finalize
NULL,                  // hasProperty
NULL,                  // getProperty
NULL,                  // setProperty
NULL,                  // deleteProperty
NULL,                  // getPropertyNames
NULL,                  // callAsFunction
battery_constructor_cb, // callAsConstructor
NULL,                  // hasInstance
NULL                   // convertToType
};

/* Callback - JavaScript window object has been cleared */
static void window_object_cleared_cb(WebKitWebView  *web_view,
WebKitWebFrame *frame,
gpointer        context,
gpointer        window_object,
gpointer        user_data)

{
/* Add classes to JavaScriptCore */
JSObjectRef classObj = JSObjectMake(context, classDef, context);
JSObjectRef globalObj = JSContextGetGlobalObject(context);
JSStringRef str = JSStringCreateWithUTF8CString("Battery");
JSObjectSetProperty(context, globalObj, str, classObj, kJSPropertyAttributeNone, NULL);
}

/* Destroy callback */
static void destroy(GtkWidget *widget,
gpointer   data )
{
gtk_main_quit();
}

int
main (int argc, char* argv[])
{
/* Initialize the widget set */
gtk_init (&argc, &argv);

/* Create the window widgets */
GtkWidget *main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);

/* Create the WebKit Web View widget */
GtkWidget *web_view = webkit_web_view_new ();

/* Connect the window object cleared event with callback */
g_signal_connect (G_OBJECT (web_view), "window-object-cleared", G_CALLBACK(window_object_cleared_cb), web_view);

/* Place the WebKitWebView in the GtkScrolledWindow */

/* Connect the destroy window event with destroy function */
g_signal_connect (G_OBJECT (main_window), "destroy", G_CALLBACK (destroy), NULL);

/* Open webpage */

/* Create the main window */
gtk_window_set_default_size (GTK_WINDOW (main_window), 800, 600);

/* Show the application window */
gtk_widget_show_all (main_window);

/* Enter the main event loop, and wait for user interaction */
gtk_main ();

/* The user lost interest */
return 0;
}```

To compile it on Ubuntu:

\$ gcc webkit-05.c -o webkit.c `pkg-config --cflags --libs webkitgtk-3.0 dbus-glib-1`

Above, the corresponding HTML file webkit-05.html.

```<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<body>
<h1>Extending JavaScript with WebKit. Battery class.</h1>
<div id="battery-status"></div>
<script type="text/javascript">
var display = function () {
var div = document.getElementById("battery-status");
var battery_status = "Capacity: " + Battery.capacity() + "<br>";
battery_status += "Percentage: " + Battery.percentage() + "%<br>";
battery_status += "Voltage: " + Battery.voltage() + "<br>";
battery_status += "Update Time: " + Battery.updateTime() + "<br>";
battery_status += "Power supply: " + Battery.powerSupply() + "<br>";
div.innerHTML = battery_status;
}

var battery = new Battery();
battery.onChange = display;
display();
</script>
</body>
</html>
```

var display stores a reference to a function. This function fills the empty <div id=battery-status> with the actual battery status. Finally, a Battery() object is created and battery.onChange is defined.

If we run our program

\$ ./webkit-05

when UPower.Device.Changed() is emitted, our JavaScript function will be called and the battery status, automatically updated in the web page.

As before, the complete source code is available at github.com/vrruiz/WebKit-JavaScriptCore-Extensions.

rvr

WebKit: Extending JavaScript - D-Bus and UPower (III)

In the first post we described what WebKit and JavaScriptCore is, how to program a simple WebKitGTK+ application and how to extend the JavaScript functionality with a dumb (empty) class. In the second post, we extended JavaScript to enable desktop notifications.

In this third tutorial we are going to extend WebKit/JavaScriptCore to enable access to system information, specifically, battery status. We'll do this using D-Bus.

What's D-Bus?

Today's desktop environments, like GNOME and KDE, quickly respond to USB events: when an external drive is connected, a file navigator appears. How does it work?

GNOME and KDE provide a standard system for interprocess communication, called D-Bus. D-Bus communications is object oriented: applications expose objects with their methods, properties and events, and they are remotely available.

There are GUI applications to play with D-Bus. One of them is D-Feet. To install it on Ubuntu, type:

\$ sudo apt-get install d-feet

In D-Feet we can connect to two default buses: the session bus and the system bus. Regular desktop applications use the session bus, tied to the user running the current desktop session. The system bus has a lower level and used by services in the operating system. This screenshot shows D-Feet connected to the session bus:

And finally the enigma is solved: if the desktop wants to know when a new disk is attached to the computer, it just can do it using D-Bus and UDisks interface: actually, the operating system uses the system bus to communicate disk events.

D-Bus and battery status: UPower.

In the screenshot above, on the right we can see the interfaces, methods and properties exposed by UPower in the system bus.  For example, the list of power devices (batteries and power line) is available using the EnumerateDevices() method, which returns the device list as and array of objects. Another interface, UPower.Device, gives us access to the battery status, and we'll use it to build our custom JavaScript class.

In order to connect to D-Bus, we use the Glib's D-Bus bindings. To install the development libraries, type:

\$ sudo apt-get install libdbus-glib-1-dev

The actual code is this:

```#include <stdlib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <gtk/gtk.h>
#include <webkit/webkit.h>
#include <JavaScriptCore/JavaScript.h>

DBusGConnection *conn;
DBusGProxy *proxy;
DBusGProxy *properties_proxy;

/* Class initialize */
static void battery_init_cb(JSContextRef ctx,
JSObjectRef object)
{
GError *error = NULL;

/* Connection to the system bus */
conn = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);

if (conn == NULL)
{
g_printerr ("Failed to open connection to bus: %s\n", error->message);
g_error_free (error);
return;
}

/* Create a proxy object for "org.freedesktop.UPower" */
proxy = dbus_g_proxy_new_for_name (conn,
"org.freedesktop.UPower",
"/org/freedesktop/UPower/devices/battery_BAT0",
"org.freedesktop.UPower.Device.Properties");
if (proxy == NULL)
{
g_printerr ("Failed to create proxy object\n");
return;
}

/* Creates a proxy using an existing proxy as a template */
properties_proxy = dbus_g_proxy_new_from_proxy (proxy,
"org.freedesktop.DBus.Properties",
dbus_g_proxy_get_path (proxy));
if (properties_proxy == NULL)
{
g_object_unref (proxy)
g_printerr ("Failed to create proxy object\n");
return;
}

error = NULL;
}

/* Class finalize */
static void battery_destroy_cb(JSObjectRef object)
{
/* Ends Battery. Free allocated memory. */
if (proxy != NULL) g_object_unref (proxy);
if (properties_proxy != NULL) g_object_unref (properties_proxy);
}

static gboolean proxy_property_value(char *property,
GValue *get_value,
GError **error)
{
/* Call Get method, wait for reply */
return dbus_g_proxy_call (properties_proxy, "Get", error,
G_TYPE_STRING, "/org/freedesktop/UPower/devices/battery_BAT0",
G_TYPE_STRING, property,
G_TYPE_INVALID,
G_TYPE_VALUE, get_value,
G_TYPE_INVALID);
}

static JSValueRef proxy_double_value(JSContextRef context,
char *property,
size_t argumentCount)
{
/* Calls to UPower to get a double value */

GError *error = NULL;
GValue get_value = {0, };

if (argumentCount == 0) {
/* Get property value */
if (!proxy_property_value(property, &get_value, &error))
{
g_printerr ("Error: %s\n", error->message);
g_error_free (error);
return JSValueMakeUndefined(context);
}

/* Convert value to double */
gdouble value = g_value_get_double(&get_value);
g_value_unset(&get_value);
return JSValueMakeNumber(context, value);
}

return JSValueMakeUndefined(context);
}

static JSValueRef proxy_uint64_value(JSContextRef context,
char *property,
size_t argumentCount)
{
/* Calls to UPower to get a uint64 value */
GError *error = NULL;
GValue get_value = {0, };

if (argumentCount == 0) {
/* Get property value */
if (!proxy_property_value(property, &get_value, &error))
{
g_printerr ("Error: %s\n", error->message);
g_error_free (error);
return JSValueMakeUndefined(context);
}

/* Convert value to uint64 */
guint64 value = g_value_get_uint64(&get_value);
g_value_unset(&get_value);
return JSValueMakeNumber(context, value);
}

return JSValueMakeUndefined(context);
}

static JSValueRef proxy_boolean_value(JSContextRef context,
char *property,
size_t argumentCount)
{
/* Calls to UPower to get a boolean value */

GError *error = NULL;
GValue get_value = {0, };

if (argumentCount == 0) {
/* Call method, wait for reply */
if (!proxy_property_value(property, &get_value, &error))
{
g_printerr ("Error: %s\n", error->message);
g_error_free (error);
return JSValueMakeUndefined(context);
}

/* Convert value to boolean */
gboolean value = g_value_get_boolean(&get_value);
g_value_unset(&get_value);
return JSValueMakeBoolean(context, value);
}

return JSValueMakeUndefined(context);
}

/* Battery.capacity method callback implementation */
static JSValueRef battery_capacity_cb(JSContextRef context,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef *exception)
{
/* Get battery capacity status */
return proxy_double_value(context, "Capacity", argumentCount);
}

/* Battery.percentage method callback implementation */
static JSValueRef battery_percentage_cb(JSContextRef context,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef *exception)
{
/* Get battery percentage status */
return proxy_double_value(context, "Percentage", argumentCount);
}

/* Battery.voltage method callback implementation */
static JSValueRef battery_voltage_cb(JSContextRef context,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef *exception)
{
/* Get battery voltage status */
return proxy_double_value(context, "Voltage", argumentCount);
}

/* Battery.updateTime method callback implementation */
static JSValueRef battery_update_time_cb(JSContextRef context,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef *exception)
{
/* Get battery update time */
return proxy_uint64_value(context, "UpdateTime", argumentCount);
}

/* Battery.PowerSupply method callback implementation */
static JSValueRef battery_power_supply_cb(JSContextRef context,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef *exception)
{
/* Get battery power supply */
return proxy_boolean_value(context, "PowerSupply", argumentCount);
}

/* Class method declarations */
static const JSStaticFunction battery_staticfuncs[] =
{
{ NULL, NULL, 0 }
};

{
0,                     // version
kJSClassAttributeNone, // attributes
"Battery",             // className
NULL,                  // parentClass
NULL,                  // staticValues
battery_staticfuncs,   // staticFunctions
battery_init_cb,       // initialize
battery_destroy_cb,    // finalize
NULL,                  // hasProperty
NULL,                  // getProperty
NULL,                  // setProperty
NULL,                  // deleteProperty
NULL,                  // getPropertyNames
NULL,                  // callAsFunction
NULL,                  // callAsConstructor
NULL,                  // hasInstance
NULL                   // convertToType
};

/* Callback - JavaScript window object has been cleared */
static void window_object_cleared_cb(WebKitWebView  *web_view,
WebKitWebFrame *frame,
gpointer        context,
gpointer        window_object,
gpointer        user_data)

{
/* Add classes to JavaScriptCore */
JSObjectRef classObj = JSObjectMake(context, classDef, context);
JSObjectRef globalObj = JSContextGetGlobalObject(context);
JSStringRef str = JSStringCreateWithUTF8CString("Battery");
JSObjectSetProperty(context, globalObj, str, classObj, kJSPropertyAttributeNone, NULL);
}

/* Destroy callback */
static void destroy(GtkWidget *widget,
gpointer   data )
{
gtk_main_quit();
}

int
main (int argc, char* argv[])
{
/* Initialize the widget set */
gtk_init (&argc, &argv);

/* Create the window widgets */
GtkWidget *main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);

/* Create the WebKit Web View widget */
GtkWidget *web_view = webkit_web_view_new ();

/* Connect the window object cleared event with callback */
g_signal_connect (G_OBJECT (web_view), "window-object-cleared", G_CALLBACK(window_object_cleared_cb), web_view);

/* Place the WebKitWebView in the GtkScrolledWindow */

/* Connect the destroy window event with destroy function */
g_signal_connect (G_OBJECT (main_window), "destroy", G_CALLBACK (destroy), NULL);

/* Open webpage */

/* Create the main window */
gtk_window_set_default_size (GTK_WINDOW (main_window), 800, 600);

/* Show the application window */
gtk_widget_show_all (main_window);

/* Enter the main event loop, and wait for user interaction */
gtk_main ();

/* The user lost interest */
return 0;
}
```

This program creates a new JavaScript class, called Battery, with some useful methods, like Battery.percentage(), Battery.capacity() and Battery.powerSupply(). When the class is initiated, a system bus connection is created, which is used later by the methods to obtain actual battery values.

This is webkit-04.html, a simple web file which uses the newly created Battery class:

```<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<body>
<h1>Extending JavaScript with WebKit. Battery class.</h1>
<script type="text/javascript">
document.write("Capacity: " + Battery.capacity() + "<br>");
document.write("Percentage: " + Battery.percentage() + "%<br>");
document.write("Voltage: " + Battery.voltage() + "<br>");
document.write("Update Time: " + Battery.updateTime() + "<br>");
document.write("Power supply: " + Battery.powerSupply() + "<br>");
</script>
</body>
</html>
```

To compile and run the program, type:

\$ gcc -o webkit-04 webkit-04.c `pkg-config --cflags --libs webkitgtk-3.0 dbus-glib-1`

\$ ./webkit-04

The program, if running on a laptop with batteries, will display something like this:

Great, isn't it!? :-)

The source code is available at github.com/vrruiz/WebKit-JavaScriptCore-Extensions.

As we've seen, D-Bus is a powerful system. Mixing JavaScript with D-Bus gives us incredible possibilities. See you in the next post!

rvr

WebKit: Extending JavaScript (I)

In recent years, JavaScript has become a very popular language. Google has promoted rich web applications which compete with desktop programs: Gmail, Google Maps and Google Docs are rivals of Outlook, Google Earth and Office. Today HTTP, HTML, CSS and JavaScript are key technologies in which companies are heavily investing so they can develop even more powerful web applications,  i.e. HTML5 features enable off-line web applications (i.e. store local data).

JavaScript has a restricted programming model in order to meet security concerns. But, wouldn't be fun if we could extend JavaScript to create wonderful programs which mix desktop and web technologies? Absolutely! In order to do that, we'll use WebKit and Gtk+.

The source code of this tutorial is available at github.com/vrruiz/WebKit-JavaScriptCore-Extensions.

WebKit

Chances are that you're using a browser which comes with WebKit. This open source technology was originally developed by KDE, and forked by Apple. WebKit powers Apple's Safari, Google's Chrome and many other browsers.

WebKit is to browsers what an engine is to cars: many bodyworks can carry the same engine model. WebKit provides the basic functions to download, parse, run and display web pages. However, WebKit doesn't provide a user interface to introduce URL address, change settings, navigation buttons, etc. That's the developer's job.

WebKit is multiplatform. Interesting to us is that WebKit is extensible and provides ways to interact with its JavaScript default engine, JavaScriptCore.

Currently, KDE, Gnome and MacOS X support WebKit, to provide HTML views inside desktop applications. WebKit has been ported to many platforms (Mac, Linux, Windows), many SDK's (Cocoa, Gtk, Qt) and many languages.  One of this ports is WebKitGTK+.

WebKitGTK+

GTK+ is multiplatform graphical toolkit, a set of graphical libraries to program desktop applications (the popular Linux desktop enviroment GNOME is built upon GTK+). WebKitGTK+ allows GTK+ applications to display web pages using WebKit. Originally, WebKit is programmed in C++, but WebKitGTK+ has a C interface using GObject (part of GLib, which "enables" object-oriented programming in plain C).

To install GTK+ and WebKitGTK+ development files in Ubuntu do this in the command line:

\$ sudo apt-get install gnome-devel libwebkitgtk-3.0-dev

A simple web view.

This program creates a GTK+ application. The main window has 800 x 600 pixels, and contains a scrolled window which finally holds the web view. The web view displays this blog.

```#include <gtk/gtk.h>
#include <webkit/webkit.h>

/* Destroy callback */
static void destroy_cb( GtkWidget *widget,
gpointer   data )
{
gtk_main_quit();
}

int
main (int argc, char* argv[])
{
/* Initialize the widget set */
gtk_init (&argc, &argv);

/* Create the window widgets */
GtkWidget *main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);

/* Create the WebKit Web View widget */
GtkWidget *web_view = webkit_web_view_new ();

/* Place the WebKitWebView in the GtkScrolledWindow */

/* Connect the destroy window event with destroy function */
g_signal_connect (G_OBJECT (main_window), "destroy", G_CALLBACK (destroy_cb), NULL);

/* Open webpage */

/* Create the main window */
gtk_window_set_default_size (GTK_WINDOW (main_window), 800, 600);

/* Show the application window */
gtk_widget_show_all (main_window);

/* Enter the main event loop, and wait for user interaction */
gtk_main ();

/* The user lost interest */
return 0;
}
```

To compile and run this program, type:

\$ gcc webkit-01.c -o webkit-01 `pkg-config --cflags --libs webkitgtk-3.0`

\$ ./webkit-01

An application with a web view will appear.

Your own browser in just a minute. Easy, isn't it?

Interacting with JavaScriptCore.

What's great about WebKit is that the JavaScript engine can be extended to support custom functions. PhoneGap SDK actually uses this feature to provide mobile developers access to low-level OS features via JavaScript (i.e. accelerometer).

As previously stated, JavaScriptCore is WebKit's JavaScript engine, at it provides an API to extend JavaScript and add new classes. Basically, for each class we need to provide callbacks for the constructor and destructor class, and a list of class methods and a callback for each of them.

Next is the source code of a bare JavaScript class declaration. It does nothing, except to print a messages in the console when the class is initialized and the constructor method called.

```#include <gtk/gtk.h>
#include <webkit/webkit.h>
#include <JavaScriptCore/JavaScript.h>

/* Class initialize */
static void class_init_cb(JSContextRef ctx,
JSObjectRef object)
{
g_message("Custom class initialize.");
}

/* Class finalize */
static void class_finalize_cb(JSObjectRef object)
{
g_message("Custom class finalize.");
}

/* Class constructor. Called at "new CustomClass()" */
JSObjectRef class_constructor_cb(JSContextRef ctx,
JSObjectRef constructor,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef* exception)
{
g_message("Custom class constructor");
}

static const JSClassDefinition class_def =
{
0,                     // version
kJSClassAttributeNone, // attributes
"CustomClass",         // className
NULL,                  // parentClass
NULL,                  // staticValues
NULL,                  // staticFunctions
class_init_cb,         // initialize
class_finalize_cb,     // finalize
NULL,                  // hasProperty
NULL,                  // getProperty
NULL,                  // setProperty
NULL,                  // deleteProperty
NULL,                  // getPropertyNames
NULL,                  // callAsFunction
class_constructor_cb,  // callAsConstructor
NULL,                  // hasInstance
NULL                   // convertToType
};

/* Callback - JavaScript window object has been cleared */
static void window_object_cleared_cb(WebKitWebView  *web_view,
WebKitWebFrame *frame,
gpointer        context,
gpointer        window_object,
gpointer        user_data)

{
/* Add classes to JavaScriptCore */
JSClassRef classDef = JSClassCreate(&class_def);
JSObjectRef classObj = JSObjectMake(context, classDef, context);
JSObjectRef globalObj = JSContextGetGlobalObject(context);
JSStringRef str = JSStringCreateWithUTF8CString("CustomClass");
JSObjectSetProperty(context, globalObj, str, classObj, kJSPropertyAttributeNone, NULL);
}

/* Destroy callback */
static void destroy(GtkWidget *widget,
gpointer   data )
{
gtk_main_quit();
}

int
main (int argc, char* argv[])
{
/* Initialize the widget set */
gtk_init (&argc, &argv);

/* Create the window widgets */
GtkWidget *main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);

/* Create the WebKit Web View widget */
GtkWidget *web_view = webkit_web_view_new ();

/* Connect the window object cleared event with callback */
g_signal_connect (G_OBJECT (web_view), "window-object-cleared", G_CALLBACK(window_object_cleared_cb), web_view);

/* Place the WebKitWebView in the GtkScrolledWindow */

/* Connect the destroy window event with destroy function */
g_signal_connect (G_OBJECT (main_window), "destroy", G_CALLBACK (destroy), NULL);

/* Open webpage */

/* Create the main window */
gtk_window_set_default_size (GTK_WINDOW (main_window), 800, 600);

/* Show the application window */
gtk_widget_show_all (main_window);

/* Enter the main event loop, and wait for user interaction */
gtk_main ();

/* The user lost interest */
return 0;
}
```

This program loads a local file, webkit-02.html, which only defines a CustomClass object.

```<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<body>
<h1>Extending JavaScript with WebKit. Custom Class.</h1>
<script type="text/javascript">
custom = new CustomClass();
</script>
</body>
</html>
```

To compile this, type:

\$ gcc webkit-02.c -o webkit-02 `pkg-config --cflags --libs webkitgtk-3.0`