2015年8月23日日曜日

著作権法と DVD と Linux

先日,以下のニュースを知った.DVD リッピングを行うソフトウェアを配布していた人物が著作権法違反により逮捕されたというものである.
  • JVA ニュースリリース リッピングソフトをアップロードしていた者を著作権法違反で初めて検挙 及び、出版社従業員等を著作権法違反の幇助でも検挙
    http://jva-net.or.jp/news/news_150819/news.pdf
DVD リッピングのソフトウェアなんて,特に Linux を使っていればごく普通に入手できるものである.なぜこれが違法になるのだと疑問に思い調べ始めたところ,2012 年の著作権法改正によってこのあたりが大きく変わり,ソフトウェア配布のみならず私的使用における複製も違法であることがわかった.そんなことはこれまでまったく知らなかったので,3 年遅れで整理しようというエントリである.

なお,できるかぎり正確な記述をしようと努力はしているが,ちゃんと法律を勉強したわけでもないので,エントリの内容に誤りがないことの保証はできないのでご了承ください.

1. 前提: DVD のスクランブルと Linux における扱い

市場に流通している大多数の DVD には Content Scramble System (CSS) というスクランブルがかかっており,視聴時にはプレイヤーがスクランブルを解除する動作となっている.スクランブル解除のために必要な CSS の仕様は DVD Copy Control Association (DVD CCA) にライセンスを受けることで入手できるが,ライセンスにより当該仕様の情報公開が禁止される.PC において DVD 再生を行うにあたり,スクランブル解除を担っているのは DVD ドライブではなくソフトウェアであり,正規のソフトウェアは DVD CCA にライセンスを受けスクランブル解除のコードを利用するということとなる.

Linux 等ではオープンソースソフトウェアが標準的に利用されている.オープンソースソフトウェアは,上記の情報公開禁止条項を満たすことができないため正規に DVD CCA のライセンスを受けることができずスクランブルを解除できないということになる.だが実際にはオープンソースソフトウェアでも DVD の再生を行うことができる.これはライセンスを受けずに CSS を解析した技術を利用しているからである.当該技術は最初は DeCSS というプログラムによって公開され,現在は CSS 解除ライブラリ libdvdcss として標準的に利用されている.Linux 等で DVD 再生を行うことができるメディアプレイヤーは現在ほぼすべてこの技術を利用している.

CSS 仕様が DVD CCA のライセンス範囲に閉じていればコピープロテクションとしての機能を果たすことができるが,DeCSS により CSS 解除機能を持つソフトウェアを自由に作ることができるようになった結果,DVD の複製が可能となった.

2. 著作権法の理解

著作権法における,上記 DVD スクランブルと Linux における扱いに関連する箇所に関してまとめる.なお,引用は現行の著作権法 (2015 年改正) から.

まず,2012 年の著作権法改正によって,CSS が 「技術的保護手段」 に含まれるようになった.
第二条  この法律において、次の各号に掲げる用語の意義は、当該各号に定めるところによる。
二十  技術的保護手段 電子的方法、磁気的方法その他の人の知覚によつて認識することができない方法(次号において「電磁的方法」という。)により、第十七条第一項に規定する著作者人格権若しくは著作権又は第八十九条第一項に規定する実演家人格権若しくは同条第六項に規定する著作隣接権(以下この号、第三十条第一項第二号及び第百二十条の二第一号において「著作権等」という。)を侵害する行為の防止又は抑止(著作権等を侵害する行為の結果に著しい障害を生じさせることによる当該行為の抑止をいう。第三十条第一項第二号において同じ。)をする手段(著作権等を有する者の意思に基づくことなく用いられているものを除く。)であつて、著作物、実演、レコード、放送又は有線放送(次号において「著作物等」という。)の利用(著作者又は実演家の同意を得ないで行つたとしたならば著作者人格権又は実演家人格権の侵害となるべき行為を含む。)に際し、これに用いられる機器が特定の反応をする信号を著作物、実演、レコード若しくは放送若しくは有線放送に係る音若しくは影像とともに記録媒体に記録し、若しくは送信する方式又は当該機器が特定の変換を必要とするよう著作物、実演、レコード若しくは放送若しくは有線放送に係る音若しくは影像を変換して記録媒体に記録し、若しくは送信する方式によるものをいう。
「当該機器が特定の変換を必要とするよう著作物、実演、レコード若しくは放送若しくは有線放送に係る音若しくは影像を変換して記録媒体に記録」 の部分は 2012 年の改正により追加された部分となる.CSS 解除は 「特定の変換」 に該当するため CSS は 「技術的保護手段」 に含まれることになった.

