From 5427fc8b5a6bdbd79ba7af7df2011fe2f2bd7403 Mon Sep 17 00:00:00 2001 From: David Greaves Date: Fri, 18 Jul 2025 19:44:28 +0100 Subject: [PATCH 1/4] Expose Snapclient, Snapgroup and Snapstream These are useful for typing Signed-off-by: David Greaves --- snapcast/control/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/snapcast/control/__init__.py b/snapcast/control/__init__.py index ec6ad3e..b575a84 100644 --- a/snapcast/control/__init__.py +++ b/snapcast/control/__init__.py @@ -1,6 +1,9 @@ """Snapcast control for Snapcast 0.11.1.""" from snapcast.control.server import Snapserver, CONTROL_PORT +from snapcast.control.client import Snapclient +from snapcast.control.stream import Snapstream +from snapcast.control.group import Snapgroup async def create_server(loop, host, port=CONTROL_PORT, reconnect=False): From f6debf5d4ecc391be3c27a906ed8375c76bb4473 Mon Sep 17 00:00:00 2001 From: David Greaves Date: Fri, 18 Jul 2025 19:46:05 +0100 Subject: [PATCH 2/4] Add a stream attribute to a Snapclient In keeping with the existing group attribute Signed-off-by: David Greaves --- snapcast/control/client.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/snapcast/control/client.py b/snapcast/control/client.py index af14496..67a4804 100644 --- a/snapcast/control/client.py +++ b/snapcast/control/client.py @@ -34,6 +34,12 @@ def group(self): return group return None + @property + def stream(self): + """Get stream.""" + g = self.group + return self._server.stream(g.stream) if g else None + @property def friendly_name(self): """Get friendly name.""" From 58cc9804e0c6c4af1a5ab86dee18ed3eebe63b7d Mon Sep 17 00:00:00 2001 From: David Greaves Date: Fri, 18 Jul 2025 19:48:05 +0100 Subject: [PATCH 3/4] Add a complete working example.py and reference it in the README Note this uses the client.stream attribute Signed-off-by: David Greaves --- README.md | 2 ++ example.py | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 example.py diff --git a/README.md b/README.md index 2bdd608..5cb0bf1 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,8 @@ server.clients[0].set_callback(my_update_func) loop.run_forever() ``` +See `example.py` for a basic working example. + ### Client Note: This is experimental. Synchronization is not yet supported. Requires GStreamer 1.0. diff --git a/example.py b/example.py new file mode 100644 index 0000000..40e0d26 --- /dev/null +++ b/example.py @@ -0,0 +1,48 @@ +import argparse +import asyncio +import snapcast.control +import logging +import signal + + +def changed(client): + print(client) + print(f"{client.friendly_name} volume {client.volume}" + f" playing: {client.stream}") + + +async def main(host): + server = snapcast.control.Snapserver( + asyncio.get_running_loop(), host) + + # Handle signals + waiter = asyncio.Event() + loop = asyncio.get_event_loop() + loop.add_signal_handler(signal.SIGTERM, waiter.set) + loop.add_signal_handler(signal.SIGINT, waiter.set) + + await server.start() + + for client in server.clients: + print(f"Setting callback for {client}") + client.set_callback(changed) + + for g in server.groups: + print(g) + + for s in server.streams: + print(s) + + await waiter.wait() + server.stop() + +if __name__ == "__main__": + + parser = argparse.ArgumentParser(description="snapcast example") + parser.add_argument("host", help="mpd hostname") + args = parser.parse_args() + + logging.basicConfig(level="DEBUG") + logging.getLogger("snapcast.control.server").setLevel("DEBUG") + + asyncio.run(main(host=args.host)) From 9064c7a4a80a0ec38d4baeca651813c91b1469b4 Mon Sep 17 00:00:00 2001 From: David Greaves Date: Fri, 18 Jul 2025 19:49:46 +0100 Subject: [PATCH 4/4] Change key from deprecated hyphen form to use underscore Signed-off-by: David Greaves --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index b88034e..08aedd7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,2 @@ [metadata] -description-file = README.md +description_file = README.md