[gnome-devel-docs] Demos: substantial edits to guitar-tuner demo



commit 7fc7fec3c4d03cde7fc2f389af0e9a4a78d943f4
Author: Phil Bull <philbull gmail com>
Date:   Sat Dec 4 01:03:08 2010 +0000

    Demos: substantial edits to guitar-tuner demo

 demos/guitar-tuner.c.page            |  331 +++++++++++++++-------------------
 demos/guitar_tuner/simple-player.png |  Bin 0 -> 53147 bytes
 2 files changed, 146 insertions(+), 185 deletions(-)
---
diff --git a/demos/guitar-tuner.c.page b/demos/guitar-tuner.c.page
index 0ac6523..b900f75 100644
--- a/demos/guitar-tuner.c.page
+++ b/demos/guitar-tuner.c.page
@@ -1,13 +1,11 @@
 <page xmlns="http://projectmallard.org/1.0/";
-      type="Guitar-Tuner example for GNOME"
+      type="topic"
       id="guitar-tuner">
 
   <info>
     <link type="guide" xref="index"/>
-    <link type="seealso" xref="index"/>
   
-    <desc>This tutorial will show of Gtk+ and GStreamer to build a simple guitar tuner application
-    for GNOME</desc>
+    <desc>This tutorial shows how you can 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">
@@ -17,19 +15,18 @@
     
   </info>
 
-<title>Guitar-Tuner example</title>
+<title>Guitar Tuner</title>
 
 <synopsis>
-  <p>In this tutorial, you will learn:</p>
+  <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>Setting up a basic project in Anjuta</p></item>
-    <item><p>Creating a simple GUI with the Glade UI editor</p></item>
-    <item><p>Using GStreamer to play sound</p></item>
+    <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>The following is required to follow that tutorial</p>
+  <p>You'll need the following to be able to follow this tutorial:</p>
   <list>
-    <item><p>Anjuta (Integrated Development Environment)is 
-    installed and working (TODO: Link install instructions)</p></item>
+    <item><p>An installed copy of the <link xref="getting-ready">Anjuta IDE</link></p></item>
     <item><p>Basic knowledge of the C programming language</p></item>
   </list>
 </synopsis>
@@ -37,177 +34,108 @@
 <media type="image" mime="image/png" src="guitar_tuner/guitar-tuner.png"/>
 
 <section>
