diff --git a/pkg/rtc/participant.go b/pkg/rtc/participant.go index 2287a87f1..58cc0d647 100644 --- a/pkg/rtc/participant.go +++ b/pkg/rtc/participant.go @@ -269,6 +269,23 @@ func (p *ParticipantImpl) IsDisconnected() bool { return p.State() == livekit.ParticipantInfo_DISCONNECTED } +func (p *ParticipantImpl) IsIdle() bool { + // check if there are any published tracks that are subscribed + for _, t := range p.GetPublishedTracks() { + if t.IsSubscribed() { + return false + } + } + + p.lock.RLock() + defer p.lock.RUnlock() + // check if participant is subscribed to any tracks + if len(p.subscribedTracks) != 0 || len(p.subscriptionInProgress) != 0 || len(p.subscriptionRequestsQueue) != 0 { + return false + } + return true +} + func (p *ParticipantImpl) ConnectedAt() time.Time { return p.connectedAt } diff --git a/pkg/rtc/types/interfaces.go b/pkg/rtc/types/interfaces.go index 19097108b..7006e7f33 100644 --- a/pkg/rtc/types/interfaces.go +++ b/pkg/rtc/types/interfaces.go @@ -234,6 +234,7 @@ type LocalParticipant interface { State() livekit.ParticipantInfo_State IsReady() bool IsDisconnected() bool + IsIdle() bool SubscriberAsPrimary() bool GetClientConfiguration() *livekit.ClientConfiguration GetICEConnectionType() ICEConnectionType @@ -380,6 +381,7 @@ type MediaTrack interface { RevokeDisallowedSubscribers(allowedSubscriberIdentities []livekit.ParticipantIdentity) []livekit.ParticipantIdentity GetAllSubscribers() []livekit.ParticipantID GetNumSubscribers() int + IsSubscribed() bool // returns quality information that's appropriate for width & height GetQualityForDimension(width, height uint32) livekit.VideoQuality diff --git a/pkg/rtc/types/typesfakes/fake_local_media_track.go b/pkg/rtc/types/typesfakes/fake_local_media_track.go index 71620e389..1aeab9a68 100644 --- a/pkg/rtc/types/typesfakes/fake_local_media_track.go +++ b/pkg/rtc/types/typesfakes/fake_local_media_track.go @@ -144,6 +144,16 @@ type FakeLocalMediaTrack struct { isSimulcastReturnsOnCall map[int]struct { result1 bool } + IsSubscribedStub func() bool + isSubscribedMutex sync.RWMutex + isSubscribedArgsForCall []struct { + } + isSubscribedReturns struct { + result1 bool + } + isSubscribedReturnsOnCall map[int]struct { + result1 bool + } IsSubscriberStub func(livekit.ParticipantID) bool isSubscriberMutex sync.RWMutex isSubscriberArgsForCall []struct { @@ -1014,6 +1024,59 @@ func (fake *FakeLocalMediaTrack) IsSimulcastReturnsOnCall(i int, result1 bool) { }{result1} } +func (fake *FakeLocalMediaTrack) IsSubscribed() bool { + fake.isSubscribedMutex.Lock() + ret, specificReturn := fake.isSubscribedReturnsOnCall[len(fake.isSubscribedArgsForCall)] + fake.isSubscribedArgsForCall = append(fake.isSubscribedArgsForCall, struct { + }{}) + stub := fake.IsSubscribedStub + fakeReturns := fake.isSubscribedReturns + fake.recordInvocation("IsSubscribed", []interface{}{}) + fake.isSubscribedMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeLocalMediaTrack) IsSubscribedCallCount() int { + fake.isSubscribedMutex.RLock() + defer fake.isSubscribedMutex.RUnlock() + return len(fake.isSubscribedArgsForCall) +} + +func (fake *FakeLocalMediaTrack) IsSubscribedCalls(stub func() bool) { + fake.isSubscribedMutex.Lock() + defer fake.isSubscribedMutex.Unlock() + fake.IsSubscribedStub = stub +} + +func (fake *FakeLocalMediaTrack) IsSubscribedReturns(result1 bool) { + fake.isSubscribedMutex.Lock() + defer fake.isSubscribedMutex.Unlock() + fake.IsSubscribedStub = nil + fake.isSubscribedReturns = struct { + result1 bool + }{result1} +} + +func (fake *FakeLocalMediaTrack) IsSubscribedReturnsOnCall(i int, result1 bool) { + fake.isSubscribedMutex.Lock() + defer fake.isSubscribedMutex.Unlock() + fake.IsSubscribedStub = nil + if fake.isSubscribedReturnsOnCall == nil { + fake.isSubscribedReturnsOnCall = make(map[int]struct { + result1 bool + }) + } + fake.isSubscribedReturnsOnCall[i] = struct { + result1 bool + }{result1} +} + func (fake *FakeLocalMediaTrack) IsSubscriber(arg1 livekit.ParticipantID) bool { fake.isSubscriberMutex.Lock() ret, specificReturn := fake.isSubscriberReturnsOnCall[len(fake.isSubscriberArgsForCall)] @@ -1878,6 +1941,8 @@ func (fake *FakeLocalMediaTrack) Invocations() map[string][][]interface{} { defer fake.isMutedMutex.RUnlock() fake.isSimulcastMutex.RLock() defer fake.isSimulcastMutex.RUnlock() + fake.isSubscribedMutex.RLock() + defer fake.isSubscribedMutex.RUnlock() fake.isSubscriberMutex.RLock() defer fake.isSubscriberMutex.RUnlock() fake.kindMutex.RLock() diff --git a/pkg/rtc/types/typesfakes/fake_local_participant.go b/pkg/rtc/types/typesfakes/fake_local_participant.go index 0bd08be04..1930a8248 100644 --- a/pkg/rtc/types/typesfakes/fake_local_participant.go +++ b/pkg/rtc/types/typesfakes/fake_local_participant.go @@ -378,6 +378,16 @@ type FakeLocalParticipant struct { isDisconnectedReturnsOnCall map[int]struct { result1 bool } + IsIdleStub func() bool + isIdleMutex sync.RWMutex + isIdleArgsForCall []struct { + } + isIdleReturns struct { + result1 bool + } + isIdleReturnsOnCall map[int]struct { + result1 bool + } IsPublisherStub func() bool isPublisherMutex sync.RWMutex isPublisherArgsForCall []struct { @@ -2683,6 +2693,59 @@ func (fake *FakeLocalParticipant) IsDisconnectedReturnsOnCall(i int, result1 boo }{result1} } +func (fake *FakeLocalParticipant) IsIdle() bool { + fake.isIdleMutex.Lock() + ret, specificReturn := fake.isIdleReturnsOnCall[len(fake.isIdleArgsForCall)] + fake.isIdleArgsForCall = append(fake.isIdleArgsForCall, struct { + }{}) + stub := fake.IsIdleStub + fakeReturns := fake.isIdleReturns + fake.recordInvocation("IsIdle", []interface{}{}) + fake.isIdleMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeLocalParticipant) IsIdleCallCount() int { + fake.isIdleMutex.RLock() + defer fake.isIdleMutex.RUnlock() + return len(fake.isIdleArgsForCall) +} + +func (fake *FakeLocalParticipant) IsIdleCalls(stub func() bool) { + fake.isIdleMutex.Lock() + defer fake.isIdleMutex.Unlock() + fake.IsIdleStub = stub +} + +func (fake *FakeLocalParticipant) IsIdleReturns(result1 bool) { + fake.isIdleMutex.Lock() + defer fake.isIdleMutex.Unlock() + fake.IsIdleStub = nil + fake.isIdleReturns = struct { + result1 bool + }{result1} +} + +func (fake *FakeLocalParticipant) IsIdleReturnsOnCall(i int, result1 bool) { + fake.isIdleMutex.Lock() + defer fake.isIdleMutex.Unlock() + fake.IsIdleStub = nil + if fake.isIdleReturnsOnCall == nil { + fake.isIdleReturnsOnCall = make(map[int]struct { + result1 bool + }) + } + fake.isIdleReturnsOnCall[i] = struct { + result1 bool + }{result1} +} + func (fake *FakeLocalParticipant) IsPublisher() bool { fake.isPublisherMutex.Lock() ret, specificReturn := fake.isPublisherReturnsOnCall[len(fake.isPublisherArgsForCall)] @@ -5187,6 +5250,8 @@ func (fake *FakeLocalParticipant) Invocations() map[string][][]interface{} { defer fake.identityMutex.RUnlock() fake.isDisconnectedMutex.RLock() defer fake.isDisconnectedMutex.RUnlock() + fake.isIdleMutex.RLock() + defer fake.isIdleMutex.RUnlock() fake.isPublisherMutex.RLock() defer fake.isPublisherMutex.RUnlock() fake.isReadyMutex.RLock() diff --git a/pkg/rtc/types/typesfakes/fake_media_track.go b/pkg/rtc/types/typesfakes/fake_media_track.go index fbbc6b8f0..a6774ef1f 100644 --- a/pkg/rtc/types/typesfakes/fake_media_track.go +++ b/pkg/rtc/types/typesfakes/fake_media_track.go @@ -111,6 +111,16 @@ type FakeMediaTrack struct { isSimulcastReturnsOnCall map[int]struct { result1 bool } + IsSubscribedStub func() bool + isSubscribedMutex sync.RWMutex + isSubscribedArgsForCall []struct { + } + isSubscribedReturns struct { + result1 bool + } + isSubscribedReturnsOnCall map[int]struct { + result1 bool + } IsSubscriberStub func(livekit.ParticipantID) bool isSubscriberMutex sync.RWMutex isSubscriberArgsForCall []struct { @@ -780,6 +790,59 @@ func (fake *FakeMediaTrack) IsSimulcastReturnsOnCall(i int, result1 bool) { }{result1} } +func (fake *FakeMediaTrack) IsSubscribed() bool { + fake.isSubscribedMutex.Lock() + ret, specificReturn := fake.isSubscribedReturnsOnCall[len(fake.isSubscribedArgsForCall)] + fake.isSubscribedArgsForCall = append(fake.isSubscribedArgsForCall, struct { + }{}) + stub := fake.IsSubscribedStub + fakeReturns := fake.isSubscribedReturns + fake.recordInvocation("IsSubscribed", []interface{}{}) + fake.isSubscribedMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeMediaTrack) IsSubscribedCallCount() int { + fake.isSubscribedMutex.RLock() + defer fake.isSubscribedMutex.RUnlock() + return len(fake.isSubscribedArgsForCall) +} + +func (fake *FakeMediaTrack) IsSubscribedCalls(stub func() bool) { + fake.isSubscribedMutex.Lock() + defer fake.isSubscribedMutex.Unlock() + fake.IsSubscribedStub = stub +} + +func (fake *FakeMediaTrack) IsSubscribedReturns(result1 bool) { + fake.isSubscribedMutex.Lock() + defer fake.isSubscribedMutex.Unlock() + fake.IsSubscribedStub = nil + fake.isSubscribedReturns = struct { + result1 bool + }{result1} +} + +func (fake *FakeMediaTrack) IsSubscribedReturnsOnCall(i int, result1 bool) { + fake.isSubscribedMutex.Lock() + defer fake.isSubscribedMutex.Unlock() + fake.IsSubscribedStub = nil + if fake.isSubscribedReturnsOnCall == nil { + fake.isSubscribedReturnsOnCall = make(map[int]struct { + result1 bool + }) + } + fake.isSubscribedReturnsOnCall[i] = struct { + result1 bool + }{result1} +} + func (fake *FakeMediaTrack) IsSubscriber(arg1 livekit.ParticipantID) bool { fake.isSubscriberMutex.Lock() ret, specificReturn := fake.isSubscriberReturnsOnCall[len(fake.isSubscriberArgsForCall)] @@ -1458,6 +1521,8 @@ func (fake *FakeMediaTrack) Invocations() map[string][][]interface{} { defer fake.isMutedMutex.RUnlock() fake.isSimulcastMutex.RLock() defer fake.isSimulcastMutex.RUnlock() + fake.isSubscribedMutex.RLock() + defer fake.isSubscribedMutex.RUnlock() fake.isSubscriberMutex.RLock() defer fake.isSubscriberMutex.RUnlock() fake.kindMutex.RLock()