Glamońćanin.net

About

Stuff i did

Welcome to glamocanin.net

Here you will find the "blog" of Slavko Glamocanin. The main purpose of this page is to promote my music, me as a technical person and me as a thinker.

You can find me on facebook for a more personal contact, or on twitter.

Most of the content is in english, but i did not bother to translate from my native slovene language, or setup a dual language page.

Android game development with SDL2 - a summary

23.06.2014

I've been using SDL for a while and decided to create an openGL ES2 based toy on android.

As the process was not as nearly as straightforward as it could have been i've decided to write it down and maybe it can help somebody else too.

Getting started

So to start you need the android SDK - the ADT bundle - i got the 20140321 version and the android NDK - native development kit, because we mean business:)

You also need SDL2, i used the latest, 2.0.3

The idea is to use the Native C++ interface through JNI (java native interface) to start in the java world and immediately go a level below it to the native world with c++. That's where the fun is:) SDL will take care of all the bindings for us and leave us with the well thought out SDL api.

Start with the basic android project packaged with SDL (/android-project/), copy it to your workspace. Then copy or symlink the SDL directory to the project's jni folder (the idea is to have /jni/SDL/include structure)

The Android SDK

Download an SDK platform for api version 16 (or higher) and i would also recommend an emulator because they work really well. The x86 version because you will probably have an x86 machine and that should reduce the virtualization overhead. Fun fact, android compiles native code for three platforms (arm, even more arm and x86) and includes them all in the .apk. It's a fat apk:)

Run the ADT eclipse based development environment. I would recommend it because of the easy signing and running of the app on the emulation (otherwise it kinda sucks:). Add the project to your workspace and right click it, find android tools and a native nature to the project. 

In the jni/ folder you now have SDL and src, put your main.cpp file into the src folder. Fix android.mk from "yoursourcefilehere" to "main.cpp" to compile your file.

I stumbled across a horrible eclipse bug, its c++ indexer decided that it could not resolve the SDL function even if the ndk-build command ran fine. So i had to DISABLE the unresolved function error in eclipse's c++ indexer. That removed the error and enabled a slick transition from change code -> upload to emulator -> run.

So there you have it, a working empty SDL project running on android:) I came across a lot of small obstacles so i hope this eases the process for you.

Also i have a BlackBerry Z10 so you can image i made the process even more complex by connecting directly to my blackberry (which runs .apk's yaay!) but that's for another article:) 

The Basic Project

I took the android-project that ships with SDL and added a basic main.cpp file that took me some time to get together from different sources. Disinformation on the internet, go figure:)

Here it is!

This main.cpp creates a window and an OpenGL ES2 context. Sound is also started with a basic function handling it. Usually i make a basic handling object for audio and video rendering, then pass it to this basic function:

class BasicScript
{
public:
    BasicScript();    
	virtual void processAudio(unsigned char* stream, unsigned int len) {}
    virtual void initialize() {}
    virtual void initializeGL() {}
    virtual void paintGL() {}
    virtual void animate() {}
    virtual bool keyUp() { return false; }
    virtual bool keyDown() { return false; }
    virtual bool keyPress() { return false; }
    virtual bool event(int eventtype, const TouchEventInfo *tei) { return false; }
    virtual int resize(int width, int height) {
        windowWidth = width; windowHeight = height;
        renderableWidth = width; renderableHeight = height;
		screenRatio = 1;
		if( renderableHeight != 0 ) screenRatio = (float)renderableWidth/renderableHeight;
		if( windowHeight != 0 ) screenRatio = (float)windowWidth / windowHeight;
        return 0;
    }
	virtual bool isQuit() { return false; }
    char* readfile(const char filename, unsigned);
	virtual float getAnimateInterval() { return 1000.0/30; }
protected:
    int renderableWidth;
    int renderableHeight;
    int windowWidth;
    int windowHeight;
	float screenRatio;
};

Using this template i can create anything i want within this, then easily port it to different system just by calling the appropriate functions at the right time.

