Wednesday, November 19, 2014

"Learn IT, Girl!" mentorship program just started!

This week is official beginning of "Learn IT, Girl!" program [1]. It's international program for woman, started by a few girls from Poland and Romania, invented at the Google Anita Borg Scholarship [2] retreat in 2014. A main aim is to learn by women particular programming language. Every scholar is guided by her own mentor, who helps her. Girls learn language by doing selected earlier project (which must be open-source project ofc).

I take a part in this program as a mentor, and my my mentee is Corina Teodorescu. She's from Romania and studies Marketing. Corina has decided to learn C#, and she's going to write an mobile app for phones with Android OS. Because of a lot really great ideas, she doesn't finally choose her project. She's choosing between RSS reader and application for downloading/uploading/hash-tagging images - she didn't make a decision, but I think, both are quite useful, and Corina can learn a lot by making one of them(what's the most important during this program :)

Program takes 3 months, and I believe, that would be great time for Corina and for me as well. I hope, Corina will learn a lot, and I'm going to improve my teaching skills too. We will have fun for sure :)

 Wish me and Corina luck!

Learn IT, Girl!


Links
[1] https://sites.google.com/site/learnitgirl/
[2] http://www.google.com/anitaborg/

Tuesday, November 4, 2014

Simple macro for measuring algorithm's running time

Recently I'm spending a lot of time on my master's thesis. I'm working on algorithm for automatic number plates recognition using image segmentation. I'm trying to achieve high performance, so I need to measure execution time of my algorithms.
A few weeks ago I've written about google benchmark [1]. It's quite powerful library, and it's easy to use even in simple case, but sometimes we don't want to depend on an external library. So is it in my case too.
I've created simple macro for measuring running time:
#include <chrono>

#define MEASURE_TIME(unit, ...)    \
  [&] {         \
    using namespace std::chrono;     \
    auto start = high_resolution_clock::now ();    \
    __VA_ARGS__;       \
    auto time = high_resolution_clock::now () - start;   \
    return duration_cast<unit> (time).count ();    \
  } ();


Arguments:
  • unit - std::chrono::duration time interval. You can simply pass defined in standard library types, e.g. predefined types:
    • std::chrono::nanoseconds
    • std::chrono::microseconds
    • std::chrono::milliseconds
    • std::chrono::seconds
    • std::chrono::minutes
    • std::chrono::hours
  • ... - code for measurement
And example usage:
  int value = 0;

  auto duration = MEASURE_TIME(std::chrono::milliseconds, 
    int arg0, arg1;
    arg0 = run_time_consuming_algorithm ();
    arg1 = run_another_one(arg0);
    value = run_third_algorithm(arg1);
  );

  cout << "Execution time: " << duration << std::endl
       << "Computed value: " << value;

Note, that you can use earlier declared values (value variable, in my case), because all the values are captured by reference in lambda.

Feel free to use it ;)

Links
[1] http://cookandcommit.blogspot.com/2014/09/tiny-c-benchmark-framework_29.html 

Wednesday, October 29, 2014

Useful (to me) post-commit hook script for checking commit message

