Fork me on GitHub

2011/04/18


このエントリーをはてなブックマークに追加
MacにはGrowlがあり、WindowsにはGrowl For Windowsがあります。LinuxにもNotify-OSDがあるじゃないかという人もいますが、Linuxユーザは皆こう思ってる。「これGrowlじゃないもん!」
mumblesというpython+DBusで書かれたGrowl Systemもありましたが、どうやらプロジェクトが消え去った様子。

これはまずい。

と、僕は「Growl For Linux」を作り始める事を決めた

C言語でGTKを使ったGUI。プロトコルは今後、MacのGrowl 1.3でもサポートされる予定であるGNTP(Growl Network Transfer Protocol)を使う事にした。
本来ならば今日あたりにバージョン0.1あたりをリリースする予定だったんだけど、色々と立て込んでいて実はまだ出来てない。でもGNTPを受信して、Growlポップアップが出て、ディスプレイが数種類動く所まではこぎつけた。
今のところ
display1
こんなのや
display2
こんなのや
display3
こんなのが動きます。「キャプチャが思いっきりWindowsじゃねぇか!」と思われるかもしれまんが、ちゃんとLinuxで動作確認してます。
GNTPなので通常のGrowl送信ツールではなくGNTPをサポートした物が必要です。
などなど、この辺みてもらえれば色々あります。
残課題としては
  • 通知音再生
  • ディスプレイの充実/設定変更
  • subscriberアプリケーションの作成
などなどあります。一応、MD5/SHA1/SHA256のパスワードハッシュと、AES/DES/3DESの暗号通信をサポートしてます。
まだ始まったばかりのプロジェクトなので色々と問題がありますが、ぜひpatch書いて送って下さい!
いい物出来たら、きっと世界中から使って貰えます。君も一緒に開発やらないか?ウホッ
Posted at 01:55 in ソフトウェア
Tagged as: C, growl, gtk, linux
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip

2011/01/22


このエントリーをはてなブックマークに追加
go-gtk meets webkit!先日書いたのですが、ようやく形になってきたのでご報告。
Go言語でGTKを扱えるライブラリ、go-gtkのWidget上にwebkitブラウザをembed出来るライブラリを書きました。
mattn/go-webkit - GitHub

Go bindings for WebKit

https://github.com/mattn/go-webkit/
使い方もgo-gtkのWidgetと同じです。
簡単なサンプルだとこう書けます。
package main

import "os"
import "gtk"
import "webkit"

func main() {
    gtk.Init(nil)
    window := gtk.Window(gtk.GTK_WINDOW_TOPLEVEL)
    window.SetTitle("webkit")
    window.Connect("destroy", gtk.MainQuit, nil)

    swin := gtk.ScrolledWindow(nil, nil)
    swin.SetPolicy(gtk.GTK_POLICY_AUTOMATIC, gtk.GTK_POLICY_AUTOMATIC)
    swin.SetShadowType(gtk.GTK_SHADOW_IN)

    webview := webkit.WebView()
    webview.Connect("load-committed", func() {
        entry.SetText(webview.GetUri())
    }, nil)
    swin.Add(webview)

    window.Add(swin)
    window.SetSizeRequest(600, 600)
    window.ShowAll()

    proxy := os.Getenv("HTTP_PROXY")
    if len(proxy) > 0 {
        soup_uri := webkit.SoupUri(proxy)
        webkit.GetDefaultSession().Set("proxy-uri", soup_uri)
        soup_uri.Free()
    }
    webview.LoadUri("http://mattn.kaoriya.net/")

    gtk.Main()
}
簡単ですね!
go言語はWebサーバが簡単に書けるライブラリがたくさんあります。web.gotwisterを使えばfotofloみたいなサイトも簡単に書けます。これ、コンパイルされた実行モジュールで動いてるんですよ。かっこいいすよね。
garyburd/fotoflo - GitHub

This project is the source for fotoflo.info

https://github.com/garyburd/fotoflo
こういったWebサーバと埋め込みブラウザを使った1つのアプリケーションを提供出来る様になるって事です。面白いですね。
ぜひ楽しいアプリケーションを作ってみて下さい。
Posted at 00:57 in ソフトウェア::lang::go
Tagged as: go-gtk, golang, gtk, webkit
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip

2009/12/31


このエントリーをはてなブックマークに追加
最近、GoのGTKバインディングを作ってるのだけど、先日ようやく簡易twitterクライアントを作れるまでに至ったのだが、そのtwitterクライアントの「タイムライン更新」ボタンを押した時に画面をブロックさせずに画面を更新する方法を考えてた。
Perl-GTKならばCoroを使ってこうするだろうか。
use strict;
use warnings;
use Gtk2 '-init', '-threads-init';
use AnyEvent;
use Coro;
use Coro::Timer;

my $window = Gtk2::Window->new('toplevel');
$window->signal_connect(
    destroy => sub {
        exit;
    }
);
my $vbox = Gtk2::VBox->new;

my $button = Gtk2::Button->new('click me');
$button->signal_connect(
    clicked => sub {
        $button->set_sensitive(0);
        async {
            Coro::Timer::sleep 3;
            Gtk2::Gdk::Threads->enter;
            $button->set_sensitive(1);
            Gtk2::Gdk::Threads->leave;
        };
    }
);
$vbox->add($button);

$window->add($vbox);
$window->show_all;

