Blame platform-demos/pt_BR/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="pt-BR">
Packit 1470ea
Packit 1470ea
  <info>
Packit 1470ea
    <title type="text">Guitar tuner (Python)</title>
Packit 1470ea
    <link type="guide" xref="py#examples"/>
Packit 1470ea
Packit 1470ea
    <desc>Use GTK+ and GStreamer to build a simple guitar tuner application for GNOME. Shows off how to use the interface designer.</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>GNOME Documentation Project</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>Rafael Ferreira</mal:name>
Packit 1470ea
      <mal:email>rafael.f.f1@gmail.com</mal:email>
Packit 1470ea
      <mal:years>2013</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  </info>
Packit 1470ea
Packit 1470ea
<title>Guitar tuner</title>
Packit 1470ea
Packit 1470ea
<synopsis>
Packit 1470ea
  

In this tutorial, we're going to make a program which plays tones that you can use to tune a guitar. You will learn how to:

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

Set up a basic project in Anjuta

</item>
Packit 1470ea
    <item>

Create a simple GUI with Anjuta's UI designer

</item>
Packit 1470ea
    <item>

Use GStreamer to play sounds

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

You'll need the following to be able to follow this tutorial:

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

An installed copy of the <link xref="getting-ready">Anjuta IDE</link>

</item>
Packit 1470ea
    <item>

Basic knowledge of the Python programming language

</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>Create a project in Anjuta</title>
Packit 1470ea
  

Before you start coding, you'll need to set up a new project in Anjuta. This will create all of the files you need to build and run the code later on. It's also useful for keeping everything together.

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

Start Anjuta and click <guiseq><gui>File</gui><gui>New</gui><gui>Project</gui></guiseq> to open the project wizard.

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

Choose <gui>PyGTK (automake)</gui> from the <gui>Python</gui> tab, click <gui>Continue</gui>, and fill out your details on the next few pages. Use <file>guitar-tuner</file> as project name and directory.

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

Click <gui>Apply</gui> and the project will be created for you. Open <file>src/guitar_tuner.py</file> from the <gui>Project</gui> or <gui>File</gui> tabs. You should see some code which starts with the lines:

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>Run the code for the first time</title>
Packit 1470ea
  

Most of the code in the file is template code. It loads an (empty) window from the user interface description file and shows it. More details are given below; skip this list if you understand the basics:

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

The import lines at the top include the tell Python to load the user interface and system

Packit 1470ea
libraries needed.

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

A class is declared that will be the main class for our application. In the __init__ method

Packit 1470ea
	the main window is loaded from the GtkBuilder file (<file>src/guitar-tuner.ui</file>) and the
Packit 1470ea
	signals are connected.

Packit 1470ea
    

Connecting signals is how you define what happens when you push a button, or when some other event happens. Here, the destroy method is called (and quits the app) when you close the window.

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

The main function is run by default when you start a Python application. It just creates

Packit 1470ea
	an instance of the main class and starts the main loop to bring up the window.

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

This code is ready to be used, so you can run it by clicking <guiseq><gui>Run</gui><gui>Execute</gui></guiseq>.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="ui">
Packit 1470ea
  <title>Create the user interface</title>
Packit 1470ea
  

A description of the user interface (UI) is contained in the GtkBuilder file. To edit the user interface, open <file>src/guitar_tuner.ui</file>. This will switch to the interface designer. The design window is in the center; widgets and widgets' properties are on the right, and the palette of available widgets is on the left.

Packit 1470ea
  

Packit 1470ea
  

The layout of every UI in GTK+ is organized using boxes and tables. Let's use a vertical <gui>GtkButtonBox</gui> here to assign six <gui>GtkButtons</gui>, one for each of the six guitar strings.

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
   

Select a <gui>GtkButtonBox</gui> from the <gui>Container</gui> section of the <gui>Palette</gui> on the right and put it into the window. In the <gui>Properties</gui> pane, set the number of elements to 6 (for the

Packit 1470ea
six strings) and the orientation to vertical.

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

Now, choose a <gui>GtkButton</gui> from the palette and put it into the first part of the box.

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

While the button is still selected, change the <gui>Label</gui> property in the <gui>Widgets</gui> tab to <gui>E</gui>. This will be the low E string.

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

Switch to the <gui>Signals</gui> tab (inside the <gui>Widgets</gui> tab) and look for the clicked signal of the button. You can use this to connect a signal handler that will be called when the button is clicked by the user. To do this, click on the signal and type on_button_clicked in the <gui>Handler</gui> column and press <key>Return</key>.

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

Repeat the above steps for the other buttons, adding the next 5 strings with the names A, D, G, B, and e.

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

Save the UI design (by clicking <guiseq><gui>File</gui><gui>Save</gui></guiseq>) and keep it open.

Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="signal">
Packit 1470ea
  <title>Write the signal handler</title>
Packit 1470ea
  

In the UI designer, you made it so that all of the buttons will call the same function, <gui>on_button_clicked</gui>, when they are clicked. We need to add that function in the source file.

Packit 1470ea

To do this, open <file>guitar_tuner.py</file> while the user interface file is still open. Switch to the <gui>Signals</gui> tab, which you already used to set the signal name. Now take the row where you set the

Packit 1470ea
<gui>clicked</gui> signal and drag it into to the source file inside the class. The following code will be added to your source file:

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

This signal handler has two arguments: the usual Python class pointer, and the Gtk.Button that called the function.

