# Kytavorá ladička (JavaScript)

Susanna Huhtanen
ihmis.suski@gmail.com 2012
Používá GTK+ a GStreamer k sestavení jednoduché aplikace pro GNOME s funkcionalitou kytarové ladičky.

# Kytarová ladička

          V této lekci sestavíme malou aplikaci, kytarovou ladičku, pomocí jazyka JavaScript a knihoven GTK+ a GStreamer. Abyste tak mohli učinit a spustit si kód z příkladu, budete potřebovat nainstalovaný editor pro psaní kódu, terminál a GNOME 3.0 nebo novější.

          Roury systému GStreamer
          Skript pro spuštění aplikace
          Importované knihovny
          Vytvoření hlavního okna pro aplikaci
          Tlačítka pro ladění
          Vyluzování zvuků systémem GStreamer
          Napojení tlačítek na playSound
          Celý program
          Spuštění aplikace z terminálu

Po přečtení této lekce byste měli na obrazovce dostat toto:

# Roury systému GStreamer

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 (pipeline) obsahující různé prvky zpracující směrem od zdroje (source) do cíle (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.

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.

# Skript pro spuštění aplikace

#!/usr/bin/gjs

Tento řádek říká, jak spustit skript. Musí být prvním řádek v souboru s kódem a soubor musí být spustitelný. Abyste získali práva na spuštění, jděte do terminálu a ve správné složce spusťte: chmod +x název_skriptu. Nebo můžete použít grafického správce souborů. Přejděte do správné složky s vašim kódem, klikněte na soubor s kódem pravým tlačítkem, zvolte vlastnosti, klikněte na kartu oprávnění a zaškrtněte políčko, které povoluje spuštění souboru jako programu.

# Importované knihovny

var Gtk = imports.gi.Gtk; var Gst = imports.gi.Gst;

const Mainloop = imports.mainloop;

Abychom dostali fungující program, potřebujeme naimportovat pár GObject Introspection, tj. knihoven, pro naše použití. Pro fungující uživatelské rozhraní potřebujeme Gtk a pro GStreamer potřebujeme Gst. Import se provádí hned na začátku, takže budou fungovat všude. Na začátku také naimportujeme konstrukt Mainloop, který se bude starat o časové omezení při vydávání ladicích tónů.

# Vytvoření hlavního okna pro aplikaci

Gtk.init(null, 0); Gst.init(null, 0);

var guitarwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL, border_width: 100}); guitarwindow.title = "Guitar Tuner"; guitarwindow.connect("destroy", function(){Gtk.main_quit()});

guitarwindow.show(); Gtk.main();

Jen naimportovat Gtk a Gst nestačí, je třeba je inicializovat, aby fungovaly. Když jsou Gtk a Gst nastavené a běží, potřebujeme vytvořit okno pro aplikaci. Později do tohoto okna vložíme všechna tlačítka pro vydávání tónů. Aby se okno zobrazilo, musíme mu říci, ať se zobrazí, a také musíme spustit kód s `Gtk.main()`.

# Tlačítka pro ladění

var guitar_box = new Gtk.ButtonBox ({orientation: Gtk.Orientation.VERTICAL, spacing: 10});

var E = new Gtk.Button({label: "E"}); var A = new Gtk.Button({label: "A"}); var D = new Gtk.Button({label: "D"}); var G = new Gtk.Button({label: "G"}); var B = new Gtk.Button({label: "B"}); var e = new Gtk.Button({label: "e"});

guitar_box.add(E); guitar_box.add(A); guitar_box.add(D); guitar_box.add(G); guitar_box.add(B); guitar_box.add(e);

guitarwindow.add(guitar_box);

guitar_box.show_all();

Protože `Gtk.Window` může obsahovat jen jediný widget, potřebujeme vytvořit nějaký další podkladový, který bude schopný do sebe přidat všechna tlačítka. V tomto příkladu použijeme `Buttonbox` (box na tlačítka). Po jeho vytvoření vytvoříme tlačítka s patřičnými popisky. Když máme tlačítka, musíme je přidat do kontejneru Buttonbox a ten musíme přidat do Gtk.Window a vše v boxu na tlačítka se musí zobrazit.

Po této fázi byste měli mít okno, které se ukáže na obrazovce a zobrazí šest tlačítek. Je v pořádku, že tlačítka nic nedělají, to budeme řešit později. Než vůbec můžeme někam napojit signály tlačítek, musíme ono „někam“ nejdříve naprogramovat.

# Vyluzování zvuků systémem GStreamer

var frequencies = {E: 329.63, A: 440, D: 587.33, G: 783.99, B: 987.77, e: 1318.5}

