PeerCastStationをOSXで使うときにちょっと便利にした話

PeerCastStationはOSXやLinuxでも動作するのでマルチな環境での視聴が捗りますよね。ですが、Windows上で視聴の補助ツールを使う前提となっており、そのままではいささか使いづらいのも事実です。私はOSXを使っているのでOSXでの使い勝手を向上させてみました。

（2017/06/17追記：WMVが再生できなかったのでJSとスクリプトを更新しました。）

# 完成イメージ
![名称未設定2.gif](https://qiita-image-store.s3.amazonaws.com/0/114013/4cd76269-f863-5aa1-1b3d-af2b0721499f.gif)

# TL;DR

長くなってしまいましたがやることは2つ
1. PeerCastStationの生成リンクの変更
2. スクリプトエディタ(AppleScript)でアプリを作成しURLリンク経由でVLCを立ち上げる

### そもそもPeerCastStationをOSXで使うと嫌なこと

ダブルクリックや再生ボタンなどで配信を再生しようとしても、直接再生できず、プレイリストのファイルとしてダウンロードされてしまい、ダウンロードフォルダがプレイリストファイルで一杯になる。そもそもブラウザ上で完結させたいけど、NPAPIが廃止されてるのでVLCプラグインも使えない。

# 生成リンクの変更

例えばブラウザ上のURLとして ```callto://***``` が指定してあるとSkypeが立ち上がって、通話を開始してくれるように、ブラウザ上のURLのプロトコルをオレオレなものに変更することによって、このあと作るVLCランチャーをブラウザから立ち上げられるようにする。今回は ```pecast://``` をオレオレプロトコルにすることにする。

PeerCastStationのプログラムディレクトリの中にある ```/html/js/channels.js``` で ```http://127.0.0.1:7144/html/channels.html``` のリンク、 ```/html/js/relays.js``` で
 ```http://127.0.0.1:7144/html/relays.js``` のリンクをそれぞれ生成しているので、それぞれのJavascriptのリンクのアドレスを書き換える。

```diff:channels.js
@@ -226,12 +226,12 @@
     return (self.tags()!=null && self.tags()!=='') ? 'tooltip' : '';
   });
   self.streamUrl       = ko.computed(function() {
-    var url = 'pecast://localhost:7144/stream/' + self.channelId() + "." + self.infoContentType() + "?tip=" + self.tracker();
+    var url = '/stream/' + self.channelId() + "?tip=" + self.tracker();
     var auth_token = owner.authToken();
     return auth_token ? url + '&auth=' + auth_token : url;
   });
   self.playlistUrl     = ko.computed(function() {
-    var url = 'pecast://localhost:7144/stream/' + self.channelId() + "." + self.infoContentType() + "?tip=" + self.tracker();
+    var url = '/pls/' + self.channelId() + "?tip=" + self.tracker();
     var auth_token = owner.authToken();
     return auth_token ? url + '&auth=' + auth_token : url;
   });
```

```diff:relays.js
@@ -428,6 +428,17 @@
 var ChannelViewModel = function(owner, initial_value) {
   var self = this;
   self.channelId       = ko.observable(initial_value.channelId);
+  self.streamUrl = ko.computed(function () {
+      var url = '/stream/' + self.channelId();
+      var auth_token = owner.authToken();
+      return auth_token ? url + '?auth=' + auth_token : url;
+    });
+  self.playlistUrl = ko.computed(
+    function () {
+      var url = '/pls/' + self.channelId();
+      var auth_token = owner.authToken();
+      return auth_token ? url + '?auth=' + auth_token : url;
+    });
   self.infoName        = ko.observable(initial_value.info.name);
   self.infoUrl         = ko.observable(initial_value.info.url);
   self.infoBitrate     = ko.observable(initial_value.info.bitrate);
@@ -466,17 +477,6 @@
   self.isFirewalled = ko.computed(function() {
     return channelsViewModel.isFirewalled();
   });
-  self.streamUrl = ko.computed(function () {
-      var url = 'pecast://localhost:7144/stream/' + self.channelId() + "." + self.infoContentType();
-      var auth_token = owner.authToken();
-      return auth_token ? url + '?auth=' + auth_token : url;
-    });
-  self.playlistUrl = ko.computed(
-    function () {
-      var url = 'pecast://localhost:7144/stream/' + self.channelId() + "." + self.infoContentType();
-      var auth_token = owner.authToken();
-      return auth_token ? url + '?auth=' + auth_token : url;
-    });
 
   self.connectionStatus = ko.computed(function () {
     var result = "";
```

これで下準備は完了。

#　VLCランチャーの作成

### スクリプトエディタでランチャーを作る

```pecast://``` リンクはVLCに直接渡してもうまく解釈できないので、 ```http://``` に置換してVLCアプリケーションに渡すようにする。

```applescript:PecastLauncher.app
-- PecastLauncher
-- This provides generate appropiate URL and send URL to VLC

on open location inputUrl -- inputUrl is something like "pecast://localhost:7144/xxxx.xxx?tip=xxx"
	activate
	if inputUrl starts with "pecast://" then
		if (findStr(inputUrl as string, ".WMV") = 1) then
			set outputUrl to replaceScheme(inputUrl as string, "mms://")
		else
			set outputUrl to replaceScheme(inputUrl as string, "http://")
		end if
		playUrlWithVlc(outputUrl as string)
	end if
	quit
end open location

on replaceScheme(inputUrl, scheme) -- replace URL scheme of input
	set swap to AppleScript's text item delimiters
	set AppleScript's text item delimiters to "://"
	set authority to last text item of (inputUrl as string)
	set AppleScript's text item delimiters to swap
	set outputUrl to scheme & authority
	return outputUrl
end replaceScheme

on playUrlWithVlc(playUrl) -- Call VLC application and play URL stream
	tell application "/Applications/DnD/VLC.app" -- Please change your enviroment
		activate
		OpenURL playUrl
		play
		play -- I don't know why this is required
	end tell
end playUrlWithVlc

on findStr(inputText, searchStr) -- find some strings in input text
	set swap to AppleScript's text item delimiters
	set AppleScript's text item delimiters to searchStr
	set inputText to every text item of inputText
	set AppleScript's text item delimiters to swap
	set theList to {}
	set x to 0
	set delNum to number of searchStr
	repeat with curItem in inputText
		set x to x + (number of curItem)
		set end of theList to x + 1
		set x to x + delNum
	end repeat
	if (number of theList) = 1 then return 0
	return 1
end findStr
```

アプリケーションとして保存する。

### アプリに ```pecast://``` プロトコルの関連付けを追加

できたランチャーアプリのパッケージ内容を表示して ```***.app/Contents/Info.plist``` に下記の記述を追加する。これによりChromeなどのブラウザからこのランチャーを関連付けて起動してくれるようになる。

```xml:Info.plist
	<key>CFBundleURLTypes</key>
	<array>
		<dict>
			<key>CFBundleURLName</key>
			<string>Peercast stream URL</string>
			<key>CFBundleURLSchemes</key>
			<array>
				<string>pecast</string>
			</array>
		</dict>
	</array>
	<key>LSUIElement</key>
	<true/>
```

これでランチャーアプリは出来上がった。

### プロトコルの関連付けを登録する

これをそのまま ```/Applications/``` フォルダにコピーしたいところだが、その場合だとプロトコルの関連付けがなされない。そのためディスクイメージから ```/Applications/``` フォルダにコピーする必要がある。適当なフォルダに先程のランチャーアプリを入れ、OSX付属のディスクユーティリティでフォルダからのイメージ作成をすればディスクイメージが作れるのでそれで作成するのがお手軽。
![スクリーンショット 2017-05-18 19.22.09.png](https://qiita-image-store.s3.amazonaws.com/0/114013/36433d0e-5497-2b87-2343-418770e0c753.png)

あとは ```/Applications/``` フォルダにコピーすれば完了。

# 参考

- [OSXでオレオレ･プロトコルのヘルパアプリケーションを作成する] https://blog.katsuma.tv/2007/12/osx_protocol_helper.html

# 次にやること

- Channelsページからダブルクリックで再生すると空白タブが開きっぱなしになる
- 多重視聴に向けてVLCを複数起動させる

# あとがき
ブラウザ上で完結させたい…させたくない？