Gtk2->main;
ここでCoro::Timer::sleepしているのは、生のsleepを使うとCoroがスケジュール割り当てとして介入出来なくなるのを回避する為。非同期で動作はするものの、スレッド動作になるので「Gtk2::Threads->enter」と「Gtk2::Threads->leave」でUIに関連する処理をブロックしなければなりません。つまり例えばボタン押下時の処理が5段階あり、その都度UIの何かしらを変更しなければならない場合、「Gtk2::Threads->enter」と「Gtk2::Threads->leave」でそれぞれブロックしなければならない事になります。
平たく言うと、スレッドを使う予定の無かったUI処理を、スレッド対応にするには多少のコード修正が必要になるという事です。
今回、goで作った簡易twitterクライアントの「タイムライン更新」ボタンを非同期対応するのに費やしたコードはたった2行。元のコード
    button.Clicked(func(w *gtk.GtkWidget, args []unsafe.Pointer) {
        button.SetSensitive(false);
        if r, _, err := http.Get("http://twitter.com/statuses/public_timeline.json"); err == nil {
            // タイムライン取得、表示処理
        }
        button.SetSensitive(true);
    }, nil);
となっていたコードに「go」で実行されるブロックを追加しただけ。
    button.Clicked(func(w *gtk.GtkWidget, args []unsafe.Pointer) {
        button.SetSensitive(false);
        go func() {
            if r, _, err := http.Get("http://twitter.com/statuses/public_timeline.json"); err == nil {
                // タイムライン取得、表示処理
            }
            button.SetSensitive(true);
        }();
    }, nil);
何が言いたいのかというと、groutineはgo組み込みであって、Coroがsleepやhttp_getを置き換えようとしている(CORE::GLOBAL上書きもあるけど)物とは違い、言語として非同期をサポートしているという事。もちろんgoにおいてもボタンクリック時にsleepを呼ぶとUIはブロックされるのだけど、実際sleepなんて使わないし、そもそもgoroutineはスレッドじゃない。
そう、goroutineはスレッドじゃない。
A Tutorial for the Go Programming Language

Go has its own model of process/threads/light-weight processes/coroutines, so to avoid notational confusion we call concurrently executing computations in Go goroutines.

http://golang.org/doc/go_tutorial.html
実際にはgoが内部でscheduleを行って実行する処理連鎖で実現している。なのでgtkを呼び出す場合においてもgdk_threads_enter/gdk_threads_leaveを呼び出す必要もない。なぜなら並列とは言えど同時実行ではないのでコンテキストスイッチも意識しなくて良い。
故に上記の様な 「go func(){}()」ブロックだけで非同期処理が書けるという訳。例えばcursesでCUIアプリを書いても画面が崩れる事は無いだろう(未確認)。

UIの開発に有利な言語にはある程度、共通する物があると思う。
  • 匿名関数をコールバックとして扱える
  • サードパーティでも良いので非同期処理の仕組みがある
  • GCが効く
この内、2個か3個あてはまるとUIを扱う上で有利になると思う。Javascriptはこの点(組み込みで非同期が扱える:というかそういうものしか扱えない?)素晴らしいし、jQueryを使えばAjax/UIとして作り手側はかなりの恩恵が得られる。Perlは「sub {}」で匿名関数が使えるがので優秀だが非同期となるとスレッドに頼らざるを得ないのが難点。rubyも同様。pythonは匿名関数が使えないのが少し悲しい(でもpygtkは好きだ)。結局の所、メインループと非同期処理をどう扱うかがネックになっている。例えば各言語でCOMを扱う場合、STA(Single Thread Apartment)しか対応していないCOMは、言語側でメインループをグルグル回すしかない。まぁ言語として用途が違うんだ(JavascriptはそもそもUI記述言語だろ...とか)から、比べちゃならんだろ...とも言えるし。
goにおいては上記3点あてはまるが、デストラクタが無いのが一番の難点。
これからのUIはどんどん非同期な物になって行くんだろうな。

10年程前のUIと言えば、非同期なUIはあまり見られなかった。VB6においても定期的に「DoEvents」を実行してプログレスバーを更新するという、なんちゃって非同期処理が横行していた頃だ。最近はVB.NETでコンポーネント自身がスレッドサポート(実際にはデリゲート)しているので簡単に非同期処理が書ける様になったが、これら全てにおいてもやはり
非同期対応するつもりの無かったUI処理を、非同期対応にするには多少のコード修正が必要になる
には違い無いし、その点でgoには期待している。
Posted at 00:49 in ソフトウェア::lang::go
Tagged as: golang, gtk, ui
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip

2009/12/04


このエントリーをはてなブックマークに追加
GtkTreeModelとか面倒くさい部分に差し掛かってます。でもこれないとコンボボックスもツリーもリストも作れないんすよね。
go-gtk-20091204
いまんところこんな感じ。
イベントクロージャが内包出来てJavaScriptを書いているかの様にGTKプログラミングが出来ています。
    //--------------------------------------------------------
    // GtkButton
    //--------------------------------------------------------
    button := gtk.ButtonWithLabel("Button with label");
    button.Clicked(func(w *gtk.GtkWidget, args []unsafe.Pointer) {
        print("button clicked: ", button.GetLabel(), "\n");
        dialog := gtk.MessageDialog(
            button.GetTopLevelAsWindow(),
            gtk.GTK_DIALOG_MODAL,
            gtk.GTK_MESSAGE_INFO,
            gtk.GTK_BUTTONS_OK,
            entry.GetText()
        );
        dialog.Response(func(w *gtk.GtkWidget, args []unsafe.Pointer) {
            println("Dialog OK!")
        }, nil);
        dialog.Run();
        dialog.Destroy();
    }, nil);
    buttons.Add(button);
完成はまだまだ先です。頑張ります。
Posted at 00:30 in ソフトウェア::lang::go
Tagged as: go, golang, gtk
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip