<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="assets/xml/rss.xsl" media="all"?><rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Ricardo Kirkner's personal website</title><link>http://www.kirkner.com.ar/</link><description></description><atom:link href="http://www.kirkner.com.ar/rss.xml" type="application/rss+xml" rel="self"></atom:link><language>en</language><lastBuildDate>Tue, 20 Dec 2016 14:15:18 GMT</lastBuildDate><generator>https://getnikola.com/</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>configglue 0.11 released</title><link>http://www.kirkner.com.ar/blog/configglue-011-released/</link><dc:creator>Ricardo Kirkner</dc:creator><description>&lt;p&gt;This release (0.11) brings configglue another step closer to the much
awaited 1.0 milestone.&lt;/p&gt;
&lt;p&gt;It includes two incredible features:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Environment variables support&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Environment variables are now supported in two flavours&lt;/p&gt;
&lt;p&gt;&lt;em&gt;During command-line integration&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If an environment variable of the form CONFIGGLUE_FOO_BAR is defined, it will
be used to override the configuration value for option &lt;strong&gt;foo&lt;/strong&gt; in section
&lt;strong&gt;bar&lt;/strong&gt;, according to the following precedence rules&lt;/p&gt;
&lt;pre class="literal-block"&gt;
1. Explicitly defined via command-line (i.e, --section_option=value)
2. Implicitly defined via environment variable (i.e, CONFIGGLUE_SECTION_OPTION)
3. Explicitly defined via configuration files
4. Implicitly defined via schema defaults
&lt;/pre&gt;
&lt;br&gt;&lt;p&gt;&lt;em&gt;As placeholders in configuration files&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In the configuration files, if an option has a value such as $FOO or ${FOO}
it will be interpolated using the FOO environment variable, or if that variable
is not defined, it will fallback to the default value for that option.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Base class for writing configglue-enabled applications&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By inheriting from &lt;strong&gt;configglue.app.App&lt;/strong&gt;, your application will now
automatically&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Read configuration files from standard locations&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The configglue-enabled app will automatically follow the XDG standards for
looking up configuration files. For example, if your application is named
'''myapp''', the following locations will be searched for configuration values&lt;/p&gt;
&lt;pre class="literal-block"&gt;
1. /etc/xdg/myapp/myapp.cfg
2. /home/user/.config/myapp/myapp.cfg
3. ./local.cfg
&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Support plugins for extending your application&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The class &lt;strong&gt;configglue.app.Plugin&lt;/strong&gt; will allow you to write plugins for your
application so that each plugin can have it's own configglue-based configuration.&lt;/p&gt;
&lt;p&gt;Each plugin registered with the application will have it's own schema and
configuration files, which will be included during validation. If the plugin
is named '''myplugin''', the following additional locations will be searched
for configuration values&lt;/p&gt;
&lt;pre class="literal-block"&gt;
1. /etc/xdg/myapp/myplugin.cfg
2. /home/user/.config/myapp/myplugin.cfg
&lt;/pre&gt;
&lt;p&gt;Plugins need to be registered with the manually for the time being. For doing
so, just call &lt;strong&gt;App.plugins.register&lt;/strong&gt;, like&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a name="rest_code_60abe54e775a49c79452b83e05191cfe-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FooSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;a name="rest_code_60abe54e775a49c79452b83e05191cfe-2"&gt;&lt;/a&gt;    &lt;span class="n"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IntOption&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a name="rest_code_60abe54e775a49c79452b83e05191cfe-3"&gt;&lt;/a&gt;
&lt;a name="rest_code_60abe54e775a49c79452b83e05191cfe-4"&gt;&lt;/a&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Plugin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;a name="rest_code_60abe54e775a49c79452b83e05191cfe-5"&gt;&lt;/a&gt;    &lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;a name="rest_code_60abe54e775a49c79452b83e05191cfe-6"&gt;&lt;/a&gt;    &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FooSchema&lt;/span&gt;
&lt;a name="rest_code_60abe54e775a49c79452b83e05191cfe-7"&gt;&lt;/a&gt;
&lt;a name="rest_code_60abe54e775a49c79452b83e05191cfe-8"&gt;&lt;/a&gt;&lt;span class="n"&gt;myapp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'myapp'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_60abe54e775a49c79452b83e05191cfe-9"&gt;&lt;/a&gt;&lt;span class="n"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;br&gt;&lt;p&gt;This example will register a &lt;strong&gt;Foo&lt;/strong&gt; plugin which will be enabled by default.&lt;/p&gt;
&lt;p&gt;Plugins can be enabled/disabled on demand, by calling the respective method, like&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a name="rest_code_4259c96a1d9d435ba9b209ecb09faae6-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_4259c96a1d9d435ba9b209ecb09faae6-2"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt;
&lt;a name="rest_code_4259c96a1d9d435ba9b209ecb09faae6-3"&gt;&lt;/a&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="s1"&gt;'&amp;gt;]&lt;/span&gt;
&lt;a name="rest_code_4259c96a1d9d435ba9b209ecb09faae6-4"&gt;&lt;/a&gt;
&lt;a name="rest_code_4259c96a1d9d435ba9b209ecb09faae6-5"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;disable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_4259c96a1d9d435ba9b209ecb09faae6-6"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt;
&lt;a name="rest_code_4259c96a1d9d435ba9b209ecb09faae6-7"&gt;&lt;/a&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/pre&gt;&lt;br&gt;&lt;p&gt;The list of available plugins can be retrieved like&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a name="rest_code_524c8c09051c4614a283fa057b22ed14-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;
&lt;a name="rest_code_524c8c09051c4614a283fa057b22ed14-2"&gt;&lt;/a&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="s1"&gt;'&amp;gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;br&gt;&lt;p&gt;&lt;strong&gt;Closing remarks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Documentation is still missing for this release, but I hope that this short
introduction will raise your interest enough to check out the code and start
using it!&lt;/p&gt;
&lt;p&gt;Questions will as usual always be answered on #configglue (on freenode).&lt;/p&gt;
&lt;p&gt;Happy hacking!&lt;/p&gt;</description><guid>http://www.kirkner.com.ar/blog/configglue-011-released/</guid><pubDate>Thu, 23 Jun 2011 18:21:49 GMT</pubDate></item><item><title>dual monitor management heaven</title><link>http://www.kirkner.com.ar/blog/dual-monitor-management-heaven/</link><dc:creator>Ricardo Kirkner</dc:creator><description>&lt;p&gt;For some time now I have been struggling to find a non-brain-dead way of
managing my dual-monitor setup.&lt;/p&gt;
&lt;p&gt;I have a laptop and an external monitor, and while it's fairly easy to
configure X to extend the virtual desktop across both (using the
nvidia-settings tool, as the proprietary drivers don't cope well with the
standard monitor management tool in Ubuntu), it was always a hassle when you
need to disconnect your laptop and move away from your desktop; most of your
windows would remain hidden from view in the "other" monitor, and you had to
resort to hacky ways of letting X know: "I now have just 1 monitor so please
adjust my settings".&lt;/p&gt;
&lt;p&gt;Today I found a very nice tool that handles this problem very well:
autorandr, you just made it to the list of my favorite tools.&lt;/p&gt;
&lt;p&gt;autorandr lets you save a given screen configuration into a profile which can
be enabled/disabled on demand. It uses disper or xrandr underneath to do the
dirty work of configuring your monitors/screens.&lt;/p&gt;
&lt;p&gt;What I did was basically:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
1. Configure my screens as I have them usually at home (external monitor
   is primary screen + laptop extends to the right)

