Ubuntu 11.04 インストール(ソフト編)

というわけで、前回はハードに攻めましたので Ubuntu 11.04 インストール・ソフト編です(?)。。

Unity/Compiz が動作している様子を動画で撮りましたのでインストールしていない方もお楽しみください。 :)

クリーンインストールしました USB HDD にて初期設定から。

Adobe Flash などのサードパーティソフトウェアと、Unity の設定ができる Compiz 設定マネージャ。

sudo apt-get install ubuntu-restricted-extras
sudo apt-get install compizconfig-settings-manager

サードパーティソフトはライセンスをご確認の上インストールを。 CUI からやるとライセンス認証もテキストででます。 TAB とエンターで操作です。

次は Eclipse 動かすために sun-java6 をインストールしました。 まずは Synaptic パッケージマネージャを起動して、設定->リポジトリから Canonical パートナーパッケージにチェック。

ubuntu1104-30

でもって、以下のコマンドでまずは sun-java6-jdk が入ります。

sudo apt-get install sun-java6-jdk sun-java6-plugin
sudo update-alternatives --config java

下の update-alternatives コマンドでおそらく初期状態 OpenJDK に向いている Java を sun-java6 に向ければ準備完了。

あとは適当に Eclipse 展開して実行すれば動くはずです。 本来は /opt とかに入れたいところですが、Linux 版の Eclipse で shared モード動作させるとうまくインストールできないプラグインがでたことがありましたので、ぼくは /home/hiromasa/apps とかに入れています。

でもって、このようなパッケージ外のアプリケーションを入れると Unity ランチャーくんがアイコン表示してくれなかったり、うまくピン留めできなかったりちょっと悲しい感じになります。

この方法であっているか分からないのですが、このような場合、以下の場所に .desktop ファイルを作成してダブルクリック起動するとアイコンとかちゃんとでますので、その状態でピン留めとかするとうまい感じに動くようです。

cat ~/.gnome2/panel2.d/default/launchers/eclipse.desktop
#!/usr/bin/env xdg-open
 
[Desktop Entry]
Version=1.0
Type=Application
Terminal=false
Icon[ja_JP]=/home/hiromasa/apps/eclipse-jee-helios-SR2-linux-gtk/icon.xpm
Exec=/home/hiromasa/apps/eclipse-jee-helios-SR2-linux-gtk/eclipse
Name[ja_JP]=Eclipse JEE
Name=Eclipse JEE
Icon=/home/hiromasa/apps/eclipse-jee-helios-SR2-linux-gtk/icon.xpm

こんな感じに設定ファイルつくると Songbird とかもちゃんとアイコンだせるようになりますぞ。 :D

ubuntu1104-33

うーむ、よしよし。 あとは適当にソフト入れて完了です。

ubuntu1104-31

最後にぴょこぴょこ動く Unity/Compiz を動画でお楽しみください。 :)

 

萌え。(2回目)

Ubuntu 11.04 インストール(外付け USB HDD 編)

半年に一回のお楽しみ、Ubuntu 11.04 がリリースされました。 :)

今回は alpha も beta も入れていなく youtube のスクリーンキャストでみていたのみでした。 GNOME 3 を入れずにつっこんできた噂の Unity は果たして! 楽しみ。

というわけで早速インストールでございます。

まずは Shuttle のデスクトップ PC から。 こちらは 10.10 からのアップデートインストールを試みてみました。 程なく終わり、難なく起動です。

ubuntu1104-10

Unity さんは Compiz 版じゃないのを 10.10 の Netbook Remix で使い続けていたので操作的な違和感はありませんでした。 ワイドスクリーンは左右余ってるでしょ、という感じの UI に仕上がっておりますので 16:9、16:10 そして 1024×768 の低めの解像度の環境でもうまい感じに動くと思います。

一点、Netbook Remix と違うのが左のドックがデフォルトで隠れる動作をすること。 おそらく、高解像度環境では常に出ていた方が便利と思います。 これらは conpizconfig-setting-manager の中の Unity Plugin 画面で変更可能です。(追加インストールします)

ubuntu1104-11

Behaviour タブのところで、Hide Launcher を Naver にすれば隠れなくなります。 また、アイコンの表示方式や大きさなども設定できるようです。 低解像度では 32 アイコンがよさそうです。

Netbook Remix の Unity ではデスクトップ領域があまり活用できませんでしたが、Compiz 版になってファイル置いたり screenlets とか普通に動くようになりましたので便利です。 :)

というわけで、Netbook Remix で使っていた ThinkPad と IdeaPad で動作させていた USB HDD 起動の Ubuntu 10.10 もアップデートしよう、、と思いきや。

インストーラクラッシュ!

実は前々からそうだったのですが、うちの USB 外付け HDD に Ubuntu を入れるのはなかなかの鬼門で、インストーラを起動するマシンによって最後の GRUB インストール時に失敗するという事象が起きていました。

ubuntu1104-04

右の DVDドライブから、左の USB HDD にインストールする、、という感じです。 一度 Ubuntu が入ってしまえば、この USB HDD を別のマシンにつなげばそのまんま OS 起動するという Firefox Sync も Ubuntu One もいらないという素晴らしいシンクロ環境。 気に入っていたのに…。

10.10 はインストールマシン変えるとうまくいったり、HDD を全消去するとうまくいったりしていたのでだましだましやっていたのですが、11.04 はどーやっても、

申し訳ありません。 エラーが発生したために指定の位置にブートローダをインストールすることができませんでした。

となってしまいうまくいきません。 /var/log/syslog をみてもようわからん…。

・・・手を変え品を変え再試行インストール回数は 12回を超える。。

