Subtitel

A blog by Juri Urbainczyk | Juri on Google+ | Juri on Twitter | Juri on Xing

Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Sunday, November 22, 2015

node.js and MIDI

jazz-midi (www.thejazzpage.de) is a node.js module which allows access to MIDI interfaces. Midi (musical instrument digital interface) is an international standard for communication between electronical music devices which was invented in the early 80ies. Recently, I have been playing around with jazz-midi quite a bit and I figured I should share my experiences here. Now, first of all opening MIDI devices goes like a breeze:

var outName = MIDI.MidiOutOpen(2);
if (outName) {
  console.log('Opened MIDI-Out port: ', outName); 
} else {
  console.log('Cannot open MIDI-Out port!');
}


This example opens a MIDI out port with the port number 2 (if this one is available). To get a list of available MIDI ports, just use MIDI.MidiOutList() or MIDI.MidiInList() respectively. As easy as this is, I quickly found out that you cannot open multiple ports and then, for instance, receive events from all the ports simultaneously. I tried different ways to circumvent this issue (e.g. calling MidiOutOpen() multiple times) but nothing really worked. That's quite a limitation.

On to the next step, receiving and sending MIDI events:

var inName = MIDI.MidiInOpen( 1, function(t, msg) {   
    if ((msg[0] != 254) && (msg[0] != undefined)) {
        MIDI.MidiOut(msg[0]+midiChannel-1, msg[1], msg[2]);   
    }
});


The above example opens the MIDI in port 1. Whenever a MIDI event comes along, it just triggeres the anonymous callback function which then again sends the MIDI event to the MIDI out port we just opened. The if-statement filters out all the MIDI "active sensing" events, which are generated by many devices just to tell the world that they are alive. Also, take a look at the MidiOut statement. It includes a global variable (bah!) called "midiChannel" which can hold the value 1 to 16 which indicate the "Midi Channel" to send the data to. A MIDI device, such as a synthesizer, will only receive the event, when it listens to the corresponding channel.

The next step, obviously would be to play a note. In MIDI each note is defined by two MIDI events called 'note-on' and 'note-off'. A MIDI note-of must be parametrized with a key value (which defines the pitch) and the key attack velocity (which most of the time defines the volume). Each can have valid values between 0 and 127. A note-off also has to have a key value and a release velocity (which is ignored by most MIDI devices). To play a note, you have to combine a note-on with a corresponding note-off event. The time difference between note-on and note-off defines the duration of the note. All this is accomplished by the following piece of code:

function playNote( note, velocity, length, channel ) {
        MIDI.MidiOut(144+channel-1, note, velocity);
        setTimeout( function() {
                MIDI.MidiOut(144+channel-1, note, 0);
                MIDI.MidiOut(128+channel-1, note, 64); // also send MIDI note off
            },
        length );
}


This sends a note-on on a defined MIDI channel (that's why it's 144+channel-1). And then it creates a timeout which will send the corresponding note-off 'length' milliseconds after the note-on.

Great, now we can play music on our devices triggered by JavaScript. But what happens if something goes awry and notes keep playing on the MIDI device forever? For this scenario MIDI inventend the 'all-notes-off' command, which tells the device to just shut up. Of course, we can send that from JavaScript as well, as the following example shows:

function sendAllNotesOff() {
    //loop over all MIDI channels and send all notes off and all controllers off
    for (var i=0; i<16; i++) {
        MIDI.MidiOut( 176+i, 123, 0 );   
        MIDI.MidiOut( 176+i, 121, 0 );   
    }
}


The following screenshot shows the MIDI events captured by the node.js program when playing on the MIDI keyboard.

MIDI Events
Have fun.

Wednesday, April 8, 2015

Implementing a REST API with node.js