Packit 1470ea
  

For now, we'll leave the signal handler empty while we work on writing the code to produce sounds.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="gstreamer">
Packit 1470ea
  <title>GStreamer pipelines</title>
Packit 1470ea
  

GStreamer is GNOME's multimedia framework — you can use it for playing, recording, and processing video, audio, webcam streams and the like. Here, we'll be using it to produce single-frequency tones.

Packit 1470ea
  

Conceptually, GStreamer works as follows: You create a pipeline containing several processing elements going from the source to the sink (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.

Packit 1470ea
  

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.

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

An example GStreamer pipeline.

Packit 1470ea
  </media>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="pipeline">
Packit 1470ea
  <title>Set up the pipeline</title>
Packit 1470ea
  

In this simple example we will use a tone generator source called audiotestsrc and send the output to the default system sound device, autoaudiosink. We only need to configure the frequency of the tone generator; this is accessible through the freq property of audiotestsrc.

Packit 1470ea
Packit 1470ea
  

Change the import line in <file>guitar_tuner.py</file>, just at the beginning to :

Packit 1470ea
  
Packit 1470ea
  

The Gst includes the GStreamer library. You also need to initialise GStreamer properly which

Packit 1470ea
     is done in the main() method with this call added above the app = GUI()
Packit 1470ea
     line:

Packit 1470ea
  
Packit 1470ea
  

Then, copy the following function into the class in <file>guitar_tuner.py</file> somewhere:

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
    

The first three lines create source and sink GStreamer elements and a pipeline element (which will be used as a container for the other two elements). The pipeline is given the name "note"; the source is named "source" and is set to the audiotestsrc source; and the sink is named "output" and set to the autoaudiosink sink (default sound card output).

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

The call to source.set_property sets the freq property of the source element to frequency, which was passed as an argument to the play_sound function. This is just the frequency of the note in Hertz; some useful frequencies will be defined later on.

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

The next two lines call pipeline.add, putting the source and sink into the pipeline. The pipeline can contain multiple other GStreamer elements. In general, you can add as many elements as you like to the pipeline by calling its add method repeatedly.

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

Next pipeline.set_state is used to start playback, by setting the state of the pipeline to 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>Stopping playback</title>
Packit 1470ea
  

We don't want to play an annoying tone forever, so the last thing play_sound does is to call GObject.timeout_add. This sets a timeout for stopping the sound; it waits for LENGTH milliseconds before calling the function pipeline_stop, and will keep calling it until pipeline_stop returns False.

Packit 1470ea
  

Now, we'll write the pipeline_stop function which is called by GObject.timeout_add. Insert the following code above the play_sound function:

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
  

You need to define the LENGTH constant inside the class, so add this code at the beginning of the

Packit 1470ea
main class:

Packit 1470ea
  
Packit 1470ea
LENGTH = 500
Packit 1470ea
]]>
Packit 1470ea
  

The call to pipeline.set_state stops the playback of the pipeline.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="tones">
Packit 1470ea
  <title>Define the tones</title>
Packit 1470ea
  

We want to play the correct sound when the user clicks a button. First of all, we need to know the frequencies for the six guitar strings, which are defined (at the beginning of the main class) inside a dictionary so

Packit 1470ea
we can easily map them to the names of the strings:

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
  

Now to flesh out the signal handler that we defined earlier, on_button_clicked. We could have connected every button to a different signal handler, but that would lead to a lot of code duplication. Instead, we can use the label of the button to figure out which button was clicked:

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
  

The button that was clicked is passed as an argument (button) to on_button_clicked. We can get the label of that button by using button.get_child, and then get the text from that label using label.get_label.

Packit 1470ea
  

The label text is then used as a key for the dictionary and play_sound is called with the frequency appropriate for that note. This plays the tone; we have a working guitar tuner!

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="run2">
Packit 1470ea
  <title>Run the application</title>
Packit 1470ea
  

All of the code should now be ready to go. Click <guiseq><gui>Run</gui><gui>Execute</gui></guiseq> to start the application. Enjoy!

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="impl">
Packit 1470ea
 <title>Reference Implementation</title>
Packit 1470ea
 

If you run into problems with the tutorial, compare your code with this <link href="guitar-tuner/guitar-tuner.py">reference code</link>.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="next">
Packit 1470ea
  <title>Next steps</title>
Packit 1470ea
  

Here are some ideas for how you can extend this simple demonstration:

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

Have the program automatically cycle through the notes.

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

Make the program play recordings of real guitar strings being plucked.

Packit 1470ea
   

To do this, you would need to set up a more complicated GStreamer pipeline which allows you to load and play back music files. You'll have to choose <link href="http://gstreamer.freedesktop.org/documentation/plugins.html">decoder and demuxer</link> GStreamer elements based on the file format of your recorded sounds — MP3s use different elements to Ogg Vorbis files, for example.

Packit 1470ea
   

You might need to connect the elements in more complicated ways too. This could involve using <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-intro-basics.html">GStreamer concepts</link> that we didn't cover in this tutorial, such as <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-intro-basics-pads.html">pads</link>. You may also find the <cmd>gst-inspect</cmd> command useful.

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

Automatically analyze notes that the user plays.

Packit 1470ea
   

You could connect a microphone and record sounds from it using an <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-autoaudiosrc.html">input source</link>. Perhaps some form of <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-plugin-spectrum.html">spectrum analysis</link> would allow you to figure out what notes are being played?

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