<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" type="guide" style="task" id="guitar-tuner.js" xml:lang="es">
  <info>
    <link type="guide" xref="index#js"/>
    <revision version="0.1" date="2012-03-09" status="stub"/>

    <credit type="author copyright">
      <name>Susanna Huhtanen</name>
      <email>ihmis.suski@gmail.com</email>
      <years>2012</years>
    </credit>

    <desc>Usar GTK+ y GStreamer para construir un sencillo afinador de guitarra para GNOME.</desc>
  </info>

  <title>2. Afinador de guitarra</title>
  
    <synopsis>
      <p>En este tutorial se construirá una pequeña aplicación, «Afinador de guitarra», usando JavaScript, GTK+ y GStreamer. Para escribirla y poder ejecutar los ejemplos, necesitará un editor en el que escribir el código, una terminal y GNOME 3 o superior instalado en su equipo.</p>
   <list> 
      <item><p> <link xref="#gstreamer">Tuberías de Gstreamer</link> </p></item>
      <item><p> <link xref="#script">Script para ejecutar la aplicación</link> </p></item>
      <item><p> <link xref="#imports">Bibliotecas que importar</link> </p></item>
      <item><p> <link xref="#mainwindow">Crear la ventana principal de la aplicación</link> </p></item>
      <item><p> <link xref="#buttons">Botones para los tonos</link> </p></item>
      <item><p> <link xref="#playSound">Crear sonidos con GStreamer</link> </p></item>
      <item><p> <link xref="#connecting">Conectar los botones a playSound</link> </p></item>
      <item><p> <link xref="#guitarjs">El programa completo</link> </p></item>
      <item><p> <link xref="#terminal">Ejecutar la aplicación desde la terminal</link> </p></item>
    </list> 
  </synopsis>
  <p>Después de leer este tutorial, debería ver esto en su pantalla:</p>
  <media type="image" mime="image/png" src="media/guitar-tuner.png"/>
  <section id="gstreamer">
    <title>Tuberías de Gstreamer</title>
    <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>
    <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>
    <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>
    <media type="image" mime="image/png" src="media/guitar-tuner-pipeline.png">
      <p>Un ejemplo de tubería de GStreamer.</p>
    </media>
  </section>
  <section id="script">
    <title>Script para ejecutar la aplicación</title>
    <code mime="text/javascript" style="numbered"><![CDATA[
  #!/usr/bin/gjs]]></code>
    <p>Esta línea indica cómo ejecutar el script. Debe ser la primera línea del código y debe ser ejecutable. Para obtener permisos de ejecución vaya a la terminal y ejecute lo siguiente en la carpeta adecuada: chmod +x nombrescript. También puede usar el gestor de archivo. Simplemente vaya a la carpeta donde está el código, pulse con el botón derecho sobre el archivo de código y elija «Propiedades», pulse en la pestaña «Permisos» y marque la casilla para permitir ejecutar el archivo como un programa.</p>
  </section>
  <section id="imports">
    <title>Bibliotecas que importar</title>
    <code mime="text/javascript" style="numbered"><![CDATA[
var Gtk = imports.gi.Gtk;
var Gst = imports.gi.Gst;

const Mainloop = imports.mainloop;]]></code>
    <p>Para que el programa funcione se debe importar una biblioteca de introspección de GObject. Para que funcione la IU se necesita GTK+ y, para que funcione GStreamer se necesita GST. Estas bibliotecas se importan al inicio, por lo que están en uso en todos los sitios. También, al principio, se importa el constructor Mainloop para gestionar el tiempo de espera que usar para los tonos de afinación.</p>
    </section>
  <section id="mainwindow">
    <title>Crear la ventana principal de la aplicación</title> 
    <code mime="text/javascript" style="numbered"><![CDATA[
Gtk.init(null, 0);
Gst.init(null, 0);

var guitarwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL, border_width: 100});
guitarwindow.title = "Guitar Tuner";
guitarwindow.connect("destroy", function(){Gtk.main_quit()});

guitarwindow.show();
Gtk.main();]]></code>
    <p>Importing Gtk and Gst is not enough, we need to initialize them in order to get them working. When Gtk and Gst are up and running we need to create the window for the application. Later we are going to put all the buttons for making sounds inside this window. In order to get the window showing, we need to tell it to show and we need also to run the code with the Gtk.main() </p>
  </section>
  <section id="buttons">
   <title>Botones para los tonos</title>
   <code mime="text/javascript" style="numbered"><![CDATA[
var guitar_box = new Gtk.ButtonBox ({orientation: Gtk.Orientation.VERTICAL, spacing: 10});

var E = new Gtk.Button({label: "E"});
var A = new Gtk.Button({label: "A"});
var D = new Gtk.Button({label: "D"});
var G = new Gtk.Button({label: "G"});
var B = new Gtk.Button({label: "B"});
var e = new Gtk.Button({label: "e"});

guitar_box.add(E);
guitar_box.add(A);
guitar_box.add(D);
guitar_box.add(G);
guitar_box.add(B);
guitar_box.add(e);

guitarwindow.add(guitar_box);

guitar_box.show_all();]]></code>
   <p>Because Gtk.Window can only contain a single widget, we need to create something under it to be able to add all the necessary buttons inside it. In this example we use Buttonbox. After creating the Buttonbox we create buttons with necessary labels. After we have the buttons we need to add them to the Buttonbox and the Buttonbox must be added to the Gtk.Window and everything in the Buttonbox must be shown.</p>
   <p>After this stage you should have a window appearing to your screen showing 6 buttons. Right now the buttons don't do anything and we shall address that issue later. Before we can connect the button signals to something we need to code that something first. </p>
  </section>
  <section id="playSound">
   <title>Crear sonidos con GStreamer</title>
   <code mime="text/javascript" style="numbered"><![CDATA[
var frequencies = {E: 369.23, A: 440,	D: 587.33,	G: 783.99,	B: 987.77,	e: 1318.5}

function playSound(frequency){
  var pipeline = new Gst.Pipeline({name: "note"});
  var source = new Gst.ElementFactory.make("audiotestsrc","source");
  var sink = new Gst.ElementFactory.make("autoaudiosink","output");
  
  source.set_property('freq', frequency);
  pipeline.add(source);
  pipeline.add(sink);
  source.link(sink);
  pipeline.set_state(Gst.State.PLAYING);

  Mainloop.timeout_add(500, function () { 
    pipeline.set_state(Gst.State.PAUSED);
	  return false;
  });	
}]]></code>
   <p>The first thing we need to do is decide what tunes we want to make when we push a button. The frequencies list takes care of that. After that we get to actually making the sounds with the function playSound. For function playSound we give as an input a frequency (that we just defined in the frequencies variable). First thing we need to construct is a pipeline, a source and a sink. For the source we set the frequency. To the pipeline we add both the source and the sink and then we tell it to keep playing. As a last thing we use the const Mainloop to get the pipeline to pause after a 500ms.  </p>
   <p>Now we have the method of playing a tune when clicking a button. Next well make the conncetions between pushing a button and playing the correct sound from that button.</p>
  </section>
  <section id="connecting">
   <title>Conectar los botones a playSound</title>
   <code mime="text/javascript" style="numbered"><![CDATA[
E.connect("clicked", function() {
  playSound(frequencies.E);
});
A.connect("clicked", function(){
  playSound(frequencies.A);
});
D.connect("clicked", function(){
  playSound(frequencies.D);
});
G.connect("clicked", function(){
  playSound(frequencies.G);
});
B.connect("clicked", function(){
  playSound(frequencies.B);
});
e.connect("clicked", function(){
  playSound(frequencies.e);
});]]></code>
   <p>The method of connecting button clicks to playSound with the correct tune is by using the connect method of the button widget. So we yelp-check validate *pagechoose a button to be connected and type E.connect("clicked", function(){playSound(frequencies.E);}); The connect tells that when pushing E, something should happen. The "clicked" tells the type of something happening to E and then in the function(){}; we the playSound happen with the correct tune that should be associated to the button.</p>
  </section>
  <section id="guitarjs">
    <title>El programa completo</title>
    <p>So this is what all the parts combined looks like. When running this code, you should be able to tune your guitar(if you have correctly calibrated speakers).</p>
      <code mime="text/javascript" style="numbered"><![CDATA[
#!/usr/bin/gjs
var Gtk = imports.gi.Gtk;
var Gst = imports.gi.Gst;

const Mainloop = imports.mainloop;

Gtk.init(null, 0);
Gst.init(null, 0);

var guitarwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL, border_width: 100});
guitarwindow.title = "Guitar Tuner";
guitarwindow.connect("destroy", function(){Gtk.main_quit()});

