水曜日, 12月 01, 2010

道を聞かれた 2010 師走

小学校までの道のりを聞かれた。
私は知らないが、嫁が知っていたので伝える。
だいぶ分かりづらいと思うのだけど、たどり着けただろうか。

ほとんど外出しないので、本年最後の「道を聞かれた」になるはず。

木曜日, 11月 25, 2010

IBM developerWorks Japan 最優秀www大賞受賞感想

IBM Web Award 2010:「最優秀www大賞」を受賞だそうです。

この記事を紹介するツイートがあったので、
真面目な賞なんだろうけど何故か小馬鹿にしている感じがする。本文はまだ読んでない “@dW_Japan: 編集長ブログ更新:『IBM Web Award 2010:「最優秀www大賞」を受賞』 http://bit.ly/giJJ5W

http://twitter.com/#!/kameturu/status/7671097809969152

こんな茶々を入れたら、
本文をお読みになって是非ご感想をお寄せください(dW Japan編集長より) @kameturu: 真面目な賞なんだろうけど何故か小馬鹿にしている感じがする。本文はまだ読んでない

http://twitter.com/#!/dW_Japan/status/7673367763091456

こんな返答が。
すみません。どっちが小馬鹿にしているんだって話ですよね。

というわけで読みましたので、その感想。
まずはおめでとうございます。

さて、他のノミネートサイトが分からないので、他のサイトとの比較は出来ないのですが、外から見た場合この賞をdwが取ったというのは順当なように思います。むしろ他に思いつくサイト、ページが無い。
僕のWeb生活上、他のIBMのページは検索にひっかかったついでに見る程度だけど、dwについてはfeedを購読しているし、後で読もうと思ってブックマークだけしているページは数知れず。
たしかdwを定期的に更新されるサイトとして認知したのは、Pythonを覚え始めた頃で、David Mertzさんの記事をむさぼる様に読んでいた記憶があります。

編集長さんの今回の記事に『優秀な翻訳ベンダーとの協業により Contents Quality を高く維持できていること。』とあるのだけど、確かに古い記事は自動翻訳のような不自然な訳が目立っていたけど、段々と普通の訳になっていったように思います。しかも、何年か前までは、翻訳されるスピードが遅くて「これなら英語版を直接読んだ方が速いなあ」と思っていたけど、一年ぐらい(?)前から、物凄い速さで訳されるようになって、英語版を後で読もうと思っていたら、次の週には日本語訳が出来ていたりなんてザラにあったり。
本当に優秀でありがたいです。

一方で『ソーシャル化』ってのはちょっとピンと来なかったり。サインイン出来ることは知っているけど、その利点が今一つかめなかったり。とはいえ、これはネガティブな点ではなくソーシャル機能なんてなくても「読むサイト」としてのクオリティが高いという証左なのだと思います。

感想からどんどん離れていってしまいますが、dw「Japan」に対する要望としては、「Japan」独自の記事をもっと読みたいなあと、いつも思っています。具体例が思い浮かばないのですが、日本発の情報というものもきっといろいろあるんじゃないかと。英語サイトも平行して読んでいると、あの記事の翻訳だなという事がほとんどで、驚きがあまりなかったり。テクニカルナイトの報告記事だけでもあると楽しいのにと思います。

なんのかんの言っても、毎週金曜の更新を楽しみにしている人は、多いはず。
dw編集長、担当の皆さん、今後も楽しい記事を楽しみにしています。



おまけ

毎週チェックしているわけじゃないけど、僕がIBMのサイトで他に良く見ているところ
Design @ IBM

土曜日, 11月 20, 2010

gofmtをvimで簡単に使うためのスクリプト

Go言語は、推奨コーディングスタイルがあります。
とはいえ、実際に書くときにはあまり細かく気にする必要はなく、gofmtというGo言語をインストールするとついてくるフォーマッタを通してやれば、推奨スタイル通りに整形してくれます。
これを随時実行したいので、vimスクリプトを書いてみました。
都合上、フォーマットをかける前に、ファイルを保存します。

function! Gofmt()
:w
python << EOF
import vim
import subprocess

cb = vim.current.buffer
cursor = vim.current.window.cursor
p=subprocess.Popen(
['gofmt', cb.name],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
close_fds=True)
returncode=p.poll()
if not returncode:
err = p.stderr.read()
if err != None and err == '':
del cb[:]
cb.append(p.stdout.readlines(), 0)
else:
print(err)
vim.current.window.cursor = cursor
EOF
endfunction

月曜日, 11月 15, 2010

子供が生まれた

11月15日の七五三の日の朝に誕生。
病院の方針なのか、夫が立ち会う事は前提になっていたので、生まれた直後の子供を見ることが出来た。

病院に行ったのは、金曜日の朝なので、だいたい72時間で生まれたことに。
10分間隔で痛くなったら来いとの指示だったそうだけど、今思えば早すぎた感はあり。
初めてのことなので、痛いのレベルが分からなかったというのが大きいけど、とりあえず「痛い、痛い」言っているレベルではまだ先は長いです。
最終的には基本的に痛くてしゃべれないし、言えたとしても絞り出すようにしかしゃべれない。
(中の人を含めて)個人差も大きいだろうから、一概には言えないのだろうけど。
外から見る限りでは、分娩前の陣痛の方が分娩中より痛そうでした。もしかしたら分娩中は痛みどころでは無いのかな。

立ち会うとはいえ、何か出来るわけでもなく、汗を拭いて、うちわで扇ぐだけ。基本的に夫は何も出来ないわけです。
それでも、Twitterでリアルタイムで実況出来るほど余裕があるわけでもなく、途中途中の空き時間に友人、知人に向けて短くツイートする程度。他にも実家にメールとかもしてたしね。
分娩中にTwitterで実況したい人は、妻、助産師、看護師、医師、(もしかしたら子供も)からの白い目に耐えるだけの精神力を鍛えてください。

それにしても、赤ちゃんは文句無しにかわいい。
病院内で他の赤ちゃんを見かける機会は時々あって、かわいいなとは思っていたけど、自分の子はそれとは別の感覚としてかわいいと感じる。
客観的に見れば、生まれたての赤ちゃんは基本的にほわほわしていて、大人以上に個人差がないはずなのに。

今日は出てくるのに疲れたのか、あまり泣いたりしなかったけど(鼻から羊水を吸い出すためにチューブを突っ込まれると流石に泣いてた)、明日からは元気に泣くんだろうな。

水曜日, 11月 10, 2010

gocode入れてみた

VimでGoがautocomplete出来るgocodeがいい感じ」を見て、gocodeを入れてみた。

ビルドやインストールについては、gocodeのサイトに書いてあって、特に引っかかるところはない。
ただ、その説明だけでは、gvimでは動作しなかったので、gvimrcに以下の行を追加した。

let $GOBIN="$HOME/bin/go/"
let $GOROOT="$HOME/src/go/"
let $PATH="$PATH:$HOME/bin/go"

火曜日, 11月 09, 2010

Gordonさまがマウスカーソルにくっつく

多少書き直してみた。ついでに分身の術ではなく、マウスカーソルにくっつくように動くようにした。
コールバックな部分は若干やっつけだけど、基本的にはこんな感じだと思う。
event.goは綺麗というかすっきりして、ここまで来たらファイルを分離する意味が無い。
その分、main.goのhandleMouseEventがやたら汚い。
interface{}を具体的な型に落とす方法はswitchしかないのかな。

