トイレとか食事の時にヘッドフォンを外してYoutubeやらMusicやらを止めて...ってやるのがめんどくさかったのでヘッドフォンを置いた時に勝手に止めるようなデバイスを作りました。
デバイスと言いつつほとんどソフトウェア側の実装です。
また、MacOSでしか動きません。
完成したコードはここからダウンロードできます
用意するもの
- ヘッドフォン
- パソコン(MacOS以外は想定してないです)
- Arduino(Arduino IDEで書き込めれば何でも良い)
- リードスイッチ(磁石に反応するセンサ)
- 磁石
リードスイッチじゃなくても大丈夫です。スイッチとか
組み立て
Arduinoとリードスイッチを以下のように接続します。
https://learn.sparkfun.com/tutorials/reed-switch-hookup-guide?_ga=2.265836815.1235452650.1682338515-855519520.1682338515 より引用
デバイスは以下のようなものを作成しました。
スタンドの上部にリードスイッチをつけ、スタンドとヘッドフォンが接触する場所に磁石をつけます。こうすることでリードスイッチが反応するので置いたかどうか判断できます。
コード
Arduinoに書き込むコードです。
const int REED = 2;
bool is_placed = false;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(REED, INPUT_PULLUP);
}
void loop() {
// put your main code here, to run repeatedly:
int prox = digitalRead(REED);
if (prox == 0) {
if (is_placed == false) {
Serial.println("detected");
is_placed = true;
}
} else {
if (is_placed == true) {
is_placed = false;
}
}
delay(500);
}
やってることはREEDピンからの値が0になったら"detected"
と出力しているだけです。何度も"detected"
を送るのが嫌なので前フレームで出力した時は出力しないようにしています。
ブラウザやアプリを直接操作するためにAppleScriptを使います。
AppleScriptのコードです。
to muteSafari()
if application "Safari" is running then
tell application "Safari"
try
set windowcount to number of windows
--ウィンドウ数でループ
repeat with x from 1 to windowcount
--タブ数でループ
set tabcount to number of tabs in window x
repeat with y from 1 to tabcount
set tabName to name of tab y of window x
set tabURL to URL of tab y of window x
set temp to "youtube"
--タブのurlにyoutubeという文字が含まれていたら
if (offset in tabURL of temp) > 0 then
--再生中か否かを取得
set isPaused to (do JavaScript "document.querySelector('#movie_player video').paused" in tab y of window x)
--再生中なら再生ボタンをクリックし、停止
if isPaused = false then
set theScript to "document.getElementsByClassName('ytp-play-button')[0].click()"
do JavaScript theScript in tab y of window x
end if
end if
end repeat
end repeat
end try
end tell
end if
end muteSafari
to muteMusic()
--Musicが再生中なら
if application "Music" is running then
--音楽を止める
tell application "Music" to pause
end if
end muteMusic
to muteChrome()
if application "Google Chrome" is running then
tell application "Google Chrome"
try
set windowcount to number of windows
repeat with z from 1 to windowcount
set tabcount to number of tabs in window z
repeat with w from 1 to tabcount
--Get Tab Name & URL
set tabName to title of tab w of window z
set tabURL to URL of tab w of window z
set temp to "youtube"
if (offset in tabURL of temp) > 0 then
set isPaused to (execute of tab w of window z javascript "document.querySelector('#movie_player video').paused")
if isPaused = false then
set theScript to "document.getElementsByClassName('ytp-play-button')[0].click()"
execute of tab w of window z javascript theScript
end if
end if
end repeat
end repeat
end try
end tell
end if
end muteChrome
muteSafari()
muteMusic()
muteChrome()
とても見辛いのですが、やっていることは
- SafariのYoutubeを止める
- ChromeのYoutubeを止める
- Musicを止める
の三つです。関数はそれぞれmuteSafari
,muteChrome
,muteMusic
です。
Arduinoからの出力を受け取るPythonコードを書きます。
import serial
import atexit
import subprocess
import sys
import os
ser = serial.Serial("シリアルポート名", 115200)
def all_done():
# 終了時の処理
print("\nDone!")
ser.close()
def main():
atexit.register(all_done)
try:
while(True):
line = ser.readline().strip().decode('utf-8')
# 何かしらのトリガーがあったらスクリプトを実行する。
# 今回はシリアルモニタから"detected"という文字列が送られてきたら実行する。
if line == "detected":
subprocess.run(["osascript", "/path/to/stopyoutube.scpt"])
print("stopped!")
except KeyboardInterrupt:
sys.exit(0)
if __name__ == "__main__":
main()
シリアルモニタを読んで、"detected"
を検知したら先ほどのAppleScriptを実行しているだけです。
動かす
$ python runapplescript.py
ブラウザで動かしていたYoutube、Musicが止まれば成功です
ありがとうございました。