Every so often there is the necessity to implement some mock-up web services or maybe even a prototype which shall offer its functionality via web services. This happened to me once again in March 2015 when preparing the API for a hackathon. To be precise, there already was an API, but it did not really fit to the requirements of the hackathon’s sponsor. Therefore, we decided to implement a second API (as a mock API) on top of the existing one. Our, second, API should add additional functionality to the existing services.
It was quite clear that the API should be REST with JSON as transport protocol. Unfortunately, we only had less than 4 weeks to design, implement and test the mock API. Thus, only a very lightweight technology could make this possible, like node.js.
Being JavaScript on the server, node.js is indeed a very lightweight technology. In its most basic configuration it will require you to write only one JavaScript file, which is then read and executed by node. Furthermore, it come with a module concept which lets you include already existing modules into your code with the “require” statement. Node also brings a packet manager (named “npm”) which lets you easily install all those modules to your project’s file system. In our mock API we used the following imports:
var http = require('http');
var express = require('express');
var url = require( "url" );
var path = require("path");
var fs = require("fs");
var queryString = require( "querystring" );

For our purposes, the “express” module is very important: it enables us to write REST services like in the following example. This short piece of code implements a web service, using the HTTP “GET” method, which echoes all input back to the response.

var api = express();

api.get('/echo', function(req,res) {

       var myobj = "";
      
        // parses the request url
        var theUrl = url.parse( req.url );
       
        //check if there is a query       
        if ((theUrl.query != null) && (theUrl.query != "")) {

             // gets the query part of the URL and parses it creating an object
             var queryObj = queryString.parse( theUrl.query );
              
             // queryObj contains the data of the query as an object
             // and jsonData is a property of it
             myobj = JSON.parse( queryObj.jsonData );                   
       }

       res.json( myobj );
});

As this examples shows, it’s really quite simple. For the response, you have to create a JavaScript object (which also might be a quite big one with arrays included and so on…) and transform it to JSON with “res.json”. This data is then returned to the client. There is a catch, though: with a HTTP “GET” method the input parameters will be encoded in the URL and therefore there is an upper limit of data which can be input to the service (around 8 kB, depending on the browser and other factors).  So, in order to potentially input more data into the web service, a “POST” method should be used, like in the next example. This one also shows how to extract parameters from the request header and do some basic authentication. Anyway, please bear in mind, it's still only a prototype source code (e.g. there should be another return code than 400 if an error occurred).

api.post('/api/booking', function (request, response) {

     //Read header & body
     var jsonData = request.body.requestPayload;

     var requestID = request.header('requestId');
     var userName = request.header('userName');
     var userPassword = request.header('password')
     var timeStamp = request.header('timeStamp');

     if (!checkAuthWithResponse(userName, userPassword, response)) return;

     resultAsString = '';

     var err = oVali.runHeaderValidation(request);
     if (err.length > 0) {
  
          // some logging and error handling here
     } else {

          // some business logic here

     }

     Response.send( resultAsString, 400);
})

Our mock API was intended to implement additional business logic on top of the existing API. The client would then call the mock API’s services to execute this business logic. Because the logic would only be depending on the values of the input parameters of the services there was no need for additional data storage or caching. Nevertheless, it would be quite easy as well to integrate a NoSQL database into node.js, for example.
Our mock API based on node.js was implemented just in time for the Hackathon and it was used there with very good results. We experienced no outages and had no problems with the performance as well.

As a summary, what are the advantages of using node.js for REST API development? We can name the following:

  1. As a developer, you are up and running very quickly. Install node, download some modules, write ONE file, and you are done.
  2. You don’t need to learn a lot of tools and IDEs (low overhead).
  3. The feedback cycles are very short, enabling you to develop with high speed.
  4. Integration with file system and databases is easy.
  5. Many standard problems can be used out-of-the-box with only a few lines of code.
  6. There is a big community, helping you out if you run into problems. Online documentation and FAQ is huge.
  7. It’s very easy to transport node projects. Just zip and unzip the files and you are done.
  8. There are a lot of possibilities to deploy and run node projects on the web. Pricing starts very low as well.