(一度投降後、何度かコードを綺麗にしてます)

main.go

package main

import (
"fmt"
"exp/draw"
"exp/draw/x11"
"image"

"./event"
"./gordon"
)

func handleMouseEvent(event interface{}, args ...interface{}) {
switch e := event.(type) {
case draw.MouseEvent:
{
me := draw.MouseEvent(e)
switch win := args[0].(type) {
case draw.Window:
{
win = draw.Window(win)
switch char := args[1].(type) {
case gordon.Character:
{
char = gordon.Character(char)
fmt.Printf(
"MouseEvent: Button= %d, Loc= %v\n",
me.Buttons, me.Loc)

draw.Draw(win.Screen(), char.Canon(), char.Mask(), image.ZP)
char.Position(me.Loc.X, me.Loc.Y)
draw.Draw(win.Screen(), char.Canon(), char, image.ZP)
win.FlushImage()
}
}
}
}
}
}
}

func main() {
gordon1, e := gordon.NewGordon(image.Point{X: 0, Y: 0})
if e != nil {
fmt.Printf("Error %v\n", e)
return
}

win, e := x11.NewWindow()
if e != nil {
fmt.Printf("Error %v\n", e)
return
}

eventChan := win.EventChan()
mouseCallBack := event.CallBack(handleMouseEvent)
sync := make(<-chan bool)
go event.HandleCallBack(eventChan, mouseCallBack, win, gordon1)
<-sync
}

event.go

package event

type CallBack func(event interface{}, args ...interface{})

func HandleCallBack(eventChan <-chan interface{}, fun CallBack, args ...interface{}) {
for {
event := <-eventChan
go fun(event, args...)
}
}

gordon.go

package gordon

import (
"bufio"
"image"
"image/png"
"os"
)
os.DevNull

type Character interface {
image.Image
Canon() image.Rectangle
Mask() image.Image
Position(x, y int)
}

type Gordon struct {
image.Image
Rect image.Rectangle
maskImage image.Image
}

func (g *Gordon) Position(x, y int) {
r := g.Bounds()
g.Rect = image.Rect(
x, y,
x+r.Max.X, y+r.Max.Y)
}

func (g *Gordon) Canon() image.Rectangle {
return g.Rect.Canon()
}

func (g *Gordon) Mask() image.Image {
return g.maskImage
}

func NewGordon(point image.Point) (gordon *Gordon, e os.Error) {
gordon = new(Gordon)
img, e := loadGordon()
if e != nil {
return nil, e
}
gordon.Image = img
gordon.Position(point.X, point.Y)
gordon.maskImage = image.NewGray(img.Bounds().Max.X, img.Bounds().Max.Y)
return gordon, e
}

func loadGordon() (image.Image, os.Error) {
file, e := os.Open("./Gordon.png", os.O_RDONLY, 0666)
if e != nil {
return nil, e
}

read := bufio.NewReader(file)
icon, e := png.Decode(read)
if e != nil {
return nil, e
}
return icon, nil
}

月曜日, 11月 08, 2010

Gordonさまと遊んでみて

とりあえず、自分で見ても滅茶苦茶なソースだと思う。
Interfaceなんて使ってみたかっただけで、無理やり過ぎる。
そもそも書いてある場所がどう考えてもおかしい。
コールバック的なものは関数型を渡してやればいいんだろうけど、何故かうまくいかなかった。
基本的な文法で間違っている可能性大。

そんな適当ながらも、書いてみてのGoの感想。

1. interfaceにFieldを宣言出来ないのは若干不便
Javaで言えばpublicなFieldの値を取りたいだけなのに、関数が必要になるのは不便。
要するにsetter/getterもインターフェースに書く必要があるわけで。
とはいえinterfaceてのはそういうものなのかも

2. ifの括弧が無いのは楽
慣れると他の言語で括弧を書くのを忘れる。

3. 型の後置は慣れると気にならない。
たまに間違うけど

4. 出来上がるバイナリがでかい
パソコンで動かしていると大して気にならないけど。もっと貧弱な環境だと大変かも。

CにもPythonにも似ていないけど、慣れれば便利な予感。

日曜日, 11月 07, 2010

GoでGordonさまと遊ぶ

Go言語のマスコットのGordonさまは、みんなから気持ち悪いと言われていますが、じっと見ていると、かわいいところが無く無くない気がしてきました。

なので、ちょっとコードが整理されていませんが、GoでGordonさまをいっぱい並べられるものを作ってみました。
コールバックな関数はどう書けばいいんだろう。

main.go

package main

import (
"fmt"
"exp/draw/x11"
"image"

"./event"
"./gordon"
)


func main() {
gordon1, e := gordon.NewGordon(image.Point{X: 0, Y: 0})
if e != nil {
fmt.Printf("Error %v\n", e)
return
}

win, e := x11.NewWindow()
if e != nil {
fmt.Printf("Error %v\n", e)
return
}

eventChan := win.EventChan()
sync := make(<-chan bool)
go event.Handle(eventChan, win, gordon1)
<-sync

}


gordon.go

package gordon

import (
"bufio"
"image"
"image/png"
"os"
)

type Gordon struct {
image.Image
Rect image.Rectangle
}

func (g *Gordon) Position(x, y int) {
r := g.Bounds()
g.Rect = image.Rect(
x, y,
x+r.Max.X, y+r.Max.Y)
}

func (g *Gordon) Canon() image.Rectangle {
return g.Rect.Canon()
}

func NewGordon(point image.Point) (gordon *Gordon, e os.Error) {
gordon = new(Gordon)
img, e := loadGordon()
if e != nil {
return nil, e
}
gordon.Image = img
gordon.Position(point.X, point.Y)
return gordon, e
}

func loadGordon() (image.Image, os.Error) {
file, e := os.Open("./Gordon.png", os.O_RDONLY, 0666)
if e != nil {
return nil, e
}

read := bufio.NewReader(file)
icon, e := png.Decode(read)
if e != nil {
return nil, e
}
return icon, nil
}


event.go

package event

import (
"exp/draw"
"fmt"
"image"
)

type Character interface {
image.Image
Canon() image.Rectangle
Position(x, y int)
}

func Handle(eventChan <-chan interface{}, win draw.Window, char Character) {
for {
event := <-eventChan
switch e := event.(type) {
case draw.MouseEvent:
{
me := MouseEvent(e)
go me.handleMouseEvent(win.Screen(), char)
}
case draw.KeyEvent:
{
ke := KeyEvent(e)
go ke.handleKeyEvent(win.Screen(), char)
}
}
win.FlushImage()
}
}


type MouseEvent draw.MouseEvent
type KeyEvent draw.KeyEvent

func (me *MouseEvent) handleMouseEvent(screen draw.Image, char Character) {
fmt.Printf("MouseEvent: Button= %d, Loc= %v : %v\n", me.Buttons, me.Loc, char)
char.Position(me.Loc.X, me.Loc.Y)
draw.Draw(screen, char.Canon(), char, image.ZP)
}

func (ke *KeyEvent) handleKeyEvent(screen draw.Image, char Character) {
fmt.Printf("KeyEvent: Key= %d\n", ke.Key)
}


実行結果

日曜日, 10月 17, 2010

Ubuntu 10.10 型破りなミーアキャット

今回は大した変更はなし。
インストーラが変わって、アカウント設定なんかはインストール(ファイルのコピー)中に行えるようになったのが目立つ程度。
Unityが入るネットブックの方が今回は派手な印象。
個人的にUbuntuのアップデートは定期バックアップを兼ねているのでやったけど、正直いって、無理に上げる必要はなさそう。

最近デスクトップ版は派手な変更は無いけど、次回はGnome3が入るから期待したいところ。
その分トラブルも多そうだけど。

日曜日, 9月 05, 2010

最近買ったもの

ここ2ヶ月ほどの間に買ったものたち。

Kindle DX グラファイト


増え続ける本を少しでも減らすために購入。

これを買った一ヶ月後に、日本語対応されたKindle3が出て若干がっかりですが、画面サイズがでかいし、そのうちファームウェアアップデートがあるはず。

画面の表示は、そこそこ高級なわら半紙にきちんと印刷したというレベルで、非常に読みやすい。
見た感じはかなり紙に近いので、読んでいて疲れるということがありません。反面、文字入力はし辛いし、日本語は入力できない。書き換え速度の限界から、カーソル移動ももっさり。
本当に読書をメインにした端末で、速読も不可能なので、まったり読むことが大好きな人以外にはおすすめできない。
何となく、読書端末以上の可能性は感じるのだけど、これはKindleアプリが出てくれば分かるのかも。

いまのところ入っている本は、青空文庫の小説をPDF化したものとか、適当なライブラリのドキュメントとかで、まだ電子書籍は一冊も買っていなかったり。厳密にはiPhoneアプリのオライリー本から、ePubを抜いたのがいくつか入っているので、これをもって電子書籍を買ったと、言えなくもないけど。

なんで買っていないかと言えば、欲しい本の電子版が無いというシンプルな理由で、まだまだ移行期なんだなあということを実感させられています。

オライリーの読み物系の本で、面白そうなものがいくつかあるので、それらはそのうち買うかも。
Oreilly Safariに日本語の本がたくさんあれば、確実にユーザ登録するのだけどね。

Sony BRAVIA KDL-40HX800


液晶テレビです。
選んだ理由は、モーションフロープロによる240コマ再生機能。
クアトロンも出ていたけど、色の違いが気になるような映像より、残像が気になる映像をみるケースの方がはるかに多いので。
実際、モーションフローの補完機能は凄まじい。
ONにしたときと、OFFにしたときでは、まったく別の映像になってしまう。特に3DCGアニメとの相性は抜群で、絶対に映画館では見られないような映像に変化してしまっている。
コマを補完して追加するので、実際別の映像と言ってもよいのだけど、では正しい映像の再現とは何なのだろうと考えてしまう。
映画にしろテレビにしろ撮影というプロセスを経たその時点で実際の光学的風景とは別のものが記録されているわけで、それを「再生」したときの正解とは何なのかという問題になる。しかも電波で送信される場合、なんらかの変換が加えられている。3DCGの場合は、そもそも光学的実体すら存在しないわけで、ますますわけがわからないものを見ていることになる。
こんなメディアアートな体験が出来る面白テレビは、他に無いような気がする。

画面が大きくなったので、いままで見えていなかったものが見えるようになったというのも単純に嬉しいです。

iPhone4


電話代やら、その他いろいろ考えての変更。
まだ使いこなせていないからか、タッチしても意図しないところが反応してしまってイライラすることが多いです。小さいキーボードを買おうか考え中。
マルチタスクというか、複数のアプリを行ったり来たり出来るところは、非常に便利。
ただ、PythonなりPerlなりRubyなりが一つでも動けば、ものすごく便利になるのだけど。

土曜日, 7月 17, 2010

道を聞かれた ソニー歴史資料館

道聞かれラッシュ。

今回はソニー歴史資料館
聞かれた場所が資料館から結構離れていた所だったので、簡単な道のりと坂道の上にあることしか伝えられなかった。たどり着けただろうか。

なにかイベントでもあったのかと思ったけど、そういうわけではなさそう。
仕事かな?地図を持ってないあたり、営業ではなさそうだったけど。

水曜日, 7月 14, 2010

道を聞かれた 梅雨明けもうすぐ

今回も駅の場所。
分かっている人には線路どころかホームも見えているのですが、分からない人には認識できないのだろうな。

とりあえず横断歩道ですれちがうときには聞かないで欲しい。危ないので。

日曜日, 6月 20, 2010

道を聞かれた梅雨

うちの近所で一丁目はどっちかと聞かれた。どっちだったかなあと考えている間に「こっちだよね」と指で道を示しながら言われたので、「ええ多分」と答えてしまう。

ごめんね逆方向だったよ。
丁目じゃなくてランドマークで聞かれたならちゃんと答えられたかも

日曜日, 5月 30, 2010

CからOCamlを呼ぶ

今月ずっとやっていたことのまとめ。

CのコードからOCamlを呼び出す方法については、既に先人がいるのだけど、bigarrayと絡めるとあまり見当たらなかったので、まとめてみる。
OCamlのドキュメントだと、Chapter 18 Interfacing C with Objective Camlのあたりと、Chapter 29 The bigarray libraryのあたり。

基本編


CからOCamlのプログラムを呼び出す場合、大体以下の事を頭に入れておくとよいらしい。

  1. Cから呼び出したいOCamlの関数をCallback.registerに設定する

  2. C側でOCamlの関数を呼び出す前にmain関数でcaml_startup(argv)を呼ぶ

  3. caml_named_valueでCallback.registerに設定したOCaml関数を取り出す

  4. caml_callbackNでOCaml関数を呼ぶ

  5. OCamlとのやり取りにはvalue型の値が使われる

  6. OCaml関数への引数はCAMLparamNやCAMLlocalNで宣言(?)する(型によっては不要)

  7. Cの関数でCAMLparamNを通した値を戻り値にするときはCAMLreturnを使う(型によっては不要)



ではこれらを踏まえた簡単なサンプルを作ってみる。

ocaml.ml

let ocaml_process (a : int) (b : int) = a + b

(* 1. 呼びたい関数をCallback.registerに登録する *)
let _ = Callback.register "ocaml_process" ocaml_process

ただの足し算。

main.c

#include <stdio.h>

#include <caml/memory.h>
#include <caml/callback.h>

int main(int argc, char ** argv)
{
// 2. caml_startupを呼ぶ
caml_startup(argv);
// 3. OCamlの関数を取り出す
value *func = caml_named_value ("ocaml_process");

// 5. OCamlとのやり取りにはvalue型を使う
// Val_intでOcamlのintにします。
value a, b, result;
a = Val_int(2);
b = Val_int(4);
// 4. caml_callbackNでOCaml関数を呼ぶ
// 今回は引数が2つなのでN=2
// 引数が一つの場合はcaml_callbackと書き、数字はつけない
result = caml_callback2 (*func, a, b);

// 5. 戻ってきたvalue型の値をCの型に戻す
int print_result = Int_val(result);

printf("%d\n", result);
printf("%d\n", print_result);

return 0;
}

6番の7番についての記述が無いのはint型では必要ないから。必要となるのはblockedな値らしい。blockedってのが良く分かっていないが、とりあえずGCで管理されるような値という認識。
Int_valを使わない場合もあえてprintするようにしている。

これをビルドするためのMakefileはこんなの。ライブラリの位置はOSなどなどによって違うはず。

PROGRAM=call_ocaml
OCAML_LIB=/usr/lib/ocaml
OBJS = camlcode.o main.o

program : $(OBJS)
${CC} $(OBJS) -ldl -lm -L ${OCAML_LIB} -lasmrun -o ${PROGRAM}

main.o : main.c
${CC} -o $@ -c main.c

camlcode.o : ocaml.ml
ocamlopt -output-obj -o $@ ocaml.ml


さて、これを実行してみると、Int_valを使わない場合は13、使った場合は6がprintされることが分かる。
つまりOCamlのintを右に1シフトすると、Cのintになると。
詳しくはmlvalues.hを参照。Val_intの場合は何をやっているのかも分かったり。

argvにアクセス出来ない場合は?


一連の流れの中で、一番厄介なのはcaml_startup(argv)。main関数で呼べと言われても、mainに触れない場合なんてざらにあるわけで。何らかのフレームワークなんて使う場合は特にそう。それでもargvへのインターフェースが提供されていれば解決するけど、それも無いとお手上げ。
本当にそうなのか?というかargvへのインターフェースが無いと使えないなんて現実的じゃないだろう。と思って調べていたら、こんなページを発見。
無ければこんな感じに作ればいいらしい。

static void
ocaml_init ()
{
char *dummy_argv[2];
dummy_argv[0] = 0;
dummy_argv[1] = NULL;
caml_startup (dummy_argv);
}

ドキュメントにはこんなやり方書いていないのだけど、とりあえず動く。

bigarrayでやりとり


さて、世の中でかい数字の配列を使う機会というのはままあるわけですが、OCamlの配列は4M程度までしか扱えないらしい。4Mもあれば十分な気もするけど、足りない場合もあるし、充分なのか足りないのか良く分からない場合というのもある。
そんなときはbigarrayというものを使うそうな。これを使うと整数と浮動小数点数限定で16次元までの制限はるものの、横のサイズに制限は無しな素敵な配列が使えるらしい。
ついでにbigarrayのメモリレイアウトはCやFortrunと互換性があるので、これら2つの言語とOCamlをくっつけるときにも便利。

説明については、マニュアルのが詳しいので、Cの配列をbigarrayにするサンプルコードを示す。
value call_ocaml(){
int array[5] = {0, 1, 2, 3, 4};
value result;
CAMLparam1 (result);
CAMLlocal1 (barray);
long dims[1];
dims[0] = 5;
barray = alloc_bigarray(BIGARRAY_UINT8 | BIGARRAY_C_LAYOUT, 1, array, dims);
value *func = caml_named_value ("ocaml_process");
result = caml_callback (*func, barray);
CAMLreturn(result);
}

alloc_bigarrayがCの配列からbigarrayを作る関数。第1引数で配列の要素の型と、メモリレイアウトを指定。第2引数で配列の次元、第3引数にbigarrayに変換したいCの配列、第4引数に各次元の配列サイズを配列にして渡す。
厳密には「作る」のではなくポインタをOCamlに渡せる形にすると言った方が良いと思う。
それとbigarrayにすると言っても、Cの世界ではvalue型として扱われる。
OCaml関数でbigarrayを返り値にした場合も、Cで受けとるときはvalue型になる。つまりintの場合と同様に変換が必要になる。
biggarrayの場合はData_bigarray_val(big_array_value)というようにする。

簡単なサンプルコードを書いてみる。
ocaml.ml
let ocaml_process barray =
barray.{0}<-1;
barray;;

let _ = Callback.register "ocaml_process" ocaml_process

第1要素を1にしているだけ。

main.c
#include <stdio.h>
#include <caml/memory.h>
#include <caml/callback.h>
#include <caml/bigarray.h>

value call_ocaml(){
int array[5] = {0, 1, 2, 3, 4};
value result;
CAMLparam1 (result);
CAMLlocal1 (barray);
long dims[1];
dims[0] = 5;
barray = alloc_bigarray(BIGARRAY_UINT8 | BIGARRAY_C_LAYOUT, 1, array, dims);
value *func = caml_named_value ("ocaml_process");
result = caml_callback (*func, barray);
CAMLreturn(result);
}

int main(int argc, char ** argv)
{
caml_startup(argv);
int* result = (int*)Data_bigarray_val(call_ocaml());
printf("%d\n", result[0]);
return 0;
}

5要素の一次元配列を渡す。

Makefile
PROGRAM=call_ocaml
OCAML_LIB=/usr/lib/ocaml
OBJS = camlcode.o main.o

program : $(OBJS)
${CC} $(OBJS) -ldl -lm -L ${OCAML_LIB} -lasmrun -lbigarray -o ${PROGRAM}

main.o : main.c
${CC} -o $@ -c main.c

camlcode.o : ocaml.ml
ocamlopt -output-obj bigarray.cmxa -o $@ ocaml.ml


ポインタを渡している事を確認するのであれば、mainで配列を作ってOCamlからの返り値を投げ捨てた上で、元の配列を覗いてみるとよい。

日曜日, 5月 09, 2010

Ubuntu 10.04 入れた

10.04はLucid Lynx(透き通った山猫)。

特に問題はなくインストールできた。5/1に入れて一週間ほどたつけど、特に問題無し。
閉じるボタンの位置が変わったのはちょっと驚いたけど、普段はAlt + F4で閉じているので、そのうち気にならなくなるはず。

あえて不満を言うと、Fx3.5上のTwitterのWebインターフェースでの入力がやたら遅いという事と、デスクトップの「名前順に整理する」でアイコンがどこかにすっ飛んでいくことぐらい。
もしかしたらコアラの時からそうだったかもしれないけど、気になるほどではないかな。

ところで、透き通った山猫ってのはチェシャ猫みたいなものだろうか。

火曜日, 4月 06, 2010

子供が出来て考えたこと

出来たといっても、まだ生まれていないので、正直まだ実感が湧かない
エコー写真で1cmも満たない黒い影(既に心臓は動いているらしい)を見ても良く分からない。
そんな状態で思ったことをいくつか。

母子手帳。父はどこに?


妊娠すると母子手帳ってのがもらえます。正確には母子健康手帳です。市町村(区)から交付されます。
とりあえずツッコミどころとして「母子」なんですよね。「父」はどこに行ったんでしょう?ものすごい疎外感です。
これ、なんで「母子健康手帳」なのかっていうと、法律だからなんですね。母子保健法の第十六条にばっちり「母子健康手帳」と書いてあります。


(母子健康手帳)
第十六条  市町村は、妊娠の届出をした者に対して、母子健康手帳を交付しなければならない。
2  妊産婦は、医師、歯科医師、助産師又は保健師について、健康診査又は保健指導を受けたときは、その都度、母子健康手帳に必要な事項の記載を受けなければならない。乳児又は幼児の健康診査又は保健指導を受けた当該乳児又は幼児の保護者についても、同様とする。
3  母子健康手帳の様式は、厚生労働省令で定める。
4  前項の厚生労働省令は、健康診査等指針と調和が保たれたものでなければならない。


