Wednesday, September 29, 2010

Open or Edit a QML file?

One limitation of doing things based purely on the MIME type of a file is that sometimes things that might be sniffed as C source code are really not. This also comes up with XML files. One solution which feels like adding a level of indirection is having the sniffer say this is XML and what the schema is, or this looks like C source but is really a QML interface. While this blog post presents a libferris oriented solution, I thought I'd syndicate because the core problem is broadly applicable.

Because I tend to want to have the computer do different things for the same mime type depending on where it is located or other metadata, libferris lets you tell it what to do based on any arbitrary predicate, instead of a mimetype == value test.

Like most things, this is setup and edited using... drum roll... a filesystem. The filtered bindings are evaluated before the normal mimetype value tests, and if a filtered binding is found it is used instead of any "generic" mimetype based action.

So, for the Qt SDK, I can have double click run the QML application and middle click open the source in emacs with a setup like the one below. Notice that I restrict the override to only /usr/local/qt URLs so I don't go handing QML files from arbitrary sources to qmlviewer. For those new to libferris the "| ferris-redirect" is like the shell ">" but can operate on any virtual filesystem object directly, without using FUSE etc.


fmkdir mime://filtered-bindings/qt-qml
fmkdir mime://filtered-bindings/qt-qml/actions
echo '(&(url=~file:/*usr/local/qt.*)(name-extension==qml))' \
| ferris-redirect mime://filtered-bindings/qt-qml/ffilter

ftouch mime://filtered-bindings/qt-qml/actions/open
echo -n misc/qmlviewer \
| ferris-redirect -a ferris-appname mime://filtered-bindings/qt-qml/actions/open

ftouch mime://filtered-bindings/qt-qml/actions/edit
echo -n emacs \
| ferris-redirect -a ferris-appname mime://filtered-bindings/qt-qml/actions/edit


These actions are used in the ego file manager as well as from the command line with
$ ferris-file-action -v foourl.qml
to view. Of course, alias fv="ferris-file-action -v" is your friend.

Saturday, September 25, 2010

n900: The claw arrives!

Clawmotia is a MythTV remote control written using Qt and EFL technology. My repository contains a tarball ready to install clawmotia onto an n900. Desktop shortcut optional :)



Simply extract the tarball into /opt on the device. From there, you currently have to install the desktop file yourself to get it onto the menus. Finally, you'll need to edit start-clawmotia.sh to tell the application where your mythtv server is at and which client you want to control through that server. I plan to add dynamic client selection and a user configuration window in the app itself, but I seem to have more plans than the clock allows.

Wednesday, September 22, 2010

Camera to Web the eagle has landed!

Pop quiz, hot shot; an n900 sits before you and something wonderful is happening in the distance. You've love to take advantage of the rear camera and share images of the wonderful event on any flickr API website or some sort of facial book site. What do you do? The camera has all sorts of custom APIs to access it, and the web sites all need some authentication and use REST.

Well, for those who know me, or of me, the answer is quite simple... just "cp" the data from your camera to the Web. And I've now got this working on the n900. I tried the front camera too, but unfortunately it comes out quite underexposed on in house shots.

To read the camera, libferris uses gstreamer. Because there are a whole bunch of ways you might like to read information, frame rates, transcodings etc, you use a file in your ~/.ferris directory to tell libferris how to create virtual files for your input hardware like so:

cat ~/.ferris/gstreamer.xml
<gstreamer>
<capture>
<file name="live.jpg">
<source>
v4l2src num-buffers=1
! videorate ! video/x-raw-yuv,framerate=\(fraction\)3/1
! ffmpegcolorspace ! jpegenc
! appsink name=sink
</source>
</file>
</capture>
</gstreamer>


Those with a keen eye will notice that the live.jpg is generated with the same thing you can use in gst-launch to create a jpeg image. The final element is an appsink which is where libferris gets the bytes from. I made that last element explicit because you can tee the data in gstreamer and do other things to have multiple end points.

Then to take a photo and put it up on the net:


$ fcat gstreamer://capture/live.jpg >| /Card/tmp/out.jpg
$ ferriscp gstreamer://capture/live.jpg 23hq://monkeyiq/upload


Of course, the fcat line above hints that you can use ssh to grab an image from the n900 to your laptop or server and upload it from there. See the ferris-capplet-auth for how to authenticate with the web sites and also how to have libferris scale before upload (optional) and what privacy settings to add during upload.

Next up is using the vimeo and youtube mounting in libferris to stream video to the net.

Monday, September 20, 2010

n900 goodies: unison, gphoto, working soprano, libferris, sixdof, coreutils, xerces3 et al

