Monday, June 30, 2014

GSoC Report #2

Previously I wrote about an application, which allows you to find metadata tags using audio file fingerprint. This application was written in C#, and required some minor fixes.

Rewriting standalone application in F#
So that's what I've done during last week; I fixed minor bugs (e.g. some fields in JSON file were optional), and the most important: rewrote application in F#. From now on, I'm not writing in C# during GSoC no more :)

Implemented AcoustID in a Banshee's plugin
Afterwards, I've finally implemented AcoustID support in Banshee! Now you can get any audio file form your disk, and find metadata of it. For now my plug-in supports only finding track Artist and Title fields, but I hope, the rest of them will be done and available in the nearest future.

Plugin based on fingerprints in Metadata Fixer

Caching AcoustID results
Fingerprint computation is a long process (approximately 5 seconds per file), so calculated fingerprints are stored in a cache directory. It allows to use results in the future.
Fingerprints are saved in a files, where filename is a hash of track URI and size of file.

Computing fingerprints in a background
Moreover, I also started to implement mechanism, which computes fingerprints in a background, so user don't have to waste his time on a waiting for fingerprints. It's working now, but I didn't test it too much, and probably it requires still a lot of work.

Empty album's names fixer improvements
However, I improved a little MetadataFixer plugin by adding another column to a main view: Track Info. It was useful in my plugin, and might be also used in the future. Plugin's author can decide, whether this column should be available (by overriding specific method), and what should be there displayed (e.g. file URI or track title).

Track Info column in Metadata Fixer plugin

Wednesday, June 25, 2014

Amazing (FSharp.Data) Data Access Library for F#

Last few days I spent on a working with data stored in JSON and XML files. I tried to download a file with audio metadata (e.g. [1]), and get some useful informations about a track (e.g. recording's author or release types). My GSoC's mentor, Andrés G. Aragoneses, recomended me an amazing library for this purpose; FSSharp.Data [2].

A Few Words About FSharp.Data

FSharp.Data is a library, which allows you work with data in a simple and convenience way. It offers to user easy access to particular elements of JSON, XML and CSV's through defined in the library providers. It supports also WorldBank and Freebase services.

Example code

An aim of code shown below is to parse simple JSON data (defined as a data) and displays it on a screen.
open FSharp.Data
type Vehicles = JsonProvider<""" 
[
    {
    "type" : "some-type", 
    "year" : 2000, 
    "photos": [
        {
        "location" : "some-location"
        }
    ]
    }
] """>

let data = """ 
[
    {
    "type" : "car", 
    "year" : 2005, 
    "photos": [
        {
        "location" : "img_001.jpg"
        },
        {
        "location" : "img_002.jpg"
        }
    ]
    },
    {
    "type" : "bike", 
    "year" : 2014, 
    "photos": [
        {
        "location" : "my_bike.jpg"
        }
    ]
    }
] """

let parse =
    let records = Vehicles.Parse(data);
    for vehicle in records do
        printfn "Type: %s" vehicle.Type
        printfn "Year: %i" vehicle.Year
        printfn "Photos: "
        for photo in vehicle.Photos do
            printfn "\t * %s" photo.Location
At the beginning, there is generation of a type(Vehicles) by parameterizing JsonProvider using one parameter - string. This parameter is a sample JSON data which has the same structure as another documents (which will be parsed using this type in the future) or a file contains JSON data. Type exposes properties (in a PascalCase) according to a nodes defined in a JSON sample data. Result:
loganek@loganek-cmp ~$ ./vehicles.exe 
Type: car
Year: 2005
Photos: 
  * img_001.jpg
  * img_002.jpg
Type: bike
Year: 2014
Photos: 
  * my_bike.jpg
loganek@loganek-cmp ~$ 

Follow the link [3] for more informations about JsonProvider.

Dynamic loading JSon data structure

In an example shown above JSON's data structure was known in compile-time. Usually we knows, what kind of document will be passed to our application, and there's no need to dynamic loading structure description. But there's a few situations (e.g. XML <-> JSON file converter), where structure is known only in runtime. In that case, JsonExtensions [4] (or CsvExtensions [5], depends on a data) might be used.
That's less convenient and less efficient way, and if it's possible, providers should be used instead of it.

Suggestions in MonoDevelop

The most amazing thing, which I discovered during work with FSharp.Data, is that, MonoDevelop suggest property's names (even with their types). Little thing, but made me happy :)



Links
[1] http://api.acoustid.org/v2/lookup?client=8XaBELgH&meta=recordings+releasegroups&trackid=9ff43b6a-4f16-427c-93c2-92307ca505e0
[2] http://fsharp.github.io/FSharp.Data/
[3] http://fsharp.github.io/FSharp.Data/library/JsonProvider.html
[4] http://fsharp.github.io/FSharp.Data/library/JsonValue.html 
[5] http://fsharp.github.io/FSharp.Data/library/CsvFile.html


Saturday, June 21, 2014

GSoC Report #1 (slightly delayed)

At first, I have to explain my little delay of progress report - I started my work a little bit later (that's because of exams on my university), and that's why I'm writing my progress report now (I promise, I will publish my further report in the nearest two weeks:)

Last time I spent a lot of time on a  learning F# language. My mentor, Andrés G. Aragoneses, proposed me to write my task in this language (at the beginning it was to be a C# ). I'd never written anything using this language, so I started to read everything what I noticed in the internet about it. The most interesting articles I can be found at the end of post.
Because I even after reading a lot of articles I wasn't so experienced in F# (I'm still not ;), I started to write in C#, and then I rewrote my code to F#.

Empty album's names fixer
My first subtask was add new function to  Metadata Fixer plugin. Pluggin allowed to find and fix duplicated artists, albums and genres in loaded files. I implemented one more option: finding tracks, which has empty album's names, and setting this field to "God's Album". Screenshot of plugin and results is shown below:

Input track list, with empty album's names


Tracks with empty album's field, found by plugin


Fixed album's names

After that, I improved it a little, by finding real album's name in MusicBrainz [1] service.
Album's names found in MusicBrainz

Meanwhile I fixed bug [2], which totally prevented to use Metadata Fixer in the newest Banshee version.

Working with AcoustID
Now I'm trying to use AcoustID [3] - it's an Open Source project, which allows to read fingerprints from audiofile. Fingerprint may be used for finding more informations about track (e.g. track name, artist, release etc.).
For now, I wrote an application, which takes audiofile as an argument, reads fingerprints, and display some informations about this file.
Sample usage:
loganek@loganek-cmp ~$ ./ChromaPrintTest.exe ~/unknown.mp3
Track ID: 370f8c7a-ae8d-4ac4-9c41-f731929580e7
=========================
Recording ID: cfe8e73c-09c1-4c86-a86c-d31da7448a08
Title: Ten sen
Artists:
     * Varius Manx (ID: 04f19c9f-f9c3-4645-bb26-7f7211ae7b6f)
Release Groups:
     * Najlepsze z dobrych (Type: Album, ID: c6ac2258-16c4-3362-8396-08c5fa49456d)
     * Ego (Type: Album, ID: 322c5fec-d0bf-37ba-82a9-c1d1b93608c3)

loganek@loganek-cmp ~$
Fingerprints are calculated from decoded stream, so we can use this application for every audio format, which is supported by GStreamer installed on your system.

Commits
For my commits, follow the link [4]

F# tutorials
Links