A lot of projects are managed using bug-tracking tool (e.g. JIRA [1], Bugzilla [2], Redmine [3]), and most commits refer to a specified ticket. It's good to enter ticket number in a commit message - it allows other developers find a bug report, read more about a problem, which concern a commit.
I don't know about you, but I often forget about put it in a commit message. So I've prepared simple script, which reminds me about enter ticket message in a message. I'm using this script as a post-commit hook both at work and in my private projects.
I've pushed it to my github repository [4] (I've added also simple instruction - you can find it in a README.md file). Feel free to use and improve it (I'm not a bash and git expert) - patches are welcome ;)

REPO_REGEX parameter

Some of my friends have asked me about REPO_REGEX parameter. So let me clarify; e.g. at work I'm using mostly company's repositories, where should I enter ticket number. But I've got also a few open source repositories, where I don't need to (sometimes even I can't, because it doesn't strongly connected with bug-reporting service) pass this number. To make my life easier, I've added this script as a global. REPO_REGEX allows me define company repositories pattern, so I don't see warning message during committing to a non-company repositories.

Links
[1] https://www.atlassian.com/software/jira
[2] http://www.bugzilla.org/
[3] http://www.redmine.org/
[4] https://github.com/loganek/postcommit-checker

Monday, September 29, 2014

Tiny C++ Benchmark Framework

Lately I had to improve a little some of my algorithms. I wanted to check, how changes affect to time of algorithms execution. So I started to search benchmark framework for C++. After a while, I have found quite small, but powerful framework - google benchmark [1].

Simple usage

The simplest usage of google benchmark is shown below:
#include <benchmark/benchmark.h>
#include <algorithm>

int complex_computation(int n)
{
  if (n == 0) 
    return 0;

  unsigned int a = 1, b = 1;

  for (unsigned int i=0; i < n-1; i++) 
    {
      std::swap(a, b);
      b += a;
    }

  return b;
}

static void BM_Fibonacci(benchmark::State& state)
{
  int ret;

  while (state.KeepRunning())
    ret |= complex_computation(500);

  CHECK(ret != 0);
}

BENCHMARK(BM_Fibonacci);

int main(int argc, const char* argv[]) 
{
  benchmark::Initialize(&argc, argv);
  benchmark::RunSpecifiedBenchmarks();

  return 0;
}
At the beginning, we have to define function, which will be measured (complex_computation, in my case). Next, we're defining benchmark method - BM_Fibonacci. It has one argument - state (I will talk about it later). In while loop we call our method, until benchmark's working. ret variable is used only because of compiler optimizations (we'd like to avoid removing dummy code). Benchmark method should be later registered (using BENCHMARK macro). In main function, framework should be initialized, and after that, we can run all our benchmark methods.
loganek@hf-gcs-computer:~/Documents/blog-benchmark$ g++ benchmark.cpp -std=c++11 -lbenchmark -lpthread -O2 -o benchmark
loganek@hf-gcs-computer:~/Documents/blog-benchmark$ ./benchmark 
Reading /proc/self/cputime_ns failed. Using getrusage().
Benchmarking on 4 X 2701 MHz CPUs
2014/09/29-00:49:29
CPU scaling is enabled: Benchmark timings may be noisy.
DEBUG: Benchmark      Time(ns)    CPU(ns) Iterations
----------------------------------------------------
DEBUG: BM_Fibonacci        208        225    2222788                                  
loganek@hf-gcs-computer:~/Documents/blog-benchmark$ 

As you can see, there is computation time, cpu and iterations count - everything what we need :) Moreover, we can also get a few informations about machine.

Arguments, range of arguments

Snippet shown above is very simple, but this framework offers users much more. We can define a set of arguments for benchmark. Let's remind previous example. We tried to measure fibonacci implementation. But I hardcoded an argument. Sometimes we'd like to measure one method with different arguments. We don't have to define BM_Fibonacci_5, BM_Fibonacci_42, BM_Fibonacci_87 functions for different arguments. Let's look at the improvement of previous code:
static void BM_Fibonacci(benchmark::State& state)
{
  int ret;
  while (state.KeepRunning())
    ret |= complex_computation(state.range_x());
  CHECK(ret != 0);
}

BENCHMARK(BM_Fibonacci)->Arg(5)->Arg(42)->Arg(87);
and the output is also quite different:
loganek@hf-gcs-computer:~/Documents/blog-benchmark$ ./benchmark 
Reading /proc/self/cputime_ns failed. Using getrusage().
Benchmarking on 4 X 2701 MHz CPUs
2014/09/29-01:20:03
CPU scaling is enabled: Benchmark timings may be noisy.
DEBUG: Benchmark         Time(ns)    CPU(ns) Iterations
-------------------------------------------------------
DEBUG: BM_Fibonacci/5           3         19   25832109                                  
DEBUG: BM_Fibonacci/42         18         35   14398500                                  
DEBUG: BM_Fibonacci/87         44         61    8224413   
We've access for results of every argument, which I passed to a benchmark method.
It is also possible to pass range of arguments to our benchmark method.
BENCHMARK(BM_Fibonacci)->Range(0, 1024);
Defined range runs benchmark for min, max in this range, and every power of 8 from this range. So in my case: 0, 1, 8, 64, 512 and 1024.

Multithreading, other features

Google Benchmark framework gives a few other features for developers:
  • multithreading
  • benchmark templates
  • pair of arguments
  • custom reporter class
You may see usage of other features in google benchmark example code [2] or on README page[3].

Summary

That's one of first test framework, which I used for now. Previously I wrote simple methods for measurements, but it wasn't so convenient, and in the long run, it's just waste of time. Moreover, benchmark helps me keep in order my tests, so my code is much cleaner than before.
In the future, I'd like to check also other frameworks; I heard about Celero [4] and hayai [5]. But for now, google benchmark fits my needs.



Links
[1] https://github.com/google/benchmark
[2] https://github.com/google/benchmark/blob/master/test/benchmark_test.cc
[3] https://github.com/google/benchmark/blob/master/README.md
[4] https://github.com/DigitalInBlue/Celero
[5] https://github.com/nickbruun/hayai

Friday, August 29, 2014

gstreamermm on Windows & Visual Studio

Hi everyone!
Recently me and my friends have ported quite big project from Linux to Windows, and had to build it in Visual Studio environment. (Un)fortunatelly, we're strongly dependent on gstreamermm project, so I had to prepare .vcxproj files, which allows us to compile gstreamermm in Microsoft's IDE.
I spent one evening on that, and that's it! I've commited Visual Studio project file for building gstreamermm project, and also property sheet (.props), which contains all necessary dependencies for gstreamermm-based projects.
I've tested it in Debug/Release configuration, both platforms (Win32 and x64), and have used Visual Studio 2010 (project file probably can be upgraded to VS2013, but I didn't test it yet).
You can find it in the nearest gstreamermm release (currently I'm working on 1.2.4 version, it should be finished in a next month), but I've already prepared unofficial release for you [1].
Go ahead, download, use, and file  a bugs on a bugzilla [2] ;)

