Pomocí GTK+ a GStreamer sestavíme jednoduchou aplikaci GNOME fungující jako kytarová ladička. Ukážeme si také, jak používat návrhář rozhraní.
Dokumentační projekt GNOME
gnome-doc-list@gnome.org
Johannes Schmid
jhs@gnome.org
Tiffany Antopolski
tiffany.antopolski@gmail.com
Marta Maria Casetti
mmcasetti@gmail.com 2013

# Kytarová ladička

      V této lekci vytvoříte aplikaci, která přehrává tóny, které můžete použít k naladění kytary. Naučíte se:

        Vytvořit základní projekt pomocí IDE Anjuta.
        Vytvořit jednoduché GUI v návrháři uživatelského rozhraní Anjuta.
        Používat knihovnu GStreamer k přehrávání zvuků.

      Abyste mohli pokračovat v této lekci, budete potřebovat následující:

        Základní znalosti programovacího jazyka Vala.
        Nainstalovanou kopii vývojářského studia Anjuta.

# Vytvoření projektu v IDE Anjuta.

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ě.

Spusťte aplikaci Anjuta a klikněte na Vytvořit nový projekt nebo Soubor Nový Projekt, aby se otevřel průvodce projektem.

Na kartě Vala zvolte GTK+ (jednoduchý). Klikněte na Pokračovat a na několika následujících stránkách vyplňte své údaje. Jako název projektu a složky použijte guitar-tuner.

Ujistěte se, že Konfigurovat externí balíčky je přepnuto na Zapnuto. Na následující stránce vyberte v seznamu gstreamer-0.10, aby se knihovna GStreamer zahrnula do vašeho projektu. Klikněte na Pokračovat.

Klikněte na Použít a vytvoří se vám projekt. Dvojitým kliknutím na kartě Projekt nebo Soubor otevřete src/guitar_tuner.vala. Měli byste vidět kód, který začíná řádky:

using GLib; using Gtk;

# Prvotní sestavení kódu

Kód 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:

Dva řádky `using` importují jmenné prostory, takže je nebudeme muset výslovně uvádět.

Konstruktor třídy `Main` vytvoří nové okno otevřením souboru GtkBuilder (src/guitar-tuner.ui definovaný a pár řádků dřív), napojí jeho signály a zobrazí jej v okně. Soubor obsahuje popis uživatelského rozhraní a všech jeho prvků. K návrhu uživatelského rozhraní můžete použít editor v IDE Anjuta.

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 funkce `on_destroy` (a ukončení aplikace) při zavření okna.

Statická funkce `main` se spustí jako výchozí, když spustíte aplikaci napsanou v jazyce Vala. Volá pár funkcí, které vytvoří třídu `Main` a nastaví a spustí aplikaci. Funkce `Gtk.main` spustí hlavní smyčku GTK, která spustí uživatelské rozhraní a začne naslouchat událostem (jako je kliknutí nebo zmáčknutí klávesy).

Kód je připraven k použití, takže jej můžete zkompilovat kliknutím na Sestavit Sestavit projekt (nebo zmáčknutím Shift F7). Když to uděláte, objeví se dialogové okno. Změňte Konfiguraci na Výchozí a klikněte na Spustit, aby se nakonfigurovala složka, ve které se provádí sestavení. Stačí to udělat jen jednou, pro první sestavení.

# Vytvoření uživatelského rozhraní

Popis uživatelského rozhraní se nachází v souboru GtkBuilder src/guitar_tuner.ui definovaném na začátku třídy. Když chcete uživatelské rozhraní upravit, otevřete src/guitar_tuner.ui dvojitým kliknutím na něj v části Projekt nebo Soubory. Přepnete se tím do návrháře rozhraní. Navrhované okno je uprostřed, widgety a jejich vlastnosti jsou napravo a paleta dostupných widgetů je nalevo.

Rozvržení každého uživatelského rozhraní v GTK+ je provedeno pomocí boxů a mřížek. Zde použijeme svislý `GtkButtonBox`, do kterého přiřadíme šest `GtkButtons`, jedno pro každou z kytarových strun.

