<?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.py" xml:lang="ko">

  <info>
    <title type="text">기타 조율기(Python)</title>
    <link type="guide" xref="py#examples"/>

    <desc>GTK+와 지스트리머를 간단한 그놈용 기타 조율기 프로그램을 만들어보겠습니다. 인터페이스 디자이너 사용법을 나타냅니다.</desc>

    <revision pkgversion="0.1" version="0.1" date="2010-12-02" status="stub"/>
    <credit type="author">
      <name>그놈 문서 프로젝트</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>
    <credit type="editor">
      <name>Marta Maria Casetti</name>
      <email its:translate="no">mmcasetti@gmail.com</email>
      <years>2013</years>
    </credit>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>조성호</mal:name>
      <mal:email>shcho@gnome.org</mal:email>
      <mal:years>2017, 2018</mal:years>
    </mal:credit>
  </info>

<title>기타 조율기</title>

<synopsis>
  <p>이 지침서에서, 기타 조율에 사용할 수 있는 음색을 재생하는 프로그램을 만들겠습니다. 다음 내용을 배워나갑니다:</p>
  <list>
    <item><p>안주타에서 기본 프로젝트 설정</p></item>
    <item><p>안주타 사용자 인터페이스 디자이너에서 간단한 GUI 만들기</p></item>
    <item><p>지스트리머를 사용하여 소리 재생하기</p></item>
  </list>
  <p>이 지침을 따라갈 수 있으려면 다음이 필요합니다:</p>
  <list>
    <item><p><link xref="getting-ready">안주타 IDE</link> 설치 사본</p></item>
    <item><p>파이썬 프로그래밍 언어 기본 지식</p></item>
  </list>
</synopsis>

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

<section id="anjuta">
  <title>안주타에서 프로젝트 만들기</title>
  <p>코딩을 시작하기 전에 안주타에서 새 프로젝트를 설정해야합니다. 이 프로그램은 빌드에 필요한 모든 파일을 만들고 그 다음 코드를 실행합니다. 또한 이 모든 상태를 유지 관리하는데 쓸만합니다.</p>
  <steps>
    <item>
    <p>안주타를 시작하고 <guiseq><gui>파일</gui><gui>새로 만들기</gui><gui>프로젝트</gui></guiseq> 를 눌러 프로젝트 마법사를 여십시오.</p>
    </item>
    <item>
    <p><gui>파이썬</gui> 탭에서 <gui>PyGTK (automake)</gui>를 선택하고 <gui>계속</gui>을 누르신 다음 몇가지 페이지에서 세부 내용을 채워나가십시오. 프로젝트 이름과 디렉터리 이름을 <file>guitar-tuner</file>로 정하십시오.</p>
   	</item>
    <item>
    <p><gui>적용</gui>을 누르면 프로젝트를 만들어줍니다. <gui>프로젝트</gui>나 <gui>파일</gui>탭에서 <file>src/guitar_tuner.py</file> 파일을 여십시오. 다음 줄로 시작하는 코드가 나타납니다:</p>
    <code mime="test/x-python">
from gi.repository import Gtk, GdkPixbuf, Gdk
import os, sys</code>
    </item>
  </steps>
</section>

<section id="run">
  <title>첫 코드 실행</title>
  <p>이 파일의 대부분의 코드는 코드 서식입니다. 사용자 인터페이스 설명 파일에서 (빈)창을 불러오고 보여줍니다. 더 자세한 내용은 아래에 있습니다. 기본을 알고 계신다면 이 부분은 건너 뛰십시오:</p>

  <list>
  <item>
    <p>상단의 <code>import</code> 줄은 파이썬에 사용자 인터페이스와 시스템 라이브러리가 필요함을 알리는 내용이 들어갑니다.</p>
   </item>
   <item>
    <p>프로그램의 주 클래스가 될 클래스를 선언합니다. <code>__init__</code> 메서드에서는 GtkBuilder 파일(<file>src/guitar-tuner.ui</file>)에서 메인 창을 불러오고 시그널을 연결합니다.</p>
    <p>시그널을 연결하는건 단추를 누르거나 어떤 일이 일어나면 동작이 일어나게 하는 방편입니다. 여기서 <code>destroy</code> 메서드는 창을 닫을 때 호출(하고 프로그램을 끝내기)합니다.</p>
   </item>
   <item>
    <p><code>main</code>은 파이썬 프로그램을 시작할 때 기본으로 시작합니다. 메인 클래스의 인스턴스를 만들고 창을 띄우는 메인 루프를 시작합니다.</p>
   </item>
  </list>

  <p>이 코드를 사용할 준비가 되었으니 <guiseq><gui>실행</gui><gui>실행</gui></guiseq>을 눌러 프로그램을 실행할 수 있습니다.</p>
