Blame platform-demos/de/guitar-tuner.vala.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.vala" xml:lang="de">
Packit 1470ea
Packit 1470ea
  <info>
Packit 1470ea
    <link type="guide" xref="vala#examples"/>
Packit 1470ea
Packit 1470ea
    <desc>Use <link href="http://developer.gnome.org/platform-overview/stable/gtk">GTK+</link> and <link href="http://developer.gnome.org/platform-overview/stable/gstreamer">GStreamer</link> 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="2012-02-09" status="candidate"/>
Packit 1470ea
    <credit type="author">
Packit 1470ea
      <name>GNOME-Dokumentationsprojekt</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>Tiffany Antopolski</name>
Packit 1470ea
      <email its:translate="no">tiffany.antopolski@gmail.com</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>Mario Blättermann</mal:name>
Packit 1470ea
      <mal:email>mario.blaettermann@gmail.com</mal:email>
Packit 1470ea
      <mal:years>2011, 2013</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  </info>
Packit 1470ea
Packit 1470ea
<title>Gitarrenstimmgerät</title>
Packit 1470ea
Packit 1470ea
<synopsis>
Packit 1470ea
  

In this tutorial you will create an application which plays tones that you can use to tune a guitar. You will learn how to:

Packit 1470ea
  <list type="numbered">
Packit 1470ea
    <item>

Set up a basic project using the <link xref="getting-ready">Anjuta IDE</link>.

</item>
Packit 1470ea
    <item>

Create a simple GUI with <app>Anjuta</app>'s UI designer.

</item>
Packit 1470ea
    <item>

Use the <link href="http://developer.gnome.org/platform-overview/stable/gstreamer">GStreamer</link> library 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>

Basic knowledge of the <link href="https://live.gnome.org/Vala/Tutorial">Vala</link> programming language.

</item>
Packit 1470ea
    <item>

An installed copy of <app>Anjuta</app>.

</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 <app>Anjuta</app></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 <app>Anjuta</app> and click <gui>Create a new project</gui> or <guiseq><gui>File</gui><gui>New</gui><gui>Project</gui></guiseq> to open the project wizard.

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

Click on the <gui>Vala</gui> tab and select <gui>GTK+ (Simple)</gui>. 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
    

Make sure that <gui>Configure external packages</gui> is switched <gui>ON</gui>. On the next page, select

Packit 1470ea
      <link href="http://valadoc.org/gstreamer-0.10/index.htm">gstreamer-0.10</link> from the list to include the GStreamer library in your project. Click <gui>Continue</gui>

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

Click <gui>Apply</gui> and the project will be created for you. From the <gui>Project</gui> or <gui>Files</gui> tab, open <file>src/guitar_tuner.vala</file> by double-clicking on it. You should see some code which starts with the lines:

Packit 1470ea
    
Packit 1470ea
using GLib;
Packit 1470ea
using Gtk;
Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="build">
Packit 1470ea
  <title>Build the code for the first time</title>
Packit 1470ea
  

The code loads an (empty) window from the user interface description file and displays it. More details are given below; you may choose to skip this list if you understand the basics:

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

The two using lines import namespaces so we don't have to name them explicitly.

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

The constructor of the Main class creates a new window by opening a GtkBuilder file (<file>src/guitar-tuner.ui</file>, defined a few lines above), connecting its signals and then displaying it in a window. This GtkBuilder file contains a description of a user interface and all of its elements. You can use Anjuta's editor to design GtkBuilder user interfaces.

Packit 1470ea
    <note>
Packit 1470ea
    

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

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

The static main function is run by default when you start a Vala application. It calls a few functions which create the Main class, set up and then run the application. The Gtk.main function starts the GTK main loop, which runs the user interface and starts listening for events (like clicks and key presses).

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

This code is ready to be used, so you can compile it by clicking <guiseq><gui>Build</gui><gui>Build Project</gui></guiseq> (or press <keyseq><key>Shift</key><key>F7</key></keyseq>). When you do this, a dialog will appear. Change the <gui>Configuration</gui> to <gui>Default</gui> and then click <gui>Execute</gui> to configure the build directory. You only need to do this once, for the first build.

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 <file>src/guitar_tuner.ui</file> defined at the top of the class. To edit the user interface, open <file>src/guitar_tuner.ui</file> by double-clicking on it in the <gui>Project</gui> or <gui>Files</gui> section. This will switch to the interface designer. The design window is in the center; <gui>Widgets</gui> and the widget properties are on the right, and the <gui>Palette</gui> 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 GtkButtonBox here to assign six GtkButtons, 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
   

