Blame platform-demos/es/guitar-tuner.py.page

Packit 1470ea
Packit 1470ea
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" type="topic" id="guitar-tuner.py" xml:lang="es">
Packit 1470ea
Packit 1470ea
  <info>
Packit 1470ea
    <title type="text">Afinador de guitarra (Python)</title>
Packit 1470ea
    <link type="guide" xref="py#examples"/>
Packit 1470ea
Packit 1470ea
    <desc>Usar GTK+ y GStreamer para construir un sencillo afinador de guitarra para GNOME. Muestra cómo usar el diseñador de interfaces.</desc>
Packit 1470ea
Packit 1470ea
    <revision pkgversion="0.1" version="0.1" date="2010-12-02" status="stub"/>
Packit 1470ea
    <credit type="author">
Packit 1470ea
      <name>Proyecto de documentación de GNOME</name>
Packit 1470ea
      <email its:translate="no">gnome-doc-list@gnome.org</email>
Packit 1470ea
    </credit>
Packit 1470ea
    <credit type="author">
Packit 1470ea
      <name>Johannes Schmid</name>
Packit 1470ea
      <email its:translate="no">jhs@gnome.org</email>
Packit 1470ea
    </credit>
Packit 1470ea
    <credit type="editor">
Packit 1470ea
      <name>Marta Maria Casetti</name>
Packit 1470ea
      <email its:translate="no">mmcasetti@gmail.com</email>
Packit 1470ea
      <years>2013</years>
Packit 1470ea
    </credit>
Packit 1470ea
    <credit type="editor">
Packit 1470ea
      <name>Marta Maria Casetti</name>
Packit 1470ea
      <email its:translate="no">mmcasetti@gmail.com</email>
Packit 1470ea
      <years>2013</years>
Packit 1470ea
    </credit>
Packit 1470ea
  
Packit 1470ea
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
Packit 1470ea
      <mal:name>Daniel Mustieles</mal:name>
Packit 1470ea
      <mal:email>daniel.mustieles@gmail.com</mal:email>
Packit 1470ea
      <mal:years>2011 - 2017</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  
Packit 1470ea
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
Packit 1470ea
      <mal:name>Nicolás Satragno</mal:name>
Packit 1470ea
      <mal:email>nsatragno@gmail.com</mal:email>
Packit 1470ea
      <mal:years>2012 - 2013</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  
Packit 1470ea
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
Packit 1470ea
      <mal:name>Jorge González</mal:name>
Packit 1470ea
      <mal:email>jorgegonz@svn.gnome.org</mal:email>
Packit 1470ea
      <mal:years>2011</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  </info>
Packit 1470ea
Packit 1470ea
<title>Afinador de guitarra</title>
Packit 1470ea
Packit 1470ea
<synopsis>
Packit 1470ea
  

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

Packit 1470ea
  <list>
Packit 1470ea
    <item>

Configurar un proyecto básico en Anjuta

</item>
Packit 1470ea
    <item>

Crear una IGU sencilla con el diseñador IU de Anjuta

</item>
Packit 1470ea
    <item>

Usar GStreamer para reproducir sonidos

</item>
Packit 1470ea
  </list>
Packit 1470ea
  

Necesitará lo siguiente para poder seguir este tutorial:

Packit 1470ea
  <list>
Packit 1470ea
    <item>

Una copia instalada del <link xref="getting-ready">EID Anjuta</link>

</item>
Packit 1470ea
    <item>

Conocimiento básico del lenguaje de programación Python

</item>
Packit 1470ea
  </list>
Packit 1470ea
</synopsis>
Packit 1470ea
Packit 1470ea
<media type="image" mime="image/png" src="media/guitar-tuner.png"/>
Packit 1470ea
Packit 1470ea
<section id="anjuta">
Packit 1470ea
  <title>Crear un proyecto en Anjuta</title>
Packit 1470ea
  

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.

Packit 1470ea
  <steps>
Packit 1470ea
    <item>
Packit 1470ea
    

Inicie Anjuta y pulse <guiseq><gui>Archivo</gui><gui>Nuevo</gui><gui>Proyecto</gui></guiseq> para abrir el asistente de proyectos.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
    