</section>

<section id="ui">
  <title>사용자 인터페이스 만들기</title>
  <p>사용자 인터페이스(UI) 설명은 GtkBuilder 파일에 있습니다. 사용자 인터페이스를 편집하려면 <file>src/guitar_tuner.ui</file> 파일을 여십시오. 이 파일을 열면 인터페이스 디자이너로 이동합니다. 디자인 창은 가운데에 있고, 위젯과 위젯 속성은 오른편에, 쓸 수 있는 위젯의 팔레트는 왼편에 있습니다.</p>
  <p>GTK+의 모든 UI 배치는 상자와 표로 구성합니다. 가로 방향 <gui>GtkButtonBox</gui>를 여기서 사용하여 각 기타 줄에 해당하는 여섯 개의 <gui>GtkButtons</gui> 단추를 넣어보겠습니다.</p>

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

  <steps>
   <item>
   <p>우측 <gui>팔레트</gui>의 <gui>컨테이너</gui> 섹션에서 <gui>GtkButtonBox</gui> 를 선택하여 창에 가져다 높으십시오. <gui>속성</gui> 창에서 구성 요소 수를 6(기타 줄 6개)으로 설정하고, 방향은 세로(vertical)로 설정하십시오.</p>
   </item>
   <item>
    <p>이제 팔레트에서 <gui>GtkButton</gui> 를 선택하고 상자의 처음 부분에 가져다 놓으십시오.</p>
   </item>
   <item>
    <p>단추를 선택한 상태에서 <gui>위젯</gui> 탭의 <gui>레이블</gui> 속성을 <gui>E</gui>로 바꾸십시오. 기타의 낮은 E 줄을 의미합니다.</p>
    </item>
    <item>
     <p><gui>시그널</gui> 탭(<gui>위젯</gui> 탭에 있음)으로 옮겨가서 단추의 <code>clicked</code> 시그널을 찾아보십시오. 이 시그널을 사용자가 단추를 눌렀을 때 호출할 시그널 핸들러에 연결할 수 있습니다. 이렇게 하려면, 시그널을 누르고 <gui>핸들러</gui> 칸에 <code>on_button_clicked</code>를 입력하신 다음 <key>Return</key>키를 누르십시오.</p>
    </item>
    <item>
    <p>다른 단추에 대해서도 그 다음 줄 이름 <em>A</em>, <em>D</em>, <em>G</em>, <em>B</em>, <em>e</em>를 추가하여 위 단계를 반복하십시오.</p>
    </item>
    <item>
    <p>UI 디자인을 저장(<guiseq><gui>파일</gui><gui>저장</gui></guiseq> 누름)하시고 열어둔 상태로 두십시오.</p>
    </item>
  </steps>
</section>

<section id="signal">
  <title>시그널 핸들러 작성</title>
  <p>UI 디자이너에서 모든 단추를 누르면 동일한 <gui>on_button_clicked</gui> 함수를 호출하도록 할 수 있습니다. 이 함수를 소스 파일에 추가해야합니다.</p>
<p>진행하려면 사용자 인터페이스 파일을 열어둔 상태에서 <file>guitar_tuner.py</file> 파일을 여십시오. 앞에서 시그널 이름을 설정한 <gui>시그널</gui> 탭으로 가십시오. 이제 <gui>clicked</gui> 시그널 줄로 가서 소스 파일의 클래스에 이 시그널을 끌어다 넣으십시오. 소스 파일에 다음 코드가 들어갑니다:</p>
<code mime="text/x-csrc">
def on_button_clicked (self, button):
</code>

  <p>이 시그널 핸들러에는 파이썬 클래스 포인터와 함수를 호출하는 <code>Gtk.Button</code> 인자가 있습니다.</p>
  <p>이제 소리를 내는 코드를 작성하는 동안 시그널 핸들러를 비워두겠습니다.</p>
</section>

<section id="gstreamer">
  <title>지스트리머 파이프라인</title>
  <p>지스트리머는 그놈 멀티미디어 프레임워크입니다. 동영상 오디오 웹캠 스트림 같은걸 재생, 녹음/녹화, 처리할 때 지스트리머를 사용할 수 있습니다. 여기서는 단일 주파수 음색을 만들 때 사용하겠습니다.</p>
  <p>개념적으로 지스트리머 동작은 다음과 같습니다. (우선) <em>source</em>에서  <em>sink</em>(출력)으로 내보낼 수많은 처리 요소가 들어간 <em>파이프라인</em>을 만듭니다. source는 그림 파일, 동영상, 음악 파일일 수 있으며, 출력 대상은 위젯 또는 사운드 카드가 될 수 있습니다.</p>
  <p>source와 sink 사이에서 다양한 필터와 변환 프로그램을 적용하여 효과를 처리하거나, 형식을 변환하는 등을 할 수 있습니다. 각 파이프라인 구성 요소에는 동작을 바꿀 수 있는 속성이 있습니다.</p>
  <media type="image" mime="image/png" src="media/guitar-tuner-pipeline.png">
    <p>지스트리머 파이프라인 예제입니다.</p>
  </media>
