Usar GTK+ y GStreamer para construir una sencilla aplicación de afinador de guitarra para GNOME. Muestra cómo usar el diseñador de interfaces.
Proyecto de documentación de GNOME
gnome-doc-list@gnome.org
Johannes Schmid
jhs@gnome.org
Tiffany Antopolski
tiffany.antopolski@gmail.com
Marta Maria Casetti
mmcasetti@gmail.com 2013
Daniel Mustieles
daniel.mustieles@gmail.com 2011 - 2020
Nicolás Satragno
nsatragno@gmail.com 2012 - 2013
Jorge González
jorgegonz@svn.gnome.org 2011

# Afinador de guitarra

      En este tutorial se va a hacer un programa que reproduce tonos que puede usar para afinar su guitarra. Aprenderá a:

        Configurar un proyecto básico usando el EID Anjuta.
        Crear una IGU sencilla con el diseñador de IU de Anjuta.
        Usar la biblioteca GStreamer para reproducir sonidos.

      Necesitará lo siguiente para poder seguir este tutorial:

        Conocimiento básico del lenguaje de programación Vala.
        Una copia instalada de Anjuta.

# Crear un proyecto en Anjuta

Antes de empezar a programar, deberá configurar un proyecto nuevo en Anjuta. Esto creará todos los archivos que necesite para construir y ejecutar el código más adelante. También es útil para mantener todo ordenado.

Inicie Anjuta y pulse Crear un proyecto nuevo o ArchivoNuevoProyecto para abrir el asistente de proyectos.

Pulse en la pestaña Vala y seleccione GTK+ (simple). Pulse Continuar, y rellene los detalles en las siguientes páginas. Use afinador-guitarra como nombre del proyecto y de la carpeta.

Asegúrese de que Configurar paquetes externos está activada. En la siguiente página, seleccione gstreamer-0.10 de la lista para incluir la biblioteca GStreamer en su proyecto. Pulse Continuar

Pulse Aplicar y se creará el proyecto. Abra src/guitar_tuner.vala desde las pestañas Proyecto o Archivo pulsando dos veces sobre él. Debería ver algo de código que comience con las líneas:

using GLib; using Gtk;

# Construir el código por primera vez

El código carga una ventana (vacía) desde el archivo de descripción de interfaz de usuario y la muestra. Se ofrecen más detalles a continuación; omita esta lista si entiende los conceptos básicos:

Las dos líneas `using` importan espacios de nombres, por lo que no hay que nombrarlas explícitamente.

El constructor de la clase `Main` crea una ventana nueva abriendo un archivo de GtkBuilder (src/guitar-tuner.ui, definido unas pocas líneas más arriba), conectando sus señales y mostrándolo en una ventana. El archivo de GtkBuilder contiene una descripción de una interfaz de usuario y de todos sus elementos. Puede usar el editor Anjuta para diseñar interfaces de usuario con GtkBuilder.

Conectar señales es como se define lo que pasa cuando pulsa un botón, o cuando ocurre algún otro evento. Aquí, se llama a la función `on_destroy` (y se sale de la aplicación) cuando cierra la ventana.

La función estática `main` se ejecuta de manera predeterminada cuando inicia una aplicación en Vala. Llama a algunas funciones que crean la clase «Main» y configuran y ejecutan la aplicación. La función `Gtk.main` inicia el bucle principal de GTK+, que ejecuta la interfaz de usuario y empieza a escuchar eventos (como pulsaciones del ratón y del teclado).

Este código está listo para usarse, por lo que puede compilarlo pulsando ConstruirConstruir proyecto (o pulsando MayúsF7). Cuando lo haga, aparecerá un diálogo. Cambie la Configuración a Predeterminada y pulse Ejecutar para configurar la carpeta de construcción. Sólo tendrá que hacer esto una vez, para la primera construcción.

# Crear la interfaz de usuario

El archivo de GtkBuilder src/guitar_tuner.ui contiene una descripción de la interfaz de usuario (IU), definida en la parte superior de la clase. Para editar la interfaz de usuario, abra src/guitar_tuner.ui pulsando dos veces sobre el archivo en las secciones Proyecto or Archivos. Esto cambiará al diseñador de interfaces. La ventana de diseño está en el centro; los Widgets y sus propiedades están a la izquierda, y la Paleta de los widgets disponibles está a la derecha.

La distribución de cualquier IU en GTK+ se organiza usando cajas y tablas. Aquí se usará una GtkButtonBox vertical para asignar seis GtkButtons, uno para cada una de las cuerdas de la guitarra.