Kliknutím na ikonu vyberte Box na tlačítka (GtkButtonBox) z oddílu Kontejnery na kartě Paleta. Pak kliknutím na návrh okna uprostřed tento box do okna umístěte. Objeví se dialogové okno, kde nastavte Počet položek na 6. Nakonec klikněte na Vytvořit.

Můžete také změnit Počet prvků a Orientaci na kartě Obecné napravo.

Nyní na Paletě v oddílu Ovládání a zobrazení vyberte kliknutím Tlačítko (GtkButton). Umístěte jej do první části GtkButtonBox kliknutím do této první části.

Zatímco je tlačítko stále vybráno, přejděte napravo na kartu Obecné na vlastnost Popiseka změňte ji na E. Bude se jednat o spodní kytarovou strunu E.

Karta Obecné se nachází v části Widgety napravo.

Přepněte se na kartu Signál v části Widgety napravo a podívejte se po signálu `clicked` 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 `main_on_button_clicked` do sloupce Obslužná rutina a zmáčknutím Enter.

Zopakujte předchozí kroky pro ostatní tlačítka, takže přidáte následujících 5 strun s názvy A, D, G, B a e.

Návrh uživatelského rozhraní uložte (kliknutím na Soubor Uložit) a ponechte jej otevřený.

# Roury systému GStreamer

Tato část předvádí, jak vytvořit kód, který vydává zvuk. 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í.

Koncepčně GStreamer funguje následovně: Vytvoříte rouru obsahující různé prvky zpracující směrem od zdroje do cíle (výstupu). Zdrojem může být například soubor s obrázkem, videosoubor nebo hudební soubor, výstupem pak widget nebo zvuková karta.

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říklad roury systému GStreamer.

# Vytvoření roury

V tomto příkladu použijeme jako zdroj tónový generátor nazývaný `audiotestsrc` a výstup pošleme do výchozího systémového zvukového zařízení `autoaudiosink`. Nastavit nám stačí jen frekvenci tónového generátoru. Ta je přístupná v podobě vlastnosti `freq` u `audiotestsrc`.

Musíme přidat řádek inicializující GStreamer. Vložte následující kód na řádek nad volání `Gtk.init` ve funkci `main`:

Gst.init (ref args);

Pak nakopírujte následující funkci do třídy `Main` v guitar_tuner.vala:

Gst.Element sink; Gst.Element source; Gst.Pipeline pipeline;

private void play_sound(double frequency) { pipeline = new Gst.Pipeline ("note"); source = Gst.ElementFactory.make ("audiotestsrc", "source"); sink = Gst.ElementFactory.make ("autoaudiosink", "output");

/* nastavení frekvence */ source.set ("freq", frequency);

pipeline.add (source); pipeline.add (sink); source.link (sink);

pipeline.set_state (Gst.State.PLAYING);

/* zastavení po 200 ms */ var time = new TimeoutSource(200);

time.set_callback(() => { pipeline.set_state (Gst.State.NULL); return false; }); time.attach(null); }

Prvních tři řádky vytvoří prvky GStreamer typu zdroj a cíl (`Gst.Element`) a prvek typu roura (který bude použit jako kontejner pro první dva prvky). Jedná se o proměnné třídy, takže jsou definovny mimo metodu. Roura dostane název „note“. Zdroj je pojmenován „source“ a je nastaven jako `audiotestsrc`. Cíl je pojmenován „output“ a je nastaven jako `autoaudiosink` (výchozí výstup zvukové karty).

Volání `source.set_property` nastaví vlastnost `freq` prvku `source` na frekvenci `frequency`, která je předána jako argument do funkce `play_sound`. Jedná se o frekvenci v Hertzích. Správné frekvence nadefinujeme později.

`pipeline.add` vloží zdroj a cíl do roury. Roura je `Gst.Bin`, 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í opakovaného volání `pipeline.add`.

Následně je `sink.link` použito k propojení prvků navzájem, takže výstup prvku `source` (tón) putuje do vstupu prvku `sink` (což je výstup do zvukové karty). `pipeline.set_state` je použito ke spuštění přehrávání nastavením stavu roury na přehrávání (`Gst.State.PLAYING`).