Installer
If I have a time, I will prepare windows installer for sure, and upload it with official v1.2.4 release. If not, maybe someone else will pick up the gauntlet, and do one-click installer for gstreamermm community - if you'd like to help, just let me know, I'll help you so far as it is possible.

Dependencies
gstreamermm depends on many other libraries, so you need to install gtkmm package (can be found here [3]), or build necessary yourself from sources (that's way which I have chosen).

Links
[1] https://dl.dropboxusercontent.com/u/14229925/gstreamermm-1.0.10-msvc-support.tar.gz
[2] https://bugzilla.gnome.org/enter_bug.cgi?product=gstreamermm
[3] http://ftp.gnome.org/pub/gnome/binaries/

Monday, August 18, 2014

Week with drones - IMAV 2014 report

Last week I spent far away of my homely hacker zone, I was in Netherlands, and took part in IMAV - International Micro Air Vehicle Conference and Competition [1], as a member of High Flyers - Academic Scientific Association from Silesian University of Technology [2].

Briefly about IMAV
IMAV is an annual competition for UAV aficionado, combined with conference concerning micro air vehicles. Last year, IMAV was organized by ENAC University, from Toulouse [3]. That was my first time, when I participated in IMAV, and I really enjoyed. Me and my friends (from High Flyers also) decided to attend in both the conference and the competition. We did our best, and we won two silver medals in indoor category (autonomy and operation) [4]!!! The atmosphere on the conference was amazing - everyone was very friendly, you could talk about UAV technologies with people from another universities, countries, and even continents. Moreover, organizers invited us to Airbus factory [5], and we could see, how one of the biggest airliners are made.
HF-4X - our last year platform, and awards :)
https://www.facebook.com/high.flyers.polsl


IMAV 2014
This year, IMAV was organized by University of Technology in Delf, in Netherlands. Organizers made every effort, to prepare conference as good as in France. And this is it! Guys from Delf have organized conference very well.

