feat: migrate routing to Essentials v3-routing.21 API - #36
Draft
anthony-lopez-pd wants to merge 40 commits into
Draft
anthony-lopez-pd wants to merge 40 commits into
anthony-lopez-pd wants to merge 40 commits into
Conversation
- input '0' value caused null reference exception
Improved logging clarity and consistency by explicitly importing PepperDash.Core.Logging and updating log statements. Enhanced feedback handling, especially for video sync detection and input resolution changes. Removed redundant lines and improved formatting for better readability and maintainability. No changes to core functionality.
…tputController (#29) Update PepperDashEssentials NuGet reference from v2.7.0 to v2.29.0. IBasicVolumeControls now extends IKeyName, requiring Key and Name properties. DmpsAudioOutput and DmCardAudioOutputController implement IBasicVolumeWithFeedback but are not EssentialsDevice subclasses, so they lacked these properties, causing VTable initialization failures at runtime on processors running Essentials v2.29.0."
DmCardAudioOutputController and DmpsAudioOutput implement IBasicVolumeWithFeedback, which now chains to IKeyName/IKeyed and requires Key and Name members. Add them via an optional constructor parameter with a sensible derived default, threading unique keys at the DmCardAudioOutputController chassis call sites. These helpers are not registered with DeviceManager, so the values are used for identification/logging only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implement the new IHasWirelessSharing interface on AirMediaController so room plugins and other consumers can react to wireless sharing activity without depending on the concrete device type. IsSharingFeedback aliases the existing IsInSessionFeedback, and a SharingChanged event is raised from the existing AirMedia status handler. Bump PepperDashEssentials to 2.37.0-feature-air-media-sharing-interface.1, the version that introduces IHasWirelessSharing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
routing.21 removed the routing-interface family this plugin used. Migrate onto the consolidated replacements without changing hardware-switching behavior: - Bump PepperDashEssentials to 3.0.0-dev-v3-routing.21. - Add plugin-local IDmInputSlot / IDmOutputSlot (replace removed IRoutingInputSlot / IRoutingOutputSlot; slot model is plugin-internal) and plugin-local ITxRouting(WithFeedback) / IRmcRouting(WithFeedback) : IRoutingMidpointWithFeedback. - IRoutingInputsOutputs -> IRoutingMidpoint on endpoint/passthrough controllers. - IRoutingNumeric(WithFeedback) / IRouting / IMatrixRouting -> consolidated IRoutingMidpointWithFeedback on chassis/midpoint controllers; add the newly-required ClearRoute / CurrentRoutes / RouteChanged members, populated from existing switch feedback. Shared TX members implemented once in DmTxControllerBase. - DmChassisController: drop IMatrixRouting (kept IRoutingMidpointWithFeedback); retype InputSlots/OutputSlots to the plugin-local slot interfaces. Crestron switching logic (DMOutput.VideoOut/AudioOut/USBRoutedTo, off-timers, feedback wiring) is unchanged. Builds clean against routing.21; all 84 plugin validation tests pass. Hardware validation pending. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… Wyrestorm) Brings the DM routing-feedback surface in line with the reviewed Wyrestorm NetworkHD migration: - IDmOutputSlot/DmMatrixOutput.CurrentRoutes now exposed as IReadOnlyDictionary so route state can't be mutated outside SetInputRoute (which raises OutputSlotChanged). - DmMatrixClearInput (the "none"/route-off sentinel) caches a single IsOnline BoolFeedback reporting online, instead of allocating a new offline feedback on every access. - Removed the dead VideoSyncDetected/VideoSyncChanged surface from IDmInputSlot (no consumers); kept concrete on DmMatrixInput only. Drops the CS0067 pragma from the sentinel. - DmMatrixOutput ctor no longer swallows exceptions into a half-built, still-registered slot; it validates/throws and the chassis call site skips-and-logs a failed slot so one bad card can't poison startup. Build clean (0 warnings); 84 tests pass. Hardware-switching logic unchanged. The chassis breakaway CurrentRoutes clobber (output-only removal key) is tracked separately and not addressed here. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Log a warning when chassis video/audio route feedback can't resolve a matching output/input port (distinguishes a genuine route-off from a lookup miss that would otherwise silently report no source). - Drop the dead Usb seed from DmMatrixOutput.currentRoutes (never set; the output only tracks Video/Audio from hardware feedback). - Null-guard the DmMatrixInput constructor (device/videoSyncfeedback). - Comment accuracy: document the known output-only keying limitation on UpdateCurrentRoute (breakaway A/V clobber, tracked separately); correct the "plugin-private" slot-dictionary claim (they're public members, just no longer part of a core routing contract); fix the orphaned doc block on Chassis_DMOutputChange. Build clean (0 warnings); 84 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t tests Fixes the breakaway-routing clobber in the new IRoutingMidpointWithFeedback surface (#1) and adds the first laptop unit tests of the route-feedback bookkeeping (#10). Problem: the chassis recorded CurrentRoutes keyed on the output port only. DM output/input ports are typed Audio|Video and the same RoutingOutputPort instance is reported for both the video and audio feedback events, so an audio route and a video route to the same output overwrote each other — DM breakaway (independent A/V) routes could not be represented, and RouteChanged reported the wrong/missing signal. Change: - New DmRouteFeedbackTracker maintains CurrentRoutes keyed on the explicit (output port, signal type) pair — signal type from the feedback event is the only reliable discriminator since the ports are AudioVideo-typed. Pure bookkeeping over Crestron-free Essentials.Core routing types. - DmChassisController, DmTxControllerBase, and DmRmc4kZScalerCController now delegate to the shared tracker, replacing three near-duplicate, divergent implementations (the chassis keyed output-only; the TX keyed on InputPort .Type, which also fails when input ports are AudioVideo). - Tests: tests/DmRouteFeedbackTrackerTests.cs links the production helper and exercises breakaway coexistence, per-signal replace, per-signal route-off, multi-output isolation, null-output guard, Clear(), and list-instance stability. Required referencing PepperDash.Essentials.Core in the test project (the routing port/descriptor types are Crestron-free, so they load in the test host even though the plugin itself is reflection-only). Build clean (0 warnings); 91 tests pass (84 existing + 7 new). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ges and update CurrentRoutes
…e changes and update CurrentRoutes
Essentials 2.28.1 added IKeyed and IKeyName to IBasicVolumeWithFeedback. DmpsAudioOutput and DmCardAudioOutputController did not implement Key or Name, so Mono vtable setup failed at type load and the plugin loader logged errors for DmpsAudioOutput, DmpsAudioOutputWithMixer, and DmpsAudioOutputWithMixerAndEq on every processor. Add Key/Name to both classes, thread a key through the DmpsAudioOutput hierarchy and its call sites, bump PepperDashEssentials to 2.39.0, and raise MinimumEssentialsFrameworkVersion to 2.28.1 across the factories.
Co-authored-by: erikdred <88980320+erikdred@users.noreply.github.com>
…o fix-usb-switch-null-ref
Fix usb switch null ref
…utput' into feature/routing21-migration # Conflicts: # src/Chassis/DmCardAudioOutput.cs # src/Chassis/DmChassisController.cs # src/PepperDash.Essentials.DM.csproj
…ace' into feature/routing21-migration # Conflicts: # src/AirMedia/AirMediaController.cs # src/Chassis/DmCardAudioOutput.cs # src/Chassis/DmpsAudioOutputController.cs # src/PepperDash.Essentials.DM.csproj
…ons' into feature/routing21-migration # Conflicts: # src/AirMedia/AirMediaController.cs # src/Chassis/DmBladeChassisController.cs # src/Chassis/DmCardAudioOutput.cs # src/Chassis/DmChassisController.cs # src/Chassis/DmpsAudioOutputController.cs # src/Chassis/DmpsRoutingController.cs # src/Chassis/HdMd8xNController.cs # src/Chassis/HdMdNxM4kEBridgeableController.cs # src/Chassis/HdPsXxxController.cs # src/DmLite/HdMdxxxCEController.cs # src/Endpoints/DGEs/Dge100Controller.cs # src/Endpoints/DGEs/DmDge200CController.cs # src/Endpoints/Receivers/DmRmcHelper.cs # src/Endpoints/Transmitters/DmTxHelpers.cs # src/PepperDash.Essentials.DM.csproj # src/VideoWindowing/HdWp4k401cController.cs
Feat/hdps volume controls
…ew.1 The public 3.0.0-rc.2 Core package does not contain IHasWirelessSharing (that interface only shipped on the release/feature tags, never merged into rc), so CI could not compile AirMediaController and the release build produced no artifact. Repin both PepperDashEssentials and PepperDash.Essentials.Core to the published 3.0.0-feat-update-ihaswebview.1, which contains the interface, and drop the stale local-override comment.
…ix routing status
Add named input/output routing slots (per-signal-type route feedback for the mobile-control matrix routing page) to the seven DM matrix midpoints that had IRoutingMidpointWithFeedback but not IHasNamedRoutingSlots: DmBladeChassisController, HdMd8xNController, HdMdNxM4kEBridgeableController, HdMdNxM4kzEController, HdPsXxxController, HdMdxxxCEController, DmpsRoutingController. DmChassisController already had it. New reusable RoutingPortNamedSlots helper builds slots from each controller's InputPorts/OutputPorts and tracks the routed input per signal type (lazy-built so port-population timing is irrelevant); fed from each controller's existing route-feedback hook. Adds 8 Crestron-free xUnit tests.
The plugin references PepperDashEssentials with <ExcludeAssets>runtime</ExcludeAssets> (so the .cplz doesn't ship framework DLLs), which strips the Essentials assemblies (Core, mobile-control-messengers, ...) from both the plugin output dir and its deps.json. The FactoryDiscoveryTests' MetadataLoadContext resolver relied on exactly those sources, so GetTypes() threw 'Could not find assembly' for every factory (19 failures). Resolve the full restore graph from the plugin's project.assets.json libraries list (which ExcludeAssets does not strip) by enumerating each package's lib folder on disk - the assets file's per-target runtime section is itself reduced to a _._ placeholder, so it can't be used. Also add the test host output dir as a resolution source. Plugin packaging is unchanged; all 99 tests now pass.
Devices implementing IHasNamedRoutingSlots publish slot keys that mobile control's matrix routing sends straight back as the route selector, but every ExecuteSwitch here cast the selector directly to its Crestron type. A string selector cast to null, so the switch was dropped with "Unable to execute switch for inputSelector matrixInput-1 to outputSelector matrixOutput-4" and routing from the matrix page did nothing. MockRoutingMidpoint works only because it makes slot key, port name and port Selector the same string. The two slot models need different translations, so each resolves its own: - DmChassisController publishes "matrixInput-N"/"matrixOutput-N" from DmMatrixInput/DmMatrixOutput, so it maps a key through the slot's SlotNumber (read off the hardware object, not parsed from the key, which matters for the dual-output cards whose keys are derived as 2n-1/2n) to Chassis.Inputs and Chassis.Outputs. Also applied to the two USB out-to-out casts. - The blade chassis and the HdMd/HdPs controllers publish port keys through RoutingPortNamedSlots, so the shared RoutingSelectorResolver looks the key up in the port collection and returns that port's Selector. Both keep passing a real selector object straight through, so existing callers are unaffected, and both return null for a null selector so ClearRoute (which delegates to ExecuteSwitch) still reads it as "clear this output". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NuA3AHfaUo9qJxhDyRU3pD
f5b2955 covered five of the eight controllers implementing IHasNamedRoutingSlots here; HdMd8xNController, DmpsRoutingController and HdMdxxxCEController were missed and still drop every route sent from mobile control's matrix page. The first two take the same fix as their siblings. HdMdxxxCEController selects by slot number rather than by a Crestron object, so Resolve<T>'s reference-type constraint does not fit it: ResolveSelector is the same lookup untyped, with Resolve<T> now delegating to it so there is still one implementation. Its Convert.ToUInt32 also threw straight out of the messenger action on any non-numeric selector, so it now logs and returns like every other controller here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NuA3AHfaUo9qJxhDyRU3pD
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Migrates the DM plugin off the routing-interface family that
3.0.0-dev-v3-routing.21removed, onto the consolidated replacements, without changing hardware-switching behavior. 43 controllers + the matrix slot types.Mapping applied
IRoutingInputSlot/IRoutingOutputSlot→ plugin-localIDmInputSlot/IDmOutputSlot(slot model is plugin-internal).IRoutingInputsOutputs→IRoutingMidpoint(endpoint/passthrough controllers — pure rename).IRoutingNumeric(WithFeedback)/IRouting/IMatrixRouting→IRoutingMidpointWithFeedback(chassis/midpoints), adding the now-requiredClearRoute/CurrentRoutes/RouteChanged, populated from existing switch feedback.ITxRouting(WithFeedback)/IRmcRoutingWithFeedback→ plugin-local interfaces extendingIRoutingMidpointWithFeedback; shared TX members implemented once inDmTxControllerBase.DmChassisController: droppedIMatrixRouting(keptIRoutingMidpointWithFeedback);InputSlots/OutputSlotsretyped to the plugin-local slot interfaces (retained as public members; nothing external consumed theIMatrixRoutingtype).Crestron switching logic (
DMOutput.VideoOut/AudioOut/USBRoutedTo, off-timers, feedback wiring) is unchanged.Status
CurrentRoutes/RouteChangedpopulation after switch and after clear (Mobile Control / route-feedback consumers).ClearRoutesemantics per device family (chassis/matrix issue a real hardware route-off; source-style devices select "no source"; AirMedia & the two no-feedback controllers drop the tracked route only).DmMatrixOutput.IsOnlinewas previously declared-but-never-initialized (latent NRE); now initialized to matchDmMatrixInput.Same pattern as the Wyrestorm routing migration (PepperDash/epi-wyrestorm-networkHD#3).
🤖 Generated with Claude Code