Nechceme ale hrát nějaký tón navždycky, takže poslední věcí, kterou `play_sound` udělá, je že přidá `TimeoutSource`. Tím se nastaví časový limit pro zastavení zvuku. Čeká 200 milisekund a pak zavolá obsluhu signálu definovanou jako vloženou, která zastaví a zlikviduje rouru. Ta vrací `false`, aby odstranila sebe sama z `TimeoutSource`, jinak by se pokračovalo v jejím volání každých 200 ms.

# Vytvoření obsluhy signálů

V návrháři uživatelského rozhraní to můžete udělat tak, že všechna tlačítka budou, když se na ně klikne, volat stejnou funkci on_button_clicked. Ve skutečnosti napíšeme main_on_button_clicked, což návrháři říká, že tato metoda je součástí Main. Tuto funkci musíme přidat do souboru se zdrojovým kódem.

K tomuto účelu vyberte v souboru s uživatelským rozhraním (guitar_tuner.ui) kliknutím jedno z tlačítek a pak otevřete guitar_tuner.vala (kliknutím na kartu uprostřed). Přepněte se na kartu Signály napravo, kterou jste již použili pro nastavení názvu signálu. Nyní chytněte řádek, na kterém jste nastavili signál clicked a přetáhněte jej do zdrojového kódu na začátek třídy. Do zdrojového kódu se přidá následující kód:

public void on_button_clicked (Gtk.Button odesilatel) {

}

Místo přetahování z návrháře můžete kód samozřejmě také napsat ručně na začátek třídy.

Tato obsluha signálu má jen jeden argument: `Gtk.Widget`, který je volán funkcí (v našem případě vždy `Gtk.Button`).

# Definování obsluhy signálů

Když uživatel klikne na tlačítko, chceme přehrát správný zvuk. To znamená, že musíme oživit obsluhu signálu `on_button_clicked`, kterou jsem zadeklarovali již dříve. 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:

public void on_button_clicked (Gtk.Button sender) { var label = sender.get_child () as Gtk.Label; switch (label.get_label()) { case "E": play_sound (329.63); break; case "A": play_sound (440); break; case "D": play_sound (587.33); break; case "G": play_sound (783.99); break; case "B": play_sound (987.77); break; case "e": play_sound (1318); break; default: break; } }

Tlačítko `Gtk.Button`, na které bylo kliknuto, je předáno jako argument (`odesilatel`) do `on_button_clicked`. Pomocí `get_child` můžeme získat popisek tohoto tlačítka a z něj následně získat jeho text pomocí `get_label`.

Výraz `switch` porovnává text popisku s notami, které chceme zahrát a funkce `play_sound` je zavolána s příslušnou frekvencí pro tuto notu. Tím se přehraje tón – máme funkční kytarovou ladičku!

# Sestavení a spuštění aplikace

Celý kód by nyní měl být připravený k fungování. Klikněte na Sestavit Sestavit projekt, aby se vše znovu sestavilo a pak na Spustit Spustit, aby se aplikace spustila.

Pokud jste tak ještě neučinili, zvolte aplikaci Debug/src/guitar-tuner v dialogovém okně, které se objeví. Nakonec klikněte na Spustit a užijte si ji!

# Ukázková implementace

Pokud v této lekci narazíte na nějaké problémy, porovnejte si svůj kód s tímto ukázkovým kódem.

# Co dalšího si přečíst

Jestli si chcete najít více o programování v jazyce Vala, můžete se podívat na Výuku jazyka Vala a Dokumentaci k API jazyka Vala.

# Další postup

Zde je pár nápadů, jak byste mohli tuto jednoduchou ukázku rozšířit:

Přidat do programu možnost cyklicky procházet tóny.

Naučit program přehrávat nahrávky vybrnkání jednotlivých reálných kytarových strun.

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 dekodér a demultiplexor podle formátu souborů s vašimi zvukovými nahrávkami – například MP3 používá jiné prvky než Ogg Vorbis.

Můžete také potřebovat prvky propojit mnohem komplikovanějším způsobem. Toho lze dosáhnout pomocí konceptů GStreamer, které jsme v této lekci neprobírali. Mezi ně patří například přípojné body. Hodit se vám může také příkaz gst-inspect.

Automaticky analyzovat tóny, které uživatel zahraje.

Mohli byste připojit mikrofón a nahrávat z něj zvuky pomocí vstupního zdroje. Zjistit, který tón je přehráván, by vám možná pomohla spektrální analýza.