The bottom line is: node.js is a perfect choice for implementing prototype REST services. In how far this could be extended to full blown operational services – that’s another matter.

Tuesday, June 25, 2013

An HTML5 canvas component for ExtJS 4

As I described in another post, ExtJS 4 features components for graphics ("Ext.draw.Component") which are based on the standard HTML SVG tag. But what if we liked to use a <canvas> tag? ExtJS does not bring one of those - thus we have to create one.

We also need a nice little showcase. For that, I implemented a small application, which simulates a solar system, with a configurable number of planets, moons and stars. The application calculates the gravity which affects the objects and then determines their new positions. This is done repeatedly, leading to a simulated continuous motion. The positions (and trajectories) of all objects are displayed in the canvas element. Picture 1 shows the solar system simulator in action.
Picture 1: Solar system simulator written with the canvas component
I put the canvas component in a separate file (canvasPanelClass.js), thus it should be easily reusable. The component utilizes the powerful object-oriented features of ExtJS. It extends Ext.Panel and creates the canvas element in the constructor method. In the afterrender listener (when the component already is complete) it stores a reference to the canvas in a private variable (this.canvas = this.items.items[0].el.dom;).

After that, the canvas is ready to be used. The component already brings some important methods, e.g. drawCircle( 50, 50, 10, "red" ) which draws a red circle with a radius of 10 pixels around the point 50, 50.

And now, the most interesting part of the source code:

        Ext.define('CanvasPanelClass', {
            extend: 'Ext.Panel',
           
            gridColor: '',
            ctx: null,        // is set when rendered
            canvas: null,    // is set when rendered                       
            bodyStyle: { background: '#000' },
            frame: false,
            margin: '2 2 2 2',
           
            listeners: {
                afterrender: {
                    fn: function(){                       
                        this.canvas = this.items.items[0].el.dom;           
                        this.ctx = this.canvas.getContext("2d");                                       this.clear();                       
                    }
                }       
            },           
           
            constructor: function(config) {
               
                //define this here because we can set width and height
                this.items = {
                    xtype: 'box',
                    autoEl:{
                        tag: 'canvas',
                        height: config.height,
                        width: config.width
                    }
                };
               
                this.tempCanvas = document.createElement("canvas");
               
                CanvasPanelClass.superclass.constructor.call(this, config);
            },
                    
            drawRect: function( x, y, width, height, lineWidth, color ) {
                this.ctx.strokeStyle = color;
                this.ctx.lineWidth = lineWidth;
                this.ctx.strokeRect(x,y,width,height);               
            },
           
            fillRect: function( x, y, width, height, color ) {
                this.ctx.fillStyle = color;
                this.ctx.fillRect(x,y,width,height);               
            },       
           
            drawCircle : function( x, y, radius, color ) {
                this.ctx.beginPath();
                this.ctx.strokeStyle = color;
                this.ctx.fillStyle = color;
                this.ctx.arc( x, y, radius, 0, Math.PI*2, true );
                this.ctx.closePath();
                this.ctx.fill();       
            },           
           
            putPixel: function( x, y, size, color ) {
                this.ctx.fillStyle = color;
                this.ctx.fillRect(x,y,size,size);           
            },

                  
            clear: function() {
           
                // Store the current transformation matrix
                this.ctx.save();

                // Use the identity matrix while clearing the canvas
                this.ctx.setTransform(1, 0, 0, 1, 0, 0);
                this.ctx.clearRect ( 0, 0, this.getWidth(), this.getHeight() );

                // Restore the transform
                this.ctx.restore();                                      
            }


        }); // define CanvasPanelClass

