Blame platform-demos/es/guitar-tuner.cpp.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.cpp" xml:lang="es">
Packit 1470ea
Packit 1470ea
  <info>
Packit 1470ea
    <link type="guide" xref="cpp#examples"/>
Packit 1470ea
Packit 1470ea
    <desc>Usar GTKmm y GStreamermm 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="2011-03-17" status="review"/>
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
  
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 C++

</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
    

Elija <gui>GTKmm (simple)</gui> de la pestaña <gui>C++</gui>, pulse <gui>Adelante</gui> y rellene los detalles en las siguientes páginas. Use <file>afinador-guitarra</file> como nombre de proyecto y de carpeta.

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

Asegúrese de que <gui>Configurar paquetes externos</gui> está seleccionada. En la siguiente página, seleccione gstreamermm-0.10 de la lista para incluir la biblioteca GStreamermm en su proyecto.

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

Pulse <gui>Terminado</gui> y se creará el proyecto. Abra <file>src/main.c</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
#include <gtkmm.h>
Packit 1470ea
#include <iostream>
Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="build">
Packit 1470ea
  <title>Construir el código por primera vez</title>
Packit 1470ea
  

Esto es una configuración de código C++ usando GTKmm. Se ofrecen más detalles a continuación; omita esta lista si entiende los conceptos básicos:

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

Las tres líneas #include en la parte superior incluyen las bibliotecas config (definiciones últiles para construcción con autoconf), gtkmm (interfaz de usuario) iostream (STL). Las funciones de estas bibliotecas se usan en el resto del código.

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

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

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

Después llama a algunas funciones que configuran y después ejecutan la aplicación. La función kit.run inicia el bucle principal de GTKmm, que ejecuta la interfaz de usuario y empieza a escuchar eventos (como pulsaciones del ratón y del teclado).

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

Este código está listo para usarse, por lo que puede compilarlo pulsando <guiseq><gui>Construir</gui><gui>Construir proyecto</gui></guiseq> (o pulsando <keyseq><key>Mayús</key><key>F7</key></keyseq>).

Packit 1470ea
  

Pulse <gui>Ejecutar</gui> en la siguiente ventana que aparece para configurar una construcción de depuración. Esto sólo necesita hacer una vez para la primera construcción.

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 izquierda, y la paleta de los widgets disponibles está a la derecha.

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. Cambie también la propiedad <gui>Nombre</gui> a <gui>button_E</gui>. Este es el nombre al que se hará referencia más tarde en el código.

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

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

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 cierre el archivo.

Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="gst">
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. GStreamermm es la implementación de GStreamer en C++ que se usará aquí.

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="usinggst">
Packit 1470ea
  <title>Usar GStreamermm</title>
Packit 1470ea
  

Para usar GStreamermm, se debe inicializar. Esto se hace añadiendo la siguiente línea de código junto a la línea Gtk::Main kit(argc, argv); en <file>main.cc</file>:

Packit 1470ea
  	Gst::init (argc, argv);
Packit 1470ea
  

Mientras está con esto, asegúrese de que <file>gstreamermm.h</file> se incluye correctamente en <file>main.cc</file>.

Packit 1470ea
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
  

Para simplificar el manejo de la tubería, se definirá una clase Sound auxiliar. Esto se hace en <file>main.cc</file> para mantener la sencillez de este ejemplo, pero puede querer usar un archivo aparte.

Packit 1470ea
  
