ability to only run specified Stream Decks instead of all attached decks - #227
ability to only run specified Stream Decks instead of all attached decks#227violet4 wants to merge 2 commits into
Conversation
…cks. achieved by adding `--list` and `--paths` command line arguments. `--list` lists all the attached Stream Deck devices with some basic information, including their "paths", and exits `--paths` takes 1 or more paths (found via `--list`) and filters out paths not specified before initializing the devices
|
Nice work! In the future we can maybe even add an option to the settings for this. The only problem I'm encountering is that if I instance is already running and |
|
tl;dr go ahead and close this PR when you see my message and i'll eventually submit a better one that handles more cases. also my PR doesn't work so great if the externally managed stream deck is connected while StreamController is already running, since StreamController seems to watch new stream deck connections and attach to them automatically. so clearly, this naïve/lazy PR isn't going to work for most use cases and i'm gonna have to put some more work into making it more robust and generally acceptable. i'm not in any rush to make this super fully integrated and handle all cases, but i'm thinking this PR should be closed and i can use my own branch for a while over the course of a period of time and make small fixes until it's been a while since i've seen any issues. i can continuously rebase from this repo so it stays in sync and eventually make a PR when i've fixed all (currently unhandled) cases i've encountered (plus the one you mentioned). i'll let you see this message, feel free to close the PR and i'll (slowly) work on improving it on my branch. at the moment my main concern is ensuring compatibility with my own awful stream deck implementation that i depend upon daily until i get the functionality moved over to StreamController. ((for example, i'll have to learn how the plugin system works so i can port my cute little stream deck calculator app.)) thank you for your time and patience! |
|
also i created a ticket for myself to keep track of specific needed fixes violet4#2 |
Sounds nice! @violet4 I'll convert this PR to a draft so that you don't have to create a new one (which you can ofc also do if you want). |
Brings src/windows/** from 254 mypy errors to 0. Type-only apart from the genuine defects below, each of which mypy surfaced. Bugs fixed (behaviour changes): - AssetManager/CustomAssets/Chooser.py: gl.asset_manager.set_cursor_from_name was called unguarded, but AssetManager.on_close nulls gl.asset_manager -- a drop or file-dialog callback landing after the window closed raised AttributeError. Guarded; the files are still added. - mainWindow.py: get_active_page() returned gl.page_manager.dummy_page, an attribute that exists nowhere, so the no-deck-selected path raised AttributeError. Returns None (the widened contract) instead. - ActionMissing/OutdatedActionRow.py: passed coords= to a MissingRow that takes identifier=, so every outdated-action row raised TypeError. Signature realigned with the sibling MissingActionButtonRow and its call site. - Sidebar/Sidebar.py: KeyEditorKeyBox.load_for_key called ActionManager.load_for_coords, which lives on ActionGroup -> AttributeError. - ActionManager.py: ActionRow.update_comment wrote to a comment_row that has never existed (comment_label does). set_label_toggled referenced an on_allow_label_toggled handler on no class; disabled alongside its already-commented call site. - ActionConfigurator.py: select_event dereferenced a None event_assigner when the model's first item was not the "None" entry. - StreamDeckUI/code_conv.py: a bare `# type: ignore` hid an undefined _DELAY_KEYSYM, so any imported hotkey with a delay token raised NameError into the importer's except and silently dropped the whole hotkey. Delay tokens are now rejected explicitly. - Store/InfoPage.py: set_stargazer drove a row commented out in build(); disabled with it. - Settings/Settings.py: CustomContentEntry assigned url/branch strings that the EntryRow widgets overwrote two statements later; dead stores removed. Contract corrections: MainWindow.get_active_controller/get_active_page, DeckStack.remove_page/get_page_attributes, PageSelector.sort_func, OnboardingWindow.set_button_status, Store preview setters and ImageEditor.update_values (annotated KeyLabel, handed an ImageLayout) all declared types their bodies contradict. Forwarded guards: ActionChooser's get_arrow_image() call sites (MR 2) and PluginSettingsPage's ActionRow title (MR 3). 24 pinned ignores (12 gi stub, 6 late-init, 6 cross-MR forwards), 1 bare ignore removed. Total mypy errors 949 -> 679; no new out-of-scope errors (StoreBackend drops 16 via the StoreData widening MR 6 asked for).
Review round on the previous commit.
10th defect, directly under the earlier edit: EventAssignerUI.
change_assignment_for_event called self.action.set_event_assignments, which
exists on no class (ActionCore only has the singular set_event_assignment,
ActionCore.py:591). Its one call site sat after an unconditional return in
EventAssignerRow.on_changed, so the whole tail was dead -- and the comment
added last round ("the persisted map is keyed and valued by the events'
string names") was wrong twice over: persisted VALUES are event_assigner.id
strings (Page.py:572), not event names. Deleted the dead method and the dead
tail of on_changed instead of type-annotating fiction; the live part of
on_changed (get_event_assigner_by_id -> set_event_assignment) is untouched.
Guard asymmetry corrected: last round guarded gl.app in the DEAD _on_close
while the live on_close (:83) still dereferenced gl.app unguarded for
GLib.idle_add(gl.app.on_quit). gl.app is honestly Optional, so the live path
is now guarded too.
Honesty corrections to the previous commit message:
- Sidebar.py KeyEditorKeyBox.load_for_key: the load_for_coords ->
load_for_identifier fix is correct, but KeyEditorKeyBox is instantiated
nowhere, so this was dead code, not a live AttributeError. The same method
also passes key.coords where an InputIdentifier is expected (hidden by an
unannotated return type) -- left for the residual sweep.
- Store/Icons/IconPage.py: the guarded get_custom_translation block is dead
-- the next line unconditionally overwrites `description` from
short_description/description. Pre-existing; the guard is still correct for
the day that line goes.
- The three FlowBox super().__init__(base_class=...) -> positional changes
are no-ops today: every construction goes through FLOW_BOX_CLASS(preview,
chooser) with an empty *args.
Gates unchanged: src/windows/** 0 errors, total 679, 24 pinned ignores,
ruff clean, harness 174/174.
…roller#227) Rebased onto gitlab/main (86db4f9, MRs StreamController#222/StreamController#223/StreamController#225/StreamController#226 landed). Eleven in-scope errors appeared, all from StreamController#225's honest widening; re-zeroed. Absorbed (11): - LabelEditor.py (10) -- KeyLabel.text/color/outline_width/outline_color/ alignment/font_name/font_size/style/font_weight are all `| None` now. _update_values_locked treats an unset text as "", and the four LabelRow setters take `| None` and no-op rather than being handed a None (which color_values_to_gdk / set_value would have raised on). The font description needs all four properties, so an incompletely composed label leaves the chooser alone instead of calling Pango with None. - ImageEditor.py (1) -- ImageLayout.size is `| None`; the spinner keeps its value when unset instead of evaluating None*100. Stale ignores removed (4): StreamController#225 fixed both root causes this branch forwarded, so the two color_values_to_gdk arg-type ignores in LabelEditor and the two InputIdentifier.Events attr-defined ignores in ActionConfigurator are gone. Verified with a --warn-unused-ignores diagnostic run: no stale ignores remain in src/windows (config untouched). Ignores: 24 -> 20 (12 gi stub, 6 late-init, 2 cross-MR). Both surviving cross-MR forwards outlived StreamController#226, which zeroed those files without widening the two signatures (their only offending callers live in src/windows, so StreamController#226 never saw the errors) -- for the residual sweep: - PageManagerBackend.set_default_page:309 `path: str`, but None is the documented "clear the default" value. - AssetManagerBackend.add_custom_media_set_by_ui:333 `path: str`, whose first branch is `if path is None and url is not None`. Gates on the rebased tree: src/windows/** 0 errors, total 228 (all in DeckController.py 227 + ActionCore.py 1, i.e. StreamController#224's scope), ruff clean, harness 175/175.
types(7/8): windows/ to zero mypy errors Closes StreamController#227 See merge request naz/Deckard!116
this is achieved by adding
--listand--pathscommand line arguments.--listlists all the attached Stream Deck devices with some basic information, including their "paths", and exits--pathstakes 1 or more paths (found via--list) and filters out paths not specified before initializing the devicesif anyone cares about this change enough to want to merge it, but it's terrible or doesn't match the project requirements, please point me in the correct direction and i'd be happy to improve it and make it acceptable. however, at the moment, this makes it so i can use this software with one of my stream decks and my own program with my other stream deck simultaneously.