Rules
This year there was no division into outdoor and indoor category. Whole mission, which should be done, took place in both inside the buildings, and also outside. So participants have to prepare platform, which can fly in various conditions, or just made two kind of platforms - for indoor and outdoor operations. Most of (or maybe all) teams have chosen later variant (including High Flyers).
Competition has took place in the village of Oostdorp. Participants had to make a map of Oostdorp, find obstacles on the roads, read numbers on the buildings, precisely scan one of them, observe digits shown on seven-segment display. And the most important - every mission should be performed fully autonomous. If an operator interfere during a mission, a team will get less points. Competition rules might be found on an official IMAV 2014 website [6].

Me and my team on IMAV 2014
High Flyers has participated with three platforms. Two of them was designed for outdoor conditions, and one - for flying inside a building. Unfortunately, one of outdoor platforms has broken down on competition's day (one day earlier, during a tests, everything has worked fine...:), and we used only two platforms. Even so, we have won very good, 4th place. Gold medal for team from Singapore, silver - Germany, and bronze - for previous organizers - France. Final competition results might be found on the IMAV 2014 website [7].

High Flyers with UAVs before...
https://www.facebook.com/high.flyers.polsl

...and during competition
https://www.facebook.com/high.flyers.polsl



Future
Next year - Achen, Germany. I'm looking forward to the rules. If it is possible, I definitely will go there. I think, every one interested in UAV, should be on IMAV, meet people crazy about drones.

IMAV's disadvantages
IMAV was really amazing, but when I backed home, I get to know the only one disadvantage of this conference. I wasn't at home whole week, and I totally forgot about my plants :/ Rosemary looks quite ok, but basil probably can't be rescued. I'll do my best, but I'm afraid, I have to buy a new one.
Almost dead basil



Links
[1] http://www.imavs.org/2014/
[2] http://uav.polsl.pl/
[3] http://www.imav2013.org/
[4] http://www.imav2013.org/index.php/final-results.html
[5] http://www.airbus.com/
[6] http://www.imavs.org/2014/documents/IMAV2014CompetitionRules_V1_4.pdf
[7] http://www.imavs.org/2014/competition.html

Wednesday, August 6, 2014

GSoC Report #4


Last stage of my Google Summer of Code 2014 project was to implement mechanism for sending metadata to AcoustID service.
Me and my mentor decided, that metadata will be sent automatically in a background. There is no need for user interaction. Data is sent on adding new audio file to a music library, or on a change metadata of existing track.
AcoustID requires API key for acceptance new metadata, so user has to enter his key into a preferences window.

Metadata Fixer preferences window

Key might be obtained on a acoust id website [1]. While user doesn't enter api key, in plugin window, "AcoustID Settings" button will be displayed.

Plugin info with button referring to an AcoustID preferences window





Links
[1] https://acoustid.org/api-key

Sunday, August 3, 2014

gstreamermm 1.0 finally released!

Yeah, after more than year, I finally released gstreamermm [1] 1.0 version - it might be downloaded from the website [2]. I'm really sorry people, who have waited for this release, I had not so much time to do it. Ok. I had time, I didn't it earlier because of my laziness. GUADEC finally motivated me to do this release, and I'm promis, I'll work on gstreamermm project regular, and also official releases will be done as soon as it will be possible.

Changes
The most important change, compared to previous version, is supported gstreamer 1.0.
Moreover, possibility for writing your own plugin was added (thanks peper0 [3]).
I also used gtest [4] for writing testcases.

Future plans
  • There is a lot of bugs, which I'll for sure fix in the next stable version. I'm going to write much more test cases (my aim - cover every single function). Feel free to use this library, file a bugs and send patches on a bugzilla [5]!
  • I'm also going to wrap new things from 1.2 version, and later also from 1.4 version.
Packaging - HELP!
I'm looking for help with releasing Ubuntu/Fedora packages. I'd never done it, and it would be nice, if somebody help me, or even do it instead of me :)

Sunday, July 13, 2014

GstCreator - introduction


I'd like to introduce to you my OpenSource project - GstCreator [1]. It's some kind of IDE for GStreamer framework [2]. User can rapidly prototype GStreamer pipeline, and (in the future, not implemented yet) generate C or C++ file with code.
However, user can peek buffers, events and queries on every single pad.