Packit 1470ea
class Sound
Packit 1470ea
{
Packit 1470ea
	public:
Packit 1470ea
		Sound();
Packit 1470ea
Packit 1470ea
		void start_playing(double frequency);
Packit 1470ea
		bool stop_playing();
Packit 1470ea
Packit 1470ea
	private:
Packit 1470ea
		Glib::RefPtr<Gst::Pipeline> m_pipeline;
Packit 1470ea
		Glib::RefPtr<Gst::Element> m_source;
Packit 1470ea
		Glib::RefPtr<Gst::Element> m_sink;
Packit 1470ea
};
Packit 1470ea
Packit 1470ea
Sound::Sound()
Packit 1470ea
{
Packit 1470ea
	m_pipeline = Gst::Pipeline::create("note");
Packit 1470ea
	m_source = Gst::ElementFactory::create_element("audiotestsrc",
Packit 1470ea
	                                               "source");
Packit 1470ea
	m_sink = Gst::ElementFactory::create_element("autoaudiosink",
Packit 1470ea
	                                             "output");
Packit 1470ea
	m_pipeline->add(m_source);
Packit 1470ea
	m_pipeline->add(m_sink);
Packit 1470ea
	m_source->link(m_sink);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
void Sound::start_playing (double frequency)
Packit 1470ea
{
Packit 1470ea
	m_source->set_property("freq", frequency);
Packit 1470ea
	m_pipeline->set_state(Gst::STATE_PLAYING);
Packit 1470ea
Packit 1470ea
	/* stop it after 200ms */
Packit 1470ea
	Glib::signal_timeout().connect(sigc::mem_fun(*this, &Sound::stop_playing),
Packit 1470ea
	                               200);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
bool Sound::stop_playing()
Packit 1470ea
{
Packit 1470ea
	m_pipeline->set_state(Gst::STATE_NULL);
Packit 1470ea
	return false;
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
Packit 1470ea
  

El código tiene el propósito siguiente:

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

En el constructor se crean los elementos «fuente» y «sumidero» de GStreamer (GstElement), 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). Después de añadir los elementos a la tubería y de enlazarlos unos con otros, la tubería está lista para ejecutarse.

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

start_playing configura el elemento fuente para reproducir una frecuencia determinada e inicia la tubería, por lo que el sonido empieza a reproducirse. Como no se quiere reproducir un sonido molesto durante mucho tiempo, se establece un tiempo de expiración para detener la tubería después de 200 ms, llamando a stop_playing.

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

En stop_playing a la que se llama cuando ha transcurrido el tiempo, se detiene la tubería y como tal, ya no habrá ninguna salida de sonido. Ya que GStreamermm usa una referencia continua a traves del objeto Glib::RefPtr, la memoria se libera automáticamente una vez que la clase Sound se ha destruido.

Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="signals">
Packit 1470ea
  <title>Conectar las señales</title>
Packit 1470ea
  

Se quiere reproducir el sonido correcto cuando el usuario pulsa un botón. Lo que significa que hay que conectar la señal disparada cuando el usuario pulsa el botón. También se quiere proporcionar información a la función llamada dependiendo del tono que reproducir. GTKmm hace que esto sea fácil ya que se puede vincular información con la biblioteca sigc.

Packit 1470ea
Packit 1470ea
  

La función a la que se llama cuando el usuario pulsa un botón puede ser muy sencilla, ya que todo lo interesante se hace ahora en la clase auxiliar:

Packit 1470ea
  
Packit 1470ea
static void
Packit 1470ea
on_button_clicked(double frequency, Sound* sound)
Packit 1470ea
{
Packit 1470ea
	sound->start_playing (frequency);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
  

Sólo llama a la clase auxiliar definida anteriormente para reproducir las frecuencias correctas. Con algo de código más inteligente, se podría haber conectado directamente con la clase sin usar la función, pero esto se dejará como ejercicio.

Packit 1470ea
Packit 1470ea
  

El código para configurar las señales de debe añadir a la función main(), justo después de la línea builder->get_widget("main_window", main_win);:

Packit 1470ea
  
Packit 1470ea
Sound sound;
Packit 1470ea
Gtk::Button* button;
Packit 1470ea
Packit 1470ea
builder->get_widget("button_E", button);
Packit 1470ea
button->signal_clicked().connect (sigc::bind<double, Sound*>(sigc::ptr_fun(&on_button_clicked),
Packit 1470ea
                                              329.63, &sound));
Packit 1470ea
Packit 1470ea
	<steps>
Packit 1470ea
	<item>
Packit 1470ea
	

En primer lugar, se crea una instancia de la clase auxiliar que se quiere usar ahora y se declara una variable para el botón al que se quiere conectar.

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

Después se recibe el objeto de botón desde la interfaz de usuario que se creó fuera del archivo de la interfaz de usuario. Recuerde que button_E es el nombre que se dio al primer botón.

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

Por último, se conecta la señal clicked. Esto no es del todo sencillo porque se hace de manera completamente segura para el tipo, y actualmente se quiere pasar la frecuencia y la clase auxiliar al manejador de la señal. sigc::ptr_fun(&on_button_clicked) crea un slot para el método on_button_clicked definido anteriormente. Con sigc::bind es posible pasar argumentos adicionales al slot y, en este caso, se pasa la frecuencia (como «double») y la clase auxiliar.

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

Ahora que se ha establecido el botón E, se debe conectar el resto de botones de acuerdo con sus frecuencias: 440 para A, 587.33 para D, 783.99 para G, 987.77 para B y 1318.5 para E agudo. Esto se hace de la misma manera, pasando simplemente una frecuencia diferente al manejador.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="run">
Packit 1470ea
  <title>Construir y ejecutar la aplicación</title>
Packit 1470ea
  

Todo el código debería estar listo para ejecutarse. Pulse <guiseq><gui>Construir</gui><gui>Construir proyecto</gui></guiseq> para construir todo otra vez y pulse <guiseq><gui>Ejecutar</gui><gui>Ejecutar</gui></guiseq> para iniciar la aplicación.

Packit 1470ea
  

Si todavía no lo ha hecho, elija la aplicación <file>Debug/src/afinador-guitarra</file> en el diálogo que aparece. Finalmente, pulse <gui>Ejecutar</gui> 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.cc">código de referencia</link>.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="further">
Packit 1470ea
  <title>Lecturas adicionales</title>
Packit 1470ea
  

La mayor parte de lo que se ha visto anteriormente se explica detalladamente en el <link href="http://library.gnome.org/devel/gtkmm-tutorial/stable/">libro de GTKmm</link> que también cubre muchos más conceptos clave para usar todo el potencial de GTKmm. Es posible que también le interese la <link href="http://library.gnome.org/devel/gstreamermm/">documentación de referencia de GStreamermm</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>