Blob Blame History Raw
<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" type="topic" id="guitar-tuner.c" xml:lang="cs">

  <info>
    <title type="text">Kytarová ladička (C)</title>
    <link type="guide" xref="c#examples"/>

    <desc>Jak použít GTK+ a GStreamer k sestavení jednoduché aplikace pro GNOME fungující jako kytarová ladička. Předvedeme si, jako používat návrhář rozhraní.</desc>

    <revision pkgversion="0.1" version="0.1" date="2010-12-02" status="review"/>
    <credit type="author">
      <name>Dokumentační projekt GNOME</name>
      <email its:translate="no">gnome-doc-list@gnome.org</email>
    </credit>
    <credit type="author">
      <name>Johannes Schmid</name>
      <email its:translate="no">jhs@gnome.org</email>
    </credit>
    <credit type="editor">
      <name>Marta Maria Casetti</name>
      <email its:translate="no">mmcasetti@gmail.com</email>
      <years>2013</years>
    </credit>
  </info>

<title>Kytarová ladička</title>

<synopsis>
  <p>V této lekci vytvoříme program, který přehrává tóny, které můžete použít k ladění kytary. Naučíte se, jak udělat tyto věci:</p>
  <list>
    <item><p>Vytvořit základní projekt ve studiu Anjuta.</p></item>
    <item><p>Vytvořit jednoduché GUI v návrháři GUI ve studiu Anjuta.</p></item>
    <item><p>Použít GStreamer k přehrání zvuku.</p></item>
  </list>
  <p>Abyste mohli pokračovat v této lekci, budete potřebovat následující:</p>
  <list>
    <item><p>Nainstalovanou kopii <link xref="getting-ready">IDE Anjuta</link></p></item>
    <item><p>Základní znalosti programovacího jazyka C</p></item>
  </list>
</synopsis>

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

<section id="anjuta">
  <title>Vytvoření projektu ve studiu Anjuta</title>
  <p>Než začnete s kódováním, musíte ve studiu Anjuta vytvořit nový projekt. Tím se vytvoří všechny soubory, které budete později potřebovat k sestavení a spuštění kódu. Je to také užitečné kvůli udržení všeho pohromadě.</p>
  <steps>
    <item>
    <p>Spusťte IDE Anjuta a klikněte na <guiseq><gui>Soubor</gui> <gui>Nový</gui> <gui>Projekt</gui></guiseq>, aby se otevřel průvodce projektem.</p>
    </item>
    <item>
    <p>Na kartě <gui>C</gui> zvolte <gui>GTK+ (jednoduchý)</gui>, klikněte na <gui>Pokračovat</gui> a na několika následujících stránkách vyplňte své údaje. Jako název projektu a složky použijte <file>guitar-tuner</file>.</p>
   	</item>
    <item>
    <p>Ujistěte se, že <gui>Konfigurovat externí balíčky</gui> je přepnuto na <gui>Zapnuto</gui>. Na následující stránce vyberte v seznamu <em>gstreamer-0.10</em>, aby se knihovna GStreamer zahrnula do vašeho projektu.</p>
    </item>
    <item>
    <p>Klikněte na <gui>Použít</gui> a vytvoří se vám projekt. Otevřete <file>src/main.c</file> na kartě <gui>Projekt</gui> nebo <gui>Soubor</gui>. Měli byste vidět kód, který začíná řádky:</p>
    <code mime="text/x-csrc">
#include &lt;config.h&gt;
#include &lt;gtk/gtk.h&gt;</code>
    </item>
  </steps>
</section>

