<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" type="guide" style="task" id="guitar-tuner.js" xml:lang="ko">
  <info>
  <title type="text">Guitar tuner (JavaScript)</title>
    <link type="guide" xref="js#examples"/>
    <revision version="0.1" date="2012-03-09" status="stub"/>

    <credit type="author copyright">
      <name>Susanna Huhtanen</name>
      <email its:translate="no">ihmis.suski@gmail.com</email>
      <years>2012</years>
    </credit>

    <desc>그놈용 단순 기타 조율 프로그램을 만들 때 GTK+와 지스트리머를 사용합니다.</desc>
  
    <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-2019.</mal:years>
    </mal:credit>
  </info>

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

    <synopsis>
      <p>이 따라하기 지침에서는 JavaScript와 GTK+, 지스트리머로, 간단한 기타 조율 프로그램을 구성해보겠습니다. 여러분이 직접 코드 예제를 작성하고 실행해보려면, 코드를 작성할 편집기, 터미널, 그놈 3 이상을 컴퓨터에 설치해야합니다.</p>
   <list>
      <item><p><link xref="#gstreamer">지스트리머 파이프라인</link></p></item>
      <item><p><link xref="#script">실행 프로그램 스크립트</link></p></item>
      <item><p><link xref="#imports">가져올 라이브러리</link></p></item>
      <item><p><link xref="#mainwindow">프로그램 메인 창 만들기</link></p></item>
      <item><p><link xref="#buttons">조율 단추</link></p></item>
      <item><p><link xref="#playSound">지스트리머로 소리 만들기</link></p></item>
      <item><p><link xref="#connecting">소리 재생 단추에 연결</link></p></item>
      <item><p><link xref="#guitarjs">전체 프로그램</link></p></item>
      <item><p><link xref="#terminal">터미널에서 프로그램 실행</link></p></item>
    </list>
  </synopsis>
  <p>지침서를 읽고 나면 이 내용을 화면에서 볼 수 있어야합니다:</p>
  <media type="image" mime="image/png" src="media/guitar-tuner.png"/>
  <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="script">
    <title>실행 프로그램 스크립트</title>
    <code mime="application/javascript" style="numbered">
  #!/usr/bin/gjs</code>
    <p>이 줄은 스크립트 실행 방법을 알려줍니다. 이 부분은 코드의 처음 부분에 들어가야하며, 스크립트 파일을 실행할 수 있어야합니다. 실행 권한을 가져오려면 터미널을 열고 올바른 폴더에서 chmod +x scriptname 명령을 실행하십시오. 또는 그래픽 파일 관리자를 활용할 수 있습니다. 코드가 있는 적절한 폴더에 들어가서 코드를 작성한 파일에 마우스 커서를 두고 오른쪽 단추를 누른 다음, 속성, 권한 탭을 선택하시고 파일을 프로그램처럼 실행하도록 상자에 표시하십시오.</p>
  </section>
  <section id="imports">
    <title>가져올 라이브러리</title>
    <code mime="application/javascript" style="numbered">
var Gtk = imports.gi.Gtk;
var Gst = imports.gi.Gst;

