Want to revisit 2009's N900 tech demo but you got rid of your old toys long ago or don't want to bother digging them out of your desk drawer? The Maemulator to the rescue! It uses QEMU user-space emulation and some LD_PRELOAD magic + other in-process trickery to get it working on any modern Linux machine that has an OpenGL driver. Add multi-sample anti-aliasing, anisotropic filtering, higher resolutions, keyboard input and various fixes, and you are all set for a few minutes of fun distraction.
Planet maemo: category "feed:437c40ecc45d4b0fa868e422ae16adb1"
As part of a summer clean-up of the desk drawers, I pulled out the N800 and N9 and ported my game Loonies 8192 to these devices. Since those are "proper" Linux devices, one can compile things directly on-device (just install gcc from the SDK repos), and with SSH, it's easy to type on a real keyboard.
Anyway, you can install the game via the landing pages:
For the N800, make sure "maemo Extras" is enabled so it will find libsdl1.2 if it's not already installed. Head over to https://loonies.thp.io/n800/ on the device and download the deb, it will be installed by Application manager.
For the N9, make sure you have n9repomirror installed (again, so libsdl1.2 can be installed if necessary). Enable third party applications in Settings, Applications, Installations. Then head over to https://loonies.thp.io/n9/ on the device and download the deb, selecting after the download is finished will ask you to install it.
The N9 version is also available on openrepos.net.
And don't forget that the game is also available for DOS, various consoles and handheld consoles as well as on Windows. All of the builds are available on itch.io.
This depends on Bounce (the N900 .deb) and SDL 1.2 being installed. Google "bounce_1.0.0_armel.deb" for the former, and use n9repomirror for the latter.
sudo debootstrap --arch armhf --foreign sid sid sudo tar czvf sid.tgz -C sid . du -sh sid.tgz # 98M sid.tgz scp sid.tgz nemo@192.168.2.15:To unpack the chroot tarball:
ssh nemo@192.168.2.15 devel-su # password mkdir sid cd sid tar xvf ../sid.tgz chroot /home/nemo/sid/ /debootstrap/debootstrap --second-stage chroot /home/nemo/sid/ apt-get clean echo "deb http://http.debian.net/debian sid main" \ >/home/nemo/sid/etc/apt/source.listTo enter the chroot:
ssh nemo@192.168.2.15 devel-su # password mount --bind /proc /home/nemo/sid/proc mount --bind /sys /home/nemo/sid/sys mount --bind /dev /home/nemo/sid/dev mount --bind /dev/pts /home/nemo/sid/dev/pts cp /etc/resolv.conf /home/nemo/sid/etc/ chroot /home/nemo/sid/ apt-get update
Here's a list of my N9 apps that you can now get for free ("deb download" is as of posting this, for new versions visit the webpage or openrepos.net):
- Billboard Standby Screen (web page, deb download, openrepos.net)
- Volume+ As Camera Button (web page, deb download, openrepos.net)
- Headset Camera Button (web page, deb download, openrepos.net)
- Personal Web Server (web page, deb download, openrepos.net)
- Mustr (web page, deb download, openrepos.net)
- gPodder (web page, deb download, openrepos.net)
- qw The Game (web page, openrepos.net)
- Tennix! Redux Demo (web page, deb download, openrepos.net)
- Petals (web page, deb download, openrepos.net)
- Brain Party (web page, openrepos.net)
- Numpty Physics (web page, openrepos.net)
- Plonk (web page, openrepos.net)
- chro.mono (web page, deb download, openrepos.net)
A list of all my apps on OpenRepos.net is also available.
Please note that unless otherwise noted, do not copy the .deb files and distribute them yourself, please always link to the project webpage (the page, not the file) or the openrepos.net page - this makes sure users can always download the latest version and from a known-good source (always be careful when downloading and installing .debs from random webpages). For end users who want to stay up to date and install the packages comfortably, the Warehouse client for OpenRepos.net is recommended.
For some of these apps (not games) that are not open source yet, I plan to clean up and publish the source at some point in the future, so interested developers can have a look, add features and/or port it to new platforms.
If you haven't read last year's article about Python and Qt 5, now might be a good time to do so. PyOtherSide is a much more minimalistic approach to Python bindings, and - in my obviously biased opinion - works better for gluing together a QML UI with a Python backend. In fact, it lends itself to clearly splitting the frontend from the backend, and with the "asynchronous by default" design, you have to work really hard to block your UI thread with long-running Python code (or multithreaded Python code that's waiting for the GIL to be released). PyOtherSide these days is also well-documented, and some early annoyances and bugs have been fixed with recent releases in February. In combination with Qt 5 and Python 3, it works well on OS X, Blackberry 10, Linux, Sailfish OS and Windows. With Qt 5.2 having official support for Android, and a Python 3 port being available, it's only a matter of time before PyOtherSide lands on Android.
For all Sailfish OS users out there: Until the next Sailfish OS update, you might have to install some dependencies before gPodder will correctly start up, these are:
- libpython3 (the Python 3 interpreter)
- python3-base (the Python 3 standard library)
- pyotherside (the Qt 5-Python3 bindings)
If you want to integrate such features into your own app, the code for querying the headset buttons is readily available in the gPodder source tree (src/gpodder/qmlui/helper.py):
import dbus class MediaButtonsHandler(QtCore.QObject): def __init__(self): QtCore.QObject.__init__(self) headset_path = '/org/freedesktop/Hal/devices/computer_logicaldev_input_0' headset_path2 = '/org/freedesktop/Hal/devices/computer_logicaldev_input' system_bus = dbus.SystemBus() system_bus.add_signal_receiver(self.handle_button, 'Condition', 'org.freedesktop.Hal.Device', None, headset_path) system_bus.add_signal_receiver(self.handle_button, 'Condition', 'org.freedesktop.Hal.Device', None, headset_path2) def handle_button(self, signal, button): if signal == 'ButtonPressed': if button in ('play-cd', 'phone'): self.playPressed.emit() elif button == 'pause-cd': self.pausePressed.emit() elif button == 'previous-song': self.previousPressed.emit() elif button == 'next-song': self.nextPressed.emit() playPressed = QtCore.Signal() pausePressed = QtCore.Signal() previousPressed = QtCore.Signal() nextPressed = QtCore.Signal()MediaButtonsHandler is already a QObject subclass, so you can easily expose an instance of this class to your QDeclarativeView rootContext() and connect to the signals in QML (such a "headset button handler" might actually be a good candidate for inclusion into nemo-qml-plugins in Sailfish OS and Nemo Mobile?). As it's really just using the Python D-Bus bindings to get property changes from Hal devices, the code above should be easy (read: trivial) to port from Python to Qt/C++. Be aware that you need to connect to both .../computer_logicaldev_input_0 and .../computer_logicaldev_input, which can both exist if you have a cable headset and a Bluetooth headset connected at the same time.
You can get the Headset Camera App for the N9 in Nokia Store now, there is also a video on YouTube showing the app. Or start integrating headset button features into your own app or scripts by adapting the code above. One use case that comes to mind is using the previous/next buttons on a Bluetooth headset to control a photo slideshow on the N9 connected to TV-Out. Enjoy :)
Petals: A puzzle game written in pure JavaScript and QML The gameplay logic of the game is implemented in pure JavaScript (without any QML dependencies), so it could easily be ported to, say, HTML5, but for integration reasons, QML seemed like the better choice for a release on the N9/Harmattan. Also, writing things in JavaScript wouldn't preclude a console-based frontend using nodejs and node-ncurses from happening should the need arise (making the flowers look good in ASCII art would be the challenge there - or cheating by using libcaca). Ok, ok - stop cursing, I'll stop talking about curses (cue laugh track).
Writing pure QML applications has the advantage of easing porting to Qt 5. While QtQuick 1.1 still exists on Qt 5 (and is the only QML option at the moment if you are also targetting iOS), QtQuick 2.0 is usually the better choice for performance reasons.
In my case, the changes necessary to port from QtQuick 1.1 to QtQuick 2.0 were:
- Change "import QtQuick 1.1" to "import QtQuick 2.0" (sed(1) helps here)
- Instead of assigning a JavaScript function to a property to create a dynamic property binding (item.someprop = function() { return otheritem.otherprop * 3.0; }), this function has to be wrapped in a call to Qt.binding() in Qt 5 (see "Creating Property Bindings from JavaScript" in the Qt 5 docs)
- Instead of using SQL Local Storage directly as in QtQuick 1.1, use QtQuick.LocalStorage 2.0, which you can still do in your .js files - use ".import" as described in this blog post
- In your C++ launcher (in case you need one), QApplication becomes QGuiApplication, and QDeclarativeView becomes QQuickView
- Use "QT += quick qml" instead of "QT += declarative" in your qmake project file
- Fixed MeeCast icon (in 1.0.8, you can already use <<{meecast-icon-src}>>)
- New formatter that allows you to nest {} expressions used for adding dynamic content
- Optional image dithering (using # after the filename) for better colors in low power mode
If you are looking for additional ways to tweak and enhance your Billboard-on-N9 experience, have a look at billboard-scripts, a growing collection of Shell and Python scripts that provide even more ways of customizing your standby screen.
If you haven't purchased Billboard from Nokia Store yet, you can get the current version now for your N9, and get the upgrade to 1.0.9 as soon as it's available. If you are already a happy user, watch your application updates in the next few days, and get the new version.