var guitar_box = new Gtk.ButtonBox ({orientation: Gtk.Orientation.VERTICAL, spacing: 10});

var E = new Gtk.Button({label: "E"});
var A = new Gtk.Button({label: "A"});
var D = new Gtk.Button({label: "D"});
var G = new Gtk.Button({label: "G"});
var B = new Gtk.Button({label: "B"});
var e = new Gtk.Button({label: "e"});

var frequencies = {E: 369.23, A: 440,	D: 587.33,	G: 783.99,	B: 987.77,	e: 1318.5}


function playSound(frequency){
  var pipeline = new Gst.Pipeline({name: "note"});

  var source = new Gst.ElementFactory.make("audiotestsrc","source");
  var sink = new Gst.ElementFactory.make("autoaudiosink","output");
    
  source.set_property('freq', frequency);
  pipeline.add(source);
  pipeline.add(sink);
  source.link(sink);
  pipeline.set_state(Gst.State.PLAYING);

  Mainloop.timeout_add(500, function () { 
    pipeline.set_state(Gst.State.PAUSED);
	  return false;
});	
}

E.connect("clicked", function() {
  playSound(frequencies.E);
});
A.connect("clicked", function(){
  playSound(frequencies.A);
});
D.connect("clicked", function(){
  playSound(frequencies.D);
});
G.connect("clicked", function(){
  playSound(frequencies.G);
});
B.connect("clicked", function(){
  playSound(frequencies.B);
});
e.connect("clicked", function(){
  playSound(frequencies.e);
});

guitar_box.add(E);
guitar_box.add(A);
guitar_box.add(D);
guitar_box.add(G);
guitar_box.add(B);
guitar_box.add(e);

guitarwindow.add(guitar_box);

guitar_box.show_all();
guitarwindow.show();
Gtk.main();]]></code>
  </section>

<section id="terminal">
  <title>Ejecutar la aplicación desde la terminal</title>
  <p>Para ejecutar esta aplicación ,abra una terminal, vaya a la carpeta donde está la aplicación y ejecute</p> <screen> <output style="prompt">$</output><input>GJS_PATH=`pwd` gjs guitarTuner.js</input> </screen>
    </section>

<section id="impl">
 <title>Implementación de referencia</title>
 <p>If you run into problems with the tutorial, compare your code with this <link href="guitar-tuner/guitar-tuner.js">reference code</link>.</p>
</section>
  
 
</page>