Seleccione <gui>PyGTK (automake)</gui> en la pestaña <gui>Python</gui>, pulse <gui>Continuar</gui>, y rellene los detalles en las siguientes páginas. Use <file>afinador-guiterra</file> como nombre del proyecto y de la carpeta.

Packit 1470ea
   	</item>
Packit 1470ea
    <item>
Packit 1470ea
    

Pulse <gui>Aplicar</gui> y se creará el proyecto. Abra <file>src/afinador-guitarra.py</file> desde las pestañas <gui>Proyecto</gui> o <gui>Archivo</gui>. Debería ver algo de código que comience con las líneas:

Packit 1470ea
    
Packit 1470ea
from gi.repository import Gtk, GdkPixbuf, Gdk
Packit 1470ea
import os, sys
Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="run">
Packit 1470ea
  <title>Ejecutar el código por primera vez</title>
Packit 1470ea
  

La mayor parte del código del archivo se usa como plantilla. 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:

Packit 1470ea
Packit 1470ea
  <list>
Packit 1470ea
  <item>
Packit 1470ea
    

Las líneas import en la parte superior indican a Python que cargue la interfaz de usuario y las bibliotecas del sistema necesarias.

Packit 1470ea
   </item>
Packit 1470ea
   <item>
Packit 1470ea
    

Se declara una clase que estará en la clase principal de la aplicación. En el método __init__ se carga la ventana principal desde el archivo de GtkBuilder (<file>src/guitar-tuner.ui</file>) y se conectan las señales.

Packit 1470ea
    

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 al método destroy (y se sale de la aplicación) cuando cierra la ventana.

Packit 1470ea
   </item>
Packit 1470ea
   <item>
Packit 1470ea
    

La función main se ejecuta de manera predeterminada cuando inicia una aplicación Python. Simplemente crea una instancia de la clase principal e inicia el bucle principal para mostrar la ventana.

Packit 1470ea
   </item>
Packit 1470ea
  </list>
Packit 1470ea
Packit 1470ea
  

Este código está listo para usarse, por lo que puede ejecutarlo pulsando <guiseq><gui>Ejecutar</gui><gui>Ejecutar</gui></guiseq>.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="ui">
Packit 1470ea
  <title>Crear la interfaz de usuario</title>
Packit 1470ea
  

El archivo de GtkBuilder contiene una descripción de la interfaz de usuario (IU). Para editar la interfaz de usuario, abra <file>src/guitar_tuner.ui</file>. 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 derecha, y la paleta de los widgets disponibles está a la izquierda.

Packit 1470ea
  

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

Packit 1470ea
Packit 1470ea
<media type="image" mime="image/png" src="media/guitar-tuner-glade.png"/>
Packit 1470ea
Packit 1470ea
  <steps>
Packit 1470ea
   <item>
Packit 1470ea
   

Seleccione una <gui>GtkButtonBox</gui> de la sección <gui>Contenedor</gui> de la <gui>Paleta</gui> de la derecha y póngalo en la ventana. En el panel de <gui>Propiedades</gui>, establezca el número de elementos a «6» (para las seis cuerdas) y la orientación a «vertical».

Packit 1470ea
   </item>
Packit 1470ea
   <item>
Packit 1470ea
    

Ahora, elija un <gui>GtkButton</gui> de la paleta y póngalo en la primera parte de la caja.

Packit 1470ea
   </item>
Packit 1470ea
   <item>
Packit 1470ea
    

Mientras el botón esté seleccionado, cambie la propiedad <gui>Etiqueta</gui> en la pestaña <gui>Widgets</gui> a <gui>E</gui>. Esta será la cuerda Mi grave.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
     

Cambie a la pestaña <gui>Señales</gui> (dentro de la pestaña <gui>Widgets</gui>) y busque la señal clicked del botón. Puede usar esto para conectar un manejador de señal al que se llamará cuando el usuario pulse el botón. Para hacer esto, pulse sobre la señal, escriba on_button_clicked en la columna <gui>Manejador</gui> y pulse <key>Intro</key>.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
    

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

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
    

Guarde el diseño de la IU (pulsando <guiseq><gui>Archivo</gui><gui>Guardar</gui></guiseq>) y déjelo abierto.

Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="signal">
Packit 1470ea
  <title>Escribir el manejador de señales</title>
Packit 1470ea
  

