<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Multigesture.net</title>
        <description>A multitouch and HCI research blog</description>
        <link>https://multigesture.net//</link>
        <atom:link href="https://multigesture.net//feed.xml" rel="self" type="application/rss+xml"/>
        <pubDate>Mon, 24 Mar 2025 20:54:30 +0000</pubDate>
        <lastBuildDate>Mon, 24 Mar 2025 20:54:30 +0000</lastBuildDate>
        <generator>Jekyll v3.10.0</generator>
        
            <item>
                <title>A Deepdive Debugging WebP Image Support on Android</title>
                <description>&lt;p&gt;Whether it’s the app’s stability, a smoother user experience or better app performance (e.g. reduced loading times), we’re always looking for ways to improve our app at &lt;a href=&quot;https://www.whatnot.com/&quot;&gt;Whatnot&lt;/a&gt;. As an Android engineer on the Discovery team, I was tasked in late ’23 to review our feed-driven surfaces. This post focuses on &lt;strong&gt;auditing the network calls&lt;/strong&gt; the app was making as well as looking at the &lt;strong&gt;bandwidth usage&lt;/strong&gt; of the Android app. For a livestream shopping app where latency and performance sit at the core of our experience, this investment led to better app and scroll performance for our Android Whatnot users, which is especially important as Whatnot continues to grow internationally where there are many Android users.&lt;/p&gt;

&lt;h1 id=&quot;starting-point&quot;&gt;Starting point&lt;/h1&gt;

&lt;p&gt;Android Studio comes with an inbuilt Network traffic &lt;a href=&quot;https://developer.android.com/studio/debug/network-profiler&quot;&gt;inspector&lt;/a&gt; that allows you to review your network calls. For more granular information, we prefer to use a tool like &lt;a href=&quot;https://proxyman.io/&quot;&gt;Proxyman&lt;/a&gt; to capture and inspect network traffic with ease. Especially being able to filter out specific endpoints or inspect network requests originating from the third-party SDKs in your app.&lt;/p&gt;

&lt;p&gt;Besides slimming down your network requests (e.g. request fewer fields in your API calls), the other thing that we can do is to ensure that we only request images that are appropriately sized for mobile devices.&lt;/p&gt;

&lt;p&gt;The JPG format has been the de facto standard for the web for a while now and it is no surprise that we have been using this on Android as well. As new image formats were developed (e.g. WebP, HEIF, AVIF) we had options for alternative more efficient image formats. On the web, WebP is slowly gaining popularity and is supported by all major modern &lt;a href=&quot;https://caniuse.com/webp&quot;&gt;browsers&lt;/a&gt;. The main benefit of migrating from JPG to WebP is the reduction of the image file size while maintaining a reasonable picture quality.&lt;/p&gt;

&lt;p&gt;With the help of Proxyman, we did a simple test. For the same show, we requested the show image but in different file formats: JPG, PNG and WebP.&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2024/03/show-jpg.webp&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2024/03/show-png.webp&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2024/03/show-webp.webp&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
  &lt;em&gt;jpg (68.1 KB) | png (877 KB) 😂 | webp (45.1 KB)&lt;/em&gt;
&lt;/div&gt;

&lt;p&gt;On average, we measured a reduction of ~34% when using WebP which seems to be on par with the WebP Compression &lt;a href=&quot;https://developers.google.com/speed/webp/docs/webp_study&quot;&gt;Study&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A smaller file size, means faster image loading times, a more responsive app and hopefully happier users.&lt;/p&gt;

&lt;h1 id=&quot;the-importance-of-internal-dogfooding&quot;&gt;The importance of internal dogfooding&lt;/h1&gt;

&lt;p&gt;Regularly using our own products internally helps us catch bugs early. Initially, when we released the changes internally, things seemed to be ok until one of our community moderators noticed that something was wrong with some of his listings. They were showing up correctly on the profile shop on his iPhone, but not on his Android device. On the Android app, the WebP images were being displayed sideways. Luckily this problem was found early and we were able to revert the change so it wouldn’t impact our users.&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2024/03/dogfood.webp&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h1 id=&quot;finding-the-culprit&quot;&gt;Finding the culprit&lt;/h1&gt;

&lt;p&gt;With all the benefits of WebP, it would be a shame not to be able to use it on Android.&lt;/p&gt;

&lt;p&gt;Not knowing what could be the reason for the wrong image orientation, the first step was to see if we could find some hints by checking the image data.&lt;/p&gt;

