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.cpp" xml:lang="cs">

  <info>
    <link type="guide" xref="cpp#examples"/>

    <desc>Jak použít GTKmm a GStreamermm 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="2011-03-17" 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 programování v jazyce 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>GTKmm (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 zapnuto. Na následující stránce vyberte v seznamu <em>gstreamermm-0.10</em>, aby se knihovna GStreamer zahrnula do vašeho projektu.</p>
    </item>
    <item>
    <p>Klikněte na <gui>Dokončit</gui> a projekt se vám vytvoří. Otevřete <file>src/main.cc</file> z karty <gui>Projekt</gui> nebo <gui>Soubor</gui>. Měli byste vidět kód začínající řádky:</p>
    <code mime="text/x-csrc">
#include &lt;gtkmm.h&gt;
#include &lt;iostream&gt;</code>
    </item>
  </steps>
</section>

<section id="build">
  <title>Prvotní sestavení kódu</title>
  <p>Jedná se o zcela základní kód C++ nastavující GTKmm. Podrobněji je to popsáno dále. Pokud základům rozumíte, tak tento sezmam přeskočte:</p>
  <list>
  <item>
    <p>Tři řádky s <code>#include</code> na začátku vkládají <code>config</code> (užitečný pro definice sestavení pomocí autoconf), <code>gtkmm</code> (uživatelské rozhraní) a <code>iostream</code> (STL). Funkce z těchto knihoven jsou použity ve zbytku kódu.</p>
   </item>
   <item>
    <p>Funkce <code>main</code> vytvoří nové okno otevřením souboru GtkBuilder (<file>src/guitar-tuner.ui</file> definovaný a pár řádků dřív) 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.</p>
   </item>
   <item>
    <p>Poté se volá několik funkcí, které nastaví a spustí aplikaci. Funkce <code>kit.run</code> spustí hlavní smyčku GTKmm, která spustí uživatelské rozhraní a začne naslouchat událostem (jako jsou kliknutí nebo zmáčknutí kláves).</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>Dokud je tlačítko ještě vybráno, změňte vlastnost <gui>Popisek</gui> na kartě <gui>Widgety</gui> na <gui>E</gui>. Bude se jednat o dolní strunu E. Také změňte vlastnost <gui>Název</gui> na <gui>button_E</gui>. Tímto názvem se na widget budeme později odkazovat v kódu.</p>
    </item>
    <item>
    <p>Opakujte předchozí kroky po ostatní tlačítka, tj. přidejte dalších 5 řetězců s popisky <em>A</em>, <em>D</em>, <em>G</em>, <em>B</em> a <em>e</em> a názvy <em>button_A</em>, atd.</p>
    </item>
    <item>
    <p>Uložte návrh uživatelského rozhraní (kliknutím na <guiseq><gui>Soubor</gui> <gui>Uložit</gui></guiseq>) a soubor zavřete.</p>
    </item>
  </steps>
</section>

<section id="gst">
  <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í. GStreamermm je vazba C++ na GStreamer, kterou zde použijeme.</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="usinggst">
  <title>Používání GStreamermm</title>
  <p>Aby bylo možné používat knihovnu GStreamermm, je nutné ji inicializovat. To provedeme přidáním následujícího řádku s kódem za řádek <code>Gtk::Main kit(argc, argv);</code> v <file>main.cc</file>:</p>
  <code>	Gst::init (argc, argv);</code>
  <p>Když jsme u toho, ujistěte se také, že v <file>main.cc</file> je správně deklarováno <code>include</code> pro <file>gstreamermm.h</file>.</p>

  <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>Pro zjednodušení práce s rourou nadefinujeme pomocnou třídu <code>Sound</code>. Provedeme to v <file>main.cc</file>, abychom zachovali tuto ukázku jednoduchou, ale normálně byste k tomu použili samostatný soubor:</p>
  <code>
class Sound
{
	public:
		Sound();

		void start_playing(double frequency);
		bool stop_playing();

	private:
		Glib::RefPtr&lt;Gst::Pipeline&gt; m_pipeline;
		Glib::RefPtr&lt;Gst::Element&gt; m_source;
		Glib::RefPtr&lt;Gst::Element&gt; m_sink;
};

Sound::Sound()
{
	m_pipeline = Gst::Pipeline::create("note");
	m_source = Gst::ElementFactory::create_element("audiotestsrc",
	                                               "source");
	m_sink = Gst::ElementFactory::create_element("autoaudiosink",
	                                             "output");
	m_pipeline-&gt;add(m_source);
	m_pipeline-&gt;add(m_sink);
	m_source-&gt;link(m_sink);
}

void Sound::start_playing (double frequency)
{
	m_source-&gt;set_property("freq", frequency);
	m_pipeline-&gt;set_state(Gst::STATE_PLAYING);

	/* Zastaví to po 200 ms */
	Glib::signal_timeout().connect(sigc::mem_fun(*this, &amp;Sound::stop_playing),
	                               200);
}

bool Sound::stop_playing()
{
	m_pipeline-&gt;set_state(Gst::STATE_NULL);
	return false;
}
</code>

  <p>Kód má následující účel:</p>
  <steps>
    <item>
    <p>V konstruktoru se vytvoří prvky GStreamer typu zdroj a cíl (<code>Gst::Element</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). Jakmile jsou prvky přidány do roury a spojeny dohromady, je roura připravena k použití.</p>
    </item>
    <item>
    <p><code>start_playing</code> nastaví zdrojový prvek, aby hrál příslušnou frekvenci, a následně spustí rouru, takže zvuk se začne opravdu hrát. Protože tento zvuk nechceme poslouchat navěky, nastavíme časový limit pro zastavení roury pomocí volání <code>stop_playing</code> po 200 ms.</p>
    </item>
    <item>
    <p>Ve funkci <code>stop_playing</code>, která je zavolána po uplynutí časového limitu, je zastavena roura a zvuk tak přestané znít. GStreamermm používá počítání odkazů pomocí objektu <code>Glib::RefPtr</code>, takže po zlikvidování třídy <code>Sound</code> je paměť automaticky uvolněna.</p>
    </item>
  </steps>
</section>

<section id="signals">
  <title>Připojení signálů</title>
  <p>Když uživatel klikne na tlačítko, chceme přehrát správný zvuk. To znamená, že musíme napojit signál, který je spuštěn uživatelovým kliknutím na tlačítko. Také chceme volané funkci poskytnout informaci, který tón má zahrát. GTKmm toto usnadňuje, protože můžeme lehce propojit informace s knihovnou <em>sigc</em>.</p>

  <p>Funkce, která je volána, když uživatel klikne na tlačítko, může být hezky jednoduchá, protože všechny zajímavé věci jsou nyní provedeny v pomocí třídě:</p>
  <code mime="text/x-csrc">
static void
on_button_clicked(double frequency, Sound* sound)
{
	sound-&gt;start_playing (frequency);
}
</code>
  <p>Toto je jen pomocná třída, kterou jsem nadeklarovali dříve, aby přehrávala správné frekvence. Kvůli přehlednějšímu kódy bychom také měli být schopni napojit se přímo do třídy bez použití funkce, ale necháme to tak, kvůli použití jako příkladu.</p>

  <p>Kód nastavující signály by měl být přidán do funkce <code>main()</code> přímo za řádek <code>builder-&gt;get_widget("main_window", main_win);</code>:</p>
  <code mime="text/x-csrc">
Sound sound;
Gtk::Button* button;

builder-&gt;get_widget("button_E", button);
button-&gt;signal_clicked().connect (sigc::bind&lt;double, Sound*&gt;(sigc::ptr_fun(&amp;on_button_clicked),
                                              329.63, &amp;sound));
</code>
	<steps>
	<item>
	<p>Nejprve vytvoříme instanci naší pomocné třídy, kterou chceme nyní použít a deklarujeme proměnnou pro tlačítko, které na ni chceme napojit.</p>
	</item>
	<item>
	<p>Následně obdržíme objekt tlačítka od uživatelského rozhraní, které bylo vytvořeno ze souboru s uživatelským rozhraním. Pamatujte, že <em>button_E</em> je název, který jsme dali prvnímu tlačítku.</p>
	</item>
	<item>
	<p>Nakonec napojíme signál <em>clicked</em>. To není úplně přímočaré, protože je to uděláno typově plně bezpečným způsobem a prakticky chceme obsluze signálu předat frekvenci a naši pomocnou třídu. <code>sigc::ptr_fun(&amp;on_button_clicked)</code> vytvoří <em>slot</em> pro metodu <code>on_button_clicked</code>, kterou jsme nadefinovali dříve. Pomocí <code>sigc::bind</code> jsme schopni předat dodatečné argumenty do slotu a v tomto případě tak předáme frekvenci (jako <code>double</code>) a naši pomocnou třídu.</p>
	</item>
  </steps>
  <p>Teď, když máte nastavené tlačítko <em>E</em>, musíme propojit ostatní tlačítka s jejich správnými frekvencemi: 440 pro A, 587.33 pro D, 783.99 pro G, 987.77 pro H (v anglické notaci B) a 1318.5 pro horní E. To se provede stejným způsobem, akorát se obsluze předá jiná frekvence.</p>
</section>

<section id="run">
  <title>Sestavení a spuštění aplikace</title>
  <p>Celý kód je nyní připraven ke spuště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.cc">ukázkovým kódem</link>.</p>
</section>

<section id="further">
  <title>Náměty ke čtení</title>
  <p>Řada věcí předvedených výše je podrobně vysvětlena v <link href="http://library.gnome.org/devel/gtkmm-tutorial/stable/">Kniha o GTKmm</link>, která se zabývá více i klíčovými koncepty pro plnohodnotné použití GTKmm. Mohla by vás zajímat i <link href="http://library.gnome.org/devel/gstreamermm/">referenční dokumentace GStreamermm</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>