Showing posts with label OpenSource. Show all posts
Showing posts with label OpenSource. Show all posts

Wednesday, April 15, 2020

HawkTracer - low-overhead instrumentation-based profiler


Disclaimer: this post introduces HawkTracer profiler but doesn't try to go deep into details of that. Follow the links attached to find all the features (and limitations) of the tool.

A while ago, at Amazon we've open-sourced instrumentation-based profiler - HawkTracer - which introduces very low overhead so it can be used on low-end platforms, where development environment is somehow limited (e.g. no ssh access, very limited disk storage etc). We used it to fix performance issues of Prime Video app on living room devices (SmartTVs, Streaming sticks, Game consoles etc).

The profiler can be used to measure resource usage (mainly time spend in scope, but also others like CPU usage etc) in your C/C++ code (but it's easy to write bindings for other languages, there are already some in Python and Rust) and then visualize it using Trace Event Profiling Tool or as FlameGraphs. Example instrumentation can be found below:

void foo()
{
  HT_G_TRACE_FUNCTION();

  very_expensive_call();
}
void bar()
{
  HT_G_TRACE_FUNCTION();
  for (int i = 0; i < 100; i++)
  {
    foo();
    {
      HT_G_TRACE_OPT_STATIC("InternalOp");
      recursive(10);
    }
  }
}

That example generates following results:

How does it work?

The idea behind HawkTracer is very trivial and well-known - the design is a simple server-client architecture, where the profiling application (usually running on an embedded device) runs as a server that emits tracing events. The serialized events are transmitted to a client through an user-specific protocol (by default TCP/IP and File are supported, but that can be extended by user). The client then can convert received events to some human-readable format - again, only few of them are supported by default (ChromeTracing and FlameGraph) but user can extend the client by adding more conversion methods.
The HawkTracer itself is a library that's just linked to your executable, so there's no need to run separate profiling process.



But it's C... and we all need Rust now!

Well, if you're a Rust lover, I have a good news for you. There are already bindings for HawkTracer in Rust! The snippet below shows how can you instrument your codebase:

#[macro_use]
extern crate rust_hawktracer;
use rust_hawktracer::*;
use std::{thread, time};

#[hawktracer(trace_this)]
fn method_to_trace() {
    thread::sleep(time::Duration::from_millis(1));
}

fn main() {
    let instance = HawktracerInstance::new();
    let _listener = instance.create_listener(HawktracerListenerType::TCP {
        port: 12345,
        buffer_size: 4096,
    });

    println!("Hello, world!");
    {
        scoped_tracepoint!(_test);
        thread::sleep(time::Duration::from_millis(10));

        {
            for _ in 0..10 {
                scoped_tracepoint!(_second_tracepoint);
                thread::sleep(time::Duration::from_millis(10));
            }
        }
    }
}

The tracepoints can be disabled at build time (as they're implemented as macros) - see the repository for details.

Want to know more?

This blogpost is just a very short introduction to HawkTracer. I'll be posting here more about the profiler, but in the meantime, checkout the following links to have more details about it:

Friday, April 7, 2017

GNOME Paint - simple drawing app for GNOME

TL;DR
I've started working on simple drawing application for GNOME. Current state - just started (see the current screenshot [1]), but progressing. Help needed (especially UX guys).

Motivation
A couple of weeks ago I've needed to make a very simple modification of the image - some cutting, moving some part of the image from left to right, draw a few lines. Turns out, that I couldn't easily find a software, that I could use. I've tried following:
  • gnome-paint [2] - the name (GNOME-XXX) convinced me to try this tool as a first one. The first attempt of modifying the image (AFAIR I just wanted to resize the canvas) - crash. Ok, that happens. Fortunately, we live in the open source world so I can fix it. I've downloaded the sources, and... bang! The project was unmaintained for a while (last commit more than 6 years ago), GTK+2, etc - I gave up. I didn't have that much time, I just needed to do simple modifications of the image. So let's try another tool:
  • gpaint [3] - the same story - unmaintained, and crashed after few clicks. Keep searching, and I found:
  • GNU Paint [4] - this app looks awful (especially if you got used to beautiful GNOME apps) but at least it seems functional. Unfortunately, didn't work for me neither. After few minutes of using it, the app just didn't respond to the input (yes, it means that I couldn't save my work, I had to do the print-screen...). And finally, I've installed:
  • KolourPaint [5] with tons of KDE stuff... seriously, I couldn't believe that I can't easily find simple image editor for GNOME...
Hey, but what about GIMP?
Sorry to say that, but it's not a SIMPLE image editor. Every time when I tried to do something that would be simple in MS Paint, I had to search for a tutorial. Every single time. 

You didn't do the research good enough, I know tool XXX which is based on GTK+
That's true, I didn't spend that much time on doing the research. However, after a few failures, I was just tired of this. I just wanted to do a simple modification, so I finally ended up with an app that I used to use some time ago, which was stable, functional, and simple. Now I'm aware of a few more apps (Pinta, mtpaint etc).

GNOME Paint
I've decided to start a new project - GNOME Paint. You can find some of the reasons in the paragraph "Motivation", here are the others:
  1. There is no GNOME-look-like drawing editor. Would be nice to have one. If the app will be good enough, and people will like it, it might be a part of GNOME core apps (but that's very long way)
  2. I finally want to dive deep into the GTK+ framework. I used to use it for several projects (mostly GTKMM), but without deep understanding of the framework, and working on a real project is IMO a better way for learning the framework than just reading the manual.
  3. I'm going to use it a lot, and it's also fun using software that you made on your own.
Current state
See the screenshot below. I've high-level design and some basic data structures, but still missing minimal functionality, so it's not even close to the first release. Also, the UI needs to be re-done (but I didn't pay attention to the UI so far). Hopefully, I'll be able to do a simple demo of the first release during the lightning session at GUADEC, but no promises.

Help needed
Any help (most important - UX, GNOME HIG experts) very welcome!


Links

Saturday, January 7, 2017

chromietabs - getting information about open tabs in Google Chrome browser

This blog post is about chromietabs [1] library, that provides information (URL) about currently open tabs in Google Chrome and Chromium web browsers.
TL;DR;

Motivation
I was always curious how do I spend time using my computer - what applications do I use, how much time do I spend using particular app etc. I know there is plenty of software that could track my activity on the market, however, none of them met my requirements, so couple of months ago I've started workertracker project [2], which does the job. I'll blog about the application in the future, since is not ready yet (there's a few pre-releases, so feel free to test it), however, the post is about quite important feature of the app - accessing current URL of the browser (in google-chrome, for now).

chromietabs library
Since I couldn't find any good solution on the internet, I've decided to implement a tiny library that will provide information about active tab in Google Chrome and Chromium web browsers.
An Interface of the chromietabs library is very simple, and it consists of few layers - depends on how detailed information you need, you should use another class. The example below demonstrates how can you access the URL of the current tab in google chrome:

ChromieTabs::SessionAnalyzer analyzer{
           ChromieTabs::SessionReader("Current Session")};
auto window_id = analyzer.get_current_window_id();
auto active_tab_id = analyzer.get_current_tab_id(window_id);
std::cout << analyzer.get_current_url(active_tab_id) << std::endl;

A full example can be found in the git repository [1].
You can also use the documentation [3].
Please note, that current release (0.1) is a pre-release, and the API might change a bit.

How does it work?
I've noticed, that when I kill (not close) google-chrome, it's able to restore my tabs after the crash. It means, that it has to constantly update some file saving information about the tabs. I was right - there is a binary file in your profile directory - Current Session - that stores that information.
Unfortunately, Current Session is a binary file, so I had to go through the chromium source code to figure out the file format.

Feedback
Feedback is always appreciated! Feel free to comment, report issues[4], or create pull requests [5].

Links
[1] https://github.com/loganek/chromietabs
[2] https://github.com/loganek/workertracker
[3] https://loganek.github.io/chromietabs/master//index.html
[4] https://github.com/loganek/chromietabs/issues
[5] https://github.com/loganek/chromietabs/pulls

Saturday, July 16, 2016

Generic C++ GObject signals wrapper

Recently I've discovered, that connecting to signals in gstreamermm can be really inconvenient. The problem doesn't exist in the other mm libraries, because most of the classes and their signals are wrapped.
But GStreamer allows to create user-defined elements, so it's actually impossible to wrap everything in gstreamermm (for now library supports wrappers for gstreamer plugins core and base).

Currently, if you want to connect to a signal in gstreamermm, you have two options:
  1. Using pure C API:

  2. auto typefind = Gst::ElementFactory::create_element("typefind");
    
    g_signal_connect (typefind->gobj(), 
                      "have-type", 
                      G_CALLBACK(cb_typefind_havetype), 
                     (gpointer *)typefind->gobj());
    
    static void cb_typefind_havetype (GstTypeFindElement *typefind,
                                      guint               probability,
                                      GstCaps            *caps,
                                      gpointer            user_data)
    {
      // callback implementation
    }
    Well, it's not very bad. But... you have to use C structures in the callback instead of C++ wrappers.

  3. Using gstreamermm API
  4. As I mentioned, gstreamermm provide wrappers for core and base plugins, so some of the elements (and their signals) are already wrapped in the library:
    auto typefind = Gst::TypeFindElement::create();
    typefind->signal_have_type().connect(
        [] (guint probability, const Glib::RefPtr& caps)
        {
          // callback implementation
        });
    
However, many plugins are not wrapped (and they never will), so usually you need to either write wrapper for element which you wanted to use (and then, maintain this wrapper as well), or use pure C API.
Moreover, I'm going to remove plugin API in the next release [1], so user won't be able to use gstreamermm API even for the base and core plugins. I was wondering, if it would be possible to write generic wrapper for the GObject signals. So... there you are! The solution is not perfect yet, and I haven't tested it so much, but so far it works fine with few plugins and signals.

namespace Glib
{  
  template <typename T>
  static constexpr T wrap (T v, bool=true)
  {
    return v;
  }

  template <typename T>
  static constexpr T unwrap (T v, bool=true)
  {
    return v;
  }

  template<typename T>
  using unwrapped_t = decltype(unwrap(*((typename std::remove_reference<T>::type*)nullptr)));

  template<typename T>
  constexpr T return_helper()
  {
    typedef unwrapped_t<T> Ret;
    return Ret();
  }

  template<>
  constexpr void return_helper()
  {
    return void();
  }
}


template<typename>
class signal_callback;

template<typename Ret, typename ...T>
class signal_callback<Ret(T...)>
{
  template<typename ...Args>
  static auto callback(void* self, Args ...v)
  {
    using Glib::wrap;
    typedef sigc::slot< void, decltype(wrap(v))... > SlotType;

    void* data = std::get<sizeof...(Args)-1>(std::tuple<Args...>(v...));

    // Do not try to call a signal on a disassociated wrapper.
    if(dynamic_cast<Glib::Object*>(Glib::ObjectBase::_get_current_wrapper((GObject*) self)))
      {
	try
	  {
	    if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data))
	      {
		(*static_cast<SlotType*>(slot))(wrap(std::forward<Args>(v), true)...);
	      }
	  }
	catch(...)
	  {
	    Glib::exception_handlers_invoke();
	  }
      }

    return Glib::return_helper<Ret>();
  }

public:
  auto operator()(const std::string& signal_name, const Glib::RefPtr<Glib::Object>& obj)
  {
    using Glib::unwrap;
    static std::map<std::pair<GType, std::string>, Glib::SignalProxyInfo> signal_infos;

    auto key = std::make_pair(G_TYPE_FROM_INSTANCE (obj->gobj()), signal_name);
    if (signal_infos.find(key) == signal_infos.end())
      {
	signal_infos[key] = {
	  signal_name.c_str(),
	  (GCallback) &callback<Glib::unwrapped_t<T>..., void*>,
	  (GCallback) &callback<Glib::unwrapped_t<T>..., void*>
	};
      }

    return Glib::SignalProxy<Ret, T... >(obj.operator->(), &signal_infos[key]);
  }
};


auto typefind = Gst::ElementFactory::create_element("typefind"),
signal_callback<void(guint, const Glib::RefPtr<Gst::Caps>&)> signal_wrapper;

signal_wrapper("have-type", typefind).connect(
  [&ready, &cv] (guint probability, const Glib::RefPtr<Gst::Caps>& caps) {
    std::cout << "have-type: probability=" << probability << std::endl;
    Gst::Structure structure = caps->get_structure(0);
    const Glib::ustring mime_type = structure.get_name();
    std::cout << "have-type: mime_type=" << mime_type << std::endl;

    structure.foreach([] (const Glib::QueryQuark& id, const Glib::ValueBase& value) {
      const Glib::ustring str_id = id;
      gchar* str_value = g_strdup_value_contents(value.gobj());
      std::cout << "Structure field: id=" << str_id << ", value=" << str_value << std::endl;
      g_free(str_value);		      
      return true;
  });
});

Full source of the code can be found on the github [2].
As you see, you still have to know the type of the callback, but at least you can use gstreamermm C++ classes.
There is couple of things to do in this code, like getting last parameter from the list in more efficient way than through the tuple, etc.
I don't feel it is stable enough to integrate it with gstreamermm, but probably in the future I'll do that. Also, we could even internally use it in the glibmm to reduce amount of generated code.

Links
[1] https://bugzilla.gnome.org/show_bug.cgi?id=755395
[2] https://gist.github.com/loganek/7833089caff73ff2e8b1f076c8f7910e

Sunday, August 30, 2015

GUADEC 2015

At the beginning of this month I've spent a few great days in Goteborg, at GUADEC conference. That was my second GUADEC (first time I've participated last year, in Strasbourg).

There were a lot of interesting presentations, but the most I enjoyed all of the keynotes. As a Google Summer of Code student (I've worked for GStreamer project [1]), I was able to give a lightning talk about my project. It seemed to be interested to some people, so after that someone asked me to show him my project "in action". We were talking about possible improvements and new features.

In the evenings organizers prepared for attendees some event, so I could integrate with other GNOME people. Moreover, they organized for us (GSOC students and mentors) a dinner, so I could meet other students a little bit better, talk mostly about our summer projects, but also about differences in education at their universities  (people came from different part of world).

In conclusion, I enjoyed GUADEC, all presentations and evening events. I'd like to thank the GNOME Foundation for sponsoring my travel and my hostel. My participation probably wasn't be able without Foundation's help. Thanks a lot!


[1] http://www.cookandcommit.eu/2015/06/gstreamer-debugger-introduction.html

Monday, June 29, 2015

GStreamer Debugger - introduction

Hi everyone,
This year I've been accepted to Google Summer of Code :) Last year I worked on Banshee project [1], and this year I joined to GStreamer [2] team.
This summer I work on tool for GStreamer-based applications - GStreamer Debugger.

Goals
At the end of this summer, I'm going to provide you an application, which allows you to connect to your remote pipeline (obviously, lo interface can be used as well :)), watch pipeline graph (and its changes), spy selected queries, events, log messages, messages from bus and log messages, and even buffers. Application won't allow user modify pipeline and pipeline's state, but who knows - if it is useful feature, I implement it in the future.
GStreamer doesn't provide possibility to connect to pipeline, so I have to do it on my own.

Progress
June is a month, when I've exams on my university (fortunately, I've already passed all of them!), so I didn't spend as much time as I wanted on this project. Anyway, I accomplished a few milestones.
There's a list, what already has been done:
  • gst-trace [3] plugin, containing tcp server. For now, it sends GstEvents, GstMessages, and log messages to clients (todo: send GstBuffers, and GstQueries)
  • client application, which displays events and log messages (todo: display GstBuffers, GstQueries, GstMessages). I have a lot of ideas, how to improve client application, but I'm not sure whether I meet GSOC deadline, so I suppose, most of them will be implement after Google's program. 
  • protocol - I used Google Protobuf library [4]. In general, I've defined most of protocol's structures, I just make minor improvements, when I need it.
Below you can find a few screenshoots of client application. Full code can be found on my github account ([5], [6]).




Links
[1] http://www.cookandcommit.eu/2014/04/google-summer-of-code-2014-with-gnome.html
[2] http://gstreamer.freedesktop.org/
[3] https://bugzilla.gnome.org/show_bug.cgi?id=733187
[4] https://developers.google.com/protocol-buffers/
[5] https://github.com/loganek/gstreamer
[6] https://github.com/loganek/gst-debugger

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/

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/

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/

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

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.