-  <title>Setup the project in anjuta</title>
+  <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>Startup <app>anjuta</app></p></item>
-    <item><p>Open the project wizard with <guiseq><gui>File</gui><gui>New</gui><gui>Project</gui></guiseq></p></item>
-    <item><p>Choose <gui>Gtk+ (Simple)</gui> from the <gui>C</gui> tab and hit <gui>Next</gui></p></item>
-    <item><p>Fill out your details on the next pages. Use <file>guiter-tuner</file> as project name and 
-       directory</p></item>
-    <item><p>Enable the <gui>Configure external pages</gui> switch and choose </p></item>
-    <item><p>After you hit <gui>Finished</gui> the project should be created for you and 
-    you can open the <file>src/main.c</file>
-    from the <gui>Project</gui> or the <gui>File</gui> tab. You should see the following code:</p></item>
-  </steps>
-  <code mime="text/C"><![CDATA[
+    <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>C</gui> tab, click <gui>Next</gui>, and fill-out your details on the next few pages. Use <file>guiter-tuner</file> as project name and directory.</p>
+   	</item>
+    <item>
+    <p>Make sure that <gui>Configure external packages</gui> is selected.</p>
+    </item>
+    <item>
+    <p>Click <gui>Finished</gui> and the project will be created for you. Open <file>src/main.c</file> from the <gui>Project</gui> or <gui>File</gui> tabs. You should see some code which starts with the lines:</p>
+    <code mime="text/x-csrc"><![CDATA[
 #include <config.h>
-#include <gtk/gtk.h>
-
-
-#include <glib/gi18n.h>
-
-
-/* For testing propose use the local (not installed) ui file */
-/* #define UI_FILE PACKAGE_DATA_DIR"/gtk_foobar/ui/gtk_foobar.ui" */
-#define UI_FILE "src/gtk_foobar.ui"
-
-/* Signal handlers */
-/* Note: These may not be declared static because signal autoconnection
- * only works with non-static methods
- */
-
-/* Called when the window is closed */
-void
-destroy (GtkWidget *widget, gpointer data)
-{
-	gtk_main_quit ();
-}
-
-static GtkWidget*
-create_window (void)
-{
-	GtkWidget *window;
-	GtkBuilder *builder;
-	GError* error = NULL;
-
-	/* Load UI from file */
-	builder = gtk_builder_new ();
-	if (!gtk_builder_add_from_file (builder, UI_FILE, &error))
-	{
-		g_warning ("Couldn't load builder file: %s", error->message);
-		g_error_free (error);
-	}
-
-	/* Auto-connect signal handlers */
-	gtk_builder_connect_signals (builder, NULL);
-
-	/* Get the window object from the ui file */
-	window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
-	g_object_unref (builder);
-	
-	return window;
-}
-
-int
-main (int argc, char *argv[])
-{
- 	GtkWidget *window;
-
-
-#ifdef ENABLE_NLS
-	bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
-	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-	textdomain (GETTEXT_PACKAGE);
-#endif
-
-	
-	gtk_set_locale ();
-	gtk_init (&argc, &argv);
-
-	window = create_window ();
-	gtk_widget_show (window);
-
-	gtk_main ();
-	return 0;
-}
-  ]]></code>
+#include <gtk/gtk.h>]]></code>
+    </item>
+  </steps>
 </section>
 
 <section>
-  <title>Initial build</title>
-  <p>C is a rather verbose language so don't be surprised that this is quite a lot of code, most of it is
-     template code. It loads an (empty) window from the user interface description file and shows it.</p>
-  <p>But it already works so you can compile it by using <guiseq><gui>Build</gui><gui>Build Project</gui></guiseq> or
-    <key>Shift+F7</key>. Just hit <gui>Configure</gui> on the next dialog to configure a debug build. This is only
-    necessary for the first build. </p>
+  <title>Build the code for the first time</title>
+  <p>C is a rather verbose language, so don't be surprised that the file contains quite a lot of code. Most of it 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>#include</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/gtk_foobar.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 compile it by clicking <guiseq><gui>Build</gui><gui>Build Project</gui></guiseq> (or press <keyseq><key>Shift</key><key>F7</key></keyseq>).</p>
+  <p>Press <gui>Configure</gui> on the next window that appears to configure a debug build. You only need to do this once, for the first build.</p>
 </section>
 
 <section>
   <title>Create the user interface</title>
-  <p>The user interface is described in an XML format and can be put together graphically. To open the user-interface.
-    open <file>src/guitar_tuner.ui</file>. This will switch to the interface designer. The window is the center while
-    you have the widgets and widgets properties to the left and the pallette of available widgets to the right.
+  <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>Ever user interface in GTK+ is organized into boxes and tables. We use a vertical <gui>GtkButtonBox</gui> here
-    to assign six <gui>GtkButton</gui>s for the six guitar strings.</p>
-
-    <steps>
-        <item><p>Choose a <gui>GtkButtonBox</gui> from the <gui>Palette</gui> on the right and put 
-        in into the window. Set the number of elements to 6 for the six strings</p></item>
-        <item><p>Choose a <gui>GtkButton</gui> from the left and put in 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> for the low E string.</p></item>
-        <item><p>Switch to the <gui>Signals</gui> tab inside of <gui>Widgets</gui> and search for the 
-            <gui>clicked</gui> signal
-            of the button. You can connect a signal handler here that will be called once the user presses the button.
-            To do so, click on the signal and type <gui>on_button_clicked</gui> in the <gui>Handler</gui> column and hit
-            <key>Return</key>.</p></item>
-        <item><p>Repeat the above steps for the other buttons completing the 6 strings with the names A, D, G, B, e</p></item>
-        <item><p>Save the file (<guiseq><gui>File</gui><gui>Save</gui></guiseq>) and close it.</p></item>
-    </steps>
+  <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 in 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>Creating the signal handler</title>
-
-    <p>As all buttons call <gui>on_button_clicked</gui> now when they are clicked we need to create that function.
-    This is quite simple, just add this code a some point of <file>main.c</file>:</p>
+  <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="text/C"><![CDATA[
 void on_button_clicked (GtkWidget* button, gpointer user_data)
 {
 
-}
-]]></code>
-    <p>The prototype of each signal handler is available in the Gtk+ documentation (TODO: link). 
-    For GtkButton::clicked there are no additional arguments. The <gui>user_data</gui> is a pointer that you
-    can set in the call to gtk_builder_connect_signals() and it usually contains a pointer to a data structure
-    you might need to access inside the signal handler.</p>
+}]]></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>Playing the sound</title>
-        <section>
-        <title>The GStreamer Multimedia framework</title>
-        <p><app>GStreamer</app> is used inside of GNOME for all kind of multimedia handling. The concept
-        is that you a pipeline containing several processing elements from the source to the output (also called
-        sink here). The source can be an image file, a video, or a music file and the output could a window or
-        the soundcard. Between those elements various filters and converters can be applied to handle effects
-        or format conversions.</p>.
-        <p>Each element of the pipeline has properties to change it's behaviour.</p>
-        </section>
-
-        <section>
-        <title>Setting up the pipeline</title>
-        <p>In this simple example we use a tone generator called <gui>audiotestsrc</gui> and send
-        the output to the configured sound device (autoaudiosink).</p>
-        <p>We only need to configure the frequency of the tone generator which is accesible through
-        the <gui>freq</gui> property of <gui>audiotestsrc</gui>.</p>
-        <p>As we don't want to play an annoying tone forever, we setup a timeout for stopping.</p>
-<code mime="text/C"><![CDATA[
-/* Length of playing in ms */
-#define LENGTH 500
-
-static gboolean
-pipeline_stop (GstElement* pipeline)
-{
-	gst_element_set_state (pipeline, GST_STATE_PAUSED);
-	g_object_unref (pipeline);
-
-	/* disconnect handler */
-	return FALSE;
-}
+  <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="simple-player.png">
+    <p>An example GStreamer pipeline.</p>
+  </media>
+  <!-- FIXME: Needs copyright clearing: Image taken from GStreamer docs: http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-intro-basics-bins.html#section-pipeline-img -->
+</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 code into <file>main.c</file>:</p>
+  <code mime="text/C"><![CDATA[
 static void 
 play_sound (gdouble frequency)
 {
@@ -228,28 +156,58 @@ play_sound (gdouble frequency)
 
 	gst_element_set_state (pipeline, GST_STATE_PLAYING);
 
-	/* stop it after 200ms */
+	/* stop it after 500ms */
 	g_timeout_add (LENGTH, (GSourceFunc) pipeline_stop, pipeline);
-}
-]]></code>
-    </section>
-    <section>
-    <title>Bringing everything together</title>
-    <p>Finally we need to play the correct sound when the user clicks a button. We already setup the
-    signal handler so this is also really easy. The only thing we need to take core of is that we
-    play the right sound for the clicked string. We could have connected every button to a different signal
-    handler but that would lead to a lot of code duplication. Instead, we abuse the label of the button
-    to know which button was clicked.</p>
-    <p>Of course we also need to know the frequencies for the six guitar strings which we need to define.</p>
-    <code mime="text/C"><![CDATA[
+}]]></code>
+  
+  <steps>
+    <item>
+    <p>The first five 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>g_object_set</code> sets the <code>freq</code> property of the source element to <code>frequency</code>, which is 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><code>gst_bin_add_many</code> puts the source and sink into the pipeline. The pipeline is 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 adding more arguments to <code>gst_bin_add_many</code>.</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>gst_element_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>g_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="text/C"><![CDATA[
+#define LENGTH 500 /* Length of playing in ms */
+
+static gboolean
+pipeline_stop (GstElement* pipeline)
+{
+	gst_element_set_state (pipeline, GST_STATE_PAUSED);
+	g_object_unref (pipeline);
+	
+	return FALSE;
+}]]></code>
+  <p>The call to <code>gst_element_set_state</code> pauses the playback of the pipeline and <code>g_object_unref</code> unreferences the pipeline, destroying it and freeing its memory.</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 as follows:</p>
+  <code mime="text/C"><![CDATA[
 /* Frequencies of the strings */
 #define NOTE_E 369.23
 #define NOTE_A 440
 #define NOTE_D 587.33
 #define NOTE_G 783.99
 #define NOTE_B 987.77
-#define NOTE_e 1318.5
-
+#define 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>
+  <code mime="text/C"><![CDATA[
 /* Callback for the buttons */
 void on_button_clicked (GtkButton* button,
                         gpointer user_data)
@@ -271,16 +229,19 @@ void on_button_clicked (GtkButton* button,
 	    play_sound (NOTE_e);
 }
 ]]></code>
-    </section>
+  <p>A pointer to 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>gtk_bin_get_child</code>, and then get the text from that label using <code>gtk_label_get_label</code>.</p>
+  <p>The label text is then compared to the notes that we have using <code>g_str_equal</code>, 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>Building and running the application</title>
-<steps>
-    <item><p><guiseq><gui>Build</gui><gui>Build Project</gui></guiseq> to build everything again</p></item>
-    <item><p><guiseq><gui>Run</gui><gui>Run</gui></guiseq> to start the application</p></item>
-    <item><p>Choose the <file>Debug/src/guitar-tuner</file> application if not already done in the dialog</p></item>
-    <item><p>Hit <gui>Run</gui> and enjoy!</p></item>
-</steps>
+  <title>Build and run the application</title>
+  <p>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>Run</gui></guiseq> to start the application.</p>
+  <p>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!</p>
 </section>
+
+<section>
+  <title>Next steps</title>
+  <p></p>
+</section>
+
 </page>
diff --git a/demos/guitar_tuner/simple-player.png b/demos/guitar_tuner/simple-player.png
new file mode 100644
index 0000000..b3b3ca1
Binary files /dev/null and b/demos/guitar_tuner/simple-player.png differ



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