<section id="build">
  <title>Prvotní sestavení kódu</title>
  <p>C je celkem „upovídaný“ jazyk, takže nebuďte překvapeni, že soubor obsahuje poměrně hodně kódu. Většina toho je kód šablony. Načte (prázdné) okno ze souboru s popisem uživatelského rozhraní a zobrazí jej. Dále to podrobněji rozebereme. Pokud jste již pochopili základy, tak tento seznam můžete přeskočit:</p>

  <list>
  <item>
    <p>Tři řádky <code>#include</code> na začátku vkládají knihovny <code>config</code> (užitečné definice pro sestavení pomocí autotools), <code>gtk</code> (uživatelské rozhraní) a <code>gi18n</code> (internacionalizace). Funkce z těchto knihoven se používají ve zbytku kódu.</p>
   </item>
   <item>
    <p>Funkce <code>create_window</code> vytvoří nové okno ze souboru GtkBulder (<file>src/guitar-tuner.ui</file>, definováno o pár řádků výše), připojí jeho signály a zobrazí jej v okně. Soubor GtkBuilder obsahuje popis uživatelského rozhraní a jeho prvků. K návrhu uživatelského rozhraní GtkBuilder můžete použít editor přímo ve vývojářském studiu Anjuta.</p>
    <p>Napojení signálu je způsob, jak definovat, co se má stát, když zmáčknete tlačítko nebo se prostě něco přihodí. Zde je zavolána metoda <code>destroy</code> (a ukončení aplikace) při zavření okna.</p>
   </item>
   <item>
    <p>Funkce <code>main</code> se spustí jako výchozí, když spustíte aplikaci napsanou v jazyce C. Volá pár funkcí, které nastaví a spustí aplikaci. Funkce <code>gtk_main</code> spustí hlavní smyčku GTK, která spustí uživatelské rozhraní a začne naslouchat událostem (jako je kliknutí nebo zmáčknutí klávesy).</p>
   </item>
   <item>
    <p>Podmíněná definice <code>ENABLE_NLS</code> nastavuje <code>gettext</code>, což je základní konstrukce pro překládání aplikací do národních jazyků. Tyto funkce určují, jak mají překladové nástroje pracovat s vaší aplikací za běhu.</p>
   </item>
  </list>

  <p>Kód je připravený k použití, takže jej můžete zkompilovat kliknutím na <guiseq><gui>Sestavit</gui> <gui>Sestavit projekt</gui></guiseq> (nebo zmáčknutím <keyseq><key>Shift</key> <key>F7</key></keyseq>).</p>
  <p>V následujícím okně zmáčkněte <gui>Spustit</gui>, aby se nakonfigurovalo ladicí sestavení. Stačí to udělat jen jednou, pro první sestavení.</p>
</section>

<section id="ui">
  <title>Vytvoření uživatelského rozhraní</title>
  <p>Popis uživatelského rozhraní se nachází v souboru GtkBuilder. Když chcete uživatelské rozhraní upravit, otevřete <file>src/guitar_tuner.ui</file>. Přepnete se tím do návrháře rozhraní. Navrhované okno je uprostřed, widgety a jejich vlastnosti jsou nalevo a paleta dostupných widgetů je napravo.</p>
  <p>Rozvržení každého uživatelského rozhraní v GTK+ je provedeno pomocí boxů a mřížek. Zde použijeme svislý <code>GtkButtonBox</code>, do kterého přiřadíme šest <code>GtkButtons</code>, jedno pro každou z kytarových strun.</p>

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

  <steps>
   <item>
   <p>Vyberte <gui>GtkButtonBox</gui> z oddílu <gui>Kontejnery</gui> v <gui>Paletě</gui> napravo a vložte jej do okna. V panelu <gui>Vlastnosti</gui> nastavte počet prvků na 6 (pro 6 strun) a orientaci na svislou.</p>
   </item>
   <item>
    <p>Nyní v paletě zvolte <gui>GtkButton</gui> a vložte jej do první části boxu.</p>
   </item>
   <item>
    <p>Zatímco je tlačítko stále vybráno, změňte vlastnost <gui>Popisek</gui> na kartě <gui>Widgety</gui> na <gui>E</gui>. Bude se jednat o spodní strunu E.</p>
    </item>
    <item>
     <p>Přepněte se na kartu <gui>Signál</gui> (uvnitř karty <gui>Widgety</gui>) a podívejte se po signálu <code>clicked</code> tlačítka. Můžete jej použít k napojení na obsluhu signálu, která bude volána, když uživatel na tlačítko klikne. Provede se to kliknutím na signál a vepsáním <code>on_button_clicked</code> do sloupce <gui>Obslužná rutina</gui> a zmáčknutím <key>Enter</key>.</p>
    </item>
    <item>
    <p>Zopakujte předchozí kroky pro ostatní tlačítka, takže přidáte následujících 5 strun s názvy <em>A</em>, <em>D</em>, <em>G</em>, <em>B</em> a <em>e</em>.</p>
    </item>
    <item>
    <p>Návrh uživatelského rozhraní uložte (kliknutím na <guiseq><gui>Soubor</gui> <gui>Uložit</gui></guiseq>) a ponechte jej otevřený.</p>
    </item>
  </steps>
