-
Notifications
You must be signed in to change notification settings - Fork 0
/
chromecast2lox.py
136 lines (107 loc) · 4.1 KB
/
chromecast2lox.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import time
import socket
import sys
import pychromecast
from pychromecast.controllers.media import MediaStatusListener
from pychromecast.controllers.receiver import CastStatusListener
def send_udp_message(udp_message):
print(udp_message)
class MyCastStatusListener(CastStatusListener):
"""Cast status listener"""
def __init__(self, name, cast):
self.name = name
self.cast = cast
def new_cast_status(self, status):
print(f"[{time.ctime()} - {self.name}] status chromecast change: {status}")
volume = int(round(status.volume_level * 100))
app_name = status.display_name
send_udp_message(f"{self.name}/volume/{volume}")
if app_name:
send_udp_message(f"{self.name}/app/{app_name}")
class MyMediaStatusListener(MediaStatusListener):
"""Status media listener"""
def __init__(self, name, cast):
self.name = name
self.cast = cast
def new_media_status(self, status):
print(f"[{time.ctime()} - {self.name}] status media change: {status}")
volume = int(round(status.volume_level * 100))
artist = status.artist
song = status.title
album = status.album_name
playback_status = status.player_state
send_udp_message(f"{self.name}/volume/{volume}")
if artist:
send_udp_message(f"{self.name}/artist/{artist}")
if song:
send_udp_message(f"{self.name}/song/{song}")
if album:
send_udp_message(f"{self.name}/album/{album}")
if playback_status:
send_udp_message(f"{self.name}/status/{playback_status}")
def load_media_failed(self, item, error_code):
print(
"[",
time.ctime(),
" - ",
self.name,
"] load media filed for item: ",
item,
" with code: ",
error_code,
)
# Function to handle incoming UDP commands
def handle_udp_commands(data):
data = data.decode('utf-8')
print(f"Request received: {data}")
command = data.strip().split('/')
if len(command) == 3:
cast_name, cmd, value = command
cast_name = cast_name.strip()
cmd = cmd.strip()
for chromecast in chromecasts:
if chromecast.name == cast_name:
if cmd == "play":
chromecast.media_controller.play()
elif cmd == "pause":
chromecast.media_controller.pause()
elif cmd == "stop":
chromecast.media_controller.stop()
elif cmd == "next":
chromecast.media_controller.skip()
elif cmd == "rewind":
chromecast.media_controller.rewind()
elif cmd == "spotify":
chromecast.start_app("CC32E753")
elif cmd == "incvol":
chromecast.volume_up()
elif cmd == "decvol":
chromecast.volume_down()
elif cmd == "setvol" and value.isdigit():
volume = int(value)
if 0 <= volume <= 100:
chromecast.set_volume(volume / 100)
chromecasts, browser = pychromecast.get_chromecasts()
if not chromecasts:
print(f'No chromecasts discovered')
sys.exit(1)
for chromecast in chromecasts:
# Start socket client's worker thread and wait for initial status update
chromecast.wait()
listenerCast = MyCastStatusListener(chromecast.name, chromecast)
chromecast.register_status_listener(listenerCast)
listenerMedia = MyMediaStatusListener(chromecast.name, chromecast)
chromecast.media_controller.register_status_listener(listenerMedia)
# Create a UDP socket
my_hostname = socket.gethostname()
my_ip_address = socket.gethostbyname(my_hostname)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((my_ip_address, 4444))
try:
while True:
print("####### Server is listening #######")
data, address = s.recvfrom(4096)
handle_udp_commands(data)
except KeyboardInterrupt:
# Shut down discovery
browser.stop_discovery()