[gnome-devel-docs] Added guitar-tuner.py tutorial (needs fixing), minor changes to g-t.c.page



commit 9a0eccd1b77f50f812c212812795435f47adfb55
Author: Phil Bull <philbull gmail com>
Date:   Tue Dec 7 08:39:58 2010 +0000

    Added guitar-tuner.py tutorial (needs fixing), minor changes to g-t.c.page

 demos/C/guitar-tuner.c.page  |    4 +-
 demos/C/guitar-tuner.py.page |  253 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 255 insertions(+), 2 deletions(-)
---
diff --git a/demos/C/guitar-tuner.c.page b/demos/C/guitar-tuner.c.page
index f3fe949..9cfc8a7 100644
--- a/demos/C/guitar-tuner.c.page
+++ b/demos/C/guitar-tuner.c.page
@@ -5,9 +5,9 @@
   <info>
     <link type="guide" xref="index#c"/>
   
-    <desc>This tutorial shows how you can use Gtk+ and GStreamer to build a simple guitar tuner application for GNOME</desc>
+    <desc>Use Gtk+ and GStreamer to build a simple guitar tuner application for GNOME</desc>
     
-    <revision pkgversion="0.1" version="0.1" date="2010-12-02" status="stub"/>
+    <revision pkgversion="0.1" version="0.1" date="2010-12-02" status="review"/>
     <credit type="author">
       <name>GNOME Documentation Project</name>
       <email>gnome-doc-list gnome org</email>
