Skip to content

Commit b26970f

Browse files
committed
Merge branch 'main' of github.com:igfarm/roFrame
2 parents e12854f + 446efed commit b26970f

3 files changed

Lines changed: 67 additions & 89 deletions

File tree

app.py

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import zoneinfo
55
import time
66
from threading import Event
7-
import asyncio
7+
import asyncio
88
import logging
99

1010
from flask import Flask, render_template, jsonify, send_from_directory
@@ -21,9 +21,7 @@
2121
myRoonApi = None
2222

2323
app = Flask(__name__)
24-
socketio = SocketIO(
25-
app, cors_allowed_origins="*"
26-
)
24+
socketio = SocketIO(app, cors_allowed_origins="*")
2725
thread = None
2826
thread_stop_event = Event()
2927

@@ -34,13 +32,16 @@
3432
display_off_hour = int(os.getenv("DISPLAY_OFF_HOUR", 23))
3533
display_control = os.getenv("DISPLAY_CONTROL", "off")
3634
slideshow_enabled = os.getenv("SLIDESHOW", "on") == "on"
37-
slideshow_folder = os.getenv("SLIDESHOW_FOLDER", os.path.join(app.root_path, "./pictures"))
35+
slideshow_folder = os.getenv(
36+
"SLIDESHOW_FOLDER", os.path.join(app.root_path, "./pictures")
37+
)
3838
slideshow_transition_seconds = int(os.getenv("SLIDESHOW_TRANSITION_SECONDS", 15))
3939

4040
# Configure logging
4141
logging.basicConfig(level=logging.INFO)
4242
logger = logging.getLogger(__name__)
4343