Some goodies for the n900 are now in my repository. Yes, I know it's evil to have my own, but if that's all it takes to be George Thorogood then so be it. In the at the aforementioned link you will find unison, gphoto, stldb4, libferris, ocaml, a compiled install of coreutils to avoid battling busybox, xercesc, xalanc, xqilla, and a (more) working soprano.

I'm a tad surprised that unison hasn't made its way into the main repositories yet. I can't imagine that outsiders like me are the only ones who use it or want to. If you follow the "only one me" assumption then unison works well for providing bidirectional data syncing. I have compiled unison without a GUI under the assumption that you will be starting the process from the laptop or other more endowed machine. Although unison is written in ocaml, you shouldn't need to install that to get the unison package going.

The coreutils is just a compile and DESTDIR install wrapped up into a tarball. Shove them into /opt somewhere and prepend them to your path and magically df -lh and other normal commands work again.

I have ported libferris to xercesc3 finally, so I had to package that for maemo5 too. Which explains the xml packages. I put xalanc and xqilla there too so I can play around with xsltfs:// and XQuery on the device. It's powerful enough for these things so why not do them ;)

Once I installed libferris on the device I discovered a strange crash. Long story short, the soprano on the device was using redland as it's backend, and redland was defaulting to using its hashes backend (Berkeley db) which wasn't available. So the current soprano works only with memory models it seems. Though support for sqlite is compiled into redland it isn't the default for soprano persistent storage. What is stranger is that db4.2 was already on my n900. So all of this could have gone away if redland was compiled with db4 support (which happens automatically when the db4-dev package is installed before compiling redland). To see if your redland will work with db4 run these on your n900... The first works if SQLite is supported, the second will fail if you do not have berkeley db4 support compiled. The redland (librdf) from my repository uses libdb4.2 on the device to enable the second command to work properly.


$ rdfproc -s sqlite myrdf add \
'http://witme.sf.net/libferris-core/0.1/myrdf-so2p.db' \
'http://witme.sf.net/libferris-core/0.1/start' \
'http://witme.sf.net/libferris-core/0.1/base'
rdfproc: added triple to the graph

$ rdfproc -s hashes myrdf add \
'http://witme.sf.net/libferris-core/0.1/myrdf-so2p.db' \
'http://witme.sf.net/libferris-core/0.1/start' \
'http://witme.sf.net/libferris-core/0.1/base'
rdfproc: added triple to the graph


So now the fun part starts, using libferris to "copy" images from the camera to flickr, mounting the sqlite databases on the device as filesystems, gluing the geolocations markers to those created on the desktop and other data/filesystem games.

Wednesday, September 15, 2010

n900: The new device!

Last week I got a wonderful surprise in the mail, a tasty new n900! The package "from" lists Quim Gil as the sender, so its come directly from half way around the world. Thanks Quim! And now for my initial thoughts and investigations; some of this will be of no surprise to existing owners, some of it was of some surprise to me. Oh, before I begin and loose folks to the down arrow key, anyone know of plasma packages for the n900? I'd like to port my abomination australian weather plasmoids over for mobile use.

Firstly, the device feels much faster than the n810. I'm not sure how much of this to attribute to the 50% faster clock of the CPU, the new GPU, differences in the ARM core itself or differences in software stack optimizations.

I should mention that during installation I found a few warts and issues here and there. Overall I really like the device, please don't consider the following criticisms as my only thoughts on the device, but given a limited amount of time with it so far, these bumps are still on my mind. Good points and comments about libferris on the n900, efl apps, accelerometer fun, and other hacking will likely follow once I get scratchbox up and running in a 32bit ubuntu vm.

As a filesystem guy I noticed a few rather nasty warts off the bat. A little constructive criticism for the new device?

Firstly that MyDocs is vfat, which I discovered when trying a good old ln(1) invocation. This is fairly easy to fix, and its now an ext4 filesystem. Soft links aside, the shared map tile cache gets put into ~/MyDocs/.maps by default, and I've seen some reports of bad internal fragmentation arising if that has remained vfat.

The temptation for btrfs was of course there, but for now MyDocs and /MemoryCard are ext4. That brings up the second thing I noticed, plugging in a new sdhc card, it was mounted and offered right off the bat. But if you mkfs.ext3 on that card (and change it to the right part type), the n900 doesn't want to know about it. There are fixes for this, mainly hacking /usr/sbin/mmc-mount to accept partition type 83 (Linux) and mount it "auto".