diff --git a/demos/C/guitar-tuner.py.page b/demos/C/guitar-tuner.py.page
new file mode 100644
index 0000000..c805521
--- /dev/null
+++ b/demos/C/guitar-tuner.py.page
@@ -0,0 +1,253 @@
+<page xmlns="http://projectmallard.org/1.0/";
+      type="topic"
+      id="guitar-tuner.py">
+
+  <info>
+    <link type="guide" xref="index#py"/>
+  
+    <desc>Use Gtk+ and GStreamer to build a simple guitar tuner application for GNOME</desc>
+    
+    <revision pkgversion="0.1" version="0.1" date="2010-12-02" status="stub"/>
+    <credit type="author">
+      <name>GNOME Documentation Project</name>
+      <email>gnome-doc-list gnome org</email>
+    </credit>
+    <credit type="author">
+      <name>Johannes Schmid</name>
+      <email>jhs gnome org</email>
+    </credit>
+  </info>
+
+<title>Guitar Tuner (FIXME)</title>
+
+<synopsis>
+  <p>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:</p>
+  <list>
+    <item><p>Set-up up a basic project in Anjuta</p></item>
+    <item><p>Create a simple GUI with Anjuta's UI designer</p></item>
+    <item><p>Use GStreamer to play sounds</p></item>
+  </list>
+  <p>You'll need the following to be able to follow this tutorial:</p>
+  <list>
+    <item><p>An installed copy of the <link xref="getting-ready">Anjuta IDE</link></p></item>
+    <item><p>Basic knowledge of the Python programming language</p></item>
+  </list>
+</synopsis>
+
+<media type="image" mime="image/png" src="media/guitar-tuner.png"/>
+
+<section>
+  <title>Create a project in Anjuta</title>
+  <p>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.</p>
+  <steps>
+    <item>
+    <p>Start Anjuta and click <guiseq><gui>File</gui><gui>New</gui><gui>Project</gui></guiseq> to open the project wizard.</p>
+    </item>
+    <item>
+    <p>Choose <gui>Gtk+ (Simple)</gui> from the <gui>Python</gui> tab, click <gui>Forward</gui>, and fill-out your details on the next few pages. Use <file>guitar-tuner</file> as project name and directory.</p>
+   	</item>
+    <!--<item>
+    <p>Make sure that <gui>Configure external packages</gui> is selected. On the next page, select
+       <em>gstreamer-0.10</em> from the list to include the <app>GStreamer</app> library into your project.</p>
+    </item>-->
+    <item>
+    <p>Click <gui>Finished</gui> and the project will be created for you. Open <file>src/main.py</file> from the <gui>Project</gui> or <gui>File</gui> tabs. You should see some code which starts with the lines:</p>
+    <!-- FIXME -->
+    <code mime="test/x-python"><![CDATA[
+from gi.repository import Gtk, Gst, GObject 
+import sys]]></code>
+    </item>
+  </steps>
+</section>
+
+<section>
+  <title>Run the code for the first time</title>
+  <p>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:</p>
+  
+  <list>
+  <item>
+    <p>The three <code>import</code> lines at the top include the <code>config</code> (useful autoconf build defines), <code>gtk</code> (user interface) and <code>gi18n</code> (internationalization) libraries. Functions from these libraries are used in the rest of the code.</p>
+   </item>
+   <item>
+    <p>The <code>create_window</code> function 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. The GtkBuilder file contains a description of a user interface and all of its elements. You can use Anjuta's editor design GtkBuilder user interfaces.</p>
+    <p>Connecting signals is how you define what happens when you push a button, or when some other event happens. Here, the <code>destroy</code> function is called (and quits the app) when you close the window.</p>
+   </item>
+   <item>
+    <p>The <code>main</code> function is run by default when you start a C application. It calls a few functions which set-up and then run the application. The <code>gtk_main</code> function start the GTK mainloop, which runs the user interface and starts listening for events (like clicks and key presses).</p>
+   </item>
+   <item>
+    <p>The <code>ENABLE_NLS</code> conditional definition sets-up <code>gettext</code>, which is a framework for translating applications. These functions specify how translation tools should handle your app when you run them.</p>
+   </item>
+  </list>
+
+  <p>This code is ready to be used, so you can run it by clicking <guiseq><gui>Run</gui><gui>Run</gui></guiseq>.</p>
+</section>
+
+<section>
+  <title>Create the user interface</title>
+  <p>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 left, and the palette of available widgets is on the right.
+  </p>
+  <p>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.</p>
+  <steps>
+   <item>
+   <p>Select a <gui>GtkButtonBox</gui> from 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 six strings).</p>
+   </item>
+   <item>
+    <p>Now, choose a <gui>GtkButton</gui> from the palette and put it into the first part of the box.</p>
+   </item>
+   <item>
+    <p>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.</p>
+    </item>
+    <item>
+     <p>Switch to the <gui>Signals</gui> tab (inside the <gui>Widgets</gui> tab) and look for the <code>clicked</code> 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 <code>on_button_clicked</code> in the <gui>Handler</gui> column and press <key>Return</key>.</p>
+    </item>
+    <item>
+    <p>Repeat the above steps for the other buttons, adding the next 5 strings with the names <em>A</em>, <em>D</em>, <em>G</em>, <em>B</em>, and <em>e</em>.</p>
+    </item>
+    <item>
+    <p>Save the UI design by clicking <guiseq><gui>File</gui><gui>Save</gui></guiseq>) and then close it.</p>
+    </item>
+  </steps>
+</section>
+
+<section>
+  <title>Write the signal handler</title>
+  <p>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 create that function in the source file.</p>
+  <p>To do this, add the following code somewhere in <file>main.c</file>:</p>
+<code mime="test/x-python"><![CDATA[
+void on_button_clicked (GtkWidget* button, gpointer user_data)
+{
+
+}]]></code>
+  <p>This signal handler has two arguments: a pointer to the GtkWidget that called the function (in our case, always a GtkButton), and a pointer to some "user data" that you can define, but which we won't be using here. (You can set the user data by calling <code>gtk_builder_connect_signals</code>; it is normally used to pass a pointer to a data structure that you might need to access inside the signal handler.)</p>
+  <p>You can find the prototypes of signal handlers in the Gtk+ documentation.</p>
+  <p>For now, we'll leave the signal handler empty while we work on writing the code to produce sounds.</p>
+</section>
+
+<section>
+  <title>GStreamer pipelines</title>
+  <p>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.</p>
+  <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>
+  <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>
+  <media type="image" mime="image/png" src="media/guitar-tuner-pipeline.png">
+    <p>An example GStreamer pipeline.</p>
+  </media>
+</section>
+
+<section>
+  <title>Set up the pipeline</title>
+  <p>In this simple example we will use a tone generator source called <code>audiotestsrc</code> and send the output to the default system sound device, <code>autoaudiosink</code>. We only need to configure the frequency of the tone generator; this is accessible through the <code>freq</code> property of <code>audiotestsrc</code>.</p>
+  
+  <p>Insert the following line into <file>main.py</file>, just below the <code><![CDATA[#include <gtk/gtk.h>]]></code> line:</p>
+  <code mime="test/x-python"><![CDATA[#include <gst/gst.h>]]></code>
+  <p>This includes the GStreamer library. You also need to add a line to initialize GStreamer; put the following code on the line above the <code>gtk_init</code> function in the <code>main</code> function:</p>
+  <code><![CDATA[gst_init (&argc, &argv);]]></code>
+  <p>Then, copy the following function into <file>main.c</file> somewhere:</p>
+  <code mime="test/x-python"><![CDATA[
+def play_sound(self, frequency):
+  pipeline = Gst.Pipeline(name='note')
+  source = Gst.ElementFactory.make('audiotestsrc', 'src')
+  sink = Gst.ElementFactory.make('autoaudiosink', 'output')
+  
+  source.set_property('freq', frequency)
+  pipeline.add(source)
+  pipeline.add(sink)
+  pipeline.set_state(Gst.State.PLAYING)
+  
+  GObject.timeout_add(self.LENGTH, self.pipeline_stop, pipeline)]]></code>
+  
+  <steps>
+    <item>
+    <p>The first three lines create source and sink GStreamer elements (<code>GstElement</code>), 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 <code>audiotestsrc</code> source; and the sink is named "output" and set to the <code>autoaudiosink</code> sink (default sound card output).</p>
+    </item>
+    <item>
+    <p>The call to <code>source.set_property</code> sets the <code>freq</code> property of the source element to <code>frequency</code>, which was passed as an argument to the <code>play_sound</code> function. This is just the frequency of the note in Hertz; some useful frequencies will be defined later on.</p>
+    </item>
+    <item>
+    <p>The next two lines call <code>pipeline.add</code>, putting the source and sink into the pipeline. The pipeline is actually a <code>GstBin</code>, which is just an element that can contain multiple other GStreamer elements. In general, you can add as many GstElements as you like to the pipeline by calling its <code>add</code> method repeatedly.</p>
+    </item>
+    <item>
+    <p>Next, <code>gst_element_link</code> 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). <code>pipeline.set_state</code> is then used to start playback, by setting the state of the pipeline to playing (<code>Gst.State.PLAYING</code>).</p>
+    </item>
+  </steps>
+  
+</section>
+
+<section>
+  <title>Stopping playback</title>
+  <p>We don't want to play an annoying tone forever, so the last thing <code>play_sound</code> does is to call <code>GObject.timeout_add</code>. This sets a timeout for stopping the sound; it waits for <code>LENGTH</code> milliseconds before calling the function <code>pipeline_stop</code>, and will keep calling it until <code>pipeline_stop</code> returns <code>False</code>.</p>
+  <p>Now, we'll write the <code>pipeline_stop</code> function which is called by <code>g_timeout_add</code>. Insert the following code <em>above</em> the <code>play_sound</code> function:</p>
+  <code mime="test/x-python"><![CDATA[
+LENGTH = 500
+
+def pipeline_stop(self, pipeline):
+  pipeline.set_state(Gst.State.PAUSED)
+  return False]]></code>
+  <p>The call to <code>pipeline.set_state</code> pauses the playback of the pipeline.</p>
+</section>
+
+<section>
+  <title>Define the tones</title>
+  <p>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 top of <file>main.c</file>) as follows:</p>
+  <code mime="test/x-python"><![CDATA[
+# Frequencies of the strings
+NOTE_E = 369.23
+NOTE_A = 440
+NOTE_D = 587.33
+NOTE_G = 783.99
+NOTE_B = 987.77
+NOTE_e = 1318.5]]></code>
+  <p>Now to flesh-out the signal handler that we defined earlier, <code>on_button_clicked</code>. 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:</p>
+  <!-- Not done in a very Python-y way. Can we just loop through a list? -->
+  <!-- Also, what's the deal with the semicolons? -->
+  <code mime="test/x-python"><![CDATA[
+def on_button_clicked(self, button):
+  label = button.get_child()
+  text = label.get_label()
+
+  if text == "E":
+    self.play_sound (self.NOTE_E);
+  elif text == "A":
+    self.play_sound (self.NOTE_A);
+  elif text == "G":
+    self.play_sound (self.NOTE_G);
+  elif text == "D":
+    self.play_sound (self.NOTE_D);
+  elif text == "B":
+    self.play_sound (self.NOTE_B);
+  elif text == "e":
+    self.play_sound (self.NOTE_e);]]></code>
+  <p>The GtkButton that was clicked is passed as an argument (<code>button</code>) to <code>on_button_clicked</code>. We can get the label of that button by using <code>button.get_child</code>, and then get the text from that label using <code>label.get_label</code>.</p>
+  <p>The label text is then compared to the notes that we have in an <code>if ... elif</code> block, and <code>play_sound</code> is called with the frequency appropriate for that note. This plays the tone; we have a working guitar tuner!</p>
+</section>
+
+<section>
+  <title>Run the application</title>
+  <p>All of the code should now be ready to go. Click <guiseq><gui>Run</gui><gui>Run</gui></guiseq> to start the application. Enjoy!</p>
+</section>
+
+<section>
+ <title>Reference Implementation</title>
+ <p>If you run into problems with the tutorial, compare your code with this <link href="guitar-tuner/guitar-tuner.py">reference code</link>.</p>
+</section>
+
+<section>
+  <title>Next steps</title>
+  <p>Here are some ideas for how you can extend this simple demonstration:</p>
+  <list>
+   <item>
+   <p>Have the program automatically cycle through the notes.</p>
+   </item>
+   <item>
+   <p>Make the program play recordings of real guitar strings being plucked.</p>
+   <p>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.</p>
+   <p>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/";>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/";>pads</link>. You may also find the <cmd>gst-inspect</cmd> command useful.</p>
+   </item>
+   <item>
+   <p>Automatically analyze notes that the user plays.</p>
+   <p>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 is being played?</p>
+   </item>
+  </list>
+</section>
+
+</page>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]