この間、ぼんやりと次の手は浮かんできていたのです。 USB HDD へのインストールは失敗するけど SATA へのインストールは成功するはずなんだ…。

ubuntu1104-01

そして殻を割られるかわいそうな USB HDD くん。(笑)

USB 変換をとってしまえばただの 2.5 インチ SATA HDD。 これを ThinkPad の SATA に移植です。

ubuntu1104-02

持っててよかった ThinkPad。 HDD すぐ抜けるようになっているでございます。 ありがとう。

で、SATA めがけて Ubuntu をインストール。 通常起動、キタ!

これをまた外して、USB HDD に戻して、、ブートしてくれよぅ。 面倒なので裸で(笑)

ubuntu1104-03

キター!

ubuntu1104-00

ubuntu1104-12

萌え。(完)

twitter streaming API への接続

その昔、twitter が Jabber プロトコルをサポートしていたことを覚えている人は何人いるだろうか?(笑)

どうもぼかぁ最新データをとるのにいちいちポーリングするのってのが全般的に好きではなくて twitter も Jabber 復活を心待ちにしていたのですが、果たしていつの日だったかストリーミング API として戻ってきたのでした。 良かった :)

というわけで、API 公開からずいぶんずいぶん経ってしまいましたが、何となく思い立って Groovy からつないでみました。

Java には twitter4j というとてもよくサポートされたtwitter ライブラリがありますので、まずはこちらを利用させていただきます!

Twitter4J – A Java library for the Twitter API

Twitter4J は Twitter API の Java ラッパです。 Twitter4J を使うと JSON や HTTP に詳しくなくても容易に Twitter とインタラクトするアプリケーションを書くことが出来ます。

さて、まず twitter につなぐのに面倒なのが oAuth 。。 とりあえず動作確認したいだけなのにアプリの登録とかしなければならなくあれですが、しょうがないのでしますです。

Twitter / アプリケーションを登録

ここでOAuthを使ったアプリケーションを登録することができます。OAuthは新しい外部アプリケーションの認証システムです。

アプリの登録をすると、consumerKey と consumerSecret がもらえますのでメモして、以下の Groovy ソースに入れて実行してみます。

import twitter4j.*
 
def oAuthConsumer = "入れる"
def oAuthConsumerSecret = "入れる"
 
def twitter = new TwitterFactory().getInstance()
twitter.setOAuthConsumer(oAuthConsumer, oAuthConsumerSecret)
 
def requestToken = twitter.getOAuthRequestToken()
def accessToken = ""
 
println "ブラウザで以下の URL にアクセスして表示された PIN コードを入力してください。"
println " ${requestToken.getAuthorizationURL()}"
System.in.withReader {
    print "PIN コード: "
    accessToken = twitter.getOAuthAccessToken(requestToken, it.readLine())
}
 
println "access.token=${accessToken.getToken()}"
println "access.token.secret=${accessToken.getTokenSecret()}"

実行すると URL がでてきますので、ブラウザにコピって入力して先ほど登録したアプリケーションからのアクセスを自分の twitter アカウントに対して許可してあげます。 そうすると PIN コードでてくるので、こっちのアプリに入力してあげると、今度はアクセストークンが2つもらえます。

コンシューマキー 2 つと、アクセストークン 2 つが揃ったらいよいよアプリをかきます。

ここではストリーミング API を使ってリアルタイムに自分のタイムラインをひろってみます。

import twitter4j.*
import twitter4j.conf.*
 
def consumer = "入れる"
def consumer_secret = "入れる"
def access_token = "入れる"
def access_token_secret = "入れる"
 
def builder = new ConfigurationBuilder()
builder.setOAuthConsumerKey(consumer)
builder.setOAuthConsumerSecret(consumer_secret)
builder.setOAuthAccessToken(access_token)
builder.setOAuthAccessTokenSecret(access_token_secret)
 
def config = builder.build()
def twitter = new TwitterFactory(config).getInstance()
def stream =
    new TwitterStreamFactory(config).getInstance(twitter.getOAuthAccessToken())
 
stream.addListener(new UserStreamAdapter() {
    @Override
    public void onStatus(Status status) {
        def user = status.getUser().getScreenName()
        def text = status.getText()
        println "@${user} ${text}"
    }
})
 
println "Start streaming..."
stream.user()
 
System.in.withReader {
    while((line = it.readLine()) && (line=line.trim()));
}
 
println "Stop streaming and cleanup..."
stream.cleanUp()

じゃんじゃんじゃん。 エンター押すと終了です。

ソケットつなぎっぱなしになりますのでリアルタイムにタイムラインが表示されると思います。 Web より速くでるときもあるみたいですね。 :D

これでたとえば、Ubuntu とかだと notify-send で簡単に画面に通知出せますので、画像ファイル取得とかちょこちょこつけると・・・

stream01

あっという間に通知クライアントのできあがり。 よい。

てなわけで oAuth はちょっと面倒ですが、それ以外は twitter4j と Groovy のおかげでとてもお手軽。 クライアントつくってみてはどうでしょう。

そういえば、オープンソースの twitter クライアントって、コンシューマーキーはどうしているんだろう・・・。

う。

初めての WebGL

ここ 1年くらいのブログを見返しているとずいぶん投稿数が減ったなぁ、と。 こうみえて昔は、毎日更新だったんですよ(笑) 原因は何かの途中経過を書かなくなったことだと思うのですが、それは新しいことをやっていない裏返しなのかも、ということで「初めての WebGL」。。

まずはお勉強でございます。 ちなみにわたくしは、3D とか全然分からないです(笑)

