1<?xml version="1.0" encoding="utf-8"?>
2<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">
3
4  <info>
5    <title type="text">Afinador de guitarra (Python)</title>
6    <link type="guide" xref="py#examples"/>
7
8    <desc>Usar GTK+ y GStreamer para construir un sencillo afinador de guitarra para GNOME. Muestra cómo usar el diseñador de interfaces.</desc>
9
10    <revision pkgversion="0.1" version="0.1" date="2010-12-02" status="stub"/>
11    <credit type="author">
12      <name>Proyecto de documentación de GNOME</name>
13      <email its:translate="no">gnome-doc-list@gnome.org</email>
14    </credit>
15    <credit type="author">
16      <name>Johannes Schmid</name>
17      <email its:translate="no">jhs@gnome.org</email>
18    </credit>
19    <credit type="editor">
20      <name>Marta Maria Casetti</name>
21      <email its:translate="no">mmcasetti@gmail.com</email>
22      <years>2013</years>
23    </credit>
24    <credit type="editor">
25      <name>Marta Maria Casetti</name>
26      <email its:translate="no">mmcasetti@gmail.com</email>
27      <years>2013</years>
28    </credit>
29
30    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
31      <mal:name>Daniel Mustieles</mal:name>
32      <mal:email>daniel.mustieles@gmail.com</mal:email>
33      <mal:years>2011 - 2020</mal:years>
34    </mal:credit>
35
36    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
37      <mal:name>Nicolás Satragno</mal:name>
38      <mal:email>nsatragno@gmail.com</mal:email>
39      <mal:years>2012 - 2013</mal:years>
40    </mal:credit>
41
42    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
43      <mal:name>Jorge González</mal:name>
44      <mal:email>jorgegonz@svn.gnome.org</mal:email>
45      <mal:years>2011</mal:years>
46    </mal:credit>
47  </info>
48
49<title>Afinador de guitarra</title>
50
51<synopsis>
52  <p>En este tutorial se va a hacer un programa que reproduce tonos que puede usar para afinar su guitarra. Aprenderá a:</p>
53  <list>
54    <item><p>Configurar un proyecto básico en Anjuta</p></item>
55    <item><p>Crear una IGU sencilla con el diseñador IU de Anjuta</p></item>
56    <item><p>Usar GStreamer para reproducir sonidos</p></item>
57  </list>
58  <p>Necesitará lo siguiente para poder seguir este tutorial:</p>
59  <list>
60    <item><p>Una copia instalada del <link xref="getting-ready">EID Anjuta</link></p></item>
61    <item><p>Conocimiento básico del lenguaje de programación Python</p></item>
62  </list>
63</synopsis>
64
65<media type="image" mime="image/png" src="media/guitar-tuner.png"/>
66
67<section id="anjuta">
68  <title>Crear un proyecto en Anjuta</title>
69  <p>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.</p>
70  <steps>
71    <item>
72    <p>Inicie Anjuta y pulse <guiseq><gui>Archivo</gui><gui>Nuevo</gui><gui>Proyecto</gui></guiseq> para abrir el asistente de proyectos.</p>
73    </item>
74    <item>
75    <p>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.</p>
76   	</item>
77    <item>
78    <p>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:</p>
79    <code mime="test/x-python">
80from gi.repository import Gtk, GdkPixbuf, Gdk
81import os, sys</code>
82    </item>
83  </steps>
84</section>
85
86<section id="run">
87  <title>Ejecutar el código por primera vez</title>
88  <p>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:</p>
89
90  <list>
91  <item>
92    <p>Las líneas <code>import</code> en la parte superior indican a Python que cargue la interfaz de usuario y las bibliotecas del sistema necesarias.</p>
93   </item>
94   <item>
95    <p>Se declara una clase que estará en la clase principal de la aplicación. En el método <code>__init__</code> se carga la ventana principal desde el archivo de GtkBuilder (<file>src/guitar-tuner.ui</file>) y se conectan las señales.</p>
96    <p>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 <code>destroy</code> (y se sale de la aplicación) cuando cierra la ventana.</p>
97   </item>
98   <item>
99    <p>La función <code>main</code> 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.</p>
100   </item>
101  </list>
102
103  <p>Este código está listo para usarse, por lo que puede ejecutarlo pulsando <guiseq><gui>Ejecutar</gui><gui>Ejecutar</gui></guiseq>.</p>
104</section>
105
106<section id="ui">
107  <title>Crear la interfaz de usuario</title>
108  <p>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.</p>
109  <p>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.</p>
110
111<media type="image" mime="image/png" src="media/guitar-tuner-glade.png"/>
112
113  <steps>
114   <item>
115   <p>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».</p>
116   </item>
117   <item>
118    <p>Ahora, elija un <gui>GtkButton</gui> de la paleta y póngalo en la primera parte de la caja.</p>
119   </item>
120   <item>
121    <p>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.</p>
122    </item>
123    <item>
124     <p>Cambie a la pestaña <gui>Señales</gui> (dentro de la pestaña <gui>Widgets</gui>) y busque la señal <code>clicked</code> 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 <code>on_button_clicked</code> en la columna <gui>Gestor</gui> y pulse <key>Intro</key>.</p>
125    </item>
126    <item>
127    <p>Repita los pasos anteriores para el resto de botones, añadiendo las 5 cuerdas restantes con los nombres <em>A</em>, <em>D</em>, <em>G</em>, <em>B</em>, y <em>e</em>.</p>
128    </item>
129    <item>
130    <p>Guarde el diseño de la IU (pulsando <guiseq><gui>Archivo</gui><gui>Guardar</gui></guiseq>) y déjelo abierto.</p>
131    </item>
132  </steps>
133</section>
134
135<section id="signal">
136  <title>Escribir el gestor de señales</title>
137  <p>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.</p>
138<p>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:</p>
139<code mime="text/x-csrc">
140def on_button_clicked (self, button):
141</code>
142
143  <p>Este gestor de la señal tiene dos argumentos: el puntero de clase Python habitual y el <code>Gtk.Button</code> que llamó a la función.</p>
144  <p>Por ahora, se dejará el gestor de la señal vacío mientras se escribe el código para producir sonidos.</p>
145</section>
146
147<section id="gstreamer">
148  <title>Tuberías de Gstreamer</title>
149  <p>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.</p>
150  <p>Conceptualmente. GStreamer funciona de la siguiente manera: puede crear una <em>tubería</em> que contenga varios elementos de procesado que van desde la <em>fuente</em> hasta el <em>sumidero</em> (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.</p>
151  <p>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.</p>
152  <media type="image" mime="image/png" src="media/guitar-tuner-pipeline.png">
153    <p>Un ejemplo de tubería de GStreamer.</p>
154  </media>
155</section>
156
157<section id="pipeline">
158  <title>Configurar la tubería</title>
159  <p>En este sencillo ejemplo se usará un generador de tonos llamado <code>audiotestsrc</code> y se enviará la salida al dispositivo de sonido predeterminado del sistema, <code>autoaudiosink</code>. Sólo es necesario configurar la frecuencia del generador de tonos; esto es accesible a través de la propiedad <code>freq</code> de <code>audiotestsrc</code>.</p>
160
161  <p>Cambie la línea de importación en <file>afinador_guitarra.py</file>, justo al principio, por:</p>
162  <code mime="test/x-python">from gi.repository import Gtk, Gst, GObject </code>
163  <p>El <code>Gst</code> incluye la biblioteca GStreamer. También debe debe inicializar GStreamer correctamente, lo que se ha hecho en el método <code>main()</code> con esta llamada añadida encima de la línea <code>app = GUI()</code>:</p>
164  <code mime="test/x-python">Gst.init_check(sys.argv)</code>
165  <p>Después, copie la siguiente función en la de <file>guitar_tuner.py</file>, en cualquier sitio:</p>
166  <code mime="test/x-python">
167def play_sound(self, frequency):
168	pipeline = Gst.Pipeline(name='note')
169	source = Gst.ElementFactory.make('audiotestsrc', 'src')
170	sink = Gst.ElementFactory.make('autoaudiosink', 'output')
171
172	source.set_property('freq', frequency)
173	pipeline.add(source)
174	pipeline.add(sink)
175	source.link(sink)
176	pipeline.set_state(Gst.State.PLAYING)
177
178	GObject.timeout_add(self.LENGTH, self.pipeline_stop, pipeline)</code>
179  <steps>
180    <item>
181    <p>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 <code>audiotestsrc</code> y el sumidero se llama «output» y se asocia con el sumidero <code>autoaudiosink</code> (la salida de la tarjeta de sonido predeterminada).</p>
182    </item>
183    <item>
184    <p>La llamada a <code>source.set_property</code> establece la propiedad <code>freq</code> del elemento fuente a <code>frequency</code>, que se pasa como argumento a la función <code>play_sound</code>. Esto sólo es la frecuencia de la nota en Hercios; más adelante se definirán algunas frecuencias útiles.</p>
185    </item>
186    <item>
187    <p>Las dos siguientes líneas llaman a <code>pipeline.add</code>, 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 <code>add</code> repetidamente.</p>
188    </item>
189    <item>
190    <p>El siguiente <code>pipeline.set_state</code> se usar para iniciar la reproducción, estableciendo el estado de la tubería a «playing» (<code>Gst.State.PLAYING</code>).</p>
191    </item>
192  </steps>
193
194</section>
195
196<section id="playback">
197  <title>Detener la reproducción</title>
198  <p>No se quiere reproducir un tono molesto para siempre, por lo que lo último que <code>play_sound</code> hace es llamar a <code>GObject.timeout_add</code>. Esto establece un tiempo de expiración para detener el sonido; espera <code>LENGTH</code> milisegundos antes de llamar a la función <code>pipeline_stop</code>, y se queda llamando a <code>pipeline_stop</code> hasta que devuelve <code>False</code>.</p>
199  <p>Ahora se escribirá el código de la función <code>pipeline_stop</code>, llamada por <code>GObject.timeout_add</code>. Inserte el código siguiente <em>encima</em> de la función <code>play_sound</code>:</p>
200  <code mime="test/x-python">
201def pipeline_stop(self, pipeline):
202	pipeline.set_state(Gst.State.NULL)
203	return False
204</code>
205  <p>Necesita definir la constante <code>LENGTH</code> dentro de la clase, por lo que debe añadir este código al principio de la clase principal:</p>
206  <code mime="test/x-python">
207LENGTH = 500
208</code>
209  <p>La llamada a <code>pipeline.set_state</code> detiene la reproducción de la tubería.</p>
210</section>
211
212<section id="tones">
213  <title>Definir los tonos</title>
214  <p>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:</p>
215  <code mime="test/x-python">
216# Frequencies of the strings
217frequencies = {
218	'E': 329.63,
219	'A': 440,
220	'D': 587.33,
221	'G': 783.99,
222	'B': 987.77,
223	'e': 1318.5
224}
225</code>
226  <p>Ahora se se profundiza en el gestor de la señal definido anteriormente, <code>on_button_clicked</code>. 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:</p>
227  <code mime="test/x-python">
228def on_button_clicked(self, button):
229	label = button.get_child()
230	text = label.get_label()
231
232	self.play_sound (self.frequencies[text])
233</code>
234  <p>El botón que se ha pulsado se pasa como argumento (<code>button</code>) a <code>on_button_clicked</code>. Se puede obtener la etiqueta de ese botón usando <code>button.get_child</code>, y obteniendo entonces el texto de esa etiqueta usando <code>label.get_label</code>.</p>
235  <p>La etiqueta de texto se usa como clave para el diccionario, y se llama a <code>play_sound</code> con la frecuencia correspondiente a esa nota. Esto reproduce el tono; el afinador de guitarra ya está funcionando.</p>
236</section>
237
238<section id="run2">
239  <title>Ejecutar la aplicación</title>
240  <p>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.</p>
241</section>
242
243<section id="impl">
244 <title>Implementación de referencia</title>
245 <p>Si tiene problemas con este tutorial, compare su código con este <link href="guitar-tuner/guitar-tuner.py">código de referencia</link>.</p>
246</section>
247
248<section id="next">
249  <title>Siguientes pasos</title>
250  <p>Aquí hay algunas ideas sobre cómo puede extender esta sencilla demostración:</p>
251  <list>
252   <item>
253   <p>Hacer que el programa recorra las notas automáticamente.</p>
254   </item>
255   <item>
256   <p>Hacer que el programa reproduzca grabaciones de cuerdas de guitarras que se están afinando.</p>
257   <p>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.</p>
258   <p>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>.</p>
259   </item>
260   <item>
261   <p>Analizar automáticamente las notas que toca el músico.</p>
262   <p>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?</p>
263   </item>
264  </list>
265</section>
266
267</page>
268