Saturday 9 November 2013

Porting a Qt Desktop application to Android

I am getting Dream to work on Android. There a many things to do and most of them are hard. I'll post a few things about the experience here. Things to do are:
  • port the audio capture and playout
  • Make dream work in a single window rather than many overlapping windows
  • get menus working
  • other things I haven't thought of yet
The first thing I tried was to write an openSL ES sound driver. I couldn't get it to work. Qt is supposed to support capture and playback using Qt Multimedia on Android from Qt 5.2. So I've hacked Dream to use Qt Multimedia. If it works well on Andriod we can make it the default for a GUI build and just keep pulseaudio, portaudio and Windows MM for console builds. I tried making a main window display in QML. It works OK but it will be much quicker to stay mostly with QWidgets. I found the Qt 5.2beta1 needs the QML libraries anyway so I gave it a go. It seems you can embed QML in QWidgets but not the other way round. See QML in a QWidget.

Friday 17 May 2013

Trying out Wordpress

I promised Julie I would try Wordpress out again. So I have here. It seems just as easy to use as blogger. I'll also try it from my phone and tablet.

The default look is nice. The only things I found a little annoying were the continual prompting to go premium and the mix of secure and non-secure content on the page which causes annoying popups in IE.

Mapping the Old Gaffers

It is the Old Gaffers Association's 50th year and a summer long party is in progress around the British Isles. One of the main items is a circumnavigation and we wanted to track the boats on-line.

Trackaphone kindly offered to sponsor the event and provide phones and apps for the boats to report their positions and a dedicated map. But gaffers are an independent lot and only about a third of the boats signed up. Some are blogging their positions, others have class B AIS transceivers on-board, a few have mAIS/iAIS apps on their phones and others are technology-free.

I thought it would be cool to create a combined map showing all the boats we can. This is how it works.

Feeds

We have three basic sources of information, Trackaphone, Marine Traffic and human beings. Trackaphone collect the data from their apps and present it in a simple xml feed at a specific URL. Trackaphone take care of assigning the inputs from specific phones to our fleet.

Marine Traffic offer a 'my fleet' service. Anyone can register on their website and create a list of boats they are interested in. There are AIS receivers all over the world which receive AIS transmissions and report positions to the site. Additionally, there are many ways ships can send their data to the site without needing a real AIS transceiver. The primary key for ships is their MMSI. Boats (like Robinetta) without a DSC radio can register on the site and Marine Traffic will allocate them a dummy MMSI for use just on the site.

Marine Traffic offer fleet xml feeds as a commercial service. Demitris at Marine Traffic kindly set up a feed for my fleet until the end of August free of charge as a birthday present to the OGA. Thanks Demitris! There are two feeds, a short feed which can be queried every 5 minutes and a long feed which can be queried every hour. Only ships which have reported recently are included in the feed, so I need some way to persist the data.

Finally, for boats with no automatic reporting, I get emails and read blog posts to get updates which can be manually applied to the database.

Hosting

Heroku is a 'Cloud Application Platform' which offers commercial application hosting with a free development tier. The traffic and uptime requirements for my map fit comfortably in the free tier. Heroku apps can be written using Ruby, Node.js, Clojure, Java, Python, and Scala. Of these, I'm most proficient in Java but Heroku support Spring MVC and I only know enough Spring to use Apache Camel and a full MVC is way over the top for building a single map. I know enough Python to get by and Heroku encourage Django which looked about right.

Heroku provide a postgres database for every application and postgres is my favourite!

There are hundreds of add-ons. The only one I needed was the scheduler which provides cron-like facilities.

Server-side Code

This was my first time using a framework like Django in earnest. Like Rails, Django provides a strong set of policies for separating the layers of a web application. It supports Views, Models and Templates and, I'm sure loads more that I haven't needed.

Models are the way in Django that you define your persistant objects. You define a Python class, using some conventions and Django goes away and creates a database and tables for the objects using its' Object-Relational Mapping system. One weakness is that if you add a field to the model there is no way Django will update the database schema. But it's easy enough to do by hand in SQL.

The coolest thing about models is that they come with an automatically generated admin interface. This provides a facility similar to MysqlAdmin but just for the Django model objects. It is possible to enhance and skin this but it works out of the box. This is how I do the manual updates for non-tracked boats.

Views render pages using templates.

For my map, I put all the html and Javascript in a single template (OK, I should separate out the scripts, but this is a quick and dirty project). The template has a template language which can loop over parameters passed in from the view, and this is what it does with each object.

The basic model for the application is as follows:
  • Every 10 minutes, Heroku Scheduler calls my refresh script (a normal Django/Python script) which polls the MarineTraffic and Trackaphone xml feeds and updates the database.
  • When I get new information about a non-tracked boat I use the Django admin page to update the database.
  • When a user views the map page, a Django View reads the database, extracts the boats and passes them to the template processor.
  • The map is rendered in the browser.

Map

The map is rendered by the Leaflet Javascript mapping library using the MapQuest Open tileset based on openstreetmap. Each boat or Relay Challenge Token is represented by a marker with a popup.

The markers are custom versions of free markers from Nicolas Mollet's Maps Icons Collection. I hand modified the sailing icon to look more gaffer-ish using Adobe Photoshop Elements and created shadow images for them using Erwin Bolwidt's Shadowmaker.

Where possible, boats have a popup which provides an image of the boat, and a link to the boat's blog. These links are all stored in the database by hand.

Tuesday 14 May 2013

Blogging on the iPad

I don't have an iPad but I have an iPhone and my friend Julie wants some advice on this topic.

Before I first started blogging I tried all the free services I could find and settled on blogger.

But the official iPhone blogger app isn't great.

Looking around the web it seems some consolidation has happened. People only talk about blogger and Wordpress. That makes things easier.

Wordpress is a clear choice if you think you might want to host your blog yourself.

You can start on Wordpress.com and the software is free and you can migrate your content.

Blogger is very simple to get started with. I'm still happy with it for robinetta-log.

I found two good posts on this topic. In my next post on the subject I'll report on using Wordpress again.

Unfortunately blogsy which is recommended only works on the iPad.

http://www.macstories.net/reviews/blogsy-a-better-blogging-app-for-ipad/

http://theedublogger.com/2011/06/15/blogging-with-an-ipad-writing-posts-using-apps-and-via-the-dashboard-in-a-web-browser/

Sunday 17 February 2013

List of times in Oracle

Oracle Row Generator Techniques is pretty definitive. Here is a nice example to provide 15 minute times in a day:

select to_char(trunc(sysdate)+(level-1)*15/1440, 'HH24:MI') from dual connect by level <= 240;