</section>

<section id="signal">
  <title>Vytvoření obsluhy signálů</title>
  <p>V návrháři uživatelského rozhraní můžete nastavit to, že všechna tlačítka budou při kliknutí volat stejnou funkci <gui>on_button_clicked</gui>. Tuto funkci musíme přidat do zdrojového kódu.</p>
  <p>K tomu otevřete <file>main.c</file> a soubor s uživatelským rozhraním při tom ponechte stále otevřený. Přepněte se na kartu <gui>Signály</gui>, kterou jste již použili pro nastavení názvu signálu. Nyní chytněte řádek, na kterém jste nastavili signál <gui>clicked</gui> a přetáhněte jej do zdrojového kódu na místo mimo kteroukoliv funkci. Do zdrojového kódu se přidá následující kód:</p>
<code mime="text/x-csrc">
void on_button_clicked (GtkWidget* button, gpointer user_data)
{

}</code>
  <p>Obsluha signálu má dva argumenty: ukazatel na <code>GtkWidget</code>, který funkci zavolal (v našem případě vždy <code>GtkButton</code>) a ukazatel na nějaká „uživatelská data“, která si můžete nadefinovat, ale zde je nebudeme chtít použít. (Uživatelská data můžete nastavit zavoláním <code>gtk_builder_connect_signals</code>. Normálně se použivá k předání ukazatele na datovou strukturu, ke které můžete potřebovat přístup uvnitř obsluhy signálu.)</p>
  <p>Prozatím ponecháme obsluhu signálu prázdnou a budeme pracovat na psaní kódu pro vyluzování zvuků.</p>
</section>

<section id="gstreamer">
  <title>Roury systému GStreamer</title>
  <p>GStreamer je základní multimediální rámec GNOME. Můžete jej použít k přehrávání, nahrávání a zpracování videa, zvuku, vysílání z webové kamery a podobně. Zde jej použijeme ke generování tónu s jednou frekvencí.</p>
  <p>Koncepčně GStreamer funguje následovně: Vytvoříte <em>rouru</em> (pipeline) obsahující různé prvky zpracující směrem od <em>zdroje</em> (source) do <em>cíle</em> (sink), tj. výstupu. Zdrojem může být například soubor s obrázkem, videosoubor nebo hudební soubor, výstupem pak widget nebo zvuková karta.</p>
  <p>Na cestě mezi zdrojem a cílem můžete použít různé filtry a převodníky k vytvoření efektů, převodníky formátů atd. Každý prvek roury má vlastnosti, které můžete použít ke změně jeho chování.</p>
  <media type="image" mime="image/png" src="media/guitar-tuner-pipeline.png">
    <p>Příklad roury systému GStreamer.</p>
  </media>
</section>