function playSound(frequency){ var pipeline = new Gst.Pipeline({name: "note"}); var source = Gst.ElementFactory.make("audiotestsrc","source"); var sink = Gst.ElementFactory.make("autoaudiosink","output");

source.set_property('freq', frequency); pipeline.add(source); pipeline.add(sink); source.link(sink); pipeline.set_state(Gst.State.PLAYING);

Mainloop.timeout_add(500, function () { pipeline.set_state(Gst.State.NULL); return false; }); }

Nejprve se musíme rozhodnout, jaké tóny chceme při zmáčknutí tlačítka vyloudit. O to se postará seznam frekvencí. Tím se dostáváme k tomu, jak vydat zvuk ve funkci `playSound`. Té jako vstup předáváme frekvenci (ty jsme právě nadefinovali do proměnné). Jako první musíme sestrojit rouru, zdroj a cíl. Zdroji nastavíme frekvenci. K rouře přidáme zdroj i cíl a pak řekneme, ať to hraje. Jako poslední věc použijeme objekt `Mainloop` k zastavení roury po 500 ms.

Nyní máme způsob, jak přehrát tón při kliknutí na tlačítko. Takže jako další krok propojíme zmáčknutí tlačítka s přehráním správného tónu.

# Napojení tlačítek na playSound

E.connect("clicked", function() { playSound(frequencies.E); }); A.connect("clicked", function(){ playSound(frequencies.A); }); D.connect("clicked", function(){ playSound(frequencies.D); }); G.connect("clicked", function(){ playSound(frequencies.G); }); B.connect("clicked", function(){ playSound(frequencies.B); }); e.connect("clicked", function(){ playSound(frequencies.e); });

Způsob propojení kliknutí na tlačítko a funkce `playSound` se správným tónem se provede pomocí metody `connect` widgetu tlačítka. Zvolíme napojované tlačítko a napíšeme `E.connect("clicked", function(){playSound(frequencies.E);});`. Metoda `connect` říká, že když se zmáčkne E, má se něco stát. Řetězec `"clicked"` říká, o jaký typ signálu se u tlačítka jedná a funkce `function(){};` volá `playSound` se správnou notou, která k tlačítku patří.

# Celý program

Takže všechny části spojené dohromady vypadají takto. Když spustíte tento kód, měli byste být schopni naladit si svoji kytaru (pokud máte správně zkalibrované reproduktory).

#!/usr/bin/gjs var Gtk = imports.gi.Gtk; var Gst = imports.gi.Gst;

const Mainloop = imports.mainloop;

Gtk.init(null, 0); Gst.init(null, 0);

var guitarwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL, border_width: 100}); guitarwindow.title = "Guitar Tuner"; guitarwindow.connect("destroy", function(){Gtk.main_quit()});

var guitar_box = new Gtk.ButtonBox ({orientation: Gtk.Orientation.VERTICAL, spacing: 10});

var E = new Gtk.Button({label: "E"}); var A = new Gtk.Button({label: "A"}); var D = new Gtk.Button({label: "D"}); var G = new Gtk.Button({label: "G"}); var B = new Gtk.Button({label: "B"}); var e = new Gtk.Button({label: "e"});

var frequencies = {E: 329.63, A: 440, D: 587.33, G: 783.99, B: 987.77, e: 1318.5}

function playSound(frequency){ var pipeline = new Gst.Pipeline({name: "note"});

var source = Gst.ElementFactory.make("audiotestsrc","source"); var sink = Gst.ElementFactory.make("autoaudiosink","output");

source.set_property('freq', frequency); pipeline.add(source); pipeline.add(sink); source.link(sink); pipeline.set_state(Gst.State.PLAYING);

Mainloop.timeout_add(500, function () { pipeline.set_state(Gst.State.NULL); return false; }); }

E.connect("clicked", function() { playSound(frequencies.E); }); A.connect("clicked", function(){ playSound(frequencies.A); }); D.connect("clicked", function(){ playSound(frequencies.D); }); G.connect("clicked", function(){ playSound(frequencies.G); }); B.connect("clicked", function(){ playSound(frequencies.B); }); e.connect("clicked", function(){ playSound(frequencies.e); });

guitar_box.add(E); guitar_box.add(A); guitar_box.add(D); guitar_box.add(G); guitar_box.add(B); guitar_box.add(e);

guitarwindow.add(guitar_box);

guitar_box.show_all(); guitarwindow.show(); Gtk.main();

# Spuštění aplikace z terminálu

Pro spuštění aplikace otevřete terminál, přejděte do složky, kde je vaše aplikace uložená a pak ji spusťte

     $  GJS_PATH=`pwd` gjs guitarTuner.js

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