Josh On DesignArt, Design, and Usability for Software EngineersTue Aug 19 2014 18:55:56 GMT+0000 (UTC)\nBuilding a Headline Viewer with AminoThis is part 3 of a series on <a href='https://github.com/joshmarinacci/aminogfx'>Amino</a>, a JavaScript graphics library for OpenGL on the Raspberry PI. You can also read <a href='http://joshondesign.com/2014/08/08/aminorefactored'>part 1</a> and <a href='http://joshondesign.com/2014/08/10/aminoslideshow'>part 2</a>. <p> Amino is built on <a href='http://nodejs.org'>Node JS</a>, a robust JavaScript runtime married to a powerful IO library. That’s nice and all, but the real magic of Node is the modules. For any file format you can think of someone has probably written a Node module to parse it. For any database you might want use, someone has made a module for it. <a href='https://www.npmjs.org'>npmjs.org</a> lists nearly ninety thousand packages! That’s a lot of modules ready for you to use. </p> <p> For today’s demo we will build a nice rotating display of news headlines that could run in the lobby of an office using a flatscreen TV on the wall. It will look like this: </p> <p> <img src='https://dl.dropbox.com/s/s9kkajq9axygafn/rssfeed2.png?raw=1' alt='image'/> </p> <p> </p> <p> We will fetch news headlines as RSS feeds. Feeds are easy to parse using Node streams and the <code>feedparser</code> module. Lets start by creating a <code>parseFeed</code> function. This function takes a url. It will load the feed from the url, extract the title of each article, then call the provided callback function with the list of headlines. </p> <pre><code>var FeedParser = require('feedparser'); var http = require('http'); function parseFeed(url, cb) { var headlines = []; http.get(url, function(res) { res.pipe(new FeedParser()) .on('meta',function(meta) { //console.log('the meta is',meta); }) .on('data',function(article) { console.log("title = ", article.title); headlines.push(article.title); }) .on('end',function() { console.log("ended"); cb(headlines); }) }); }</code></pre> <p> Node uses <i>streams</i>. Many functions, like the <code>http.get()</code> function, return a stream. You can pipe this stream through a filter or processor. In the code above we use the <code>FeedParser</code> object to filter the HTTP stream. This returns a new stream which will produce events. We can then listen to the events as the data flows through the system, picking up just the parts we want. In this case we will watch for the <code>data</code> event, which provides the article that was just parsed. Then we add just the title to the <code>headlines</code> array. When the <code>end</code> event happens we send the headlines array to the callback. This sort of streaming IO code is very common in Node programs. </p> <p> Now that we have a list of headlines lets make a display. We will hard code the size to 1280 x 720, a common HDTV resolution. Adjust this to fit your own TV if necessary. As before, the first thing we do is turn the titles into a CircularBuffer (see <a href='http://joshondesign.com/2014/08/10/aminoslideshow'>previous blog</a> ) and create a root group. </p> <pre><code>var amino = require('amino.js'); var sw = 1280; var sh = 720; parseFeed('http://www.npr.org/rss/rss.php?id=1001',function(titles) { amino.start(function(core, stage) { var titles = new CircularBuffer(titles); var root = new amino.Group(); stage.setSize(sw,sh); stage.setRoot(root); …</code></pre> <p> The RSS feed will be shown as two lines of text, so let’s create a text group then two text objects. Also create a background group to use later. Shapes are drawn in the order they are added, so we have to add the <code>bg</code> group <b>before</b> the textgroup. </p> <pre><code> var bg = new amino.Group(); root.add(bg); var textgroup = new amino.Group(); root.add(textgroup); var line1 = new amino.Text().x(50).y(200).fill("#ffffff").text('foo').fontSize(80); var line2 = new amino.Text().x(50).y(300).fill("#ffffff").text('bar').fontSize(80); textgroup.add(line1,line2);</code></pre> <p> Each Text object has the same position, color, and size except that one is 100 pixels lower down on the screen than the other. Now we need to animate them. </p> <p> The animation consists of three sections: set the text to the current headline, rotate the text in from the side, then rotate the text back out after a delay. </p> <p> In the <code>setHeadlines</code> function; if the headline is longer than the max we support (currently set to 34 letters) then chop it into pieces. If we were really smart we’d be careful about not breaking words, but I’ll leave that as an exercise to the reader. </p> <pre><code> function setHeadlines(headline,t1,t2) { var max = 34; if(headline.length > max) { t1.text(headline.substring(0,max)); t2.text(headline.substring(max)); } else { t1.text(headline); t2.text(''); } }</code></pre> <p> The <code>rotateIn</code> function calls <code>setHeadlines</code> with the next title, then animates the Y rotation axis from 220 degrees to 360 over two seconds (2000 milliseconds). It also triggers <code>rotateOut</code> when it’s done. </p> <pre><code> function rotateIn() { setHeadlines(titles.next(),line1,line2); textgroup.ry.anim().from(220).to(360).dur(2000).then(rotateOut).start(); }</code></pre> <p> A quick note on rotation. Amino is fully 3D so in theory you can rotate shapes in any direction, not just in the 2D plane. To keep things simple the <code>Group</code> object has three rotation properties: <code>rx</code>, <code>ry</code>, and <code>rz</code>. These each rotate <b>around</b> the x, y, and z axes. The x axis is horizontal and fixed to the top of the screen, so rotating around the x axis would flip the shape from top to bottom. The y axis is vertical and on the left side of the screen. Rotating around the y axis flips the shape left to right. If you want to do a rotation that looks like the standard 2D rotation, then you want to go around the Z axis with <code>rz</code>. Also note that all rotations are in <i>degrees</i>, not radians. </p> <p> The <code>rotateOut()</code> function rotates the text group back out from 0 to 140 over two seconds, then triggers <code>rotateIn</code> again. Since each function triggers the other they will continue to ping pong back and forth forever, pulling in a new headline each time. Notice the <code>delay()</code> call. This will make the animation wait five seconds before starting. </p> <pre><code> function rotateOut() { textgroup.ry.anim().delay(5000).from(0).to(140).dur(2000).then(rotateIn).start(); }</code></pre> <p> Finally we can start the whole shebang off back calling rotateIn the first time. </p> <pre><code> rotateIn();</code></pre> <p> What we have so far will work just fine but it’s a little boring because the background is pure black. Let’s add a few subtly moving rectangles in the background. </p> <p> First we will create the three rectangles. They are each fill the screen and are 50% translucent, in the colors red, green, and blue. </p> <pre><code> //three rects that fill the screen: red, green, blue. 50% translucent var rect1 = new amino.Rect().w(sw).h(sh).opacity(0.5).fill("#ff0000"); var rect2 = new amino.Rect().w(sw).h(sh).opacity(0.5).fill("#00ff00"); var rect3 = new amino.Rect().w(sw).h(sh).opacity(0.5).fill("#0000ff"); bg.add(rect1,rect2,rect3);</code></pre> <p> Now let’s move the two back rectangles off the left edge of the screen. </p> <pre><code> //animate the back two rects rect1.x(-1000); rect2.x(-1000);</code></pre> <p> Finally we can slide them from left to right and back. Notice that these animations set <code>loop</code> to -1 and <code>autoreverse</code> to 1. The loop count sets how many times the animation will run. Using <code>-1</code> makes it run forever. The autoreverse property makes the animation alternate direction each time. Rather than going from left to right and starting over at the left again, instead it will go left to right then right to left. Finally the second animation has a five second delay. This staggers the two animations so they will always be in different places. Since all three rectangles are translucent the colors will continually mix and change as the rectangles slide back and forth. </p> <pre><code> rect1.x.anim().from(-1000).to(1000).dur(5000) .loop(-1).autoreverse(true).start(); rect2.x.anim().from(-1000).to(1000).dur(3000) .loop(-1).autoreverse(true).delay(5000).start();</code></pre> <p> Here’s what it finally looks like. Of course a still picture can’t do justice to the real thing. </p> <p> <img src='https://www.dropbox.com/s/j198efaumm873kg/rssfeed.png?raw=1' alt='image'/> </p> <p> </p> <p> <img src='https://dl.dropbox.com/s/s9kkajq9axygafn/rssfeed2.png?raw=1' alt='image'/> </p> http://joshondesign.com/2014/08/19/amino3\nPhoto Slideshow in AminoThis is the second blog in a series about Amino, a Javascript OpenGL library for the Raspberry Pi. The first post is <a href='http://joshondesign.com/2014/08/08/aminorefactored'>here</a>. <p> This week we will build a digital photo frame. A Raspberry PI is perfect for this task because it plugs directly into the back of a flat screen TV through HDMI. Just give it power and network and you are ready to go. </p> <p> Last week I talked about the new Amino API built around properties. Several people commented that I didn’t say how to actually get and run Amino. Very good point! Let’s kick things off with an install-fest. These instructions assume you are running Raspbian, though pretty much any Linux distro should work. </p> <p> Amino is fundamentally a Node JS library so first you’ll need Node itself. Fortunately, installing Node is far easier than it used to be. In brief, update your system with <code>apt-get</code>, download and unzip Node from <code>nodejs.org</code>, and add <code>node</code> and <code>npm</code> to your path. Verify the installation with <code>npm —version</code>. I wrote full instructions <a href='http://joshondesign.com/2013/10/23/noderpi'>here</a> </p> <p> Amino uses some native code, so you’ll need <b>Node Gyp</b> and <b>GCC</b>. Verify GCC is installed with <code>gcc —version</code>. Install node-gyp with <code>npm install -g node-gyp</code>. </p> <p> Now we can checkout and compile Amino. You’ll also need Git installed if you don’t have it. </p> <pre><code>git clone git@github.com:joshmarinacci/aminogfx.git cd aminogfx node-gyp clean configure --OS=raspberrypi build npm install node build desktop export NODE_PATH=build/desktopnode tests/examples/simple.js</code></pre> <p> This will get the amino source, build the native parts, then build the Javascript parts. When you run <code>node tests/examples/simple.js</code> you should see this: </p> <p> <img src='https://dl.dropbox.com/s/7ls6p2z80wyrwlu/simple_circle.png' alt='image'/> </p> <p> </p> <p> </p> <p> Now let’s build a photo slideshow. The app will scan a directory for image, then loop through the photos on screen. It will slide the photos to the left using two ImageViews, one for the outgoing image and one for the incoming, then swap them. First we need to import the required modules. </p> <pre><code>var amino = require('amino.js'); var fs = require('fs'); var Group = require('amino').Group; var ImageView = require('amino').ImageView;</code></pre> <p> Technically you could call <code>amino.Group()</code> instead of importing <code>Group</code> separately, but it makes for less typing later on. </p> <p> Now let’s check that the user specified an input directory. If so, then we can get a list of images to load. </p> <pre><code>if(process.argv.length &lt; 3) { console.log("you must provide a directory to use"); return; } var dir = process.argv[2]; var filelist = fs.readdirSync(dir).map(function(file) { return dir+'/'+file; });</code></pre> <p> So far this is all straight forward Node stuff. Since we are going to loop through the photos over and over again we will need an index to increment through the array. When the index reaches the end it should wrap around to the beginning, and handle the case when new images are added to the array. Since this is a common operation I created a utility object with a single function: <code>next()</code>. Each time we call <code>next</code> it will return the next image, automatically wrapping around. </p> <pre><code>function CircularBuffer(arr) { this.arr = arr; this.index = -1; this.next = function() { this.index = (this.index+1)%this.arr.length; return this.arr[this.index]; } } //wrap files in a circular buffer var files = new CircularBuffer(filelist);</code></pre> <p> Now lets set up a scene in Amino. To make sure the threading is handled properly you must always pass a setup function to <code>amino.start()</code>. It will set up the graphics system then give you a reference to the <code>core</code> object and a <code>stage</code>, which is the window you can draw in. (Technically it’s the contents of the window, not the window itself). </p> <pre><code>amino.start(function(core, stage) { stage.setSize(800,600); var root = new Group(); stage.setRoot(root); var sw = stage.getW(); var sh = stage.getH(); //create two image views var iv1 = new ImageView().x(0); var iv2 = new ImageView().x(1000); //add to the scene root.add(iv1,iv2); … };</code></pre> <p> The setup function above sets the size of the stage and creates a Group to use as the root of the scene. Within the root it adds two image views, <code>iv1</code> and <code>iv2</code>. </p> <p> The images may not be the same size as the screen so we must scale them. However, we can only scale once we know how big the images will be. Furthermore, the image view will hold different images as we loop through them, so we really want to recalculate the scale every time a new image is set. To do this, we will watch for changes to the image property of the image view like this. </p> <pre><code> //auto scale them with this function function scaleImage(img,prop,obj) { var scale = Math.min(sw/img.w,sh/img.h); obj.sx(scale).sy(scale); } // call scaleImage whenever the image property changes iv1.image.watch(scaleImage); iv2.image.watch(scaleImage); //load the first two images iv1.src(files.next()); iv2.src(files.next());</code></pre> <p> Now that we have two images we can animate them. Sliding images to the left is as simple as animating their <code>x</code> property. This code will animate the x position of <code>iv1</code> over 3 seconds, starting at <code>0</code> and going to <code>-sw</code>. This will slide the image off the screen to the left. </p> <pre><code>iv1.x.anim().delay(1000).from(0).to(-sw).dur(3000).start();</code></pre> <p> To slide the next image onto the screen we do the same thing for iv2, </p> <pre><code>iv2.x.anim().delay(1000).from(sw).to(0).dur(3000)</code></pre> <p> However, once the animation is done we want to swap the images and move them back, so let’s add a <code>then(afterAnim)</code> function call. This will invoke <code>afterAnim</code> once the second animation is done. The final call in the chain is to the <code>start()</code> function. Until <code>start</code> is called nothing will actually be animated. </p> <pre><code> //animate out and in function swap() { iv1.x.anim().delay(1000).from(0).to(-sw).dur(3000).start(); iv2.x.anim().delay(1000).from(sw).to(0).dur(3000) .then(afterAnim).start(); } //kick off the loop swap();</code></pre> <p> The <code>afterAnim</code> function moves the ImageViews back to their original positions and moves the image from <code>iv2</code> to <code>iv1</code>. Since this happens between frames the viewer will never notice anything has changed. Finally it sets the source of <code>iv2</code> to the next image and calls the <code>swap()</code> function to loop again. </p> <pre><code> function afterAnim() { //swap images and move views back in place iv1.x(0); iv2.x(sw); iv1.image(iv2.image()); // load the next image iv2.src(files.next()); //recurse swap(); }</code></pre> <p> A note on something a bit subtle. The <code>src</code> of an image view is a string, either a url of file path, which refers to the image. The <code>image</code> property of an ImageView is the actual in memory image. When you set the <code>src</code> to a new value the ImageView will automatically load it, then set the <code>image</code> property. That’s why we added a watch function to the <code>iv1.image</code> not <code>iv1.src</code>. </p> <p> Now let’s run it, the last argument is the path to a directory containing some JPGs or PNGs. </p> <pre><code>node demos/slideshow/slideshow.js demos/slideshow/images</code></pre> <p> If everything goes well you should see something like this: </p> <p> <img src='https://dl.dropbox.com/s/ctarisvabzp98mt/amino_yosemite_slideshow.png' alt='image'/> </p> <p> By default, animations will use a cubic interpolator so the images will start moving slowly, speed up, then slow down again when they reach the end of the transition. This looks nicer than a straight linear interpolation. </p> <p> So that’s it. A nice smooth slideshow in about 80 lines of code. By removing comments and utility functions we could get it under 40, but this longer version is easier to read. </p> <p> Here is the final complete code. It is also in the git repo under demos/slideshow. </p> <pre><code>var amino = require('amino.js'); var fs = require('fs'); var Group = require('amino').Group; var ImageView = require('amino').ImageView; if(process.argv.length &lt; 3) { console.log("you must provide a directory to use"); return; } var dir = process.argv[2]; var filelist = fs.readdirSync(dir).map(function(file) { return dir+'/'+file; }); function CircularBuffer(arr) { this.arr = arr; this.index = -1; this.next = function() { this.index = (this.index+1)%this.arr.length; return this.arr[this.index]; } } //wrap files in a circular buffer var files = new CircularBuffer(filelist); amino.start(function(core, stage) { stage.setSize(800,600); var root = new Group(); stage.setRoot(root); var sw = stage.getW(); var sh = stage.getH(); //create two image views var iv1 = new ImageView().x(0); var iv2 = new ImageView().x(1000); //add to the scene root.add(iv1,iv2); //auto scale them function scaleImage(img,prop,obj) { var scale = Math.min(sw/img.w,sh/img.h); obj.sx(scale).sy(scale); } iv1.image.watch(scaleImage); iv2.image.watch(scaleImage); //load the first two images iv1.src(files.next()); iv2.src(files.next()); //animate out and in function swap() { iv1.x.anim().delay(1000).from(0).to(-sw).dur(3000).start(); iv2.x.anim().delay(1000).from(sw).to(0).dur(3000) .then(afterAnim).start(); } swap(); function afterAnim() { //swap images and move views back in place iv1.x(0); iv2.x(sw); iv1.image(iv2.image()); iv2.src(files.next()); //recurse swap(); } });</code></pre> <p> Thank you and stay tuned for more Amino examples on my blog. </p> <p> <a href='https://github.com/joshmarinacci/aminogfx'>Amino repo</a> </p> http://joshondesign.com/2014/08/10/aminoslideshow\nAmino: RefactoredI’ve been working on <a href='https://github.com/joshmarinacci/aminolang'>Amino</a>, my graphics library, for several years now. I’ve ported it from pures Java, to JavaScript, to a complex custom-language generator system (I was really into code-gen two years ago), and back to JS. It has accreted features and bloat. And yet, through all that time, even with blog posts and the <a href='http://goamino.org/'>goamino.org</a> website, I don’t think anyone but me has ever used it. I had accepted this fact and continued tweaking it to meet my personal needs; satisfied that I was creating something that lets me build other useful things. Until earlier this year. <p> </p> <h3 id="id99617">OSCON</h3> <p> In January I thought to submit a session to OSCON entitled <a href='http://www.oscon.com/oscon2014/public/schedule/detail/34535'>Data Dashboards with Amino, NodeJS, and the Raspberry Pi</a>. The concept was simple: Raspberry Pis are cheap but with a surprisingly powerful GPU. Flat screen TVs are also cheap. I can get a <a href='http://www.costco.com/Vizio-32%22-Class-720P-LED-HDTV-E320-B0.product.100089402.html'>32in model at Costco</a> for 200$. Combine them with a wall mount and you have a cheap data dashboard. Much to my shock the talk was accepted. </p> <p> The session at OSCON was very well attended, proving there is clearly interest in Amino, at least on the Raspberry Pi. The demos I was able to pull off for the talk show that Amino is powerful enough to really push the Pi. My final example was an over the top futuristic dashboard for 'Awesomonium Levels', clearly at home in every super villain’s lair. If Amino can pull this off then it’s found it’s niche. X windows and browsers are so slow on the Pi that people are willing to use something different. </p> <p> <img src='https://dl.dropboxusercontent.com/s/2woolscwfrlbigv/globe_super.png' alt='globe'/> </p> <p> </p> <h3 id="id35359">Refactoring</h3> <p> However, Amino still needs some work. While putting the demos together for my session a noticed how inefficient the API is. I’ve been working on Amino in various forms for at least 3 years, so the API patterns were set quite a while ago. The objects full of getters and setters clearly reflect my previous Java background. Not only have I improved my Javascript skills since then, I have read a lot about functional programming styles lately (book reports coming soon). This let me finally see ways to improve the API. </p> <p> Much like any other UI toolkit, the core of the Amino API has always been a tree of nodes. Architecturally there are actually two trees, the Javascript one you interact with and the native one that actually makes the OpenGL calls; however the native one is generally hidden away. </p> <p> Since I came from a Java background I started with an object full of properties accessed with getters and setters. While this works, the syntax is annoying. You have to type the extra get/set words and remember to camel case the property names. Is the font name set with setFontName or setFontname? Because the getter and setter functions were just functions there was no place to access the property as a single object. This means other property functions have to be controlled with a separate API. To animate a property you must refer to it indirectly with a string, like this: </p> <pre><code>var rect = new amino.ProtoRect().setX(5); var anim = core.createPropAnim(rect,’x’,0,100,1000);</code></pre> <p> Not only is the animation configured through a separate object (core) but you have to remember the exact order of the various parameters for starting and end values, duration, and the property name. Amino needs a more fluent API. </p> <p> </p> <h3 id="id381">Enter Super Properties</h3> <p> After playing with Javascript native getters and setters for a bit (which I’ve determined have no real use) I started looking at the JQuery API. A property can be represented by a single function which both gets and sets depending on the arguments. Since functions in Javascript are also objects, we can attach extra functionality to the function itself. Magic behavior like binding and animation. The property itself becomes the natural place to put this behavior. I call these super properties. Here’s what they look like. </p> <p> </p> <p> To get the x property of a rectangle </p> <pre><code>rect.x()</code></pre> <p> to set the x property of a rectangle: </p> <pre><code>rect.x(5);</code></pre> <p> the setter returns a reference to the parent object, so super properties are chain able: </p> <pre><code>rect.x(5).y(5).w(5);</code></pre> <p> This syntax is already more compact than the old one: </p> <pre><code>rect.setX(5).setY(5).setWidth(5);</code></pre> <p> The property accessor is also an object with it’s own set of listeners. If I want to know when a property changes I can <i>watch</i> it like this: </p> <pre><code>rect.x.watch(function(val) { console.log(“x changed to “+val); });</code></pre> <p> Notice that I am referring to the accessor as an object <b>without</b> the parenthesis. </p> <p> Now that we can watch for variable changes we can also bind them together. </p> <pre><code>rect.x.bindto(otherRect.x);</code></pre> <p> If we combine binding with a modifier function, then properties become very powerful. To make rect.x always be the value of otherRect.x plus 10: </p> <pre><code>rect.x.bindto(otherRect.x, function(val) { return val + 10; });</code></pre> <p> Modifier functions can be used to convert types as well. Let’s format a string based on a number: </p> <pre><code>label.text.bindto(rect.x, function(val) { return “The value is “ + val; });</code></pre> <p> Since Javascript is a functional language we can improve this syntax with some meta-functions. This example creates a reusable string formatter. </p> <pre><code>function formatter(str) { return function(val) { return str.replace(‘%’,val); } } label1.text.bindto(rect.x, formatter(‘the x value is %’)); label2.text.bindto(rect.y, formatter(‘the y value is %’));</code></pre> <p> Taking a page out of JQuery’s book, I added a find function to the Group object. It returns a selection with proxies the properties to the underlying objects. This lets me manipulate multiple objects at once. </p> <p> Suppose I have a group with ten rectangles. Each has a different position but they should all be the same size and color: </p> <pre><code>group.find(‘Rect’).w(20).h(30).fill(‘#00FF00’);</code></pre> <p> Soon Amino will support searching by CSS class and ID selectors. </p> <p> </p> <h3 id="id96808">Animation</h3> <p> Lets get back to animation for a second. The old syntax was like this: </p> <pre><code>var rect = new amino.ProtoRect().setX(5); var anim = core.createPropAnim(rect,’x’,0,100,1000);</code></pre> <p> Here is the new syntax: </p> <pre><code>var rect = new Rect().x(5); rect.x.anim().from(0).to(100).dur(1000).start();</code></pre> <p> We don’t need to pass in the object and property because the <code>anim</code> function is already attached to the property itself. Chaining the functions makes the syntax more natural. The <code>from</code> and <code>dur</code> functions are optional. If you don’t specifiy them the animation will start with the current value of the property (which is usually what you wanted anyway) and a default duration (1/4 sec). Without those it looks like: </p> <pre><code>rect.x.anim().to(100).start();</code></pre> <p> Using a start function makes the animation behavior more explicit. If you don’t call <code>start</code> then the animation doesn’t start. This lets you set up and save a reference to the animation to be used later. </p> <pre><code>var anim = rect.x.anim().from(-100).to(100).dur(1000).loop(5); //some time later anim.start();</code></pre> <p> Delayed start also lets us add more complex animation control in the future, like chained or parallel animations: </p> <pre><code>Anim.parallel([ rect.x.anim().to(1000), circle.radius.anim().to(50), group.y.anim().from(50).to(100) ]).start();</code></pre> <p> I’m really happy with the new syntax. Simple functions built on a common pattern of objects and super properties. Not only does this make a nicer syntax, but the implementation is cleaner as well. I was able to deleted about a third of Amino’s JavaScript code! That’s an all-round win! </p> <p> Since this changes Amino so much I’ve started a new repo for it. The old amino is still available at: </p> <p> <a href='https://github.com/joshmarinacci/aminolang'>https://github.com/joshmarinacci/aminolang</a> </p> <p> The new amino, the only one you should be using, is at: </p> <p> <a href='https://github.com/joshmarinacci/aminogfx'>https://github.com/joshmarinacci/aminogfx</a> </p> <p> </p> <p> That’s it for today. Next time I’ll show you how to build a full screen photo slideshow with the new animation API and a circular buffer. After that we’ll dig into 3D geometry and make a cool spinning globe. </p> http://joshondesign.com/2014/08/08/aminorefactored\nElectron 0.3 Released I’m happy to announce the release of Electron 0.3. While there are a few under the hood improvements, the big news is a <b>brand new user interface</b>. We’ve rewritten the UI <i>from scratch</i> using Angular JS. This will make Electron more stable and easier to improve in the future. <p> </p> <h3 id="id75785">New UI features:</h3> <p> </p> <ul><li>a proper file browser on the left, with collapsing folders</li> <li>collapsing resizable panels.</li> <li>New dialogs to search for boards and libraries</li> <li>new fonts (Source Sans Pro, Source Serif Pro, and Source Code Pro)</li> <li>proper multiple tabs for editing source files</li> </ul> <p> </p> <p> </p> <h3 id="id7301">Boards and Libs</h3> <p> The data repo has added support for </p> <p> </p> <ul><li>Adafruit Trinket & Gemma,</li> <li>Flora,</li> <li>timer libs</li> <li>Arduino Yun</li> <li>Esplora</li> <li>DigiSpark Tiny / Pro (buggy)</li> <li>Fio</li> </ul> <p> </p> <p> </p> <h3 id="id10467">Broken Stuff</h3> A few things that worked before are now broken, so be aware: <p> </p> <ul><li>serial console (filled with mockup text)</li> <li>docs viewer (filled with mockup text)</li> <li>'+'/'-' buttons for creating/deleting sketches</li> </ul> <p> </p> <h3 id="id56701">Thanks to contributors:</h3> <p> </p> <ul><li>Alan Holding</li> <li>Nick Oliver</li> <li>Walter Lapchynski</li> </ul> <p> The next release (in a few weeks, hopefully) will focus only on bug fixes and app-izing Electron to have only a single download (no git required). </p> <p> We need your help testing for the next release. <a href='https://github.com/joshmarinacci/ElectronIDE/issues'>Please file your kudos, bugs, and requests here</a>. </p> <p> Thanks, Josh </p> http://joshondesign.com/2014/08/06/electronv03\n60s Book Review: TinkerCad <p> <a href='http://www.tinkercad.com/'>TinkerCad</a> is a free web based CAD program. It runs entirely in the browser using <a href='http://en.wikipedia.org/wiki/WebGL'>WebGL</a>, so you’ll probably want to use it with Chrome (I think Safari may work in Yosemite+). TinkerCad is meant for novice CAD users. So novice that you can know absolutely nothing about CAD and be able to make something after five minutes of their built in learning quests (tutorials). Then you an save your creation to their cloud or download it for 3D printing. </p> <p> TinkerCad isn’t full featured. You can’t add chamfered edges for example, but you can combine shapes with CSG operations, stretch and rotate them, and add useful prefab shapes like letters and stars. There is even a scripting language for building programmatic objects. The UI challenge of building a CAD for newbies is daunting, yet somehow they did it. TinkerCad almost went out of business since it turns out novice users are also unlikely to pay for CAD applications. Fortunately AutoDesk bought them and have made TinkerCad their free entry level offering. </p> <p> But this is a book review, right? <a href='http://www.amazon.com/3D-Modeling-Printing-Tinkercad-Create/dp/0789754908'>3D Modeling and Printing with TinkerCad</a> is a new book by James Floyd Kelly. it walks you through the basics of navigation, creating shapes, merging and subtracting them, all the way to printing models and importing them into Minecraft. The book is very well written and easy to follow with lots of pictures. </p> <p> So should you buy it? That depends. TinkerCad’s own interactive tutorials are quite good. While I enjoyed the book I’d say 75% of it covers the same things you’ll learn in the tutorials. It really comes down to whether you are more comfortable learning on screen or by reading a paper book. If you learn by paper, then buy it. </p> <p> <a href='http://www.amazon.com/3D-Modeling-Printing-Tinkercad-Create/dp/0789754908'>3D Modeling and Printing with Tinkercad: Create and Print Your Own 3D Models, James Floyd Kelly</a> </p> <p> </p> http://joshondesign.com/2014/08/04/tinkercadreview\nElectron Updates <p> Now that OSCON is over I can get back to working on Electron. That means a new version is coming, and by far the biggest change will be a brand new user interface. I had posted an early preview <a href='http://joshondesign.com/p/apps/electron/ElectronIDE/public/nextgen.html'>here</a> but that's now completely out of date. You see, I discovered a new framework. </p> <p> Currently Electron is built from two main components. The backend end is NodeJS code. This is the part that actually compiles and uploads your Arduino code. The front end is HTML and JavaScript. This is the part you actually interact with: editor, debugging, clicking the compile button, choosing boards, etc. Currently the UI is written in plain HTML with Bootstrap and JQuery. Sadly, this form of development won't scale. JQuery is great for manipulating a few DOM objects but it just doesn't scale up to a full app. I had considered a few UI frameworks like JQuery UI but several people at OSCON mentioned Angular JS. When I got home I bought a book from O'Reilly and built a few prototypes. I'm so glad that I did. </p> <p> Angular isn't a set of widgets. It's a JavaScript modules framework with data binding. With Angular I can break Electron up into proper reusable, testable components. It also handles much of the data update boilerplate I previously wrote by hand. </p> <p> After two days I've completely rewritten the UI in Angular. Almost everything that worked before works in the new UI. The switch over went smoothly thanks to the backend being done entirely with REST requests. I can actually run both the old and new UIs at the same time. </p> <p> Here is a screenshot of what the new version looks like. </p> <p> <img src='https://dl.dropbox.com/s/a3dk0np4xgqdudj/electron_v3preview.png' alt='preview'/> </p> <p> Some time next week I should have v0.3 released. After that the focus will be entirely on integrating Atom-Shell so that you don't need the command line at all. You'll be able to just download a proper app binary like any other desktop program. </p> <p> Oh yeah, and we had a BOF at OSCON on Electron. I got lots of good feedback that will work it's way into the first post 1.0 release. </p> <p> And one more thing... </p> <p> If you live here in Eugene I'll be doing an Electron presentation at <a href='http://www.meetup.com/EUGLUG-Eugene-Unix-GNU-Linux-Users-Group/'>this week's Eugene Linux User's Group</a> . </p> <p> </p> http://joshondesign.com/2014/08/02/electron03\n60 Sec Book Review: Physics of the ImpossibleMichio Kaku, the science popularizer and theoretical physicist, is always a wonderful speaker. I’ve greatly enjoyed his TED talks. In <i>Physics of the Impossible</i> he takes on the many improbable technologies of science fiction to determine if they are in fact impossible. Surprisingly, few truly are. He divides technologies into three levels of impossible: likely today or in the next 20 years with existing science (ex: replicators), likely in the next hundred or so without violating any known laws of physics (shockingly, time travel is in this bunch), and the truly impossible without some new laws of physics. There are very few things in the last category. It’s an easy read and lots of fun. <p> Should you read it? <b>Yes!</b> </p> <p> <a href='http://www.amazon.com/Physics-Impossible-Scientific-Exploration-Teleportation/dp/0307278824'>Physics of the Impossible: A Scientific Exploration into the World of Phasers, Force Fields, Teleportation, and Time Travel, by Michio Kaku</a> </p> <p> </p> <p> <a href='http://thedailyshow.cc.com/videos/6zj4ki/michio-kaku'>Dr. Kaku on the Daily Show</a> </p> <p> </p> <p> </p> <p> </p> http://joshondesign.com/2014/08/02/kaku\nCommand Parser for Arduino<i>This is day zero of my Month Of Writing</i> <p> Controlling an Arduino project over a serial connection is one of the most common tasks you might want to do, and yet it's surprisingly hard to find a good library. I really don't like the official ones because they are limited and require too much setup. After much googling with Bing I found one called <b>CmdArduino</b> by Akiba at <a href='http://www.freaklabs.org'>Freaklabs</a>. </p> <p> CmdArduino does exactly what I want, minus a few tweaks. I emailed Akiba about it. Even though he had never done an update to the library in three years he responded right away. I asked if I could take over the lib and he said yes! So I'm now the official maintainer for CmdArduino. For my first release I've added Stream support so it will work with more than just the regular Serial port; very important for working with alternative streams like Bluetooth LE modules. </p> <p> </p> <p> CmdArduino is super easy to use. Create your command functions with a signature like: </p> <pre><code>void left(int arg_cnt, char **args)</code></pre> <p> </p> <p> Then register it like this: </p> <pre><code>cmdInit(&MyStream); cmdAdd('left',left);</code></pre> <p> Now the <code>left</code> function will be called whenever you type 'left' into the other end of the stream. If you add arguments after the command they will show up in the <code>args</code> array. At OSCON I build a robot controlled by a chat app on my phone over BLE. When I typed in <code>spin 3000</code> the robot's spin function would be called with the value 3000 for the duration. The code looks like this: </p> <pre><code>void spin(int arg_cnt, char **args) { int time = 1000; if(arg_cnt > 0) { time = parseInt(args[0]); } LeftMotor->run(BACKWARD); RightMotor->run(FORWARD); delay(time); RightMotor->run(RELEASE); LeftMotor->run(RELEASE); } void setup() { Serial.begin(9600); cmdInit(&ble); cmdAdd('spin',spin); }</code></pre> <p> </p> <p> It's that easy. The code is up in my github repo now. </p> <p> <a href='https://github.com/joshmarinacci/CmdArduino'>https://github.com/joshmarinacci/CmdArduino</a> </p> <p> Thanks Akiba! </p> http://joshondesign.com/2014/07/31/slug\nAmino at OSCONI'm finally back from OSCON, and what a trip it was. Friend of the show <a href='https://twitter.com/wxl'>wxl</a> came with me to assist and experience the awesomeness that is <a href='http://www.oscon.com/oscon2014'>OSCON</a>. Over the next few days I'll be posting about the three sessions we taught and many, many sessions we attended. A splendid time is guaranteed for all. To kick things off, here is the code from my Amino talk. <p> Amino is my JavaScript graphics library I've been working on for a few years. Last year I started a big refactor to make it work nicely on the Raspberry Pi. Once we get X windows out of the way we can talk to the Pi's GPU using OpenGL ES. This makes things which were previously impossible, like 3d spinning globes, trivial on the Raspberry Pi. </p> <p> For the talk I started by explaining how Node and Amino work on the Raspberry Pi, then shows some simple code to make a photo slideshow. (in this case, Beatles album covers). </p> <p> <img src='https://dl.dropbox.com/s/f5mv2f1386ah2jy/beatles.png' alt='beatles'/> </p> <p> Next we showed a 3D rotating text RSS headline viewer. </p> <p> <img src='https://dl.dropbox.com/s/ylwgkus5hf6edvn/rotating_text.png' alt='rss viewer'/> </p> <p> And finally, using the same GeoJSON code from the D3/Canvas workshop, a proper rotating 3D globe. </p> <p> <img src='https://dl.dropbox.com/s/80hdol2arctlcjs/globe.png' alt='globe'/> </p> <p> Hmm... Did you ever notice that the earth with just countries and no water looks a lot like the half constructed Death Start in Return of the Jedi? </p> <p> Of course, my dream has always been to create those cool crazy computer interfaces you see in sci-fi movies. You know, the ones with translucent graphs full of nonsense data and spinning globes. And even better, we made one run on the Raspberry Pi. Now you can always know the critical Awesomonium levels of your mining colony. </p> <p> <img src='https://dl.dropbox.com/s/2woolscwfrlbigv/globe_super.png' alt='awesomonium'/> </p> <p> </p> <p> <a href='https://www.dropbox.com/s/1sltp5h047ggvze/amino-talk.zip'>Source for the demos</a> on DropBox. </p>http://joshondesign.com/2014/07/28/amino\nElectron 0.2 Released<p>I’m happy to announce Electron 0.2. We’ve done a lot of work to improve the compiler and library tools. The biggest news is Windows and Linux support. Also, you don’t need to pre-install the regular Arduino IDE anymore. Electron will auto-download it’s own copy of the required toolchain. Here’s the details: </p> <ul><li> Initial Windows and Linux support!</li> <li> You don’t need to modify settings.js anymore. Electron will auto detect your Arduino/Sketchbook dir.</li> <li> You don’t need the regular Arduino IDE installed anymore. The appropriate toolchain will be auto-downloaded for you the first time you compile something.</li> <li> User installed libs work now. Note that user installed libs take a priority over libs installed by the IDE.</li> <li> the serial port will be automatically closed and reopened when you upload a sketch. If this crashes your computer please let me know. I might need to increase the timeouts.</li> <li> Preliminary support for auto-detecting which board you are using by the USB VID/PID. Special thanks to PixnBits for that.</li> <li> Set the serial port speed</li> <li> Sketch rename works now</li> <li> download progress is shown in the browser (partially)</li> <li> tons of under the hood fixes</li> <li> auto scroll the console</li> </ul> <p>The <code>arduino-data</code> project was also updated with new boards an libraries: </p> <ul><li> New boards: TinyLily and Gamebuino</li> <li> More networking libs: CmdMessenger, OneWire, PS2Keyboard, SerialControl, SSoftware2Mobile, Webduino</li> <li> More specs on various boards</li> <li> The rest of the built in libraries: Ethernet, Firmata, GSM, LiquidCrystal, SD, SoftwareSerial, TFT, WiFi</li> <li> Support library sub-dependencies</li> </ul> <p>Thanks to contributors: </p> <ul><li> Dan O’Donovan / Dan-Emutex</li> <li> Nick Oliver / PixnBits</li> <li> Sean McCarthy / seandmcarthy</li> <li> trosper</li> </ul> <p>You can get the latest code on the <a href="https://github.com/joshmarinacci/ElectronIDE">github project</a>.Please test this with every board and OS you have. File bugs in the <a href="https://github.com/joshmarinacci/ElectronIDE/issues">issue tracker</a>.</p> <p>I’ve registered a domain for Electron, electron.pw, though don’t bother going there yet. I haven’t built the website. If anyone is a talented webdev who’d like to help with that job, please contact me. </p> <p>I’ve you’d a sneak peek of the next version of Electron, check out <a href='http://joshondesign.com/p/apps/electron/ElectronIDE/public/nextgen.html'>the mockup here</a>. It’s got a new library picker, a proper tree based file picker, and resizable panes. It still needs a lot of work before it can go live, but this will give you an idea of where we are going. </p> <p>Thank you, and keep on testing. </p>http://joshondesign.com/2014/07/04/electronv02