<?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 <config.h>
#include <gtk/gtk.h></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 <gtk/gtk.h></code>:</p>
<code mime="text/x-csrc">#include <gst/gst.h></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 (&argc, &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>