disper -d CRT-0,DFP-0 -r 1680x1050,1440x900 -e -t right

2. Save that configuration as a profile called "dual"

auto-disper --save dual

3. Configure my screens so that the laptop is the only available monitor

disper -d DFP-0 -r 1440x900 -s

4. Save that configuration as a profile called "laptop" (I disconnected
   my external monitor to make sure the tool only sees the laptop monitor)

auto-disper --save laptop

5. Bound the "auto-disper --change" command to a key so that when I
   unplug the external monitor I can just run that and auto-disper will
   adjust the screen configuration to match the the hardware profile.
&lt;/pre&gt;
&lt;p&gt;Now, whenever I plug the external monitor in or out I can just hit that key
combination and my screens will get correctly configured!&lt;/p&gt;
&lt;p&gt;Easy! :)&lt;/p&gt;
&lt;p&gt;What I'd like to figure out next is how to have the tool automatically detect
such events (external monitor plug in/out) and run the auto-disper command
automatically.&lt;/p&gt;</description><guid>http://www.kirkner.com.ar/blog/dual-monitor-management-heaven/</guid><pubDate>Tue, 24 May 2011 17:29:15 GMT</pubDate></item><item><title>experimenting with lalita</title><link>http://www.kirkner.com.ar/blog/experimenting-with-lalita/</link><dc:creator>Ricardo Kirkner</dc:creator><description>&lt;p&gt;I decided to play around a bit with lalita. Lalita is an irc bot
developed by some members of the PyAr - Python Argentina community.
What I wanted to achieve is to have some way to be notified when there
is something interesting going on in the irc channel, without having to
read every single message, or requiring others to actually say my name
(so my client notifies me).&lt;/p&gt;
&lt;p&gt;I thought about writing a bot (or in this case, extending one), to be
able to detect "interesting" threads and notify me about them. The first
approach involves detecting different "conversations". To keep it
simple, I just decided to define a conversation as a sequence of
messages within the same time frame (i.e. the difference between two
consecutive messages is small). Thus, a conversation ends when there is
a significant pause in the stream. This is a very simple approach, but
it's enough for the time being.&lt;/p&gt;
&lt;p&gt;Next, in order to determine if a conversation is interesting, I
calculate the probability of an user taking part of a given
conversation. This is simply the number of messages written by that
user , over the total number of messages in the conversation. If the
probability of a user taking part on a conversation assuming a second
user has taken part of the conversation (conditional probability --
bayes theorem) is "high enough", then the conversation can be marked
as "interesting" for the first user.&lt;/p&gt;
&lt;p&gt;So basically, the idea is to keep running conditional probabilities
for the active conversation in the channel, and if the conditional
probabilities match, just notify the user that the current
conversation might be of interest.&lt;/p&gt;
&lt;p&gt;Future ideas include:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
- fine tuning the "conversation" definition
- scanning for keywords, to make interests also dependent on the actual content of the conversation
- tracking interest relationships
&lt;/pre&gt;</description><guid>http://www.kirkner.com.ar/blog/experimenting-with-lalita/</guid><pubDate>Thu, 29 Oct 2009 17:18:26 GMT</pubDate></item><item><title>experimenting with live voice and aubionotes</title><link>http://www.kirkner.com.ar/blog/experimenting-with-live-voice-and-aubionotes/</link><dc:creator>Ricardo Kirkner</dc:creator><description>&lt;p&gt;Clearly, the aubionotes default pitch detector is quite sensitive when
analyzing vocal audio. It throws in a lot of in-between notes, which makes
the resulting midi output a bit "tremolous".&lt;/p&gt;
&lt;p&gt;I think now is the time to read more about the different pitch detection
functions, and/or other filters to try to make the pitch detection algorithm
less sensitive to small pitch variations, or else maybe even implementing my
own pitch detection algorithm.&lt;/p&gt;
&lt;p&gt;So far it has been a lot of fun!&lt;/p&gt;</description><guid>http://www.kirkner.com.ar/blog/experimenting-with-live-voice-and-aubionotes/</guid><pubDate>Mon, 28 Sep 2009 17:04:25 GMT</pubDate></item><item><title>experimenting with pitch detection</title><link>http://www.kirkner.com.ar/blog/experimenting-with-pitch-detection/</link><dc:creator>Ricardo Kirkner</dc:creator><description>&lt;p&gt;Last weekend I found about the aubio project. In their own words:&lt;/p&gt;
&lt;blockquote&gt;
aubio is a library for audio labelling. Its features include
segmenting a sound file before each of its attacks, performing pitch
detection, tapping the beat and producing midi streams from live
audio. [...]&lt;/blockquote&gt;
&lt;p&gt;In particular, one interesting piece of code is aubionotes. This
script analyzes audio data and produces a midi output stream from it
(what I was looking for!). I tried it out, but it turns that it wasn't
as straightforward as I would have liked, because it works on top of
the Jack audio server. What it does is to provide an audio input and a
midi output, and transforms any audio data received into a midi
stream.&lt;/p&gt;
&lt;p&gt;I have been struggling against it until I realized how it was supposed
to work (naturally, I came up with the idea on the way to work, so I
had to wait the whole day to try it out). As it happens, I was on the
(wrong) assumption that aubionotes would take the microphone input
directly. It was after I fully understood how it wanted to interact
with jack that I came to realize that I needed to use some software
that would communicate with jack. So right after work I installed
alsaplayer, recorded some audio, launched jack, launched aubionotes,
connected mi midi keyboard, plugged everything together using qjackctl
connections panel, and pressed 'play'. Oh what a joy! Midi notes were
being played on my keyboard, trying to mimic what I had been singing.
Even though a lot of extra notes were being played, I guess that's
alright for a first experiment (and can be considered noise), the
general idea of the tune I had sung could be heared being played in
the keyboard.&lt;/p&gt;
&lt;p&gt;Considering all the processing involved in order to convert voice to
midi notes, I call this first experiment a success.&lt;/p&gt;
&lt;p&gt;Now I have to figure out how to make jack use my microphone directly
to capture live audio, so I don't have to pre-record it.&lt;/p&gt;</description><guid>http://www.kirkner.com.ar/blog/experimenting-with-pitch-detection/</guid><pubDate>Mon, 28 Sep 2009 16:19:08 GMT</pubDate></item><item><title>starting with luciano</title><link>http://www.kirkner.com.ar/blog/starting-with-luciano/</link><dc:creator>Ricardo Kirkner</dc:creator><description>&lt;p&gt;Luciano is the latest addition to my collection of ongoing proyects.
The idea behind it is to have a tutor for enhancing your singing
skills.&lt;/p&gt;
&lt;p&gt;My goal with luciano is to make it capture input from a microphone,
analyze the voice audio, and map it to midi-like notes, so that it can
display the notes you are singing.
In addition to this, luciano will follow a score (for example a midi
file), and match the notes recognized in the raw audio input to the
notes that should have been sung.&lt;/p&gt;
&lt;p&gt;In that way, the singer will have a visual feedback to the way he/she
is singing. For example, he/she may see if the note he/she just sang
was correct or if it was out of pitch.&lt;/p&gt;
&lt;p&gt;The general idea is that by having the computer mark the errors, it
will make it easier for the singer to learn a particular score.&lt;/p&gt;</description><guid>http://www.kirkner.com.ar/blog/starting-with-luciano/</guid><pubDate>Mon, 28 Sep 2009 15:54:19 GMT</pubDate></item></channel></rss>