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 でやると確かにお手軽感あります!

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

最近のスクリプト言語

といっても全然最近ではないのですが。 :)

前のエントリでも書きましたが恥ずかしながら Ruby とかやったことがなく、実はいつだったか Ruby のソースをみたときに処理は分かれど、ライブラリの中身がどうやっているのか理解できず、ショックで引退を考えたことがありましたので最近ようやく勉強を始めました(笑)

ちょっと仕事に近いところというところで、Ruby じゃなくて Groovy でやってます。

DVC00169

Groovy In Action は絶版になっているのか Amazon ですごい値段がついていましたが、ジュンク堂で無事ゲット。 2008 年の本なのでぼくがみても現行バージョンと変わっているなと思う点もありますが(HashMap が LinkedHashMap になっている等)、それほど困ることはなさそうです。 この本は技術書としてもとても面白かったです。 :)

Groovy はマップ・リスト操作、動的系の機能とクロージャなどのシンタックスを限りなく最小限に抑えている他、JDK にリフレクションで追加する形でクロージャを用いて処理を差し込むパターンのメソッドが多数用意してあるため、ソースから冗長な記述を削除できすっきりとしたソースをかくことができるようです。

というわけで Groovy In Action を読んで仕掛けが何となく分かったので、試しに RSS から画像を取得してファイル保存するプログラムをかいてみました。

// @Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.5.1')
import groovyx.net.http.HTTPBuilder
import static groovyx.net.http.Method.*
import static groovyx.net.http.ContentType.*
 
rssUrl = "http://feedblog.ameba.jp/rss/ameblo/nakagawa-shoko/rss20.xml"
pUrl  = /<img [^>]*src\s*=\s*[\"']?([^\"'> ]+.jpg)/
pFile = /([^\/]+?\.jpg)$/
 
new HTTPBuilder(rssUrl).request(GET, XML) {
   response.success = { res, rss ->
      rss.channel.item.each {
         it.description.text().eachMatch(pUrl) {
            filename = it[1].toURI().path =~ pFile
            new HTTPBuilder(it[1]).request(GET, BINARY) {
               response.success = { res2, image ->
                  new File("./file/${filename[0][0]}").bytes = image.bytes
               }
            }
         }
      }
   }
}

もうちょっと短く書く方法もあるとは思うですが、例えば PHP でかいた場合と違って、http アクセス失敗とか File のオープンクローズとかの処理がソース上に現れていないにもかかわらず、これでうまくいってしまうであろうところが良いですね。

XML パースにはダイナミックランゲージの機能が使われているのが分かります。 あとは String の eachMatch にクロージャ渡せるとか便利です。

  • メソッドの引数の括弧は省略できる。 また、一番外側の引数がクロージャだった場合は括弧にいれなくてOK。
  • インスタンスのフィールドは getter/setter が勝手に生成され、プロパティみたいにフィールド名かけばアクセスできる。

他にもコンストラクタにマップ渡すとフィールドを key/value で初期化できるとか、その際のマップの記述は [] つけなくていいとか、なんだか知らないとぱっと見分からないことでいっぱいだったりするのですが、慣れると便利そうです。

動的型付け、動的言語機能は IDE がほぼ無力になるのでドキュメントとにらめっこするのがちょっと大変ですし、ランタイムエラーをやっぱり出しがちですが、どこで苦労するかのバランスは悪くないように思いました。

というわけで実行。

groovy10 

わーい。 とれた。

…引退します。。(笑)

2011 年スタート!

気が付けば 2010 年も終わりまして、2011 年がスタートしよりました。 あけましておめでとうございます!。

2010 年はお仕事先が何回か変わったり、WordCamp Yokohama、OSC 北海道以降いろいろな方にお会いすることができたり、刺激が多かった年だったように思います。 :)

まぁまぁ長いお付き合いの方たちは薄々気が付いていると思いますが、変化はあれど相変わらず性格はひろまさです(いいんだか悪いんだか、、)、、今年もよろしくお願いいたします!。

せっかくブログっぽい書き出しなので、今年やってみたいことなど。