<section id="pipeline">
  <title>Vytvoření roury</title>
  <p>V tomto příkladu použijeme jako zdroj tónový generátor nazývaný <code>audiotestsrc</code> a výstup pošleme do výchozího systémového zvukového zařízení <code>autoaudiosink</code>. Nastavit potřebujeme jen frekvenci tónového generátoru. Ta je přístupná přes vlastnost <code>freq</code> zmíněného <code>audiotestsrc</code>.</p>

  <p>Vložte do <file>main.c</file> následující řádek, hned pod řádek <code>#include &lt;gtk/gtk.h&gt;</code>:</p>
  <code mime="text/x-csrc">#include &lt;gst/gst.h&gt;</code>
  <p>Tímto se vloží knihovna GStreamer. Potřebujete také přidat řádek inicializující GStreamer. Vložte následující kód na řádek nad volání <code>gtk_init</code> do funkce <code>main</code>:</p>
  <code>gst_init (&amp;argc, &amp;argv);</code>
  <p>Pak nakopírujte následující funkci do <file>main.c</file> nad prázdnou funkci <code>on_button_clicked</code>:</p>
  <code mime="text/x-csrc">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");

	/* nastaví frekvenci */
	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);

	/* zastaví to po 500 ms */
	g_timeout_add (LENGTH, (GSourceFunc) pipeline_stop, pipeline);
}</code>

  <steps>
    <item>
    <p>Prvních pět řádků vytvoří prvky GStreamer typu zdroj a cíl (<code>GstElement</code>) a prvek typu roura (který bude použit jako kontejner pro první dva prvky). Roura dostane název „note“. Zdroj je pojmenován „source“ a je nastaven jako <code>audiotestsrc</code>. Cíl je pojmenován „output“ a je nastaven jako <code>autoaudiosink</code> (výchozí výstup zvukové karty).</p>
    </item>
    <item>
    <p>Volání <code>g_object_set</code> nastaví vlastnost <code>freq</code> zdrojového prvku na <code>frequency</code>, která byla předána jako argument funkci <code>play_sound</code>. Jedná se o frekvenci tónu v hertzích. Správné frekvence nadefinujeme později.</p>
    </item>
    <item>
    <p><code>gst_bin_add_many</code> vloží zdroj a cíl do roury. Roura je <code>GstBin</code>, což je zase jen prvek, který může obsahovat více dalších prvků GStreamer. Obecně můžete přidat tolik prvků, kolik chcete, pomocí předáním více argumentů do <code>gst_bin_add_many</code>.</p>
    </item>
    <item>
    <p>Následně je <code>gst_element_link</code> použito k propojení prvků navzájem, takže výstup prvku <code>source</code> (tón) putuje do vstupu prvku <code>sink</code> (což je výstup do zvukové karty). <code>gst_element_set_state</code> je použito ke spuštění přehrávání nastavením stavu roury na přehrávání (<code>GST_STATE_PLAYING</code>).</p>
    </item>
  </steps>

</section>

<section id="stop">
  <title>Zastavení přehrávání</title>
  <p>Nechceme ale hrát nějaký tón navždycky, takže poslední věcí, kterou <code>play_sound</code> udělá, je, že zavolá <code>g_timeout_add</code>. Tím se nastaví časový limit pro zastavení zvuku. Čeká v délce <code>LENGTH</code> milisekund a pak zavolá funkci <code>pipeline_stop</code>, která vrátí <code>FALSE</code>, jinak by se v jejím volání pokračovalo.</p>
  <p>Nyní budeme psát funkci <code>pipeline_stop</code>, která je volána z <code>g_timeout_add</code>. Vložte následující kód <em>nad</em> funkci <code>play_sound</code>:</p>
  <code mime="text/x-csrc">
#define LENGTH 500 /* Délka přehrávání v ms */

static gboolean
pipeline_stop (GstElement* pipeline)
{
	gst_element_set_state (pipeline, GST_STATE_NULL);
	g_object_unref (pipeline);

	return FALSE;
}</code>
  <p>Zavolání <code>gst_element_set_state</code> zastaví přehrávání roury a <code>g_object_unref</code> zruší odkazy na rouru, zlikviduje ji a uvolní její paměť.</p>
</section>

<section id="tones">
  <title>Definice tónů</title>
  <p>Když uživatel klikne na tlačítko, chceme zahrát správný zvuk. Nejdříve ze všeho potřebujeme znát frekvence pro šest kytarových strun, které jsou definovány (na začátku <file>main.c</file>) následovně:</p>
  <code mime="text/x-csrc">
/* Řetězce pro jednotlivé frekvence */
#define NOTE_E 329.63
#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>Nyní oživíme obsluhu signálu, kterou jsme zadeklarovali již dříve po názvem <code>on_button_clicked</code>. Mohli bychom mít napojená všechna tlačítka na různé obslužné funkce, ale to by vedlo ke zbytečné duplicitě kódu. Místo toho použijeme popisek každého z tlačítek ke zjištění, na které tlačítko bylo kliknuto:</p>
  <code mime="text/x-csrc">
/* Zpětná volání pro tlačítka */
void on_button_clicked (GtkButton* button,
                        gpointer user_data)
{
	const gchar* text = gtk_button_get_label (button);

	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>Ukazatel na <code>GtkButton</code>, na které bylo kliknuto je předán jako argument (<code>button</code>) do <code>on_button_clicked</code>. Text tohoto tlačítka můžeme získat pomocí <code>gtk_button_get_label</code>.</p>
  <p>Text se porovnává s notami, které máme pomocí <code>g_str_equal</code> a <code>play_sound</code> je voláno s příslušnou frekvencí odpovídající notě. Tím se zahraje tón a my máme konečně fungující kytarovou ladičku!</p>
</section>

<section id="run">
  <title>Sestavení a spuštění aplikace</title>
  <p>Celý kód by nyní měl být připravený k fungování. Klikněte na <guiseq><gui>Sestavit</gui> <gui>Sestavit projekt</gui></guiseq>, aby se vše znovu sestavilo a pak na <guiseq><gui>Spustit</gui> <gui>Spustit</gui></guiseq>, aby se aplikace spustila.</p>
  <p>Pokud jste tak ještě neučinili, zvolte aplikaci <file>Debug/src/guitar-tuner</file> v dialogovém okně, které se objeví. Nakonec klikněte na <gui>Spustit</gui> a užijte si ji!</p>
</section>

<section id="impl">
 <title>Ukázková implementace</title>
 <p>Pokud v této lekci narazíte na nějaké problémy, porovnejte si svůj kód s tímto <link href="guitar-tuner/guitar-tuner.c">ukázkovým kódem</link>.</p>
</section>

<section id="next">
  <title>Další postup</title>
  <p>Zde je pár nápadů, jak byste mohli tuto jednoduchou ukázku rozšířit:</p>
  <list>
   <item>
   <p>Přidat do programu možnost cyklicky procházet tóny.</p>
   </item>
   <item>
   <p>Naučit program přehrávat nahrávky vybrnkání jednotlivých reálných kytarových strun.</p>
   <p>Abychom to mohli udělat, potřebujeme sestavit mnohem složitější rouru GStreamer, která umožní načíst a přehrát hudební soubory. Budete muset zvolit prvky GStreamer typu <link href="http://gstreamer.freedesktop.org/documentation/plugins.html">dekodér a demultiplexor</link> podle formátu souborů s vašimi zvukovými nahrávkami – například MP3 používá jiné prvky než Ogg Vorbis.</p>
   <p>Můžete také potřebovat prvky propojit mnohem komplikovanějším způsobem. Toho lze dosáhnout pomocí <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-intro-basics.html">konceptů GStreamer</link>, které jsme v této lekci neprobírali. Mezi ně patří například <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-intro-basics-pads.html">přípojné body</link>. Hodit se vám může také příkaz <cmd>gst-inspect</cmd>.</p>
   </item>
   <item>
   <p>Automaticky analyzovat tóny, které uživatel zahraje.</p>
   <p>Mohli byste připojit mikrofón a nahrávat z něj zvuky pomocí <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-autoaudiosrc.html">vstupního zdroje</link>. Zjistit, který tón je přehráván, by vám možná pomohla <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-plugin-spectrum.html">spektrální analýza</link>.</p>
   </item>
  </list>
</section>

</page>