WebGL Lesson 1 – 三角形と四角形 – Hack The WebGL (WebGL勉強会)

ようこそ私の最初のWebGLチュートリアルへ!この最初のレッスンはNeHe OpenGLチュートリアルのNo.2をもとにしています。NeHe OpenGLチュートリアルはゲーム開発者向けの3Dグラフィックスの学習手段として人気です。
今回はWebページ上に三角形と四角形を出す方法を解説します。

大変参考になりますです。

まず分かったのは、WebGL は OpenGL 2.0 ES のラッパーであって OpenGL とは互換がないということです。 以前、ちょっと OpenGL をいじっていたのでそのまま移植できるかなと思ってたのですが、いわゆる固定シェーダがないのですね。

hiromasa.another :o )» Blog Archive » Java + LWJGL + OpenGL で 2D ゲーム

ということでとりだしてきました、 OpenGL の Java ラッパー LWJGL。 OpenGL で古き良き 2D 描画をなんとか再現してやろうかと奮闘中であります。

2.0 ES でレンダリングするには必ずバーテックスシェーダとフラグメントシェーダで描画する必要があるようです。 JavaScript の中に C like な記述が入るのはなかなか興味深い。

webgl01

というわけでいろいろふっとばしますが、なんとか豆腐とテクスチャの貼り付けまではいけました。 ソースはもうちょっと動いてからにしましょう。

 

オチなしのプレッシャー…。

Firefox 4.0 リリース!

結構前から Minefiled で beta を追っていていたのですが beta13 から RC1、2 を経ましてついに Firefox 4.0 がリリースされました。 :) 1.0 がでて喜んでいたのは 2005 年ですので月日が流れるのは早いものです。。

4.0 で最初にぱっと目を引くのは UI の変更で、Tab on Top とかメニューが左上に統合されたり、タブをピンで止めれるようになったりしています。

Linux 版。

firefox402

Windows 版。

firefox401

 

Windows のほうの beta はあまり見ていなかったのですが、途中でタブのデザインが変わったように思います。 正式版いれたときあれ?って思いました。 :)

Ubuntu 10.10 は Firefox 3.5 系なので 4.0 を使うには stable の PPA を入れると良いと思います。

Nattyまで待てない!Ubuntuで今すぐFirefox4.0を使う

さて、我らがUbuntuでは、現行版の10.10Maverickでは残念ながらアップデートが入ってきていません。せっかく高速に便利になったFirefox 4.0が使えないのはもったいないので、10.10でもFirefox 4.0を使えるようにしました。

非常に参考になります!

何度かこのブログでも取り上げていました、新機能の WebGL についてですが、Linux 版については残念ながら NVIDIA プロプライエタリ ドライバ以外はブラックリスト入りの対応になったようです。

しかるに NVIDIA 以外のカードではいじらずには WebGL 表示できません。 無念。 beta の途中までは Intel とかでも動いていたのですが、バグが多かった模様です。

Windows に関しては Intel 内蔵とかでも動くようなので遊んでみると良いかもしれません。

WebGL Experiments

WebGL is a new web technology that brings hardware-accelerated 3D graphics to the browser without installing additional software.To try these WebGL experiments with Google Chrome, please download and install it below.

基本 Chrome デモ用ですがこちらのサイトに続々新作が追加されています。

firefox403

少しインターネットを検索していると、初音ミクさんが踊りだしたりしていました。 面白いのができる予感。 ぼくも空間系のサイトを何かやってみたいなと思っているのですが、OpenGL 勉強しないとですね。

…。 やべっ。

無理矢理のオチ。。。 (IE8 ではでませんな

Groovy と PS3 Media Server プラグイン

主に PS3 向けの DNLA サーバアプリ PS3 Media Server のプラグインを、言語の勉強がてら Groovy でかいてみました。 :)

また、pms のプラグインのつくりかたはあまりインターネット上にドキュメントがないみたいなのでメモも兼ねまして。 まぁこんなことしようする人はソースみれば分かる内容ですが(笑)。。。

PS3 Media Server は Java でできていますので、Groovy の jar をクラスパスにいれてあげれば Groovy でプラグインをかくことができます。 Groovy 言語はプリコンパイルでただの .class にできますので Java との相互運用性は非常に高く、こういうときにとても便利です。

とりあえず、pms3 の trunk を落としてきて lib/groovy-all-1.7.10.jar を入れて、ant かけて pms3.jar の本体を差し替え。 あとはプラグインかくだけ。

以下ソースから追ってつくっていますので、間違えがありましたらご容赦を。

まず作成するプラグインを以下のパッケージに配置。

package net.pms.external

 

画面にルートフォルダを一つ追加する場合は、AdditionalFolderAtRoot を implements してあげたクラスを作成。 で、extends VirtualFolder なクラスをつくって addChild して構築したものを getChild() から戻してあげれば初期設定完了です。

class SamplePlugin implements AdditionalFolderAtRoot {
    
    def root
    
    def SamplePlugin() {
        root = new VirtualFolder("Sample", "")
        root.addChild(new SampleDirectory("Child"))
    }
    
    @Override
    public DLNAResource getChild() {
        return root
    }
    
    @Override
    public String name() {
        return "SamplePlugin"
    }
    
    @Override
    public void shutdown() {
        // nothing to do
    }
    
    @Override
    public JComponent config() {
        // no gui
        return new JPanel()
    }
}

 

extends VirtualFolder な discoverChildren() ではそれが持つ子供(さらにフォルダとかファイルとかストリームとか)を addChild(DLNAResiyrce) で追加していきます。このメソッドはクリックされたときに動きます。

class SampleDirectory extends VirtualFolder {
    