ちょっとひどいよね。一応、自治体によっては名称を親子手帳に変えているところもあるみたいですが(豊田市の事例岡山市の事例ぐぐって見つけた順)。
それと母子手帳とは別に父子手帳を用意している自治体もあります。例えば東京都は父親ハンドブックというものを配布しています(紙は180円で売っているそうな)。
とはいえ、法律でそのような名称を規程しているのはどうなんだろう。
まさか親子手帳ってのは男女共同参画(内閣府)でやるべきで、育児(厚生労働省)ではやるべきでない、みたいな典型的縦割行政ってことはないよね。

まあ、妊娠出産する上で、父親には何のリスクも無いというのも事実なわけですが。

産むより育てる(育つ)方が大変らしい


当たり前かもしれませんが、母子手帳で出産に関する部分って前の方のほんのちょっとです。あとは全部生まれてからのこと。
時間的にも生まれてからの方がはるかに長い(少なくともそれを期待する)わけですしね。
ただ産むのが楽かというとそうでもない。母体への負担はもちろんだけど、分娩可能な病院は妊娠確認後にすぐ予約しないと駄目らしい。今、Wikipediaの出産難民の項を見たけど、『「分娩予約が予定日の6ヶ月前」などという事態がみられ』と書いてある。6ヶ月前ならまだマシな方です。誰か書き換えておいて下さい。
ともかく、産科の医師不足ってのは深刻らしい。
とりあえずうちは予約できたので一安心しておく。

妊娠を伝える時期


当然ながら、妊娠した事を親戚知人に伝えねばなら無いわけで(内緒にしないといけない人もいるかもしれませんが)。うちは割とすぐ話しましたが。世の中には安定期になるまで話さないという人もいるらしい。
回りのサポートを得るには早い方がいいとは思うものの、初期流産の率は10~15%と結構高いので、ある程度待つというのも分かる気がする。
初期流産というのは防ぎようがない確率の問題らしいし。といっても妊婦はショックが大きいらしいし、場合によっては身体が危険になる場合もあるらしい。例によって父親には少なくとも身体的リスクは無いのだけど。精神的にはどうだろう。
なんだかんだで産むのも大変なような。

妊婦の様子


どうやら、ものすごく眠くなるらしい(寝つわり)。そして口に何か入れていないと気持ち悪くなるそうな(食べつわり)。なので少しの量を分散させて食べている。そうなのだが、明らかに量が増えているような気がしないでもない。それはともかく食べ過ぎは良くないらしい。赤ちゃんはまだ2cmぐらいなので、栄養が行っても処理し切れないのだろうな。赤ちゃんを育てるだけでなく母体も中をガードするために壁を作らなければならないだろうから、少しぐらいはいいのだろうか。食べられなくなるつわりは、もう少したったらなるみたいだし、そうなったら量も取れなくなるだろうし。
一応、ノートにその日何を食べたか記録しているけど、続くかしら。
嫁様は偏頭痛持ちなので、妊娠後に発生するかと思ったけど、どうやらなっていないらしい。人によっては症状がひどくなるらしいので、これはよかった。今気づいたけど、カフェインの摂取を減らしているのに頭痛になってないもよう。
コーヒーが切れると頭痛が起きる身としては羨ましい。



もうすこしエコー画像が人型になれば実感がわくようになるかなあ。

水曜日, 3月 03, 2010

道を聞かれた

おばあさんに駅までの道を聞かれる。
駅は見えている場所なのだが、道が分からなかったらしい。
世の中の駅は難しい場所にあるものなのか。

土曜日, 2月 13, 2010

道を聞かれた2010年初

道をあるいていたら、おばちゃんから公共施設の場所を聞かれた。
知っている場所だったので普通に教えた。
どうやら私の前の人の説明が適当過ぎだったらしい。

火曜日, 2月 02, 2010

gstreamerでWebCamを使うときにひっかかった罠

gstreamerという、ライブラリ(ライブラリ群?)があります。
Linuxな人には馴染み深いですね。マルチメディア処理では定番のライブラリです。
このライブラリは、様々なマルチメディア要素をパイプラインを通すように処理出来ます。
詳しいことは、ちゃんとしたチュートリアルを見てください。

さて、それらのチュートリアルに、もしかしらWebCamから映像を取り込む内容が含まれているかもしれません。ここに罠が潜んでいます。
WebCamソースを表すgstreamerの識別子は「v4l2src」です。「412」ではなく「4l2」です。
「Video for Linux 2 のソース」 = 「v4l2src」=「ぶい よん える に えす あーる しー」です。

世界的に引っかかる人が多く、おそらくこれからもひっかかる人が多数出るはずなので、メモを残しておきます。

木曜日, 1月 21, 2010

ClutterのチュートリアルをPyClutterに翻訳 その2

ClutterのチュートリアルをPyClutterに翻訳するその2

Scoreを使って複数のタイムラインを流すところの前半まで。後半のところはPyClutterの問題なのか、うまく出来ないので、原因を調査中。
追記:原因解明。何が問題だったのかは後で書く。

複数タイムラインの次は画像の読み込みのチュートリアルだけど、画像を用意するのが面倒なのでやらない。

大きさの変更やオブジェクトの選択


まわして、かくだい
#!/usr/bin/python
# -*- coding: utf-8 -*-

import clutter
import mathhacks

global rotation
global scale
rotation = 0
scale = 0


def on_timeline_new_frame(timeline, frame_num, rect_list):
global rotation
global scale

rotation += 0.3
rect_list[0].set_rotation(clutter.Z_AXIS, rotation * 5, 0, 0, 0)
rect_list[1].set_rotation(clutter.Z_AXIS, rotation * 4, 0, 0, 0)
rect_list[2].set_rotation(clutter.Z_AXIS, rotation * 3, 0, 0, 0)
rect_list[3].set_rotation(clutter.Z_AXIS, rotation * 2, 0, 0, 0)
rect_list[4].set_rotation(clutter.Z_AXIS, rotation * 1, 0, 0, 0)
rect_list[5].set_rotation(clutter.Z_AXIS, rotation * 0.5, 0, 0, 0)

scale += 0.01
if scale > 1.0:
scale = 0

scale_amount = mathhacks.smooth_step2(1.0, 2.0, scale)
for rect in rect_list:
rect.set_scale(scale_amount, scale_amount)


def quit(actor, *args):
clutter.main_quit()


def create_rect(color):
rect = clutter.Rectangle(color)
rect.set_size(256, 128)
rect.set_position(128, 128)
rect.set_anchor_point(128, 64)

return rect


clutter.init()
stage_color = clutter.Color(0, 0, 0, 255)
stage = clutter.Stage()
stage.set_size(512, 512)
stage.set_color(stage_color)

red = clutter.Color(255, 0, 0, 128)
green = clutter.Color(0, 255, 0, 128)
blue = clutter.Color(0, 0, 255, 128)
yellow = clutter.Color(255, 255, 0, 128)
cyan = clutter.Color(0, 255, 255, 128)
purple = clutter.Color(255, 0, 255, 128)

rect_list = []
rect_list.append(create_rect(red))
rect_list.append(create_rect(green))
rect_list.append(create_rect(blue))
rect_list.append(create_rect(yellow))
rect_list.append(create_rect(cyan))
rect_list.append(create_rect(purple))

stage.connect('hide', quit)
stage.show()

for r in rect_list:
stage.add(r)

timeline = clutter.Timeline(60)
timeline.connect('new-frame', on_timeline_new_frame, rect_list)
timeline.set_loop(True)
timeline.start()