const Mainloop = imports.mainloop;</code>
    <p>프로그램을 동작하게 하려면 GObject Introspection 라이브러리를 임포팅해야합니다. UI를 동작하게 하려면 Gtk를, 지스트리머를 동작하게 하려면 Gst를 임포팅해야합니다. 코드 시작 부분에서 임포팅해서 어디서든 활용할 수 있게 합니다. 또한 조율음의 재생 시간 제한을 처리할 Mainloop 생성자를 임포팅하겠습니다.</p>
    </section>
  <section id="mainwindow">
    <title>프로그램 메인 창 만들기</title>
    <code mime="application/javascript" style="numbered">
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();</code>
    <p>Gtk와 Gst를 임포팅 하는 것만으로는 충분치 않기에 동작하려면 초기화해야합니다. Gtk와 Gst를 띄우고 나면 프로그램 창을 만들어야합니다. 그 다음 이 창에서 소리를 낼 모든 단추를 만들어 두겠습니다. 창을 띄우려면, 화면에 나타내라고 직접 알려야 하며, Gtk.main()으로 코드를 실행해야합니다.</p>
  </section>
  <section id="buttons">
   <title>조율 단추</title>
   <code mime="application/javascript" style="numbered">
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();</code>
   <p>Gtk.Window는 단일 위젯을 둘 수 있기 때문에 단추를 안에 다 넣을 수 있으려면 무언가를 만들어야합니다. 이 예제에서 Buttonbox를 사용하겠습니다. Buttonbox를 만들고 나면, 각 단추를 만들어 필요한 레이블을 붙이겠습니다. 이 단추를 만들고 나면 Buttonbox에 넣고 Buttonbox를 Gtk.Window에 넣어 Buttonbox에 넣은 모든 단추가 나타나야합니다.</p>
   <p>이 단계가 끝나면 단추 6개가 뜨는 창이 화면에 나타나야합니다. 바로 지금은 단추가 아무 동작을 하지 않으며 이 문제는 나중에 처리하겠습니다. 단추 시그널을 어딘가에 연결할 수 있기 전에는 무언가를 먼저 코드로 작성해야합니다.</p>
  </section>
  <section id="playSound">
   <title>지스트리머로 소리 만들기</title>
   <code mime="application/javascript" style="numbered">
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;
  });
}</code>
   <p>우리가 먼저 해야 할 일은 단추를 눌렀을 때 어떤 음을 낼지를 결정하는 일입니다. 주파수 목록이 이런 역할을 합니다. 그 다음 실제로 playSound 함수로 소리를 냅니다. playSound 함수로 소리를 낼 때 주파수를 입력값(바로 위에서 정의한 frequencies 변수 값)으로 넣습니다. 우선 파이프라인, source, sink를 만들어야합니다. source에 주파수를 설정하겠습니다. 파이프라인에 source와 sink를 추가하고, 재생 상태를 유지하라고 지시하겠습니다. 마지막으로 const Mainloop를 활용하여 파이프라인 동작을 500ms 후에 멈추게 하겠습니다.</p>
   <p>이제 단추를 눌렀을 때 음을 재생하는 메서드를 작성했습니다. 다음 단추를 누르면 단추에서 올바른 음을 재생하도록 연결하겠습니다.</p>
  </section>
  <section id="connecting">
   <title>소리 재생 단추에 연결</title>
   <code mime="application/javascript" style="numbered">
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);
});</code>
   <p> 올바른 음 값을 주어 playSound를 호출하는 연결 단추 메서드는 단추 위젯의 연결 메서드를 활용합니다. 따라서 연결한 단추를 선택하고 <code>E.connect("clicked", function(){playSound(frequencies.E);});</code> 를 입력하십시오.  <code>connect</code> 함수는 E를 눌렀을 때 일어날 일을 지시합니다.  <code>clicked</code>는 E에서 나타나는 시그널 형식을,  <code>function(){};</code> 은 단추와 관련있는 올바른 음을 재생할 playSound 입니다.</p>
  </section>
  <section id="guitarjs">
    <title>전체 프로그램</title>
    <p>따라서 이 부분은 모든 부분을 합친 것과 같은 부분입니다. 코드를 실행하면 (음을 제대로 보정한 스피커를 연결했을 경우) 여러분 스스로가 기타를 조율할 수 있어야합니다.</p>
      <code mime="application/javascript" style="numbered">
#!/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();</code>
  </section>

<section id="terminal">
  <title>터미널에서 프로그램 실행</title>
  <p>프로그램을 실행하려면 터미널을 열고, 프로그램을 저장한 폴더로 들어간 후 실행하십시오</p> <screen> <output style="prompt">$ </output><input> GJS_PATH=`pwd` gjs guitarTuner.js</input> </screen>
    </section>

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


</page>
