TrackMeのWebインターフェイスを日本語化、バグ修正

EMONSTER等のGPS内蔵WindowMobile端末向けにTrackMeというアプリケーションがあります。端末内でGPSログを保存することはもちろん、リアルタイムでサーバーに位置情報を送信することもできます。このサーバー用のPHPスクリプトも上記ページで公開されており、自前のサーバーで運用することもできます。自動リロードで常に端末の現在位置をGoogleMapsで表示するモードなどもあり、サイバーです。バックエンドにMySQLを利用しており、テーブル構成などをのぞけば、色々と応用が広がりそうです。

■日本語ランゲージ定義の追加

で、そのスクリプトによるWeb画面はマルチランゲージ対応されているのですが、残念ながら日本語の設定はありません。中を覗いてみたところ、定義ルーチンが独立していて簡単に追加できそうだったのでサクっと作業してみました。下記の2ファイルを更新すれば使えるようになると思います。

一応、開発者の人に送ってみるつもりですが、自前でパッチ当てしたい人向けに貼っておきます。

index.php (818行目辺りに赤字部分を追加)

$html .= "                        <select name=\"language\">\n";
$html .= "                            <option value=\"english\""; if($language == "english") { $html .= " SELECTED"; } $html .= ">English</option>\n";
$html .= "                            <option value=\"italian\""; if($language == "italian") { $html .= " SELECTED"; } $html .= ">Italian</option>\n"; //trackmeIT
$html .= "                            <option value=\"german\""; if($language == "german") { $html .= " SELECTED"; } $html .= ">German</option>\n";
$html .= "                            <option value=\"spanish\""; if($language == "spanish") { $html .= "SELECTED"; } $html .= ">Spanish</option>\n";
$html .= "                            <option value=\"french\""; if($language == "french") { $html .= "SELECTED"; } $html .= ">French</option>\n";
$html .= "                            <option value=\"dutch\""; if($language == "dutch") { $html .= "SELECTED"; } $html .= ">Dutch</option>\n";
$html .= "                            <option value=\"japanese\""; if($language == "japanese") { $html .= "SELECTED"; } $html .= ">Japanese</option>\n";
$html .= "                        </select>$display_language_text<br>\n";
$html .= "                        <select name=\"units\">\n";
$html .= "                            <option value=\"imperial\""; if($units == "imperial") { $html .= " SELECTED"; } $html .= ">Imperial</option>\n";
$html .= "                            <option value=\"metric\""; if($units == "metric") { $html .= " SELECTED"; } $html .= ">Metric</option>\n";
$html .= "                        </select> $display_units_text<br>\n";

language.php (356行目辺りに赤字部分を追加)

(↑ 他の言語定義が並んでいる部分 Italian Language Data)
       $speed_metric_unit_balloon_text      = "km/h";
       $distance_metric_unit_balloon_text   = "chilometri";
       $height_metric_unit_balloon_text     = "metri"; 
     }
   elseif($language == "japanese")
    {
        $title_text                          = "TrackMe Display";
        $trip_button_text                    = "軌跡表示";
        $location_button_text                = "リアルタイム更新ON";
        $location_button_text_off            = "リアルタイム更新OFF";
        $filter_button_text                  = "更新";
        $filter_none_text                    = "全て表示";
        $filter_photo_comment_text           = "写真、コメント付きポイントのみ";
        $filter_photo_text                   = "写真付きポイントのみ";
        $filter_comment_text                 = "コメント付きポイントのみ";
 
       $filter_last_20                      = "最新20ポイントのみ";
        $filter_daterange                    = "日時範囲指定";
        $footer_text                         = "軌跡データ生成:";
        $incomplete_install_text             = "インストールが正しく終了しませんでした。ファイルinstall.php、database.sqlはまだTrackMeフォルダに存在します。これらを削除するまで地図表示は有効になりません。";
        $no_data_text                        = "DB内の1つ以上のTrackMe テーブルにデータがありませんY。Windows MobileデバイスでTrackMeアプリケーションを実行し、軌跡データを生成する必要があります。";
        $database_fail_text                  = "DBとの接続が切断され、表示が中断されました。";
        $trip_none_text                      = "なし";
        $trip_any_text                       = "全て";
        $display_options_title_text          = "表示オプション";
        $display_header_text                     = "ヘッダーを表示";
        $display_showbearing_text                = "方向矢印を表示";
        $display_crosshair_text              = "中心の十字マークを表示";
        $display_clickcenter_text            = "クリックした位置を中心にする";
        $display_overview_text               = "ミニマップを表示";
        $display_language_text               = "表示言語を選択";
        $display_units_text                  = "表示単位を選択";
        $display_button_text                 = "設定を保存"; 
        $startdate_text                                          = "開始:"; 
        $enddate_text                                            = "終了:"; 
        $trip_title                                                      = "Trip:"; 
        $filter_title                                            = "フィルタ:"; 
        $date_title                                                      = "日付:";
        $tripsummary_title                                       = "Trip 概要";
        $tripstatus_title                                        = "現在位置";
        $summary_time                                            = "トータル時間:";
        $summary_photos                                          = "写真数:";
        $summary_comments                                        = "コメント数:";
        // Public Display Information
        $user_button_text                    = "ユーザ切替";
        $showconfig_button_text                          = "設定";
&#
160;       $showconfig_button_text_off                      = "設定";
        // Private Display Information
        $page_private                                        = "ページの表示にはユーザ名とパスワードのよる認証が必要です。";//trackmeIT
        $trip_data                                                   = "ユーザ名:"; //trackmeIT
        $login_text                          = "ユーザ名";
        $password_text                       = "パスワード";
        $login_button_text                   = "ログイン"; 

        // Balloon Fields Information
        $user_balloon_text                   = "ユーザ";
        $trip_balloon_text                   = "Trip";
        $time_balloon_text                   = "時間";
        $speed_balloon_text                  = "速度";
        $altitude_balloon_text               = "高度";
        $total_time_balloon_text             = "累積時間";
        $avg_speed_balloon_text              = "平均速度";
        $total_distance_balloon_text         = "移動距離";
        $point_balloon_text                  = "ポイント";
        $comment_balloon_text                = "コメント";
        $speed_imperial_unit_balloon_text    = "mph";
        $distance_imperial_unit_balloon_text = "miles";
        $height_imperial_unit_balloon_text   = "feet";
        $speed_metric_unit_balloon_text      = "km/h";
        $distance_metric_unit_balloon_text   = "km";
        $height_metric_unit_balloon_text     = "m";
    }
    else
    {

(↓ 以降、デフォルトの英語表記のデータ Defaults English Data)

 

■ユーザ選択がリセットするバグの修正

リアルタイム表示のON/OFFをすると、ユーザ選択がリセットされてしま現象が出たので、場当たり的対応してみました。

index.php (305行目辺りの赤字部分を追加)

$html .= "                      function livetrack()\n";
$html .= "                      {\n";
$html .= "                              if(document.getElementById(\"last_location\").value == \"$location_button_text\")\n";
$html .= "                              {\n";
$html .= "                                      location=\"index.php?ID=$ID&last_location=yes\";\n";
//$html .= "                                            document.getElementById(\"last_location\").value = \"$location_button_text_off\";\n";
$html .= "                              }\n";
$html .= "                              else\n";
$html .= "                              {\n";
$html .= "                                      location=\"index.php?ID=$ID\";\n";
//$html .= "                                            document.getElementById(\"last_location\").value = \"$location_button_text\";\n";
$html .= "         &
#160;                    }\n";
$html .= "                      }\n";

rep2の携帯用画面のフッターをカスタマイズする際の覚え書き

σ(^^)は2chの閲覧にASP型ビューワーのrep2を愛用しています。複数マシンやケータイ閲覧でもお気入りスレや未読の管理が一元化できるのがポイントです。

で、そのケータイ閲覧画面で1つ不満が。スレ表示画面のフッターにトップへ戻るショートカットしかなく、閲覧の起点となる「お気に入りスレの新着」に戻れません。スレ表示が1画面の時にはブラウザバックで戻ればいいんですが、何ページも遷移した場合に不便です。そこで、カスタマイズを企てました。ソースを追って該当箇所を見つけるのに苦労したので覚え書きです。

該当ファイルは、インストールディレクトリ/conf/conf.inc.phpでした。このファイルの348行目あたりに赤字部分を追加しました。

$_conf[‘k_to_index_ht’] = <<<EOP
<a {$_conf[‘accesskey’]}="0" href="subject.php?spmode=fav&sb_view=shinchaku&b=k">0.お気に新着一覧</a><br />
<a href="index.php{$_conf[‘k_at_q’]}">TOP</a>
EOP;

accesskeyの0は元々Topに割り当ててあったんですが、個人的な使用頻度から追加部分に割り当て直しています。

ただ、rep2は新着一覧画面を呼ぶ度に、各スレッドの更新チェックをするので、読み込みに時間がかかるのが難点です。スレッド表示が単一ページで足りた場合は、ブラウザバックで戻る方が合理的でしょう。

HTTPベースの動画ライブラリ、実家から検証

少し前のエントリで実現して、TeraStation上のDivX動画ライブラリを、Apache経由で公開する実験ですが、実家から検証してみました。

結論から言ってラクショーでした。光->光なら問題ありませんね。今までのVPN+SMBであれこれ苦労してたのがおポンチでした。SMBは応答速度が低いと極端にパフォーマンスが落ちるプロトコルであることを最近知りました。

■ADSL + 無線LAN + PS3でも割とイケる

あと、妹のアパートに貸し出してあるPS3/40GB(たまに帰省した時に使う様に折半で購入)でも試しました。妹宅はADSLでしかもLANは11gの無線ですが、予想外に健闘。1ファイル最後まで完走させたワケじゃないですが、試した限りでは1280x720pのファイルでも大丈夫そうでした。ただ逆に720×400でも途切れまくるのもあったり。ウチは品質保持エンコだから、瞬間レートが跳ね上がるようなのはツライのかも知れません。ただ、PS3のブラウザからファイルを選んですぐ再生できるし、BASIC認証のパスワードもちゃんと保存できるので、この方式用のVOD端末としてはかなり重宝すると思います。これでレジューム再生ができればいうことないんですけどね。

■PC上からもストリーミング再生したい(1) Opera + VLC編

こうなってくると、PS3だけでなくPCブラウザ上からもストリーミング再生したくなります。で、色々試行錯誤した結果、Opera + VLCという方法を発見しました。VLCは「URLで開く」メニューがある動画プレーヤーのうちで、唯一マトモに再生できました。DivXデコーダーも内蔵しているので、ネットカフェなどで使うにも便利。パスワード保存はできませんが、BASIC認証には対応しています。

で、Operaの方でMIMEタイプがvideo/x-msvideoなストリームに対して、VLCを使うよう設定します。この時、唯一Operaだけが、URLのまま渡すことが可能なようで、IEやFireFoxだと、一度ローカルに保存してからVLCで開く、という動作にしかなりませんでした。

ともあれ、Opera + VLCで正しく設定すれば、Operaで一覧を表示して、目的の動画をクリックしたら自動でVLCが起動して(IDとパスワードを改めて入力しなきゃいけないけど)ストリーミング再生開始、という流れを実現できました。

ただ、VLCにはタイムスライダーがないので、途中を飛ばして観られないのが難点です。あと、(1)、(2)共通の問題ですが、2GBを超えるファイルは扱えないようです。まぁ、そんなサイズをストリーミングすんな、って話ですな。

■PC上からもストリーミング再生したい(2) DivX Web Player編

DivXのストリーミングといえば、普通にDivX Web Playerプラグインがあります。実は当然これも最初に試しました。Apache側で.aviの拡張子に対して、video/divxというMIMEタイプを定義しておけば、各ブラウザでDivX Web Playerが起動するようになります。ただ、これだけではダメなようで、当初断念して、(1)の方法に流れていました。

で、改めて調べたところ、DivX Web Playerによるストリーミング再生には、単にAタグによるリンクではなく、OBJECTタグによるページ上への埋め込みが必要なようでした。具体的には、

<object classid="clsid:67DABFBF-D0AB-41fa-9C46-CC0F21721616" codebase="http://go.divx.com/plugin/DivXBrowserPlugin.cab">
    <param name="src" value="http://(ユーザ名):(パスワード)@(ファイルのパス).avi" />
    <param name="bannerEnabled" value="false" />
    <param name="minVersion" value="1.0.0" />
<embed type="video/divx" src="http://(ユーザ名):(パスワード)@(ファイルのパス).avi" width="640" height="372" pluginspage="http://go.divx.com/plugin/download/" bannerEnabled="false">
</embed>
</object>

って感じ。DivX LABSのDivX Web Player Code Generatorでサンプルソースを生成してもらえます。動画の縦ピクセル数に20を足すのがポイントのようです(コントローラーの分)。DivX Web Player自体はBASIC認証ダイアログを持ってナサゲなので、パスの部分にユーザ名とパスワードを埋め込んでみました。

で、Aタグしか生成してくれないApacheのインデックスリストではダメだということがわかりました。ということは本来はフォルダ中のファイル名一覧を取得して、上記HTMLを個別生成するPHPスクリプトでも自作しなければ、ということになるんですが、そこまでは気力がわかなかったので、手抜き対処。具体的には、ファイルインデックス画面のフッター部分にHTMLを挿入するApacheのReadmeNameディレクティブを使って極簡単なPHPによるHTMLフォームをインクルードし、ブラウザ上で目的動画ファイルのリンクをコピペして再生ページに投げます。で、再生ページもやはりPHPで受け取った動画のURIを使って、上記のDivX Web Player用HTMLを生成するだけです。

画面例

動画のサイズも取得する術がないので、とりあえず手動で指定しています。まさに超手抜き(^^;)。

補足:ffmpeg-phpを使って、phpから動画ファイルのサイズを取得できました。

更に補足:フォームを使わずとも、JavaScriptを使って実現できました。>URL書き換え

でもまぁ、自分と家族などごく身近な人間しか使わないのでこれでOK。基本はダウンロードかPS3利用推奨ってことで。

とりあえず、上記の手順でブラウザ上のストリーミング再生ができるようになりました。本来は.aviではなく.divxでないとダメっぽいですが、一応観れてます。DivX Web Player自体、タイムスライダーもあるし、どこまでDLできてるかバーでわかるし、ブラウザから切り離したり、全画面再生もできるしと、VLCよりは使い勝手が良いです。

ApacheからTeraStationのファイルを公開

 前エントリでTeraStationにたまってるDivXファイルを、なんとかHTMLリンク一覧としてHTTP共有できると、DLNAとかより便利かも、ということに気付いたので、早速チャレンジしてみました。

■CIFSでマウントする

TeraStationをLinuxマシンでマウントするには、とりあえずSMB、FTP、ちょっとゴニョってNFSという選択肢があるわけですが、とりあえず手軽そうなSMBを試してみたところできない。調べてみると、CentOS5ではsmbfsやsmbmountの代わりにCIFSというあたらしいWindowsファイル共有プロトコルを使えば良いとわかりました。

mount -t cifs -o user=<ユーザ名>,password=<パスワード> //<TeraStation名/<共有名> /mnt/terastation/

って感じでOKでした。

あとは、このフォルダをApacheのドキュメントルート下に適当にシンボリックリンクして、BASIC認証をかけます。

ただ、これだけだと、リストは取得できるんですが、動画ファイルにアクセスするとエラーになってしまいます。ターミナルからcpなどでコピーはできるんですが、Apacheを経由するとダメ。

これは

EnableSendfile Off

で解決。パフォーマンス向上のための機能のようなので、当該ディレクトリのディレクティブ内に設定するのが良いでしょう。

■Apacheのインデックスリストをカスタマイズして利用

さて、これでアドレスでディレクトリ名を指定すれば、(そのフォルダにindex.htmlが無いので)Apacheが生成するインデックスリスト(ファイル一覧画面)が表示され、PS3からそれをクリックして再生できるのが確認できました。しかし2バイト文字が文字化けしています。ブラウザの設定でUTF-8にすれば正常に表示されるんですが、ページ遷移するたびにするのは面倒だし、それこそ実家向けには難しすぎます。なんとかインデックスリストの文字コードを指定する方法を模索して、

IndexOptions Charset=UTF-8

でいけることを突き止めました。これも当該ディレクトリ内だけで良いんでしょうけど、特に他で弊害もでなさそうだったので、グローバルに指定しておきました。これで、きちんと日本語ファイル名で表示でき、先の実験でダメだったPS3からの再生/DLもなぜか出来てしまいました。

ついでに、インデックスリストをカスタマイズするオプションを色々見つけたので、最終更新日付を非表示にする、.AVIファイルのdescriptionに「DivX/etc Video Files」と表示する、Thumb.dbを隠す、などカスタマイズ。外部スタイルシートも指定できました。

ざっとこんな感じ。

IndexOptions Charset=UTF-8
AddDescription "DivX/etc Video File" .avi

<Directory /xxxxx/xxxxx/video/>
  Options FollowSymLinks Indexes IncludesNOEXEC
  AllowOverride None
  IndexOptions SuppressLastModified SuppressHTMLPreamble HTMLTable
  IndexIgnore *.db *~
  IndexStyleSheet "video_list.css"
  EnableSendfile Off
</Directory>

PS3でDivXのプログレッシブダウンロード

PS3はファームウェア2.0から動画ファイルをダウンロードしながら再生する「プログレッシブダウンロード」に対応しました。基本的に、PlayStationStoreのMPEG4ファイル用と思ってたんですが、ふと思い立ってDivXなAVIファイルで実験。

できました!

適当なHTMLにリンク書いておけば、内蔵ブラウザでリンクを選択するだけで再生が始まります(PlayStationStoreのように再生するかどうかのボタンは出ない)。ローカルに保存することも可能。ただし、2バイト文字のファイル名はダメっぽいです。

PS3/40GBを購入した実家向けに、手軽に動画を見せる/渡す方法として地味に重宝しそうな予感。適当なポータル作っておいて、今度帰省した時にブックマーク登録してこよっと。

ウチのDivXファイル群はTeraStation上に保存してあるので、FTPかSMBでサーバーからマウントして、適当な半角英数ファイル名を生成するゲートウェイスクリプトを書いたら、帰省中の動画消化にも良いんじゃないかとか。