Another Small Package Release

After releasing the first nepomuktvnamer package here comes the first release of the previously presented Nepomuk Music KIO slave.

Like the tvnamer you can get it from download.kde.org mirrors in the unstable/nepomuk folder.

Advertisements

Season Posters Anyone?

I simply cannot stop playing around with TV Shows and Nepomuk. We already had posters for the series but not for the seasons. Well, we do now:

Fun, isnt’ it? But sadly it required an improved libtvdb and additions to SDO. The former is already in git master. But the SDO changes are a bit experimental. That is why I put them into branch nmm/banners. Also due to both these requirements not being that easy to install I put the improved season handling of nepomuktvnamer into branch seasonResources.

So in order to try this yourself you need to get libtvdb git master and the mentioned branches of SDO and nepomuktvnamer. But do not worry, I am pretty sure that I will get the SDO changes merged soon. Then this will become easier.

A Fun Release: Nepomuk TV Namer 0.2

As requested I prepared a release of the TV Show managing thingi I implemented. You can download it from download.kde.org mirrors at unstable/nepomuk/nepomuktvnamer-0.2.0.tar.bz2.

The nepomuktvnamer 0.2.0 is a little more polished than the original version and comes with a nice service menu extension allowing to manually start the fetching of TV Show information on folders or video files. This is important since the service does only react on new videos. So you need to start the initial information fetching manually on your TV Show folder.

The tvnamer has two requirements in addition to the typical KDE ones:

  • LibTVDb – LibTvdb is a Qt-based library which provides asynchronous access to TV series information from thetvdb.com via a very simple interface. Its use in the Nepomuk TV namer should be obvious.
  • Shared-Desktop-Ontologies 0.9.0 – The recently released new version of SDO provides the required nfo:depiction property used by the tvnamer to store banners.

I also recommend to apply the kdelibs patch I mentioned earlier to actually see the TV Show banners. Have fun with it – maybe someone will even package it.

Just For The Fun Of It: Browsing Music With Nepomuk

Since implementing the TV Show KIO slave was that easy I decided I could do the same for music – just to show how simple it can be. There a a few more lines but that is only because I added browsing by album, artist, and genre. So there are a lot of if/else constructs. Anyway, here goes:

Browsing music by artist is easy. As you can see I also implemented a preview generator plugin the same way I did for the TV Shows. The only problem is that there is no tool yet that automatically fetches those images. Thus, I had to do it manually for one example which looks somewhat like this:

qdbus org.kde.NepomukStorage 
  /datamanagement
  org.kde.nepomuk.DataManagement.addProperty
  "nepomuk:/res/0152825f-5c49-4ca8-aa0a-23fc9a1305f1"
  "nfo:depiction"
  "/home/trueg/atb2.jpg"
  "shell"

This is part of the fancy Data management API which allows me to add the file atb2.jg as a nfo:depiction of the nco:Contact resource identifying the artist ATB.

Anyway, entering the artist themselves and what lies beyond:

(Again I had to fetch the cover art manually. I did not want to implement my own cover art retrieval tool and I found the Amarok code not to be very reusable. Again maybe someone wants to take up this task?)

Finally we end up in the album tracks. Sadly dragging an album to a media player playlist does not work yet. I am not quite sure how to fix that.

Last but not least a quick look at browsing by genre:

This was fun. But before I go to bed let me share with you the very simple code which is responsible for the nice previews (abbreviated of course):

bool MusicThumbCreator::create(const QString &path,
                               int w, int h,
                               QImage &img)
{
  KUrl url(path);
  QStringList pathTokens
      = url.path().split('/', QString::SkipEmptyParts);
  if(pathTokens.count() < 2) {
    return false;
  }

  // there are only two cases for us: artists and albums
  if(pathTokens[pathTokens.count()-2] == QLatin1String("artists") ||
     pathTokens[pathTokens.count()-2] == QLatin1String("albums")) {
      const QUrl uri = recoverUriFromUrlToken(pathTokens.last());
    // we just query the first depiction there is
    Soprano::QueryResultIterator it
       = Nepomuk::ResourceManager::instance()->mainModel()
         ->executeQuery(
              QString::fromLatin1("select ?u where { "
                                  "%1 nfo:depiction [ nie:url ?u ] . "
                                  "} LIMIT 1")
              .arg(Soprano::Node::resourceToN3(uri)),
              Soprano::Query::QueryLanguageSparql);
    if(it.next()) {
      img.load(it["u"].uri().toLocalFile());
      return true;
    }
  }

  return false;
}