En la pestaña Paleta, en la sección Contenedores, seleccione una Caja de botones (GtkButtonBox) pulsando sobre el icono. Pulse en el centro del diseño de la ventana para colocarla en la ventana. Se mostrará un diálogo donde puede establecer el Número de elementos a 6. Luego pulse en Crear.

También puede cambiar el Número de elementos y la Orientación en la pestaña General a la derecha.

Ahora, desde la sección Controlar y mostrar de la Paleta elija un Botón (GtkButton) pulsando sobre él. Sitúelo en la primera sección de la GtkButtonBox pulsando sobre ella.

Mientras el botón esté seleccionado, cambie la propiedad Etiqueta en la pestaña General a E. Esta será la cuerda Mi grave de la guitarra.

La pestaña General se encuentra en la sección Widgets de la derecha.

Cambie a la pestaña Señales dentro de la sección Widgets a la derecha y busque la señal `clicked` del botón. Puede usar esto para conectar un gestor de señal al que se llamará cuando el usuario pulse el botón. Para hacer esto, pulse sobre la señal, escriba `main_on_button_clicked` en la columna Gestor y pulse Intro.

Repita los pasos anteriores para el resto de botones, añadiendo las 5 cuerdas restantes con los nombres A, D, G, B, y e.

Guarde el diseño de la IU (pulsando ArchivoGuardar) y déjelo abierto.

# Tuberías de Gstreamer

En esta sección se mostrará cómo crear el código para generar sonidos. GStreamer es el entorno multimedia de trabajo de GNOME: puede usarlo para reproducir, grabar y procesar vídeo, sonido, flujos de la cámara web y similares. En este caso, se usará para generar tonos de frecuencia única.

Conceptualmente. GStreamer funciona de la siguiente manera: puede crear una tubería que contenga varios elementos de procesado que van desde la fuente hasta el sumidero (salida). La fuente puede ser, por ejemplo, un archivo de imagen, un vídeo o un archivo de música, y la salida puede ser un widget o la tarjeta de sonido.

Entre la fuente y el sumidero, puede aplicar varios filtros y conversores para manejar efectos, conversiones de formato, etc. Cada elemento de la tubería tiene propiedades que se pueden usar para cambiar este comportamiento.

Un ejemplo de tubería de GStreamer.

# Configurar la tubería

En este ejemplo se usará un generador de tonos llamado `audiotestsrc` y se enviará la salida al dispositivo de sonido predeterminado del sistema, `autoaudiosink`. Sólo es necesario configurar la frecuencia del generador de tonos; esto es accesible a través de la propiedad `freq` de `audiotestsrc`.

Se debe añadir una línea para inicializar GStreamer; ponga el siguiente código encima de la llamada a `Gtk.init`, en la función `main`:

Gst.init (ref args);

Después, copie la siguiente función en guitar_tuner.vala dentro de la clase `Main`:

Gst.Element sink; Gst.Element source; Gst.Pipeline pipeline;

private void play_sound(double frequency) { pipeline = new Gst.Pipeline ("note"); source = Gst.ElementFactory.make ("audiotestsrc", "source"); sink = Gst.ElementFactory.make ("autoaudiosink", "output");

/* set frequency */ source.set ("freq", frequency);

pipeline.add (source); pipeline.add (sink); source.link (sink);

pipeline.set_state (Gst.State.PLAYING);

/* stop it after 200ms */ var time = new TimeoutSource(200);

time.set_callback(() => { pipeline.set_state (Gst.State.NULL); return false; }); time.attach(null); }

Las cinco primeras líneas crean los elementos «fuente» y «sumidero» de GStreamer (`Gst.Element`), y un elemento de tubería (que se usará como contenedor de los otros dos elementos). Son variables de clase, por lo que se definen fuera del método. A la tubería se le asigna el nombre «note»; la fuente se llama «source» y se asocia a la fuente `audiotestsrc` y el sumidero se llama «output» y se asocia con el sumidero `autoaudiosink` (la salida de la tarjeta de sonido predeterminada).

La llamada a `source.set` establece la propiedad `freq` del elemento fuente a `frequency`, que se pasa como argumento a la función `play_sound`. Esto sólo es la frecuencia de la nota en Hercios; más adelante se definirán algunas frecuencias útiles.

`pipeline.add` añade la fuente y el sumidero a la tubería. La tubería es un `Gst.Bin`, que es un elemento que puede contener otros muchos elementos de GStreamer. En general, puede añadir tantos elementos como quiera a una tubería añadiendo más argumentos a `pipeline.add`.