</section>

<section id="pipeline">
  <title>파이프라인 구성</title>
  <p>여기 단순 예제에서는 <code>audiotestsrc</code> 라는 음 재생기 소스를 사용하고 기본 시스템 사운드 장치 <code>autoaudiosink</code>로 출력을 내보내겠습니다. 우리는 여기서 음 재생기 주파수를 설정해야합니다.  <code>audiotestsrc</code>의 <code>freq</code> 속성을 사용하면 됩니다.</p>

  <p><file>guitar_tuner.py</file> 파일에 import 줄을 다음과 같이 바꾸십시오:</p>
  <code mime="test/x-python">from gi.repository import Gtk, Gst, GObject </code>
  <p><code>Gst</code>에는 지스트리머 라이브러리가 들어있습니다. <code>app = GUI()</code> 줄 위에 추가한 이 호출과 <code>main()</code> 메서드 안의 코드로 지스트리머 속성을 초기화해야합니다:</p>
  <code mime="test/x-python">Gst.init_check(sys.argv)</code>
  <p>그 다음 <file>guitar_tuner.py</file>의 클래스 어딘가에 다음 함수 코드를 복사하십시오:</p>
  <code mime="test/x-python">
def play_sound(self, frequency):
	pipeline = Gst.Pipeline(name='note')
	source = Gst.ElementFactory.make('audiotestsrc', 'src')
	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)

	GObject.timeout_add(self.LENGTH, self.pipeline_stop, pipeline)</code>
  <steps>
    <item>
    <p>처음 세 줄에서는 source와 sink 지스트리머 구성 요소, 파이프라인 구성 요소(source와 sink의 컨테이너로 활용)를 만듭니다. 파이프라인 이름은 "note"라고 지어둡니다. source는 "source"로 이름 붙이고 <code>audiotestsrc</code>로 설정합니다. sink는 "output"으로 이름 붙이고 <code>autoaudiosink</code> sink로 설정합니다(기본은 사운드 카드 출력).</p>
    </item>
    <item>
    <p><code>source.set_property</code> 호출에서는 source 구성 요소의 <code>freq</code> 속성에 <code>play_sound</code> 함수의 인자로 전달한 <code>frequency</code> 값을 설정합니다. 이 값은 헤르쯔 단위의 음 주파수입니다. 쓸만한 주파수는 나중에 정의하겠습니다.</p>
    </item>
    <item>
    <p>다음 두 줄에서는 source 구성 요소와 sink 구성 요소를 파이프라인에 두는 <code>pipeline.add</code> 함수를 호출합니다. 파이프라인에는 여러 지스트리머 구성 요소를 넣을 수 있습니다. 보통 <code>add</code> 메서드를 반복적으로 호출하여 파이프라인에 원하는 만큼 구성 요소를 넣을 수 있습니다.</p>
    </item>
    <item>
    <p>다음 <code>pipeline.set_state</code> 함수는 파이프라인 상태를 재생 상태(<code>Gst.State.PLAYING</code>)로 설정하여 음 재생을 시작할 때 사용합니다.</p>
    </item>
  </steps>

</section>

<section id="playback">
  <title>재생 정지</title>
  <p>음을 짜증나게 무한정 재생하고 싶진 않기에 <code>play_sound</code> 함수에서 마지막으로 할 일은 <code>GObject.timeout_add</code> 함수를 호출하는 일입니다. 이 함수는 음 재생을 멈출 제한 시간을 설정합니다. <code>pipeline_stop</code> 함수를 호출하기 전 <code>LENGTH</code> 밀리초동안 기다리고 <code>pipeline_stop</code> 함수에서 <code>False</code>를 반환하기 전까지 계속 호출합니다.</p>
  <p>이제 <code>GObject.timeout_add</code> 함수에서 호출할  <code>pipeline_stop</code> 함수를 작성하겠습니다. 다음 코드를 <code>play_sound</code> 함수 <em>상단</em>에 넣으십시오:</p>
  <code mime="test/x-python">