El el diseñador de interfaces, se ha hecho que todos los botones llamen a la misma función, <gui>on_button_clicked</gui>, cuando se pulsan. Se debe añadir esta función al archivo de código fuente.

Packit 1470ea

Para hacer esto, abra <file>guitar_tuner.py</file> mientras el archivo de la interfaz de usuario está abierto. Cambie a la pestaña <gui>Señales</gui>, que ya ha usado para establecer el nombre de la señal. Ahora vaya a la fila en la que estableció la señal <gui>clicked</gui> y arrástrela al archivo de código fuente, dentro de la clase principal. Se añadirá el siguiente código a su archivo de código fuente:

Packit 1470ea
Packit 1470ea
def on_button_clicked (self, button):
Packit 1470ea
Packit 1470ea
Packit 1470ea
  

Este manejador de la señal tiene dos argumentos: el puntero de clase Python habitual y el Gtk.Button que llamó a la función.

Packit 1470ea
  

Por ahora, se dejará el manejador de la señal vacío mientras se escribe el código para producir sonidos.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="gstreamer">
Packit 1470ea
  <title>Tuberías de Gstreamer</title>
Packit 1470ea
  

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.

Packit 1470ea
  

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.

Packit 1470ea
  

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.

Packit 1470ea
  <media type="image" mime="image/png" src="media/guitar-tuner-pipeline.png">
Packit 1470ea
    

Un ejemplo de tubería de GStreamer.

Packit 1470ea
  </media>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="pipeline">
Packit 1470ea
  <title>Configurar la tubería</title>
Packit 1470ea
  

En este sencillo 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.

Packit 1470ea
Packit 1470ea
  

Cambie la línea de importación en <file>afinador_guitarra.py</file>, justo al principio, por:

Packit 1470ea
  from gi.repository import Gtk, Gst, GObject 
Packit 1470ea
  

El Gst incluye la biblioteca GStreamer. También debe debe inicializar GStreamer correctamente, lo que se ha hecho en el método main() con esta llamada añadida encima de la línea app = GUI():

Packit 1470ea
  Gst.init_check(sys.argv)
Packit 1470ea
  

Después, copie la siguiente función en la de <file>guitar_tuner.py</file>, en cualquier sitio:

Packit 1470ea
  
Packit 1470ea
def play_sound(self, frequency):
Packit 1470ea
	pipeline = Gst.Pipeline(name='note')
Packit 1470ea
	source = Gst.ElementFactory.make('audiotestsrc', 'src')
Packit 1470ea
	sink = Gst.ElementFactory.make('autoaudiosink', 'output')
Packit 1470ea
Packit 1470ea
	source.set_property('freq', frequency)
Packit 1470ea
	pipeline.add(source)
Packit 1470ea
	pipeline.add(sink)
Packit 1470ea
	source.link(sink)
Packit 1470ea
	pipeline.set_state(Gst.State.PLAYING)
Packit 1470ea
Packit 1470ea
	GObject.timeout_add(self.LENGTH, self.pipeline_stop, pipeline)
Packit 1470ea
  <steps>
Packit 1470ea
    <item>
Packit 1470ea
    

Las tres primeras líneas crean los elementos «fuente» y «sumidero» de GStreamer y un elemento de tubería (que se usará como contenedor de los otros dos elementos). 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).

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
    

La llamada a source.set_property establece la propiedad freq del elemento fuente a frequency, que se pasa como argumento a la función play_sound. Esto sólo es la frecuencia de la nota en Hercios; más adelante se definirán algunas frecuencias útiles.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
    

Las dos siguientes líneas llaman a pipeline.add, poniendo la fuente y el sumidero en la tubería. La tubería puede contener muchos otros elementos de GStreamer. En general, puede añadir tantos elementos como quiera a una tubería llamando al método add repetidamente.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
    

El siguiente pipeline.set_state se usar para iniciar la reproducción, estableciendo el estado de la tubería a «playing» (Gst.State.PLAYING).

Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="playback">
Packit 1470ea
  <title>Detener la reproducción</title>
Packit 1470ea
  

No se quiere reproducir un tono molesto para siempre, por lo que lo último que play_sound hace es llamar a GObject.timeout_add. Esto establece un tiempo de expiración para detener el sonido; espera LENGTH milisegundos antes de llamar a la función pipeline_stop, y se queda llamando a pipeline_stop hasta que devuelve False.

