|
@@ -9,6 +9,7 @@
|
|
#import "TXFullVideoView.h"
|
|
#import "TXFullVideoView.h"
|
|
#import "ClassroomService.h"
|
|
#import "ClassroomService.h"
|
|
#import "TXFullVideoCell.h"
|
|
#import "TXFullVideoCell.h"
|
|
|
|
+#import "KSIndexPathValidator.h"
|
|
|
|
|
|
@interface TXFullVideoView ()<UICollectionViewDelegate, UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
|
|
@interface TXFullVideoView ()<UICollectionViewDelegate, UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
|
|
|
|
|
|
@@ -22,6 +23,12 @@
|
|
|
|
|
|
@property (nonatomic, assign) CGSize cellSize;
|
|
@property (nonatomic, assign) CGSize cellSize;
|
|
|
|
|
|
|
|
+@property (nonatomic, strong) dispatch_semaphore_t signalSemaphore;
|
|
|
|
+
|
|
|
|
+@property (nonatomic, strong) dispatch_semaphore_t signalQualitySemaphore;
|
|
|
|
+
|
|
|
|
+@property (nonatomic, strong) dispatch_semaphore_t signalVolumeSemaphore;
|
|
|
|
+
|
|
@end
|
|
@end
|
|
|
|
|
|
@implementation TXFullVideoView
|
|
@implementation TXFullVideoView
|
|
@@ -32,6 +39,9 @@
|
|
if (self) {
|
|
if (self) {
|
|
_viewFrame = CGRectMake(0, 0, KLandscapeWidth, KLandscapeHeight);
|
|
_viewFrame = CGRectMake(0, 0, KLandscapeWidth, KLandscapeHeight);
|
|
[self addSubview:self.videoView];
|
|
[self addSubview:self.videoView];
|
|
|
|
+ _signalSemaphore = dispatch_semaphore_create(1);
|
|
|
|
+ _signalQualitySemaphore = dispatch_semaphore_create(1);
|
|
|
|
+ _signalVolumeSemaphore = dispatch_semaphore_create(1);
|
|
[self addCancleButton];
|
|
[self addCancleButton];
|
|
}
|
|
}
|
|
return self;
|
|
return self;
|
|
@@ -60,15 +70,14 @@
|
|
}
|
|
}
|
|
|
|
|
|
- (void)showVideoList {
|
|
- (void)showVideoList {
|
|
|
|
+ __weak typeof(self) weakSelf = self;
|
|
dispatch_async(self.videoListQueue, ^{
|
|
dispatch_async(self.videoListQueue, ^{
|
|
|
|
+ __strong typeof(weakSelf) strongSelf = weakSelf;
|
|
|
|
+ if (!strongSelf) return;
|
|
|
|
+ MJ_LOCK(strongSelf.signalSemaphore)
|
|
NSArray *tempArray = [ClassroomService sharedService].currentRoom.memberList;
|
|
NSArray *tempArray = [ClassroomService sharedService].currentRoom.memberList;
|
|
-// NSMutableArray *array = [NSMutableArray arrayWithArray:[ClassroomService sharedService].currentRoom.memberList];
|
|
|
|
-// [array addObjectsFromArray:tempArray];
|
|
|
|
-// [array addObjectsFromArray:tempArray];
|
|
|
|
-// [array addObjectsFromArray:tempArray];
|
|
|
|
-//// [array addObjectsFromArray:tempArray];
|
|
|
|
-// tempArray = [NSArray arrayWithArray:array];
|
|
|
|
if (tempArray.count <= 0) {
|
|
if (tempArray.count <= 0) {
|
|
|
|
+ MJ_UNLOCK(strongSelf.signalSemaphore)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
NSSortDescriptor * des = [[NSSortDescriptor alloc] initWithKey:@"joinTime" ascending:YES];
|
|
NSSortDescriptor * des = [[NSSortDescriptor alloc] initWithKey:@"joinTime" ascending:YES];
|
|
@@ -106,64 +115,132 @@
|
|
[sortArray removeObjectsAtIndexes:set];
|
|
[sortArray removeObjectsAtIndexes:set];
|
|
}
|
|
}
|
|
[lastArray addObjectsFromArray:sortArray];
|
|
[lastArray addObjectsFromArray:sortArray];
|
|
|
|
+
|
|
|
|
+ NSArray *safeData = [lastArray copy]; // 创建不可变副本
|
|
|
|
+
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
- self.videoDataSource = [lastArray mutableCopy];
|
|
|
|
|
|
+ if (!strongSelf || !strongSelf.videoView) {
|
|
|
|
+ MJ_UNLOCK(strongSelf.signalSemaphore)
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ self.videoDataSource = [safeData mutableCopy];
|
|
[self.videoView reloadData];
|
|
[self.videoView reloadData];
|
|
|
|
+ MJ_UNLOCK(strongSelf.signalSemaphore)
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
- (void)updateUserVideo:(NSString *)userId {
|
|
- (void)updateUserVideo:(NSString *)userId {
|
|
|
|
+ __weak typeof(self) weakSelf = self;
|
|
dispatch_async(self.videoListQueue, ^{
|
|
dispatch_async(self.videoListQueue, ^{
|
|
- for(int i=0;i < self.videoDataSource.count; i++) {
|
|
|
|
- RoomMember *member = self.videoDataSource[i];
|
|
|
|
- if([member.userId isEqualToString:userId]) {
|
|
|
|
- NSIndexPath *index = [NSIndexPath indexPathForItem:i inSection:0];
|
|
|
|
- dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
- TXFullVideoCell * cell = (TXFullVideoCell *)[self.videoView cellForItemAtIndexPath:index];
|
|
|
|
- if (cell) {
|
|
|
|
- [self.videoView reloadItemsAtIndexPaths:@[index]];
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
|
|
+ __strong typeof(weakSelf) strongSelf = weakSelf;
|
|
|
|
+ if (!strongSelf) return;
|
|
|
|
+
|
|
|
|
+ MJ_LOCK(strongSelf.signalSemaphore)
|
|
|
|
+ NSArray *safeDataSource = [strongSelf.videoDataSource copy];
|
|
|
|
+ NSMutableArray *indexPaths = [[NSMutableArray alloc] init];
|
|
|
|
+
|
|
|
|
+ [safeDataSource enumerateObjectsUsingBlock:^(RoomMember *member, NSUInteger idx, BOOL *stop) {
|
|
|
|
+ if ([member.userId isEqualToString:userId]) {
|
|
|
|
+ [indexPaths addObject:[NSIndexPath indexPathForRow:idx inSection:0]];
|
|
}
|
|
}
|
|
|
|
+ }];
|
|
|
|
+
|
|
|
|
+ if (indexPaths.count == 0) {
|
|
|
|
+ MJ_UNLOCK(strongSelf.signalSemaphore)
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
+ __strong typeof(weakSelf) strongSelf = weakSelf;
|
|
|
|
+ if (!strongSelf) {
|
|
|
|
+ MJ_UNLOCK(strongSelf.signalSemaphore)
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ NSArray *validIPs = [[KSIndexPathValidator validatorWithType:KSScrollViewTypeCollectionView] validateForCollectionView:self.videoView indexPaths:indexPaths];
|
|
|
|
+ if (validIPs.count) {
|
|
|
|
+ [strongSelf.videoView performBatchUpdates:^{
|
|
|
|
+ [strongSelf.videoView reloadItemsAtIndexPaths:validIPs];
|
|
|
|
+ } completion:^(BOOL finished) {
|
|
|
|
+ MJ_UNLOCK(strongSelf.signalSemaphore)
|
|
|
|
+ }];
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ MJ_UNLOCK(strongSelf.signalSemaphore)
|
|
|
|
+ }
|
|
|
|
+ });
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)updateUserQuality:(NSString *)userId netWorkingStatus:(TXNetWorkingStatus)quality {
|
|
- (void)updateUserQuality:(NSString *)userId netWorkingStatus:(TXNetWorkingStatus)quality {
|
|
|
|
+
|
|
|
|
+ __weak typeof(self) weakSelf = self;
|
|
dispatch_async(self.videoListQueue, ^{
|
|
dispatch_async(self.videoListQueue, ^{
|
|
- for(int i = 0;i < self.videoDataSource.count; i++) {
|
|
|
|
- RoomMember *member = self.videoDataSource[i];
|
|
|
|
- if([member.userId isEqualToString:userId]) {
|
|
|
|
- NSIndexPath *index = [NSIndexPath indexPathForRow:i inSection:0];
|
|
|
|
|
|
+ __strong typeof(weakSelf) strongSelf = weakSelf;
|
|
|
|
+ if (!strongSelf) return;
|
|
|
|
+
|
|
|
|
+ MJ_LOCK(strongSelf.signalQualitySemaphore)
|
|
|
|
+ NSArray *safeDataSource = [strongSelf.videoDataSource copy];
|
|
|
|
+
|
|
|
|
+ [safeDataSource enumerateObjectsUsingBlock:^(RoomMember *member, NSUInteger idx, BOOL *stop) {
|
|
|
|
+ if ([member.userId isEqualToString:userId]) {
|
|
|
|
+ RoomMember *currentMember = [[ClassroomService sharedService].currentRoom getMember:userId];
|
|
|
|
+ NSIndexPath *index = [NSIndexPath indexPathForRow:idx inSection:0];
|
|
|
|
+
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
+ __strong typeof(weakSelf) strongSelf = weakSelf;
|
|
|
|
+ if (!strongSelf) {
|
|
|
|
+ MJ_UNLOCK(strongSelf.signalQualitySemaphore)
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
TXFullVideoCell * cell = (TXFullVideoCell *)[self.videoView cellForItemAtIndexPath:index];
|
|
TXFullVideoCell * cell = (TXFullVideoCell *)[self.videoView cellForItemAtIndexPath:index];
|
|
if (cell) {
|
|
if (cell) {
|
|
[cell updateQuality:quality];
|
|
[cell updateQuality:quality];
|
|
}
|
|
}
|
|
|
|
+ MJ_UNLOCK(strongSelf.signalQualitySemaphore)
|
|
});
|
|
});
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
+ }];
|
|
|
|
+ MJ_UNLOCK(strongSelf.signalQualitySemaphore)
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
- (void)updateMicStatus:(NSString *)userId volume:(NSInteger)volume {
|
|
- (void)updateMicStatus:(NSString *)userId volume:(NSInteger)volume {
|
|
|
|
+ __weak typeof(self) weakSelf = self;
|
|
dispatch_async(self.videoListQueue, ^{
|
|
dispatch_async(self.videoListQueue, ^{
|
|
- for(int i = 0;i < self.videoDataSource.count; i++) {
|
|
|
|
- RoomMember *member = self.videoDataSource[i];
|
|
|
|
- if([member.userId isEqualToString:userId]) {
|
|
|
|
|
|
+
|
|
|
|
+ __strong typeof(weakSelf) strongSelf = weakSelf;
|
|
|
|
+ if (!strongSelf) return;
|
|
|
|
+
|
|
|
|
+ MJ_LOCK(strongSelf.signalVolumeSemaphore)
|
|
|
|
+ NSArray *safeDataSource = [strongSelf.videoDataSource copy];
|
|
|
|
+
|
|
|
|
+ [safeDataSource enumerateObjectsUsingBlock:^(RoomMember *member, NSUInteger idx, BOOL *stop) {
|
|
|
|
+ if ([member.userId isEqualToString:userId]) {
|
|
RoomMember *currentMember = [[ClassroomService sharedService].currentRoom getMember:userId];
|
|
RoomMember *currentMember = [[ClassroomService sharedService].currentRoom getMember:userId];
|
|
-
|
|
|
|
- NSIndexPath *index = [NSIndexPath indexPathForRow:i inSection:0];
|
|
|
|
|
|
+ NSIndexPath *index = [NSIndexPath indexPathForRow:idx inSection:0];
|
|
|
|
+
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
+ __strong typeof(weakSelf) strongSelf = weakSelf;
|
|
|
|
+ if (!strongSelf) {
|
|
|
|
+ MJ_UNLOCK(strongSelf.signalVolumeSemaphore)
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
TXFullVideoCell * cell = (TXFullVideoCell *)[self.videoView cellForItemAtIndexPath:index];
|
|
TXFullVideoCell * cell = (TXFullVideoCell *)[self.videoView cellForItemAtIndexPath:index];
|
|
if (cell) {
|
|
if (cell) {
|
|
[cell updateUserVolume:volume isCloseMic:!currentMember.microphoneEnable];
|
|
[cell updateUserVolume:volume isCloseMic:!currentMember.microphoneEnable];
|
|
}
|
|
}
|
|
|
|
+ MJ_UNLOCK(strongSelf.signalVolumeSemaphore)
|
|
});
|
|
});
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
+ }];
|
|
|
|
+ MJ_UNLOCK(strongSelf.signalVolumeSemaphore)
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
|