一応変化の速いコンピュータ業界にいますので、たまに勉強しとかないと置いてかれちゃうのですが、まずは今さらで恥ずかしながら、近代的な Lightweight Language を理解していこうかと思います。

C# とかもこの辺の言語の要素を取り入れて進化していますので、そろそろ本職にも登場してくるんじゃないかなというイメージを持っています。

DVC00143

あとは、、趣味のコンピュータとして、OpenGL とか SWT とか E4/XWT とかその辺を使って練習がてら LL からめて何かつくってみたいです。

さて、今年は WordPress が商用サイト向け CMS として躍進した印象を肌で感じました。 ぼくは Web 制作のほうは全然詳しくないので、既に役立つものをつくるのも役立つお話をするのもできなくなっている気もしているのですが、そこはマイワールドひろまさくん。 面白いこと見つけたらやってみる、相変わらずの感じで行こうと思います。 :)

もてるプログラマーに!

というわけで、今年もこんな感じです(笑)

みなさんにとって良い年でありますように。 今年もよろしくお願いいたします。 :D

XBMC 10.0 リリース!

毎回バージョンアップを楽しみにしているオープンソースのひとつ、XBMC のバージョン 10.0 が先日ついにリリースされました!。 :D

XBMC はもともと初代 XBOX をハックして動作させるメディアプレイヤーでしたが、最近は多くのプラットフォーム向けにリリースがされており、また固定的なメディアプレイヤーアプリケーションとしてだけではなく、いわゆる 10フィートUI を構築する総合的なプラットフォームを目指して開発が進められているように感じます。 です。

XBMC 10.0 | XBMC

It’s been a LONG time coming. Too long. But here it is.

今回のバージョンアップでは、画面を構築するスキン、機能を拡張するアドオンをリポジトリから選択してダウンロード、実行する環境が整ったのが一番目をひくところです。 これらは、XBMC 内部にもつ Python エンジンで動作し、これが XBMC のキモの部分だと思います。

というわけで、さっそく手元の Ubuntu 10.10 で動作させてみました。 PPA にありますので、xbmc リポジトリ追加ですぐインストールできます!

xbox1001

 xbox1002

かっこよすなぁ。 かっこよすなぁ。 スキンはいろいろありますので、10.0 からの機能をつかっていろいろ試してみるとよいと思います。

ちなみに、テレビで動かすとこんな感じになります。 これは、うちの初代 XBOX 版、、なので 9 系です。 残念ながら XBOX 版は既にファイナルバージョンとなっていますが、完成されたアプリケーションだと思います。

xbox1003

16:9  系のモニタをもつネットブックに入れれば、ポータブルメディアプレイヤーに早変わり。 モニタが立ってますので、ごろ寝でアニメみるのにぴったり?(笑)

xbox1004

今回のバージョンから動画再生支援の対応が増えていますので、最近のネットブックだと GPU の力も借りられるかもしれません。

さて、XBMC に最初にさわったのは、、たしか 6年くらい前で当初からすごくパワーを感じるソフトウェアでしたが、まさかここまで化けるとはっ。

オープンソースのリリースといえば Firefox 1.0 のときもちょっと感動しちゃいましたが、XBMC も今後とも追いかけていきたいと思います。

Redmine 1.0.5 + JRuby + Tomcat6 デプロイ

最近、主にローカル Wiki として活躍してくれている Redmine が 1.0.5 にアップデートされましたので追従してみます。 セキュリティーフィックスも含まれるとのことです。

1.0.5 より i18n で必須 gem が追加になっていますので、JRuby + Tomcat デプロイ時は設定が1つ変わりますのでメモがてら。 :)

Redmine 1.0.5 bug/security fix リリース | Redmine.JP

12月23日(日本時間)、Redmine 1.0.5がリリースされました。

Redmine 1.0.4に対して11個の修正・3個の脆弱性対策が行われています。

Redmine 1.0.5には脆弱性の修正も含まれているため、Redmineオフィシャルサイトでは全てのRedmineユーザーに対して最新版へのアップグレードを呼びかけています。

gem 追加について。

インストール・アップグレード時の注意

Redmine 1.0.5より、Rubyの国際化ライブラリi18nのバージョン0.4.2が実行時に必要です。インストール・アップグレードに先立ちサーバ上で以下のコマンドを実行してi18n 0.4.2をインストールしてください。