CSS が 「技術的保護手段」 に含まれることによるユーザへの影響として,以下条文により CSS を回避した複製が私的使用においても違法となる (罰則はなし).
第三十条  著作権の目的となつている著作物(以下この款において単に「著作物」という。)は、個人的に又は家庭内その他これに準ずる限られた範囲内において使用すること(以下「私的使用」という。)を目的とするときは、次に掲げる場合を除き、その使用する者が複製することができる。
二  技術的保護手段の回避(第二条第一項第二十号に規定する信号の除去若しくは改変(記録又は送信の方式の変換に伴う技術的な制約による除去又は改変を除く。)を行うこと又は同号に規定する特定の変換を必要とするよう変換された著作物、実演、レコード若しくは放送若しくは有線放送に係る音若しくは影像の復元(著作権等を有する者の意思に基づいて行われるものを除く。)を行うことにより、当該技術的保護手段によつて防止される行為を可能とし、又は当該技術的保護手段によつて抑止される行為の結果に障害を生じないようにすることをいう。第百二十条の二第一号及び第二号において同じ。)により可能となり、又はその結果に障害が生じないようになつた複製を、その事実を知りながら行う場合
なお,CSS 回避を行った視聴については問題ないと理解している.DVD は視聴するものであることを否定する人はいないだろうから,視聴行為自体は 「当該技術的保護手段によつて防止される行為」 には当然含まれない.

であるから,Linux ユーザとしては,以下のようになる.
  • libdvdcss を使用するソフトウェアで DVD を再生することは合法
  • libdvdcss を使用するソフトウェアで DVD をリッピングすることは違法

また,ソフトウェア開発者などへの影響として,以下条文により CSS を回避して複製を行うプログラムの作成・配布を行うことができなくなる (罰則あり,非親告罪).
第百二十条の二  次の各号のいずれかに該当する者は、三年以下の懲役若しくは三百万円以下の罰金に処し、又はこれを併科する。
一  技術的保護手段の回避を行うことをその機能とする装置(当該装置の部品一式であつて容易に組み立てることができるものを含む。)若しくは技術的保護手段の回避を行うことをその機能とするプログラムの複製物を公衆に譲渡し、若しくは貸与し、公衆への譲渡若しくは貸与の目的をもつて製造し、輸入し、若しくは所持し、若しくは公衆の使用に供し、又は当該プログラムを公衆送信し、若しくは送信可能化する行為(当該装置又は当該プログラムが当該機能以外の機能を併せて有する場合にあつては、著作権等を侵害する行為を技術的保護手段の回避により可能とする用途に供するために行うものに限る。)をした者
冒頭に挙げた事例は,当該ソフトウェアをアップロードしていた人物が著作権法違反で,当該サイトにリンクを張っていた人物が著作権法違反の幇助で逮捕された事例であり,上記条文の行為に該当していることになる.