If you start hacking with partitions and whatnot, make sure you peek at and probably mangle /usr/lib/genfstab.awk to be smarter. I'm not sure using awk for creating /etc/fstab is a gain here. Especially inferring /home and ~/MyDocs based on partition type. Filesystem labels might be a wiser choice if lvm is not sought. I mention this because I managed to get the device into an endless reboot cycle which I suspect is due to it not finding the right filesystems early in the boot. As /opt is on /home and stuff gets shoved into /opt to save space on / (which is /usr too) then not finding /home might have some negative impact during boot.

For now I just made a more solid entry for /home and ~/MyDocs in the BEGIN block. Device boots up fine, is vfat partitionless and has goodness of ext3 and ext4 filesystens.

I then spent a bunch of time getting syncevolution to be happy. The result is I now have contacts and events from desktop, laptop, e71, and n900 all syncing. The issue that frustrated me was that the n900 was dropping timezone info and just calling imported events GMT. Of course this winds up shifting events in the calendar off by your UTC offset. For now, forcing syncevolution to use the older text/x-vcalendar format to hand to the n900 works around this issue. But it took at while to find that one out. Thanks to the syncevolution guys for their quick responses to my bug report. To get things clean, I need to move the report to the respective software that handles the data that syncevolution offers the n900.

I have KOffice installed on the n900 and abiword. The former brings RDF to the device and the later will soon join its ranks. Rich RDF cut and paste anyone? There are some very interesting possibilities using office documents, RDF and an Internet connected device when on the move. But I need to get some more lines of C++ out of my head and into my emacs before I can show them in action.

Wednesday, September 8, 2010

Metadata extraction and segv

This is a post about metadata extraction from files for desktop search. While it applies specifically to libferris, the same considerations apply to anything which trawls an entire filesystem looking to create a rich index of metadata to allow desktop search to run queries in a reasonable timeframe. Ferris runs fine on KDE and the n810 (soon n900?) so its applicable to both syndications in a way.

Back in January 2008 I released a version of libferris which allowed metadata extraction to be performed out of process. While this obviously means some context switching is added, it is not necessarily slower for it. It will likely be slower on a single core ARM chip, but on a four or more core desktop the processes can run in parallel and so might actually be faster for it.

I recently tinkered with this, moving to using QT for DBus inter process communications and activation. The design uses a worker interface which has simple get/set methods which take the URL and name of the metadata to fetch and return the data. The set also takes the new value to set.

There is a broker which sits between the client and the worker and provides an async interface and also allows more than one worker to be spawned and controlled without the client needing to worry or care about this. The broker has asyncGet which takes the same URL and metadata name, and returns a numeric ID for this request. A signal is then fired either for success (with value) or failure (without). A failure might occur when the file at the URL is corrupted and the library used to inspect it for the metadata crashed. This is of course recorded so it doesn't constantly happen for that file.

The upshot is that I can use libferris to view a directory and if the xine metadata plugin crashes, the file manager stays around and only the background dbus worker process crashes. This is not to pick on Xine, which is a great project, but if hacking on libferris has told me anything it is that there is always a file on the drive which has some bytes in a strange way that is unexpected.

Perhaps more interesting than the file manager, the file indexer can trawl through everything and will not itself crash when a strange invalid file causes a segv in metadata extraction. So partially downloaded (and failed) content in my ~/FromInternet folder will not halt the indexing process with a segv.

Using DBus with a simple interface like that also allows new metadata extractors to be shared more easily. It doesn't matter if Strigi, Tracker, Beagle, or Indexer Foo use C++, Qt, mono, perl or whatever, as long as they can offer two methods on DBus. Though some factory/activation stuff is also needed to let the indexers and projects know that metadata these plugins can handle.

For those who haven't hit the pagedown by now, the interfaces are in
DBusGlue/ferris_internal_metadata_broker_introspect.xml
and worker_introspect.xml in the upcoming release of libferris (ie, the one that will happen in the next week or so when I get a moment). The DBus processes live in the apps/metadataserver of the libferris tarball.

The broker interface looks like this:

<method name="asyncGet">
<arg type="s" name="earl" direction="in"/>
<arg type="s" name="name" direction="in"/>
<arg type="i" name="reqid" direction="out"/>
</method>

<signal name="asyncGetResult">
<arg type="i" name="reqid" />
<arg type="s" name="earl" />
<arg type="s" name="name" />
<arg type="ay" name="value" />
</signal>

<signal name="asyncGetFailed">
<arg type="i" name="reqid" />
<arg type="s" name="earl" />
<arg type="i" name="eno" />
<arg type="s" name="ename" />
<arg type="s" name="edesc" />
</signal>