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="guide" style="task" id="guitar-tuner.js" xml:lang="gl"> 3 <info> 4 <title type="text">Guitar tuner (JavaScript)</title> 5 <link type="guide" xref="js#examples"/> 6 <revision version="0.1" date="2012-03-09" status="stub"/> 7 8 <credit type="author copyright"> 9 <name>Susanna Huhtanen</name> 10 <email its:translate="no">ihmis.suski@gmail.com</email> 11 <years>2012</years> 12 </credit> 13 14 <desc>Use GTK+ and GStreamer to build a simple guitar tuner application for GNOME.</desc> 15 16 <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright"> 17 <mal:name>Fran Dieguez</mal:name> 18 <mal:email>frandieguez@gnome.org</mal:email> 19 <mal:years>2012-2013.</mal:years> 20 </mal:credit> 21 </info> 22 23 <title>Guitar tuner</title> 24 25 <synopsis> 26 <p>In this tutorial we'll construct a small application, Guitar Tuner, using JavaScript and GTK+ and GStreamer. To do and run all the code examples yourself, you need an editor to write code in, terminal and GNOME 3. or higher installed into your computer.</p> 27 <list> 28 <item><p> <link xref="#gstreamer">GStreamer pipelines</link> </p></item> 29 <item><p> <link xref="#script">Script for running the application</link> </p></item> 30 <item><p> <link xref="#imports">Libraries to import</link> </p></item> 31 <item><p><link xref="#mainwindow">Creando a xanela principal para a aplicación</link></p></item> 32 <item><p> <link xref="#buttons">Buttons for the tunes</link> </p></item> 33 <item><p> <link xref="#playSound">Making the sounds with GStreamer</link> </p></item> 34 <item><p> <link xref="#connecting">Connecting buttons to playSound</link> </p></item> 35 <item><p> <link xref="#guitarjs">The whole program</link> </p></item> 36 <item><p> <link xref="#terminal">Running the application form Terminal</link> </p></item> 37 </list> 38 </synopsis> 39 <p>Despois de ler este manual, debería ver isto na pantalla:</p> 40 <media type="image" mime="image/png" src="media/guitar-tuner.png"/> 41 <section id="gstreamer"> 42 <title>Tuberías de GStreamer</title> 43 <p>GStreamer é un marco de traballo multimedia de GNOME — vostede pode usalo para reproducir, gravar e procesar vídeo, son, fluxos de cámara web e semellantes. Aquí, usarémolo para producir tonos dunha única frecuencia.</p> 44 <p>Conceptually, GStreamer works as follows: You create a <em>pipeline</em> containing several processing elements going from the <em>source</em> to the <em>sink</em> (output). The source can be an image file, a video, or a music file, for example, and the output could be a widget or the soundcard.</p> 45 <p>Between source and sink, you can apply various filters and converters to handle effects, format conversions and so on. Each element of the pipeline has properties which can be used to change its behaviour.</p> 46 <media type="image" mime="image/png" src="media/guitar-tuner-pipeline.png"> 47 <p>Un exemplo de tubería de GStreamer.</p> 48 </media> 49 </section> 50 <section id="script"> 51 <title>Script para executar a aplicación</title> 52 <code mime="application/javascript" style="numbered"><![CDATA[ 53 #!/usr/bin/gjs]]></code> 54 <p> This line tells how to run the script. It needs to be the first line of the code and it needs to be executable. To get the execution rights go to terminal and run in right folder: chmod +x scriptname. Or you can use the graphical filemanager. Just go to the right folder where your code is, right click you code file, choose properties, click the permissions tab and check the box for allow executing file as a program 55 </p> 56 </section> 57 <section id="imports"> 58 <title>Bibliotecas a importar</title> 59 <code mime="application/javascript" style="numbered"><![CDATA[ 60var Gtk = imports.gi.Gtk; 61var Gst = imports.gi.Gst; 62 63const Mainloop = imports.mainloop;]]></code> 64 <p>In order to have a working program we need to import a few GObject Introspection -libraries to our use. For working UI, we need Gtk and for Gstreamer to work we need Gst. These are imported in the beginning so we have them at use everywhere. Also in the beginning we import a construct Mainloop to handle the timeout to be used with the tuning sounds.</p> 65 </section> 66 <section id="mainwindow"> 67 <title>Crear a xanela principal para a aplicación</title> 68 <code mime="application/javascript" style="numbered"><![CDATA[ 69Gtk.init(null, 0); 70Gst.init(null, 0); 71 72var guitarwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL, border_width: 100}); 73guitarwindow.title = "Guitar Tuner"; 74guitarwindow.connect("destroy", function(){Gtk.main_quit()}); 75 76guitarwindow.show(); 77Gtk.main();]]></code> 78 <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> 79 </section> 80 <section id="buttons"> 81 <title>Buttons for the tunes</title> 82 <code mime="application/javascript" style="numbered"><![CDATA[ 83var guitar_box = new Gtk.ButtonBox ({orientation: Gtk.Orientation.VERTICAL, spacing: 10}); 84 85var E = new Gtk.Button({label: "E"}); 86var A = new Gtk.Button({label: "A"}); 87var D = new Gtk.Button({label: "D"}); 88var G = new Gtk.Button({label: "G"}); 89var B = new Gtk.Button({label: "B"}); 90var e = new Gtk.Button({label: "e"}); 91 92guitar_box.add(E); 93guitar_box.add(A); 94guitar_box.add(D); 95guitar_box.add(G); 96guitar_box.add(B); 97guitar_box.add(e); 98 99guitarwindow.add(guitar_box); 100 101guitar_box.show_all();]]></code> 102 <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> 103 <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> 104 </section> 105 <section id="playSound"> 106 <title>Making the sounds with GStreamer</title> 107 <code mime="application/javascript" style="numbered"><![CDATA[ 108var frequencies = {E: 329.63, A: 440, D: 587.33, G: 783.99, B: 987.77, e: 1318.5} 109 110function playSound(frequency){ 111 var pipeline = new Gst.Pipeline({name: "note"}); 112 var source = Gst.ElementFactory.make("audiotestsrc","source"); 113 var sink = Gst.ElementFactory.make("autoaudiosink","output"); 114 115 source.set_property('freq', frequency); 116 pipeline.add(source); 117 pipeline.add(sink); 118 source.link(sink); 119 pipeline.set_state(Gst.State.PLAYING); 120 121 Mainloop.timeout_add(500, function () { 122 pipeline.set_state(Gst.State.NULL); 123 return false; 124 }); 125}]]></code> 126 <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 stop after a 500ms.</p> 127 <p>Now we have the method of playing a tune when clicking a button. Next well make the connections between pushing a button and playing the correct sound from that button.</p> 128 </section> 129 <section id="connecting"> 130 <title>Connecting buttons to playSound</title> 131 <code mime="application/javascript" style="numbered"><![CDATA[ 132E.connect("clicked", function() { 133 playSound(frequencies.E); 134}); 135A.connect("clicked", function(){ 136 playSound(frequencies.A); 137}); 138D.connect("clicked", function(){ 139 playSound(frequencies.D); 140}); 141G.connect("clicked", function(){ 142 playSound(frequencies.G); 143}); 144B.connect("clicked", function(){ 145 playSound(frequencies.B); 146}); 147e.connect("clicked", function(){ 148 playSound(frequencies.e); 149});]]></code> 150 <p>The method of connecting button clicks to playSound with the correct tune 151 is by using the connect method of the button widget. So we choose a button 152 to be connected and type <code>E.connect("clicked", 153 function(){playSound(frequencies.E);});</code> The <code>connect</code> 154 tells that when pushing E, something should happen. The <code>clicked</code> 155 tells the type of the signal happening to E and then in the 156 <code>function(){};</code> we call playSound with the correct note that 157 should be associated with the button.</p> 158 </section> 159 <section id="guitarjs"> 160 <title>The whole program</title> 161 <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> 162 <code mime="application/javascript" style="numbered"><![CDATA[ 163#!/usr/bin/gjs 164var Gtk = imports.gi.Gtk; 165var Gst = imports.gi.Gst; 166 167const Mainloop = imports.mainloop; 168 169Gtk.init(null, 0); 170Gst.init(null, 0); 171 172var guitarwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL, border_width: 100}); 173guitarwindow.title = "Guitar Tuner"; 174guitarwindow.connect("destroy", function(){Gtk.main_quit()}); 175 176var guitar_box = new Gtk.ButtonBox ({orientation: Gtk.Orientation.VERTICAL, spacing: 10}); 177 178var E = new Gtk.Button({label: "E"}); 179var A = new Gtk.Button({label: "A"}); 180var D = new Gtk.Button({label: "D"}); 181var G = new Gtk.Button({label: "G"}); 182var B = new Gtk.Button({label: "B"}); 183var e = new Gtk.Button({label: "e"}); 184 185var frequencies = {E: 329.63, A: 440, D: 587.33, G: 783.99, B: 987.77, e: 1318.5} 186 187 188function playSound(frequency){ 189 var pipeline = new Gst.Pipeline({name: "note"}); 190 191 var source = Gst.ElementFactory.make("audiotestsrc","source"); 192 var sink = Gst.ElementFactory.make("autoaudiosink","output"); 193 194 source.set_property('freq', frequency); 195 pipeline.add(source); 196 pipeline.add(sink); 197 source.link(sink); 198 pipeline.set_state(Gst.State.PLAYING); 199 200 Mainloop.timeout_add(500, function () { 201 pipeline.set_state(Gst.State.NULL); 202 return false; 203}); 204} 205 206E.connect("clicked", function() { 207 playSound(frequencies.E); 208}); 209A.connect("clicked", function(){ 210 playSound(frequencies.A); 211}); 212D.connect("clicked", function(){ 213 playSound(frequencies.D); 214}); 215G.connect("clicked", function(){ 216 playSound(frequencies.G); 217}); 218B.connect("clicked", function(){ 219 playSound(frequencies.B); 220}); 221e.connect("clicked", function(){ 222 playSound(frequencies.e); 223}); 224 225guitar_box.add(E); 226guitar_box.add(A); 227guitar_box.add(D); 228guitar_box.add(G); 229guitar_box.add(B); 230guitar_box.add(e); 231 232guitarwindow.add(guitar_box); 233 234guitar_box.show_all(); 235guitarwindow.show(); 236Gtk.main();]]></code> 237 </section> 238 239<section id="terminal"> 240 <title>Running the application form Terminal</title> 241 <p>To run this application open Terminal, go to the folder where your application is stored and then run</p> <screen> <output style="prompt">$ </output><input> GJS_PATH=`pwd` gjs guitarTuner.js</input> </screen> 242 </section> 243 244<section id="impl"> 245 <title>Implementación de referencia</title> 246 <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> 247</section> 248 249 250</page> 251