In the <gui>Palette</gui> tab, from the <gui>Containers</gui> section, select a <gui>Button Box</gui> (GtkButtonBox) by clicking on the icon. Then click on the design window in the center to place it into the window. A dialog will display where you can set the <gui>Number of items</gui> to <input>6</input>. Then click <gui>Create</gui>.

Packit 1470ea
 <note>

Packit 1470ea
 You can also change the <gui>Number of elements</gui> and the <gui>Orientation</gui> in the <gui>General</gui> tab on the right.

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

Now, from the <gui>Control and Display</gui> section of the <gui>Palette</gui> choose a <gui>Button</gui> (GtkButton) by clicking on it. Place it into the first section of the GtkButtonBox by clicking in the first section.

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

While the button is still selected, scroll down in the <gui>General</gui> tab on the right to the <gui>Label</gui> property, and change it to <gui>E</gui>. This will be the low E guitar string.

Packit 1470ea
  <note>

Packit 1470ea
    The <gui>General</gui> tab is located in the <gui>Widgets</gui> section on the right.
Packit 1470ea
  

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

Click on the <gui>Signals</gui> tab in the <gui>Widgets</gui> section on the right, 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 main_on_button_clicked in the <gui>Handler</gui> column and press the <key>Enter</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="gstreamer">
Packit 1470ea
  <title>GStreamer-Weiterleitungen</title>
Packit 1470ea
  

This section will show you how to create the code to produce sounds. <link href="http://developer.gnome.org/platform-overview/stable/gstreamer">GStreamer</link> 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 <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-intro-basics-bins.html">pipeline</link> 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
    

Eine Beispiel-Weiterleitung in GStreamer.

Packit 1470ea
  </media>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="pipeline">
Packit 1470ea
  <title>Einrichten der Weiterleitung</title>
Packit 1470ea
  

In this 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
  

We need to add a line to initialize GStreamer; put the following code on the line above the Gtk.init call in the main function:

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

Then, copy the following function into <file>guitar_tuner.vala</file> inside our Main class:

Packit 1470ea
  
