|  | @@ -13,18 +13,30 @@
 | 
	
		
			
				|  |  |  #import "KSPlayerSliderView.h"
 | 
	
		
			
				|  |  |  #import "KSVideoPlayerView.h"
 | 
	
		
			
				|  |  |  #import "KSAudioPlayAnimationView.h"
 | 
	
		
			
				|  |  | -#import "KSNewAlertView.h"
 | 
	
		
			
				|  |  | +#import "MergeTipsAlert.h"
 | 
	
		
			
				|  |  |  #import "MusicPublistAlert.h"
 | 
	
		
			
				|  |  |  #import "KSMediaManager.h"
 | 
	
		
			
				|  |  |  #import <RSKImageCropper/RSKImageCropper.h>
 | 
	
		
			
				|  |  |  #import "KSVideoCropViewController.h"
 | 
	
		
			
				|  |  |  #import <KSAudioSessionManager.h>
 | 
	
		
			
				|  |  | -#import "ShareFunctionView.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#import "ShareFunctionView.h"
 | 
	
		
			
				|  |  |  #import "KSUMShareManager.h"
 | 
	
		
			
				|  |  |  #import "KSLogManager.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #import "KSMergeEnginePlayer.h"
 | 
	
		
			
				|  |  | +#import "MergeMusicStaffView.h"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 功能引导
 | 
	
		
			
				|  |  | +#import "KSBaseGuideManager.h"
 | 
	
		
			
				|  |  | +// 音波动画
 | 
	
		
			
				|  |  | +#import "KSSpectrumView.h"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 滚动label
 | 
	
		
			
				|  |  | +#import "CBAutoScrollLabel.h"
 | 
	
		
			
				|  |  | +#import "UIView+KSLayer.h"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define WEB_TOP (10)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  @interface KSMediaMergeView ()<KSMergeEnginePlayerDelegate,KSVideoPlayerViewDelegate,RSKImageCropViewControllerDelegate,RSKImageCropViewControllerDataSource>
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -62,8 +74,6 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  @property (nonatomic, strong) KSAudioPlayAnimationView *playAnimationView;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -@property (nonatomic, strong) NSTimer *timer;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  // 远端资源
 | 
	
		
			
				|  |  |  @property (nonatomic, strong) NSString *remoteVideoUrl;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -84,7 +94,7 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  @property (nonatomic, strong) NSDictionary *preJsonDic;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -@property (nonatomic, strong) KSNewAlertView *alertView;
 | 
	
		
			
				|  |  | +@property (nonatomic, strong) MergeTipsAlert *alertView;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  @property (nonatomic, assign) BOOL hasSave;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -108,12 +118,33 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  @property (nonatomic, assign) NSInteger defaultDelay;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +@property (nonatomic, assign) CGFloat bgPlayerRate;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  @property (nonatomic, assign) NSInteger evaluateDelay;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  @property (nonatomic, assign) BOOL fromDraftPage; // 是否从草稿页面进入
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  @property (nonatomic, strong) KSUMShareManager *shareManager;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +@property (nonatomic, strong) UIView *webViewContainer; // 单行谱
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +@property (nonatomic, strong) UIView *colorView; // 视频时渐变色
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +@property (nonatomic, strong) MergeMusicStaffView *staffView;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +@property (nonatomic, assign) BOOL hasSaveDraft;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +@property (nonatomic, strong) KSBaseGuideManager *guideManager;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +@property (nonatomic, assign) BOOL needShowGuide;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +@property (nonatomic, strong) KSSpectrumView *spectrumView;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +@property (nonatomic, assign) CGFloat spectrumViewWidth;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +@property (nonatomic, assign) BOOL isCancel;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  @end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  @implementation KSMediaMergeView
 | 
	
	
		
			
				|  | @@ -125,7 +156,6 @@
 | 
	
		
			
				|  |  |          [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnterBackground) name:@"appEnterBackground" object:nil];
 | 
	
		
			
				|  |  |          [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(otherLogin) name:@"otherLogin" object:nil];
 | 
	
		
			
				|  |  |          [self configAudioSession];
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      return self;
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -169,15 +199,69 @@
 | 
	
		
			
				|  |  |      self.originalOffset = 0;
 | 
	
		
			
				|  |  |      [self.contrlView configWithOffsetTime:0];
 | 
	
		
			
				|  |  |      self.contrlView.hideBackView = NO;
 | 
	
		
			
				|  |  | -    [self configUI];
 | 
	
		
			
				|  |  | -    [LOADING_MANAGER showCustomLoading:@"资源下载中"];
 | 
	
		
			
				|  |  | -    [self modifyBgSpeed:self.bgAudioUrl callback:^{
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    [self prepareSource];
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +- (void)cancelTask {
 | 
	
		
			
				|  |  | +    [LOADING_MANAGER removeCustomLoading];
 | 
	
		
			
				|  |  | +    self.isCancel = YES;
 | 
	
		
			
				|  |  | +    if (self.mergeCallback) {
 | 
	
		
			
				|  |  | +        [self removeViewTips:NO];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    else {
 | 
	
		
			
				|  |  | +        [self removeView];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +- (void)prepareSource {
 | 
	
		
			
				|  |  | +    [LOADING_MANAGER showCancelCustomLoading:@"资源加载中,请稍等…" cancel:^{
 | 
	
		
			
				|  |  | +        [self cancelTask];
 | 
	
		
			
				|  |  | +    }];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    [self requestSource];
 | 
	
		
			
				|  |  | +    [self checkGuide];
 | 
	
		
			
				|  |  | +    [self modifySpeed];
 | 
	
		
			
				|  |  | +    dispatch_group_notify(self.requestGroup, dispatch_get_main_queue(), ^{
 | 
	
		
			
				|  |  | +        [self configUI];
 | 
	
		
			
				|  |  |          [self configPlayer];
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +- (void)modifySpeed {
 | 
	
		
			
				|  |  | +    dispatch_group_enter(self.requestGroup);
 | 
	
		
			
				|  |  | +    [self modifyBgSpeed:self.bgAudioUrl callback:^{
 | 
	
		
			
				|  |  | +        dispatch_group_leave(self.requestGroup);
 | 
	
		
			
				|  |  |      }];
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -- (void)configRemoteVideoUrl:(NSString *)remoteVideoUrl bgAudioUrl:(NSString *)remoteBgAudioUrl recordUrl:(NSString *)remoteRecrodUrl jsonConfig:(NSString *)jsonConfig callback:(DraftEditCallback)callback {
 | 
	
		
			
				|  |  | +- (void)requestSource {
 | 
	
		
			
				|  |  | +    dispatch_group_enter(self.requestGroup);
 | 
	
		
			
				|  |  | +    [KSNetworkingManager musicPracticeRecordRequest:KS_GET recordId:self.recordId success:^(NSDictionary * _Nonnull dic) {
 | 
	
		
			
				|  |  | +        if (dic) {
 | 
	
		
			
				|  |  | +            NSDictionary *data = [dic ks_dictionaryValueForKey:@"data"];
 | 
	
		
			
				|  |  | +            if (data == nil) {
 | 
	
		
			
				|  |  | +                self.hasSaveDraft = NO;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else {
 | 
	
		
			
				|  |  | +                self.hasSaveDraft = YES;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        dispatch_group_leave(self.requestGroup);
 | 
	
		
			
				|  |  | +    } faliure:^(NSError * _Nonnull error) {
 | 
	
		
			
				|  |  | +        dispatch_group_leave(self.requestGroup);
 | 
	
		
			
				|  |  | +    }];
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +- (void)checkGuide {
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    if (UserDefaultBoolForKey(MERGE_GUIDEKEY) == NO) {
 | 
	
		
			
				|  |  | +        self.needShowGuide = YES;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +- (void)configRemoteVideoUrl:(NSString *)remoteVideoUrl bgAudioUrl:(NSString *)remoteBgAudioUrl recordUrl:(NSString *)remoteRecrodUrl jsonConfig:(NSString *)jsonConfig callback:(DraftEditCallback)callback {
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  |      if (callback) {
 | 
	
		
			
				|  |  |          self.draftCallback = callback;
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -207,15 +291,21 @@
 | 
	
		
			
				|  |  |      self.offsetTime = self.originalOffset;
 | 
	
		
			
				|  |  |      [self.contrlView configWithOffsetTime:self.originalOffset];
 | 
	
		
			
				|  |  |      self.contrlView.hideBackView = YES;
 | 
	
		
			
				|  |  | +    // 草稿列表表示已保存了
 | 
	
		
			
				|  |  | +    self.hasSaveDraft = YES;
 | 
	
		
			
				|  |  |      [self downloadFileSource];
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  - (void)downloadFileSource {
 | 
	
		
			
				|  |  | -    [LOADING_MANAGER showCustomLoading:@"资源下载中"];
 | 
	
		
			
				|  |  | +    [LOADING_MANAGER showCancelCustomLoading:@"资源加载中,请稍等…" cancel:^{
 | 
	
		
			
				|  |  | +        [self cancelTask];
 | 
	
		
			
				|  |  | +    }];
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  |      [self downloadVideo];
 | 
	
		
			
				|  |  |      [self downloadAccompany];
 | 
	
		
			
				|  |  |      [self downloadAudio];
 | 
	
		
			
				|  |  | +    [self checkGuide];
 | 
	
		
			
				|  |  |      dispatch_group_notify(self.requestGroup, dispatch_get_main_queue(), ^{
 | 
	
		
			
				|  |  |          [self configUI];
 | 
	
		
			
				|  |  |          [self configPlayer];
 | 
	
	
		
			
				|  | @@ -228,6 +318,9 @@
 | 
	
		
			
				|  |  |          [KSNetworkingManager downloadFileRequestWithFileUrl:self.remoteVideoUrl progress:^(int64_t bytesRead, int64_t totalBytes) {
 | 
	
		
			
				|  |  |              
 | 
	
		
			
				|  |  |          } success:^(NSURL * _Nonnull fileUrl) {
 | 
	
		
			
				|  |  | +            if (self.isCancel) {
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |              dispatch_group_leave(self.requestGroup);
 | 
	
		
			
				|  |  |              self.videoUrl = fileUrl;
 | 
	
		
			
				|  |  |          } faliure:^(NSError * _Nonnull error) {
 | 
	
	
		
			
				|  | @@ -258,6 +351,9 @@
 | 
	
		
			
				|  |  |          [KSNetworkingManager downloadFileRequestWithFileUrl:self.remoteRecrodUrl progress:^(int64_t bytesRead, int64_t totalBytes) {
 | 
	
		
			
				|  |  |              
 | 
	
		
			
				|  |  |          } success:^(NSURL * _Nonnull fileUrl) {
 | 
	
		
			
				|  |  | +            if (self.isCancel) {
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |              dispatch_group_leave(self.requestGroup);
 | 
	
		
			
				|  |  |              self.recordUrl = fileUrl;
 | 
	
		
			
				|  |  |          } faliure:^(NSError * _Nonnull error) {
 | 
	
	
		
			
				|  | @@ -272,6 +368,9 @@
 | 
	
		
			
				|  |  |          [KSNetworkingManager downloadFileRequestWithFileUrl:self.remoteBgAudioUrl progress:^(int64_t bytesRead, int64_t totalBytes) {
 | 
	
		
			
				|  |  |              
 | 
	
		
			
				|  |  |          } success:^(NSURL * _Nonnull fileUrl) {
 | 
	
		
			
				|  |  | +            if (self.isCancel) {
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |              self.bgAudioUrl = fileUrl;
 | 
	
		
			
				|  |  |              [self modifyBgSpeed:self.bgAudioUrl callback:^{
 | 
	
		
			
				|  |  |                  dispatch_group_leave(self.requestGroup);
 | 
	
	
		
			
				|  | @@ -283,13 +382,19 @@
 | 
	
		
			
				|  |  |          }];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  - (void)configPlayer {
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | +    if (self.isCancel) {
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    BOOL needAnalyzer = YES;
 | 
	
		
			
				|  |  |      if (self.isVideoPlay) {
 | 
	
		
			
				|  |  |          [self.videoView preparePlayNativeVideoWithPath:self.videoUrl];
 | 
	
		
			
				|  |  |          self.videoView.isMute = YES;
 | 
	
		
			
				|  |  | +        needAnalyzer = NO;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    // 视频不需要分析频谱
 | 
	
		
			
				|  |  | +    self.mergePlayer.needAnalyzer = needAnalyzer;
 | 
	
		
			
				|  |  |      if (self.bgAudioUrl && self.recordUrl) {
 | 
	
		
			
				|  |  |          [self.mergePlayer prepareNativeSongWithUrl:self.recordUrl bgMusic:self.bgAudioUrl];;
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -311,12 +416,46 @@
 | 
	
		
			
				|  |  |      [self.contrlView configRecordVolume:originalVolume bgVolume:accompanyVolume];
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +- (void)configAnalyzerDefault:(CGFloat)spectrumViewWidth {
 | 
	
		
			
				|  |  | +    if (_spectrumView) {
 | 
	
		
			
				|  |  | +        CGFloat barSpace = spectrumViewWidth / (CGFloat)(self.mergePlayer.analyzer.frequencyBands * 3 - 1);
 | 
	
		
			
				|  |  | +        self.spectrumView.barWidth = barSpace * 1.5;
 | 
	
		
			
				|  |  | +        self.spectrumView.space = barSpace * 1.5;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  - (void)configUI {
 | 
	
		
			
				|  |  | +    CGFloat leftSpace = STATUS_GAP;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    if (self.isCancel) {
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  |      self.backgroundColor = [UIColor whiteColor];
 | 
	
		
			
				|  |  |      if (self.isVideoPlay) {
 | 
	
		
			
				|  |  |          [self addSubview:self.videoView];
 | 
	
		
			
				|  |  | +        // 添加顶部阴影
 | 
	
		
			
				|  |  | +        UIView *headLayerView = [[UIView alloc] init];
 | 
	
		
			
				|  |  | +        [self addSubview:headLayerView];
 | 
	
		
			
				|  |  | +        [headLayerView mas_makeConstraints:^(MASConstraintMaker *make) {
 | 
	
		
			
				|  |  | +            make.left.right.top.mas_equalTo(self);
 | 
	
		
			
				|  |  | +            make.height.mas_equalTo(70);
 | 
	
		
			
				|  |  | +        }];
 | 
	
		
			
				|  |  | +        CAGradientLayer *headLayer = [UIView createGradientLayerFromColor:HexRGBAlpha(0x000000, 0.7f) startPoint:CGPointMake(0.5, 0) endColor:HexRGBAlpha(0x000000, 0.0f) endPoint:CGPointMake(0.5, 1) bounds:CGRectMake(0, 0, KLandscapeWidth, 70)];
 | 
	
		
			
				|  |  | +        [headLayerView.layer addSublayer:headLayer];
 | 
	
		
			
				|  |  | +        // 添加底部阴影
 | 
	
		
			
				|  |  | +        UIView *bottomLayerView = [[UIView alloc] init];
 | 
	
		
			
				|  |  | +        [self addSubview:bottomLayerView];
 | 
	
		
			
				|  |  | +        [bottomLayerView mas_makeConstraints:^(MASConstraintMaker *make) {
 | 
	
		
			
				|  |  | +            make.left.right.bottom.mas_equalTo(self);
 | 
	
		
			
				|  |  | +            make.height.mas_equalTo(150);
 | 
	
		
			
				|  |  | +        }];
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        CAGradientLayer *bottomLayer = [UIView createGradientLayerFromColor:HexRGBAlpha(0x000000, 0.0f) startPoint:CGPointMake(0.5, 0) endColor:HexRGBAlpha(0x000000, 0.7f) endPoint:CGPointMake(0.5, 1) bounds:CGRectMake(0, 0, KLandscapeWidth, 150)];
 | 
	
		
			
				|  |  | +        [bottomLayerView.layer addSublayer:bottomLayer];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      else {
 | 
	
		
			
				|  |  | +        // 动效
 | 
	
		
			
				|  |  |          [self addSubview:self.playerView];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      
 | 
	
	
		
			
				|  | @@ -341,31 +480,36 @@
 | 
	
		
			
				|  |  |          UIImageView *shadowImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"merge_music_bg"]];
 | 
	
		
			
				|  |  |          [self.playerView addSubview:shadowImage];
 | 
	
		
			
				|  |  |          
 | 
	
		
			
				|  |  | +        // 音波动画
 | 
	
		
			
				|  |  | +        [self.playerView addSubview:self.spectrumView];
 | 
	
		
			
				|  |  |          
 | 
	
		
			
				|  |  | -        [self.playerView addSubview:self.playAnimationView];
 | 
	
		
			
				|  |  | -        [self.playAnimationView mas_makeConstraints:^(MASConstraintMaker *make) {
 | 
	
		
			
				|  |  | -            make.centerX.mas_equalTo(self.playerView.mas_centerX);
 | 
	
		
			
				|  |  | -            make.centerY.mas_equalTo(self.playerView.mas_centerY);
 | 
	
		
			
				|  |  | -            make.width.mas_equalTo(424);
 | 
	
		
			
				|  |  | -            make.height.mas_equalTo(80);
 | 
	
		
			
				|  |  | -        }];
 | 
	
		
			
				|  |  | +        CGFloat ratio = IS_IPAD ? 1.5 : 1.2;
 | 
	
		
			
				|  |  |          
 | 
	
		
			
				|  |  |          [self.playerView mas_makeConstraints:^(MASConstraintMaker *make) {
 | 
	
		
			
				|  |  |              make.left.top.bottom.mas_equalTo(self);
 | 
	
		
			
				|  |  |              make.right.mas_equalTo(self.contrlView.mas_left).offset(20);
 | 
	
		
			
				|  |  |          }];
 | 
	
		
			
				|  |  |          
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  |          [self.playerView addSubview:self.animationView];
 | 
	
		
			
				|  |  |          [self.animationView mas_makeConstraints:^(MASConstraintMaker *make) {
 | 
	
		
			
				|  |  |              make.centerX.mas_equalTo(self.playerView.mas_centerX);
 | 
	
		
			
				|  |  | -            make.centerY.mas_equalTo(self.playerView.mas_centerY);
 | 
	
		
			
				|  |  | -            make.width.height.mas_equalTo(200);
 | 
	
		
			
				|  |  | +            make.centerY.mas_equalTo(self.playerView.mas_centerY).offset(-20);
 | 
	
		
			
				|  |  | +            make.width.height.mas_equalTo(180);
 | 
	
		
			
				|  |  |          }];
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        [self.spectrumView mas_makeConstraints:^(MASConstraintMaker *make) {
 | 
	
		
			
				|  |  | +            make.centerX.mas_equalTo(self.animationView.mas_centerX);
 | 
	
		
			
				|  |  | +            make.centerY.mas_equalTo(self.animationView.mas_centerY);
 | 
	
		
			
				|  |  | +            make.width.mas_equalTo(320 * ratio);
 | 
	
		
			
				|  |  | +            make.height.mas_equalTo(100 * ratio);
 | 
	
		
			
				|  |  | +        }];
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  |          [shadowImage mas_makeConstraints:^(MASConstraintMaker *make) {
 | 
	
		
			
				|  |  | -            make.width.mas_equalTo(284);
 | 
	
		
			
				|  |  | -            make.height.mas_equalTo(151);
 | 
	
		
			
				|  |  | +            make.width.mas_equalTo(284*0.9);
 | 
	
		
			
				|  |  | +            make.height.mas_equalTo(151*0.9);
 | 
	
		
			
				|  |  |              make.centerX.mas_equalTo(self.playerView.mas_centerX);
 | 
	
		
			
				|  |  | -            make.top.mas_equalTo(self.animationView.mas_top).offset(86);
 | 
	
		
			
				|  |  | +            make.top.mas_equalTo(self.animationView.mas_top).offset(86*0.9);
 | 
	
		
			
				|  |  |          }];
 | 
	
		
			
				|  |  |          [self.animationView configWithImageWithUrl:self.coverImage];
 | 
	
		
			
				|  |  |          
 | 
	
	
		
			
				|  | @@ -373,35 +517,93 @@
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  |      [self addSubview:self.playControlView];
 | 
	
		
			
				|  |  |      [self.playControlView mas_makeConstraints:^(MASConstraintMaker *make) {
 | 
	
		
			
				|  |  | -        make.left.mas_equalTo(self.mas_left);
 | 
	
		
			
				|  |  | +        make.left.mas_equalTo(self.mas_left).offset(leftSpace);
 | 
	
		
			
				|  |  |          make.right.mas_equalTo(self.contrlView.mas_left).offset(-20);
 | 
	
		
			
				|  |  |          make.height.mas_equalTo(44);
 | 
	
		
			
				|  |  |          make.bottom.mas_equalTo(self.mas_bottom).offset(-30);
 | 
	
		
			
				|  |  |      }];
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  |      [self.playControlView configViewDisplayColor:self.isVideoPlay];
 | 
	
		
			
				|  |  | -    NSString *imgName = self.isVideoPlay ? @"back_button_white" : @"back_black";
 | 
	
		
			
				|  |  | +    NSString *imgName = self.isVideoPlay ? @"merge_back_white" : @"merge_back_black";
 | 
	
		
			
				|  |  |      UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
 | 
	
		
			
				|  |  |      [backButton setImage:[UIImage imageNamed:imgName] forState:UIControlStateNormal];
 | 
	
		
			
				|  |  |      [backButton addTarget:self action:@selector(backAction) forControlEvents:UIControlEventTouchUpInside];
 | 
	
		
			
				|  |  |      [self addSubview:backButton];
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  |      [backButton mas_makeConstraints:^(MASConstraintMaker *make) {
 | 
	
		
			
				|  |  |          make.width.height.mas_equalTo(44);
 | 
	
		
			
				|  |  | -        make.left.mas_equalTo(self.mas_left).offset(10);
 | 
	
		
			
				|  |  | -        make.top.mas_equalTo(self.mas_top).offset(10);
 | 
	
		
			
				|  |  | +        make.left.mas_equalTo(self.mas_left).offset(10.5);
 | 
	
		
			
				|  |  | +        make.top.mas_equalTo(self.mas_top).offset(10.5);
 | 
	
		
			
				|  |  |      }];
 | 
	
		
			
				|  |  | -        
 | 
	
		
			
				|  |  | -    UILabel *songLabel = [[UILabel alloc] init];
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    CBAutoScrollLabel *songLabel = [[CBAutoScrollLabel alloc] init];
 | 
	
		
			
				|  |  |      songLabel.font = [UIFont systemFontOfSize:16.0f weight:UIFontWeightSemibold];
 | 
	
		
			
				|  |  |      songLabel.text = [NSString returnNoNullStringWithString:self.songName];
 | 
	
		
			
				|  |  |      songLabel.textColor = self.isVideoPlay ? HexRGB(0xffffff) : HexRGB(0x131415);
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    songLabel.labelSpacing = 30;
 | 
	
		
			
				|  |  | +    songLabel.pauseInterval = 1.5;
 | 
	
		
			
				|  |  | +    songLabel.scrollDirection = CBAutoScrollDirectionLeft;
 | 
	
		
			
				|  |  | +    [songLabel observeApplicationNotifications];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      [self addSubview:songLabel];
 | 
	
		
			
				|  |  |      [songLabel mas_makeConstraints:^(MASConstraintMaker *make) {
 | 
	
		
			
				|  |  | -        make.left.mas_equalTo(backButton.mas_right);
 | 
	
		
			
				|  |  | -        make.centerY.mas_equalTo(backButton.mas_centerY);
 | 
	
		
			
				|  |  | +        make.left.mas_equalTo(backButton.mas_right).offset(4);
 | 
	
		
			
				|  |  | +        make.top.mas_equalTo(self.mas_top).offset(20);
 | 
	
		
			
				|  |  |          make.height.mas_equalTo(22);
 | 
	
		
			
				|  |  | -        make.right.mas_greaterThanOrEqualTo(self.contrlView.mas_left).offset(20);
 | 
	
		
			
				|  |  | +        make.width.mas_equalTo(200);
 | 
	
		
			
				|  |  | +    }];
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    UILabel *singerLabel = [[UILabel alloc] init];
 | 
	
		
			
				|  |  | +    singerLabel.font = [UIFont systemFontOfSize:12.0f weight:UIFontWeightRegular];
 | 
	
		
			
				|  |  | +    singerLabel.textColor = self.isVideoPlay ? HexRGB(0xffffff) : HexRGB(0x333333);
 | 
	
		
			
				|  |  | +    [self addSubview:singerLabel];
 | 
	
		
			
				|  |  | +    [singerLabel mas_makeConstraints:^(MASConstraintMaker *make) {
 | 
	
		
			
				|  |  | +        make.left.mas_equalTo(songLabel.mas_left);
 | 
	
		
			
				|  |  | +        make.top.mas_equalTo(songLabel.mas_bottom).offset(4);
 | 
	
		
			
				|  |  | +        make.height.mas_equalTo(18);
 | 
	
		
			
				|  |  | +        make.right.mas_equalTo(songLabel.mas_right);
 | 
	
		
			
				|  |  |      }];
 | 
	
		
			
				|  |  | +    NSString *userName = [NSString returnNoNullStringWithString:UserDefault(NicknameKey)];
 | 
	
		
			
				|  |  | +    if (userName.length > 8) {
 | 
	
		
			
				|  |  | +        userName = [NSString stringWithFormat:@"%@...", [userName substringWithRange:NSMakeRange(0, 8)]];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    singerLabel.text = [NSString stringWithFormat:@"演奏:%@",userName];
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    // 添加曲谱占位
 | 
	
		
			
				|  |  | +    if (![NSString isEmptyString:self.musicSheetId]) {
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        [self addSubview:self.webViewContainer];
 | 
	
		
			
				|  |  | +        [self.webViewContainer mas_makeConstraints:^(MASConstraintMaker *make) {
 | 
	
		
			
				|  |  | +            make.left.mas_equalTo(self.mas_left);
 | 
	
		
			
				|  |  | +            make.bottom.mas_equalTo(self.playControlView.mas_top);
 | 
	
		
			
				|  |  | +            make.right.mas_equalTo(self.contrlView.mas_left);
 | 
	
		
			
				|  |  | +            make.height.mas_equalTo(68+WEB_TOP);
 | 
	
		
			
				|  |  | +        }];
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        if (self.isVideoPlay) {
 | 
	
		
			
				|  |  | +            self.colorView = [[UIView alloc] initWithFrame:CGRectZero];
 | 
	
		
			
				|  |  | +            self.colorView.backgroundColor = HexRGBAlpha(0xffffff, 0.7);
 | 
	
		
			
				|  |  | +            [self.webViewContainer addSubview:self.colorView];
 | 
	
		
			
				|  |  | +            [self.colorView mas_makeConstraints:^(MASConstraintMaker *make) {
 | 
	
		
			
				|  |  | +                make.left.right.top.bottom.mas_equalTo(self.webViewContainer);
 | 
	
		
			
				|  |  | +            }];
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        [self.webViewContainer addSubview:self.staffView];
 | 
	
		
			
				|  |  | +//        NSString *rendMode = self.isVideoPlay ? @"video" : @"audio";
 | 
	
		
			
				|  |  | +        NSString *rendMode = @"audio";
 | 
	
		
			
				|  |  | +        [self.staffView loadWebViewWithSongID:self.musicSheetId renderType:self.musicRenderType partIndex:self.partIndex backgroundMode:rendMode];
 | 
	
		
			
				|  |  | +        [self.staffView mas_makeConstraints:^(MASConstraintMaker *make) {
 | 
	
		
			
				|  |  | +            make.left.mas_equalTo(self.webViewContainer.mas_left).offset(leftSpace);
 | 
	
		
			
				|  |  | +            make.right.mas_equalTo(self.webViewContainer.mas_right).offset(-20);
 | 
	
		
			
				|  |  | +            make.top.mas_equalTo(self.webViewContainer.mas_top).offset(WEB_TOP);
 | 
	
		
			
				|  |  | +            make.bottom.mas_equalTo(self.webViewContainer.mas_bottom);
 | 
	
		
			
				|  |  | +        }];
 | 
	
		
			
				|  |  | +        self.webViewContainer.hidden = YES;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //将按钮提前
 | 
	
		
			
				|  |  | +    [self bringSubviewToFront:self.showButton];
 | 
	
		
			
				|  |  | +    [self bringSubviewToFront:backButton];
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  - (void)refreshTotalTime {
 | 
	
	
		
			
				|  | @@ -413,12 +615,14 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  - (void)backAction {
 | 
	
		
			
				|  |  |      [self stopPlay];
 | 
	
		
			
				|  |  | -    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
 | 
	
		
			
				|  |  | -        if (self.hasModify) {
 | 
	
		
			
				|  |  | +    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
 | 
	
		
			
				|  |  | +        // 如果修改过或者没有保存过草稿
 | 
	
		
			
				|  |  | +        if (self.hasModify || self.hasSaveDraft == NO) {
 | 
	
		
			
				|  |  |              MJWeakSelf;
 | 
	
		
			
				|  |  | -            [self.alertView configTitle:@"提示" descMessage:@"是否将本次录制的作品保存为草稿?" leftButtonTitle:@"取消" rightButtonTitle:@"确认" leftButtonAction:^{
 | 
	
		
			
				|  |  | +            [self.alertView configWithDesc:@"是否将本次录制的作品存为草稿?" leftTitle:@"取消" rightTitle:@"确认"];
 | 
	
		
			
				|  |  | +            [self.alertView actionCallbackCancel:^{
 | 
	
		
			
				|  |  |                  [weakSelf removeViewTips:NO];
 | 
	
		
			
				|  |  | -            } rightButtonAction:^{
 | 
	
		
			
				|  |  | +            } sure:^{
 | 
	
		
			
				|  |  |                  [weakSelf saveCurrentDraft:YES];
 | 
	
		
			
				|  |  |              }];
 | 
	
		
			
				|  |  |              [self.alertView showAlert];
 | 
	
	
		
			
				|  | @@ -434,6 +638,26 @@
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// 重新评测
 | 
	
		
			
				|  |  | +- (void)retryEvaluatingAlert {
 | 
	
		
			
				|  |  | +    MJWeakSelf;
 | 
	
		
			
				|  |  | +    [self.alertView configWithDesc:@"是否重新录制作品?" leftTitle:@"取消" rightTitle:@"确认"];
 | 
	
		
			
				|  |  | +    [self.alertView actionCallbackCancel:^{
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +    } sure:^{
 | 
	
		
			
				|  |  | +        [weakSelf retryEvaluating];
 | 
	
		
			
				|  |  | +    }];
 | 
	
		
			
				|  |  | +    [self.alertView showAlert];
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +- (void)retryEvaluating {
 | 
	
		
			
				|  |  | +    [self freePlayer];
 | 
	
		
			
				|  |  | +    [self removeFromSuperview];
 | 
	
		
			
				|  |  | +    if (self.mergeCallback) {
 | 
	
		
			
				|  |  | +        self.mergeCallback(MERGEBACK_RETRY);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #pragma mark ----- lazying
 | 
	
		
			
				|  |  |  - (KSAudioAnimationView *)animationView {
 | 
	
		
			
				|  |  |      if (!_animationView) {
 | 
	
	
		
			
				|  | @@ -473,9 +697,9 @@
 | 
	
		
			
				|  |  |      if (self.isVideoPlay) {
 | 
	
		
			
				|  |  |          [self.videoView seekToTimePlay:playPosition];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    else {
 | 
	
		
			
				|  |  | -        [self.playAnimationView startAnimation];
 | 
	
		
			
				|  |  | -        [self startTimer];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (_staffView) {
 | 
	
		
			
				|  |  | +        [self.staffView staffPageStartPlay];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -487,9 +711,11 @@
 | 
	
		
			
				|  |  |      if (self.isVideoPlay) {
 | 
	
		
			
				|  |  |          [self.videoView puasePlay];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    else {
 | 
	
		
			
				|  |  | -        [self.playAnimationView stopAnimation];
 | 
	
		
			
				|  |  | -        [self stopTimer];
 | 
	
		
			
				|  |  | +    if (_staffView) {
 | 
	
		
			
				|  |  | +        [self.staffView staffPageStop:self.playControlView.playScheduleTime];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if (_spectrumView) {
 | 
	
		
			
				|  |  | +        [self.spectrumView resetLayer];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -510,7 +736,11 @@
 | 
	
		
			
				|  |  |              if (self.mergePlayer.isPlaying) {
 | 
	
		
			
				|  |  |                  [self.mergePlayer seekToTimePlay:rate];
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            
 | 
	
		
			
				|  |  | +            else {
 | 
	
		
			
				|  |  | +                if (_staffView) {
 | 
	
		
			
				|  |  | +                    [self.staffView updateSliderProgress:rate/1000.0f];
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |              if (self.isVideoPlay) {
 | 
	
		
			
				|  |  |  //                NSInteger realOffsetTime = self.offsetTime + self.evaluateDelay;
 | 
	
		
			
				|  |  |                  [self.videoView seekOffsetTime:rate];
 | 
	
	
		
			
				|  | @@ -523,15 +753,6 @@
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -- (void)startTimer {
 | 
	
		
			
				|  |  | -    [self.timer setFireDate:[NSDate distantPast]];
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -- (void)stopTimer {
 | 
	
		
			
				|  |  | -    [self.timer setFireDate:[NSDate distantFuture]];
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  - (KSMergeAudioControlView *)contrlView {
 | 
	
		
			
				|  |  |      if (!_contrlView) {
 | 
	
		
			
				|  |  |          _contrlView = [KSMergeAudioControlView shareIntance];
 | 
	
	
		
			
				|  | @@ -548,7 +769,8 @@
 | 
	
		
			
				|  |  |      switch (action) {
 | 
	
		
			
				|  |  |          case MERGEACTION_CANCLE:
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            [self backAction];
 | 
	
		
			
				|  |  | +            [self stopPlay];
 | 
	
		
			
				|  |  | +            [self retryEvaluatingAlert];
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |              break;
 | 
	
		
			
				|  |  |          case MERGEACTION_MODIFY:
 | 
	
	
		
			
				|  | @@ -585,6 +807,7 @@
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              [self stopPlay];
 | 
	
		
			
				|  |  |              [self showPublishAlert];
 | 
	
		
			
				|  |  | +            
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |              break;
 | 
	
		
			
				|  |  |          case MERGEACTION_HIDEVIEW:
 | 
	
	
		
			
				|  | @@ -612,6 +835,8 @@
 | 
	
		
			
				|  |  |      switch (type) {
 | 
	
		
			
				|  |  |          case PUBLISH_ACTION_PUBLISH:
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | +            // 暂停播放
 | 
	
		
			
				|  |  | +            [self stopPlay];
 | 
	
		
			
				|  |  |              self.desc = [NSString isEmptyString:self.publishAlert.publishContainView.textView.text] ? @"我发布了一首演奏作品,快来听听吧~" :self.publishAlert.publishContainView.textView.text;
 | 
	
		
			
				|  |  |              if (self.settingImage || self.videoCoverImage) { // 上传图片
 | 
	
		
			
				|  |  |                  [self updateWithCoverImage];
 | 
	
	
		
			
				|  | @@ -717,7 +942,7 @@
 | 
	
		
			
				|  |  |          NSData *imgData = [UIImage turnsImaegDataByImage:self.settingImage];
 | 
	
		
			
				|  |  |          NSString *fileName = @"musicCoverImg";
 | 
	
		
			
				|  |  |          [UPLOAD_MANAGER configWithfilePath:@"/user/"];
 | 
	
		
			
				|  |  | -        [[KSUploadManager shareInstance] uploadImage:imgData fileName:fileName successCallback:^(NSMutableArray * _Nonnull fileUrlArray) {
 | 
	
		
			
				|  |  | +        [UPLOAD_MANAGER uploadImage:imgData fileName:fileName successCallback:^(NSMutableArray * _Nonnull fileUrlArray) {
 | 
	
		
			
				|  |  |              NSString *avatarUrl = [fileUrlArray lastObject];
 | 
	
		
			
				|  |  |              self.coverImage = avatarUrl;
 | 
	
		
			
				|  |  |              [self uploadVideoCover];
 | 
	
	
		
			
				|  | @@ -738,7 +963,7 @@
 | 
	
		
			
				|  |  |          NSData *imgData = [UIImage turnsImaegDataByImage:self.videoCoverImage];
 | 
	
		
			
				|  |  |          NSString *fileName = @"musicCoverImg";
 | 
	
		
			
				|  |  |          [UPLOAD_MANAGER configWithfilePath:@"/user/"];
 | 
	
		
			
				|  |  | -        [[KSUploadManager shareInstance] uploadImage:imgData fileName:fileName successCallback:^(NSMutableArray * _Nonnull fileUrlArray) {
 | 
	
		
			
				|  |  | +        [UPLOAD_MANAGER uploadImage:imgData fileName:fileName successCallback:^(NSMutableArray * _Nonnull fileUrlArray) {
 | 
	
		
			
				|  |  |              NSString *avatarUrl = [fileUrlArray lastObject];
 | 
	
		
			
				|  |  |              self.videoCoverUrl = avatarUrl;
 | 
	
		
			
				|  |  |              [self publishMusic];
 | 
	
	
		
			
				|  | @@ -903,10 +1128,32 @@
 | 
	
		
			
				|  |  |  #pragma mark ----- player delegate
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  - (void)videoPlayerIsReadyPlay:(AVPlayer *)player {
 | 
	
		
			
				|  |  | +    if (self.isCancel) {
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      if (self.mergePlayer.isReady) {
 | 
	
		
			
				|  |  | -        [LOADING_MANAGER removeCustomLoading];
 | 
	
		
			
				|  |  | -        [self startPlay];
 | 
	
		
			
				|  |  | +        if (_staffView) {
 | 
	
		
			
				|  |  | +            if (self.staffView.isReady) {
 | 
	
		
			
				|  |  | +                if (self.needShowGuide) {
 | 
	
		
			
				|  |  | +                    [self configGuideView];
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                else {
 | 
	
		
			
				|  |  | +                    [LOADING_MANAGER removeCustomLoading];
 | 
	
		
			
				|  |  | +                    [self startPlay];
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else {
 | 
	
		
			
				|  |  | +            if (self.needShowGuide) {
 | 
	
		
			
				|  |  | +                [self configGuideView];
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else {
 | 
	
		
			
				|  |  | +                [LOADING_MANAGER removeCustomLoading];
 | 
	
		
			
				|  |  | +                [self startPlay];
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -935,27 +1182,71 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #pragma mark ------- merge Player delegate
 | 
	
		
			
				|  |  |  - (void)updatePlayProgress:(NSInteger)playTime andTotalTime:(NSInteger)totalTime andProgress:(CGFloat)progress currentInterval:(NSTimeInterval)currentInterval inPlayer:(KSMergeEnginePlayer *)player {
 | 
	
		
			
				|  |  | -    /*
 | 
	
		
			
				|  |  | -    CMTime videoPlayTime = [self.videoView getCurrentPlayTime];
 | 
	
		
			
				|  |  | -    NSTimeInterval videoTime = CMTimeGetSeconds(videoPlayTime) * 1000;
 | 
	
		
			
				|  |  | -    NSLog(@"----- offset %f ", playTime - videoTime);
 | 
	
		
			
				|  |  | -     */
 | 
	
		
			
				|  |  | +    //    NSLog(@"-------- playTime ---%zd", playTime);
 | 
	
		
			
				|  |  |      dispatch_main_async_safe(^{
 | 
	
		
			
				|  |  |          self.playControlView.playScheduleTime = playTime;
 | 
	
		
			
				|  |  | +        if (self->_staffView) {
 | 
	
		
			
				|  |  | +            [self.staffView updatePlayProgress:playTime/1000.0];
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  - (void)enginePlayerIsReadyPlay:(KSMergeEnginePlayer *)player {
 | 
	
		
			
				|  |  | +    if (self.isCancel) {
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      dispatch_main_async_safe(^{
 | 
	
		
			
				|  |  | -        [LOADING_MANAGER removeCustomLoading];
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        CGFloat ratio = IS_IPAD ? 1.5 : 1.2;
 | 
	
		
			
				|  |  | +        [self configAnalyzerDefault:(320 * ratio)];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          [self refreshTotalTime];
 | 
	
		
			
				|  |  |          if (self.isVideoPlay) {
 | 
	
		
			
				|  |  |              if (self.videoView.isReady) {
 | 
	
		
			
				|  |  | -                [self startPlay];
 | 
	
		
			
				|  |  | +                if (self->_staffView) {
 | 
	
		
			
				|  |  | +                    if (self.staffView.isReady) {
 | 
	
		
			
				|  |  | +                        if (self.needShowGuide) {
 | 
	
		
			
				|  |  | +                            [self configGuideView];
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                        else {
 | 
	
		
			
				|  |  | +                            [LOADING_MANAGER removeCustomLoading];
 | 
	
		
			
				|  |  | +                            [self startPlay];
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                else {
 | 
	
		
			
				|  |  | +                    if (self.needShowGuide) {
 | 
	
		
			
				|  |  | +                        [self configGuideView];
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                    else {
 | 
	
		
			
				|  |  | +                        [LOADING_MANAGER removeCustomLoading];
 | 
	
		
			
				|  |  | +                        [self startPlay];
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          else {
 | 
	
		
			
				|  |  | -            [self startPlay];
 | 
	
		
			
				|  |  | +            if (self->_staffView) {
 | 
	
		
			
				|  |  | +                if (self.staffView.isReady) {
 | 
	
		
			
				|  |  | +                    if (self.needShowGuide) {
 | 
	
		
			
				|  |  | +                        [self configGuideView];
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                    else {
 | 
	
		
			
				|  |  | +                        [LOADING_MANAGER removeCustomLoading];
 | 
	
		
			
				|  |  | +                        [self startPlay];
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else {
 | 
	
		
			
				|  |  | +                if (self.needShowGuide) {
 | 
	
		
			
				|  |  | +                    [self configGuideView];
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                else {
 | 
	
		
			
				|  |  | +                    [LOADING_MANAGER removeCustomLoading];
 | 
	
		
			
				|  |  | +                    [self startPlay];
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  |      
 | 
	
	
		
			
				|  | @@ -966,16 +1257,19 @@
 | 
	
		
			
				|  |  |          [self.mergePlayer stopPlay];
 | 
	
		
			
				|  |  |          self.animationView.isPlay = NO;
 | 
	
		
			
				|  |  |          self.playControlView.isPlay = NO;
 | 
	
		
			
				|  |  | -        [self.playAnimationView stopAnimation];
 | 
	
		
			
				|  |  | -        
 | 
	
		
			
				|  |  | -        [self stopTimer];
 | 
	
		
			
				|  |  |          self.playControlView.playScheduleTime = 0;
 | 
	
		
			
				|  |  |          
 | 
	
		
			
				|  |  |          if (self.isVideoPlay) {
 | 
	
		
			
				|  |  |              [self.videoView puasePlay];
 | 
	
		
			
				|  |  |              [self.videoView seekToStart];
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        
 | 
	
		
			
				|  |  | +        if (self->_staffView) {
 | 
	
		
			
				|  |  | +            [self.staffView staffPageStop:0];
 | 
	
		
			
				|  |  | +            [self.staffView updateSliderProgress:0];
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (self->_spectrumView) {
 | 
	
		
			
				|  |  | +            [self.spectrumView resetLayer];
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -1001,7 +1295,24 @@
 | 
	
		
			
				|  |  |              
 | 
	
		
			
				|  |  |          }];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +- (void)player:(KSMergeEnginePlayer *)player didGenerateSpectrum:(NSArray<NSArray<NSNumber *> *> *)spectra {
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | +    dispatch_main_async_safe(^{
 | 
	
		
			
				|  |  | +        if (self->_spectrumView) {
 | 
	
		
			
				|  |  | +            if (self.spectrumView.isModify == NO) {
 | 
	
		
			
				|  |  | +                self.spectrumView.spectra = spectra;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +- (KSSpectrumView *)spectrumView {
 | 
	
		
			
				|  |  | +    if (!_spectrumView) {
 | 
	
		
			
				|  |  | +        _spectrumView = [[KSSpectrumView alloc] initWithFrame:CGRectMake(0, 0, 320, 100)];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return _spectrumView;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  - (KSVideoPlayerView *)videoView {
 | 
	
	
		
			
				|  | @@ -1061,7 +1372,10 @@
 | 
	
		
			
				|  |  |      [parm setValue:@(self.accompanyVolume) forKey:@"accompanyVolume"];
 | 
	
		
			
				|  |  |      [parm setValue:@(self.defaultDelay) forKey:@"defaultDelay"];
 | 
	
		
			
				|  |  |      [parm setValue:@(self.evaluateDelay) forKey:@"evaluateDelay"];
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +    [parm setValue:@(self.musicSpeed) forKey:@"speedRate"];
 | 
	
		
			
				|  |  | +    [parm setValue:self.musicRenderType forKey:@"musicRenderType"];
 | 
	
		
			
				|  |  | +    [parm setValue:@(self.partIndex) forKey:@"part-index"];
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  |      self.jsonConfig = [parm mj_JSONString];
 | 
	
		
			
				|  |  |      [KSNetworkingManager saveMusicMessage:KS_POST jsonConfig:self.jsonConfig img:self.coverImage videoUrl:fileUrl accompanyUrl:self.remoteBgAudioUrl desc:self.desc type:type musicPracticeRecordId:self.recordId videoImg:self.videoCoverUrl success:^(NSDictionary * _Nonnull dic) {
 | 
	
		
			
				|  |  |          if ([dic ks_integerValueForKey:@"code"] == 200) {
 | 
	
	
		
			
				|  | @@ -1108,6 +1422,7 @@
 | 
	
		
			
				|  |  |      [shareView shareOutCallback:^(MINESHARETYPE type) {
 | 
	
		
			
				|  |  |          [weakSelf shareAction:type desc:desc productId:productId];
 | 
	
		
			
				|  |  |      }];
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  - (void)shareAction:(MINESHARETYPE)type desc:(NSString *)desc productId:(NSString *)productId {
 | 
	
	
		
			
				|  | @@ -1117,7 +1432,6 @@
 | 
	
		
			
				|  |  |      UIImage *image = [UIImage new];
 | 
	
		
			
				|  |  |      NSString *descMessage = desc;
 | 
	
		
			
				|  |  |      id thumImage = [NSString isEmptyString:self.coverImage] ? [UIImage imageNamed:@"pub_music_placeholder"] : [self.coverImage getUrlEndcodeString];
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  |      switch (type) {
 | 
	
		
			
				|  |  |          case MINESHARETYPE_FRIEND:
 | 
	
		
			
				|  |  |          {
 | 
	
	
		
			
				|  | @@ -1152,18 +1466,20 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  - (void)showSaveDraftTipsAlert {
 | 
	
		
			
				|  |  |      MJWeakSelf;
 | 
	
		
			
				|  |  | -    [self.alertView configTitle:@"提示" descMessage:@"已成功保存到草稿,草稿7天未发布将自动删除。" leftButtonTitle:@"确认" rightButtonTitle:@"查看草稿" leftButtonAction:^{
 | 
	
		
			
				|  |  | +    [self.alertView configWithDesc:@"已成功保存到草稿,草稿7天未发布将自动删除。" leftTitle:@"我知道了" rightTitle:@"查看草稿"];
 | 
	
		
			
				|  |  | +    [self.alertView actionCallbackCancel:^{
 | 
	
		
			
				|  |  |          
 | 
	
		
			
				|  |  | -    } rightButtonAction:^{
 | 
	
		
			
				|  |  | +    } sure:^{
 | 
	
		
			
				|  |  |          [weakSelf displayDraft];
 | 
	
		
			
				|  |  |      }];
 | 
	
		
			
				|  |  |      [self.alertView showAlert];
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  - (void)displayDraft {
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  | +    [self freePlayer];
 | 
	
		
			
				|  |  |      // 跳转到我的作品
 | 
	
		
			
				|  |  |      UIViewController *baseCtrl = [self findViewController];
 | 
	
		
			
				|  |  |      [baseCtrl.navigationController popToRootViewControllerAnimated:YES];
 | 
	
	
		
			
				|  | @@ -1179,7 +1495,7 @@
 | 
	
		
			
				|  |  |      NSData *fileData = [NSData dataWithContentsOfURL:fileUrl];
 | 
	
		
			
				|  |  |      NSString *suffix = [NSString stringWithFormat:@".%@",[fileUrl pathExtension]];
 | 
	
		
			
				|  |  |      [UPLOAD_MANAGER configWithfilePath:@"/user/"];
 | 
	
		
			
				|  |  | -    [[KSUploadManager shareInstance] videoUpload:fileData fileName:@"video" fileSuffix:suffix progress:^(int64_t bytesWritten, int64_t totalBytes) {
 | 
	
		
			
				|  |  | +    [UPLOAD_MANAGER videoUpload:fileData fileName:@"video" fileSuffix:suffix progress:^(int64_t bytesWritten, int64_t totalBytes) {
 | 
	
		
			
				|  |  |          // 显示进度
 | 
	
		
			
				|  |  |          float progress = (bytesWritten*1.0 / totalBytes) * rate + beginProgress;
 | 
	
		
			
				|  |  |          dispatch_main_async_safe(^{
 | 
	
	
		
			
				|  | @@ -1248,40 +1564,14 @@
 | 
	
		
			
				|  |  |      return _playAnimationView;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -- (NSTimer *)timer{
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  | -    if (!_timer) {
 | 
	
		
			
				|  |  | -        MJWeakSelf;
 | 
	
		
			
				|  |  | -        _timer = [NSTimer scheduledTimerWithTimeInterval:0.5f repeats:YES block:^(NSTimer * _Nonnull timer) {
 | 
	
		
			
				|  |  | -            [weakSelf timerAction];
 | 
	
		
			
				|  |  | -        }];
 | 
	
		
			
				|  |  | -        [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
 | 
	
		
			
				|  |  | -        [_timer setFireDate:[NSDate distantFuture]];
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return _timer;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  - (void)timerAction {
 | 
	
		
			
				|  |  |      float value = drand48();
 | 
	
		
			
				|  |  |      [self.playAnimationView setSoundsValue:value];
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#pragma mark -- 重置定时器
 | 
	
		
			
				|  |  | -- (void)resetTimer{
 | 
	
		
			
				|  |  | -    [self.timer setFireDate:[NSDate distantPast]];
 | 
	
		
			
				|  |  | -    [_timer invalidate];
 | 
	
		
			
				|  |  | -    _timer = nil;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -- (void)removeAll{
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  | -    if (_timer) {
 | 
	
		
			
				|  |  | -        [_timer invalidate];
 | 
	
		
			
				|  |  | -        _timer = nil;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  |  - (void)dealloc {
 | 
	
		
			
				|  |  | -    [self removeAll];
 | 
	
		
			
				|  |  |      [[NSNotificationCenter defaultCenter] removeObserver:self];
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -1293,10 +1583,9 @@
 | 
	
		
			
				|  |  |      return _requestGroup;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -- (KSNewAlertView *)alertView {
 | 
	
		
			
				|  |  | +- (MergeTipsAlert *)alertView {
 | 
	
		
			
				|  |  |      if (!_alertView) {
 | 
	
		
			
				|  |  | -        _alertView = [KSNewAlertView shareInstance];
 | 
	
		
			
				|  |  | -        
 | 
	
		
			
				|  |  | +        _alertView = [MergeTipsAlert shareInstance];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      return _alertView;
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -1375,6 +1664,157 @@
 | 
	
		
			
				|  |  |      [controller dismissViewControllerAnimated:YES completion:nil];
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#pragma mark ----- 谱面
 | 
	
		
			
				|  |  | +- (UIView *)webViewContainer {
 | 
	
		
			
				|  |  | +    if (!_webViewContainer) {
 | 
	
		
			
				|  |  | +        _webViewContainer = [[UIView alloc] initWithFrame:CGRectZero];
 | 
	
		
			
				|  |  | +        _webViewContainer.backgroundColor = [UIColor clearColor];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return _webViewContainer;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +- (MergeMusicStaffView *)staffView {
 | 
	
		
			
				|  |  | +    if (!_staffView) {
 | 
	
		
			
				|  |  | +        _staffView = [MergeMusicStaffView shareIntance];
 | 
	
		
			
				|  |  | +        MJWeakSelf;
 | 
	
		
			
				|  |  | +        [_staffView webActionCallback:^(CGFloat pageHeight) {
 | 
	
		
			
				|  |  | +            [weakSelf refreshContainerHeight:pageHeight];
 | 
	
		
			
				|  |  | +        }];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return _staffView;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +- (void)refreshContainerHeight:(CGFloat)height {
 | 
	
		
			
				|  |  | +    [self.webViewContainer mas_updateConstraints:^(MASConstraintMaker *make) {
 | 
	
		
			
				|  |  | +        make.height.mas_equalTo(height+WEB_TOP);
 | 
	
		
			
				|  |  | +    }];
 | 
	
		
			
				|  |  | +    self.webViewContainer.hidden = NO;
 | 
	
		
			
				|  |  | +    if (self.isVideoPlay) {
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        if (self.videoView.isReady && self.mergePlayer.isReady) {
 | 
	
		
			
				|  |  | +            if (self.needShowGuide) {
 | 
	
		
			
				|  |  | +                [self configGuideView];
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else {
 | 
	
		
			
				|  |  | +                [LOADING_MANAGER removeCustomLoading];
 | 
	
		
			
				|  |  | +                [self startPlay];
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    else {
 | 
	
		
			
				|  |  | +        if (self.mergePlayer.isReady) {
 | 
	
		
			
				|  |  | +            if (self.needShowGuide) {
 | 
	
		
			
				|  |  | +                [self configGuideView];
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else {
 | 
	
		
			
				|  |  | +                [LOADING_MANAGER removeCustomLoading];
 | 
	
		
			
				|  |  | +                [self startPlay];
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#pragma mark ------- 功能引导
 | 
	
		
			
				|  |  | +- (void)configGuideView {
 | 
	
		
			
				|  |  | +    [self.guideManager clearAllGuideModel];
 | 
	
		
			
				|  |  | +    UIWindow *window = [NSObject getKeyWindow];
 | 
	
		
			
				|  |  | +    NSInteger totalCount = 7;
 | 
	
		
			
				|  |  | +    if (self.contrlView.hideBackView) {
 | 
	
		
			
				|  |  | +        totalCount = 6;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    NSInteger currentIndex = 0;
 | 
	
		
			
				|  |  | +    // 音量引导
 | 
	
		
			
				|  |  | +    CGRect volumeGuideFrame = [self.contrlView.volumeGuideBg convertRect:self.contrlView.volumeGuideBg.bounds toView:window];
 | 
	
		
			
				|  |  | +    CGRect volumeImageFrame = CGRectMake(CGRectGetMinX(volumeGuideFrame) - 270 - 8, CGRectGetMinY(volumeGuideFrame) + 10, 270, 161);
 | 
	
		
			
				|  |  | +    CGRect volumeButtonFrame = CGRectMake(CGRectGetMinX(volumeImageFrame) + 16, CGRectGetMaxY(volumeImageFrame) + 17, 100, 33);
 | 
	
		
			
				|  |  | +    KSBaseGuideModel *volumeGuideModel = [self createGuideModelWithDisplayImage:@"merge_guide_volume" guideViewFrame:volumeGuideFrame imageFrame:volumeImageFrame buttonFrame:volumeButtonFrame currentIndex:currentIndex totalCount:totalCount];
 | 
	
		
			
				|  |  | +    [self.guideManager addGuideModel:volumeGuideModel];
 | 
	
		
			
				|  |  | +    currentIndex++;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    // 演奏后移
 | 
	
		
			
				|  |  | +    CGRect delayGuideFrame = [self.contrlView.delayGuideBg convertRect:self.contrlView.delayGuideBg.bounds toView:window];
 | 
	
		
			
				|  |  | +    CGRect delayImageFrame = CGRectMake(CGRectGetMinX(delayGuideFrame) - 270 - 5, CGRectGetMidY(delayGuideFrame) - 207, 270, 207);
 | 
	
		
			
				|  |  | +    CGRect delaybuttonFrame = CGRectMake(CGRectGetMinX(delayImageFrame) + 16, CGRectGetMaxY(delayImageFrame) - 33 + 5, 100, 33);
 | 
	
		
			
				|  |  | +    KSBaseGuideModel *delayGuideModel = [self createGuideModelWithDisplayImage:@"merge_guide_delay" guideViewFrame:delayGuideFrame imageFrame:delayImageFrame buttonFrame:delaybuttonFrame currentIndex:currentIndex totalCount:totalCount];
 | 
	
		
			
				|  |  | +    [self.guideManager addGuideModel:delayGuideModel];
 | 
	
		
			
				|  |  | +    currentIndex++;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    // 演奏提前
 | 
	
		
			
				|  |  | +    CGRect forwardGuideFrame = [self.contrlView.forwardGuideBg convertRect:self.contrlView.forwardGuideBg.bounds toView:window];
 | 
	
		
			
				|  |  | +    CGRect forwardImageFrame = CGRectMake(CGRectGetMinX(forwardGuideFrame) - 270 - 5, CGRectGetMidY(forwardGuideFrame) - 209, 270, 209);
 | 
	
		
			
				|  |  | +    CGRect forwardbuttonFrame = CGRectMake(CGRectGetMinX(forwardImageFrame) + 16, CGRectGetMaxY(forwardImageFrame) - 33 + 5, 100, 33);
 | 
	
		
			
				|  |  | +    KSBaseGuideModel *forwardGuideModel = [self createGuideModelWithDisplayImage:@"merge_guide_forward" guideViewFrame:forwardGuideFrame imageFrame:forwardImageFrame buttonFrame:forwardbuttonFrame currentIndex:currentIndex totalCount:totalCount];
 | 
	
		
			
				|  |  | +    [self.guideManager addGuideModel:forwardGuideModel];
 | 
	
		
			
				|  |  | +    currentIndex++;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    // 对齐slider调整
 | 
	
		
			
				|  |  | +    CGRect offsetGuideFrame = [self.contrlView.offsetSliderBg convertRect:self.contrlView.offsetSliderBg.bounds toView:window];
 | 
	
		
			
				|  |  | +    CGRect offsetImageFrame = CGRectMake(CGRectGetMinX(offsetGuideFrame) - 270 - 5, CGRectGetMidY(offsetGuideFrame) - 206, 270, 206);
 | 
	
		
			
				|  |  | +    CGRect offsetbuttonFrame = CGRectMake(CGRectGetMinX(offsetImageFrame) + 16, CGRectGetMaxY(offsetImageFrame) - 33 + 5, 100, 33);
 | 
	
		
			
				|  |  | +    KSBaseGuideModel *offsetGuideModel = [self createGuideModelWithDisplayImage:@"merge_guide_offset" guideViewFrame:offsetGuideFrame imageFrame:offsetImageFrame buttonFrame:offsetbuttonFrame currentIndex:currentIndex totalCount:totalCount];
 | 
	
		
			
				|  |  | +    [self.guideManager addGuideModel:offsetGuideModel];
 | 
	
		
			
				|  |  | +    currentIndex++;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    // 重新录制
 | 
	
		
			
				|  |  | +    if (self.contrlView.hideBackView == NO) {
 | 
	
		
			
				|  |  | +        CGRect retryGuideFrame = [self.contrlView.retryGuideBg convertRect:self.contrlView.retryGuideBg.bounds toView:window];
 | 
	
		
			
				|  |  | +        CGRect retryImageFrame = CGRectMake(CGRectGetMidX(retryGuideFrame) - 260, CGRectGetMinY(retryGuideFrame) - 228 - 5, 260, 228);
 | 
	
		
			
				|  |  | +        CGRect retrybuttonFrame = CGRectMake(CGRectGetMinX(retryImageFrame) + 16, CGRectGetMaxY(retryImageFrame) - 33 - 15, 100, 33);
 | 
	
		
			
				|  |  | +        KSBaseGuideModel *retryGuideModel = [self createGuideModelWithDisplayImage:@"merge_guide_retry" guideViewFrame:retryGuideFrame imageFrame:retryImageFrame buttonFrame:retrybuttonFrame currentIndex:currentIndex totalCount:totalCount];
 | 
	
		
			
				|  |  | +        [self.guideManager addGuideModel:retryGuideModel];
 | 
	
		
			
				|  |  | +        currentIndex++;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    // 发布作品
 | 
	
		
			
				|  |  | +    CGRect publishGuideFrame = [self.contrlView.publishGuideBg convertRect:self.contrlView.publishGuideBg.bounds toView:window];
 | 
	
		
			
				|  |  | +    CGRect publishImageFrame = CGRectMake(CGRectGetMidX(publishGuideFrame) - 270 - 5, CGRectGetMinY(publishGuideFrame) - 227 - 5, 270, 227);
 | 
	
		
			
				|  |  | +    CGRect publishbuttonFrame = CGRectMake(CGRectGetMinX(publishImageFrame) + 16, CGRectGetMaxY(publishImageFrame) - 33 - 15, 100, 33);
 | 
	
		
			
				|  |  | +    KSBaseGuideModel *publishGuideModel = [self createGuideModelWithDisplayImage:@"merge_guide_publish" guideViewFrame:publishGuideFrame imageFrame:publishImageFrame buttonFrame:publishbuttonFrame currentIndex:currentIndex totalCount:totalCount];
 | 
	
		
			
				|  |  | +    [self.guideManager addGuideModel:publishGuideModel];
 | 
	
		
			
				|  |  | +    currentIndex++;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    // 保存草稿
 | 
	
		
			
				|  |  | +    CGRect draftGuideFrame = [self.contrlView.saveGuideBg convertRect:self.contrlView.saveGuideBg.bounds toView:window];
 | 
	
		
			
				|  |  | +    CGRect draftImageFrame = CGRectMake(CGRectGetMidX(draftGuideFrame) - 260, CGRectGetMinY(draftGuideFrame) - 246 - 5, 260, 246);
 | 
	
		
			
				|  |  | +    CGRect draftButtonFrame = CGRectMake(CGRectGetMinX(draftImageFrame) + 16, CGRectGetMaxY(draftImageFrame) - 33 - 15, 82, 33);
 | 
	
		
			
				|  |  | +    KSBaseGuideModel *draftGuideModel = [self createGuideModelWithDisplayImage:@"merge_guide_saveDraft" guideViewFrame:draftGuideFrame imageFrame:draftImageFrame buttonFrame:draftButtonFrame currentIndex:currentIndex totalCount:totalCount];
 | 
	
		
			
				|  |  | +    [self.guideManager addGuideModel:draftGuideModel];
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    [LOADING_MANAGER removeCustomLoading];
 | 
	
		
			
				|  |  | +    [self.guideManager beginGuide];
 | 
	
		
			
				|  |  | +    self.needShowGuide = NO;
 | 
	
		
			
				|  |  | +    UserDefaultSetBoolForKey(YES, MERGE_GUIDEKEY);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +- (KSBaseGuideModel *)createGuideModelWithDisplayImage:(NSString *)guideImage guideViewFrame:(CGRect)guideViewFrame imageFrame:(CGRect)imageFrame buttonFrame:(CGRect)buttonFrame currentIndex:(NSInteger)currentIndex totalCount:(NSInteger)totalCount {
 | 
	
		
			
				|  |  | +    KSBaseGuideModel *model = [[KSBaseGuideModel alloc] init];
 | 
	
		
			
				|  |  | +    model.displayImageName = guideImage;
 | 
	
		
			
				|  |  | +    model.currentIndex = currentIndex;
 | 
	
		
			
				|  |  | +    model.totalIndex = totalCount;
 | 
	
		
			
				|  |  | +    model.guideViewFrame = guideViewFrame;
 | 
	
		
			
				|  |  | +    model.buttonFrame = buttonFrame;
 | 
	
		
			
				|  |  | +    model.imageFrame = imageFrame;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    return model;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +- (KSBaseGuideManager *)guideManager {
 | 
	
		
			
				|  |  | +    if (!_guideManager) {
 | 
	
		
			
				|  |  | +        _guideManager = [[KSBaseGuideManager alloc] init];
 | 
	
		
			
				|  |  | +        [_guideManager configskipButtonImage:@"merge_guide_skip" nextButtonImage:@"merge_guide_nextBg" replayButtonImage:@"merge_guide_retryBg" finishButtonImage:@"merge_guide_finishBg"];
 | 
	
		
			
				|  |  | +        MJWeakSelf;
 | 
	
		
			
				|  |  | +        [_guideManager GuideFinish:^{
 | 
	
		
			
				|  |  | +            [weakSelf guideFinishAction];
 | 
	
		
			
				|  |  | +        }];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return _guideManager;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +- (void)guideFinishAction {
 | 
	
		
			
				|  |  | +    [self startPlay];
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  /*
 | 
	
		
			
				|  |  |  // Only override drawRect: if you perform custom drawing.
 | 
	
		
			
				|  |  |  // An empty implementation adversely affects performance during animation.
 |