そうすると Linux ディストリビューション / パッケージのミラーを行っているサイトなどが問題になるのではないかと思ったのだが,国内ミラーサーバの Gentoo / Arch Linux のパッケージを確認したところ,libdvdcss とソフトウェアが分離された (ごく一般的な) かたちでソース,バイナリの双方での配布が行われているようだ.一方,Linux Mint は “No codecs” バージョンのみの配布となっている.状況から考えると,以下のような整理になるのだろうかと推測する
  • libdvdcss は CSS 回避の機能のみを持ち,単体での配布は 「著作権等を侵害する行為」 である複製の用途に供するとの判断はできない
  • libdvdcss に依存する DVD 複製ソフトウェアはそれ自身では CSS 回避の機能を持たず,「技術的保護手段の回避」 に該当しない
  • libdvdcss に依存するメディアプレイヤーは,「著作権等を侵害する行為」「技術的保護手段の回避」 の双方に該当しない
  • libdvdcss に依存しない,もしくはバンドル済みの DVD 複製ソフトウェアは,「著作権等を侵害する行為を技術的保護手段の回避により可能とする用途に供する」 に該当する
  • libdvdcss に依存しない,もしくはバンドル済みのメディアプレイヤーは,「著作権等を侵害する行為」 に該当しない
なお,これらの配布に関しては 2012 年以前から不正競争防止法も関連するもよう.ここでは触れない.

これら条文の根底にある考えはこうなのだと思う: 「DVD を複製できないようにスクランブルをかけたのだから,複製してくれるな.複製の手段を配布することも認めない.スクランブルを回避しても目的が視聴のみであれば,いたしかたあるまい」

3. 個人の感想

恥ずかしながら,私的使用における複製も違法であるということを今までまったく知らず,そのことを知ったときにはかなりのショックだった.それまでは音楽 CD と同じようなものと思っていた.音楽 CD は私的使用の範囲内での複製が認められているため吸い出したコンテンツを携帯プレイヤーで楽しむといったことに問題がないが,CSS が利用された DVD にはそのような選択肢がなくなったということになる.
DRM 一般について言えることだが,利用者の選択を制限する方向性の技術は嫌いだ.

以下に著作権法に関して持った疑問を 2 点挙げておく.
  • 私的使用まで踏み込んで違法化することの有効性
    2012 年改正で CSS が 「技術的保護手段」 に含まれるようになったことにより,私的使用においても CSS を回避して複製することが違法となった.ただし,2012 年改正以前においても,複製コンテンツを不特定多数がダウンロードできるようにするといった行為は私的使用の範疇を超えた違法行為であった.実際問題として,CSS を回避した DVD の複製は海外では特に制限対象となっておらず,海外のリソースを参照すればソフトウェアも情報もたやすく入手できる.私的使用まで踏み込んだ制限を行うことで,著作権者の利益をどれだけ守れることになるのだろうか.
  • スクランブルは複製を防止するための手段なのか
    まあこれは,2012 年改正から認められるようになったということなのだけれど.地デジ放送は? などと考え始めると,あまり納得感はない.

参考


2015年2月8日日曜日

感想文: The Visual Display of Quantitative Information

Edward R. Tufte, The Visual Display of Quantitative Information を読んだので感想文を書こうと思う。

そもそも本書を知ったきっかけは Cytoscape の開発者である Ono 氏のブログだったと思うのだけれど、見つからなかったので SlideShare へのリンクを以下に。

『繋がり』を見る: Cytoscapeと周辺ツールを使ったグラフデータ可視化入門
http://www.slideshare.net/keiono/cytoscape

また、Tufte および本自体については以下のブログがわかりやすかった。

タフテ、タフテという呪文 - 三上のブログ
http://d.hatena.ne.jp/elmikamino/20080402/1207139139


洋書である。私は英語が大得意ではないので、洋書というといつも要所要所しか読まない (読めない) のだが、本書はかなり平易な英語になっていると感じた。また、絵図が多用されており、これらからもかなりの意味を読み取ることができ、読み進めるにあたりさほど苦労はなかった。たまに過去の文章の引用があったりすると、時代なのか、イギリスだからなのか、論文だからなのか、とたんに難しくなる。