Toolchain
Entire project is written in C++. I'm using Qt library [3](maybe in the future it will be replaced by Gtk+ [4], will see). CMake [5] is my build system. I don't use GStreamer directly, but gstreamermm library [6], which is C++ wrapper for GStreamer framework. It's because of two reasons: 
  • don't like mix 2 languages in one project (even if syntax of both languages is very similar)
  • I'm currently maintainer of gstreamermm project, and use this library by myself helps me find and eliminate a lot of bugs.
Development plan
GstCreator is not ready, ah, it's quite long long way to make first release of this application. But I'm of good cheer.
The list of most important features, which should be implemented in the nearest future:
  • linking to a `sometimes` pads
  • improved `ProbesWatcher` module by showing more informations about buffers, events, and queries, and adding possibility for filtering data
  • save & load project
List above shows only the most important tasks, but there is a lot of minor bugs, which should be implemented ASAP. There is a lot ideas in my head, how to improve this tool, made it more useful and powerful ;)
I hope, some of you will enjoy this application, maybe there is also somebody, who'd like to help me in development ;)
I'm also waiting for your ideas connected to this project. Maybe some features are especially useful, but I didn't notice it;)

I will inform you here about my progress, new features ;)

Quiz
And at the end, short (and easy) quiz: What film is played on a screenshoot shown below?

GstCreator during playing udp stream

Links 
[1] https://github.com/loganek/gstcreator
[2] http://gstreamer.freedesktop.org/
[3] http://qt-project.org/
[4] http://www.gtk.org/
[5] http://cmake.org/
[6] https://git.gnome.org/browse/gstreamermm/

Friday, July 11, 2014

Creating SQL database `on the fly` - sqlfiddle.com

Recently I had to write some SQL queries in a quite advanced application (Banshee [1]). I'm not an expert in SQL, so I had to work through trial and error. But recompilation and restart application every time, when I changed something, was very time consuming. Unfortunately, I didn't use my own computer, and I hadn't installed(and I wasn't able to install) any SQLite shell. I started to looking for web interface for SQLite database.
One of the first result in Google was sqlfiddle [2] page. At first sight website looks very simple. And in reality - it is. On the left side you have to write DDL statements, and on the right side, you may use created schema by sending some queries.
For now, service offers many different databases:
  • MySQL (a few versions)
  • Oracle
  • PostgreSQL (a few versions)
  • SQLite
  • MS SQL Server (a few versions)
You may also generate link to your case, and paste id e.g. in some forum or irc channel.
There is also a lot of minor features, which can be use
ful in specified cases:
  • 3 types of displaying results,
  • execution time measurement,
  • query execution plan,
  • different query terminators,
and many others, which I probably missed. I would highly recommend at least try this tool. Maybe you would like it, and will use it in your daily work ;)

sqlfiddle in action

Links
[1] http://banshee.fm/
[2] http://sqlfiddle.com/

Thursday, July 10, 2014

GSoC Report #3

Finally I added all planned earlier options to my Banshee's plugin:
  • Empty Album Name - looking for tracks with empty album's name,
  • Missing Artist and Titles Fix - looking for tracks with empty fields Artist and/or Title,
  • Missing Albums Fix - looking for tracks with empty album's name,
  • Missing Most of Metadata Fix - looking for tracks with empty fields: Album, Artist, and Title,
  • Invalid Metadata Fix - looking for tracks with invalid(it means, different from online database) metadata.
All of them, except Empty Album Name, use fingerprints. So that's also the difference between Empty Album Name and Missing Album Fix. The first one uses track title and artist name, so you can't use it for looking track with empty albums and/or titles. The second one can be used even for tracks with no metadata, because it takes fingerprints for searching.

All available options in Metadata Fixer


Changes in code
There was a lot of changes in my source code. Before my GSoC attendance, I haven't so much experience in functional programming, so I wasn't able to use all of advantages, which come from F# language. Fortunatelly, my mentor, Andrés G. Aragoneses, is very helpful, so thanks his few advices, I refactored some pieces of code in my plugin. I hope, my code looks now much better now;)

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

Saturday, April 26, 2014

Google Summer of Code 2014 with GNOME!

Hello everyone! From 19th May (official, but I hope a little bit earlier) I'm starting to improve Banshee application under Google Summer of Code. Something more about project you may find here.