&lt;p&gt;Similar to the JPG image format, WebP images can also contain an Exchangeable Image File Format (&lt;a href=&quot;https://www.adobe.com/creativecloud/file-types/image/raster/exif-file.html&quot;&gt;EXIF&lt;/a&gt;) section that stores information about the image such as creation date, capturing device, image size, image rotation, color profiles, GPS locations, etc.&lt;/p&gt;

&lt;p&gt;As the images were displayed correctly on iOS it got us wondering if our image server was malforming the images during the conversion process to WebP or if the image library we are using on Android, &lt;a href=&quot;https://coil-kt.github.io/coil/&quot;&gt;Coil&lt;/a&gt;, had a bug in its implementation.&lt;/p&gt;

&lt;h1 id=&quot;inspecting-the-exif-data&quot;&gt;Inspecting the EXIF data&lt;/h1&gt;

&lt;p&gt;There are plenty of tools we can use to review the EXIF data of an image, two popular ones are &lt;a href=&quot;https://exiv2.org/&quot;&gt;Exiv2&lt;/a&gt; and &lt;a href=&quot;https://exiftool.org/&quot;&gt;ExifTool&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The first thing we did was to create some test material to replicate the problem our community moderator was seeing. We used an iPhone to take photos in 4 different orientations. By default these images were captured as JPGs and were uploaded to our image server. Next, we requested a WebP conversion via our image service and saved them locally.&lt;/p&gt;

&lt;p&gt;This allowed us to have 4 original images and 4 converted images that we could inspect. Using the ExifTool on both sets of files resulted in this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;File Name : case1-portait.jpg
Orientation : Rotate 90 CW

File Name : case1-portait.webp
Orientation : Rotate 90 CW

File Name : case2-landscape-turned-left.jpg
Orientation : Horizontal (normal)

File Name : case2-landscape-turned-left.webp
Orientation : Horizontal (normal)

File Name : case3-upside-down-portrait.jpg
Orientation : Rotate 270 CW

File Name : case3-upside-down-portrait.webp
Orientation : Rotate 270 CW

File Name : case4-landscape-turned-right.jpg
Orientation : Rotate 180

File Name : case4-landscape-turned-right.webp
Orientation : Rotate 180
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Looking at the results meant that the original image (JPG) contained proper orientation information and that the converted image (WebP) also contained orientation information.&lt;/p&gt;

&lt;p&gt;As a sanity check, we tried to open up the WebP files from the image service on Safari, and MacOS’s Finder which both displayed the image correctly. Chrome, Firefox and our app (using Coil) all seemed to fail which was very suspicious.&lt;/p&gt;

&lt;h1 id=&quot;diving-deeper-into-coil&quot;&gt;Diving deeper into Coil&lt;/h1&gt;

&lt;p&gt;As previously mentioned, we use a 3rd party image library called Coil to handle all our image loading in the app. So the next step would be to review if there is an issue with the library itself. Fortunately, Coil is open source so we have easy access to the code. Placing many breakpoints in the code and stepping through the image loader functions revealed that the orientation reported by Coil was off for some files.&lt;/p&gt;

&lt;p&gt;While the correct orientation was reported for JPG files, it failed to show any orientation information for our WebP files. Very odd, could the problem be somewhere else?&lt;/p&gt;

&lt;h1 id=&quot;the-androidx-exifinterface&quot;&gt;The AndroidX Exifinterface&lt;/h1&gt;

&lt;p&gt;While Coil helps you load images into your Composables/Views, it relies on the &lt;a href=&quot;https://developer.android.com/jetpack/androidx/releases/exifinterface&quot;&gt;AndroidX Exifinterface&lt;/a&gt; to read the EXIF data. Like Android, this is open source so that anyone can download and review (or fix) the source code.&lt;/p&gt;

&lt;p&gt;To make debugging easier, we created a &lt;a href=&quot;https://github.com/falcon4ever/WebPExifTestApp&quot;&gt;test application&lt;/a&gt; that would directly interface with the ExifInterface.&lt;/p&gt;

&lt;p&gt;One thing we noticed while looking at &lt;a href=&quot;https://github.com/androidx/androidx/tree/androidx-main/exifinterface&quot;&gt;the source code&lt;/a&gt; of the ExifInterface was that Google did cover a test case with a WebP image containing EXIF data. Why did that one work?&lt;/p&gt;

&lt;h1 id=&quot;lets-get-low-level&quot;&gt;Let’s get low level&lt;/h1&gt;

&lt;p&gt;At this point, we know that something is up between the Google WebP file and our own. Before we start inspecting the files, it’s a good idea to look up the official specifications of the image data container format. In the case of WebP, Google has published them &lt;a href=&quot;https://developers.google.com/speed/webp/docs/riff_container&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since we’re dealing with binary files, we won’t be able to use a text editor. Instead, we need something more advanced such as a hex editor.&lt;/p&gt;

&lt;p&gt;A hex editor allows you to inspect binaries in hexadecimal as well as text. On macOS, we can use a free tool called &lt;a href=&quot;http://hexfiend.com/&quot;&gt;Hex Fiend&lt;/a&gt; to open the two files.&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2024/03/google-exif-hexdump.webp&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2024/03/laurence-exif-hexdump.webp&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
  &lt;em&gt;Google’s WebP | Our WebP&lt;/em&gt;
&lt;/div&gt;

&lt;p&gt;Hmm, wait a moment, the EXIF structure looks a bit different between the two files. Let’s take a look at what the EXIF structure is supposed to look like in the &lt;a href=&quot;https://developers.google.com/speed/webp/docs/riff_container#metadata&quot;&gt;specs&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2024/03/header.webp&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;There should be an EXIF chunk header and a payload with the metadata. In both cases, we can see that the “EXIF” marker (in plain text) is present.&lt;/p&gt;

&lt;p&gt;The Exif metadata section should start with a so-called TIFF header. This header contains information about the byte order (&lt;a href=&quot;https://en.wikipedia.org/wiki/Endianness&quot;&gt;Endianness&lt;/a&gt;) of the payload. The first two bytes are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x49 0x49&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;II&lt;/code&gt; for Intel) if the byte order is little-endian or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x4D 0x4D&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MM&lt;/code&gt; for Motorola) for big-endian. The following two bytes are magic bytes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x00 0x2A&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;42&lt;/code&gt; 😉).&lt;/p&gt;

&lt;p&gt;Going back to our files we can see that the file generated by our image service contains an additional section that looks like this: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x45 0x78 0x69 0x66 0x00 0x00&lt;/code&gt; (“&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Exif\0\0&lt;/code&gt;”) before the TIFF header but why?&lt;/p&gt;

&lt;h1 id=&quot;the-exif-app1-section&quot;&gt;The EXIF APP1 Section&lt;/h1&gt;

&lt;p&gt;Checking on Google, it appears that our WebP files include an additional APP1 marker — uhm, isn’t this supposed to be standardized?&lt;/p&gt;

&lt;p&gt;Reviewing the EXIF standards by the Camera &amp;amp; Imaging Products Association (&lt;a href=&quot;https://www.cipa.jp/std/documents/e/DC-008-2010_E.pdf&quot;&gt;CIPA&lt;/a&gt;), it becomes clear that the APP1 is a JPG-specific marker that precedes the EXIF data (and is not considered part of the EXIF data payload).&lt;/p&gt;

&lt;p&gt;It’s important to note that &lt;a href=&quot;https://developers.google.com/speed/webp/docs/riff_container&quot;&gt;the official WebP specifications&lt;/a&gt; do not mention the APP1 marker at all, meaning WebP files should have never contained this APP1 marker in the first place.&lt;/p&gt;

&lt;p&gt;It’s very possible that the bug originates from image processing libraries (and that affects any frameworks relying on them), for example:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ImageMagick/ImageMagick/issues/3140&quot;&gt;https://github.com/ImageMagick/ImageMagick/issues/3140&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/libexif/libexif/issues/58&quot;&gt;https://github.com/libexif/libexif/issues/58&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This confirms that our image service is copying EXIF data directly from the original JPG file into the newly created WebP files.&lt;/p&gt;

&lt;h1 id=&quot;images-in-the-wild&quot;&gt;Images in the wild&lt;/h1&gt;

&lt;p&gt;So here we are, there are images out there because some image libraries didn’t completely adhere to the specifications and malformed WebP files that are now floating around the internet.&lt;/p&gt;

&lt;p&gt;Our best guess is that Safari, MacOS’s Finder, ExifTool and Exiv2 all use a relaxed EXIF metadata reader while Firefox, Chrome and the (AndroidX) ExifInterface are more strict.&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2024/03/this-side-up.webp&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h1 id=&quot;fixing-the-problem&quot;&gt;Fixing the problem&lt;/h1&gt;

&lt;p&gt;Going back to the ExifInterface source code we were able to track down the problem. It was failing to read the TIFF header and that resulted in not reading any of the EXIF data.&lt;/p&gt;

&lt;p&gt;Knowing this, we created a patch that would scan the first 6 bytes of the payload. If the 6 bytes match the JPG EXIF APP1 marker, we adjust the offset and skip the number of bytes and the length of the marker before processing the rest of the data.&lt;/p&gt;

&lt;p&gt;To validate the changes we updated the test application&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2024/03/google-exif.webp&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2024/03/laurence-exif.webp&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
  &lt;em&gt;Unpatched ExifInterface | Patched ExifInterface&lt;/em&gt;
&lt;/div&gt;

&lt;p&gt;Success!&lt;/p&gt;

&lt;p&gt;We provided the patch to Google which was merged into the codebase at &lt;a href=&quot;https://android-review.googlesource.com/c/platform/frameworks/support/+/2889627&quot;&gt;https://android-review.googlesource.com/c/platform/frameworks/support/+/2889627&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;whats-next&quot;&gt;What’s next&lt;/h1&gt;

&lt;p&gt;It’s rare to stumble upon a bug this low level, but it’s always helpful to know your debugging tool options. While the debugger in Android Studio is very advanced and should cover most of your day-to-day app development needs, external tools like Proxyman and Hex Editors can make your life much easier when it’s time to debug a problem.&lt;/p&gt;

&lt;p&gt;The complicated part here is that the bug is likely caused by an external image generation framework (seemingly harmless) but that didn’t surface until a more strict EXIF library was trying to read the data.&lt;/p&gt;

&lt;p&gt;Now that the AndroidX ExifInterface is patched, libraries like Coil will also be able to benefit from this change.&lt;/p&gt;

&lt;p&gt;Since we have full control of our image service, we also decided to circumvent the issue on the backend by reading EXIF data from the JPG file and applying the rotation on the requested image. The benefit of this approach is that it will now work out of the box on Android, Chrome and Firefox plus it allows us to strip away all EXIF information for privacy reasons.&lt;/p&gt;

&lt;p&gt;&lt;sub&gt;This article was previous posted on the &lt;a href=&quot;https://medium.com/whatnot-engineering/a-deepdive-debugging-webp-image-support-on-android-54fdbd8080d2&quot;&gt;Whatnot Engineering blog&lt;/a&gt;&lt;/sub&gt;&lt;/p&gt;
</description>
                <pubDate>Wed, 06 Mar 2024 11:00:00 +0000</pubDate>
                <link>https://multigesture.net//2024/06/03/a-deepdive-debugging-webp-image-support-on-android/</link>
                <guid isPermaLink="true">https://multigesture.net//2024/06/03/a-deepdive-debugging-webp-image-support-on-android/</guid>
                
                
                <category>Android</category>
                
                <category>Featured</category>
                
            </item>
        
            <item>
                <title>My mobile journey</title>
                <description>&lt;p&gt;If you are a mobile developer and haven’t read &lt;a href=&quot;https://twitter.com/chethaase&quot;&gt;Chet Haase’s&lt;/a&gt; latest book “&lt;a href=&quot;https://www.amazon.com/Androids-Built-Android-Operating-System/dp/1737354829&quot;&gt;Androids: The team that built the Android operating system&lt;/a&gt;” go read it now! It’s a delightful read and a wonderful trip into Android’s history!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/09/IMG_7539.jpeg&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;Androids&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The team that created Android didn’t just create a new mobile OS they also created a new career path for software engineers like me. I’ve been coding for Android since November 2008, which means almost 13 years! The projects that I’ve worked on have been very… diverse.&lt;/p&gt;

&lt;p&gt;When the team announced their Android device, I wasn’t living in the US (yet) and they weren’t selling it in the Netherlands yet. I was intrigued by what it was, a smartphone or really a portable tiny computer. Fortunately, for work at that time, I was going to be in Austin, TX in Nov 2008 for &lt;a href=&quot;/2008/11/19/interactive-networks-at-sc08/&quot;&gt;SuperComputing 2008 to demo a multi-touch device&lt;/a&gt;. After the conference was over, I went to a T-Mobile store and tried to purchase a G1. Back then they didn’t like it when you would try to just buy the device without service, but with a bit of patience they eventually sold one to me.&lt;/p&gt;

&lt;p&gt;The first app that I wrote wasn’t going to be “Hello World”, nah, I needed a bigger challenge so I tried porting a Chip 8 emulator that I had written for Windows sometime earlier. When I ported it to Java using Eclipse (yep before Android Studio was a thing), the first game I tried was Space Invaders. I was so excited that the code ran and I was able to play it with the hardware keyboard!&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/09/IMG_0151.jpg&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/09/IMG_0152.jpg&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
  &lt;em&gt;Running Space Invaders (via emulation) on my G1&lt;/em&gt;
&lt;/div&gt;

&lt;p&gt;At that time I was still active on &lt;a href=&quot;http://www.efnet.org&quot;&gt;EFnet&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Freenode&quot;&gt;Freenode&lt;/a&gt; chat servers, I thought it would be cool to have an IRC client to check in every now and then from my phone. That’s when I started to work on &lt;a href=&quot;/2008/12/22/firc-android-chat-client-released/&quot;&gt;fIRC&lt;/a&gt; which was released just before Christmas of 2008. I never expected so many people would download and use it. By default it would drop users in &lt;strong&gt;#android-chat&lt;/strong&gt; on Freenode which became very popular and often time had hilarious chatter going on.&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/09/IMG_0160.jpg&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/09/IMG_0156.jpg&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
  &lt;em&gt;Running fIRC and mIRC side by side&lt;/em&gt;
&lt;/div&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/09/device_chat.png&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2012/02/fircdownloads.jpg&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;The old version started with great ratings and high number of downloads… until it didn’t work so well on newer Android devices as I had a lot of layout things hardcoded for landscape use&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Funny enough, fIRC was also the reason I got in touch with, &lt;a href=&quot;https://twitter.com/sanmehat&quot;&gt;San Mehat&lt;/a&gt;, one of the Android engineers who used to idle in the chatroom too (I think most Android engineers were on #android on Freenode back then). As fIRC was gaining traction, at some point there was so much talk in different languages going on that it became hard to follow any conversations. At one point he yelled “WILL YOU MORONS SPEAK ENGLISH?” and that’s how a new IRC topic was born.&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/09/screenshot4.jpeg&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;In the spring of 2009, I was still doing research work on multi-touch tech and was invited to come to the &lt;a href=&quot;/2009/07/07/interactive-displays-2009/&quot;&gt;Interactive Displays Conference in San Jose&lt;/a&gt;. As I had never been in the area before (and it was my first trip to the US by myself), I was asking for some ideas on IRC in #android-chat on things to do in the SF area (as I knew a bunch of them where SF locals). San saw the message and said that we should meet up! We actually did end up meeting in person… (what was I thinking? meeting up with a stranger from the internet??). San is a great guy, even though I was just starting out as a software developer, we had a great chat and geeked out a bit over the G1. I still remember he offered me to come to the Google Mountain View campus but unfortunately I was there only for about a week and the schedule didn’t allow for it. I still regret that.&lt;/p&gt;

&lt;p&gt;Late 2011 I started freelancing via &lt;a href=&quot;https://epicwindmill.com/&quot;&gt;Epic Windmill&lt;/a&gt; and one of my friends (&lt;a href=&quot;https://www.sethsandler.com/&quot;&gt;Seth Sandler&lt;/a&gt;) asked me if I could help porting over one of his successful iOS apps to Android. I was up for the challenge and it was the first time for me to be exposed to the complicated side of Android development. &lt;a href=&quot;https://www.nodebeat.com&quot;&gt;NodeBeat&lt;/a&gt; was written in C++ using &lt;a href=&quot;https://openframeworks.cc&quot;&gt;openFrameworks&lt;/a&gt;. Porting meant that I had to create a native Android UI as well as getting the ‘cross-platform’ common code to work via JNI (some &lt;a href=&quot;/2011/11/19/nodebeat-openframeworks-and-android/&quot;&gt;tech details here&lt;/a&gt;). Fortunately things worked out well and we released NodeBeat in October of 2011.&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2011/11/P20111011000238.png&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;While Android was gaining traction, BlackBerry was trying to convince Android developers to make BB10 apps too. Initially I &lt;a href=&quot;/2012/02/22/rewriting-and-porting-firc/&quot;&gt;ported over my IRC chat app&lt;/a&gt; for a free device and later on I wrote an &lt;a href=&quot;/2012/04/27/playbook-add-on-ofxqnx/&quot;&gt;openFrameworks add-on (ofxQNX)&lt;/a&gt; that would allow apps build with that to run on the BlackBerry PlayBook (tablet) and BB10 devices. It also helped me port over &lt;a href=&quot;https://epicwindmill.com/2012/04/28/nodebeat-for-blackberry-playbook-now-available/&quot;&gt;NodeBeat to BB10&lt;/a&gt; which got featured on the BlackBerry blog (yay!)!&lt;/p&gt;

&lt;p&gt;Sometime in 2012 because of my work on NodeBeat, I was also introduced to Dan Comerchero who needed some help for an Android port of &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.quiztones.quiztones&amp;amp;hl=en_US&amp;amp;gl=US&quot;&gt;Quiztones&lt;/a&gt;, an ear training for EQ app. I don’t remember it being too hard other than the issue where the audio files had to be decompressed WAVs else there would be a playback lag somehow. I guess back then decoding audio from ogg/mp3 wasn’t as smooth.&lt;/p&gt;

&lt;p&gt;The biggest challenge was yet to come though… via Twitter in late 2012, &lt;a href=&quot;https://twitter.com/terrycavanagh&quot;&gt;Terry Cavanagh&lt;/a&gt; was asking around for experienced Android developers and was looking to have his game Super Hexagon ported over to Android. Initially I was contracted to do the Android port but later also worked on the BB10 version and the &lt;a href=&quot;https://en.wikipedia.org/wiki/Ouya&quot;&gt;Ouya game console&lt;/a&gt; port.&lt;/p&gt;

&lt;p&gt;I remember that I was pretty much done early January 2013 after a few weeks of intense coding and we (me and Terry) were reviewing the game and Terry noticed that something was off on the Nexus 7 (It ran fine on my Nexus One). It seemed like the game was &lt;a href=&quot;http://distractionware.com/blog/2013/01/the-hold-up/&quot;&gt;less responsive on that particular device&lt;/a&gt; which for an intense game like Super Hexagon matters a lot. Unsure what could be the cause I reached out to &lt;a href=&quot;https://twitter.com/romainguy&quot;&gt;Romain Guy&lt;/a&gt; on IRC (I wasn’t sure if he was going to respond but I’m glad he did!) I think I asked him because I had seen some other low level graphics related work from him. He put me in touch with Jeff Brown and fortunately he figured out what the cause was. He pointed out that in openFrameworks the physics and render loops were out of sync and recommended us to use the Choreographer to make the game run on Android Jelly Bean devices. The game should still be available from: &lt;a href=&quot;https://superhexagon.com/&quot;&gt;https://superhexagon.com/&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/09/Screen-Shot-2021-09-25-at-2.15.38-PM.png&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
  &lt;em&gt;Jeff Brown excited about the game&lt;/em&gt;
&lt;/div&gt;

&lt;p&gt;I’m grateful that the Android team was kind enough to help out, as I’m sure they were all swamped with work for the next Android release.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/09/2014-04-13-20.11.38.jpg&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;The Ouya port on a 720p TV…&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/09/IMG_3706.jpg&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;Running on the Nexus One, BlackBerry PlayBook, Dev Alpha B device (which would become the Z10)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/09/Screen-Shot-2021-09-25-at-2.23.24-PM.png&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;Running on a square screen, Dev Alpha C device (which would become the Q10)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After the different ports for Super Hexagon, I continued writing some apps for BB10. It was basically like the Android early days experience, not a lot of apps where out there so if you were the first, it was easier to become successful. I wrote a utility app SMS Backup for BB10 which allowed you to import/export SMS. It became a success and received the Built for BlackBerry badge that boosted the sales by a lot.&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/09/twitter-682x1024-1.jpeg&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Early 2014 I was contracted by a startup that had technology that would allow you to run Android apps on non-Android platforms such as Tizen. For about 9 months I worked on their internal test tool as well as rewriting their own Android distribution app, the AppMall. It was a great learning experience with many challenges. At some point I had to make the app work on devices like the Pine Neptune which had a tiny screen (320×240). Unfortunately, the company wasn’t going to make it and I had to look for a new job.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/09/DSCF4287-s.jpeg&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;The AppMall&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/09/Screenshot-2014-09-05-23.56.41.png&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
  &lt;em&gt;The Neptune device had such a tiny screen but I made it work&lt;/em&gt;
&lt;/div&gt;

&lt;p&gt;In 2014 I joined &lt;a href=&quot;https://www.wanderu.com/&quot;&gt;Wanderu&lt;/a&gt; and helped creating a successful &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.wanderu.wanderu&quot;&gt;ground transportation travel app&lt;/a&gt; from scratch (for iOS and Android) that is loved by many.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/09/Screen-Shot-2021-09-25-at-2.35.46-PM.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/09/Screen-Shot-2021-09-25-at-2.36.19-PM.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I’m currently (joined late 2022) an Android engineer at &lt;a href=&quot;https://www.whatnot.com/&quot;&gt;Whatnot&lt;/a&gt;. We aim to enable anyone to turn their passion into a business &amp;amp; bring people together through commerce.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/09/whatnot.jpeg&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;video width=&quot;300&quot; preload=&quot;auto&quot; controls=&quot;&quot;&gt;
      &lt;source src=&quot;/wp-content/uploads/2021/09/whatnot-2023.mp4&quot; type=&quot;video/mp4&quot; /&gt;
    &lt;/video&gt;
  &lt;/div&gt;
  &lt;em&gt;Whatnot to the moon 🚀!&lt;/em&gt;
&lt;/div&gt;
</description>
                <pubDate>Sat, 25 Sep 2021 19:02:33 +0000</pubDate>
                <link>https://multigesture.net//2021/09/25/my-mobile-journey/</link>
                <guid isPermaLink="true">https://multigesture.net//2021/09/25/my-mobile-journey/</guid>
                
                
                <category>Multitouch</category>
                
            </item>
        
            <item>
                <title>Inspecting Network Traffic of any Android App</title>
                <description>&lt;p&gt;Like to see what your favorite Android app is doing ? I wrote an article of how you can inspect the network traffic of an app using the Android emulator and &lt;a href=&quot;https://mitmproxy.org/&quot;&gt;mitmproxy&lt;/a&gt; check it out here: &lt;a href=&quot;/articles/inspecting-https-network-traffic-of-any-android-app/&quot;&gt;Inspecting (HTTPS) Network Traffic of any Android App&lt;/a&gt;&lt;/p&gt;
</description>
                <pubDate>Fri, 07 May 2021 14:05:40 +0000</pubDate>
                <link>https://multigesture.net//2021/05/07/inspecting-network-traffic-of-any-android-app/</link>
                <guid isPermaLink="true">https://multigesture.net//2021/05/07/inspecting-network-traffic-of-any-android-app/</guid>
                
                
                <category>Multitouch</category>
                
            </item>
        
            <item>
                <title>Creating my own Cycling Trainer App</title>
                <description>&lt;p&gt;I’m a big fan of &lt;a href=&quot;https://www.zwift.com/&quot;&gt;Zwift&lt;/a&gt;, it’s a virtual cycling app that allows you to train and compete online in a virtual world.&lt;/p&gt;

&lt;p&gt;I started training indoors in November 2018 when the weather was getting colder and I wanted a home setup that I could use if it was raining or snowing outside. Instead of buying an indoor cycling bike or spin bike, I invested in a smart bike trainer (Wahoo Kickr 2018) that I could use with my road bike (Trek Domane SL5). This would allow me to keep using my comfortable bike and it would allow an app to manage the resistance automatically (which isn’t common on a spinbike or a peleton).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/09/46252240_928010340656136_8687854171640487190_n.jpeg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The fun part is that Zwift would also allow you to train on courses inspired by real ones. For example, there is Alpe du Zwift which is a virtual copy of Alpe d’Huez in France:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/09/91755688_210721753527967_2412481578331085166_n.jpeg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Zwift only allows you to ride the courses they provide, some are made up, others are inspired by real cities/courses.&lt;/p&gt;

&lt;p&gt;But… what if I want to ride somewhere that is more familiar to me? I spend some weeks understanding how to control the smart trainer via ANT+ / Bluetooth and started to create my own bike riding software using Unreal Engine 4.&lt;/p&gt;

&lt;p&gt;It’s still WIP, doesn’t have pretty rider graphics but it does read the sensor data (Power in Watt), runs physics calculations on it and turns that into speed (similar to what Zwift does). It then applies the slope % to the Wahoo smart bike trainer for the appropriate resistance and also read the Cadence/Heart rate sensor data. During the ride it will record your stats into a fit file that you can upload to services like &lt;a href=&quot;http://strava.com/&quot;&gt;Strava&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Basically I created a flow (by writing custom UE4 plugins) where I can import an elevation map (DTM), road information and turn it into an UE4 landscape. This means that I don’t have to create the virtual world with too much manual effort and allows me to recreate a map of any place in the world as long as there is enough (elevation) data available. Fortunately for the Boston area, there is very precise data available (1 meter precision).&lt;/p&gt;

&lt;p&gt;I took a ‘virtual ride’ at my old neighborhood. With the super steep Lowell St.:&lt;/p&gt;
&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/09/157209205_4493969893952359_1828808700321279374_n.jpeg&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/09/157168369_4493969877285694_5226292038019728876_n.jpeg&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/09/157172380_4493969963952352_8354305347879505436_n.jpeg&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/09/157669089_4493969993952349_2873986763602970460_n.jpeg&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Another experiment was Mount Greylock which is in Western Mass:&lt;/p&gt;
&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/03/Screen-Shot-2021-01-11-at-1.52.38-PM.jpeg&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/03/Screen-Shot-2021-01-11-at-1.54.08-PM.jpeg&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2021/03/Screen-Shot-2021-09-27-at-9.24.13-AM.jpeg&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
  &lt;em&gt;Left Unreal Engine 4, Right Strava&lt;/em&gt;
&lt;/div&gt;

&lt;p&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/7FwIka7p09s&quot; loading=&quot;lazy&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
</description>
                <pubDate>Sat, 06 Mar 2021 12:35:13 +0000</pubDate>
                <link>https://multigesture.net//2021/03/06/creating-my-own-cycling-trainer-app/</link>
                <guid isPermaLink="true">https://multigesture.net//2021/03/06/creating-my-own-cycling-trainer-app/</guid>
                
                
                <category>Multitouch</category>
                
            </item>
        
            <item>
                <title>NodeBeat featured on the BlackBerry Dev blog</title>
                <description>&lt;p&gt;Interested to read how we (me and &lt;a href=&quot;http://sethsandler.com/&quot;&gt;Seth&lt;/a&gt;) ported &lt;a href=&quot;http://nodebeat.com/&quot;&gt;NodeBeat&lt;/a&gt; to the BlackBerry PlayBook platform?&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://devblog.blackberry.com/&quot;&gt;BlackBerry Developer Blog&lt;/a&gt; wrote an article about us, our app and the journey that was involved with it: &lt;a href=&quot;http://devblog.blackberry.com/2012/07/dev-success-nodebeat/&quot;&gt;http://devblog.blackberry.com/2012/07/dev-success-nodebeat/&lt;/a&gt;&lt;/p&gt;
</description>
                <pubDate>Thu, 02 Aug 2012 18:27:51 +0000</pubDate>
                <link>https://multigesture.net//2012/08/02/nodebeat-featured-on-the-blackberry-dev-blog/</link>
                <guid isPermaLink="true">https://multigesture.net//2012/08/02/nodebeat-featured-on-the-blackberry-dev-blog/</guid>
                
                
                <category>Application</category>
                
                <category>BlackBerry</category>
                
                <category>Featured</category>
                
            </item>
        
            <item>
                <title>PlayBook add-on (ofxQNX)</title>
                <description>&lt;p&gt;After receiving my BlackBerry PlayBook through the &lt;a href=&quot;http://devblog.blackberry.com/2012/02/latest-blackberry-playbook-tablet-offer-for-android-developers/&quot;&gt;developer offer&lt;/a&gt; in March, I started to think of the possibility of porting &lt;a href=&quot;http://www.nodebeat.com&quot;&gt;NodeBeat&lt;/a&gt; to the PlayBook platform.&lt;/p&gt;

&lt;p&gt;As this is my first tablet (yea I know, as a multitouch enthusiast its quite weird not having an iPad or Android Tablet), I have to say that I am really enjoying the 7 inch form factor. It feels much nicer in the hand compared to most of the larger tablets (10+ inch) which can tire out your wrists quite a bit. Spec wise this device is &lt;a href=&quot;http://en.wikipedia.org/wiki/BlackBerry_PlayBook&quot;&gt;great&lt;/a&gt; (dual-core cpu, 1 GB ram, dedicated graphics chip), therefor it would be nice to test if the PlayBook would be a perfect platform to run NodeBeat on.&lt;/p&gt;

&lt;p&gt;Since I am already quite familiar with the NodeBeat code base, this would be a nice new challenge. After taking a brief look at the &lt;a href=&quot;https://bdsc.webapps.blackberry.com/native/&quot;&gt;Native SDK&lt;/a&gt;, I figured that this would not be as difficult compared to the Android port. Unlike on &lt;a href=&quot;http://developer.android.com/sdk/ndk/overview.html&quot;&gt;Android&lt;/a&gt;, there is no need for JNI bindings. Actually, I would say that developing for the PlayBook is very similar to writing applications for Linux (you can use Makefiles if you want), the compiler (qcc) is quite similar to gcc.&lt;br /&gt;
RIM includes a modified IDE (based on Eclipse) for app development and it works quite well. All the required tools are tightly integrated and the wizards help you to get through the setup. RIM also did a good job on &lt;a href=&quot;https://bdsc.webapps.blackberry.com/native/documentation&quot;&gt;documenting&lt;/a&gt; the Native SDK, including the documents on &lt;a href=&quot;https://bdsc.webapps.blackberry.com/native/documentation/porting_overview_1970891_11.html&quot;&gt;porting&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;porting&quot;&gt;Porting&lt;/h2&gt;

&lt;p&gt;NodeBeat is build on top of the popular &lt;a href=&quot;http://www.openframeworks.cc/&quot;&gt;openFrameworks&lt;/a&gt; (OF) platform, so the first thing I had to do was find out which dependencies I had to build to make it work and write an PlayBook add-on (&lt;a href=&quot;/projects/ofxqnx/&quot;&gt;ofxQNX&lt;/a&gt;) to extend the current framework.&lt;/p&gt;

&lt;p&gt;At first sight, this seemed to be quite a difficult task due the amount of dependencies OF relies on and the large code base I had to patch, but with help from the &lt;a href=&quot;http://forum.openframeworks.cc/index.php/topic,9189.0.html&quot;&gt;openFrameworks community&lt;/a&gt; and &lt;a href=&quot;http://supportforums.blackberry.com/t5/Native-Development/Porting-openFrameworks-need-help-with-the-audio-QSA-part/td-p/1641151&quot;&gt;BlackBerry community&lt;/a&gt;, it fortunately did not take long before I had some &lt;a href=&quot;https://twitter.com/#!/LaurenceMuller/status/179575497032871937&quot;&gt;stuff up and running&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2012/04/An369o-CMAA1dHD.jpeg&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
  &lt;em&gt;WIP ofxQNX&lt;/em&gt;
&lt;/div&gt;

&lt;p&gt;I won’t bore you guys to death with the details on how to get the dependencies compiled using the NDK as most of them worked straight out of the box (in the &lt;a href=&quot;https://github.com/falcon4ever/openFrameworks/tree/developPlayBook/addons/ofxQNX&quot;&gt;readme&lt;/a&gt; are some details on what to patch). The ones that were troublesome and caused me a lot of frustration were the ones that use custom build scripts (yes you &lt;a href=&quot;http://pocoproject.org/forum/viewtopic.php?f=12&amp;amp;t=5318&quot;&gt;POCO&lt;/a&gt;). I am sure those devs have a valid reason for using it, but it makes things a bit overcomplicated. In the case of POCO, the QNX build (PlayBook target) could only be build on a &lt;a href=&quot;http://pocoproject.org/docs/00200-GettingStarted.html#9&quot;&gt;Linux machine&lt;/a&gt;. I ended up installing Ubuntu in VirtualBox to compile FreeImage and Poco.&lt;/p&gt;

&lt;p&gt;It was worth the effort though as I managed to get OF run properly on my tablet:&lt;/p&gt;
&lt;p&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/JLE3v-QRa74&quot; loading=&quot;lazy&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;

&lt;h2 id=&quot;where-to-get-it&quot;&gt;Where to get it?&lt;/h2&gt;

&lt;p&gt;Details about the project can now be found here: &lt;a href=&quot;/projects/ofxqnx/&quot;&gt;ofxqnx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;del&gt;The &lt;a href=&quot;/projects/ofxqnx/&quot;&gt;ofxQNX&lt;/a&gt; add-on is available on GitHub, in the &lt;strong&gt;developPlayBook&lt;/strong&gt; branch:&lt;/del&gt;&lt;br /&gt;
&lt;del&gt;&lt;a href=&quot;https://github.com/falcon4ever/openFrameworks/tree/developPlayBook&quot;&gt;https://github.com/falcon4ever/openFrameworks/tree/developPlayBook&lt;/a&gt;&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;It is licensed under the &lt;a href=&quot;http://en.wikipedia.org/wiki/BSD_licenses#3-clause_license_.28.22New_BSD_License.22_or_.22Modified_BSD_License.22.29&quot;&gt;New BSD license&lt;/a&gt; and hopefully will become part of the mainstream branch. For now I will maintain it in my own OF fork as quite a lot of the OF core had to be patched.&lt;/p&gt;

&lt;p&gt;Included are ten example projects that explain how to use various features of ofxQNX. All project files contain settings for development on the Simulator (x86) as on the PlayBook/BB10 hardware (ARM).&lt;/p&gt;

&lt;h2 id=&quot;is-it-ready-for-prime-time&quot;&gt;Is it ready for prime time?&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;It sure is!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With &lt;a href=&quot;http://nodebeat.com/&quot;&gt;NodeBeat&lt;/a&gt; as our guinea pig, &lt;a href=&quot;http://sethsandler.com/&quot;&gt;Seth&lt;/a&gt; and I have been working pretty hard the past weeks to get NodeBeat up and running just in time for &lt;a href=&quot;http://www.blackberryjamconference.com/&quot;&gt;BB 10 Jam&lt;/a&gt;. Since NodeBeat uses a lot of different OF features, it was a perfect way to test out ofxQNX and the stability of the add-on.&lt;/p&gt;

&lt;p&gt;Below is some footage I shot of an early NodeBeat Beta running on the PlayBook. I love that compared to the Android build, this device is giving us much lower input and audio latencies which really enhance the experience.&lt;/p&gt;

&lt;p&gt;We have submitted NodeBeat to &lt;a href=&quot;https://twitter.com/#!/NodeBeat/status/195589029377486848&quot;&gt;the BlackBerry AppWorld&lt;/a&gt; so hopefully it will be available soon for your listening pleasure!&lt;/p&gt;

&lt;p&gt;NodeBeat beta:&lt;/p&gt;

&lt;p&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/xhZ46PpccGQ&quot; loading=&quot;lazy&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2012/04/IMG_1737.jpg&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2012/04/IMG_1735.jpg&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
  &lt;em&gt;NodeBeat running on the BlackBerry Playbook Tablet&lt;/em&gt;
&lt;/div&gt;

&lt;h2 id=&quot;feedback--todo&quot;&gt;Feedback / Todo&lt;/h2&gt;

&lt;p&gt;Since ofxQNX is now available to everyone on GitHub, I’d love to hear what you think about using openFrameworks for your PlayBook projects. While a lot of basic OF functionality is already available in ofxQNX, the things that are still lacking are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ofSoundPlayer, used for controlling the audio levels from the app and play wav/mp3 audio files. For now I recommend using SDL for this purpose.&lt;/li&gt;
  &lt;li&gt;Camera support. Unfortunately the current PlayBook SDK doesnt allow access to the cameras. As soon as those are supported (prob with the next release) I’ll be porting the cameraExample and openCVExample.&lt;/li&gt;
  &lt;li&gt;GPS Support with gpsExample&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Probably the most important one to focus on is ofSoundPlayer. As there is already an OpenAL implementation (ofOpenALSoundPlayer) in the repository, I am currently investigating if we will be able to (re)use it for ofxQNX.&lt;/p&gt;

&lt;p&gt;Anyway, let me know how ofxQNX runs and don’t hesitate to report bugs or submit patches (on GitHub). &lt;strong&gt;Enjoy!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[update 05/05/2012]&lt;/strong&gt;&lt;br /&gt;
ofxQNX now also supports the BlackBerry 10 Beta platform!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[update 14/09/2012]&lt;/strong&gt;&lt;br /&gt;
Updated link to the &lt;a href=&quot;/projects/ofxqnx/&quot;&gt;ofxQNX project&lt;/a&gt;, now compatible with OF0071&lt;/p&gt;
</description>
                <pubDate>Thu, 26 Apr 2012 23:34:48 +0000</pubDate>
                <link>https://multigesture.net//2012/04/27/playbook-add-on-ofxqnx/</link>
                <guid isPermaLink="true">https://multigesture.net//2012/04/27/playbook-add-on-ofxqnx/</guid>
                
                
                <category>Application</category>
                
                <category>BlackBerry</category>
                
                <category>Blogroll</category>
                
                <category>Featured</category>
                
                <category>Howto</category>
                
                <category>Multitouch</category>
                
            </item>
        
            <item>
                <title>Rewriting and porting fIRC</title>
                <description>&lt;p&gt;Late 2008 I created my &lt;a href=&quot;/2008/12/22/firc-android-chat-client-released/&quot;&gt;first Android application&lt;/a&gt; (fIRC) after obtaining the T-Mobile G1. The project was an early attempt to master the Java programming language and also a way for me to learn more about the &lt;a href=&quot;http://developer.android.com/index.html&quot;&gt;Android mobile platform&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since the Android Market was still young in 2008, my chat application fIRC became a success. While internet group chat isn’t something new, chatting on your smartphone in real time to other people was. People loved using fIRC because it was easy to join the chatroom for some small talk (By default fIRC connects the chatroom #android-chat on &lt;a href=&quot;http://webchat.freenode.net&quot;&gt;Freenode&lt;/a&gt;).&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2012/02/fircdownloads.jpg&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The reviews back in 2009 were pretty favorable, but went downhill after new Android devices were released onto the market. One of the (beginners) mistakes I made when creating fIRC, was that I designed the app specifically for one device, the device I owned: The T-Mobile G1. This means that it was created for devices that had a hardware keyboard, a 480×320 resolution display that was used in landscape mode.&lt;/p&gt;

&lt;p&gt;On new devices (let’s say Android 2.x or newer) fIRC didn’t behave that well. UI elements weren’t aligned properly and the bundled resources were only meant to be used on low or medium DPI displays, so on those new devices fIRC looked quite horrible.&lt;/p&gt;

&lt;p&gt;As the old chat code turned into a code spaghetti while trying to fix the problems, I decided to rewrite the app from scratch. I did most of the core last summer and some of the UI during fall. The newly rewritten UI of fIRC now scales properly on any phone or tablet device.&lt;/p&gt;

&lt;p&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/SsIKqkeoAM8&quot; loading=&quot;lazy&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;

&lt;h3 id=&quot;new-features&quot;&gt;New Features&lt;/h3&gt;

&lt;p&gt;The main new features:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(1) Profile wizard&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;IRC is not that common these days, one of the complaints of the previous version was that nobody knew how to connect to a different server and how to enter multiple chat rooms (or actually so called “channels”). In order to address this problem, I’ve made a profile wizard, that helps you out by providing some quick settings and a list of commonly used IRC servers (such as DALnet, EFnet and Freenode).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(2) Multi-server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;More advanced users requested muti-server supprot because they often like to join multiple irc servers. This new version allows you to do that. Simply create one profile per server, hit the menu button and choose “Connect all profiles” to connect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(3) Fast channel switching&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No need to dive into the menu anymore to switch channels, just use a swipe motion (left/right) to switch between chat rooms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(4) Fully customizable chat&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;fIRC now allows you to customize the incoming messages and color them in the way you want. You decide which font, font size, background color and text color you want to user per message type.&lt;/p&gt;

&lt;p&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/sqbwetdkZ-Q&quot; loading=&quot;lazy&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(5) File transfer support&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A unique feature on Android IRC apps: fIRC supports DCC file transfers (3G and WiFi). Currently only DCC receive is implemented.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(6) Store chat logs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;fIRC allows you to store your chat logs on your SD card for future reading.&lt;/p&gt;

&lt;h3 id=&quot;porting-to-the-blackberry-playbook&quot;&gt;Porting to the BlackBerry Playbook&lt;/h3&gt;

&lt;p&gt;Earlier this month Alex Saunders from RIM &lt;a href=&quot;http://bit.ly/x48eS&quot;&gt;tweeted&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;“Shh…. Android Devs – submit your Android app to BB AppWorld by Feb 13 and get a free Playbook –&amp;gt; tools here: &lt;a href=&quot;http://t.co/Ys32aMJT&quot; title=&quot;http://bit.ly/w758Ci&quot;&gt;http://bit.ly/w758Ci&lt;/a&gt;“.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wasn’t aware that the BlackBerry Playbook had some kind of emulation layer to run Android apps, so after watching the &lt;a href=&quot;https://bdsc.webapps.blackberry.com/android/tool&quot;&gt;video&lt;/a&gt; below, I decided to give it a shot. I mean, how hard could it possibly be?&lt;/p&gt;

&lt;p&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/62tkj53G7kU&quot; loading=&quot;lazy&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;

&lt;p&gt;Basically you will have to sign up as a vendor on this site: &lt;a href=&quot;https://appworld.blackberry.com/isvportal/&quot;&gt;https://appworld.blackberry.com/isvportal/&lt;/a&gt; . RIM will sent you an e-mail (took about a day here) with the request to provide some documents proving you are a company. Fortunately I still had a copy from the Chamber of Commerce that I could use.&lt;br /&gt;
While waiting for RIM to approve your account, you should &lt;a href=&quot;http://developer.blackberry.com/android/signingkey&quot;&gt;request a code signing key&lt;/a&gt;. You will need this key to sign your app later on. After you’re done with that, open up Eclipse and &lt;a href=&quot;https://bdsc.webapps.blackberry.com/android/documentation/install_plugin_prerequisites_1895476_11.html&quot;&gt;install BlackBerry Plug-in for Android Development Tools&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since fIRC doesn’t use any of the advanced features of the Android SDK or Android NDK (not supported), the only things I had to do were:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Convert the Android project by &lt;a href=&quot;https://bdsc.webapps.blackberry.com/android/documentation/add_blackberry_nature_1984898_11.html&quot;&gt;adding a “blackberry nature”&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Remove the Android references in the app (CTRL-F “Android”)&lt;/li&gt;
  &lt;li&gt;Resized the application icon to 86×86 pixels&lt;/li&gt;
  &lt;li&gt;Test the app in the simulator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From the list above, I’d say that testing the app on the simulator was the most time consuming. Blackberry provides a “BlackBerry Tablet Simulator”, but it is actually a virtual drive image with the Playbook software pre-loaded that you can run in VMWare Player.&lt;/p&gt;

&lt;p&gt;If you thought the Android emulator was already slow compared to the iOS simulator, think again. Booting up the Playbook takes quite a bit (it feels like booting a desktop OS), and the interaction with the mouse feels a bit sluggish. After the Tablet OS is fully booted, its time to put it in development mode. This allows you to connect to the simulator from Eclipse. Recompiling the Android project and installing it into the simulator feels almost the same as using the Android emulator. Just hit the play button.&lt;/p&gt;

&lt;p&gt;Unfortunately the Playbook simulator isn’t all that great for testing your converted BlackBerry apps. In my case the screen flickering was really bad and fonts were blurred (Native BB apps were alright though). Reading the &lt;a href=&quot;http://supportforums.blackberry.com/t5/BlackBerry-App-World-Development/bd-p/appworld_dev&quot;&gt;BlackBerry Dev forums&lt;/a&gt;, it seem to be an issue with the simulator, so hopefully it looks good on the real device.&lt;/p&gt;

&lt;p&gt;The only real trouble I had was signing the app itself to prepare it for the BlackBerry App World. I was following the steps from the Youtube video above. However, BB changed the names of the dropdown menus in Eclipse. Fortunately the documents describe how to do this properly: &lt;a href=&quot;https://bdsc.webapps.blackberry.com/android/documentation/sign_your_app_1985461_11.html&quot;&gt;Sign your app&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2012/02/fircsign.jpg&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;/h3&gt;

&lt;p&gt;For me porting fIRC to the BlackBerry platform seemed to be a quite painless experience. However, I would advice you to test apps thoroughly on the Android Emulator and when you’re ready for release, test it out on a real Playbook instead of the simulator. That would probably give you a much smoother workflow.&lt;/p&gt;

&lt;p&gt;For me that will hopefully soon be possible. Last week I received an e-mail from RIM that my application was accepted to the BlackBerry App World and that I would receive a free Playbook soon :).&lt;/p&gt;

&lt;p&gt;The latest version of fIRC for your chatting pleasure is now available from the &lt;a href=&quot;https://market.android.com/details?id=com.epicwindmill.fIRC&quot;&gt;Android market&lt;/a&gt; (Android devices 2.1 and higher) and the &lt;a href=&quot;http://appworld.blackberry.com/webstore/content/84131/?lang=en&quot;&gt;BlackBerry App World&lt;/a&gt; (BlackBerry Playbook)!&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2012/02/device-2012-02-06-235632.png&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
                <pubDate>Wed, 22 Feb 2012 21:55:36 +0000</pubDate>
                <link>https://multigesture.net//2012/02/22/rewriting-and-porting-firc/</link>
                <guid isPermaLink="true">https://multigesture.net//2012/02/22/rewriting-and-porting-firc/</guid>
                
                
                <category>Android</category>
                
                <category>Application</category>
                
                <category>BlackBerry</category>
                
                <category>Blogroll</category>
                
                <category>Featured</category>
                
                <category>Multitouch</category>
                
            </item>
        
            <item>
                <title>Epic Windmill</title>
                <description>&lt;p&gt;It’s official now, I’m proud owner of my new startup company &lt;a href=&quot;http://epicwindmill.com/&quot;&gt;Epic Windmill&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As this blog served as my online portfolio of research work I contributed to, Epic Windmill will be serving as a place for my creative and casual software projects. For the time being, it will focus on the development of applications for handheld devices such as smartphones and tablets (Android and iOS).&lt;/p&gt;

&lt;p&gt;Currently two apps are already available from the Android Market, &lt;a href=&quot;https://market.android.com/details?id=com.AffinityBlue.NodeBeat&quot;&gt;NodeBeat&lt;/a&gt; (a creative audio sequencer) and &lt;a href=&quot;http://epicwindmill.com/firc/&quot;&gt;fIRC&lt;/a&gt; (a free chat app). We’re preparing a release for NodeBeat so be sure to follow &lt;a href=&quot;https://twitter.com/#!/nodebeat&quot;&gt;@NodeBeat&lt;/a&gt; for more details. A new fIRC will be released later this month.&lt;/p&gt;

&lt;p&gt;– Laurence&lt;/p&gt;

&lt;p&gt;p.s. Don’t forget to follow us on Twitter &lt;a href=&quot;https://twitter.com/#!/EpicWindmill&quot; title=&quot;Follow us on Twitter&quot;&gt;@EpicWindmill&lt;/a&gt; and like us on &lt;a href=&quot;https://www.facebook.com/epicwindmill&quot; title=&quot;Epic Windmill on Facebook&quot;&gt;Facebook&lt;/a&gt;!&lt;/p&gt;
</description>
                <pubDate>Mon, 06 Feb 2012 15:55:41 +0000</pubDate>
                <link>https://multigesture.net//2012/02/06/epic-windmill/</link>
                <guid isPermaLink="true">https://multigesture.net//2012/02/06/epic-windmill/</guid>
                
                
                <category>Application</category>
                
                <category>Blogroll</category>
                
                <category>Featured</category>
                
            </item>
        
            <item>
                <title>NodeBeat, openFrameworks and Android</title>
                <description>&lt;p&gt;Last month we (&lt;a href=&quot;http://www.sethsandler.com/&quot;&gt;Seth Sandler&lt;/a&gt; and yours truly) released the Android port of the popular iPhone/iPad music application &lt;a href=&quot;http://nodebeat.com/&quot;&gt;NodeBeat&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;NodeBeat was created by &lt;strong&gt;Seth Sandler&lt;/strong&gt; and &lt;strong&gt;Justin Windle&lt;/strong&gt; earlier this year and released in April for the iOS platform. It is an experimental node-based audio sequencer and generative music application. By combining music and playful exploration, NodeBeat allows anyone to create an exciting variety of rhythmic sequences and ambient melodies in a fun and intuitive fashion.&lt;/p&gt;

&lt;p&gt;&lt;iframe src=&quot;https://player.vimeo.com/video/30325679?h=0d3ea7945e&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;360&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;

&lt;h2 id=&quot;how-does-it-work&quot;&gt;How Does it Work?&lt;/h2&gt;

&lt;p&gt;Octaves and Notes make up the two types of nodes. Octaves pulse and send messages to Notes within proximity. Each Octave is assigned a random octave and each Note, a random note; therefore, a Note will play in several octaves depending on the Octave it’s connected to. Pause nodes to create your own beats or let them roam free to have them generate their own.&lt;/p&gt;

&lt;p&gt;&lt;iframe src=&quot;https://player.vimeo.com/video/27323966?h=560b8b179f&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;360&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;

&lt;h2 id=&quot;cross-platform-development&quot;&gt;Cross platform development&lt;/h2&gt;

&lt;p&gt;Because NodeBeat was developed using the C++ based open source framework &lt;a href=&quot;http://www.openframeworks.cc/&quot;&gt;openFrameworks&lt;/a&gt;, I did not expected a lot of trouble getting the core to work on Android. However, since the Android port of openFarmworks is still pretty new (we’re using the &lt;a href=&quot;https://github.com/openframeworks/openFrameworks/tree/develop&quot;&gt;development branch&lt;/a&gt;) and officially only supported on the &lt;a href=&quot;http://www.openframeworks.cc/setup/android-eclipse&quot;&gt;Mac and Linux platforms&lt;/a&gt;, I decided to put some effort into making it work on Windows as well. I’m a Windows user and developer, so if I can avoid dualbooting, I will :P.&lt;/p&gt;

&lt;h2 id=&quot;native-development-kit&quot;&gt;Native Development Kit&lt;/h2&gt;

&lt;p&gt;As soon as you want to use C or C++ in your Android projects, you will have to install the &lt;a href=&quot;http://developer.android.com/sdk/ndk/index.html&quot;&gt;Native Development Kit&lt;/a&gt; (NDK). It basically allows you to compile your code into a library which you can access using &lt;a href=&quot;http://en.wikipedia.org/wiki/Java_Native_Interface&quot;&gt;JNI calls&lt;/a&gt;. While in general it is recommend to code using the &lt;a href=&quot;http://developer.android.com/sdk/index.html&quot;&gt;SDK in Java&lt;/a&gt; for your Android projects (the Dalvik VM with JIT show really good performance), lazy coders (like me :P) are always trying to find ways to reuse existing code. Instead of having a native codebase for iOS (in Objective-C) and Android (in Java), it is nicer to have a shared core in C++ with a thin layer (Obj-C or Java) to interface with it. Sure the NDK might sound intimidating at first sight and Google doesnt recommend it unless you know what you’re doing, but honestly I don’t think its rocket science either. After downloading the NDK, you will need to setup a unix like environment such as &lt;a href=&quot;http://www.mingw.org/&quot;&gt;MinGW&lt;/a&gt; or &lt;a href=&quot;http://www.cygwin.com/&quot;&gt;Cygwin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For my previous projects I already had MinGW installed (you could use Cygwin, but in general I don’t like their approach). I did a fresh &lt;a href=&quot;https://github.com/openframeworks/openFrameworks/tree/develop&quot;&gt;checkout from Github&lt;/a&gt; and started to mess around with the Makefiles to see if it would compile.&lt;/p&gt;

&lt;p&gt;It turned out that all I had to do is replacing a few IF statements (the ones that are checking the build platform) and make them point to the NDK location on my Windows computer. I’ve &lt;a href=&quot;/articles/how-to-setup-openframeworks-for-android-on-windows/&quot;&gt;created a tutorial&lt;/a&gt; that explains the steps if you want to try it out yourself. However, if you want to use openFrameworks for your own Android applications, I would highly recommend just using my &lt;a href=&quot;https://github.com/falcon4ever/openFrameworks&quot;&gt;openFrameworks fork&lt;/a&gt; instead (until they accept my pull request). It includes all the patches from the tutorial and it should be compatibly with the latest NDK. The &lt;a href=&quot;/articles/how-to-setup-openframeworks-for-android-on-windows/&quot;&gt;tutorial&lt;/a&gt; actually also explains how to run one of the examples so be sure to check that out.&lt;/p&gt;

&lt;h2 id=&quot;porting-the-gui&quot;&gt;Porting the GUI&lt;/h2&gt;

&lt;p&gt;For the UI I wanted to stay as close to the iOS version as possible. As I don’t own an iOS device, Seth gave me some screenshots of NodeBeat running on iOS which I used as a reference.&lt;/p&gt;

&lt;p&gt;Since the iOS and Android framework are quite distinct, there are cases where I had to do an alternative implementation. For example, on Android most devices have the following buttons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Back&lt;/li&gt;
  &lt;li&gt;Menu&lt;/li&gt;
  &lt;li&gt;Home&lt;/li&gt;
  &lt;li&gt;Search&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The iOS devices only have one button which brings you back to the home screen. In the original implementation of NodeBeat on iOS, there is a shortcut on the canvas that popup a menubar allowing you to access different option menus. On Android however we can use the &lt;strong&gt;options menu&lt;/strong&gt; which allows us to control the flow of the application.&lt;/p&gt;

&lt;h3 id=&quot;example-menu-bar&quot;&gt;Example: Menu bar&lt;/h3&gt;

&lt;p&gt;So instead of writing the menu code in C++, I only had to create a &lt;a href=&quot;http://developer.android.com/guide/topics/ui/menus.html#options-menu&quot;&gt;XML file for the option menu&lt;/a&gt;. It looks like this:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;&amp;lt;&lt;/span&gt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;&amp;gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;menu&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:android=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://schemas.android.com/apk/res/android&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;item&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;android:icon=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;@drawable/node_icon&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;android:id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;@+id/node&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;android:title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Node&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;item&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;android:icon=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;@drawable/audio_icon&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;android:id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;@+id/audio&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;android:title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Audio&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
...
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/menu&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Basically you define a unique id (this allows you to reference it in the Java source code), tell it which icon to use and give it a title. You need to do this for every entry, but apart from that, the Android framework will handle how to display it (depending on orientation and the number of menu items) After the user touches the menu button on Android, it will popup the option menu:&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2011/11/menu-ios-152x300.png&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2011/11/Arrow1.png&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2011/11/menu-android-180x300.png&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;example-audio-menu&quot;&gt;Example: Audio menu&lt;/h3&gt;

&lt;p&gt;Other menu elements such as the popup menu for the Audio, Rhythm and Settings menu required a different approach. I could’ve switched Views on Android, but in my opinion that would be a bad UI design decision. The problem with this is that the user would be taken away from the NodeBeat activty. Instead I much more prefer to use the &lt;a href=&quot;http://developer.android.com/guide/topics/ui/menus.html#context-menu&quot;&gt;context menu&lt;/a&gt; that the Android framework provides. This menu popups up and is placed over your current Activity. While it is on the foreground, the activity in the background is still visible and continues running. Another benefit of this approach is that the user will get immediate feedback when adjusting the audio settings. As like the menu, this &lt;a href=&quot;http://developer.android.com/guide/topics/ui/layout-objects.html&quot;&gt;UI layout&lt;/a&gt; is created entirely in XML.&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2011/11/audiomenu-ios-153x300.png&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2011/11/Arrow1.png&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2011/11/audiomenu-android-180x300.png&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;example-recording-dialog&quot;&gt;Example: Recording dialog&lt;/h3&gt;

&lt;p&gt;In some cases the context menu might be a bit of overkill if you want to let the user decide on a question. For example, in the example below we want to inform the user how to record his NodeBeat creation. All we need is a simple dialog that either lets the user confirm the action or decline it. In such cases Android provides dialogs which can be build with an &lt;a href=&quot;http://developer.android.com/guide/topics/ui/dialogs.html&quot;&gt;AlertDialog.Builder&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;AlertDialog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Builder&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AlertDialog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;You can stop recording by pressing the record button in the menu again&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setCancelable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setPositiveButton&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Yes&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DialogInterface&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnClickListener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
           &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DialogInterface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dialog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;// Start recording&lt;/span&gt;
           &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;})&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setNegativeButton&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;No&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DialogInterface&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnClickListener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
           &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DialogInterface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dialog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;dialog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;cancel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Cancel dialog&lt;/span&gt;
           &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;AlertDialog&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setTitle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Start recording&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2011/11/recording-ios-152x300.png&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2011/11/Arrow1.png&quot; loading=&quot;lazy&quot; /&gt;
    &lt;img src=&quot;/wp-content/uploads/2011/11/recording-android-180x300.png&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&quot;using-jni-callbacks&quot;&gt;Using JNI Callbacks&lt;/h2&gt;

&lt;p&gt;After we’ve ported the UI, we still need to pass on our settings to the core application. Fortunately we can use JNI callbacks to get and set NodeBeat’s properties. It is good to know that you should minimize the number of JNI callbacks for performance reasons (so don’t go mental and call tons of JNI methods each time you render a frame).&lt;/p&gt;

&lt;p&gt;Let say we would like to pass a value from one of the sliders from the Audio context menu to our NodeBeat core. In such case we first create a new static method in our Java source file:&lt;/p&gt;

&lt;h3 id=&quot;ofactivityjava&quot;&gt;OFActivity.java&lt;/h3&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;native&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sliderChanged&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is important to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;native&lt;/code&gt; keyword when you define your method. This is all we need to do in our java code and this method can be used anywhere in our java class.&lt;/p&gt;

&lt;p&gt;Now the tricky part is how to implement the function on the C++ side of your application. It’s not exactly complex, but you will have to pay attention to a few details. Three things are important here:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The namespace (in Java)&lt;/li&gt;
  &lt;li&gt;The class name&lt;/li&gt;
  &lt;li&gt;The method name&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If we assume we’re implementing this callback in one of the openFrameworks examples, this means:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The namespace (in Java): cc.openframeworks.androidEmptyExample&lt;/li&gt;
  &lt;li&gt;The class name: OFActivity&lt;/li&gt;
  &lt;li&gt;The method name: sliderChanged&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;maincpp&quot;&gt;main.cpp&lt;/h3&gt;

&lt;p&gt;Here is the code you implement in C++&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;jni.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;C&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Java_cc_openframeworks_androidEmptyExample_OFActivity_sliderChanged&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;JNIEnv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jclass&lt;/span&gt; &lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;thiz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jfloat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Do smth here&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jni&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As ugly as this method looks like, take a brief look at how it is constructed. It starts with the return type (which is void just like how we specified it in Java). Next it starts with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Java_&lt;/code&gt; and is succeeded by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;the namespace&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;classname &lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;method name&lt;/code&gt;. All dots from the namespace are replaced by underscores and between each element we place an underscore as well.&lt;/p&gt;

&lt;p&gt;In the arguments list, the “JNIEnv* env, jclass thiz” part is mandatory (so if you have a something like this: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public static native void methodname()&lt;/code&gt;, it would &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;be void methodname(JNIEnv*  env, jclass  thiz)&lt;/code&gt;). For our method we want to pass a float as argument. For some reasons you can’t just pass a float, you will need to use &lt;a href=&quot;http://en.wikipedia.org/wiki/Java_Native_Interface#Mapping_types&quot;&gt;JNI mapping types&lt;/a&gt;. The float becomes a jfloat.&lt;br /&gt;
Note: for booleans you need to compare the value to &lt;strong&gt;JNI_TRUE&lt;/strong&gt; or &lt;strong&gt;JNI_FALSE&lt;/strong&gt; and not to &lt;strong&gt;true&lt;/strong&gt; or &lt;strong&gt;false&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;honeycomb-tablets&quot;&gt;Honeycomb Tablets&lt;/h2&gt;

&lt;p&gt;Unlike the iOS devices from Apple, Android devices run at so many &lt;a href=&quot;http://developer.android.com/guide/practices/screens_support.html&quot;&gt;different configurations&lt;/a&gt; and API levels, it can be a bit tricky to support all of them. For NodeBeat we decided to create two versions: A phone version and tablet version. We basically distinguish between phones who are running Eclair or Gingerbread (2.2+) and tablets running Honeycomb (3.0). On the Android Market it seems like we only provide one version, but depending on what device you’re using to download the app, it will give you a &lt;a href=&quot;http://developer.android.com/guide/practices/screens-distribution.html#MultiApks&quot;&gt;certain version&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In order to maximize the use of the display, I’m using this line in the AndroidManifest.xml file:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;android:theme=&quot;@android:style/Theme.NoTitleBar.Fullscreen&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On phones it sets the application to fullscreen. While this works for anything running Android 2.2+, it is a problem on Honeycomb devices. Honeycomb tablets don’t have any physical buttons and when the application is running in fullscreen mode, there is no shortcut to the menu button. This shortcut is normally placed in the top right corner.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2011/11/P20111010235419.png&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;Honeycomb’s menu in the top right corner&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This means that for the tablet version, we run the application in regular display mode.&lt;br /&gt;
Other than that, NodeBeat provides a rich user experience on tablet devices such as the XOOM or Asus transfomer.&lt;/p&gt;

&lt;p&gt;Earbleeding masterpiece created by &lt;a href=&quot;http://sharathpatali.wordpress.com/&quot;&gt;Sharath Patali&lt;/a&gt; (professional coder, horrific musician)&lt;br /&gt;
&lt;img src=&quot;/wp-content/uploads/2011/11/P20111011000238.png&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;Earbleeding masterpiece created by Sharath Patali (professional coder, horrific musician)&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;android-market&quot;&gt;Android Market&lt;/h2&gt;

&lt;p&gt;Publishing the app to the Android market is no hassle at all (we were just a bit &lt;a href=&quot;http://createdigitalmusic.com/2011/10/nodebeat-visual-sequencer-for-ios-android-built-with-free-tools-back-on-android-market/&quot;&gt;unfortunate&lt;/a&gt; and had our app pulled down by accident). There is no annual fee (just a one time 25$) and apps are approved instantly. The dev guide provides a &lt;a href=&quot;http://developer.android.com/guide/publishing/publishing_overview.html&quot;&gt;comprehensive overview&lt;/a&gt; on how to build your project in release mode and how to sign it.&lt;/p&gt;

&lt;h2 id=&quot;go-get-it&quot;&gt;Go get it!&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;NodeBeat is available on the Android market&lt;/strong&gt;:&lt;br /&gt;
&lt;a href=&quot;https://market.android.com/details?id=com.AffinityBlue.NodeBeat&quot;&gt;https://market.android.com/details?id=com.AffinityBlue.NodeBeat&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it out! It’s just a dollar&lt;/strong&gt; 🙂&lt;/p&gt;

&lt;p&gt;Website: &lt;a href=&quot;http://nodebeat.com/&quot;&gt;http://nodebeat.com/&lt;/a&gt;&lt;br /&gt;
Twitter: &lt;a href=&quot;http://twitter.com/NodeBeat&quot;&gt;http://twitter.com/NodeBeat&lt;/a&gt;&lt;/p&gt;
</description>
                <pubDate>Sat, 19 Nov 2011 20:52:49 +0000</pubDate>
                <link>https://multigesture.net//2011/11/19/nodebeat-openframeworks-and-android/</link>
                <guid isPermaLink="true">https://multigesture.net//2011/11/19/nodebeat-openframeworks-and-android/</guid>
                
                
                <category>Android</category>
                
                <category>Application</category>
                
                <category>Featured</category>
                
                <category>Howto</category>
                
                <category>Multitouch</category>
                
            </item>
        
            <item>
                <title>An introduction to emulation</title>
                <description>&lt;p&gt;In the early 90s I primarly used a &lt;a href=&quot;https://www.youtube.com/watch?v=eY2gK1MPgh8&quot;&gt;Commodore 64 (C64) for gaming&lt;/a&gt;. As &lt;a href=&quot;https://www.youtube.com/watch?v=a8q-elxC6gU&quot;&gt;Santa never gave us a Nintendo&lt;/a&gt;, I used the C64 until the late 90s. At that point I was introduced to the concept of emulators. Emulators are computer programs that allow you to run software that wasn’t designed for your computer platform. For example, with emulators you could run games from the NES or Sega Master System on PCs. Nowadays computers have enough resources to run games from modern consoles such as the &lt;a href=&quot;http://www.dolphin-emulator.com/&quot;&gt;Nintendo Gamecube/Wii&lt;/a&gt; and &lt;a href=&quot;http://pcsx2.net/&quot;&gt;Playstation 2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Of course, there is always the debate whether it is legal to build an emulator. Console manufacturers will &lt;a href=&quot;http://www.nintendo.com/corp/legal.jsp#emulator&quot;&gt;always forbid&lt;/a&gt; any type of emulation of their systems. Although its a rather grey area as most documents on the chip design are publicly available (e.g. MIPS / ARM instruction sets).&lt;/p&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2011/03/spaceinvaders.jpg&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
  &lt;em&gt;Space Invaders&lt;/em&gt;
&lt;/div&gt;

&lt;p&gt;Since I got excited about emulation in general, I started to do some research on how to build one myself. As I didn’t want to spend days or even weeks to get some results, I looked for a simple system. A friend introduced me to a small system called the &lt;a href=&quot;http://en.wikipedia.org/wiki/CHIP-8&quot;&gt;Chip 8&lt;/a&gt;.&lt;br /&gt;
The Chip 8 itself didn’t existed as a hardware system, but was implemented in software. Due to the small instruction set (&lt;a href=&quot;http://en.wikipedia.org/wiki/CHIP-8#Opcode_table&quot;&gt;~30 opcodes&lt;/a&gt;), it was a very good candidate to work on as a first emulation project. The instruction set defines the functionality of the CPU. It for example contains instructions that allow the CPU to load or store data, but also perform mathematical tasks such as multiplications.&lt;/p&gt;

&lt;p&gt;Having worked on a couple of emulation projects (and emulator plugins), I started to write a guide that will hopefully help out aspiring emulator authors and inspire emulation enthusiast. The guide explains how emulators work and provides a detailed overview on how to write a Chip 8 interpreter from scratch.&lt;/p&gt;

&lt;p&gt;Writing a Chip 8 emulator shouldn’t be too time consuming. On average people tend to finish such project in one or two days. It’s a fun project to test out your programming skills and of course quite educational (and it isn’t just for CS majors ;))&lt;/p&gt;

&lt;p&gt;If you’re ready to take up the challenge, click the link below! Have fun!&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/articles/how-to-write-an-emulator-chip-8-interpreter/&quot;&gt;How to write an emulator (CHIP-8 interpreter)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;gallery-box&quot;&gt;
  &lt;div class=&quot;gallery&quot;&gt;
    &lt;img src=&quot;/wp-content/uploads/2011/03/brix.jpg&quot; loading=&quot;lazy&quot; /&gt;
  &lt;/div&gt;
  &lt;em&gt;Brix: a Breakout clone&lt;/em&gt;
&lt;/div&gt;
</description>
                <pubDate>Mon, 28 Mar 2011 22:35:32 +0000</pubDate>
                <link>https://multigesture.net//2011/03/29/an-introduction-to-emulation/</link>
                <guid isPermaLink="true">https://multigesture.net//2011/03/29/an-introduction-to-emulation/</guid>
                
                
                <category>Application</category>
                
                <category>Blogroll</category>
                
                <category>Featured</category>
                
                <category>Howto</category>
                
            </item>
        
    </channel>
</rss>