本書は二部構成になっている。第一部は 「実践」 として、過去の優れた、また優れていないグラフを数多く論じる。第二部は 「理論」 であり、情報を伝えるグラフを描くためのいくつかの原則を多数の例とともに明快に示していく。その根底にあるものは一貫している。
グラフはデータを示すものだから、グラフ自体が示すデータの密度を最大化していくべきである。
原則のひとつとして、データを表さないもの (「インク」) を可能な限り排するというものがある。装飾的な表現はもちろん、今まで疑問を持たず引いていた座標軸も、データそのものを表すものではない。そういった要素を大胆に削減し、グラフの中の情報密度を相対的に増加させていく。あまりに大胆であるため、正直やりすぎで逆にわかりづらい、と感じる箇所も多分にある。しかし Tufte はこう書く。
さらに言うと、よくあることだが、グラフを見る読者の能力を低く見積もるのは間違いだ。あなたが理解できることなのだから、読者もできるでしょう。グラフはその絵図自体が、テキストがなくても理解できるくらい、洗練されているべきなのだ。(p.136, 意訳)
まあ実際に示された大胆な例ほどの 「改善」 をやる勇気は今のところないのだけれども、それはそれで良いかと思う。

そんなふうに、ふんふん、へえ面白いと読んでいくのだが、その最後 (から 3 番目くらい) に以下の原則が示され、はっとした。
グラフはデータに関する段落であり、またそのように扱われるべきだ。(p.181, 意訳)
こういう心構え的な内容が最後に出てくるのも変わっているなと感じたのだが、これを読んだ時に今まで示されてきた数々の原則 / 方法論が急に整理されてストンと落ちた。そしてそのまま、こう続ける。
言葉も、グラフも表も、形式は違うがいずれも情報の伝達という目的は共通している。同じ事項に関する情報が、ページ上の別々の場所に分断されて配置されるべきなどということはない。
(2 ページほど略)
このように、データ解析のグラフにおいて言葉が使われる時には、(デザインが複雑な場合に) 読者がそれを 「どうやって」 読み解くべきかを示すべきであって、「何を」 読み解くべきかを示すものではない。(p.181-182, 意訳)
これをダビンチの論文を引用して話すのがまたたまらないのだが、ふと思うと、本書をこれまで読んで絵図を見て、これなんだっけ、と思ったことがまるでなかったことに気付かされた。絵図を見るためにページをめくる必要があったことすら、数えるほどしかない。そして (英語力のせいで) 文章が多少わからなくとも、その絵図自体が明快に語っている。本書に示されたいくつかの原則、またその根底にある情報を伝えるという目的を、目の前にあるその本がそのまま体現しているということに感動すら覚えた。

本書はタイポグラフィについても定評がある。Tufte にとっては、いかにして受け手に情報を伝えるかということを突き詰めていった結果、グラフも、タイポグラフィも、自信はないが文章も、こだわらざるを得なかった (自らの出版社を立ち上げる程度に) ことなのだろうと感じた。あとプレゼンテーションもすごいらしい。

 参考

2014年3月25日火曜日

ClamAV のオンアクセス スキャン

