jueves, 15 de agosto de 2013

Dropbox on a multiboot system with Debian

Motivation

Many Linux users might have problems when using the cloud synchronization tool known as Dropbox on a multiboot system. The problem arises when trying to have a Dropbox set-up on both Windows and Linux OS arising "syncronization issues", if you tried this before, you'll understand.
So i searched for solutions to this "issue", but all the proposed ways to solve it were... well, not so elegant for me.

The way i got dropbox working both on Debian GNU/Linux and Windows (same PC)

A little 'bout context

I've already have a Windows-7 OS installed, with a working Dropbox installation at

D:\Daniel\Dropbox

Without having a working installation of Dropbox at Debian.

Making symbolic links on Linux

On Debian, I've the "D:\" windows partition as "/dev/sda5", and is mounted on

/media/Disco-Local/

I wanted to have my Linux-Dropbox folder at

/home/damejia/Dropbox

So work with those locations. Given the context, boot Debian and open a terminal, to login as superuser type

$ su

It will ask you the "root" password. Then, do the following

# ln -s  /media/Disco-Local/Daniel/Dropbox  /home/damejia/Dropbox

This will create a link between both paths, so, the /home/damejia/Dropbox points to  /media/Disco-Local/Daniel/Dropbox

Change the group and the owner of the link created (in my case, the user is damejia)

# chown -R damejia  /home/damejia/Dropbox
# chgrp -R damejia  /home/damejia/Dropbox

We are ready to install Dropbox

Intalling Dropbox on Debian

Then, download the latest version of Dropbox for Debian (they have the .deb), and, from the console install the packe using dpkg (as root, is worth noting that you must be on the same directory as the package)

# dpkg -i dropbox-x.x.x-amd64.deb

On the first run of Dropbox on Debian, it will ask you for the folder to store the syched files. choose

/home/damejia/Dropbox

That is, choosing the link we created before. And... that's it, the Dropbox must appear as synched, since you haven't added files, you will have the same Dropbox path on either Windows or Linux.

lunes, 12 de agosto de 2013

Conozcamos la STL (Standard Template Library) de C++ - Primera entrega: std::map - Parte 1 de 2

Introducción

