Daily Archive for June 6th, 2008

QCGainer : Quartz Composer Gainer plugin

RubyCocoaでQuartzComposer プラグインをつくれるようになった ので、さっそくつくってみました。 みんな大好きGainer の入力を QuartzComposer からとれるようにしました。

ソースコード

github:qc_gainer に。MITライセンスです。 Funnel, osc を使っています。

短かいので、コードをはっておきます。ごさんこうに。

#
#  qc_gainer.rb
#
#  Created by mootoh on 6/6/08.
#  Copyright (c) 2008 deadbeaf.org. All rights reserved.
#
require 'osx/cocoa'
OSX.require_framework 'QuartzComposer'
require 'funnel'
 
class QCGainer < OSX::QCPlugIn
  def self.executionMode
    2
  end
 
  def self.timeMode
    1
  end
 
  def initialize
    @initialized = false
    @gio = Funnel::Gainer.new(Funnel::Gainer::MODE1)
 
    @ain = [0,0,0,0]
    @din = [0,0,0,0]
    @aot = [0,0,0,0]
    @dot = [0,0,0,0]
  end
 
  def startExecution(context)
    Thread.new do
      sleep 0.1
      4.times { |i| addInputPortWithType_forKey_withAttributes(OSX::QCPortTypeNumber, "aot_" + i.to_s, nil)  }
      4.times { |i| addInputPortWithType_forKey_withAttributes(OSX::QCPortTypeNumber, "dot_" + i.to_s, nil)  }
      4.times { |i| addOutputPortWithType_forKey_withAttributes(OSX::QCPortTypeNumber, "ain_" + i.to_s, nil) }
      4.times { |i| addOutputPortWithType_forKey_withAttributes(OSX::QCPortTypeNumber, "din_" + i.to_s, nil) }
    end
    true
  end
 
  def execute_atTime_withArguments(context, time, args)
    unless @initialized
      4.times do |i|
        @gio.ain(i).on Funnel::PortEvent::CHANGE do |event|
          @ain[i] = event.target.value
        end
        @gio.din(i).on Funnel::PortEvent::CHANGE do |event|
          @din[i] = event.target.value
        end
      end
      @initialized = false
    end
 
    4.times do |i|
      setValue_forOutputKey(@ain[i], "ain_" + i.to_s)
      setValue_forOutputKey(@din[i], "din_" + i.to_s)
    end
 
    true
  end
 
  def stopExecution(context)
    true
  end
end

使い方

  1. Gainer I/O をMacとつなげる
  2. Funnelサーバを起動
  3. Quartz Composerを起動
  4. Pluginを配置

デモ

ビデオに撮るのがめんどうなので、Ruby会議 に持っていきます。

まとめ

こんなふうに、ありものをくっつけてささっと何かをつくるというとき、glue言語としてRubyはグッドですね。

Happy Physical Hacking !

Leopard で Quartz Composer カスタム Plugin を RubyCocoa でつくる

RubyCocoaで、QuartzComposerのカスタムプラグインをつくることができました on Leopard。 LeopardでのQuartzComposerカスタムプラグインづくりの続きです。あれから4ヶ月。

サンプル: qcplugin_rb

サンプルとして、2入力をとってその間に “Ruby” を挿入して後段に流すというプラグインを書きました。 githubにアップしてあります。MITライセンスです。

ソースコード: github:qcplugin_rb

スクリーンショット

screenshot

ポイント

  • Info.plistの書きかた
  • 入出力ポートの追加方法

Info.plistの書きかた

1.まず、Info.plist の NSPrincipalClass エントリに、RubyCocoaのBundleを初期化するObjective-Cのクラスを指定します。 RubyCocoaでMacのプラグインをつくるときの共通tipsですね。

2.それと、実際のプラグインの動作を記述するクラスを QCPlugInClasses に列挙します。QCPlugInクラスを継承したやつですね。

	<key>NSPrincipalClass</key>
	<string>RBLoader</string>    <-- 1
	<key>QCPlugInClasses</key>
	<array>
		<string>QCRubyPlugin</string> <-- 2
	</array>

入出力ポートの追加方法

LeopardのQuartzComposerから、ポートの指定は Objective-C 2.0 の property 機能を使って行うようになりました。 これをRubyCocoaからどう使うか分からなかったので、QCPlugInクラスのメソッドであるaddInputPortWithType:forKey:withAttributes:addOutputPortWithType:forKey:withAttributes: を使ってなんとかします。

では、どこにこれらのメソッドを書くか。QuartzComposerの制約で、executeメソッド内に書いちゃダメよ、とあるので困ります。 サンプルコードを漁ってみたところ、別スレッドを立ててそこで呼び出すのはOKぽい。 そこで、RubyのThreadをつかってやってみたところ、うまくいきました。ただし、ちょっとdelayを設けてやらないとQuartzComposerが死にます。なぜだ。

もっとうまいやり方をご存知のかたがいれば、ぜひ教えてください。 m(_ _)m

ひっかかりどころ

バッドノウハウがいくつかありますね。

  • s/QCPlugin/QCPlugIn/ なのです。見落しやすすぎる。
  • ポート追加のdelay。
  • メソッド名。execute が execute_atTime_withArguments になったりします。気づかずにいると、いつまでたってもメソッドが呼ばれずに悲しくなる。
  • イチからXcodeのプロジェクトをつくるよりも、サンプルを元に書き換えていくとはまりにくい。

おまけ

こう書くとすんなり動くようになったみたいですが、現実は泥のようなデバッグでした。 RubyCocoaのフレームワークをデバッガで追ったり、QuartzComposerの謎の挙動に悩まされたり。 フレームワークをつかった開発でのデバッグについては得るところがあったので、別に書くことにします。

関連エントリ

まとめ

Happy Visual Hacking !

TopCoder SRM 404

日本人にやさしい時間に始まった SRM 404 でした。404 TopCoder Not Found.

250 : Reading Books

Problem Statement : コード

配列をシーケンシャルに読んでいって、3種類のなにかを拾いあつめていく問題。んー、うまく言えない。 単純に要素をカウントしていくだけだとうまくテストケースをとおせないので、ちょっと考える必要がありました。ad-hocに書いてテストケースすべてがとおったところでsubmit。190pts。

500 : RevealTriangle

Problem Statement : コード

おもしろい問題。 穴ぼこだらけの三角形に、数字を入れていくという穴埋め問題ですね。 手でやると小学生でも解ける問題だけど、じっさいコードに落とすとなるとけっこう手強い。さんざん時間をかけて、テストケースをすべてとおしてsubmit。222ptsでした。コードが汚なすぎてわらえる。 TopCoderアカウントがある方は、これ を見て「これはひどい」と感じることでしょう。

結果

Challenge phaseで晩ごはんを食べているうちにSystem testを2つともパスし、Rating は 898→943 と 45点アップしました。ひさびさの緑コーダーに返り咲きです。うれしす。


コツコツつづけていくしかないですね。まずは250, 500の両方をコンスタントに解けるようにしていくことです。