ClamAV のオンアクセス スキャンを行おうとした場合、以前は ClamFS か Dazuko (Clamuko) を使用することになっていたが、最近のバージョンではカーネルの fanotify を使用した方法に変わっていた。これを (Gentoo で) 使ってみようとしたところ注意が必要な事項があったのでそれらについて記載する。
環境は以下のとおり。
  • linux-3.12.13 (amd64: これが重要!)
  • clamav-0.98.1 

    1. fanotify サポートの有効化

    1.1 カーネルオプション

    gentoo-sources ではデフォルト無効だった。
    File systems  --->
     [*] Filesystem wide access notification
    

    1.2 ClamAV

    Gentoo ebuild では 2014 年 3 月現在、clamav の fanotify サポートが無効化 (--disable-fanotify) されており、オンアクセス スキャンが使用できない。けれども、x86 / amd64 では fanotify サポートを無効化しなくとも動作させることができるので、当該オプションを削除して fanotify サポートを有効化させることが可能。

    2. サブディレクトリの検索

    オンアクセス スキャンの対象ディレクトリは clamd.conf の OnAccessIncludePath で指定することになるが、当該ディレクティブはサブディレクトリを対象としない。つまり、OnAccessIncludePath / と指定しても ~/eicar.com へのアクセスはスキャンされない。これは期待された動作らしい (!)。私が期待する動作は (サブディレクトリも含めて) ファイルシステム全体をスキャンすることだったため以下のようにコードを変更した。
    --- a/clamd/fan.c       2014-01-13 12:02:18.000000000 -0500
    +++ b/clamd/fan.c       2014-03-23 20:33:12.382967001 -0400
    @@ -134,7 +134,7 @@
     
         if((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) {
            while(pt) {
    -           if(fanotify_mark(fan_fd, FAN_MARK_ADD, fan_mask, fan_fd, pt->strarg) != 0) {
    +           if(fanotify_mark(fan_fd, FAN_MARK_ADD | FAN_MARK_MOUNT, fan_mask, fan_fd, pt->strarg) != 0) {
                    logg("!ScanOnAccess: Can't include path '%s'\n", pt->strarg);
                    return NULL;
                } else
    
    FAN_MARK_MOUNT はマウントポイント全体を対象にするオプションのためサブディレクトリの検索とは異なるが、まあファイルシステム全体を対象にしてスキャンする使い方には問題がない。

    3. ebuild とパッチ

    ClamAV か関連の上記 2 点に対応した ebuild とパッチ (x86 / amd64 用) を https://github.com/drmn/portage/tree/master/app-antivirus/clamav に置いた。

    参考

    履歴

    • 2014/03/26: カーネルオプションについて追記、FAN_MARK_MOUNT に関する説明の誤りを訂正 (K 氏ご指摘)

    2014年3月3日月曜日

    Portage の userpriv feature

    vmware-modules が以下のエラーで emerge できず、しばらく VMware Player を使えていなかった。
    # emerge -av1 vmware-modules
    
    These are the packages that would be merged, in order:
    
    Calculating dependencies... done!
    [ebuild   R   ~] app-emulation/vmware-modules-279.0  USE="-pax_kernel" 0 kB
    
    -- snip --
    
    >>> Compiling source in /var/tmp/portage/app-emulation/vmware-modules-279.0/work ...
     * Preparing vmblock module
    make -j -l 3 HOSTCC=x86_64-pc-linux-gnu-gcc CROSS_COMPILE=x86_64-pc-linux-gnu- 'LDFLAGS=-m elf_x86_64' auto-build KERNEL_DIR=/usr/src/linux KBUILD_OUTPUT=/lib/modules/3.10.25-gentoo/build 
    Using standalone build system.
    Makefile:167: Makefile.normal: No such file or directory
    make: *** No rule to make target `Makefile.normal'.  Stop.
     * ERROR: app-emulation/vmware-modules-279.0::gentoo failed (compile phase):
     *   emake failed
    -- snip --
    
    これはどうやらカーネルのソースツリーを参照しに行ったけれどもファイルが見つからなかったというものらしく、以下で無事 emerge できた。
    # FEATURES="-userpriv" emerge -av1 vmware-modules
    
    userpriv feature は emerge のプロセスをユーザ権限 (portage) で実行する機能で、portage ユーザに必要なパーミッションがない場合に上記のようなエラーで失敗するもよう。FEATURE="-userpriv" することにより emerge が root 権限で実行され、このパーミッション問題が解決した。
    検索しても直接関わる情報が見つからなかったのは、umask をデフォルトより厳しい値 (0077) に設定していたからと思われる。また、この他にもカーネルモジュールを emerge する場合には同様の問題が発生するだろう。

    ということで、今後の emerge で -userpriv されるように以下の設定を行った。
    # echo 'FEATURES="-userpriv"' >> /etc/portage/env/rootpriv.conf
    # ecoo 'app-emulation/vmware-modules rootpriv.conf' >> /etc/portage/package.env
    

    2013年9月28日土曜日

    モナドの実際の使い方

    私の感覚としては、モナドはかなりわかりづらい。モナドの定義とか計算法則はわりとわかる。以下サイトがおすすめ。

    Haskell の State モナド (1) - 状態を模倣する | すぐに忘れる脳みそのためのメモ:
    http://jutememo.blogspot.jp/2009/10/haskell-state-1.html

    しかし実際にプログラムを書いてみると、使い方がわからない。特に IO モナドがわからない。実際にプログラムを書いて困った点、それらをどのように解決しているか? ということをまとめる。
    今から振り返ると Real World Haskell の内容ちゃんと理解して読んでたら問題にすらならなかったんですけどね。

    1. 副作用の分離?

    モナドは副作用のある計算を分離するなど言われる。確かに多くのモナドでは純粋な関数からモナドを使用し、run することにより値を取り出すことができ、状態によって結果が変わるかもしれないコードを分離することができる。素晴しい。
    ただし、最もよく使われるであろう IO モナドは値を取り出してモナドから純粋な関数に戻ることができない (unsafePerformIO は考えないことにする)。つまり、「IO モナドの関数は IO モナドの関数からしか使用できない」。
    例えば以下のようなコード。
    -- Test1.hs
    import Data.Char
    
    main = do
        let s = func0
        func1 s
    
    func0 = "s"
    
    func1 s = func11 $ s ++ s
    func11 = func12 . map toUpper
    func12 = putStrLn
    
    func1 > func11 > func12 と続く連鎖のなかで、IO を使用している関数は func12 のみだが、その間で純粋な関数しか使用しない func1, func11 も連鎖して IO モナドの関数になってしまう。
    これは非常に扱いづらいように思える。どんなプログラムでも、関数の連鎖の一番先に IO 使用する場合、そこに至る全ての関数は IO モナドにしなくてはいけない。これは 「IO モナドが伝染する」 と言われたりするよう。
    上の例だと単純に書き方が下手なだけだけど、例えばネットワークプログラミングをするとしばしば利用するであろう inet_ntoa なんかは副作用なんてあるわけなさそうだが、C の関数を利用するからという理由で IO になっている。実際のプログラムを書くにあたってこの問題は避けて通れないと思う。

    2. グローバル変数?

    これも副作用を排すという Haskell の基本ルールだが、グローバル変数が使用できない。ただ、これも実際にプログラムを書くといくらでも使いたくなる。こういった性質の変数がないと、「状態」 を使用するプログラムが極端に書きづらくなる。
    以下、ユーザから入力を受け取り、その状態に基づき出力結果を変えるプログラムのサンプル。
    -- Test2.hs
    import Data.Char
    
    main = do
        s <- func0
        func1 s
        func2 s
    
    func0 = do
        putStrLn "Enter some string:"
        getLine
    
    func1 s = do
        putStrLn "Repeat plese:"
        s' <- getLine
        putStrLn $ if s == s' then "Correct"
                              else "Wrong"
    
    func2 s = do
        putStrLn "In upper cases please:"
        s' <- getLine
        putStrLn $ if (map toUpper s) == s' then "Correct"
                                            else "Wrong"
    
    当然だけれど最初に入力した文字列をその後の処理を行う関数に渡す必要がある。実際のプログラムではこの関数がさらに別の関数を呼び…と続き、引数の引き回し地獄となること必須。こんなんだったらグローバル変数使わせてくれ、と思ってしまう。

    3. モナドの実際の使い方

    では、これらの問題をどうやって解決するかということで、実際のプログラムを見てみる。私の Haskell プログラムのリファレンスはだいたい xmonad です。今回のコードは xmonad-0.11 より。
    -- Xmonad/Main.hsc
    xmonad :: (LayoutClass l Window, Read (l Window)) => XConfig l -> IO ()
    xmonad initxmc = do
        -- snip --
        allocaXEvent $ \e ->
            runX cf st $ do
                -- snip --
    
                -- main loop, for all you HOF/recursion fans out there.
                forever $ prehandle =<< io (nextEvent dpy e >> getEvent e)
    
        -- snip --
    
    省略した部分は基本的にメインの処理に至るまでの前準備で、ポイントはメインのループ処理。ここで、ユーザからの入力やアプリケーションの状態変化を受け取り、その状態に応じて処理を行う。この関数は "X" モナドになっており、それが runX によって走らされている。X モナドの定義は以下。
    -- XMonad/Core.hs
    -- | The X monad, 'ReaderT' and 'StateT' transformers over 'IO'
    -- encapsulating the window manager configuration and state,
    -- respectively.
    --
    -- Dynamic components may be retrieved with 'get', static components
    -- with 'ask'. With newtype deriving we get readers and state monads
    -- instantiated on 'XConf' and 'XState' automatically.
    --
    newtype X a = X (ReaderT XConf (StateT XState IO) a)
        deriving (Functor, Monad, MonadIO, MonadState XState, MonadReader XConf, Typeable)
    
    -- | Run the 'X' monad, given a chunk of 'X' monad code, and an initial state
    -- Return the result, and final state
    runX :: XConf -> XState -> X a -> IO (a, XState)
    runX c st (X a) = runStateT (runReaderT a c) st
    
    コメントのとおりだが、IO, State, Reader モナドをトランスフォーマーによって組み合わせたものが X モナドである。X モナドの関数の中で get / set (State) すれば XState を操作、ask (Reader) すれば XConf を参照できる。また、X モナドは MonadIO のインスタンスになっている。このことにより、X モナドの関数中では liftIO を使用することにより IO の関数を呼び出すことができ、見かけ上 IO モナドの伝染を防ぐことができる (なお、xmonad では io = liftIO としている)。

    上述の問題で悩んでいるとき、State モナドの存在は知っていたけど、メインの処理を全てモナドで包んでやるという発想が出てこなかった。これだと、グローバル変数使うのと何が違うのか? という疑問も出るが、少なくともその変数の所在が明らかになるという点でメリットはあるのではないかと思う。

    参考

    Real World Haskell Chapter 18. Monad transformers: http://book.realworldhaskell.org/read/monad-transformers.html
    本物のプログラマはHaskellを使う - 第29回 グローバル変数の代わりに使えるReaderモナドとWriterモナド:ITpro: http://itpro.nikkeibp.co.jp/article/COLUMN/20090303/325807/

    2013年4月24日水曜日

    Haskell に興味がある人向け xmonad 設定ガイド



    2016/03/12 追記: あらためて読み返してみると,Haskell に関連する記述はだいたい間違っていることがわかりました.xmonad の設定をするうえではあまり困らないことだとは思いますが,その旨ご了承ください.

    2013年4月14日日曜日

    Linux で USB DAC を使う

    いいヘッドフォンを買ったので、USB DAC にもチャレンジしてみた。
    購入前はどの DAC が Linux で使えるかよくわからなかったので、調べたことをメモメモ。
    環境は以下のとおり。
    • Linux 3.7.10-gentoo
    • ALSA
    • PulseAudio とか JACK は使ってない、よくわからない
    まずどの DAC が使用可能かは、Windows や Mac の OS 標準ドライバで動くと謳っているものは (だいたい?) Linux でも使用可能なよう。
    USB オーディオの接続方式として、大きく分けると以下の 3 つがある。
    • USB Audio Class 1
    • USB Audio Class 2
    • その他独自方式
    USB Audio Class 1, 2 が USB.org で策定されており Linux もこれらに対応しているため、普通に ALSA のドライバで使える。
    独自方式にものについては Windows や Mac にも OS 標準ドライバとして搭載できないため別途ドライバをインストールする必要があり、そうすると Linux 向けのドライバがあるものは少ないでしょう。

    カーネルコンフィグで有効にするものは以下。
    CONFIG_SND_USB_AUDIO=m
    
    これでデバイスを接続するとあっさりと認識された。
    $ dmesg
    --- snip ---
    [   53.016830] usb 3-3.7: New USB device found, idVendor=0909, idProduct=0015
    [   53.016833] usb 3-3.7: New USB device strings: Mfr=1, Product=2, SerialNumber=0
    [   53.016837] usb 3-3.7: Product: USB Headphone Amp.
    [   53.016840] usb 3-3.7: Manufacturer: audio-technica
    [   53.017051] usb 3-3.7: usb_probe_device
    [   53.017067] usb 3-3.7: configuration #1 chosen from 1 choice
    [   53.017213] usb 3-3.7: Successful Endpoint Configure command
    [   53.017402] usb 3-3.7: adding 3-3.7:1.0 (config #1, interface 0)
    [   53.017526] usbhid 3-3.7:1.0: usb_probe_interface
    [   53.017540] usbhid 3-3.7:1.0: usb_probe_interface - got id
    [   53.027020] input: audio-technica USB Headphone Amp. as /devices/pci0000:00/0000:00:14.0/usb3/3-3/3-3.7/3-3.7:1.0/input/input11
    [   53.027346] hid-generic 0003:0909:0015.0005: input,hidraw4: USB HID v1.00 Device [audio-technica USB Headphone Amp.] on usb-0000:00:14.0-3.7/input0
    [   53.027421] usb 3-3.7: adding 3-3.7:1.1 (config #1, interface 1)
    [   53.030843] usb 3-3.7: adding 3-3.7:1.3 (config #1, interface 3)
    [   53.039448] snd-usb-audio 3-3.7:1.1: usb_probe_interface
    [   53.039463] snd-usb-audio 3-3.7:1.1: usb_probe_interface - got id
    [   53.049793] usb 3-3.7: Successful Endpoint Configure command
    [   53.050427] usb 3-3.7: Successful Endpoint Configure command
    [   53.050878] usb 3-3.7: Successful Endpoint Configure command
    [   53.051410] usb 3-3.7: Successful Endpoint Configure command
    [   53.052305] usbcore: registered new interface driver snd-usb-audio
    --- snip ---
    $ cat /proc/asound/cards 
     0 [PCH            ]: HDA-Intel - HDA Intel PCH
                          HDA Intel PCH at 0xa0610000 irq 47
     1 [Amp            ]: USB-Audio - USB Headphone Amp.
                          audio-technica USB Headphone Amp. at usb-0000:00:14.0-3.7, full speed
    $ aplay -L
    --- snip ---
    sysdefault:CARD=Amp
        USB Headphone Amp., USB Audio
        Default Audio Device
    front:CARD=Amp,DEV=0
        USB Headphone Amp., USB Audio
        Front speakers
    surround40:CARD=Amp,DEV=0
        USB Headphone Amp., USB Audio
        4.0 Surround output to Front and Rear speakers
    --- snip ---
    

    実際に音を出すには、ALSA のデフォルトの出力先か、アプリケーション単位で出力先デバイスを設定する必要がある。前者は ~/.asoundrc に設定すれば良い。
    # ~/.asoundrc
    pcm.!default sysdefault:Amp
    
    この設定はアプリケーション起動時のものが反映されるようなので、ノート PC を使用している時など接続変更が発生する時でも、接続後に設定、アプリーケション起動としてやれば良い。

    USB DAC をつないで音が良くなったか? というのは別問題。耳が追いついていない。

    参考

    第1回 USB-DACといっても必ずしも同じではない | Gaudio+PCオーディオfan: http://www.pc-audio-fan.com/special/usb-dac-research/20101115_1438/
    USB.org - Approved Device Class Document Download: http://www.usb.org/developers/devclass_docs
    What's Best Forum - USB audio: http://www.whatsbestforum.com/showthread.php?2932-USB-audio
    .asoundrc - ALSA wiki: http://alsa.opensrc.org/.asoundrc