| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- //
- // TUIVoiceMessageCellData.m
- // TXIMSDK_TUIKit_iOS
- //
- // Created by annidyfeng on 2019/5/21.
- // Copyright © 2023 Tencent. All rights reserved.
- //
- #import "TUIVoiceMessageCellData.h"
- #import <TIMCommon/TIMDefine.h>
- #import <TUICore/TUIThemeManager.h>
- @import AVFoundation;
- @interface TUIVoiceMessageCellData () <AVAudioPlayerDelegate>
- @property AVAudioPlayer *audioPlayer;
- @property NSString *wavPath;
- @property(nonatomic, strong) NSTimer *timer;
- @end
- @implementation TUIVoiceMessageCellData
- + (TUIMessageCellData *)getCellData:(V2TIMMessage *)message {
- V2TIMSoundElem *elem = message.soundElem;
- TUIVoiceMessageCellData *soundData = [[TUIVoiceMessageCellData alloc] initWithDirection:(message.isSelf ? MsgDirectionOutgoing : MsgDirectionIncoming)];
- soundData.duration = elem.duration;
- soundData.length = elem.dataSize;
- soundData.uuid = elem.uuid;
- soundData.reuseId = TVoiceMessageCell_ReuseId;
- soundData.path = elem.path;
- return soundData;
- }
- + (NSString *)getDisplayString:(V2TIMMessage *)message {
- return TIMCommonLocalizableString(TUIKitMessageTypeVoice); // @"[Voice]";
- }
- - (Class)getReplyQuoteViewDataClass {
- return NSClassFromString(@"TUIVoiceReplyQuoteViewData");
- }
- - (Class)getReplyQuoteViewClass {
- return NSClassFromString(@"TUIVoiceReplyQuoteView");
- }
- - (instancetype)initWithDirection:(TMsgDirection)direction {
- self = [super initWithDirection:direction];
- if (self) {
- if (direction == MsgDirectionIncoming) {
- self.cellLayout = [TUIMessageCellLayout incommingVoiceMessageLayout];
- _voiceImage = TUIChatDynamicImage(@"chat_voice_message_receiver_voice_normal_img",
- [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"message_voice_receiver_normal")]);
- _voiceImage = [_voiceImage rtl_imageFlippedForRightToLeftLayoutDirection];
- _voiceAnimationImages = [NSArray arrayWithObjects:[self.class formatImageByName:@"message_voice_receiver_playing_1"],
- [self.class formatImageByName:@"message_voice_receiver_playing_2"],
- [self.class formatImageByName:@"message_voice_receiver_playing_3"], nil];
- _voiceTop = [[self class] incommingVoiceTop];
- } else {
- self.cellLayout = [TUIMessageCellLayout outgoingVoiceMessageLayout];
- _voiceImage = TUIChatDynamicImage(@"chat_voice_message_sender_voice_normal_img",
- [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"message_voice_sender_normal")]);
- _voiceImage = [_voiceImage rtl_imageFlippedForRightToLeftLayoutDirection];
- _voiceAnimationImages = [NSArray arrayWithObjects:[self.class formatImageByName:@"message_voice_sender_playing_1"],
- [self.class formatImageByName:@"message_voice_sender_playing_2"],
- [self.class formatImageByName:@"message_voice_sender_playing_3"], nil];
- _voiceTop = [[self class] outgoingVoiceTop];
- }
- _voiceHeight = 21;
- }
- return self;
- }
- + (UIImage *)formatImageByName:(NSString *)imgName {
- NSString *path = TUIChatImagePath(imgName);
- UIImage *img = [[TUIImageCache sharedInstance] getResourceFromCache:path];
- return [img rtl_imageFlippedForRightToLeftLayoutDirection];
- }
- - (NSString *)getVoicePath:(BOOL *)isExist {
- NSString *path = nil;
- BOOL isDir = false;
- *isExist = NO;
- if (self.direction == MsgDirectionOutgoing) {
- if (_path.length) {
- path = [NSString stringWithFormat:@"%@%@", TUIKit_Voice_Path, _path.lastPathComponent];
- if ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]) {
- if (!isDir) {
- *isExist = YES;
- }
- }
- }
- }
- if (!*isExist) {
- if (_uuid.length) {
- path = [NSString stringWithFormat:@"%@%@.amr", TUIKit_Voice_Path, _uuid];
- if ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]) {
- if (!isDir) {
- *isExist = YES;
- }
- }
- }
- }
- return path;
- }
- - (V2TIMSoundElem *)getIMSoundElem {
- V2TIMMessage *imMsg = self.innerMessage;
- if (imMsg.elemType == V2TIM_ELEM_TYPE_SOUND) {
- return imMsg.soundElem;
- }
- return nil;
- }
- - (void)playVoiceMessage {
- if (self.isPlaying) {
- [self stopVoiceMessage];
- return;
- }
- self.isPlaying = YES;
- if (self.innerMessage.localCustomInt == 0) self.innerMessage.localCustomInt = 1;
- V2TIMSoundElem *imSound = [self getIMSoundElem];
- BOOL isExist = NO;
- if (self.uuid.length == 0) {
- self.uuid = imSound.uuid;
- }
- NSString *path = [self getVoicePath:&isExist];
- if (isExist) {
- [self playInternal:path];
- } else {
- if (self.isDownloading) {
- return;
- }
- //
- self.isDownloading = YES;
- @weakify(self);
- [imSound downloadSound:path
- progress:^(NSInteger curSize, NSInteger totalSize) {
- }
- succ:^{
- @strongify(self);
- self.isDownloading = NO;
- [self playInternal:path];
- }
- fail:^(int code, NSString *msg) {
- @strongify(self);
- self.isDownloading = NO;
- [self stopVoiceMessage];
- }];
- }
- }
- - (void)playInternal:(NSString *)path {
- if (!self.isPlaying) return;
- // play current
- TUIVoiceAudioPlaybackStyle playbackStyle = [self.class getAudioplaybackStyle];
- if(playbackStyle == TUIVoiceAudioPlaybackStyleHandset) {
- [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
- }
- else {
- [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
- }
- NSURL *url = [NSURL fileURLWithPath:path];
- self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
- self.audioPlayer.delegate = self;
- bool result = [self.audioPlayer play];
- if (!result) {
- self.wavPath = [[path stringByDeletingPathExtension] stringByAppendingString:@".wav"];
- NSURL *url = [NSURL fileURLWithPath:self.wavPath];
- [self.audioPlayer stop];
- self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
- self.audioPlayer.delegate = self;
- [self.audioPlayer play];
- }
-
- @weakify(self);
- if (@available(iOS 10.0, *)) {
- self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1
- repeats:YES
- block:^(NSTimer *_Nonnull timer) {
- @strongify(self);
- [self updateProgress];
- }];
- } else {
- // Fallback on earlier versions
- }
- }
- //The style of audio playback.
- + (TUIVoiceAudioPlaybackStyle)getAudioplaybackStyle {
- NSString *style = [NSUserDefaults.standardUserDefaults objectForKey:@"tui_audioPlaybackStyle"];
- if ([style isEqualToString:@"1"]) {
- return TUIVoiceAudioPlaybackStyleLoudspeaker;
- } else if ([style isEqualToString:@"2"]) {
- return TUIVoiceAudioPlaybackStyleHandset;
- }
- return TUIVoiceAudioPlaybackStyleLoudspeaker;
- }
- + (void)changeAudioPlaybackStyle {
- TUIVoiceAudioPlaybackStyle style = [self getAudioplaybackStyle];
- if (style == TUIVoiceAudioPlaybackStyleLoudspeaker) {
- [NSUserDefaults.standardUserDefaults setObject:@"2" forKey:@"tui_audioPlaybackStyle"];
- }
- else {
- [NSUserDefaults.standardUserDefaults setObject:@"1" forKey:@"tui_audioPlaybackStyle"];
- }
- [NSUserDefaults.standardUserDefaults synchronize];
-
- }
- - (void)updateProgress {
- @weakify(self);
- dispatch_async(dispatch_get_main_queue(), ^{
- @strongify(self);
- self.currentTime = self.audioPlayer.currentTime;
- });
- }
- - (void)stopVoiceMessage {
- if ([self.audioPlayer isPlaying]) {
- [self.audioPlayer stop];
- self.audioPlayer = nil;
- }
- if (self.timer) {
- [self.timer invalidate];
- self.timer = nil;
- }
- self.isPlaying = NO;
- }
- - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag;
- {
- [self stopVoiceMessage];
- [[NSFileManager defaultManager] removeItemAtPath:self.wavPath error:nil];
- if (self.audioPlayerDidFinishPlayingBlock) {
- self.audioPlayerDidFinishPlayingBlock();
- }
- }
- static CGFloat gIncommingVoiceTop = 12;
- + (void)setIncommingVoiceTop:(CGFloat)incommingVoiceTop {
- gIncommingVoiceTop = incommingVoiceTop;
- }
- + (CGFloat)incommingVoiceTop {
- return gIncommingVoiceTop;
- }
- static CGFloat gOutgoingVoiceTop = 12;
- + (void)setOutgoingVoiceTop:(CGFloat)outgoingVoiceTop {
- gOutgoingVoiceTop = outgoingVoiceTop;
- }
- + (CGFloat)outgoingVoiceTop {
- return gOutgoingVoiceTop;
- }
- @end
|