<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="guitar-tuner.c" xml:lang="el">

  <info>
    <link type="guide" xref="index#c"/>

    <desc>Χρησιμοποιήστε Gtk+ και GStreamer για να φτιάξετε ένα απλό πρόγραμμα συντονιστή κιθάρας για το GNOME. Αναδεικνύοντας πως να χρησιμοποιήσετε το σχεδιαστή διεπαφών.</desc>

    <revision pkgversion="0.1" version="0.1" date="2010-12-02" status="review"/>
    <credit type="author">
      <name>Έργο τεκμηρίωσης GNOME</name>
      <email>gnome-doc-list@gnome.org</email>
    </credit>
    <credit type="author">
      <name>Johannes Schmid</name>
      <email>jhs@gnome.org</email>
    </credit>
  </info>

<title>Συντονιστής κιθάρας</title>

<synopsis>
  <p>Σε αυτόν τον οδηγό, θα φτιάξουμε ένα πρόγραμμα που παίζει μουσικούς τόνους και μπορεί να συντονίσει μια κιθάρα. Θα μάθετε να:</p>
  <list>
    <item><p>Να φτιάχνετε ένα βασικό έργο στο Anjuta</p></item>
    <item><p>Δημιουργείτε απλό GUI με τον σχεδιαστή UI του Anjuta</p></item>
    <item><p>Χρησιμοποιείτε το GStreamer για να παίζετε ήχους</p></item>
  </list>
  <p>Θα χρειαστείτε τα παρακάτω για να μπορέσετε να ακολουθήσετε αυτόν τον οδηγό:</p>
  <list>
    <item><p>Ένα εγκατεστημένο αντίγραφο του </p></item>
    <item><p>Basic knowledge of the C programming language</p></item>
  </list>
</synopsis>

<media type="image" mime="image/png" src="media/guitar-tuner.png"/>

<section id="anjuta">
  <title>Δημιουργήστε ένα έργο με το Anjuta</title>
  <p>Πριν ξεκινήσετε να προγραμματίζετε, πρέπει να δημιουργήσετε ένα καινούργιο έργο στο Anjuta. Έτσι θα δημιουργηθούν όλα τα απαραίτητα αρχεία που χρειάζονται για την εκτέλεση του κώδικα αργότερα. Επίσης θα ήταν χρήσιμο να τα κρατάτε όλα μαζί.</p>
  <steps>
    <item>
    <p>Ξεκινήστε το Anjuta και πατήστε <guiseq><gui>Αρχείο</gui><gui>Νέο</gui><gui>Έργο</gui></guiseq> για να ανοίξετε το μάγο του έργου (project wizard).</p>
    </item>
    <item>
    <p>Choose <gui>Gtk+ (Simple)</gui> from the <gui>C</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.</p>
   	</item>
    <item>
    <p>Make sure that <gui>Configure external packages</gui> is switched <gui>ON</gui>. On the next page, select
       <em>gstreamer-0.10</em> from the list to include the GStreamer library in your project.</p>
    </item>
    <item>
    <p>Click <gui>Apply</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>]]></code>
    </item>
  </steps>
</section>

<section id="build">
  <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/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 to 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 starts the GTK main loop, 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>Execute</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 id="ui">
  <title>Δημιουργείτε διεπαφή χρήστη</title>
  <p>Μια περιγραφή της διεπαφής χρήστη (UI) περιέχεται στο αρχείο GtkBuilder. Για να επεξεργαστείτε τη διεπαφή χρήστη, ανοίξτε το <file>src/guitar_tuner.ui</file>. Θα βρεθείτε στο σχεδιαστή διεπαφής. Το παράθυρο σχεδίασης είναι στο κέντρο· τα γραφικά συστατικά και οι ρυθμίσεις τους είναι στα αριστερά, η παλέτα με τα διαθέσιμα γραφικά συστατικά στα δεξιά.</p>
  <p>Η διάταξη κάθε διεπαφής χρήστη σε Gtk+ οργανώνεται σε κουτιά και πίνακες. Ας χρησιμοποιήσουμε εδώ ένα κάθετο <gui>GtkButtonBox</gui> για να τοποθετήσουμε έξι <gui>GtkButtons</gui>, ένα για κάθε μία από τις χορδές της κιθάρας.</p>