The Final Development Environment

ADT seems nice, but for actual development i will use pure SDL on the desktop giving me the same environment for the code and capability to use any IDE i want to develop it. I love KDevelop and it was easy to set the project up with cmake and start coding. I actually created the files in android-project/jni/src/ and symlinked it to the kdevelop project:) So now i can develop in the comfort and the debug mode of the desktop, then just compile and run the APK on the emulator when i need to test it. Good times:)

Chromium's (chrome) helvetica font issues

01.03.2014

I am a linux user and so i'm used to things breaking. This time it was the web browser Chromium's turn.

Helvetica fonts were displayed horiffically, like they were being render at 4pt and upscaled to 24pt (that 8-bit look:).

After getting familiar with fontconfig I used "fc-match Helvetica" to discover which font file was actually used. Turns out I had some bitmap fonts (.pcf) installed - adobe-fonts (??) and they were scaled beyond all sanity:) 

I removed those fonts (not caring if any proprietary program needed them;) which enabled some pretty good looking alternatives.

Well another day in linux world passes and here's something for you googlers that i couldn't find elsewhere.. a fix.

Signing BlackBerry BAR files for publishing to the AppWorld

20.01.2013

Using the command line tools:
blackberry-signer -verbose -storepass [your store pass] [your bar file name] RDK
blackberry-signer -verbose -storepass [your store pass] [your bar file name] author

After signing you can verify your BAR file with:
blackberry-signer -verbose -verify [your bar file name]

Everything except:
META-INF/MANIFEST.MF
META-INF/AUTHOR.SF
META-INF/AUTHOR.EC
META-INF/RDK.SF
META-INF/RDK.EC

should be prefixed with "sm", which means that the entry is listed in the manifest and signed properly. The AUTHOR.* files are author signatures and the RDK.* are RIM's signatures. You need both:)

The problem i encountered was that the BAR packager (marmalade sdk in my case) left the actual directories inside the zip file.
They are seperate from files and can be removed without removing the files in them and you should do it with:
zip -d SolidDefence.bar META-INF/ native/

Don't forget to add all the directories you have in your zip file to this list, otherwise you will encounter cryptic error messages minutes before the deadline:)

This will solve the "Error: Some files are missing signatures" problem reported by verify and AppWorld:)

For more common signing errors check here: http://developer.blackberry.com/native/documentation/bb10/com.qnx.doc.native_sdk.devguide/com.qnx.doc.native_sdk.devguide/topic/app_signing_errors.html

Now go develop! 
https://developer.blackberry.com/

Bring MidiSport keyboards to life with udev and fxload on linux

25.12.2012

I'm on of those linux users who likes to tinker, and boy do i get the opportunities:)

Things change all the time, specifications, parameters, the way things work, and one of those things is how udev activates USB devices that need custom firmware loading.

For my M-audio Oxygen8 keyboard i need to run "fxload" with the firmware and usb device parameter before it starts working normally. Years ago i snatched an ubuntu targeted udev script for that, just create the file /etc/udev/rules.d/99-midisport-firmware.rules with this content:

# midisport-firmware.rules - udev rules for loading firmware into MidiSport devices

# DEVPATH=="/*.0" selects interface 0 only
# (some udev versions don't work with SYSFS{bInterfaceNumber})

