[완료]그놈 애플릿 Debug는 어떻게 ?

atie의 이미지

주말에 취미 생활(?) 컴파일을 했었습니다. 하나는 Nokia의 꽃 브라우저 였고, 또 다른 하나는 istream이라는 그놈 애플릿 이었습니다. 전자는 "web-core를 gtk로 포팅을 하는구나... 테스트 브라우저... 여전히 허접하네." 하는 기술적 내용이야 상당하더라도 사용자의 관점에서는 별 감흥이 없었고, 후자의 istream은 패널에 등록하고 한번 클릭에 라디오 방송을 들을 수 있으니 꽤 유용하구나 하는 생각을 해서 제 패널에도 등록을 해 놓았습니다.

그런데, 언제나 그렇듯이 꼭 노래 제목에서 한글이 깨지는 것은 여전하더군요.(테스트는 뮤클캐스트로...) 그래서, 잠깐 웹 검색을 해서

diff -urN istream-0.10/src/stream.c stream.c 
--- istream-0.10/src/stream.c   2007-04-07 17:39:09.000000000 -0500
+++ stream.c    2007-04-07 17:37:53.000000000 -0500
@@ -30,6 +30,19 @@
 
         g_strstrip(title);  
 
+               if (title != NULL && !g_utf8_validate (title, -1, NULL)) {
+                       const gchar *encoding;
+                       gchar *tmp;
+
+                       //need encoding = g_getenv ("GST_TAG_ENCODING")? Now, cp949
+                       //for testing
+                       encoding = "cp949";
+                       tmp = g_convert_with_fallback (title, -1, "UTF-8", encoding,
+                               "*", NULL, NULL, NULL);
+                       g_free (title);
+                       title = tmp;
+               }
+
         if (applet->title==NULL || strcmp (title, applet->title) != 0) {
           if (debug) printf ("new title (scroll)\n");
 
@@ -129,6 +142,19 @@
       if (gst_tag_list_get_string (list,tag, &title)) {
         g_strstrip(title);
 
+               if (title != NULL && !g_utf8_validate (title, -1, NULL)) {
+                       const gchar *encoding;
+                       gchar *tmp;
+
+                       //need encoding = g_getenv ("GST_TAG_ENCODING")? Now, cp949
+                       //for testing
+                       encoding = "cp949";
+                       tmp = g_convert_with_fallback (title, -1, "UTF-8", encoding,
+                               "*", NULL, NULL, NULL);
+                       g_free (title);
+                       title = tmp;
+               }
+
         if (applet->title==NULL || strcmp (title, applet->title) != 0) {
           if (debug) printf ("new title (no scroll)\n");

위와 같이 제목만이라도 한글이 나올까 싶은 테스트 코드를 만들어 보았습니다. 결과는 안되더군요. 그래서 이 애플릿을 디버깅할 필요가 생겼습니다.

웹 검색을 해서 그놈 개발자의 애플릿 디버깅 관련 글을 보기는 했는데... 어느 분이 저 예제로 명쾌하게 설명해 주실 수 있나요? 덧붙여 한글 제목이 올바르게 나오는 수정도 어느 분이 해주시면 좋겠고... 급한 것 아니니 "코드놀이" 겸 이 곳에 글을 써 놓고 오는 주말까지 답변을 기다려 보겠습니다.

그리고, 그놈에서 encoding 처리는 저 방식으로 하는 것이 맞나요? 궁금하더군요.

keizie의 이미지

제가 예전에 했을 때는, 일단 터미널에서 한 번 실행을 시키고 (libexec 밑에 있는 걸 그냥 실행하면 됐던 걸로 기억합니다만 정확한지는 모르겠습니다) 그 다음에 패널에 추가했습니다. 그러면 STDOUT 등이 터미널 쪽에 나오더라구요.

그리고는 최고의 디버깅 툴인 printf로.. (glib은 g_print..)

=3=33

ganadist의 이미지

panel-test-applets 를 이용해보세요.

----
데스크탑 프로그래머를 꿈꾸는 임베디드 삽질러

ganadist의 이미지

그리고 태그는 gstreamer에서 얻어오는 것 같네요. 먼저 gstreamer에서 제대로 얻어오는 지 확인 해봐야 할 것 같습니다.

환경변수에 다음 값을 설정해서 id3태그를 제대로 읽어오는 지 확인해보세요

$ export GST_DEBUG=id3demux:4

----
데스크탑 프로그래머를 꿈꾸는 임베디드 삽질러

bushi의 이미지

istream 수준에서 해결될 문제가 아닌 것 같습니다.
전에 rhythmbox 에서 같은 문제로 삽질을 했었는데,
gstreamer 저 깊숙한 곳에서 이미 코드가 깨져서 올라옵니다.

말하자면, istream 에서 볼 수 있는 코드는 utf8 코딩된 한글도 아니고 euckr 코딩된 한글도 아닙니다. 정체불명 국적불명 이해불가능 코드입니다.

LANG=ko_KR.euckr rhythmbox & g
하듯이
LANG=ko_KR.euckr /usr/libexec/istream &
하시고 패널에 iStream 을 추가하니 잘 뵈네요.
개인적으로... 이게 더 신기했었습니다.
gnome 의 기본정책은... 아마도... "system 의 LANG 이 뭐든간에 최종적으로 utf8 로 변환한 다음 display 에 뿌려주는 것" 으로 짐작됩니다.

euckr(또는 cp949) 코드를 utf8(system)->utf8(gnome) 변환했을 때 망가지는 이유는 gnome 또는 gstreamer 의 자가당착적 버그 같습니다. 열심히 하느라고 한 것 같기는 한데, 오바했다 싶어요. 결국 system locale 이 utf8 일 경우, utf8 이 아닌 코드는 전부 망가질 수 밖에 없을 거라 봅니다.
to_charset 과 from_charset 이 같으면 아예 건드리지 않으려니,
utf8_validate() 를 통과못한 코드를 그대로 display 시도할 경우에 발생하는 각종 문제들을 감당하기 어려워 억지로 utf8 로 꿰어 맞추는 거겠죠.

ganadist의 이미지

bushi wrote:

gnome 의 기본정책은... 아마도... "system 의 LANG 이 뭐든간에 최종적으로 utf8 로 변환한 다음 display 에 뿌려주는 것" 으로 짐작됩니다.

gtk/gnome 내부에서는 text를 전부 utf-8로 처리하도록 되어있습니다.

bushi wrote:

euckr(또는 cp949) 코드를 utf8(system)->utf8(gnome) 변환했을 때 망가지는 이유는 gnome 또는 gstreamer 의 자가당착적 버그 같습니다. 열심히 하느라고 한 것 같기는 한데, 오바했다 싶어요. 결국 system locale 이 utf8 일 경우, utf8 이 아닌 코드는 전부 망가질 수 밖에 없을 거라 봅니다.

정확히는 gstreamer에 포함된 id3tag 라이브러리가 id3태그에 정의된 인코딩(iso-8859-1, utf-8, utf-16le, utf-16be)으로만 처리하려고 해서 그렇습니다.

윈도에서 사용하는 id3태깅 프로그램들이 문자셋은 iso-8859-1로 설정을 하고 로컬 캐릭터셋으로 저장하는 만행을 저지르죠.

----
데스크탑 프로그래머를 꿈꾸는 임베디드 삽질러

atie의 이미지

뮤클캐스트의 곡 제목이 한글로 보이는 것은, (코드 수정할 필요도 없이 원래의 0.10 버전으로)
killall istream 한 후, 명령행에서 LANG=ko_KR.euckr /usr/libexec/istream & 한 후 화면 상에 뜬 대화창의 reload 버튼을 눌러 주면 그 후의 곡 제목들은 한글이 잘 보입니다. bushi님 이야기대로 입니다.

제가 테스트한 코드에서는 !g_utf8_validate 부분을 빼고, 항상 강제로 cp949 -> utf8을 유도하면 title 값이

title: ºò¸¶¸¶ - Ãູ
tmp: 쨘챵쨍쨋쨍쨋 - 횄횪쨘쨔
 
title: ¹éÁö¿µ - ³ª»Û »ç¶÷
tmp: 쨔챕횁철쩔쨉 - 쨀짧쨩횤 쨩챌쨋첨

이런 식으로 화면 상에 보여지게 됩니다. 터미널 화면 상에 보이는 것은 코드에 printf를 넣고 위와 같은 방법으로 istream을 재시작한 후에는 STDOUT 값을 볼 수 있었습니다. kz님 이야기대로 입니다.

결론은 넘어오는 gstream tag값과 g_convert_with_fallback() 내부를 보아야 할 듯 싶은데... 능력 밖이라 저는 미뤄놓겠습니다.

원 글을 쓰기 전에 kz님도 이전에 비슷한 것을 보았고, 그리고 gana님은 이미 gstream tag 쪽을 많이 본 것으로 알고 있으니 어느날 크리스마스 선물이 도착할 수도 있겠죠. :P 그리고, 대략 제가 사용해 본 플레이어 중에서 LANG=ko_KR.euckr을 주고서라도 스트림에서 가져오는 곡 제목이 제대로 보이는 플레이어는 리듬박스 하나였던 것 같습니다. 이제는 두 개가 된 셈인데, 무엇인가
"gstreamer 저 깊숙한 곳에서 이미 코드가 깨져서 올라옵니다."
이 것을 해결할 방법이 있으면 하는 생각을 갖게 하는군요.

그놈 애플릿 디버그에 관한 글은,
http://www.davyd.id.au/articles/debugging-gnome-applets.shtml
이 것을 찾아놓고 있었습니다.

답변 주신 세 분께 고맙습니다.
----
I paint objects as I think them, not as I see them.

----
I paint objects as I think them, not as I see them.
atie's minipage

ganadist의 이미지

그냥 아무생각없이 패치 만들어서 버그질라에 올렸습니다.

http://bugzilla.gnome.org/show_bug.cgi?id=428689

id3v1을 파싱할 때는 환경변수로 설정하는게 있는데 id3v2에선 그냥 날로파싱하네요..

고치는 김에 property로도 고칠 수 있도록 했습니다.

----
데스크탑 프로그래머를 꿈꾸는 임베디드 삽질러

atie의 이미지

:Happy!
----
I paint objects as I think them, not as I see them.

----
I paint objects as I think them, not as I see them.
atie's minipage

ganadist의 이미지

gstreamer 버그 담당자가 뻐팅기네요 -ㅅ-

한마디 적어주세요~

----
데스크탑 프로그래머를 꿈꾸는 임베디드 삽질러

atie의 이미지

patch가 적용이 안되서 trunk버전으로 패키지 빌드를 하려면 제가 시간이 좀 필요하겠습니다. -_- 테스트해서 이러이러니 이게 필요하다라고 예와 증명을 따라할 수 있게 하면 담당자도 수긍하겠지요.
----
I paint objects as I think them, not as I see them.

----
I paint objects as I think them, not as I see them.
atie's minipage

atie의 이미지

새로 리포트를 만들었습니다.
http://bugzilla.gnome.org/show_bug.cgi?id=428901
----
I paint objects as I think them, not as I see them.

----
I paint objects as I think them, not as I see them.
atie's minipage

ganadist의 이미지

모질라에는 문자셋이 기술되지 않은 기존의 미디어나 프로토콜의 문자셋을 짐작할 수 있는 라이브러리가 있습니다.

이넘을 glib으로 포팅해서 넣은 다음 쟤네덜을 다 고쳐버리고 싶네요.

주말마다 쌩노가다하면 언젠가는 들어갈지도.. (먼산)

일단은 첫걸음으로 kldp위키에 http://wiki.kldp.org/wiki.php/Ganadist/GCharDet 페이지를 만들었습니다.

과연 제대로 만들어져서 glib에 통합될 수 있을까요;;

----
데스크탑 프로그래머를 꿈꾸는 임베디드 삽질러

atie의 이미지

아래에 bushi님 쓰신대로 딱 그렇게 고쳐졌습니다.
----
I paint objects as I think them, not as I see them.

----
I paint objects as I think them, not as I see them.
atie's minipage

bushi의 이미지

더듬거리며 찾아봤습니다.
http://bugzilla.gnome.org/show_bug.cgi?id=428901
고생 많으셨습니다.
GST_ICY_TAG_ENCODING 를 사용하면 되는군요.

bushi의 이미지

gstreamer-plugins-good 0.10.6 릴리즈부터 적용되는군요.

OTL

bushi의 이미지

환경변수로 설정하는 것은 파일의 태그에나 먹힙니다.
나름대로 유행중인 인터넷 라디오 방송엔 소용없다니까요.

광고는 아니고... 예시로 http://mukul.inlive.co.kr/listen.pls

bushi의 이미지

두번씩이나 같은 삽질을 했다는 것이 기분나빠서 gstreamer 말고 다른 곳을 찔러봤습니다.

태그에 대한 간략한 설명
http://jicyshout.sourceforge.net/oreilly-article/java-streaming-mp3-pt2/java-streaming-mp3-pt2.html

날린 요청

GET / HTTP/1.0
Icy-MetaData:1

받은 ICY 헤더

ICY 200 OK
icy-notice1:<BR>This stream requires <a href="http://www.winamp.com/">Winamp</a><BR>
icy-notice2:SHOUTcast Distributed Network Audio Server/Linux v1.9.7<BR>
icy-name:Republic of Korea Top Radio. MUKULCAST.COM*KPOP
icy-genre:Republic of KoreaPOP
icy-url:http://mukulcast.com
content-type:audio/mpeg
icy-pub:1
icy-metaint:8192
icy-br:128

실제 받아본 ICY metadata (편의상 utf8 로 변환해서 적습니다. 본의아니게 또 광고)

StreamTitle='Cj^레이...멘트中 - 처음';StreamUrl='hTtP://mn.inlive.co.kr/?c=mukul.inlive.co.kr&p=80&ID=MUKUL';

charset encoding 에 대한 정보는 원래부터 어디에도 없었습니다.

gstreamer 는 도대체 무슨 이유때문에 꾸역거리며 억지로, 무조건 utf8 로 변환을 시도하는 건가요 ?

bushi의 이미지

잠이 싹 달아났습니다.
gstreamer icydemux 코드는
http://webcvs.freedesktop.org/gstreamer/gst-plugins-good/gst/icydemux/gsticydemux.c?revision=1.7&view=markup&pathrev=MAIN

관심이 집중되는 핵심 부분을 추리면

/* The following two charset mangling functions were copied from gnomevfssrc.
 * Preserve them under the unverified assumption that they do something vaguely
 * worthwhile.
 */
static char *
unicodify (const char *str, int len, ...)
{
  char *ret = NULL, *cset;
  va_list args;
  gsize bytes_read, bytes_written;
 
  if (g_utf8_validate (str, len, NULL))
    return g_strndup (str, len >= 0 ? len : strlen (str));
 
  va_start (args, len);
  while ((cset = va_arg (args, char *)) != NULL)
  {
    if (!strcmp (cset, "locale"))
      ret = g_locale_to_utf8 (str, len, &bytes_read, &bytes_written, NULL);
    else
      ret = g_convert (str, len, "UTF-8", cset,
          &bytes_read, &bytes_written, NULL);
    if (ret)
      break;
  }
  va_end (args);
 
  return ret;
}
 
static char *
gst_icydemux_unicodify (const char *str)
{
  return unicodify (str, -1, "locale", "ISO-8859-1", NULL);
}
 
static void
gst_icydemux_parse_and_send_tags (GstICYDemux * icydemux)
{
  GstTagList *tags = gst_tag_list_new ();
  const guint8 *data;
  int length, i;
  gchar *buffer;
  gchar **strings;
  gboolean found_tag = FALSE;
 
  length = gst_adapter_available (icydemux->meta_adapter);
 
  data = gst_adapter_peek (icydemux->meta_adapter, length);
 
  /* Now, copy this to a buffer where we can NULL-terminate it to make things
   * a bit easier, then do that parsing. */
  buffer = g_malloc (length + 1);
  memcpy (buffer, data, length);
  buffer[length] = 0;
 
  strings = g_strsplit (buffer, "';", 0);
 
  for (i = 0; strings[i]; i++) {
    if (!g_ascii_strncasecmp (strings[i], "StreamTitle=", 12)) {
      char *title = gst_icydemux_unicodify (strings[i] + 13);
 
      if (title && *title) {
        gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE,
            title, NULL);
        g_free (title);
        found_tag = TRUE;
      }
    } else if (!g_ascii_strncasecmp (strings[i], "StreamUrl=", 10)) {
      char *url = gst_icydemux_unicodify (strings[i] + 11);
 
      if (url) {
        /* 
           gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_URL, 
           url, NULL); 
           found_tag = TRUE;
         */
        g_free (url);
      }
    }
  }
 
  g_strfreev (strings);
  g_free (buffer);
  gst_adapter_clear (icydemux->meta_adapter);
 
  if (found_tag) {
    if (icydemux->srcpad) {
      gst_icydemux_send_tag_event (icydemux, tags);
    } else {
      if (!icydemux->cached_tags) {
        icydemux->cached_tags = gst_tag_list_new ();
      }
 
      gst_tag_list_insert (icydemux->cached_tags, tags,
          GST_TAG_MERGE_REPLACE_ALL);
    }
  }
}

말인즉슨 StreamTitle=... 을 받아서 $LANG->utf8 변환이 실패하면 iso8859_1->utf8 로 끝장을 보고자 했음이겠고.
gst_icydemux_unicodify() 를 적당히 변조하면 GST_ICY_CHARSET 따위의 환경변수를 집어넣는 것이 가능하다는 소리렸다.

(gana 군. "locale" 보다 우선순위가 높도록 그 앞으로 부탁함세.)

ICY 의 StreamTitle 에 대한 charset encoding 문제는 icecast 메일링리스트에서 4년전에 잠깐 반짝하고는 별 변화가 보이지 않고.
icecast 서버쪽 소스를 보니 로그를 남기기 위해 id3 tag 정보를 참조해서 encoding 변환을 하는 부분이 있긴 합니다.

atie의 이미지

당연한 것이겠지만, 위의 소스에서 iso8859_1을 cp949로 바꿔서 만든 플러그인 패키지와 함께로는 istream에 LANG 환경 변수를 주는 것 없이 한글 제목이 잘 보이는군요.

링크해주신 shoutcast 스펙의 스트림에서의 charset은 조건부이니 라디오 방송에서 그 정보를 전달하지 않는 것에 하자가 있다고 할 수는 없겠고, 결국은 gstreamer를 쓰는 각각의 플레이어를 수정하지 않으려면 gstreamer에서 단일한 그리고 똑똑한 편법을 하나 넣어야 한다는 이야기인데 gstreamer 기존의 환경 변수 값을 하나 골라 쓸 것인지 gana님의 패치처럼 속성값을 추가하는 방식인지는 선택이 어렵겠습니다. 지금 예는 shoutcast에 맞는 charset 속성이지만 또 다른 스펙에 맞게도 속성을 추가해야 할지도 모른다는 것으로 이해가 되서요.
----
I paint objects as I think them, not as I see them.

----
I paint objects as I think them, not as I see them.
atie's minipage

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.