追記 2013/01/29 23:40
appletv.local ではなく airplay.tcp.local を検索することで AppleTV ではなく AirPlay 対応のデバイス全て検索可能になりました。 僕は持ってないので検証できませんが!
追記 2013/01/17 17:40
zeroconf.el 使えば普通にできそうですね!家帰ってから試してみます
経緯
- 諸事情があって AppleTV の IP アドレスを取得したい。Emacs Lisp で。
- elcuervo / airplay を参考にしたら tenderlove / dnssd 使ってた
- dnssd の Emacs Lisp 版がない
- あるかもしれない。あったら誰か教えてください
- dnssd gem を完全にコピーする必要もなくて、結局 AppleTV の IP さえわかればいいので以下になりました
一応取れる。まあいいか。
本当はこうしたかった
;; Overwrote `dns-make-network-process' that have been written in dns.el (letf (((symbol-function 'dns-make-network-process) (lambda (server) (let ((coding-system-for-read 'binary) (coding-system-for-write 'binary)) (make-network-process :name "dns" :coding 'binary :buffer (current-buffer) :host "224.0.0.251" :service 5353 :type 'datagram))))) (dns-query "appletv.local"))
dns-query
を使いたかった- dns-make-network-process っつーマクロで service が "domain" 固定だった
- ↑ のように letf で丸ごと置き換えちゃおう
- dns.elc を load している場合、
dns-query
内のdns-make-network-process
部分が展開されてるので、letf が無力
dns.el(.gz) を手動で読みこんで dns-query を eval してもいいんだけど、まあそれはあれなのでこの形にしました。
余談
dns-write や dns-read の存在知るまで、 bindat 使って自力で DNS パケット作ったりしてた。つらい。 せっかくだから載せておく
(require 'bindat) (setq dns-packet-header-spec '((:id u16) (:flags u16) (:qdcount u16) (:ancount u16) (:nscount u16) (:arcount u16))) (setq data-spec '((:length u8) (:data str (:length)))) (setq footer-spec '((:qtype u24) (:qclass u16))) (defun qname (domain) (mapconcat (lambda (x) (bindat-pack data-spec `((:length . ,(length x)) (:data . ,x)))) (split-string domain "\\.") "")) (setq binary (concat (bindat-pack dns-packet-header-spec `((:id . #x1021) (:flags . 0) (:qdcount . 1) (:ancount . 0) (:nscount . 0) (:arcount . 0))) (qname "appletv.local") (bindat-pack footer-spec `((:qtype . #x0001) (:qclass . #x0001))))) ;; binary は ↓ と同じになる ;; (dns-write `((id #x1021) ;; (opcode query) ;; (queries (("appletv.local" (type A))))))