Packit 1470ea
Gst.Element sink;
Packit 1470ea
Gst.Element source;
Packit 1470ea
Gst.Pipeline pipeline;
Packit 1470ea
Packit 1470ea
private void play_sound(double frequency)
Packit 1470ea
{
Packit 1470ea
	pipeline = new Gst.Pipeline ("note");
Packit 1470ea
	source   = Gst.ElementFactory.make ("audiotestsrc",
Packit 1470ea
	                                    "source");
Packit 1470ea
	sink     = Gst.ElementFactory.make ("autoaudiosink",
Packit 1470ea
	                                    "output");
Packit 1470ea
Packit 1470ea
	/* set frequency */
Packit 1470ea
	source.set ("freq", frequency);
Packit 1470ea
Packit 1470ea
	pipeline.add (source);
Packit 1470ea
	pipeline.add (sink);
Packit 1470ea
	source.link (sink);
Packit 1470ea
Packit 1470ea
	pipeline.set_state (Gst.State.PLAYING);
Packit 1470ea
Packit 1470ea
	/* stop it after 200ms */
Packit 1470ea
	var time = new TimeoutSource(200);
Packit 1470ea
Packit 1470ea
	time.set_callback(() => {
Packit 1470ea
		pipeline.set_state (Gst.State.NULL);
Packit 1470ea
		return false;
Packit 1470ea
	});
Packit 1470ea
	time.attach(null);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
  <steps>
Packit 1470ea
    <item>
Packit 1470ea
    

The first three lines create source and sink GStreamer elements (<link href="http://valadoc.org/gstreamer-0.10/Gst.Element.html">Gst.Element</link>), and a <link href="http://valadoc.org/gstreamer-0.10/Gst.Pipeline.html">pipeline element</link> (which will be used as a container for the other two elements). Those are class variables so they are defined outside the method. 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 <link href="http://valadoc.org/gobject-2.0/GLib.Object.set.html">source.set</link> sets the freq property of the source element to frequency, which is passed in 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
    

<link href="http://valadoc.org/gstreamer-0.10/Gst.Bin.add.html">pipeline.add</link> puts the source and sink into the pipeline. The pipeline is a <link href="http://valadoc.org/gstreamer-0.10/Gst.Bin.html">Gst.Bin</link>, which is just an element that can contain multiple other GStreamer elements. In general, you can add as many elements as you like to the pipeline by adding more calls to pipeline.add.

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

Next, <link href="http://valadoc.org/gstreamer-0.10/Gst.Element.link.html">sink.link</link> is used to connect the elements together, so the output of source (a tone) goes into the input of sink (which is then output to the sound card). <link href="http://www.valadoc.org/gstreamer-0.10/Gst.Element.set_state.html">pipeline.set_state</link> is then used to start playback, by setting the <link href="http://www.valadoc.org/gstreamer-0.10/Gst.State.html">state of the pipeline</link> to playing (Gst.State.PLAYING).

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

We don't want to play an annoying tone forever, so the last thing play_sound does is to

Packit 1470ea
    add a <link href="http://www.valadoc.org/glib-2.0/GLib.TimeoutSource.html">TimeoutSource</link>. This sets a timeout for stopping the sound; it waits for 200 milliseconds before
Packit 1470ea
    calling a signal handler defined inline that stops and destroys the pipeline. It returns false to
Packit 1470ea
    remove itself from the timeout, otherwise it would continue to be called every 200 ms.

Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
Packit 1470ea
<section id="signal">
Packit 1470ea
  <title>Creating 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. Actually we type <gui>main_on_button_clicked</gui> which tells the UI designer that this method is part of our Main. We need to add that function in the source file.

Packit 1470ea
  

To do this, in the user interface file (guitar_tuner.ui) select one of the buttons by clicking on it, then open <file>guitar_tuner.vala</file> (by clicking on the tab in the center). Switch to the <gui>Signals</gui> tab on the right, which you used to set the signal name. Now take the row where you set the

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

Packit 1470ea
Packit 1470ea
public void on_button_clicked (Gtk.Button sender) {
Packit 1470ea
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
 <note>

You can also just type the code at the beginning of the class instead of using the drag and drop.

</note>
Packit 1470ea
  

This signal handler has only one argument: the <link href="http://valadoc.org/gtk+-3.0/Gtk.Widget.html">Gtk.Widget</link> that called the function (in our case, always a <link href="http://valadoc.org/gtk+-3.0/Gtk.Button.html">Gtk.Button</link>).

Packit 1470ea

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

We want to play the correct sound when the user clicks a button. For this, we flesh out the signal handler which we defined above, 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
public void on_button_clicked (Gtk.Button sender) {
Packit 1470ea
	var label = sender.get_child () as Gtk.Label;
Packit 1470ea
	switch (label.get_label()) {
Packit 1470ea
		case "E":
Packit 1470ea
			play_sound (329.63);
Packit 1470ea
			break;
Packit 1470ea
		case "A":
Packit 1470ea
			play_sound (440);
Packit 1470ea
			break;
Packit 1470ea
		case "D":
Packit 1470ea
			play_sound (587.33);
Packit 1470ea
			break;
Packit 1470ea
		case "G":
Packit 1470ea
			play_sound (783.99);
Packit 1470ea
			break;
Packit 1470ea
		case "B":
Packit 1470ea
			play_sound (987.77);
Packit 1470ea
			break;
Packit 1470ea
		case "e":
Packit 1470ea
			play_sound (1318);
Packit 1470ea
			break;
Packit 1470ea
		default:
Packit 1470ea
			break;
Packit 1470ea
	}
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
  

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

Packit 1470ea
  

The switch statement compares the label text to the notes that we can play, 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="run">
Packit 1470ea
  <title>Build and run the application</title>
Packit 1470ea
  

All of the code should now be ready to go. Click <guiseq><gui>Build</gui><gui>Build Project</gui></guiseq> to build everything again, and then <guiseq><gui>Run</gui><gui>Execute</gui></guiseq> to start the application.

Packit 1470ea
  

If you haven't already done so, choose the <file>Debug/src/guitar-tuner</file> application in the dialog that appears. Finally, hit <gui>Run</gui> and enjoy!

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="impl">
Packit 1470ea
 <title>Referenz-Implementierung</title>
Packit 1470ea
 

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

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="further">
Packit 1470ea
<title>Weitere Informationen</title>
Packit 1470ea

To find out more about the Vala programming language you might want to check out the

Packit 1470ea
<link href="http://live.gnome.org/Vala/Tutorial">Vala Tutorial</link> and the <link href="http://valadoc.org/">Vala API Documentation</link>

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="next">
Packit 1470ea
  <title>Nächste Schritte</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>