Last active
December 16, 2023 23:19
-
-
Save alexrecuenco/1f8e3d0edbe5e3a754e11b3ea38f127b to your computer and use it in GitHub Desktop.
Using PyChromecast to change the volume of a chrome cast device (Useful since VLC doesn't provide volume controls)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# requirement: PyChromecast==12.1.4 | |
# version 0.1 | |
import pychromecast | |
import argparse | |
from typing import List, Union | |
import dataclasses | |
UP = "up" | |
DOWN = "down" | |
UP_OPTIONS = set([UP, "up", "u", "raise", "r"]) | |
DOWN_OPTIONS = set([DOWN, "d", "lower", "l"]) | |
class Daemon: | |
cast: pychromecast.Chromecast | |
amount: float | |
def start(self): | |
self.cast.start() | |
self.cast.wait() | |
def __init__(self, cast: pychromecast.Chromecast, amount: float): | |
self.cast = cast | |
self.amount = amount | |
self.start() | |
def run(self, cmd: str, amount: float = 0.1): | |
if cmd in UP_OPTIONS: | |
self.cast.volume_up(self.amount) | |
elif cmd in DOWN_OPTIONS: | |
self.cast.volume_down(self.amount) | |
else: | |
try: | |
volume = int(cmd) | |
self.cast.set_volume(volume / 100) | |
except: | |
raise TypeError("Incorrect command") | |
@dataclasses.dataclass | |
class Options: | |
cmds: List[str] | |
amount: float | |
name: str | |
daemon: bool | |
def parse_args() -> Options: | |
parser = argparse.ArgumentParser("Chromecast remote control") | |
parser.add_argument( | |
"--cmds", | |
nargs="*", | |
choices=[UP, DOWN], | |
help="Commands to execute on chromecast", | |
default=[], | |
) | |
parser.add_argument( | |
"-a", | |
"--amount", | |
type=float, | |
default=0.1, | |
help="Amount of volumen to increase/decrease", | |
) | |
parser.add_argument( | |
"-n", | |
"--name", | |
default="living", | |
help="Name that identifies the specific chromecast (Will choose only the first one it finds)", | |
) | |
parser.add_argument( | |
"--daemon", dest="daemon", action="store_true", help="Activate daemon" | |
) | |
parser.add_argument( | |
"--no-daemon", dest="daemon", action="store_false", help="De-activate daemon" | |
) | |
parser.set_defaults(daemon=True) | |
parsed = parser.parse_args() | |
return Options( | |
cmds=parsed.cmds, | |
amount=parsed.amount, | |
name=parsed.name.lower(), | |
daemon=parsed.daemon, | |
) | |
def main(): | |
options = parse_args() | |
chromecasts = pychromecast.get_chromecasts() | |
cc_list = [cc for ccs in chromecasts if isinstance(ccs, list) for cc in ccs] | |
if len(cc_list) > 1: | |
print("All devices available ", [cc.name for cc in cc_list]) | |
name = options.name | |
cast: Union[pychromecast.Chromecast, None] = next( | |
(cc for cc in cc_list if name in cc.name.lower()), | |
None, | |
) | |
if cast is None: | |
print("No device found with name", name) | |
exit(1) | |
print("Connected to", cast.name) | |
amount = options.amount | |
daemon = Daemon(cast, amount) | |
msg = "Input one of " + ", ".join([UP, DOWN]) + ", or a number\n" | |
for cmd in options.cmds: | |
daemon.run(cmd, amount) | |
if options.daemon: | |
while True: | |
cmd = input(msg) | |
try: | |
daemon.run(cmd, amount) | |
except TypeError: | |
print("WARN: Incorrect command") | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment