fix: Microphone should still work after a view change (#1835)
- Closes #1810
This commit is contained in:
@@ -15,7 +15,7 @@ import {
|
||||
ConditionsManagerEpoch,
|
||||
getOverriddenConfig,
|
||||
} from '../../card-controller/conditions-manager.js';
|
||||
import { ReadonlyMicrophoneManager } from '../../card-controller/microphone-manager.js';
|
||||
import { MicrophoneState } from '../../card-controller/types.js';
|
||||
import { ViewManagerEpoch } from '../../card-controller/view/types.js';
|
||||
import { MediaActionsController } from '../../components-lib/media-actions-controller.js';
|
||||
import { ZoomSettingsObserved } from '../../components-lib/zoom/types.js';
|
||||
@@ -88,7 +88,7 @@ export class FrigateCardLiveCarousel extends LitElement {
|
||||
public cameraManager?: CameraManager;
|
||||
|
||||
@property({ attribute: false })
|
||||
public microphoneManager?: ReadonlyMicrophoneManager;
|
||||
public microphoneState?: MicrophoneState;
|
||||
|
||||
@property({ attribute: false })
|
||||
public viewFilterCameraID?: string;
|
||||
@@ -139,7 +139,7 @@ export class FrigateCardLiveCarousel extends LitElement {
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
if (
|
||||
changedProps.has('microphoneManager') ||
|
||||
changedProps.has('microphoneState') ||
|
||||
changedProps.has('overriddenLiveConfig')
|
||||
) {
|
||||
this._mediaActionsController.setOptions({
|
||||
@@ -158,7 +158,7 @@ export class FrigateCardLiveCarousel extends LitElement {
|
||||
}),
|
||||
...((this.overriddenLiveConfig?.auto_unmute ||
|
||||
this.overriddenLiveConfig?.auto_mute) && {
|
||||
microphoneManager: this.microphoneManager,
|
||||
microphoneState: this.microphoneState,
|
||||
microphoneMuteSeconds:
|
||||
this.overriddenLiveConfig.microphone.mute_after_microphone_mute_seconds,
|
||||
}),
|
||||
@@ -302,8 +302,8 @@ export class FrigateCardLiveCarousel extends LitElement {
|
||||
<div class="embla__slide">
|
||||
<frigate-card-live-provider
|
||||
?load=${!liveConfig.lazy_load}
|
||||
.microphoneStream=${view?.camera === cameraID
|
||||
? this.microphoneManager?.getStream()
|
||||
.microphoneState=${view?.camera === cameraID
|
||||
? this.microphoneState
|
||||
: undefined}
|
||||
.cameraConfig=${cameraConfig}
|
||||
.cameraEndpoints=${guard(
|
||||
@@ -429,7 +429,7 @@ export class FrigateCardLiveCarousel extends LitElement {
|
||||
.loop=${hasMultipleCameras}
|
||||
.dragEnabled=${hasMultipleCameras && this.overriddenLiveConfig?.draggable}
|
||||
.plugins=${guard(
|
||||
[this.cameraManager, this.overriddenLiveConfig, this.microphoneManager],
|
||||
[this.cameraManager, this.overriddenLiveConfig],
|
||||
this._getPlugins.bind(this),
|
||||
)}
|
||||
.selected=${this._getSelectedCameraIndex()}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { customElement, property } from 'lit/decorators.js';
|
||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||
import { CameraManager } from '../../camera-manager/manager.js';
|
||||
import { ConditionsManagerEpoch } from '../../card-controller/conditions-manager.js';
|
||||
import { ReadonlyMicrophoneManager } from '../../card-controller/microphone-manager.js';
|
||||
import { MicrophoneState } from '../../card-controller/types.js';
|
||||
import { ViewManagerEpoch } from '../../card-controller/view/types.js';
|
||||
import { MediaGridSelected } from '../../components-lib/media-grid-controller.js';
|
||||
import { CardWideConfig, LiveConfig, Overrides } from '../../config/types.js';
|
||||
@@ -46,7 +46,7 @@ export class FrigateCardLiveGrid extends LitElement {
|
||||
public cameraManager?: CameraManager;
|
||||
|
||||
@property({ attribute: false })
|
||||
public microphoneManager?: ReadonlyMicrophoneManager;
|
||||
public microphoneState?: MicrophoneState;
|
||||
|
||||
@property({ attribute: false })
|
||||
public triggeredCameraIDs?: Set<string>;
|
||||
@@ -67,7 +67,7 @@ export class FrigateCardLiveGrid extends LitElement {
|
||||
.overrides=${this.overrides}
|
||||
.cardWideConfig=${this.cardWideConfig}
|
||||
.cameraManager=${this.cameraManager}
|
||||
.microphoneManager=${this.microphoneManager}
|
||||
.microphoneState=${this.microphoneState}
|
||||
?triggered=${triggeredCameraID &&
|
||||
!!this.triggeredCameraIDs?.has(triggeredCameraID)}
|
||||
>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { CSSResultGroup, html, LitElement, TemplateResult, unsafeCSS } from 'lit
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { CameraManager } from '../../camera-manager/manager.js';
|
||||
import { ConditionsManagerEpoch } from '../../card-controller/conditions-manager.js';
|
||||
import { ReadonlyMicrophoneManager } from '../../card-controller/microphone-manager.js';
|
||||
import { MicrophoneState } from '../../card-controller/types.js';
|
||||
import { ViewManagerEpoch } from '../../card-controller/view/types.js';
|
||||
import { LiveController } from '../../components-lib/live/live-controller.js';
|
||||
import { CardWideConfig, LiveConfig, Overrides } from '../../config/types.js';
|
||||
@@ -38,7 +38,7 @@ export class FrigateCardLive extends LitElement {
|
||||
public cardWideConfig?: CardWideConfig;
|
||||
|
||||
@property({ attribute: false })
|
||||
public microphoneManager?: ReadonlyMicrophoneManager;
|
||||
public microphoneState?: MicrophoneState;
|
||||
|
||||
@property({ attribute: false })
|
||||
public triggeredCameraIDs?: Set<string>;
|
||||
@@ -67,7 +67,7 @@ export class FrigateCardLive extends LitElement {
|
||||
.overrides=${this.overrides}
|
||||
.cardWideConfig=${this.cardWideConfig}
|
||||
.cameraManager=${this.cameraManager}
|
||||
.microphoneManager=${this.microphoneManager}
|
||||
.microphoneState=${this.microphoneState}
|
||||
.triggeredCameraIDs=${this.triggeredCameraIDs}
|
||||
>
|
||||
</frigate-card-live-grid>
|
||||
|
||||
@@ -11,6 +11,7 @@ import { classMap } from 'lit/directives/class-map.js';
|
||||
import { guard } from 'lit/directives/guard.js';
|
||||
import { createRef, Ref, ref } from 'lit/directives/ref.js';
|
||||
import { CameraEndpoints } from '../../camera-manager/types.js';
|
||||
import { MicrophoneState } from '../../card-controller/types.js';
|
||||
import { dispatchLiveErrorEvent } from '../../components-lib/live/utils/dispatch-live-error.js';
|
||||
import { PartialZoomSettings } from '../../components-lib/zoom/types.js';
|
||||
import {
|
||||
@@ -64,7 +65,7 @@ export class FrigateCardLiveProvider
|
||||
public cardWideConfig?: CardWideConfig;
|
||||
|
||||
@property({ attribute: false })
|
||||
public microphoneStream?: MediaStream;
|
||||
public microphoneState?: MicrophoneState;
|
||||
|
||||
@property({ attribute: false })
|
||||
public zoomSettings?: PartialZoomSettings | null;
|
||||
@@ -351,7 +352,7 @@ export class FrigateCardLiveProvider
|
||||
.hass=${this.hass}
|
||||
.cameraConfig=${this.cameraConfig}
|
||||
.cameraEndpoints=${this.cameraEndpoints}
|
||||
.microphoneStream=${this.microphoneStream}
|
||||
.microphoneState=${this.microphoneState}
|
||||
.microphoneConfig=${this.liveConfig.microphone}
|
||||
?controls=${this.liveConfig.controls.builtin}
|
||||
@frigate-card:live:error=${() => this._providerErrorHandler()}
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
} from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { CameraEndpoints } from '../../../../camera-manager/types.js';
|
||||
import { MicrophoneState } from '../../../../card-controller/types.js';
|
||||
import { dispatchLiveErrorEvent } from '../../../../components-lib/live/utils/dispatch-live-error.js';
|
||||
import { CameraConfig, MicrophoneConfig } from '../../../../config/types.js';
|
||||
import { localize } from '../../../../localize/localize.js';
|
||||
@@ -44,7 +45,7 @@ export class FrigateCardGo2RTC extends LitElement implements FrigateCardMediaPla
|
||||
public cameraEndpoints?: CameraEndpoints;
|
||||
|
||||
@property({ attribute: false })
|
||||
public microphoneStream?: MediaStream;
|
||||
public microphoneState?: MicrophoneState;
|
||||
|
||||
@property({ attribute: false })
|
||||
public microphoneConfig?: MicrophoneConfig;
|
||||
@@ -147,7 +148,7 @@ export class FrigateCardGo2RTC extends LitElement implements FrigateCardMediaPla
|
||||
|
||||
this._player = new VideoRTC();
|
||||
this._player.containingPlayer = this;
|
||||
this._player.microphoneStream = this.microphoneStream ?? null;
|
||||
this._player.microphoneStream = this.microphoneState?.stream ?? null;
|
||||
this._player.src = address;
|
||||
this._player.visibilityCheck = false;
|
||||
this._player.controls = this.controls;
|
||||
@@ -172,14 +173,16 @@ export class FrigateCardGo2RTC extends LitElement implements FrigateCardMediaPla
|
||||
this._player.controls = this.controls;
|
||||
}
|
||||
|
||||
if (this._player && changedProps.has('microphoneStream')) {
|
||||
if (this._player?.microphoneStream !== this.microphoneStream) {
|
||||
this._player.microphoneStream = this.microphoneStream ?? null;
|
||||
if (
|
||||
this._player &&
|
||||
changedProps.has('microphoneState') &&
|
||||
this._player?.microphoneStream !== this.microphoneState?.stream
|
||||
) {
|
||||
this._player.microphoneStream = this.microphoneState?.stream ?? null;
|
||||
|
||||
// Need to force a reconnect if the microphone stream changes since
|
||||
// WebRTC cannot introduce a new stream after the offer is already made.
|
||||
this._player.reconnect();
|
||||
}
|
||||
// Need to force a reconnect if the microphone stream changes since
|
||||
// WebRTC cannot introduce a new stream after the offer is already made.
|
||||
this._player.reconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -394,9 +394,10 @@ export class VideoRTC extends HTMLElement {
|
||||
|
||||
this.pcState = WebSocket.CLOSED;
|
||||
if (this.pc) {
|
||||
this.pc.getSenders().forEach((sender) => {
|
||||
if (sender.track) sender.track.stop();
|
||||
});
|
||||
// Do not close the (microphone) track attached to the peer connection as
|
||||
// that is controlled by MicrophoneManager.
|
||||
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1810
|
||||
|
||||
this.pc.close();
|
||||
this.pc = null;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { customElement, property } from 'lit/decorators.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { CameraManager } from '../camera-manager/manager.js';
|
||||
import { ConditionsManagerEpoch } from '../card-controller/conditions-manager.js';
|
||||
import { ReadonlyMicrophoneManager } from '../card-controller/microphone-manager.js';
|
||||
import { MicrophoneState } from '../card-controller/types.js';
|
||||
import { ViewManagerEpoch } from '../card-controller/view/types.js';
|
||||
import {
|
||||
CardWideConfig,
|
||||
@@ -60,7 +60,7 @@ export class FrigateCardViews extends LitElement {
|
||||
public hide?: boolean;
|
||||
|
||||
@property({ attribute: false })
|
||||
public microphoneManager?: ReadonlyMicrophoneManager;
|
||||
public microphoneState?: MicrophoneState;
|
||||
|
||||
@property({ attribute: false })
|
||||
public triggeredCameraIDs?: Set<string>;
|
||||
@@ -243,7 +243,7 @@ export class FrigateCardViews extends LitElement {
|
||||
.overrides=${this.overriddenConfig.overrides}
|
||||
.cameraManager=${this.cameraManager}
|
||||
.cardWideConfig=${this.cardWideConfig}
|
||||
.microphoneManager=${this.microphoneManager}
|
||||
.microphoneState=${this.microphoneState}
|
||||
.triggeredCameraIDs=${this.triggeredCameraIDs}
|
||||
class="${classMap(liveClasses)}"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user