gem install i18n -v=0.4.2

というわけで、 JRuby で動かしている場合は、

$ sudo jruby -S gem install i18n –v=0.4.2

こういう感じで gem を追加です。

でもって、warble の config に依存 i18n を追加します。

# config を redmine 用に修正(一番したに追加)
sudo vi config/warble.rb 
config.dirs = %w(app config lib log vendor tmp lang)
config.gems << "activerecord-jdbcpostgresql-adapter" 
config.gems << "i18n" 
config.gem_dependencies = true
config.webxml.rails.env = 'production'
config.gems["rack"] = "1.0.1" 

これで、 sudo jruby -S warble でできた war を Tomcat とかにデプロイすれば動作するハズです。 :)

redmine20 

参考、リンク。

hiromasa.another » Blog Archive » Redmine を Tomcat6 にデプロイ

hiromasa.another :o )» Blog Archive » 年末のデータバックアップ

 

がってん、がってん。

年末のデータバックアップ

いつの間にか 12月ということで、部屋の掃除もせずにデータのお掃除を(笑)。

ちょっと放っておくと HDD はなんだかよく分からないファイルであふれるものですが、こちらの整理とバックアップを少々。 今回はバックアップ用に Dropbox を使ってみました。

ぼくは普段使いの PC についてはほとんどデータを入れていなくて、いつ壊しても良いようになっています。 というか、OS 入れ替えをよくやる、というか入れ替えが好きなのでその準備が常にされているというのが真相です(笑)

というわけでそれ用に別にローカルサーバがたっていて、以下のデータが保管されています。

  • 通常ファイル用 samba
  • IMAP でつなげる Maildir
  • ソースコードをコミットする Subversion
  • そのプロジェクトの資料とかを管理する用に Redmine

ちゃんとまじめに上記に登録しておけば使っている PC はいつでもフォーマットできる状態という感じです。 メールとかはサーバ側でとっているのでそっとしておけばいいですが、ソースの Subversion 登録を最近サボっていたのでまずはここから。

サボライズ。(←懐かしい)

登録後のリポジトリをお見せしたいところですが、あぶない水着もあるのでちょっと控えておきましょう。 :)

あとデータと言えば、ここコアサバ。 ブログのデータ。 こいつは rsync で持ってきています。

一応ローカルサーバは RAID1 になっていますが、バックアップという意味の断面はありませんのでどうしようか思案して、Dropbox に転送してみることにしました。

ワークステーションの PC に Dropbox を入れて、監視ディレクトリに各サーバからバックアップデータを rsync するシェルを作成。

とりゃ!

oosouji01

めでたく世界のどこかにバックアップされました。 これで札幌に何かあっても安心です(笑)

ローカルサーバ の Subversion、Redmine Postgres、Redmine File、コアサバの MySQL、アップロードファイルが対象になっています。

Dropbox は LAN 内にクライアントをみつけると、そちらに LAN Sync するのでさらに複数の HDD に複製がつくられます。 何か Dropbox 本来の使い方と違う気もしますが、良いことにしましょう。 :)

いまはカレントしかやっていないですが、履歴をもたせてもいいかもですね。 バックアップタイミングはシェルを手動で起動した時点ということになります。 簡単な運用でバックアップとれるので気に入っています。

さて履歴といえば(全然バックアップと関係ないですが)、なにかプログラム書いたときに Redmine の Wiki にメモをちょっととっていたりするのですが、これがなかなか役に立ちます。 何かつくっても数ヶ月もすると忘れるので。。 心のバックアップ。。

oosouji02

というわけで、今後も活躍してもらおうと Redmine のバージョンアップも実施。 1系の正式版 1.0.1 を入れていましたが、先月末で 1.0.4 まで上がっているようです。

oosouji03

以下、アップデートメモ。 JRuby 化して Tomcat で動かしています。