Then, the canvas component can be used like in the following code snippet. (There is an array of canvasPanels because you might want to create more than one canvas.) The mousedown handler shows how an application can react on mouse clicks into the canvas.

      canvasPanel[0] = new CanvasPanelClass({
            height: 500,
            width: 500
      });              

      canvasPanel[0].on({
            mousedown: function(DOMevent) {

                             var canvasPanelX = this.getPosition()[0];
                             var canvasPanelY = this.getPosition()[1]
                             var point = DOMevent.getPoint();

                             var eventX = point.x-canvasPanelX;
                             var eventY = point.y-canvasPanelY;

                              // do something …

                             canvasPanel[0].clear();
                             canvasPanel[0].renderGrid(25*50/ZOOM,GRIDCOLOR);
            },
            element: 'body',
            scope: canvasPanel[i] //Ensure "this" is correct during handler execution
      });

      tablePanel.add(canvasPanel[0]); 
  
      canvasPanel[0].clear();    

      canvasPanel[0].putPixel( 50, 50, 1, "green" );

Saturday, December 22, 2012

ExtJS Game of life – testing the Ext.draw library


I always wanted to check out the ExtJS graphics library (Ext.draw) and thus I decided to implement the Game of Life in ExtJS as a kind of prototype. The following screenshot shows the results, a running game of life on a 40x40 grid.

A running 40x40 game of life in ExtJS
 
Details about the Game of life can be found here: http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life

How can it be implemented in ExtJS? Since I wanted to test the ExtJS drawing functions, I chose an Ext.draw.Component as the basis. All grid cells are painted inside this component by creating a “sprite” for each grid. When a grid is alive I simply change the color of the sprite to black, otherwise I change it to white.

Now, that’s how the Ext.draw.Component is initialized. As you can see, it is created with one item (sprite) which just paints the blue border around the whole component.

var drawComponent = Ext.create('Ext.draw.Component', {
     viewBox: false,
     margin: '10 10 10 10',
     height: (DIMSIZE*(SPRITEWIDTH+SPRITEBORDER))+8,     
     width: (DIMSIZE*(SPRITEWIDTH+SPRITEBORDER))+8,
     items: [{
         type: 'rect',
         width: (DIMSIZE*(SPRITEWIDTH+SPRITEBORDER))+4,
         height: (DIMSIZE*(SPRITEWIDTH+SPRITEBORDER))+4,
         x: 0,  y: 0,
         stroke: 'blue',    
         'stroke-width': 2                    
     }]
}); 

In order to add new sprites to the Ext.draw.Component, you can just call the add() method. I noticed, that it was necessary to change one of the sprite’s attributes in order to make it appear on screen, so I just change the sprite type to ‘rect’ (as it was before). Of course, we have to implement a loop in order to create all necessary sprites.

myRect = drawComponent.surface.add({
     type: 'rect',
     width: SPRITEWIDTH,
     height: SPRITEWIDTH,
     fill: Ext.draw.Color.create(0, 0, 0, 1),
     x: 3+(x*(SPRITEWIDTH+SPRITEBORDER)),
     y: 3+(y*(SPRITEWIDTH+SPRITEBORDER)),
     xpos : x,
     ypos : y
});          

myRect.setAttributes({
     type: 'rect'
}, true);

The next picture shows which ExtJS classes are used to build the GUI:

ExtJS components in the game of life GUI

Furthermore, we need a timer, because we have to calculate the next generation and paint it again an again. This is achived with an ‘task’ object as seen in this piec of code:

var task = {
     run: function(){

         newGeneration();
         paintGeneration();              
     },
     interval: 500
}   

As you can see, the task interval (the time between to calls of the loop) is quite big: half a second. As a matter of fact, I learned that the interval could not become any smaller on my machine (and with Firefox or Chrome). Otherwise, the next run of the cycle would be called before the former generation was completed, botching the whole game. With a 40x40 grid, we already need 1600 sprites which seem to quite a lot, since the creation of the sprites takesca. 5 seconds. When I increase the grid size the time needed to instantiate the game grows heavily and the program becomes unusesable. 

As you can see, the ExtJS draw functions are not very fast and not well suited to graphics programming like this (I assume it is rather meant to be used for charting).

Thus, I decided to port the whole program to HTML5 canvas (or rather the grid part), which I will explain in a later blog post, so stay tuned.