    def SampleDirectory(name) {
        super(name, "")
    }
    
    @Override
    public void discoverChildren() {
        addChild(new SampleDirectory("Child"))
        addChild(new WebAudioStream("Station", "http://127.0.0.1/", ""))
        addChild(new RealFile(new File("/tmp/hoge.mp3"))
    }
}

 

簡単あるね。 上のソースは今そらで書いたものなので動かなかったらすいません。。イメージということで。。

最後に plugin というテキストファイルに起動クラス名(この場合は net.pms.external.SamplePlugin)を記述した上で jar にして pms3 の plugins フォルダに格納してサーバ起動すれば動作するはずです。

 icecast_02

trunk 版の起動シェルはプラグインディレクトリにクラスパス通さなくなっている修正がかかっていますのでそちらも併せて。起動メッセージに Found Plugin がでれば成功。 (ちなみに newInstance() しているのは net.pms.external.ExternalFactory.java です。 うまくプラグインが読まれない場合は確認を)

icecast_01

てなわけで、こちらは動作する例ということで Icecast サーバの実装が出力する yp.xml を解析して PS3 上に表示して再生するプラグインです。 ジャンルでサマってフォルダ分けしています。

package net.pms.external
 
import javax.swing.JPanel
import javax.swing.JComponent
 
import net.pms.dlna.DLNAResource
import net.pms.dlna.WebAudioStream
import net.pms.dlna.virtual.VirtualFolder
 
class IcecastPlugin implements AdditionalFolderAtRoot {
    
    def root
    def icecast
    
    def IcecastPlugin() {
        icecast = new Icecast("http://www.example.com/yp.xml")
        
        root = new IcecastDirectory("Icecast Radio", "", {})
        root.addChild(new IcecastDirectory("Genre", "", { c1 ->
            icecast.getGenre().each {
                c1.addChild(new IcecastDirectory(it, it, { c2 ->
                    icecast.getStationByGenre(c2.query).each {
                        c2.addChild(new WebAudioStream(it.value, it.key, ""))
                    }
                }))
            }
        }))
    }
    
    @Override
    public DLNAResource getChild() {
        return root
    }
    
    @Override
    public String name() {
        return "IcecastPlugin"
    }
    
    @Override
    public void shutdown() {
        // nothing to do
    }
    
    @Override
    public JComponent config() {
        // no gui
        return new JPanel()
    }
}
 
class IcecastDirectory extends VirtualFolder {
    
    def explorer
    def query
    
    def IcecastDirectory(name, query, explorer) {
        super(name, "")
        this.query = query
        this.explorer = explorer
    }
    
    @Override
    public void discoverChildren() {
        explorer(this)
    }
}
 
class Icecast {
    
    def yp
    def ypxml
    
    def Icecast(yp) {
        this.yp = yp
    }
    
    def getStationByGenre(genre) {
        parse()
        def stations = [:]
        ypxml.entry.each {
            if(it.genre.text() == genre) {
                stations[it.listen_url.text()] =
                    "${it.server_name.text()} (${it.bitrate.text()}K)"
            }
        }
        return stations
    }
    
    def getGenre() {
        parse()
        def genres = [:]
        ypxml.entry.each {
            genres[it.genre.text()] = ""
        }
        return genres*.key.sort()
    }
    
    def parse() {
        if(ypxml != null && ypxml.entry.size() != 0) return
        ypxml = new XmlParser().parse(yp)
    }
}

 

Groovy の勉強を兼ねていましたので中途半端に遊んでるソースですいません。 木構造でクロージャ渡しの遅延評価を使って一度にツリーを構築しています。 あとは  XML の解析部分が Groovy っぽい部分でしょうか。 ぼくが分からないだけでもっと良い方法はあることでしょう!

さて、こんな感じのものを Java でかいていたらさすがにぼくでもいらっとしそうですが、Groovy なら気楽に短時間でかけますね。

これは動かして調整して、、たぶん…。

このブログ書く方が時間かかっている!

完。

PS3 と PS3 Media Server

大変な地震が起きてしまいなんだか冷静ではいられない日々が続いていますが、無事でいられた人間がマイナス思考しているのもいけないであろう、ということで力をプラスに変換して大好きなブログ、書きたいと思います。

被災された方が早く普段の生活を取り戻せるよう祈っています。 aka さん無事で良かった。 :)

少し前になるのですがついに我が家に液晶テレビと PS3 がやってきました!

いままであったのは、おそらく最終形態のブラウン管テレビ。。 1080i が写るやつでしたので地デジもちゃんとみれていたのですが、HDMI もついていませんでしたし旧世代感は否めませんでした。

買ったテレビは REGZA さんで、超解像とか LAN 上のディスクに録画できるとか、DNLA で TS みれるとか、RD のときもそうでしたがいろいろ遊べそうなのが選定理由。

追加して PS3 も導入され、ついに 10 年くらいメディアプレイアーになっていた初代 XBOX with XBMC をお休みさせられるときがきました。 PS3 のビデオ再生は噂通り、DVD のアップスキャンも優秀で良い感じです。

ps3001

さて、PS3 も REGZA も XBOX でやっていたように、LAN 内のメディア再生が DNLA により可能です。 ここがキモ。

以前、shiroica さんに教えてもらっていた PS3 Media Player を Cent OS/ Atom サーバに導入していろいろ試していています。 :)

ps3mediaserver

PS3 Media Server is a DLNA compliant Upnp Media Server for the PS3, written in Java, with the purpose of streaming or transcoding any kind of media files, with minimum configuration. It’s backed up with the powerful Mplayer/FFmpeg packages.