Mucha personas (como yo en el pasado cercano) ignorarán el poder oculto detrás de las siglas STL. Se trata de nada más ni nada menos que una de las "cosas" que convierte a C++ en uno de los lenguajes de programación más poderosos. La STL o Standard Template Library 
La STL proporciona una colección de estructuras de datos contenedoras y algoritmos genéricos que se pueden utilizar con éstas.
(tomado de aquí: http://decsai.ugr.es/~jfv/ed1/c++/cdrom4/paginaWeb/stl.htm)

En esta entrega trataré de ilustrar el uso del contenedor map, a través de algunos ejemplos prácticos.

Dada la extensión que pretendía dar a este tema, decidí dividirlo en dos entradas independientes y complementarias.
La primera  parte de esta entrega (es decir, este post) consiste en la implementación del contenedor std::map con los tipos de datos incluidos en el estándar de C++.

En la segunda parte (disponible aquí) abordaré la implementación del contenedor std::map haciendo uso de una clase propia, es decir, una clase que hemos hecho nosotros mismos, tal como lo ilustramos en  una entrega previa, donde hemos definido una clase para la manipulación de vectores.

Contenedor std::map de la STL

Generalidades del contenedor std::map

Uno de esos contenedores incluidos en la STL corresponde a map, un contenedor de datos donde cada uno posee una clave(key en inglés) que lo identifica. Para utilizar map es necesario incluirlo en la cabecera de nuestro código fuente:
#include<map>
De esta manera, es posible hacer el llamado
std::map<tipo_variable_1 clave,tipo_variable_2 valor, criterio_comparación_clave> variable_map;
 De esta manera, se puede declarar una varible tipo map, en este caso: variable_map. Esta definición parece un poco ambigua de entender, pero todo es más claro en cuanto se entiende que la variable map lo que hace es etiquetar con la variable clave lo que contiene la variable valor. Para realizar el ordenamiento, el contenedor map utiliza un criterio de comparación basándose en alguna operación de comparación, específicamente, usando el operador< definido para del tipo_variable_1, es por esta razón que el operador< debe estar definido para el tipo de variable utilizado como clave.
Para realizar la asignación de valores a nuestro mapa, basta con escribir
variable_map[valor_tipo_variable_1]=valor_tipo_variable_2;
Para ver claramente lo que acabo de exponer, observemos el siguiente ejemplo (código c++, obviamente)



#include<iostream>
#include<string>
#include<map>


int main(void)
{
        std::map<int /*indice o clave*/, std::string /*contenido*/> mi_mapa;

       std::string palabra;

        for(int i(0);i<5;i++)
        {
                std::cout << "Ingrese una palabra: " << std::endl;
                std::cin>>palabra;
                mi_mapa[i]=palabra;
        }


        for(i=0;i<5;i++)
        {
                std::cout << "Palabra almacenada con clave " << i << " es " << mi_mapa[i] << std::endl;
        }
}


Vemos que en el ejemplo hemos usado map como si se tratase de un array. Sin embargo, la diferencia sustancial es que la información se ha guardado de manera ordenada en función del valor de i. Este comportamiento no es visible a simple vista, puesto que el orden de entrada de los datos ya están ordenados, pero considere el siguiente ejemplo

#include<iostream>
#include<string>
#include<map>

int main(void)
{
        std::map<int /*indice o clave*/, std::string /*contenido*/> mi_mapa;
        std::string palabra;
        int numero;


        for(int i(0);i<5;i++)
        {
                std::cout << "Ingrese un número: " << std::endl;
                std::cin >> numero;

                std::cout << "Ingrese una palabra: " << std::endl;
                std::cin >> palabra;


                mi_mapa[numero]=palabra;
        }


        for(i=0;i<5;i++)
        {
                std::cout << "Palabra almacenada con clave " << i << " es " << mi_mapa[i] << std::endl;
        }

}

En este caso, vemos que para cada valor no repetido de i, se muestra un valor de palabra. es decir, que para cada int i, se ha asignado una variable std::string. Este uso sigue siento familiar con el uso de los arrays. Podemos probar cambiando los tipos de variable en la definición de la variable tipo map. Considere el siguiente ejemplo

#include<iostream>
#include<string>
#include<map>

int main(void)
{
        std::map<std::string /*indice_palabra*/,int /*indice_numero*/> mi_mapa;
        std::string palabra;
        int numero;

        mi_mapa["hola"]=10;
        mi_mapa["alfabeto"]=5;
        mi_mapa["zoo"]=0;
        mi_mapa["a"]=3;
        mi_mapa["marmota"]=9;


        std::cout << " La palabra \"alfabeto\" tiene asignado el número " << mi_mapa["alfabeto"] << std::endl;
        std::cout << " La palabra \"a\" tiene asignado el número " << mi_mapa["a"] << std::endl;

        std::cout << " La palabra \"hola\" tiene asignado el número " << mi_mapa["hola"] << std::endl;
        std::cout << " La palabra \"marmota\" tiene asignado el número " << mi_mapa["marmota"] << std::endl;



}

A cada std::string se ha asignado un valor numérico tipo int, de esta manera, los llamados a cada int se realizan mediante el std::string correspondiente a su clave.

Considere ahora el siguiente ejemplo

#include<iostream>
#include<string>
#include<map>

int main(void)
{
        std::map<std::string /*indice_palabra*/,int /*indice_numero*/> mi_mapa;
        std::string palabra;
        int numero;


        for(int i(0);i<5;i++)
        {
                std::cout << "Ingrese un número: " << std::endl;
                std::in >> numero;

                std::cout << "Ingrese una palabra: " << std::endl;
                std::in >> palabra;


                mi_mapa[palabra]=numero;
                std::cout << " La palabra << palabra << " tiene asignado el número " << mi_mapa[palabra] << std::endl;

        }

}

En este caso, a cada palabra ingresada por el usuario, se ha asignado un valor numérico también ingresado por el usuario. El ordenamiento se hace según el operador< definido en la clase std::string.

jueves, 8 de agosto de 2013

System sound equalized with ALSA for Debian - Get-yo-self equalized!

(Still working on 2015. See workarounds at the end)

Motivation

Like many people, i really enjoy listening music, an, as many would know, having an equalizer can make a really big difference between "the ordinary experience" of listening music.
It's clear that many media players include plugins for audio enhancing, but, whan happens when you listen a music video on youtube, or just simply using grooveshark cloud music service?. For Windows machines the solution could be installing audio-enhancing software like DFX (A really good one, i can tell). But that kind of "stuff" isn't available for Linux. Maybe 'cause we have other kind of solutions, i have found one that works amazing, but you must have ALSA installed on your Linux distribution.

What is the ALSA System?

Many of you may wonder, hows that your Linux Distro communicates with your speakers/headphones/microphon/any-sound-device. Well, there are many ways to get the task donde, but, for Debian distributions (So, for the wide set of Debian-based distros like Ubunty, Mint, and so on) the ALSA system do the job. In words of Wikipedia [1]:
Advanced Linux Sound Architecture (known by the acronym ALSA) is a free, open source software framework released under the GNU GPL and the GNU LGPL[4] that provides an API for sound carddevice drivers. It is part of the Linux kernel. Some of the goals of the ALSA project at its inception were automatic configuration of sound-card hardware and graceful handling of multiple sound devices in a system, goals which it has largely met. A couple of different frameworks, such as JACK, use ALSA to allow performing low-latency professional-grade audio editing and mixing.
So

ALSA Equalizer

Getting the equalizer installed

Installing from repos (Debian Testing and Sid)

In the Debian Testing repositories we have the package libasound2-plugin-equal

The plugin on my Debian repository

In order to have the equalizer installed, as root, do:
# aptitude install libasound2-plugin-equal alsamixergui

  • libasound2-plugin-equal - The equalizer itself
  • alsamixergui - A GUI To control de plugin, but it's optional, cause you can use the command-line alsamixer. Unfortunatetly the only way to control the equalizer is to make use of the alsamixer utility

Manual Installing

For other linux distros, download the latest version of the plugin from here (look for "download")
Then, choose a folder and do

tar xvjf alsaequal-x.x.tar.bz2
cd alsaequal-x.x
make
sudo make install
You should read carefuly the reference [2]

Getting the equalizer to work

Single user

Into your "home" directory ("/home/user" for instance) create a file called ".asoundrc" and paste this code onto it (for more information see [2] and [3] from the references section below)
ctl.equal {
  type equal;
}
pcm.plugequal {
  type equal;
  # Modify the line below if you don't
  # want to use sound card 0.
  slave.pcm "plughw:0,0";
  # or if you want to use with multiple applications output to dmix
  # slave.pcm "plug:dmix"
}
# pcm.equal {
  # Or if you want the equalizer to be your
  # default soundcard uncomment the following
  # line and comment the above line.
 pcm.!default {
  type plug;
  slave.pcm plugequal;
}
Then, as root, you must do

# alsa force-reload

So the sound daemon restarts and loads the plugin. The equalizer should be working now.

Whole system (all users)

You must create the file

/etc/asound.conf

And paste this code onto it (for more information see [2] and [3] from the references section below, take a look at [4] too)
ctl.equal {
  type equal;
}
pcm.plugequal {
  type equal;
  # Modify the line below if you don't
  # want to use sound card 0.
  slave.pcm "plughw:0,0";
  # or if you want to use with multiple applications output to dmix
  # slave.pcm "plug:dmix"
}
# pcm.equal {
  # Or if you want the equalizer to be your
  # default soundcard uncomment the following
  # line and comment the above line.
 pcm.!default {
  type plug;
  slave.pcm plugequal;
}
Then, as root, you must do

# alsa force-reload

So the sound daemon restarts and loads the plugin. The equalizer should be working now.

Using the equalizer

The plugin installs a "virtual" audio device. This device is called "equal" (for obvious reasons).
If you followed the steps above, you shouln't have problems now.
To change the equalizer configuration, you must tell ALSA that you want to work with the "equal" device, so open a terminal and write either

$ alsamixer -D equal


This is how it looks on command line
or

$ alsamixergui -D equal


This is how it looks using alsamixergui

And choose your best audio configuration, and enjoy your audio-enhanced linux distro.

Some Workarounds (edit: 2015-Feb-04)


The above instructions still worked for me (I've resintalled Debian Testing on my PC on January of 2015), but I've noticed two little workarounds that might be of importance if you have more than a sound card or you have been experiencing no sound with web pages as youtube using google-chrome.

More than a soundcard

I've changed my motherd board and has two different sound cards which caused my system to direct the equalized sound stream to the "wrong" sound card.

Thanks to this post [7] I became aware of the need of tweaking the file /usr/share/alsa/alsa.conf in order to get ALSA using the "right" sound card.
If the working sound card is hw:0,1 and the "bad" sound card is hw:0,0, and you used hw:0,1 on your asound.conf as stated on the sections above, but still without equalized sound, you need to tell ALSA that start using sound card 1 (i.e. hw:0,1 in our example) on the file /usr/share/alsa/alsa.conf by changing the following lines:
defaults.ctl.card 0 to defaults.ctl.card 1
defaults.pcm.card 1 to defaults.pcm.card 1
defaults.rawmidi.card 1 to defaults.rawmidi.card 1
defaults.hwdep.card 1 to defaults.hwdep.card 1
defaults.timer.card 1 to defaults.timer.card 1

Youtube and HTML5 on google-chrome

Youtube video players were switched to use HTML5 (google it for more information). I don't know why the sound layer works if you use PulseAudio but if you have only ALSA, the sound migth not work (for me it was working anddd... the sound was gone).

The solution for google-chrome is to start the browser with the option

--try-supported-channel-layouts
So call google-chrome as

google-chrome --try-supported-channel-layouts

And play a nice youtube video, if that works for you, you can edit the menu entries and links to google-chrome adding the mentioned command option.
Resampling can be another issue (I can not tell about that but google product forum talks about it), some forums suggest to add the option --disable-audio-output-resampler, so another solution could be calling google-chrome as

google-chrome --disable-audio-output-resampler --try-supported-channel-layouts 
If that does not help you... Well... F*ck. 

References

  1. http://es.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture
  2. http://www.thedigitalmachine.net/alsaequal.html
  3. http://wiki.linuxmce.org/index.php/Equalizer_for_ALSA
  4. http://www.alsa-project.org/main/index.php/Asoundrc
  5. http://packages.debian.org/source/sid/alsaequal
  6. Download my asound.conf 
  7. https://coderwall.com/p/wajiaq/replacing-pulseaudio-with-alsa-linux