def pipeline_stop(self, pipeline):
	pipeline.set_state(Gst.State.NULL)
	return False
</code>
  <p>클래스 안에 <code>LENGTH</code> 상수를 정의해야 하므로, 메인 클래스 시작 부분에 다음 코드를 추가하겠습니다:</p>
  <code mime="test/x-python">
LENGTH = 500
</code>
  <p><code>pipeline.set_state</code> 함수를 호출하면 파이프라인 재생을 멈춥니다.</p>
</section>

<section id="tones">
  <title>음색 정의</title>
  <p>사용자가 단추를 누르면 올바른 음을 나게 해보겠습니다. 우선 (메인 클래스 시작 부분) 딕셔너리에 정의한 기타 각 여섯줄의 주파수를 알아내어 기타 줄에 이름에 쉽게 대응할 수 있어야합니다:</p>
  <code mime="test/x-python">
# Frequencies of the strings
frequencies = {
	'E': 329.63,
	'A': 440,
	'D': 587.33,
	'G': 783.99,
	'B': 987.77,
	'e': 1318.5
}
</code>
  <p>이제 이전에 정의한 시그널 핸들러 <code>on_button_clicked</code> 에 내용을 추가할 차례입니다. 모든 단추에 각기 다른 시그널 핸들러를 연결할 수 있지만, 같은 코드를 여러번 반복할 수 있습니다. 대신, 어떤 단추를 눌렀는지 확인할 용도로 단추 레이블을 활용할 수 있습니다:</p>
  <code mime="test/x-python">
def on_button_clicked(self, button):
	label = button.get_child()
	text = label.get_label()

	self.play_sound (self.frequencies[text])
</code>
  <p>누른 단추는 <code>on_button_clicked</code> 함수에 인자(<code>button</code>)로 전달합니다. <code>button.get_child</code> 함수로 단추 레이블 객체를 가져올 수 있고, 해당 레이블 객체에서 <code>label.get_label</code>을 사용하여 텍스트를 가져올 수 있습니다.</p>
  <p>레이블 텍스트는 딕셔너리의 키로 사용하며 음에 해당하는 적당한 주파수로 <code>play_sound</code>를 호출합니다. 이 코드로 음을 재생합니다. 이렇게 해서 동작하는 기타 조율 프로그램을 만듭니다!</p>
</section>

<section id="run2">
  <title>프로그램 실행</title>
  <p>모든 코드를 실행할 준비를 마쳤습니다. <guiseq><gui>실행</gui><gui>실행</gui></guiseq>을 눌러 프로그램을 시작하시고 즐기세요!</p>
</section>

<section id="impl">
 <title>참조 구현체</title>
 <p>지침서를 따라하는 실행하는 과정에 문제가 있다면, <link href="guitar-tuner/guitar-tuner.py">참조 코드</link>와 여러분의 코드를 비교해보십시오.</p>
</section>

<section id="next">
  <title>다음 단계</title>
  <p>여기 간단한 시험 프로그램에 여러분이 추가로 넣을 수 있는 몇가지 아이디어가 있습니다:</p>
  <list>
   <item>
   <p>프로그램에 음 재생 자동 주기 기능 넣기.</p>
   </item>
   <item>
   <p>프로그램에 실제 기타 현을 퉁겼을 때의 음을 녹음하여 재생하기.</p>
   <p>이 동작을 구현하려면 음악 파일을 불러와서 재생할 수 있도록 지스트리머 파이프라인을 좀 더 복잡하게 설정해야합니다. 녹음 음원의 파일 형식에 따른<link href="http://gstreamer.freedesktop.org/documentation/plugins.html">decoder와 demuxer</link> 지스트리머 구성 요소를 선택해야 할 수도 있습니다. 예를 들자면 MP3는 Ogg Vorbis 파일과는 다른 구성 요소를 활용합니다.</p>
   <p>좀 더 복잡한 식으로 구성 요소를 연결해야 할 수도 있습니다. <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-intro-basics-pads.html">pads</link>와 같이 우리가 지침서에서 다룰 수 없는 <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-intro-basics.html">지스트리머 개념</link>이 들어갈 수도 있습니다. 쓸만한 <cmd>gst-inspect</cmd>  명령을 찾아볼 수도 있습니다.</p>
   </item>
   <item>
   <p>사용자 연주 음을 자동으로 분석.</p>
   <p>마이크를 연결하고 <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-autoaudiosrc.html">input source</link>로 음을 녹음할 수 있습니다. 아마도 <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-plugin-spectrum.html">스펙트럼 분석</link> 같은 것으로 어떤 음을 재생했는지 알 수 있겠죠?</p>
   </item>
  </list>
</section>

</page>
