From 0becc890d8c4578d52ab6836da11dae340313ddd Mon Sep 17 00:00:00 2001 From: Hristo Terezov Date: Tue, 10 Oct 2023 12:18:05 -0500 Subject: [PATCH] feat(track-state): Log on add/remove/mute/owner. --- react/features/base/tracks/functions.any.ts | 35 +++++++++++++- react/features/base/tracks/middleware.web.ts | 51 +++++++++++++++++--- 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/react/features/base/tracks/functions.any.ts b/react/features/base/tracks/functions.any.ts index 6f78b8a1160f..dd354fad162b 100644 --- a/react/features/base/tracks/functions.any.ts +++ b/react/features/base/tracks/functions.any.ts @@ -224,6 +224,17 @@ export function getTrackByMediaTypeAndParticipant( ); } +/** + * Returns track for specified participant id. + * + * @param {ITrack[]} tracks - List of all tracks. + * @param {string} participantId - Participant ID. + * @returns {(Track[]|undefined)} + */ +export function getTrackByParticipantId(tracks: ITrack[], participantId: string) { + return tracks.filter(t => t.participantId === participantId); +} + /** * Returns screenshare track of given virtualScreenshareParticipantId. * @@ -333,8 +344,7 @@ export function isLocalVideoTrackDesktop(state: IReduxState) { * @returns {boolean} */ export function isRemoteTrackMuted(tracks: ITrack[], mediaType: MediaType, participantId: string) { - const track = getTrackByMediaTypeAndParticipant( - tracks, mediaType, participantId); + const track = getTrackByMediaTypeAndParticipant(tracks, mediaType, participantId); return !track || track.muted; } @@ -416,3 +426,24 @@ export function setTrackMuted(track: any, muted: boolean, state: IReduxState | I } }); } + +/** + * Logs the current track state for a participant. + * + * @param {ITrack[]} tracksState - The tracks from redux. + * @param {string} participantId - The ID of the participant. + * @param {string} reason - The reason for the track change. + * @returns {void} + */ +export function logTracksForParticipant(tracksState: ITrack[], participantId: string, reason?: string) { + if (!participantId) { + return; + } + const tracks = getTrackByParticipantId(tracksState, participantId); + const logStringPrefix = `Track state for participant ${participantId} changed`; + const trackStateStrings = tracks.map(t => `{type: ${t.mediaType}, videoType: ${t.videoType}, muted: ${ + t.muted}, isReceivingData: ${t.isReceivingData}, jitsiTrack: ${t.jitsiTrack?.toString()}}`); + const tracksLogMsg = trackStateStrings.length > 0 ? `\n${trackStateStrings.join('\n')}` : ' No tracks available!'; + + logger.debug(`${logStringPrefix}${reason ? `(reason: ${reason})` : ''}:${tracksLogMsg}`); +} diff --git a/react/features/base/tracks/middleware.web.ts b/react/features/base/tracks/middleware.web.ts index aa7383ba39d0..ae565fd877ab 100644 --- a/react/features/base/tracks/middleware.web.ts +++ b/react/features/base/tracks/middleware.web.ts @@ -15,6 +15,7 @@ import { TRACK_ADDED, TRACK_MUTE_UNMUTE_FAILED, TRACK_NO_DATA_FROM_SOURCE, + TRACK_OWNER_CHANGED, TRACK_REMOVED, TRACK_STOPPED, TRACK_UPDATED @@ -25,7 +26,7 @@ import { trackNoDataFromSourceNotificationInfoChanged } from './actions.web'; import { - getTrackByJitsiTrack + getTrackByJitsiTrack, logTracksForParticipant } from './functions.web'; import { ITrack } from './types'; @@ -48,9 +49,17 @@ MiddlewareRegistry.register(store => next => action => { // were granted and a local video track is added by umuting the video. if (local) { store.dispatch(getAvailableDevices()); + break; } - break; + const result = next(action); + const participantId = action.track?.participantId; + + if (participantId) { + logTracksForParticipant(store.getState()['features/base/tracks'], participantId, 'Track added'); + } + + return result; } case TRACK_NO_DATA_FROM_SOURCE: { const result = next(action); @@ -62,7 +71,32 @@ MiddlewareRegistry.register(store => next => action => { case TRACK_REMOVED: { _removeNoDataFromSourceNotification(store, action.track); - break; + + const result = next(action); + const participantId = action.track?.jitsiTrack?.getParticipantId(); + + if (participantId && !action.track?.jitsiTrack?.isLocal()) { + logTracksForParticipant(store.getState()['features/base/tracks'], participantId, 'Track removed'); + } + + return result; + } + + case TRACK_OWNER_CHANGED: { + const oldTrack = getTrackByJitsiTrack(store.getState()['features/base/tracks'], action.track?.jitsiTrack); + const oldOwner = oldTrack?.participantId; + const result = next(action); + const newOwner = action.track?.participantId; + + if (oldOwner) { + logTracksForParticipant(store.getState()['features/base/tracks'], oldOwner, 'Owner changed'); + } + + if (newOwner) { + logTracksForParticipant(store.getState()['features/base/tracks'], newOwner, 'Owner changed'); + } + + return result; } case TRACK_MUTE_UNMUTE_FAILED: { @@ -104,17 +138,22 @@ MiddlewareRegistry.register(store => next => action => { const { jitsiTrack } = action.track; const participantID = jitsiTrack.getParticipantId(); const isVideoTrack = jitsiTrack.type !== MEDIA_TYPE.AUDIO; + const local = jitsiTrack.isLocal(); if (isVideoTrack) { - if (jitsiTrack.isLocal() && !(jitsiTrack.getVideoType() === VIDEO_TYPE.DESKTOP)) { + if (local && !(jitsiTrack.getVideoType() === VIDEO_TYPE.DESKTOP)) { APP.conference.setVideoMuteStatus(); - } else if (!jitsiTrack.isLocal()) { + } else if (!local) { APP.UI.setVideoMuted(participantID); } - } else if (jitsiTrack.isLocal()) { + } else if (local) { APP.conference.updateAudioIconEnabled(); } + if (typeof action.track?.muted !== 'undefined' && participantID && !local) { + logTracksForParticipant(store.getState()['features/base/tracks'], participantID, 'Track updated'); + } + return result; }