rbcd - Ruby CD Player Copyright (C) Ueno Katsuhiro 2000 $Id: README-rbcd,v 1.4 2000/12/03 06:21:21 katsu Exp $ == rbcd ってのは 簡単な CD プレイヤーです。デバイス制御の部分を除いて ほとんど全てが Ruby で書かれています。 要 1.6.0 以上。1.4 系以前のバージョンで動くかどうかは知りません(汗) また、ユーザーインターフェースによっては Ruby/GTK なりが別途必要に なります。 == インストールとか 1. cdrom ディレクトリにある CD-ROM ドライブを制御するための 拡張ライブラリをコンパイルします。詳しくは cdrom/README.ja を参照。 2. 1. でできたライブラリと rbcd.rb をロードパスの通ったところに 適当に置きます。 3. 実際に実行するスクリプトは rbcd-<ユーザーインターフェース名>.rb という名前になっています。 余談) 将来的には rbcd-hoge.rb も lib に押しやって、 起動はラッパースクリプトで行う…って感じにするかも。 rbcd-gtk, rbcd-dance を使う場合は、Ruby/GTK に ruby-gtk-20001101.patch を 当てるか、gtk-compat.rb を gtk.rb という名前で gtk.so と同じ場所に 置いて下さい。 == rbcd-tty についてとか いわゆるコンソール版ってヤツですが、デバッグ用に作ったようなもんなので 機能的にはイマイチです。 使い方についてはソース参照 :-) == rbcd-gtk についてとか プレイリストでは、左ドラッグでトラックの移動、中クリックで 飛ばすか飛ばさないかの切り替え、中ダブルクリックで全トラック切り替え、 右クリックでメニューが出ます。 右下の枠囲みの部分をクリックすると時間表示が切り替わります。 その他の使い方は直観で分かるはず (^^ スタイルのカスタマイズは $HOME/.rbcd/gtkrc というファイルで行います。 == rbcd-dance についてとか 再生中にキャラクターが踊ります :-) それ以外は rbcd-gtk とほとんど同じです。 ダンスパターンは $HOME/.rbcd/dance/<パターン名>/pattern というファイルに 記述します。フォーマットはこんな感じ。とはいえ Ruby スクリプトとして 解釈するので、最後の一行で正しい値を返しさえすれば他の部分はどう書こうと 自由です。 width = <セルの幅> height = <セルの高さ> files = <画像ファイル名> animdata = [ [ <ダンスパターン 0> ], [ <ダンスパターン 1> ], [ <ダンスパターン 2> ], [ <ダンスパターン 3> ], ... ] [ width, height, files, animdata ] <画像ファイル名> は $HOME/.rbcd/dance/<パターン名>/ からの相対パスで 指定します。複数の画像を指定する場合はファイル名の配列にします。 各画像は <セルの幅> x <セルの高さ> に分割され、 分割後の各画像 (「セル」と呼んでます) には右→左、上→下の順に 番号が 0 から割り当てられます。 <ダンスパターン> は、0 個以上のセル番号の列と、次のダンスパターンを 表す番号で指定します。 [ <セル番号>, <セル番号>, <セル番号>, ... , <次のパターンの番号> ], 次のダンスパターンが複数ある場合は、<次のパターンの番号> を番号の配列 にします。どのパターンを次のパターンにするかは乱数で決定されます。 再生時はダンスパターン 1 から、それ以外の時はダンスパターン 0 から 始まります。 なお、フレームレートは秒間 8 コマでハードコーディングしています。 具体例は dance-sample/pattern を参照して下さい。 # ワタクシ絵心がありませんので、こんなお粗末なモノしか作れません (;_; # テストに使用したパターンは著作権的に問題があるので配布できませんし、 # どなたか Ruby's License で配布できるサンプルを描いて頂けると # 有難いのですが… # # 「マスコットキャラにもっと活躍してもらわないと」とか言ってみたりする(笑) == その他のユーザーインターフェースについてとか 以下は rbcd のユーザーインターフェースを書く際に必要そうな情報のメモです。 現在のクラス構成は、こんな感じ。 [ Track ]----->[ AudioDisc ]----->[ CDPlayer ] ^ -----o -----o | | * | * * | | observer | | | | @ v [ TrackList ]----------------------@[ Rbcd ]---------@[ RbcdInterface ] @ ---------> | observer | A--->B : association | Ao---B : aggregation [ CDDB ] A@---B : composition rbcd の具体的な動作は Rbcd クラス以下で定義されています。 RubyInterface は Rbcd クラスのインスタンスとユーザーインターフェースを 作成し、メインループを回してユーザーからの要求を Rbcd に転送します。 ユーザーインターフェースの更新は、ほとんどの場合 Rbcd オブジェクト からの要求 (= メソッド呼び出し) によって受動的に行います。 Rbcd rbcd の具体的な動作を定義するクラス。 スーパークラス: Object クラスメソッド: new(devicename, interface) インスタンスの作成。devicename は CD-ROM ドライブを表すデバイス名。 interface は更新要求を受け取るオブジェクト。 # んんー、Singleton にしたほうがよいかなぁ… interface には次のメソッドを public で定義しておくこと。 これらのメソッドは、デバイスの状態が変化したために ユーザーインターフェースを更新する必要があるときに Rbcd#dispatch から呼び出されます。 list_changed(tracks) トラックの追加/削除/移動などでプレイリストが変化したときに 呼び出されます。tracks は現在のプレイリストを表す Rbcd::Track オブジェクトの配列です。 なお、プレイリストの初期状態 (初めて list_changed が呼ばれる前) は 空です。 current_changed(track) 選択されているトラックが変わった時に呼び出されます。 具体的には、再生開始/停止、再生トラックが変わった時等に呼ばれます。 また、プレイリストが空でなくなった時、空になった時にも呼ばれます。 track は新たに選択されたトラックを表す Rbcd::Track オブジェクトか nil (= 無選択状態) です。 state_changed(state, prev_state) 状態が変った時に呼び出されます。 state, prev_state の取り得る値は :stop (停止)、:play (再生)、 :pause (ポーズ) です。 now_playing(track, disc_addr, track_time) 再生中に呼び出されます。 track は現在再生中のトラックを表す Rbcd::Track オブジェクト、 disc_addr, track_time は再生中の絶対/相対位置を表す CDROM::Time オブジェクトです。 メソッド: dispatch デバイスの状態をチェックし、必要に応じて各関連オブジェクトの メソッドを呼び出します。 ユーザーインターフェース側は、メインループ等で定期的に (できるだけ 1秒未満の間隔で) このメソッドを呼び出さなければなりません。 stop 再生を停止します。 pause ポーズ / ポーズ解除のトグル。 play 再生中でないなら、現在選択されているトラックを再生します。 next_track プレイリスト中の次のトラックを選択します。 prev_track プレイリスト中の前のトラックを選択します。 eject CD をイジェクトします。 play_from(offset) 現在選択されているトラックを途中から再生します。 offset には CDROM::Time オブジェクトか整数を指定します。 state 現在の状態を返します。state_changed の説明を参照。 move_track(track, track_to[, notify]) プレイリスト中の track を track_to の直前に移動します。 notify が真の時、移動後 list_changed メソッドを呼び出します。 notify のデフォルトは false です。 このメソッドは rbcd の状態を変化させますが、ユーザーインター フェースの更新は呼び出した側で能動的に行う必要があります。 sort_tracks([notify]) プレイリストをソートします。 notify が真の時、ソート後 list_changed メソッドを呼び出します。 notify のデフォルトは true です。 このメソッドは rbcd の状態を変化させますが、ユーザーインター フェースの更新は呼び出した側で能動的に行う必要があります。 repeat = flag flag が真の時、プレイリスト全体を繰り返し再生します。 このメソッドは rbcd の状態を変化させますが、ユーザーインター フェースの更新は呼び出した側で能動的に行う必要があります。 repeat 現在のリピート再生モードを真偽値で返します。 set_volume(volume, balance) 音量を指定します。volume は 0 以上 255 以下、 balance は 0 以上 100 以下で指定します。 このメソッドは rbcd の状態を変化させますが、ユーザーインター フェースの更新は呼び出した側で能動的に行う必要があります。 get_volume 現在の音量とバランスを返します。 save_disc([force]) 指定されたディスクの情報をデータベースに記録します。 force が真でない時、ディスクに音楽トラックやタイトルが無ければ 記録を行いません。 save_all_discs([force]) 現在セットされている全ディスクの情報をセーブします。 また、rbcd の現在の状態を得るためのメソッドがいくつかあります。 disc_id(disc) データベース上でディスクを識別するための文字列を返します。 Rbcd::Track トラックを表すクラス。 このクラスのインスタンスの状態を変化させた時のユーザーインター フェースの更新は能動的に行う必要があります。 スーパークラス: Object インクルードしているモジュール: Comparable メソッド: disc このトラックを含む Rbcd::Disc オブジェクトを返します。 title title = string トラックのタイトルの参照/更新。 ext ext = string トラックの補足情報の参照/更新。 enable? enable = flag トラックの有効/無効を指定します。 トラックが無効の時は、そのトラックは再生されません。 size トラックのサイズを CDROM::Time オブジェクトで返します。 seq?(prev_track) このトラックが物理的に prev_track の次の位置にある時、真を返します。 play([offset]) このトラックを再生します。 self <=> other ディスク順序、トラック番号の比較。 Rbcd::Disc CD を表すクラス。Rbcd::Track オブジェクトの集合体です。 このクラスのインスタンスの状態を変化させた時のユーザーインター フェースの更新は能動的に行う必要があります。 スーパークラス: Object インクルードしているモジュール: Enumerable メソッド: size CD のサイズを CDROM::Time オブジェクトで返します。 title title = string CD のタイトルの参照/更新。 artist artist = string CD のアーティスト名の参照/更新。 ext ext = string CD の補足情報の参照/更新。 max_track_no 最大のトラック番号を返します。 each { ... } CD に含まれる各トラックに対してブロックを評価します。 0 番目のトラックから順に列挙します。当該トラック番号に該当する トラックが存在しない場合はブロックに nil を渡します。 to_a n 番目の要素にトラック番号 n のトラックが入った配列を返します。 [](n) トラック番号 n のトラックを返します。 audio_tracks 音楽トラックのみを含む配列を返します。 slot_no ディスクの入っているスロット番号を返します。 CDROM#change_slot 参照。 == ToDo (-) 各クラスのインターフェースはまだ固めてません。 (-) CD チェンジャ対応っぽい書き方をしてますが、見せかけだけです(笑) 実物を持っていないので、いやはや何とも。 (-) GTK+ をよく知らないんで、期待した動作をしない部分は いろいろゴチャゴチャと妙なことをしてます。 (-) visible? が偽の時に Gtk::CList#moveto を呼ぶと何か妙なことに なるっぽいんだけど、これどないしたらええんでしょ? (-) rbcd-dance を rbcd-gtk から独立させる。 (-) rbcd-dance を長時間動かしていると大量にメモリを食う。 == 配布条件 Ruby の配布条件と同じです。 ----