cd /opt
# 新しいバージョンの tar.gz 落として展開
sudo wget http://rubyforge.org/frs/download.php/73457/redmine-1.0.4.tar.gz
sudo tar zxvf redmine-1.0.4.tar.gz
rm *.tar.gz
cd redmine-1.0.4
# 前のバージョンの config をコピー
sudo cp ../redmine-1.0.1/config/database.yml ./config/
# 秘密鍵作成(config/initializers/session_store.rb)
sudo jruby -S rake generate_session_store
# DB マイグレーション
sudo jruby -S rake db:migrate RAILS_ENV="production" 
# warble の config 作成
sudo jruby -S warble config
# config を redmine 用に修正(一番したに追加)
sudo vi config/warble.rb 
config.dirs = %w(app config lib log vendor tmp lang)
config.gems << "activerecord-jdbcpostgresql-adapter" 
config.gem_dependencies = true
config.webxml.rails.env = 'production'
config.gems["rack"] = "1.0.1" 
# war ファイル作成
sudo jruby -S warble
# tomcat 停止
sudo /etc/init.d/tomcat6 stop
# 今のバージョンの war を一応退避
sudo cp -p /home/apache/redmine/redmine.war /home/apache/redmine/redmine-1.0.1.war
# war を新バージョンに差し替え
sudo cp -p /opt/redmine-1.0.4/redmine-1.0.4.war /home/apache/redmine/redmine.war
# tomcat からアプリ削除
sudo rm -Rf /opt/tomcat6/webapps/redmine/
# tomcat 起動(自動デプロイ)
sudo /etc/init.d/tomcat6 start
# 静的ファイル格納ディレクトリにシンボリックリンク貼り直す
sudo ln -s /home/apache/redmine/files/ /opt/tomcat6/webapps/redmine/WEB-INF/files

でした。

Redmine、Subversion やレンサバ rsync についてもし興味があれば以下をみてみてください。 :)

hiromasa.another :o )» Blog Archive » Redmine を Tomcat6 にデプロイ

なにか利点があるかって話ですが、1パッケージにして JavaVM で動作させておけば、OS にのっている Ruby 実行環境に依存しなくて済むのがいいところ。 gem のバージョン依存とか考えなくていいし、Servlet の実行環境さえあればどこにでも乗せられるのでなかなか便利かもしれません。

hiromasa.another :o )» Blog Archive » Subversion サーバ を CentOS 5.5 で。

Subversion サーバは昔も家にたてていたのですが、ローカルサーバを Atom 機にしてからまだインストールしていなかったので CentOS 5.5 上に改めて構築してみました。

hiromasa.another :o )» Blog Archive » WordPress のファイルバックアップ

WordPress のブログデータの構成要素は、MySQL のデータと画像などのサイトにアップロードファイルとなりますが、ここは後者のファイルのバックアップお話。 MySQL のバックアップについては以前かいた以下の記事が参考になるかもしれません。

Ubuntu 10.10 Netbook Remix その後

先日外付けのポータブル HDD にインストールしました Ubuntu 10.10 Netbook Remix ですが結構気に入ってよく使っています。 ThinkPad X61 と IdeaPad S10e で同一ディスクをつなぎ替えて稼働中。 いわゆるネットブックだけではなく 1024×768 系のノート PC にも便利に使えるようです。 :)

Eclipse 入れたり xampp いれたり Tomcat 入れたりしてすっかりプログラムがかける環境にしてみましたが、画面がせまいノート PC でこういう用途にも Netbook Remix はうまく働いてくれるようです。

ただ、ちょっとまだ Unity はバギーかもしれません。 使っているとちょっとおかしいなというところは目につきます。 まぁ致命的なことは今のところ起きていないので、バージョンアップを楽しみに。

netbook40

OpenGL の組み合わせもなかなかうまく動作しているようです。 上は Titanion さんを動かしているの図。 パッケージに入っていますのでぜひぜひ。 操作は Z と X とその同時押しで、、って弾幕やる人なら分かりますよね(笑)

てなわけで、仮想デスクトップがてら動いているところを動画でとってみました。 エンコード失敗したのでちょっとあらくてすいませぬ。

実は Ubity さんまだキーボードショートカットがいまいちで、マウス必須になってしまうところがちょっとあれなのですが、そこは発展中ということでご愛敬。

てなわけで、動画とったら力尽きたので今日はここまででございます。。