# MidiSport 2x2
ACTION=="add", SUBSYSTEM=="usb", DEVPATH=="/*.0", ENV{PRODUCT}=="763/1001/*", RUN+="/sbin/fxload -s /usr/local/share/usb/maudio/MidiSportLoader.ihx -I /usr/local/share/usb/maudio/MidiSport2x2.ihx"
# MidiSport 1x1
ACTION=="add", SUBSYSTEM=="usb", DEVPATH=="/*.0", ENV{PRODUCT}=="763/1010/*", RUN+="/sbin/fxload -s /usr/local/share/usb/maudio/MidiSportLoader.ihx -I /usr/local/share/usb/maudio/MidiSport1x1.ihx"
# KeyStation
#ACTION=="add", SUBSYSTEM=="usb", DEVPATH=="/*.0", ENV{PRODUCT}=="763/1014/*", RUN+="/sbin/fxload -s /lib/firmware/MidiSportLoader.ihx -I /lib/firmware/MidiSportKS.ihx"
# MidiSport 4x4
ACTION=="add", SUBSYSTEM=="usb", DEVPATH=="/*.0", ENV{PRODUCT}=="763/1020/*", RUN+="/sbin/fxload -s /usr/local/share/usb/maudio/MidiSportLoader.ihx -I /usr/local/share/usb/maudio/MidiSport4x4.ihx"
# MidiSport 8x8
ACTION=="add", SUBSYSTEM=="usb", DEVPATH=="/*.0", ENV{PRODUCT}=="763/1031/110", RUN+="/sbin/fxload -s /usr/local/share/usb/maudio/MidiSportLoader.ihx -I /usr/local/share/usb/maudio/MidiSport8x8-2.10.ihx"
ACTION=="add", SUBSYSTEM=="usb", DEVPATH=="/*.0", ENV{PRODUCT}=="763/1031/121", RUN+="/sbin/fxload -s /usr/local/share/usb/maudio/MidiSportLoader.ihx -I /usr/local/share/usb/maudio/MidiSport8x8-2.21.ihx"

Great, it worked! 

But I use gentoo and a couple of udev upgrades later... it stopped:|

After debugging i discovered that fxload was not getting it's parameter for the device path. The fix is kind of simple, change all run lines to add " -D /dev/%P", like this: 
ACTION=="add", SUBSYSTEM=="usb", DEVPATH=="/*.0", ENV{PRODUCT}=="763/1014/*", RUN+="/sbin/fxload -s /lib/firmware/MidiSportLoader.ihx -I /lib/firmware/MidiSportKS.ihx -D /dev/%P"

Also, check the location of the firmware files, this is where we gentooers have them.

Have fun using your M-Audio gear:)

UDPXY + RaspberryPi - rp_filter = TV bridge

24.12.2012

My internet/tv provider uses multicast UDP to bring me my TV signal and usually has some shitty set top box connected with a variety of scart, video and whatever connectors. 

No TVs in my house just monitors, so I decided to use VLC. Downloaded a playlist with the IPs and everything worked nicely but i found that my switches are not smart enough to route multicast traffic and they just pollute the whole network with the IGMP data. (and a 700k+ bandwidth waste on wireless kinda kills it)

Finally i found a nice little utility called udpxy, which creates a TCP server from the multicast UDP data. And being connected via VDSL1, the TV network was separate from the internet network (and also its DHCP server broadcasted shit to my internal network before this solution), so i decided to make a bridge using the RaspberryPi.

I adjusted the playlist from udp://@111.222.33.44:5000 to tcp://[address of the rpi]:4022/udp/111.222.33.44:5000 and the player was set.

Bought a usb->ethernet dongle, which was a lovely case of plug and play (man i love linux, just the next day i plugged a mouse into a windows notebook and was confronted with a driver dialog... yay:D) and the thing was ready to go!!

But not really:) This project was on hold for a couple of months, because the data just wasn't coming through. After a lot of experimenting i found that the "rp_filter" functionality of the kernel is causing problems.

It is meant to keep the packets that obviously don't belong on your network, out. The problem is that the multicast traffic is such an example of a "martian", because the data received is from a different subnet than what the TVs dhcp server assigns you.

So after disabling the rp_filter (echo '0' > to the relevant interfaces in /proc/sys/net/ipv4/conf/*/rp_filter), the traffic started flowing and the system was ready!

I used gentoo as a base image (yes i know i'm a ricer:), so i just installed udpxy, configured the kernel and set everything up as an appliance... after power-on everything is automagically configured.

So here is the little thing between my router and the VDSL modem. In a hastily cut cardboard box:)