sane-cast: add a menu for choosing which device to cast to whenever there are multiple
This commit is contained in:
@@ -184,7 +184,6 @@ in
|
||||
|
||||
suggestedPrograms = [
|
||||
"blast-to-default"
|
||||
"go2tv"
|
||||
"sane-cast"
|
||||
"sane-die-with-parent"
|
||||
"xdg-terminal-exec"
|
||||
@@ -199,7 +198,7 @@ in
|
||||
sandbox.whitelistWayland = true;
|
||||
sandbox.extraHomePaths = [
|
||||
".config/mpv" #< else mpris plugin crashes on launch
|
||||
".local/share/applications" #< for xdg-terminal-exec (go2tv)
|
||||
".local/share/applications" #< for xdg-terminal-exec (sane-cast)
|
||||
# it's common for album (or audiobook, podcast) images/lyrics/metadata to live adjacent to the primary file.
|
||||
# CLI detection is too poor to pick those up, so expose the common media dirs to the sandbox to make that *mostly* work.
|
||||
"Books/local"
|
||||
|
@@ -35,4 +35,3 @@ O script-binding uosc/show-in-directory #! Utils > Show in directory
|
||||
# script-binding uosc/open-config-directory #! Utils > Open config directory
|
||||
ctrl+r script-binding sane_cast/blast #! Audiocast
|
||||
ctrl+t script-binding sane_cast/sane-cast #! Cast
|
||||
# script-binding sane_cast/go2tv-gui #! Cast (...) > GUI
|
||||
|
@@ -29,14 +29,12 @@ function invoke_paused(in_terminal, args)
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- invoke blast in a way where it dies when we die, because:
|
||||
-- 1. when mpv exits, it `SIGKILL`s this toplevel subprocess.
|
||||
-- 2. `blast-to-default` could be a sandbox wrapper.
|
||||
-- 3. bwrap does not pass SIGKILL or SIGTERM to its child.
|
||||
-- 4. hence, to properly kill blast, we have to kill all the descendants.
|
||||
mp.add_key_binding(nil, "blast", function() subprocess(false, { "sane-die-with-parent", "--descendants", "--use-pgroup", "--catch-sigkill", "blast-to-default" }) end)
|
||||
mp.add_key_binding(nil, "go2tv-gui", function() invoke_paused(false, { "go2tv" }) end)
|
||||
mp.add_key_binding(nil, "sane-cast", function() invoke_paused(true, { "sane-cast", "--verbose", "@FILE@" }) end)
|
||||
|
||||
msg.trace("load: complete")
|
||||
|
@@ -3,7 +3,8 @@
|
||||
# vim: set filetype=python :
|
||||
"""
|
||||
cast media (local video or audio files) to a device on the same network
|
||||
with some awareness of device-specific quirks.
|
||||
with some awareness of device-specific quirks
|
||||
and a menu to select a device if there's more than one online
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
@@ -133,6 +134,34 @@ class Go2TvDriver:
|
||||
os.execvp("go2tv", cli_args)
|
||||
|
||||
|
||||
def choose_device(devices: list[Device]) -> Device | None:
|
||||
if not devices:
|
||||
logger.info("no devices found!")
|
||||
return
|
||||
|
||||
if len(devices) == 1:
|
||||
return devices[0]
|
||||
|
||||
dev = None
|
||||
while dev is None:
|
||||
# TODO: use a GUI menu like zenity?
|
||||
print("choose a device:")
|
||||
for i, d in enumerate(devices):
|
||||
print(f"[{i + 1}] {d.model}")
|
||||
print("[q] quit")
|
||||
print("")
|
||||
print("> ", end="")
|
||||
|
||||
choice = input()
|
||||
if choice.strip() == "q":
|
||||
return
|
||||
try:
|
||||
dev = devices[int(choice.strip()) - 1]
|
||||
except:
|
||||
print(f"invalid choice {choice!r}")
|
||||
|
||||
return dev
|
||||
|
||||
def main():
|
||||
logging.basicConfig()
|
||||
logging.getLogger().setLevel(logging.INFO)
|
||||
@@ -149,19 +178,10 @@ def main():
|
||||
go2tv = Go2TvDriver()
|
||||
go2tv.scan_devices()
|
||||
devices = go2tv.rank_devices()
|
||||
if not devices:
|
||||
logger.info("no devices found! exiting")
|
||||
return
|
||||
|
||||
for d in devices:
|
||||
logger.info(f"found: {d.model}")
|
||||
|
||||
if len(devices) != 1:
|
||||
logger.info("found multiple devices! exiting")
|
||||
# TODO: allow choosing, or a "--yes" option
|
||||
return
|
||||
|
||||
go2tv.cast_to(devices[0], args.media)
|
||||
dev = choose_device(devices)
|
||||
if dev:
|
||||
go2tv.cast_to(dev, args.media)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
Reference in New Issue
Block a user