The rest of the code can be found in the nepomuk-audio-kio-slave scratch repository. Maybe at some point I could just throw all of those things into some “Nepomuk KIO extensions” package… oh, well, off to bed now…

Nepomuk Frameworks – kdelibs 5.0: What To Do

Development of kdelibs 5.0 has begun in the framework branch of its git repository. The main goal for kdelibs 5.0 is that there will be no more kdelibs as it is now. kdelibs (and kde-runtime) will be split up into smaller pieces to lower the barrier for non-KDE developers to use part of the power we as a KDE development community provide. The rough idea is that there will be three groups of libraries/frameworks:

  1. Tier 1: components which only depend on Qt and no other lib/component from KDE.
  2. Tier 2: components which depend on Qt and other libraries from Tier 1.
  3. Tier 3: components which depend on anything.

This of course includes Nepomuk and is a great opportunity for us to reorganize code and get rid of deprecated junk we needed to keep around for binary compatibility.

To this end we had two meetings on IRC this week to discuss how we want to proceed for KDE frameworks. It was a lot of fun (at least for me), mostly because it was rather easy to reach good decisions and fun to radically kick stuff that has been bugging us for a long time. The result is documented in a wiki page but let me summarize the basics again:

We will have four new git repositories:

  1. nepomuk-core – The main Nepomuk repository which is required in any case and provides the basic Nepomuk functionality including storage, query, and the like. I already began work on this in a nepomuk-core scratch repo. This repository will contain:

    • Nepomukserver
    • nepomukservicestub
    • Extension ontologies
    • Core services: Storage/DMS, Query service, Filewatch service, File indexer
    • Core library: the current libnepomuk including Nepomuk::Resource and Nepomuk::Types, libnepomukquery, and libnepomukdatamanagement
  2. nepomuk-ui – A repository containing Nepomuk UI extensions. For starters this will contain:

    • SearchLineEdit and SearchWidget
    • KFileMetaDataWidget which is currently living in KIO
  3. nepomuk-kde-kio – A KIO Nepomuk extension repository which contains the KIO slaves we currently provide in kde-runtime:

    • nepomuksearch – General purpose queries
    • timeline – browse files by date
    • nepomuk – a simple kio slave which allows browsing of Nepomuk resources via HTML pages
  4. nepomuk-kde-config-ui – The repository for Nepomuk configuration extensions based on KDE technology. It contains:
    • nepomukcontroller
    • Nepomuk KCM

We feel this gives a clean separation and will actually urge packagers to not split those repositories up any further.

Apart from that we decided a few more things – which API to drop, some internals, how to get rid of Soprano::Model in the Nepomuk API altogether, and so on. Actually I am very happy to soon have dedicated Nepomuk repositories as that will make development easier.

And BTW: kde-runtime/nepomuk master is frozen for commits. Development already moved to the new nepomuk-core repository.

Files on Removable Media – Step 1

So far Nepomuk only handled annotations for local files and did not care about mount points and the like. With KDE SC 4.4 that is about to change. (What I present here today is the first step in supporting removable media like USB keys or external hard drives. The next step will have to wait until 4.5.)

As always my blog will have two parts: the user visible one and the technical one which discusses implementation details.

Imagine you had a USB key with a file on it which you annotated, say with a rating of 6:

As long as the key is mounted searching for files with a rating of 6 will always return our image the way we know it:

But now we unmount the key. Thus, the file will not be accessible anymore. But the file still shows up in the search:

However, there is a slight change in the name: now it contains a hint to the USB key (this hint did not make it into 4.4). Opening the file still works since the key is automatically mounted.

But what happens if we remove the key completely and thus, auto-mounting is not an option anymore? Well, the search does still return the file but trying to open it gives us an error. Well, Gwenview does not handle KIO errors properly, thus we do not get an error message. But in theory we would get the message “Please insert the removable medium ‘1,9 GiB Removable Media’ to access this file.”. Just to show that I am not lying let me present the Okular error dialog (which could use some improvement, too):

Here you see the whole ugly Nepomuk query URL and all at the bottom the unformatted error message. Hopefully in KDE SC 4.5 we will have worked out these problems.

So if we would see this error message we would know where to find the file if we want to access it (well, giving proper names to USB keys would help, too).

This is already pretty nice. Step 2 will then be to export the annotations to the removable storage and sync them again as soon as the medium is mounted (remember how I blogged about my experiments with that already? Well, as you can see I did not get that finished, yet.)

The Technical Part

OK, now we know how it looks to the user (or how it should look). Let us have a look under the hood. Basically three players are involved in this process:

The removable storage service

The removable storage service (code in kdebase) uses the great power of Solid to act on newly inserted, mounted, and unmounted removable storage devices. The simple part is that it tells the Strigi service to index the files on the device on mount.

More interesting, however, is what happens on unmount. The service converts all absolute URLs of files on the unmounted device to relative ones. These relative URLs use the filex:/ scheme I made up and consist of two part: the UUID of the storage device and the relative path. In our example above the URL is filex://fc30-3da9/thepic.JPG. In addition a new nfo:Filesystem resource is created storing the description and the UUID of the unmounted device. The files are then related to this new nfo:Filesystem resource via nie:isPartOf.

libnepomuk

Nepomuk::Resource can now transparently handle relative filex:/ URLs. Thus, annotating the file in the example after remounting will store the annotations with the same resource although that uses a filex:/ URL.

The nepomuk:/ KIO slave

The nepomuk:/ KIO slave (code in kdebase) does the rest of the work. The nepomuksearch:/ KIO slave creates the virtual query folders but uses the nepomuk:/ KIO slave to stat all resources (at least the ones with a nepomuk:/ scheme URI).

So as soon as a relative filex:/ URL is encountered it is converted to a local URL if possible:

Solid::StorageAccess* storageFromUUID( const QString& uuid ) {
    QString solidQuery = QString::fromLatin1( "[ StorageVolume.usage=='FileSystem' AND StorageVolume.uuid=='%1' ]" ).arg( uuid.toLower() );
    QList<Solid::Device> devices = Solid::Device::listFromQuery( solidQuery );
    if ( !devices.isEmpty() )
        return devices.first().as<Solid::StorageAccess>();
    else
        return 0;
}

KUrl convertRemovableMediaFileUrl( const KUrl& url, bool evenMountIfNecessary = false ) {
    Solid::StorageAccess* storage = storageFromUUID( url.host() );
    if ( storage &&
         ( storage->isAccessible() ||
           ( evenMountIfNecessary && mountAndWait( storage ) ) ) ) {
        return storage->filePath() + QLatin1String( "/" ) + url.path();
    }
    else {
        return KUrl();
    }
}

And here you can already see the auto-mounting code being called. (I do not show it here since this is enough to read already. If you are interested have a look at the full source code.) The converted URL is then simply passed to KIO::ForwardingSlaveBase which handles the rest. In case the URL cannot be converted (the medium is not mounted and auto-mounting is not used) all information is read from the Nepomuk database to create a proper KIO::UDSEntry.

Just another way of browsing your files

The Zeitgeist guys created a fuse file system called zeitgeistfs. It is basically a calendar containing the files accessed at that specific date. So at the Akonadi meeting last weekend, having two hours to kill, I thought that should be doable with KIO. So two hours later (most of that time was spent twiddling with UDS entries) the timeline:/ KIO slave was up and running:

The code that actually does something is minimal: a bit of UDS entry creation for dates and a simple SPARQL query to forward to the nepomuksearch KIO slave. Yes, it is as easy as that since we can simply set the UDS_URL property of an item to a nepomuksearch URL and KIO will take care of the rest. Smooth. Thanks a lot David Faure. Once again you paved the way.

OK then. Try it if you like. This is just another example of what can be done with Nepomuk (no real semantics here though). The code is in the playground as always and is based on the current kdebase trunk. So with KDE 4.3 this baby won’t work. And of course as this is based on file meta data, the Nepomuk Strigi integration has to be enabled.