44+
4445
def getRoonApi():
4546
global myRoonApi
4647
if myRoonApi is None:
@@ -63,7 +64,8 @@ def background_thread():
6364
"""
6465
while not thread_stop_event.is_set():
6566
myRoonApi = getRoonApi()
66-
state = myRoonApi.get_zone_state()
67+
album = myRoonApi.get_zone_data()
68+
state = album.get("state")
6769
if state == "playing":
6870
display(True)
6971
else:
@@ -79,12 +81,14 @@ def background_thread():
7981
@app.route("/")
8082
def index():
8183
images = []
82-
art_images = ["data:image/gif;base64,R0lGODdhAQABAIABAAAAAAAAACwAAAAAAQABAAACAkwBADs="]
84+
art_images = []
8385
if slideshow_enabled:
8486
images = os.listdir(slideshow_folder)
8587
image_extensions = {".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff"}
8688
images = [
87-
img for img in images if os.path.splitext(img)[1].lower() in image_extensions
89+
img
90+
for img in images
91+
if os.path.splitext(img)[1].lower() in image_extensions
8892
]
8993
if not images:
9094
art_images = [generate_mondrian() for _ in range(10)]
@@ -130,29 +134,20 @@ def handle_disconnect():
130134
def trigger_album_update():
131135
logger.info("trigger_album_update")
132136
myRoonApi = getRoonApi()
133-
copy = myRoonApi.get_copy()
134-
state = myRoonApi.get_zone_state()
135-
message = {
136-
"name": name,
137-
"album_cover_url": myRoonApi.get_image_url(image_size=image_size),
138-
"state": state,
139-
"image_size": image_size,
140-
"album_title": copy["title"],
141-
"album_artist": copy["artist"],
142-
"album_track": copy["track"],
143-
}
144-
asyncio.run(notify_clients(message)) # Use asyncio.run to await the coroutine
145-
146-
if state == "playing":
137+
album = myRoonApi.get_zone_data()
138+
asyncio.run(notify_clients(album)) # Use asyncio.run to await the coroutine
139+
140+
if album["state"] == "playing":
147141
display(True)
148142

149143

150144
async def notify_clients(message):
151145
logger.info("notify_clients")
152146
logger.info(message)
153147
socketio.emit("album_update", message)
154-
if "state" in message and message["state"] == "playing":
148+
if message.get("state") == "playing":
155149
display(True)
156150

151+
157152
if __name__ == "__main__":
158153
socketio.run(app, debug=True, port=port, host="0.0.0.0", allow_unsafe_werkzeug=True)

myroonapi.py

Lines changed: 44 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,18 @@
99

1010
class MyRoonApi:
1111

12+
BLACK_PIXEL = (
13+
"data:image/gif;base64,R0lGODdhAQABAIABAAAAAAAAACwAAAAAAQABAAACAkwBADs="
14+
)
15+
1216
def __init__(self) -> None:
1317
self.zone_name = os.environ.get("ROON_ZONE", None)
1418
self.core_id_fname = os.environ.get("ROON_CORE_ID_FNAME", "roon_core_id.txt")
1519
self.token_fname = os.environ.get("ROON_TOKEN_FNAME", "roon_token.txt")
1620
self.clients = set()
1721
self.notify_clients: Optional[Callable[[Dict[str, Any]], None]] = None
1822
self.logger = logging.getLogger(__name__)
23+
self.image_size = os.environ.get("IMAGE_SIZE", 600)
1924

2025
if self.zone_name is None:
2126
raise Exception(
@@ -52,10 +57,14 @@ def register(self) -> None:
5257
self.__save_credentials(api.core_id, api.token)
5358
api.stop()
5459

55-
def connect(self, notify_clients: Optional[Callable[[Dict[str, Any]], None]] = None) -> None:
60+
def connect(
61+
self, notify_clients: Optional[Callable[[Dict[str, Any]], None]] = None
62+
) -> None:
5663
self.roonapi = None
5764

58-
if not os.path.exists(self.core_id_fname) or not os.path.exists(self.token_fname):
65+
if not os.path.exists(self.core_id_fname) or not os.path.exists(
66+
self.token_fname
67+
):
5968
self.logger.info("Please authorise first using discovery.py")
6069
exit()
6170

@@ -72,55 +81,47 @@ def connect(self, notify_clients: Optional[Callable[[Dict[str, Any]], None]] = N
7281

7382
self.logger.info(server)
7483
self.roonapi = RoonApi(self.appinfo, token, server[0], server[1], True)
75-
7684
self.notify_clients = notify_clients
77-
self.roonapi.register_queue_callback(self.__queue_callback, self.get_zone_id())
85+
86+
album = self.get_zone_data()
87+
88+
self.roonapi.register_queue_callback(
89+
self.__queue_callback, album["zone_id"]
90+
)
7891
self.roonapi.register_state_callback(self.__state_callback)
7992
except OSError:
8093
self.logger.info("Please authorise first using discovery.py")
8194
exit()
8295

83-
def get_zone_id(self) -> Optional[str]:
96+
def get_zone_data(self) -> Optional[str]:
8497
roonapi = self.__get_roonapi()
8598
for zone_id, zone_info in roonapi.zones.items():
8699
if zone_info["display_name"] == self.zone_name:
87-
return zone_id
88-
return None
89-
90-
def get_zone_state(self) -> Optional[str]:
91-
roonapi = self.__get_roonapi()
92-
zone_id = self.get_zone_id()
93-
if zone_id:
94-
return roonapi.zones[zone_id]["state"]
95-
return None
96-
97-
def get_image_url(self, image_size: int = 600) -> str:
98-
# start with a single pixel gif
99-
image_url = "data:image/gif;base64,R0lGODdhAQABAIABAAAAAAAAACwAAAAAAQABAAACAkwBADs="
100-
if self.get_zone_state() in ["playing", "paused"]:
101-
roonapi = self.__get_roonapi()
102-
zone_id = self.get_zone_id()
103-
if zone_id:
104-
zone = roonapi.zones[zone_id]
105-
if "now_playing" in zone:
106-
image_key = zone["now_playing"]["image_key"]
107-
image_url = roonapi.get_image(image_key, width=image_size, height=image_size)
108-
return image_url
109-
110-
def get_copy(self) -> Dict[str, str]:
111-
if self.get_zone_state() == "playing":
112-
roonapi = self.__get_roonapi()
113-
zone_id = self.get_zone_id()
114-
if zone_id:
115100
zone = roonapi.zones[zone_id]
101+
# pprint(zone )
102+
data = {
103+
"state": zone["state"],
104+
"zone_id": zone_id,
105+
"url": self.BLACK_PIXEL,
106+
"artist": "",
107+
"title": "",
108+
"track": "",
109+
}
116110
if "now_playing" in zone:
117-
lines = zone["now_playing"]["three_line"]
118-
return {
119-
"artist": lines["line2"],
120-
"title": lines["line3"],
121-
"track": lines["line1"],
122-
}
123-
return {"artist": "", "title": "", "track": ""}
111+
data.update(self.__get_album_data(zone["now_playing"]))
112+
return data
113+
return None
114+
115+
def __get_album_data(self, now_playing) -> Dict[str, Any]:
116+
return {
117+
"image_size": self.image_size,
118+
"artist": now_playing["three_line"]["line2"],
119+
"title": now_playing["three_line"]["line3"],
120+
"track": now_playing["three_line"]["line1"],
121+
"url": self.roonapi.get_image(
122+
now_playing["image_key"], width=self.image_size, height=self.image_size
123+
),
124+
}
124125

125126
def __save_credentials(self, core_id: str, token: str) -> None:
126127
with open(self.core_id_fname, "w") as f:
@@ -130,18 +131,9 @@ def __save_credentials(self, core_id: str, token: str) -> None:
130131

131132
def __state_callback(self, event: str, changed_items: Any) -> None:
132133
if event == "zones_changed":
133-
state = self.get_zone_state()
134-
copy = self.get_copy()
135-
url = self.get_image_url()
136-
evdata = {
137-
"album_artist": copy["artist"],
138-
"album_title": copy["title"],
139-
"album_track": copy["track"],
140-
"album_cover_url": url,
141-
"state": state,
142-
}
134+
data = self.get_zone_data()
143135
if self.notify_clients:
144-
asyncio.run(self.notify_clients(evdata))
136+
asyncio.run(self.notify_clients(data))
145137

146138
def __get_roonapi(self) -> RoonApi:
147139
if self.roonapi is None:
@@ -161,14 +153,5 @@ def __queue_callback(self, data: Dict[str, Any]) -> None:
161153
self.logger.info("queue_callback")
162154
album = self.__extract_album(data)
163155
if album and self.notify_clients:
164-
img = self.roonapi.get_image(album["image_key"], width=600, height=600)
165-
evdata = {
166-
"album_artist": album["three_line"]["line2"],
167-
"album_title": album["three_line"]["line3"],
168-
"album_track": album["three_line"]["line1"],
169-
"album_cover_url": img,
170-
"state": self.get_zone_state(),
171-
}
156+
evdata = self.__get_album_data(album)
172157
asyncio.run(self.notify_clients(evdata))
173-
174-

templates/index.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
socket.on('album_update', function(data) {
7575
console.log('Album update received:', data)
7676

77-
if (data.album_cover_url !== undefined) {
77+
if (data.url !== undefined) {
7878
console.log("updating album");
7979

8080
if (data.state === 'playing') {
@@ -83,10 +83,10 @@
8383
document.getElementById('album_track').style.fontSize = '1px';
8484

8585
document.getElementById('album_info').classList.remove('d-none');
86-
document.getElementById('album_img').src = data.album_cover_url;
87-
document.getElementById('album_artist').innerText = data.album_artist;
88-
document.getElementById('album_title').innerText = data.album_title;
89-
document.getElementById('album_track').innerText = data.album_track;
86+
document.getElementById('album_img').src = data.url;
87+
document.getElementById('album_artist').innerText = data.artist;
88+
document.getElementById('album_title').innerText = data.title;
89+
document.getElementById('album_track').innerText = data.track;
9090

9191
let size = getFonteSize(document.getElementById('album_artist').innerText, 40, 80);
9292
document.getElementById('album_artist').style.fontSize = size + 'px';

0 commit comments

Comments
 (0)