プログラムの話ですよ

まぁそういう関係のお仕事してますしね。
プライベートでも少しは活用しようかと思いました。

分かる人だけ分かるヒントになってますので、プログラムとか分からない人は、
わかる人にこのページを紹介して、スクリプトを作ってもらってくださいw

背景

こちらの記事で書いたとおり、新しくテレビを買ってパソコンと
つないでるんですね。

前のテレビでも同じようにつないでたんですが、ケーブルは
「DVI-D」を使っていて、「映像だけ送り出し」でした。
今回それが「HDMI」に変わりまして、「映像信号」だけでなく
「音声信号」も送り出せるようになりました。

そうすると何が変わるかというと、今までは「パソコンでブルーレイ再生」した場合、
  「映像はテレビから出てるけど、音声はパソコンのスピーカーから出てる」
みたいなちぐはぐな状況になってまして、ちょっと無駄に大きめに音出さないと、
とかいろいろ不満あったんです。それが今回のHDMI化により、
  「テレビでパソコン見る時は、音もテレビから出る」
というのが実現できる、と。普通のことが普通にできるようになるわけ。


ただ、ちょっと面倒なことがありまして。
  • 映像をパソコンモニタ出力からテレビ出力に切り替えるためにパソコンの設定操作が必要
  • 同じく、音声をパソコン側出力からテレビ出力に切り替えるためにパソコンの設定操作が必要
  • 配置の都合上、テレビおいてるソファの位置からパソコンモニタが見えない=設定操作ができない
つまり、切り替えるためにいちいちマウスでカチカチカチカチとクリックしまくる
必要があるんだけど、そういう面倒ごとは何とかしたいですよね。
というのがこの記事のスタートラインです。


なお、パソコンとテレビの解像度が同じでよければ、
映像出力先設定を「複製」にしておくだけでもいいんですよね。

ただ、新しく買ったテレビは解像度4Kなので、モニタと解像度が違う。
「複製」ではだめなんですよね。

#最終的にはこちらの記事のとおりフルHDまで解像度落とすことに
#なったわけですが、それはまた別のお話。

やりたいこと&アプローチ

整理すると、やりたいことはこんな感じ
  • パソコンの設定操作(映像出力切り替えと音声出力切り替え)を簡単にしたい
  • パソコンのモニタが見えない状態でも切り替えできるようにしたい
  • 対象OSはWindows 10
解決策はまぁあれですね。
バッチファイルとかスクリプトで上記を実施しちゃえるように。
かつ、それをキーボードショートカットで呼び出せるように。

やるためのパーツ

ここでは要素だけ簡単にご説明。

映像出力先切り替え

Windows 10の場合、「Windowsキー」+「P」を押すと、
出力先を切り替えるメニューが出てきますね。
メニュー

これをやればいいわけですが、プログラム的に(バッチ的に)
やるにはどうしましょうか、という話。

答:以下のコマンドを呼び出してください。
DisplaySwitch /internal
または以下です。
DisplaySwitch /external

これで、「PC画面のみ」「セカンドスクリーンのみ」のどちらかを
押したときの動きになります。コマンドプロンプトからやってみると
なんとなくイメージつかめると思いますので、どうぞ。

音声出力先切り替え

Windows 10の場合、音声出力先は、「コントロールパネル」の
「ハードウェアとサウンド」「サウンド」の「オーディオデバイスの管理」
から切り替えますね。
音声メニュ
これで、テレビ側に切り替える場合はテレビに接続している
HDMI Outputデバイスを選択し、「規定値に設定」して「OK」を押す、
パソコン側に切り替える場合は「スピーカー」を選択し、「規定値に設定」
して「OK」を押す、という感じです。さて。

答:上記メニューは以下コマンドで呼び出せます。
control mmsys.cpl
ここから、先ほどの「何番目を選択し、規定値に設定してOKを押す」
という操作を、コマンドラインから実現してやればよいわけ。
WSHでいうところの「SendKeys」 を使ってごにょごにょすればいいわけです。 
詳しくはここのページをパクればいいと思います。私はぱくりました。

→ Windows でサウンドの再生デバイスを切り替えるためのスクリプト(バッチ処理)

ショートカットによる呼び出し

さて、上記の切り替えを行うスクリプトを、たとえば
「hogehoge.js pc」と呼び出した場合、音声&映像出力をPC側に、
「hogehoge.js tv」と呼び出した場合、音声&映像出力をTV側に、
と切り替えるような感じで作ればいいですね。

あとは、これを、ショートカットキーのような形で
呼び出せるようにすればよい。

答:ショートカットを作成してください。
で、ショートカットのプロパティから、
  • 「リンク先」のスクリプトを引数付きで呼び出すように変更してください。
  • 「ショートカットキー」を選択し、好きなショートカットキーを充ててください。
ショートカットプロパティ

うちの場合、デスクトップで「Ctrl + Alt + 1」を押せば出力先をパソコンに、
「Ctrl + Alt + 2」を押せばテレビに切り替わるようにしましたよ。
ついでに「Ctrl + Alt + 3」なら出力先をパソコンに切り替えたうえでパソコンを
シャットダウンするようにしました。まぁそれは運用上のおまけ。

さあ!

みんなで頑張って組もう!w
いいのができたらくださいw

サンプル

今私が使ってるスクリプト。こちらの動作保証はいたしかねます。
中身読んで、理解できた人だけ使ってください。
(なんか間違ってても、直す気ありませんw)
var wait = function(title){
    do {
WScript.Sleep(100);
    } while(!WshShell.AppActivate(title));
};

var WshShell =  WScript.CreateObject("WScript.Shell");

var sound;
var disp;

if (WScript.Arguments.item(0) == "pc"){
  sound = 5;
  disp = "/external";
}
else if (WScript.Arguments.item(0) == "pcdown"){
  sound = 5;
  disp = "/external";
}
else{
  sound = 4;
  disp = "/internal";
}

var WshShell2 = WScript.CreateObject("WScript.Shell");
WshShell2.Run("DisplaySwitch " + disp,1,true);
WScript.Sleep(2000)
WshShell.Run("control mmsys.cpl");
wait("サウンド");
WshShell.SendKeys("{DOWN " + 
sound +
"}%{s}{TAB 3}{ENTER}");
if (WScript.Arguments.item(0) == "pcdown"){
  WScript.Sleep(5000);
  var WshShell3 = WScript.CreateObject("WScript.Shell");
  WshShell3.Run("shutdown /s /f /t 0");
}

コメントは以下です。
  • 少なくとも「WScript.Sleep(数値)」の部分と「sound = 数値」の部分は各自の環境向けに調整要です。
  •  このやり方の場合、ショートカット押す前にいったんログインが必要なので、本当はログイン待機画面からでもショートカットで動かせるのが理想。
  • 「Run」で第三引数「true」したらコマンド終了まで待ちになるらしいので、その後のWScript.Sleep(2000)は要らないはずなんですけど、無いとうまくいかないんですよねぇ。なんでだろう。