Packit 1470ea
  

Ahora se escribirá el código de la función pipeline_stop, llamada por GObject.timeout_add. Inserte el código siguiente encima de la función play_sound:

Packit 1470ea
  
Packit 1470ea
def pipeline_stop(self, pipeline):
Packit 1470ea
	pipeline.set_state(Gst.State.NULL)
Packit 1470ea
	return False
Packit 1470ea
Packit 1470ea
  

Necesita definir la constante LENGTH dentro de la clase, por lo que debe añadir este código al principio de la clase principal:

Packit 1470ea
  
Packit 1470ea
LENGTH = 500
Packit 1470ea
Packit 1470ea
  

La llamada a pipeline.set_state detiene la reproducción de la tubería.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="tones">
Packit 1470ea
  <title>Definir los tonos</title>
Packit 1470ea
  

Se quiere reproducir el sonido correcto cuando un usuario pulsa un botón. En primer lugar, se necesita conocer las frecuencias de las seis cuerdas de la guitarra, que están definidas (al principio de la clase principal) dentro de un diccionario, por lo que se pueden mapear fácilmente con los nombres de las cuerdas:

Packit 1470ea
  
Packit 1470ea
# Frequencies of the strings
Packit 1470ea
frequencies = {
Packit 1470ea
	'E': 329.63,
Packit 1470ea
	'A': 440,
Packit 1470ea
	'D': 587.33,
Packit 1470ea
	'G': 783.99,
Packit 1470ea
	'B': 987.77,
Packit 1470ea
	'e': 1318.5
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
  

Ahora se se profundiza en el manejador de la señal definido anteriormente, on_button_clicked. Se podría haber conectado cada botón a un manejador 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:

Packit 1470ea
  
Packit 1470ea
def on_button_clicked(self, button):
Packit 1470ea
	label = button.get_child()
Packit 1470ea
	text = label.get_label()
Packit 1470ea
Packit 1470ea
	self.play_sound (self.frequencies[text])
Packit 1470ea
Packit 1470ea
  

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

Packit 1470ea
  

La etiqueta de texto se usa como clave para el diccionario, y se llama a play_sound con la frecuencia correspondiente a esa nota. Esto reproduce el tono; el afinador de guitarra ya está funcionando.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="run2">
Packit 1470ea
  <title>Ejecutar la aplicación</title>
Packit 1470ea
  

Todo el código debería estar listo para ejecutarse. Pulse <guiseq><gui>Ejecutar</gui><gui>Ejecutar</gui></guiseq> para iniciar la aplicación y disfrute.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="impl">
Packit 1470ea
 <title>Implementación de referencia</title>
Packit 1470ea
 

Si tiene problemas con este tutorial, compare su código con este <link href="guitar-tuner/guitar-tuner.py">código de referencia</link>.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="next">
Packit 1470ea
  <title>Siguientes pasos</title>
Packit 1470ea
  

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

Packit 1470ea
  <list>
Packit 1470ea
   <item>
Packit 1470ea
   

Hacer que el programa recorra las notas automáticamente.

Packit 1470ea
   </item>
Packit 1470ea
   <item>
Packit 1470ea
   

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

Packit 1470ea
   

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 <link href="http://gstreamer.freedesktop.org/documentation/plugins.html">decodificador y demultiplexor</link> 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.

Packit 1470ea
   

Puede querer conectar los elementos de maneras más complicadas. Esto puede implicar usar <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-intro-basics.html">conceptos de GStreamer</link> que no se han comentado en este tutorial, tales como <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-intro-basics-pads.html">interfaces</link>. Es posible que encuentre útil el comando <cmd>gst-inspect</cmd>.

Packit 1470ea
   </item>
Packit 1470ea
   <item>
Packit 1470ea
   

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

Packit 1470ea
   

Puede conectar un micrófono y grabar sonidos con él usando una <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-autoaudiosrc.html">fuente de entrada</link>. ¿Es posible que algún tipo de <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-plugin-spectrum.html">análisis de espectro</link> le permita saber qué notas se están reproduciendo?

Packit 1470ea
   </item>
Packit 1470ea
  </list>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
</page>