clutter.main()


まわして、かくだいして、おしたらきえる
#!/usr/bin/python
# -*- coding: utf-8 -*-

import clutter
import mathhacks

global rotation
global scale
rotation = 0
scale = 0


def on_timeline_rotation_new_frame(timeline, frame_num, rect_list):
global rotation

rotation += 0.3
rect_list[0].set_rotation(clutter.Z_AXIS, rotation * 5, 0, 0, 0)
rect_list[1].set_rotation(clutter.Z_AXIS, rotation * 4, 0, 0, 0)
rect_list[2].set_rotation(clutter.Z_AXIS, rotation * 3, 0, 0, 0)
rect_list[3].set_rotation(clutter.Z_AXIS, rotation * 2, 0, 0, 0)
rect_list[4].set_rotation(clutter.Z_AXIS, rotation * 1, 0, 0, 0)
rect_list[5].set_rotation(clutter.Z_AXIS, rotation * 0.5, 0, 0, 0)

def on_timeline_scale_new_frame(timeline, frame_num, rect_list):
global scale
scale += 0.01
if scale > 1.0:
scale = 0

scale_amount = mathhacks.smooth_step2(1.0, 2.0, scale)
for rect in rect_list:
rect.set_scale(scale_amount, scale_amount)

def on_stage_button_press(stage, event, *arg):
x = 0
y = 0
x, y = event.x, event.y
clicked = stage.get_actor_at_pos(clutter.PICK_ALL, x, y)
if clicked == stage:
return
clicked.hide()

def quit(actor, *args):
clutter.main_quit()


def create_rect(color):
rect = clutter.Rectangle(color)
rect.set_size(256, 128)
rect.set_position(128, 128)
rect.set_anchor_point(128, 64)

return rect


clutter.init()
stage_color = clutter.Color(0, 0, 0, 255)
stage = clutter.Stage()
stage.set_size(512, 512)
stage.set_color(stage_color)

red = clutter.Color(255, 0, 0, 128)
green = clutter.Color(0, 255, 0, 128)
blue = clutter.Color(0, 0, 255, 128)
yellow = clutter.Color(255, 255, 0, 128)
cyan = clutter.Color(0, 255, 255, 128)
purple = clutter.Color(255, 0, 255, 128)

rect_list = []
rect_list.append(create_rect(red))
rect_list.append(create_rect(green))
rect_list.append(create_rect(blue))
rect_list.append(create_rect(yellow))
rect_list.append(create_rect(cyan))
rect_list.append(create_rect(purple))

stage.connect("button-press-event", on_stage_button_press)
stage.connect('hide', quit)
stage.show()

for r in rect_list:
stage.add(r)

timeline = clutter.Timeline(60)
timeline.connect('new-frame', on_timeline_new_frame, rect_list)
timeline.set_loop(True)
timeline.start()

clutter.main()

スコアを記録する


#!/usr/bin/python
# -*- coding: utf-8 -*-

import clutter
import mathhacks

global rotation
global scale
rotation = 0
scale = 0


def on_timeline_rotation_new_frame(timeline, frame_num, rect_list):
global rotation

rotation += 0.3
rect_list[0].set_rotation(clutter.Z_AXIS, rotation * 5, 0, 0, 0)
rect_list[1].set_rotation(clutter.Z_AXIS, rotation * 4, 0, 0, 0)
rect_list[2].set_rotation(clutter.Z_AXIS, rotation * 3, 0, 0, 0)
rect_list[3].set_rotation(clutter.Z_AXIS, rotation * 2, 0, 0, 0)
rect_list[4].set_rotation(clutter.Z_AXIS, rotation * 1, 0, 0, 0)
rect_list[5].set_rotation(clutter.Z_AXIS, rotation * 0.5, 0, 0, 0)


def on_timeline_scale_new_frame(timeline, frame_num, rect_list):
global scale
scale += 0.01
if scale > 1.0:
scale = 0

scale_amount = mathhacks.smooth_step2(1.0, 2.0, scale)
for rect in rect_list:
rect.set_scale(scale_amount, scale_amount)


def on_stage_button_press(stage, event, *arg):
x = 0
y = 0
(x, y) = (event.x, event.y)
clicked = stage.get_actor_at_pos(clutter.PICK_ALL, x, y)
if clicked == stage:
return
clicked.hide()


def quit(actor, *args):
clutter.main_quit()


def create_rect(color):
rect = clutter.Rectangle(color)
rect.set_size(256, 128)
rect.set_position(128, 128)
rect.set_anchor_point(128, 64)

return rect


clutter.init()
stage_color = clutter.Color(0, 0, 0, 255)
stage = clutter.Stage()
stage.set_size(512, 512)
stage.set_color(stage_color)

red = clutter.Color(255, 0, 0, 128)
green = clutter.Color(0, 255, 0, 128)
blue = clutter.Color(0, 0, 255, 128)
yellow = clutter.Color(255, 255, 0, 128)
cyan = clutter.Color(0, 255, 255, 128)
purple = clutter.Color(255, 0, 255, 128)

rect_list = []
rect_list.append(create_rect(red))
rect_list.append(create_rect(green))
rect_list.append(create_rect(blue))
rect_list.append(create_rect(yellow))
rect_list.append(create_rect(cyan))
rect_list.append(create_rect(purple))

stage.connect('button-press-event', on_stage_button_press)
stage.connect('hide', quit)

for r in rect_list:
stage.add(r)

score = clutter.Score()
score.set_loop(True)

timeline_rotation = clutter.Timeline(500)
timeline_rotation.connect('new-frame', on_timeline_rotation_new_frame,
rect_list)
score.append(timeline_rotation)

timeline_scale = clutter.Timeline(500)
timeline_scale.connect('new-frame', on_timeline_scale_new_frame,
rect_list)
score.append(timeline_scale)
score.start()

stage.show()
clutter.main()


2つのTimelineを接続する


pyclutterのREADMEを読むと書いてあるが、Score#appendの引数の順番は、CのAPIと違っている。昨日はこれに気づかなかった。ちゃんとREADMEは読めという話ですね。
これはよりPythonicな書き方をするためらしい。こういうのは今後もあると思われ。
#!/usr/bin/python
# -*- coding: utf-8 -*-

import clutter
import mathhacks

# 回転情報
global rotation
global scale
rotation = 0
scale = 0


def on_timeline_rotation_new_frame(timeline, frame_num, rect_list):
global rotation

rotation += 0.3
rect_list[0].set_rotation(clutter.Z_AXIS, rotation * 5, 0, 0, 0)
rect_list[1].set_rotation(clutter.Z_AXIS, rotation * 4, 0, 0, 0)
rect_list[2].set_rotation(clutter.Z_AXIS, rotation * 3, 0, 0, 0)
rect_list[3].set_rotation(clutter.Z_AXIS, rotation * 2, 0, 0, 0)
rect_list[4].set_rotation(clutter.Z_AXIS, rotation * 1, 0, 0, 0)
rect_list[5].set_rotation(clutter.Z_AXIS, rotation * 0.5, 0, 0, 0)


def on_timeline_scale_new_frame(timeline, frame_num, rect_list):
global scale
scale += 0.01
if scale > 1.0:
scale = 0

scale_amount = mathhacks.smooth_step2(1.0, 2.0, scale)
for rect in rect_list:
rect.set_scale(scale_amount, scale_amount)