<media type="image" mime="image/png" src="media/guitar-tuner-glade.png"/>

  <steps>
   <item>
   <p>Διαλέξτε ένα <gui>GtkButtonBox</gui> από το τμήμα <gui>Container</gui> στην <gui>Παλέτα</gui> στο δεξιά και προσθέστε το στο παράθυρο. Στην καρτέλα <gui>Ιδιότητες</gui> καθορίστε τον αριθμό των στοιχείων σε 6 (για τις έξι χορδές της κιθάρας) και τον προσανατολισμό σε κάθετο.</p>
   </item>
   <item>
    <p>Τώρα, διαλέξτε ένα <gui>GtkButton</gui> από την παλέτα και βάλτε το στο πρώτο μέρος του κουτιού.</p>
   </item>
   <item>
    <p>Έχοντας το κουμπί ακόμα επιλεγμένο, αλλάξτε την <gui>Ετικέτα</gui> στην καρτέλα <gui>Γραφικά συστατικά</gui> σε <gui>E</gui>. Αυτή θα είναι η χαμηλή χορδή Ε.</p>
    </item>
    <item>
     <p>Πηγαίνετε στην καρτέλα <gui>Σήματα</gui> (μέσα στην καρτέλα <gui>Γραφικά συστατικά</gui>) και βρείτε το σήμα <code>clicked</code> του κουμπιού. Μπορείτε να το χρησιμοποιήσετε για να συνδέσετε έναν χειριστή σημάτων που θα καλείται όταν πατηθεί το κουμπί. Για να το κάνετε αυτό, πατήστε πάνω στην στήλη <gui>Χειριστής</gui> του σήματος και γράψτε <code>on_button_clicked</code> και πατήστε <key>Return</key>.</p>
    </item>
    <item>
    <p>Επαναλάβετε τα παραπάνω βήματα για τα υπόλοιπα κουμπιά, προσθέστε τις επόμενες 5 χορδές με τα ονόματα <em>A</em>, <em>D</em>, <em>G</em>, <em>B</em>, και <em>e</em>.</p>
    </item>
    <item>
    <p>Αποθηκεύστε το αρχείο (πατώντας <guiseq><gui>Αρχείο</gui><gui>Αποθήκευση</gui></guiseq>) και κρατήστε το ανοιχτό.</p>
    </item>
  </steps>
</section>

<section id="signal">
  <title>Creating the signal handler</title>
  <p>Στον σχεδιαστή διεπαφών χρήστη, κάνατε όλα τα κουμπιά να καλούν την ίδια συνάρτηση, <gui>on_button_clicked</gui>, όταν πατηθούν. Πρέπει να προσθέσουμε αυτή την συνάρτηση στο πηγαίο κώδικα.</p>
  <p>To do this, open <file>main.c</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
<gui>clicked</gui> signal and drag it into to the source file at a
position that is outside any function. The following code will be added to your source file:</p>
<code mime="text/x-csrc"><![CDATA[
void on_button_clicked (GtkWidget* button, gpointer user_data)
{

}]]></code>
  <p>This signal handler has two arguments: a pointer to the <code>GtkWidget</code> that called the function (in our case, always a <code>GtkButton</code>), 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>Για την ώρα, θα αφήσουμε το χειριστή σημάτων άδειο καθώς θα ασχοληθούμε με το γράψιμο του κώδικα που θα παράγει τους ήχους.</p>
</section>

<section id="gstreamer">
  <title>Σωληνώσεις (pipeline) του GStreamer</title>
  <p>Το Gtreamer είναι το υποσύστημα (framework) πολυμέσων του GNOME — μπορείτε να το χρησιμοποιήσετε για να αναπαράγετε, ηχογραφήσετε, και να επεξεργαστείτε βίντεο, ήχο, ροές βίντεο και τα λοιπά. Εδώ, θα το χρησιμοποιήσουμε για να παράγουμε μονές-συχνότητες τόνων.</p>
  <p>Εννοιολογικά, το GStreamer λειτουργεί ως εξής: δημιουργείς μια <em>σωλήνωση (pipeline)</em> που περιέχει διάφορα επεξεργαζόμενα στοιχεία που πηγαίνουν από την <em>source</em> (πηγή) στο <em>sink</em> (έξοδο). Η πηγή μπορεί να είναι ένα αρχείο εικόνας, βίντεο, ή και μουσικής, για παράδειγμα, και η έξοδος μπορεί να είναι ένα γραφικό συστατικό ή η κάρτα ήχου.</p>
  <p>Ανάμεσα στην πηγή και στην έξοδο, μπορείτε να εφαρμόσετε διάφορα φίλτρα και μετατροπές για τον χειρισμό εφέ, μετατροπές είδους αρχείου (format) και λοιπά. Κάθε στοιχείο της σωλήνωσης έχει ρυθμίσεις που μπορούν να χρησιμοποιηθούν για να αλλάξουν τη συμπεριφορά.</p>
  <media type="image" mime="image/png" src="media/guitar-tuner-pipeline.png">
    <p>Ένα παράδειγμα σωλήνωσης GStreamer</p>
  </media>
</section>

<section id="pipeline">
  <title>Ρύθμιση της σωλήνωσης (pipeline)</title>
  <p>Σε αυτό το απλό παράδειγμα θα χρησιμοποιήσουμε μια πηγή παραγωγής τόνων, την <code>audiotestsrc</code> και θα στείλουμε την έξοδο στην προεπιλεγμένη συσκευή ήχου του συστήματος, <code>autoaudiosink</code>. Πρέπει μόνο να ρυθμίσουμε την συχνότητα της παραγωγής τόνου· αυτό είναι εφικτό μέσα από την ρύθμιση <code>freq</code> του <code>audiotestsrc</code>.</p>

  <p>Insert the following line into <file>main.c</file>, just below the <code><![CDATA[#include <gtk/gtk.h>]]></code> line:</p>
  <code mime="text/x-csrc"><![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> call 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> above the empty <code>on_button_clicked</code> function:</p>
  <code mime="text/x-csrc"><![CDATA[static void
play_sound (gdouble frequency)
{
	GstElement *source, *sink;
	GstElement *pipeline;

	pipeline = gst_pipeline_new ("note");
	source   = gst_element_factory_make ("audiotestsrc",
	                                     "source");
	sink     = gst_element_factory_make ("autoaudiosink",
	                                     "output");

	/* set frequency */
	g_object_set (source, "freq", frequency, NULL);

	gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
	gst_element_link (source, sink);

	gst_element_set_state (pipeline, GST_STATE_PLAYING);

	/* stop it after 500ms */
	g_timeout_add (LENGTH, (GSourceFunc) pipeline_stop, pipeline);
}]]></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 elements 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 <code>source</code> (a tone) goes into the input of <code>sink</code> (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 id="stop">
  <title>Διακοπή αναπαραγωγής</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/x-csrc"><![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 id="tones">
  <title>Ορίστε τους τόνους</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="text/x-csrc"><![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]]></code>
  <p>Για να δούμε τον χειριστή σημάτων που ορίσαμε πριν, <code>on_button_clicked</code>. Θα μπορούσαμε να είχαμε συνδέσει όλα τα κουμπιά σε διαφορετικό χειριστή σημάτων, αλλά αυτό θα οδηγούσε σε πολλές επαναλήψεις του κώδικα. Αντί αυτού, μπορούμε να χρησιμοποιήσουμε τις ετικέτες στα κουμπιά για να δούμε ποιο πατήθηκε:</p>
  <code mime="text/x-csrc"><![CDATA[
/* Callback for the buttons */
void on_button_clicked (GtkButton* button,
                        gpointer user_data)
{
	GtkWidget* label = gtk_bin_get_child (GTK_BIN (button));
	const gchar* text = gtk_label_get_label (GTK_LABEL (label));

	if (g_str_equal (text, _("E")))
	    play_sound (NOTE_E);
	else if (g_str_equal (text, _("A")))
	    play_sound (NOTE_A);
	else if (g_str_equal (text, _("G")))
	    play_sound (NOTE_G);
	else if (g_str_equal (text, _("D")))
	    play_sound (NOTE_D);
	else if (g_str_equal (text, _("B")))
	    play_sound (NOTE_B);
	else if (g_str_equal (text, _("e")))
	    play_sound (NOTE_e);
}
]]></code>
  <p>A pointer to the <code>GtkButton</code> 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 id="run">
  <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>Execute</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 id="impl">
 <title>Υλοποίηση αναφοράς</title>
 <p>If you run into problems with the tutorial, compare your code with this <link href="guitar-tuner/guitar-tuner.c">reference code</link>.</p>
</section>

<section id="next">
  <title>Επόμενα βήματα</title>
  <p>Εδώ είναι κάποιες ιδέες για το πως μπορείτε να επεκτείνετε αυτή την απλή επίδειξη:</p>
  <list>
   <item>
   <p>Βάλτε το πρόγραμμα να περνάει αυτόματα μέσα από τις νότες.</p>
   </item>
   <item>
   <p>Κάντε το πρόγραμμα να αναπαράγει ηχογραφήσεις από αληθινές χορδές κιθάρας που έχουν εισαχθεί.</p>
   <p>Για να το κάνετε αυτό, πρέπει να ρυθμίσετε μια πιο περίπλοκη σωλήνωση GStreamer που θα σας επιτρέπει να φορτώνετε και να αναπαράγετε αρχεία ήχου. Θα πρέπει να διαλέξετε τα στοιχεία GStreamer <link href="http://gstreamer.freedesktop.org/documentation/plugins.html">decoder και demuxer</link> με βάση τον τύπο του αρχείου των ηχογραφημένων ήχων — για παράδειγμα το MP3 χρησιμοποιεί διαφορετικά στοιχεία από το Ogg Vorbis.</p>
   <p>Ίσως χρειαστεί να συνδέσετε τα στοιχεία με πιο περίπλοκους τρόπους. Αυτό μπορεί να συμπεριλαμβάνει τη χρήση <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-intro-basics.html">Εννοιών GStreamer</link> που δεν καλύπτουμε σε αυτόν τον οδηγό, όπως και <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-intro-basics-pads.html">pad</link>. Ίσως βρείτε χρήσιμη και την εντολή <cmd>gst-inspect</cmd>.</p>
   </item>
   <item>
   <p>Αυτόματη ανάλυση νότων που παίζει ο χρήστης.</p>
   <p>Μπορείτε να συνδέσετε μικρόφωνο και να ηχογραφήσετε από αυτό χρησιμοποιώντας την <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-autoaudiosrc.html">πηγή input (εισόδου)</link>. Ίσως κάποια μορφή της <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-plugin-spectrum.html">ανάλυσης φάσματος</link> θα σας βοηθούσε να καταλάβετε ποια νότα παίζει;</p>
   </item>
  </list>
</section>

</page>