Ahora, el código `sink.link` se usa para conectar los elementos entre sí, por lo que la salida de la fuente (un tono) va a la entrada del sumidero (y entonces sale por la tarjeta de sonido). `pipeline.set_state` se usa para iniciar la reproducción estableciendo el estado de la tubería a «playing» (`Gst.State.PLAYING`).

No se quiere reproducir un tono molesto para siempre, por lo que lo último que `play_sound` hace es añadir un `TimeoutSource`. Esto establece un tiempo de expiración para detener el sonido; espera 200 milisegundos antes de llamar a un gestor de la señal definido en línea y destruye la tubería. Devuelve`false` para quitarse a sí mismo del tiempo de expiración, ya que de otro modo, seguiría llamándose cada 200ms,

# Crear el gestor de señales

El el diseñador de interfaces se hizo que todos los botones llamaran a la misma función, on_button_clicked cuando se pulsasen. Ahora se escribe main_on_button_clicked, lo que indica al diseñador de interfaces que este método es parte de la función `Main`. Se debe añadir esta función al archivo de código fuente.

Para hacer esto, en el archivo de interfaz del usuario (guitar_tuner.ui), seleccione uno de los botones pulsando sobre él, abra guitar_tuner.vala (pulsando en la pestaña en el centro). Cambie a la pestaña Señales de la derecha, que ya ha usado para establecer el nombre de la señal. Ahora vaya a la fila en la que estableció la señal clicked y arrástrela al archivo de código fuente, al principio de la clase. Se añadirá el siguiente código a su archivo de código fuente:

public void on_button_clicked (Gtk.Button sender) {

}

También puede escribir simplemente el texto al principio de la clase en vez de arrastrar y soltar.

El gestor de la señal sólo tiene un argumento: el `Gtk.Widget` que llama a la función (en este caso, siempre es un `Gtk.Button`).

# Definir el gestor de señales

Se quiere reproducir el sonido correcto cuando el usuario pulsa un botón. Para esto, se profundiza en el gestor de la señal definido anteriormente, `on_button_clicked`. Se podría haber conectado cada botón a un gestor de la señal diferente, pero esto había supuesto duplicar mucho código. En su lugar, se puede usar la etiqueta del botón para saber cuál de ellos se ha pulsado:

public void on_button_clicked (Gtk.Button sender) { var label = sender.get_child () as Gtk.Label; switch (label.get_label()) { case "E": play_sound (329.63); break; case "A": play_sound (440); break; case "D": play_sound (587.33); break; case "G": play_sound (783.99); break; case "B": play_sound (987.77); break; case "e": play_sound (1318); break; default: break; } }

El `Gtk.Button` que se ha pulsado se pasa como argumento (`sender`) a `on_button_clicked`. Se puede obtener la etiqueta de ese botón usando `get_child`, y entonces obtener el texto de esa etiqueta usando `get_label`.

La sentencia «switch» compara la etiqueta de texto con las notas que se pueden reproducir, y se llama a `play_sound` con la frecuencia correspondiente a esa nota. Esto reproduce el tono; el afinador de guitarra ya está funcionando.

# Construir y ejecutar la aplicación

Todo el código debería estar listo para ejecutarse. Pulse ConstruirConstruir proyecto para construir todo otra vez y pulse EjecutarEjecutar para iniciar la aplicación.

Si todavía no lo ha hecho, elija la aplicación Debug/src/afinador-guitarra en el diálogo que aparece. Finalmente, pulse Ejecutar y disfrute.

# Implementación de referencia

Si tiene problemas con este tutorial, compare su código con este código de referencia.

# Lectura complementaria

Para obtener más información sobre el lenguaje de programación Vala, puede querer revisar el Tutorial de Vala y la documentación de la API de Vala

# Siguientes pasos

Aquí hay algunas ideas sobre cómo puede extender esta sencilla demostración:

Hacer que el programa recorra las notas automáticamente.

Hacer que el programa reproduzca grabaciones de cuerdas de guitarras que se están afinando.

PAra hacer esto, debe configurar una tubería de GStreamer más complicada, que le permite cargar y reproducir archivos de música. Deberá elegir un los elementos decodificador y demultiplexor de GStreamer basándose en el formato del archivo de sus sonidos grabados; los MP3 usan elementos diferentes de los de los archivos Ogg Vorbis, por ejemplo.

Puede querer conectar los elementos de maneras más complicadas. Esto puede implicar usar conceptos de GStreamer que no se han comentado en este tutorial, tales como interfaces. Es posible que encuentre útil el comando gst-inspect.

Analizar automáticamente las notas que toca el músico.

Puede conectar un micrófono y grabar sonidos con él usando una fuente de entrada. ¿Es posible que algún tipo de análisis de espectro le permita saber qué notas se están reproduciendo?