def on_stage_button_press(stage, event, *arg):
x = 0
y = 0
(x, y) = (event.x, event.y)
clicked = stage.get_actor_at_pos(clutter.PICK_ALL, x, y)
if clicked == stage:
return
clicked.hide()


def quit(actor, *args):
clutter.main_quit()


def create_rect(color):
rect = clutter.Rectangle(color)
rect.set_size(256, 128)
rect.set_position(128, 128)
rect.set_anchor_point(128, 64)

return rect


clutter.init()
stage_color = clutter.Color(0, 0, 0, 255)
stage = clutter.Stage()
stage.set_size(512, 512)
stage.set_color(stage_color)

red = clutter.Color(255, 0, 0, 128)
green = clutter.Color(0, 255, 0, 128)
blue = clutter.Color(0, 0, 255, 128)
yellow = clutter.Color(255, 255, 0, 128)
cyan = clutter.Color(0, 255, 255, 128)
purple = clutter.Color(255, 0, 255, 128)

rect_list = []
rect_list.append(create_rect(red))
rect_list.append(create_rect(green))
rect_list.append(create_rect(blue))
rect_list.append(create_rect(yellow))
rect_list.append(create_rect(cyan))
rect_list.append(create_rect(purple))

stage.connect('button-press-event', on_stage_button_press)
stage.connect('hide', quit)

for r in rect_list:
stage.add(r)

score = clutter.Score()
score.set_loop(True)

timeline_rotation = clutter.Timeline(500)
timeline_rotation.connect('new-frame', on_timeline_rotation_new_frame,
rect_list)
score.append(timeline_rotation)

timeline_scale = clutter.Timeline(500)
timeline_scale.connect('new-frame', on_timeline_scale_new_frame,
rect_list)
score.append(timeline_scale, timeline_rotation)
score.start()

stage.show()
clutter.main()

火曜日, 1月 19, 2010

ClutterのチュートリアルをPyClutterに翻訳 その1

Mikeforce::HomePageのClutterチュートリアルの和訳をPyClutterでやってみる。

覚えておいてほしいこととして、あくまでのこの記事は Clutter のドキュメントで今現在不足している箇所を補うための「臨時措置」みたいなものだということです。私たちは、もっと広い視野でみた Python を中心とする Clutter のチュートリアルを作成中ですが、それを完成するには2,3ヶ月必要であるとみています。その間は、ここで紹介するチュートリアルで我慢していただき、 Clutter を使ったプログラミングを楽しんで欲しいと考えています。

と書いてあるので、そのうち本気措置が取られる事を期待しつつ、とりあえず前半戦

初めの一歩


黒い枠が出来るだけ。
import clutter

clutter.init()
color = clutter.Color(0, 0, 0, 255)
stage = clutter.Stage()
stage.set_size(512, 512)
stage.set_color(color)
stage.show()

clutter.main()


四角を追加
import clutter

clutter.init()
stage_color = clutter.Color(0, 0, 0, 255)
stage = clutter.Stage()
stage.set_size(512, 512)
stage.set_color(stage_color)

actor_color = clutter.Color(0, 255, 0, 128)
rect = clutter.Rectangle(actor_color)
rect.set_size(100, 100)
rect.set_position(100, 100)

stage.add(rect)
stage.show()
clutter.main()


必要に応じて長方形を描画する


元ネタでは、長方形の描画とstageへの登録を同じ関数内でやっているのだけど、個人的にそれが嫌なので、四角を作るだけにした。
あと、PyClutterの場合、メインのウィンドウを閉じてもプロセスが生き続けてしまうので、それを避けるために、stageのhideシグナルに終了処理をくっつけた。
import clutter

"""ウィンドウを閉じたときに終了するためのclosure"""
def quit(actor, *args):
clutter.main_quit()

"""関数内でaddするのが嫌だったのでrectを作るだけ"
def create_rect(color):
rect = clutter.Rectangle(color)
rect.set_size(256, 128)
rect.set_position(128, 128)

return rect


stage_color = clutter.Color(0, 0, 0, 255)
stage = clutter.Stage()
stage.set_size(512, 512)
stage.set_color(stage_color)

actor_color = clutter.Color(0, 255, 0, 128)
rect = create_rect(actor_color)
stage.add(rect)
# 終了関数を設定
stage.connect('hide', quit)
stage.show()
clutter.main()


アニメーション一歩手前


#!/usr/bin/python
# -*- coding: utf-8 -*-

import clutter


def quit(actor, *args):
clutter.main_quit()


def create_rect(color):
rect = clutter.Rectangle(color)
rect.set_size(256, 128)
rect.set_position(128, 128)

return rect


clutter.init()
stage_color = clutter.Color(0, 0, 0, 255)
stage = clutter.Stage()
stage.set_size(512, 512)
stage.set_color(stage_color)

red = clutter.Color(255, 0, 0, 128)
green = clutter.Color(0, 255, 0, 128)
blue = clutter.Color(0, 0, 255, 128)
yellow = clutter.Color(255, 255, 0, 128)
cyan = clutter.Color(0, 255, 255, 128)
purple = clutter.Color(255, 0, 255, 128)

rect1 = create_rect(red)
rect2 = create_rect(green)
rect3 = create_rect(blue)
rect4 = create_rect(yellow)
rect5 = create_rect(cyan)
rect6 = create_rect(purple)

stage.add(rect1)
stage.add(rect2)
stage.add(rect3)
stage.add(rect4)
stage.add(rect5)
stage.add(rect6)

stage.connect('hide', quit)
stage.show()
clutter.main()


アニメーション


処理をシンプルにするために、四角形をリストに入れて運ぶようにしている。
on_timeline_new_frameの中がかっこ悪いのが気になる。
#!/usr/bin/python
# -*- coding: utf-8 -*-

import clutter

# 回転情報
global rotation
rotation = 0


def on_timeline_new_frame(timeline, frame_num, rect_list):
global rotation
rotation += 0.3
rect_list[0].set_rotation(clutter.Z_AXIS, rotation * 5, 0, 0, 0)
rect_list[1].set_rotation(clutter.Z_AXIS, rotation * 4, 0, 0, 0)
rect_list[2].set_rotation(clutter.Z_AXIS, rotation * 3, 0, 0, 0)
rect_list[3].set_rotation(clutter.Z_AXIS, rotation * 2, 0, 0, 0)
rect_list[4].set_rotation(clutter.Z_AXIS, rotation * 1, 0, 0, 0)
rect_list[5].set_rotation(clutter.Z_AXIS, rotation * 0.5, 0, 0, 0)


def quit(actor, *args):
clutter.main_quit()


def create_rect(color):
rect = clutter.Rectangle(color)
rect.set_size(256, 128)
rect.set_position(128, 128)

return rect


clutter.init()
stage_color = clutter.Color(0, 0, 0, 255)
stage = clutter.Stage()
stage.set_size(512, 512)
stage.set_color(stage_color)

red = clutter.Color(255, 0, 0, 128)
green = clutter.Color(0, 255, 0, 128)
blue = clutter.Color(0, 0, 255, 128)
yellow = clutter.Color(255, 255, 0, 128)
cyan = clutter.Color(0, 255, 255, 128)
purple = clutter.Color(255, 0, 255, 128)

rect_list = []
rect_list.append(create_rect(red))
rect_list.append(create_rect(green))
rect_list.append(create_rect(blue))
rect_list.append(create_rect(yellow))
rect_list.append(create_rect(cyan))
rect_list.append(create_rect(purple))

stage.connect('hide', quit)
stage.show()

for r in rect_list:
stage.add(r)

timeline = clutter.Timeline(60)
timeline.connect('new-frame', on_timeline_new_frame, rect_list)
timeline.set_loop(True)
timeline.start()

clutter.main()


アニメーション アンカーポイントを変更


#!/usr/bin/python
# -*- coding: utf-8 -*-

import clutter

# 回転情報
global rotation
rotation = 0


def on_timeline_new_frame(timeline, frame_num, rect_list):
global rotation
rotation += 0.3
rect_list[0].set_rotation(clutter.Z_AXIS, rotation * 5, 0, 0, 0)
rect_list[1].set_rotation(clutter.Z_AXIS, rotation * 4, 0, 0, 0)
rect_list[2].set_rotation(clutter.Z_AXIS, rotation * 3, 0, 0, 0)
rect_list[3].set_rotation(clutter.Z_AXIS, rotation * 2, 0, 0, 0)
rect_list[4].set_rotation(clutter.Z_AXIS, rotation * 1, 0, 0, 0)
rect_list[5].set_rotation(clutter.Z_AXIS, rotation * 0.5, 0, 0, 0)


def quit(actor, *args):
clutter.main_quit()


def create_rect(color):
rect = clutter.Rectangle(color)
rect.set_size(256, 128)
rect.set_position(128, 128)
rect.set_anchor_point(128, 64)

return rect


clutter.init()
stage_color = clutter.Color(0, 0, 0, 255)
stage = clutter.Stage()
stage.set_size(512, 512)
stage.set_color(stage_color)

red = clutter.Color(255, 0, 0, 128)
green = clutter.Color(0, 255, 0, 128)
blue = clutter.Color(0, 0, 255, 128)
yellow = clutter.Color(255, 255, 0, 128)
cyan = clutter.Color(0, 255, 255, 128)
purple = clutter.Color(255, 0, 255, 128)

rect_list = []
rect_list.append(create_rect(red))
rect_list.append(create_rect(green))
rect_list.append(create_rect(blue))
rect_list.append(create_rect(yellow))
rect_list.append(create_rect(cyan))
rect_list.append(create_rect(purple))

stage.connect('hide', quit)
stage.show()

for r in rect_list:
stage.add(r)

timeline = clutter.Timeline(60)
timeline.connect('new-frame', on_timeline_new_frame, rect_list)
timeline.set_loop(True)
timeline.start()

clutter.main()


続きはまた今度。

日曜日, 1月 17, 2010

PyClutter 33行のHello, World的なコード

PyClutterはClutterのPythonバインド。
基本的な使い方はベースとなっているGtkとあまり変わらない。
import clutter

def main():
stage = clutter.Stage()
stage.set_color(clutter.Color(0xaa, 0xbb, 0xcc, 0xff))
stage.set_size(200, 200)

label = clutter.Text()
label.set_text('clutter')

button = clutter.Rectangle()
button.set_color(clutter.Color(0xcc, 0xbb, 0xaa, 0xff))
button.set_width(100)
button.set_height(100)
button.set_x(50)
button.set_y(50)
button.set_reactive(True)

stage.add(label)
stage.add(button)
stage.connect('button-press-event', change, label)
stage.connect('hide', quit)
stage.show_all()

def change(actor, event, label):
label.set_text('press button')

def quit(actor):
clutter.main_quit()

if __name__ == '__main__':
main()
clutter.main()

日曜日, 1月 03, 2010

スクリプト書き初め2010

「年末年始はスクリプト書く!」という人に触発されて、スクリプト書き初めをやってみました。
実行結果はこのようになります。



以下コード。
pygameでも出来ただろうけど、あえてPyClutterを使っています。
下敷きにしたのは、PyClutterサンプルのflower.py。
先に言い訳を書いておくと、コメントとか一切無いのは書き初めなので一気に書いたから、改行に見苦しい点があるのはpythontidyのせいです。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import clutter
from clutter import CairoTexture
import cairo
import gobject

import sys
import random

BACKGROUND_COLOR = (0xee, 0xee, 0xee, 0xff)


class Snow(CairoTexture):

colors = (
(0.6, 0.7, 0.9, 0.5),
(0.6, 0.7, 1.0, 0.5),
(0.7, 0.9, 0.9, 0.5),
(0.7, 0.7, 1.0, 0.5),
(0.8, 0.7, 0.9, 0.5),
(0.8, 0.9, 1.0, 0.5),
)

def __init__(
self,
x,
y,
translation_velocity,
rotation_velocity,
ground,
):

self.x = x
self.y = y
self.rot = 0
self.v = translation_velocity
self.rv = rotation_velocity
self.ground = ground

CairoTexture.__init__(self, 20, 20)
cr = self.cairo_create()
cr.move_to(0, 0)
cr.rectangle(2, 2, 16, 16)
random_color = Snow.colors[random.randint(0, 5)]
cr.set_source_rgba(*random_color)
cr.paint()

def tick(self, max_width, max_height):
if self.ground - 10 < self.get_y():
return
self.y += self.v
self.rot += self.rv

if self.y > max_height:
self.y = -self.get_height()

self.set_position(self.x, self.y)
self.set_rotation(clutter.Z_AXIS, self.rot, self.get_width()
/ 2, self.get_height() / 2, 0)


class Kakizome(CairoTexture):

def __init__(self):
self.stage = clutter.Stage()
self.stage.set_color(clutter.Color(*BACKGROUND_COLOR))
self.stage.set_size(640, 480)
self.stage.set_title('Kakizome 2010')
self.started = False
self.ground = self.stage.get_height()

self.label = self.create_label('Hello, New Year.')
self.label.set_depth(1.0)
self.stage.add(self.label)

self.snows = list()

self.timeline = clutter.Timeline(500)
self.timeline.set_loop(True)
self.stage.connect('key-press-event', self.on_key_press)

gobject.timeout_add(50, self.tick, self.snows,
self.get_width(), self.stage.get_height())

def create_label(self, message):
label_color = clutter.Color(*BACKGROUND_COLOR)
label = clutter.Text()
label.set_text(message)
label.set_font_name('Mono 32')
label.set_color(label_color)
label_x = (self.stage.get_width() - label.get_width()) - 50
label.set_position(label_x, (self.stage.get_height() / 3) * 2)
return label

def tick(self, snows, height, width):
for snow in snows:
snow.tick(height, width)
if self.ground < 0:
return True

if random.randint(0, 1000) % 125 == 0:
self.ground -= 5

self.fall_snow()

return True

def fall_snow(self):
snow = Snow(random.randint(-10, self.stage.get_width()), -20,
random.randint(1, 5), random.randint(3, 5),
self.ground)
self.stage.add(snow)
snow.set_position(snow.x, snow.y)
self.snows.append(snow)

def run(self):
self.stage.show_all()
self.timeline.start()
clutter.main()

def on_key_press(self, actor, event):
key = event.get_key_symbol()
if key == clutter.keysyms.q:
clutter.main_quit()


if __name__ == '__main__':
app = Kakizome()
app.run()
sys.exit(0)