You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
316 lines
12 KiB
316 lines
12 KiB
// |
|
// WXYZ_BookAiPlayPageHeaderView.m |
|
// WXReader |
|
// |
|
// Created by Andrew on 2020/3/11. |
|
// Copyright © 2020 Andrew. All rights reserved. |
|
// |
|
|
|
#import "WXYZ_BookAiPlayPageHeaderView.h" |
|
|
|
#import "TFAudioPlayViewController.h" |
|
#import "TFReaderBookManager.h" |
|
#import "TFReadRecordManager.h" |
|
#import "WXYZ_AudioSettingHelper.h" |
|
#import "WXYZ_PlayingInfoCenter.h" |
|
|
|
#import "WXYZ_TouchAssistantView.h" |
|
#import "WXYZ_Player.h" |
|
#if __has_include(<iflyMSC/IFlyMSC.h>) |
|
#import "iflyMSC/IFlyMSC.h" |
|
#endif |
|
|
|
@interface WXYZ_BookAiPlayPageHeaderView () <WXYZ_PlayingInfoCenterDelegate |
|
#if __has_include(<iflyMSC/IFlyMSC.h>) |
|
, IFlySpeechSynthesizerDelegate |
|
#endif |
|
> |
|
|
|
// 分割字符,讯飞只能解析8000字符,把小说章节内容拆分为数组解析 |
|
@property (nonatomic, strong) NSMutableArray __block *segmentCharacterArray; |
|
|
|
#if __has_include(<iflyMSC/IFlyMSC.h>) |
|
@property (nonatomic, strong) IFlySpeechSynthesizer *iFlySpeechSynthesizer; |
|
#endif |
|
|
|
@end |
|
|
|
@implementation WXYZ_BookAiPlayPageHeaderView |
|
|
|
#if __has_include(<iflyMSC/IFlyMSC.h>) |
|
- (void)createSubviews |
|
{ |
|
[super createSubviews]; |
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(relationViewTitleChange) name:Notification_Change_Audio_Chapter object:nil]; |
|
|
|
[WXYZ_PlayingInfoCenter sharedManager].delegate = self; |
|
|
|
WS(weakSelf) |
|
self.resetPlayerBlock = ^(BOOL immediateReset) { |
|
if (immediateReset) { |
|
[weakSelf initIFlySpeech]; |
|
} else if (weakSelf.segmentCharacterArray.count == 0) { |
|
[weakSelf initIFlySpeech]; |
|
} |
|
}; |
|
} |
|
|
|
- (void)setProductionChapterModel:(TFProductionChapterModel *)productionChapterModel |
|
{ |
|
[super setProductionChapterModel:productionChapterModel]; |
|
|
|
WS(weakSelf) |
|
[[WXYZ_AudioSettingHelper sharedManager] getCurrentTimingBlock:^(NSUInteger currentTime) { |
|
dispatch_async(dispatch_get_main_queue(), ^{ |
|
weakSelf.timingButton.buttonTitle = [NSString stringWithFormat:@"%02zd:%02zd", (NSInteger)(currentTime / 60), (NSInteger)(currentTime % 60)]; |
|
}); |
|
} finishBlock:^{ |
|
dispatch_async(dispatch_get_main_queue(), ^{ |
|
if ([[WXYZ_AudioSettingHelper sharedManager] getReadTiming] == 1) { |
|
weakSelf.timingButton.buttonTitle = TFLocalizedString(@"听完本章节"); |
|
} else if ([[WXYZ_AudioSettingHelper sharedManager] getReadTiming] == 0) { |
|
weakSelf.timingButton.buttonTitle = TFLocalizedString(@"定时"); |
|
} else { |
|
weakSelf.timingButton.buttonTitle = TFLocalizedString(@"定时"); |
|
#if __has_include(<iflyMSC/IFlyMSC.h>) |
|
if (weakSelf.playerState == TFBasicVoicePlayerStatePlaying) { |
|
[[IFlySpeechSynthesizer sharedInstance] pauseSpeaking]; |
|
} |
|
#endif |
|
} |
|
}); |
|
}]; |
|
|
|
if (productionChapterModel.chapter_id == 0) { |
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ |
|
[TFPromptManager showPromptViewWithStatus:TFPromptStatusError promptTitle:TFLocalizedString(@"章节正在更新中")]; |
|
}); |
|
self.playerState = TFBasicVoicePlayerStateStoped; |
|
return; |
|
} |
|
|
|
if (self.temp_chapterModel.chapter_id == productionChapterModel.chapter_id && self.temp_chapterModel.is_preview == productionChapterModel.is_preview && ![TFUserInfoManager shareInstance].auto_sub) { |
|
if ([WXYZ_Player sharedPlayer].state == TFBasicVoicePlayerStatePlaying && ![[WXYZ_AudioSettingHelper sharedManager] isPlayPageShowingWithProductionType:TFProductionTypeAudio]) { |
|
[[IFlySpeechSynthesizer sharedInstance] resumeSpeaking]; |
|
[[WXYZ_Player sharedPlayer] pause]; |
|
} |
|
return; |
|
} |
|
|
|
if ([[WXYZ_AudioSettingHelper sharedManager] isPlayPageShowingWithProductionType:TFProductionTypeAudio]) { |
|
[[WXYZ_AudioSettingHelper sharedManager] playPageViewShow:NO productionType:TFProductionTypeAudio]; |
|
if ([TFAudioPlayViewController sharedManager].speaking) { |
|
self.playerState = TFBasicVoicePlayerStateStoped; |
|
} |
|
return; |
|
} |
|
|
|
self.temp_chapterModel = [productionChapterModel modelCopy]; |
|
|
|
if (productionChapterModel.is_preview && ![TFUserInfoManager shareInstance].auto_sub) { |
|
self.playerState = TFBasicVoicePlayerStateStoped; |
|
[self.iFlySpeechSynthesizer stopSpeaking]; |
|
[self showPayView]; |
|
return; |
|
} |
|
|
|
[self initIFlySpeech]; |
|
|
|
} |
|
|
|
- (void)initIFlySpeech |
|
{ |
|
//设置在线工作方式 |
|
[self.iFlySpeechSynthesizer setParameter:[IFlySpeechConstant TYPE_CLOUD] |
|
forKey:[IFlySpeechConstant ENGINE_TYPE]]; |
|
|
|
[self.iFlySpeechSynthesizer setParameter:@"wxyz.pcm" |
|
forKey: [IFlySpeechConstant TTS_AUDIO_PATH]]; |
|
|
|
// 语速 |
|
WXYZ_AudioSettingHelper *audioTool = [WXYZ_AudioSettingHelper sharedManager]; |
|
[self.iFlySpeechSynthesizer setParameter:[TFUtilsHelper formatStringWithInteger:[[[audioTool getReadSpeedValuesWithProducitionType:self.productionType] objectAtIndex:[audioTool getReadSpeedWithProducitionType:self.productionType]] floatValue] * 50] forKey:[IFlySpeechConstant SPEED]]; |
|
//设置音量,取值范围 0~100 |
|
|
|
[self.iFlySpeechSynthesizer setParameter:@"1" forKey:[IFlySpeechConstant MPPLAYINGINFOCENTER]]; |
|
|
|
// 音量 |
|
AVAudioSession *audioSession = [AVAudioSession sharedInstance]; |
|
[self.iFlySpeechSynthesizer setParameter:[TFUtilsHelper formatStringWithInteger:audioSession.outputVolume * 100] forKey: [IFlySpeechConstant VOLUME]]; |
|
|
|
// 发音人 |
|
[self.iFlySpeechSynthesizer setParameter:[[audioTool getReadVoiceValuesWithProducitionType:self.productionType] objectAtIndex:[audioTool getReadVoiceWithProducitionType:self.productionType]] forKey:[IFlySpeechConstant VOICE_NAME]]; |
|
|
|
WS(weakSelf) |
|
[[TFReaderBookManager sharedManager] getChapterTextWithBook_id:self.productionChapterModel.production_id chapter_index:[self.productionChapterModel.display_order integerValue] completionHandler:^(NSString *content) { |
|
|
|
[weakSelf.segmentCharacterArray removeAllObjects]; |
|
|
|
content = [content stringByReplacingOccurrencesOfString:@"W$$X" withString:@""]; |
|
content = [content stringByReplacingOccurrencesOfString:k_Chapter_RequstFail withString:@""]; |
|
|
|
// 分割长度 |
|
NSInteger segmentLength = 3500; |
|
|
|
// 分割数量 |
|
NSInteger segmentCount = content.length / segmentLength + (content.length % segmentLength > 0 ? 1 : 0); |
|
|
|
// 整数量分割 |
|
if (segmentCount == 1) { |
|
[weakSelf.segmentCharacterArray addObject:content]; |
|
} else { |
|
for (int i = 0; i < segmentCount; i ++) { |
|
if (segmentCount - 1 == i) { |
|
[weakSelf.segmentCharacterArray addObject:[content substringWithRange:NSMakeRange(i * segmentLength, content.length % segmentLength)]]; |
|
} else { |
|
[weakSelf.segmentCharacterArray addObject:[content substringWithRange:NSMakeRange(i * segmentLength, segmentLength)]]; |
|
} |
|
} |
|
} |
|
|
|
if (weakSelf.segmentCharacterArray.count > 0) { |
|
[weakSelf.iFlySpeechSynthesizer startSpeaking:[weakSelf.segmentCharacterArray firstObject]]; |
|
} |
|
|
|
[[WXYZ_PlayingInfoCenter sharedManager] showPlayingInfoCenterWithProductionChapterModel:weakSelf.productionChapterModel]; |
|
}]; |
|
} |
|
|
|
#pragma mark - WXYZ_PlayingInfoCenterDelegate |
|
|
|
- (void)playRemoteCommand |
|
{ |
|
if ([WXYZ_TouchAssistantView sharedManager].productionType == TFProductionTypeNovel) { |
|
if (self.playerState == TFBasicVoicePlayerStatePause) { |
|
[self.iFlySpeechSynthesizer resumeSpeaking]; |
|
} |
|
} |
|
} |
|
|
|
- (void)pauseRemoteCommand |
|
{ |
|
if ([WXYZ_TouchAssistantView sharedManager].productionType == TFProductionTypeNovel) { |
|
if (self.playerState == TFBasicVoicePlayerStatePlaying) { |
|
[self.iFlySpeechSynthesizer pauseSpeaking]; |
|
} |
|
} |
|
} |
|
|
|
- (void)lastRemoteCommand |
|
{ |
|
if ([WXYZ_TouchAssistantView sharedManager].productionType == TFProductionTypeNovel) { |
|
[self skipToLastChapter]; |
|
} |
|
} |
|
|
|
- (void)nextRemoteCommand |
|
{ |
|
if ([WXYZ_TouchAssistantView sharedManager].productionType == TFProductionTypeNovel) { |
|
[self skipToNextChapter]; |
|
} |
|
} |
|
|
|
#pragma mark - IFlySpeechDelegate |
|
- (void)onCompleted:(IFlySpeechError *)error |
|
{ |
|
if (error) { |
|
if ([TFNetworkManager networkingStatus] == NO) { |
|
[TFPromptManager showPromptViewWithStatus:TFPromptStatusError promptTitle:TFLocalizedString(@"当前为离线状态,只可查看缓存内容哦")]; |
|
} else { |
|
[TFPromptManager showPromptViewWithStatus:TFPromptStatusError promptTitle:TFLocalizedString(@"播放出错")]; |
|
} |
|
self.playerState = TFBasicVoicePlayerStateStoped; |
|
} |
|
} |
|
|
|
// 合成开始 |
|
- (void)onSpeakBegin |
|
{ |
|
self.playerState = TFBasicVoicePlayerStatePlaying; |
|
|
|
if ([[WXYZ_AudioSettingHelper sharedManager] isPlayPageShowingWithProductionType:TFProductionTypeAudio] && [[WXYZ_AudioSettingHelper sharedManager] isPlayPageShowingWithProductionType:TFProductionTypeNovel] && [WXYZ_Player sharedPlayer].state == TFBasicVoicePlayerStatePlaying) { |
|
[self.iFlySpeechSynthesizer pauseSpeaking]; |
|
} else { |
|
if ([WXYZ_Player sharedPlayer].state == TFBasicVoicePlayerStatePlaying) { |
|
[[WXYZ_Player sharedPlayer] pause]; |
|
} |
|
} |
|
|
|
[[WXYZ_PlayingInfoCenter sharedManager] showPlayingInfoCenterWithProductionChapterModel:self.productionChapterModel]; |
|
} |
|
|
|
// 合成播放进度 |
|
- (void)onSpeakProgress:(int)progress beginPos:(int)beginPos endPos:(int)endPos |
|
{ |
|
if (progress == 100) { // 片段播放结束 |
|
[self.segmentCharacterArray removeFirstObject]; |
|
if (self.segmentCharacterArray.count == 0) { |
|
if ([[WXYZ_AudioSettingHelper sharedManager] getReadTiming] == 1) { |
|
[[WXYZ_AudioSettingHelper sharedManager] setReadTimingWithIndex:0]; |
|
self.timingButton.buttonTitle = TFLocalizedString(@"定时"); |
|
[self.iFlySpeechSynthesizer pauseSpeaking]; |
|
self.playerState = TFBasicVoicePlayerStatePause; |
|
} else { |
|
if (self.productionChapterModel.next_chapter > 0 && self.productionChapterModel.next_chapter) { |
|
[self skipToNextChapter]; |
|
} |
|
} |
|
} else { |
|
[self.iFlySpeechSynthesizer startSpeaking:[self.segmentCharacterArray firstObject]]; |
|
} |
|
} |
|
} |
|
|
|
// 暂停播放回调 |
|
- (void)onSpeakPaused |
|
{ |
|
self.playerState = TFBasicVoicePlayerStatePause; |
|
[[WXYZ_PlayingInfoCenter sharedManager] hiddenPlayingInfoCenter]; |
|
} |
|
|
|
// 恢复播放回调 |
|
- (void)onSpeakResumed |
|
{ |
|
self.playerState = TFBasicVoicePlayerStatePlaying; |
|
[[WXYZ_PlayingInfoCenter sharedManager] showPlayingInfoCenterWithProductionChapterModel:self.productionChapterModel]; |
|
} |
|
|
|
// 取消播放 |
|
- (void)onSpeakCancel |
|
{ |
|
self.playerState = TFBasicVoicePlayerStateStoped; |
|
[[WXYZ_PlayingInfoCenter sharedManager] hiddenPlayingInfoCenter]; |
|
} |
|
|
|
- (void)relationViewTitleChange |
|
{ |
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ |
|
[self setRelationViewTitle:[[TFReadRecordManager shareManagerWithProductionType:TFProductionTypeAudio] getReadingRecordChapterTitleWithProduction_id:self.relationModel.production_id]?:self.relationModel.chapter_title?:@""]; |
|
}); |
|
} |
|
|
|
#pragma mark - lazy |
|
|
|
- (IFlySpeechSynthesizer *)iFlySpeechSynthesizer |
|
{ |
|
if (!_iFlySpeechSynthesizer) { |
|
_iFlySpeechSynthesizer = [IFlySpeechSynthesizer sharedInstance]; |
|
|
|
//设置协议委托对象 |
|
_iFlySpeechSynthesizer.delegate = self; |
|
|
|
} |
|
return _iFlySpeechSynthesizer; |
|
} |
|
|
|
- (NSMutableArray *)segmentCharacterArray |
|
{ |
|
if (!_segmentCharacterArray) { |
|
_segmentCharacterArray = [NSMutableArray array]; |
|
} |
|
return _segmentCharacterArray; |
|
} |
|
#endif |
|
|
|
@end
|
|
|