You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Extract a GUI-agnostic casting controller from the Tkinter app so the same engine can drive a web backend, an Android app, and the headless/CLI mode (#5). This is the prerequisite for the web (#) and Android (#) tracks.
Why it's cheap
The engine in cast_to_tv.py is already ~70% GUI-free — discovery (fast_discover, find_dlna_service, discover_chromecasts, discover_airplay), DLNA control (cast_video, get_position, seek_to, stop/pause/resume_playback, _soap_call), the media servers (RangeRequestHandler, HTTPServerThread, SilentThreadingTCPServer), and the streamers (YoutubeStreamer, RadioStreamer, DongleCaster, MediaSource) are all callback-driven with zero Tkinter references. Only the dispatch glue and session state live on KeygenApp.
Scope
New CastingController that owns what's currently on the GUI object: the active streamers (youtube_streamer / radio_streamer / dongle_caster / http_server), the Chromecast/AirPlay session state (_cc_casts, _cc_browser, _airplay_confs, _aloop), device_list, server_port, pause/seek state.
Move the dispatch logic into it: play_on, cast_to_all, _dedupe_targets, _play_chromecast, _play_airplay, _discover_chromecasts, _discover_airplay, and the "which streamer for which source" orchestration currently inside do_cast.
Replace the self.log GUI callback with a generic event/callback hook (status + device-found + state-change events) so any frontend can subscribe.
KeygenApp (Tkinter) becomes a thin frontend calling the controller — behaviour unchanged. Same controller backs CLI (Headless / CLI mode (no GUI) #5), web (#), and mobile (#).
Acceptance
CastingController drives a full discover → cast → pause/seek/stop cycle with no Tkinter imported.
Tkinter GUI refactored to call the controller; existing behaviour identical (regression-tested against a real DLNA dongle).
Events exposed via callback (no self.log coupling).
Foundation for the web/Android roadmap; overlaps with #5 (headless CLI).
Summary
Extract a GUI-agnostic casting controller from the Tkinter app so the same engine can drive a web backend, an Android app, and the headless/CLI mode (#5). This is the prerequisite for the web (#) and Android (#) tracks.
Why it's cheap
The engine in
cast_to_tv.pyis already ~70% GUI-free — discovery (fast_discover,find_dlna_service,discover_chromecasts,discover_airplay), DLNA control (cast_video,get_position,seek_to,stop/pause/resume_playback,_soap_call), the media servers (RangeRequestHandler,HTTPServerThread,SilentThreadingTCPServer), and the streamers (YoutubeStreamer,RadioStreamer,DongleCaster,MediaSource) are all callback-driven with zero Tkinter references. Only the dispatch glue and session state live onKeygenApp.Scope
CastingControllerthat owns what's currently on the GUI object: the active streamers (youtube_streamer/radio_streamer/dongle_caster/http_server), the Chromecast/AirPlay session state (_cc_casts,_cc_browser,_airplay_confs,_aloop),device_list,server_port, pause/seek state.play_on,cast_to_all,_dedupe_targets,_play_chromecast,_play_airplay,_discover_chromecasts,_discover_airplay, and the "which streamer for which source" orchestration currently insidedo_cast.self.logGUI callback with a generic event/callback hook (status + device-found + state-change events) so any frontend can subscribe.KeygenApp(Tkinter) becomes a thin frontend calling the controller — behaviour unchanged. Same controller backs CLI (Headless / CLI mode (no GUI) #5), web (#), and mobile (#).Acceptance
CastingControllerdrives a full discover → cast → pause/seek/stop cycle with no Tkinter imported.self.logcoupling).Foundation for the web/Android roadmap; overlaps with #5 (headless CLI).