PS3 Media Player は Java でできた DNLA サーバアプリケーションで、各種接続機器設定に従い mplayer / mencoder へのパイプから機種にあったストリームを返却して、いろいろなメディアファイルを再生できるつくりになっているようです。 この動作をしてくれるので flac など PS3 が対応していないファイルも再生できるようになります。

いろいろ動画を再生してみましたが PS3 のアップスキャンも効いて初代 XBOX よりパワーアップすることができました。

続いて XBOX はネットラジオの再生でもずいぶん活躍してくれていたのですが、PS3 Media Server もできるかな、、と少し調べていると WEB.inf でちまちま設定はできるのですが、再生できる局とそうでない局があったりいくぶん調子が悪い。。

またネットラジオのディレクトリを読んで、、という動作もできないため XBOX より使い勝手も落ちてしまう感じです。

違う、そうじゃない… by マーチン

…ないものはつくろう精神はこのブログにも!

PS3 Media Server はプラグインで機能を追加できるようなので、うんうんとソースをよみつつ、あ、そか Groovy 使えるんだと jar をつっこみ苦節数時間。

とりゃ!

ps3002

おれの勝ちだ(笑)

ちょっと API のライセンスの関係でソースとか公開できないのです(はず)が、たぶんやり始めればすぐできると思います。  Groovy 使って150 ステップくらいでできました。

こちらのMedia Monkey の DB を読んで返すプラグインが参考になりました。

PS3Mediaserver plugin

PS3Mediaserver has lots of limitations itself, so it is best to try PS3MediaServer on its own before using the plugin.

PS3 のメディア再生はもう枯れたい域に入っているようで安心して使えますね。

XBMC のほうが動画再生中に動かせたり UI もかっこ良かったりするのですが、こちらは後のお楽しみということで、しばらく PS3 で楽しんでみたいと思います。 :D

Apache Tomcat 6.0.32 インストールメモ

すいません、完全に自分用のメモです(笑)。。

Redmine さんを家で動かす(JRuby on Rails 動作)ようになってからローカルサーバで Apache Tomcat が常時起動になりましたが、 そのバージョンが 6.0.32 に上がっていましたのでアップデートしてみました。 CentOS 5.5 でデーモン起動しています。

こういうの Redmine の wiki に書いておいているのですが、Tomcat アップデート中は Redmine みれないのでこちらに。。(笑)

IMG_0097

まずは動作環境。

$ uname -a
Linux localhost.localdomain 2.6.18-194.32.1.el5 #1 SMP Wed Jan 5 17:53:09 EST 2011 i686 i686 i386 GNU/Linux
$ java -version
java version "1.6.0_21"
Java(TM) SE Runtime Environment (build 1.6.0_21-b06)
Java HotSpot(TM) Server VM (build 17.0-b16, mixed mode)

いままで全然気が付かなかったのですが、Linux 版の Java はデフォルト Server VM モードであがるんですね。 Windows は Client VM がデフォルトであがるので、Linux でも Server VM 使うように昔から引数設定していましたが、、実は不要だったようです。

てなわけで Tomcat ダウンロードしてデーモン起動する jsvc をつくって入れるまで。 /opt/tomcat6 にいれています。 tomcat ユーザは作成のこと。

$ sudo /etc/init.d/tomcat6 stop
$ cd /opt
$ sudo wget http://ftp.jaist.ac.jp/pub/apache/tomcat/tomcat-6/v6.0.32/bin/apache-tomcat-6.0.32.tar.gz
$ sudo tar zxvf apache-tomcat-6.0.32.tar.gz 
$ sudo mv apache-tomcat-6.0.32/ tomcat6/
$ sudo chown -R tomcat:tomcat tomcat6/
$ sudo cp /opt/tomcat6/bin/commons-daemon-native.tar.gz /root
$ sudo su - root
# cd
# tar zxvf commons-daemon-native.tar.gz
# cd commons-daemon-1.0.5-native-src/
# ./configure --with-java=/usr/java/default/
# make
# cp jsvc /opt/tomcat6/bin/
# chown tomcat:tomcat /opt/tomcat6/bin/jsvc
# /etc/init.d/tomcat6 start
# /etc/init.d/tomcat6 stop
# cd /opt/tomcat6/conf/Catalina/localhost/
# vi redmine.xml
# cp redmine.xml redmine.xml.org
# chown tomcat:tomcat *
# chmod 644 *
# /etc/init.d/tomcat6 start

ちなみに、redmine.xml はコンテキストルートと .war のパス設定のみ。

$ cat /opt/tomcat6/conf/Catalina/localhost/redmine.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/redmine" docBase="/home/apache/redmine/redmine.war" />

デーモン起動用の init.d シェル。

$ cat /etc/init.d/tomcat6 
#!/bin/sh
#
# chkconfig: - 80 20
# description: jsvc
 
# Source function library.
. /etc/init.d/functions
 
JAVA_HOME=/usr/java/default
CATALINA_HOME=/opt/tomcat6
TOMCAT_USER=tomcat
TMP_DIR=/tmp
CATALINA_OPTS=
CLASSPATH=\
$JAVA_HOME/lib/tools.jar:\
$CATALINA_HOME/bin/commons-daemon.jar:\
$CATALINA_HOME/bin/bootstrap.jar
PIDFILE=/var/run/tomcat.pid
LOCKFILE=/var/lock/subsys/tomcat
DAEMON=$CATALINA_HOME/bin/jsvc
 
start(){
    #
    # Start Tomcat
    #
 
    echo -n "Starting tomcat6: "
    $DAEMON \
    -pidfile $PIDFILE \
    -user $TOMCAT_USER \
    -home $JAVA_HOME \
    -Dcatalina.home=$CATALINA_HOME \
    -Djava.io.tmpdir=$TMP_DIR \
    -outfile $CATALINA_HOME/logs/catalina.out \
    -errfile '&1' \
    $CATALINA_OPTS \
    -cp $CLASSPATH \
    org.apache.catalina.startup.Bootstrap
 
    #
    # To get a verbose JVM
    #-verbose \
    # To get a debug of jsvc.
    #-debug \
    RETVAL=$?
    if [ $RETVAL = 0 ]; then
        echo_success
        touch $LOCKFILE
    else
        echo_failure
    fi
    echo
}
 
stop(){
    #
    # Stop Tomcat
    #
    echo -n "Shutting down tomcat6: "
    $DAEMON \
    -stop \
    -pidfile $PIDFILE \
    org.apache.catalina.startup.Bootstrap
    RETVAL=$?
    if [ $RETVAL = 0 ]; then
        echo_success
        rm -f $PIDFILE $LOCKFILE
    else
        echo_failure
    fi
    echo
}
 
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    status)
        status $DAEMON
        RETVAL=$?
        ;;
    *)
        echo $"Usage: jsvc {start|stop|restart|status}"
        exit 1
        ;;
esac

Apache httpd と Apache Tomcat をつなぐ proxy_ajp.conf。

$ cat /etc/httpd/conf.d/proxy_ajp.conf 
 
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
 
#
# When loaded, the mod_proxy_ajp module adds support for
# proxying to an AJP/1.3 backend server (such as Tomcat).
# To proxy to an AJP backend, use the "ajp://" URI scheme;
# Tomcat is configured to listen on port 8009 for AJP requests
# by default.
#
 
# 
# Uncomment the following lines to serve the ROOT webapp
# under the /tomcat/ location, and the jsp-examples webapp
# under the /examples/ location.
#
#ProxyPass /tomcat/ ajp://localhost:8009/
#ProxyPass /examples/ ajp://localhost:8009/jsp-examples/
 
ProxyPass /redmine ajp://localhost:8009/redmine

Tomcat と全然関係ないですが、fastladder を動かしている passenger.conf。

$ cat /etc/httpd/conf.d/passenger.conf 
LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.2.15/ext/apache2/mod_passenger.so
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.2.15
PassengerRuby /usr/bin/ruby
 
<VirtualHost *:8081>
   ServerName localhost.localdomain
   DocumentRoot /opt/fastladder/public 
   <Directory /opt/fastladder/public>
      AllowOverride all
      Options -MultiViews
   </Directory>
</VirtualHost>

さらに関係ないですが、Redmine とつないでいる subversion.conf。

$ cat /etc/httpd/conf.d/subversion.conf
 
LoadModule dav_svn_module     modules/mod_dav_svn.so
LoadModule authz_svn_module   modules/mod_authz_svn.so
 
#
# Example configuration to enable HTTP access for a directory
# containing Subversion repositories, "/var/www/svn".  Each repository
# must be readable and writable by the 'apache' user.  Note that if
# SELinux is enabled, the repositories must be labelled with a context
# which httpd can write to; this will happen by default for
# directories created in /var/www.  Use "restorecon -R /var/www/svn"
# to label the repositories if upgrading from a previous release.
#
 
#
# To create a new repository "http://localhost/repos/stuff" using
# this configuration, run as root:
#
#   # cd /var/www/svn
#   # svnadmin create stuff   
#   # chown -R apache.apache stuff
#
 
<VirtualHost *:8082>
   <Location />
      DAV svn
      SVNParentPath /home/apache/svn
      SVNListParentPath on
      DavDepthInfinity on
      Order deny,allow
      Deny from all
      Allow from 127.0.0.1
      Allow from 192.168.0.0/24
      AuthType Basic
      AuthName "Authorization Realm"
      AuthUserFile /home/apache/passwd/.htpasswd 
      Require valid-user
   </Location>
</VirtualHost>

以上。

すいません、すいません。。

Firefox 4.0 beta と WebGL

Linux 版の Firefox 4.0 も beta11 まできまして、だいぶ良い感じに動くようになってきました。 最初はテキストボックスのキー入力がやたら遅かったり、タブの描画がおかしかったりなかなかのベータ感だったのですが、もう常用しても大丈夫な感じです(といっても当然テスト用です)

Linux 版の Firefox ってちょっと特殊で GTK のテーマをそのまま持ってくるようにつくってあります。 なので4.0 で特徴的なウインドウフレームと閉じるの統合とか、オレンジ色の右上とかはまだありません。 この辺をどうするのか興味深いですね。 :)

firefox10

そんな 4.0 の新機能の一つ WebGL、まだ Intel GPU 系が未対応のあるみたいですが、結構面白いです。 Chrome さんも 9.0 で標準 enable になってみたいですね。  Firefox 4.0 も beta9 だったか 10 だったかで標準 enable になったと思います。

Chrome 9.0 か Firefox 4.0 beta (+OpenGL 対応カード)を使っている方は以下のサイトでデモを楽しむことができます。

WebGL Experiments

WebGL is a new web technology that brings hardware-accelerated 3D graphics to the browser without installing additional software.To try these WebGL experiments with Google Chrome, please download and install it below.

一応、Chrome デモ用のサイトですが、ほとんどが Firefox 4.0 でも問題なく動作するようです。

webgl01

WebGL は JavaScript 経由で PC グラフィックカードの OpenGL ES API を呼び出すことができます。 ぱらっとみる限り 1:1 の薄いラッパーのようです。 たぶん OpenGL 知っている方ならすぐ描画できると思います。

OpenGL ES は iPhone とか Android 機でも使われている OpenGL のサブセットです。

webgl02

webgl03

サブセットとはいえ、プログラマルシェーダをカードに送り込んだりもできますので表現力があります。

既に JavaScript のフレームワークもいくつかでているようです。

GLGE WebGL Library/Framework

GLGE is a javascript library intended to ease the use of WebGL; which is basically a native browser javascript API giving direct access to openGL ES2, allowing for the use of hardware accelerated 2D/3D applications without having to download any plugins.

サイトにはなんだか市販ゲームのようなスクリーンショットもみえますね。 :)

webgl04

対応ブラウザは今のところ Webkit 系と Gecko 系になると思いますので、全ブラウザ対応とはいきませんがワンポイントで対応していればすごくなる的な使い方はできるのではないかと思います。 たとえば、このサイトの右の kougaburari のところとか 対応していれば OpenGL で描画してみたりしてみたりですね!

速くなったとはいえまだまだ JavaScript に性能はくわれちゃうと思いますが、シェーダ含めてローカル資源を活用できるという意味で面白い技術です。 :D

Groovy と GUI アプリケーション

たまに作業の関係で OS ネイティブの GUI アプリケーションを作りたくなる時があります。 適当に自分用につくったコマンドラインベースのものが "ウケ” がよくて GUI に昇格させてみんなに使ってもらう、なんてときですね。 :)

加えてぼくは普段 Linux を使っていますが、折角なのでたまに使う Windows でも同じもの動かしたいなんて要求が加わってくると使う環境は絞られてきて、、 GTK + スクリプト系言語とか Mono とか Java + Swing とかで、、いろいろやってみましたが一番簡単にランタイム環境を用意できて綺麗に動かせるのは Java + SWT ではないかと思います。

というわけで、SWT。

しかも SWT あまり分かっていないのに、これを Groovy の groovy-swt モジュールを使って呼び出してみました。 …分からないことだらけで大変(笑)

Groovy – GroovySWT

GroovySWT is a wrapper around SWT, the eclipse Standard Widget Toolkit. It allows you to easily write Eclipse SWT applications by using Groovy’s builder mechanism.

これが何かといえば、Groovy お得意の動的言語の機能をつかって、GUI のツリーを Groovy 記述で構築してしまおうというものです。

GUI コンポーネントを扱ったことがある方なら分かりますが、これらは親子関係とかいろいろ大変ですのでこれを解決しようという動きです。 XML 定義に Groovy の制御構文が使える、というイメージで扱うのがよさそうです。

ちなみに、GroovySWT のダウンロードですが、現在あろうことかリンクが切れていますのでリポジトリからダウンロードします。

Revision 21442: /trunk/groovy/modules/groovy-swt/dist

groovy-swt-0.5-examples.zip

groovy-swt-0.5-windows-all.jar

groovy-swt-0.5-without-swt.jar

without-swt のほうがうまいこと swt だけ除いてある jar になっていますので、Windows 以外の場合は without と各機種にあった swt をいっしょにクラスパスに通しておきます。

GroovySWT 0.5 時点での SWT 依存は 3.5 になっていましたので以下からダウンロードできます。(trunk のコミットコメントみると 3.5.1 でもよさそうな感じです)

Eclipse Project

swt-3.5-win32-win32-x86.zip
swt-3.5-win32-win32-x86_64.zip
swt-3.5-wpf-win32-x86.zip
swt-3.5-win32-wce_ppc-arm-j2se.zip
swt-3.5-win32-wce_ppc-arm-j2me.zip
swt-3.5-gtk-linux-x86.zip
swt-3.5-gtk-linux-x86_64.zip
swt-3.5-gtk-linux-ppc.zip
swt-3.5-motif-linux-x86.zip
swt-3.5-gtk-solaris-sparc.zip
swt-3.5-gtk-solaris-x86.zip
swt-3.5-motif-solaris-sparc.zip
swt-3.5-motif-hpux-ia64_32.zip
swt-3.5-photon-qnx-x86.zip
swt-3.5-motif-aix-ppc.zip
swt-3.5-cocoa-macosx.zip
swt-3.5-cocoa-macosx-x86_64.zip
swt-3.5-carbon-macosx.zip

各 OS の環境に合わせた x32 とか x64 とか使えばOKです。 Windows は WPF 版なんかが目を引きますね。 :)

commons-logging-1.1.1.jar も動作時に class not found したので入れました。 swt.jar と groovy-swt-0.5.without-swt.jar とあとは Groovy の jar を入れれば準備OKです。

またこれを使ってプログラムかくにはクラスライブラリのソースコード必須です。 swt と groovy-swt のソースはダウンロードして jar にアタッチしておきましょう。(まずは groovy.swt.SwtBuilder からみると良さそうです。あとは SWT のコンポーネントソース見てプロパティ設定していきます)

ということでこの状態でから始めたのですが、、

どーやってもメニューが追加できない!!

サンプルもうまく動いていない模様。  ここの解明が疲れました。。

どうやら groovy-swt のライブラリに不具合があるようです(たぶん)。

これであっているかどうかな上にひどいコードですが、以下のようにパッチ。。(早く動かしたくて手抜きしたの図)

しかも diff 逆にとってしまったのはご愛嬌。。 + と – がさかさまです(笑)

Index: WidgetFactory.java
===================================================================
--- WidgetFactory.java    (revision 5)
+++ WidgetFactory.java    (revision 2)
@@ -119,19 +119,14 @@
                                 Object[] arguments = { parent, new Integer(style) };
                                 return constructor.newInstance(arguments);
                             }
+                            // lets try to find the constructor with 1
+                            // arguments
+                        } else if (types.length == 1
+                                && types[0].isAssignableFrom(parent.getClass())) {
+                            Object[] arguments = { parent };
+                            return constructor.newInstance(arguments);
                         }
                     }
-                    // lets try to find the constructor with 1
-                    // arguments
-                    for (int i = 0, size = constructors.length; i < size; i++) {
-                        Constructor constructor = constructors[i];
-                        Class[] types = constructor.getParameterTypes();
-                        if (types.length == 1
-                                && types[0].isAssignableFrom(parent.getClass())) {
-                            Object[] arguments = { parent };
-                            return constructor.newInstance(arguments);
-                        }
-                    }
                 }
             }
             return beanClass.newInstance();

SWT の org.eclipse.swt.widgets.Menu は 2引数コンストラクタがあって parent と style が設定できて、parent が Shell オブジェクトで style が SWT.BAR のときにメニューとしてはりつくと思うのですが、パッチ前の処理では 1引数コンストラクタを先に見つけてしまうため、style なしで new されてうまくメニューがでないという不具合のようです。(たぶん他の Widget は 2引数のコンストラクタが上のほうに定義されているのでしょう)

さて、そんなこんなで以下のつくったソースで動作させてみる。

変数定義の位置がおかしいとか大文字小文字が混在しているとかは気にしない方向で。  万が一動かしてみたい奇特な方がいらっしゃいましたら、画像のところはコメントアウトしてください。 :)

import groovy.swt.SwtBuilder
import org.eclipse.swt.layout.GridData;
 
class Gonswt {
 
   def shell
   def sashForm1
   def builder
   def tab
 
   def run() {
      builder = new SwtBuilder()
      shell = builder.shell (text:'Groovy on SWT', size:[410, 600], location:[300,200]) {
         menu(style:"BAR") {
            menuItem("バインダー" , style:"CASCADE") {
               menu( style:"DROP_DOWN") {
                  menuItem(style:"PUSH", "&Open file")
                  menuSeparator()
                  menuItem(style:"PUSH", "E&xit"){
                     onEvent('Selection'){
                        shell.dispose()
                     }
                  }
               }   
            }
            menuItem("焼きそばん" , style:"CASCADE") {
            }
         }
         gridLayout()
         composite() {
            rowLayout()
            toolBar( style:"FLAT, WRAP, RIGHT") {
               toolItem(style:"push", "再チャレンジ") {
                  image( src:'resource/item1.png' )
               }
               toolItem(style:"push", "里に帰ろう") {
                  image( src:'resource/item2.png' )
               }
            }
         }
         composite(layoutData:gridData(horizontalSpan:3
            , horizontalAlignment:GridData.FILL
            , verticalAlignment:GridData.FILL
            , grabExcessHorizontalSpace:true
            , grabExcessVerticalSpace:true)) {
            fillLayout()
            sashForm1 = sashForm( style:"vertical") {
               tab = cTabFolder( id: 'myTabs', tabHeight:28, simple:false, style:"BORDER") {
                  fillLayout()
                  //gridData( style:'fill_both')
                  cTabItem( 'タイムマシーン', style:'none') {
                     table(linesVisible:true, headerVisible:true, style:"V_SCROLL") {
                        tableColumn("食べたい", width:80)
                        tableColumn("食べちゃいたい", width:60)
                        10.times {
                           tableItem(["", "ほげほげ"]) {
                              image:image( src:'resource/item3.png' )
                           }
                           tableItem(["", "もげもげ"]) {
                              image:image( src:'resource/item4.png' )
                           }
                           tableItem(["", "ほえほえ"]) {
                              image:image( src:'resource/item5.png' )
                           }
                        }
                     }
                  }
                  cTabItem( 'マンション', style:'none') {
                     text( style:'border, multi, v_scroll, h_scroll', 'Content for Tab1' ) 
                  }
                  cTabItem( 'ダイレクトショッピング', style:'none') {
                     text( style:'border, multi', 'Content for Tab2' ) 
                  }
               }
               composite( style:"none" ) {
                  fillLayout()
                  text( style: "border, multi, wrap")
                  }
            }
            // 2つの weight を決める
            sashForm1.weights = [90, 10]
            // デフォルト表示タブ
            tab.setSelection(0)
         }
         composite(style:"BORDER") {
            rowLayout()
            toolBar( style:"FLAT, WRAP, LEFT") {
               toolItem(style:"push", "ラーメンバー")
            }
         }
      }
 
      // fillLayout のときは縮められるので pack を false にする
      shell.doMainloop(false)
   }
 
   public static void main(String[] args) {
      new Gonswt().run();
   }
}

とりゃ、実行!

Linux 版。

groovy30

Windows 版。

groovy31

Mac 版。 は、残念ながら手元に機械がないのでできません(笑)

てなことで、いい感じでネイティブ描画されて同じように表示されているのが分かります。 可変ウインドウもばっちりです。 斜めタブは Eclipse でおなじみの CTabFolder 。

自分で使いそうな GUI 部品はだいたい入れてみて動いたので、この後は知恵と勇気でなんとかいけそうです。。 間違ってるかもですが。。

まぁ正直なところ SWTBuilder 使わなくても当然 Groovy からは SWT を直接呼べるのでそっちでもいいのですが、これはお遊びということで。 ちなみに、JFace の Builder もありますので、そちらを使えばコンポーネント・データバインディングを使うことができます。

一応描画ができるようになったので、あとはイベントリスナーとスレッド系の操作が分かればなにかつくれそうです。 Groovy でやると確かにお手軽感あります!

もうちょっとやってみます。 :)