Chromium Code Reviews| Index: ios/chrome/browser/ui/voice/text_to_speech_player.mm |
| diff --git a/ios/chrome/browser/ui/voice/text_to_speech_player.mm b/ios/chrome/browser/ui/voice/text_to_speech_player.mm |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..184b1b00350c3432a1b9b95a383c4b16d9dd1cd7 |
| --- /dev/null |
| +++ b/ios/chrome/browser/ui/voice/text_to_speech_player.mm |
| @@ -0,0 +1,131 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#import "ios/chrome/browser/ui/voice/text_to_speech_player.h" |
| + |
| +#import <AVFoundation/AVFoundation.h> |
| +#import <UIKit/UIKit.h> |
| + |
| +#import "base/mac/scoped_nsobject.h" |
| +#import "ios/chrome/browser/ui/voice/text_to_speech_player+subclassing.h" |
| +#import "ios/chrome/browser/ui/voice/voice_search_notification_names.h" |
| + |
|
sdefresne
2016/10/25 13:20:30
Should we convert the file to ARC?
rohitrao (ping after 24h)
2016/10/25 15:23:12
I'll leave that to stk to decide =)
|
| +@interface TextToSpeechPlayer ()<AVAudioPlayerDelegate> { |
| + // The audio data to be played. |
| + base::scoped_nsobject<NSData> _audioData; |
| + // The AVAudioPlayer playing TTS audio data. |
| + base::scoped_nsobject<AVAudioPlayer> _player; |
| + // Whether playback has finished. |
| + BOOL _playbackFinished; |
| +} |
| + |
| +// Cancels TTS audio playback, and sends a kTTSDidStopPlayingNotification |
| +// notification if |sendNotification| is YES. |
| +- (void)cancelPlaybackAndSendNotification:(BOOL)sendNotification; |
| + |
| +@end |
| + |
| +@implementation TextToSpeechPlayer |
| + |
| +- (instancetype)init { |
| + if ((self = [super init])) { |
| + SEL handler = @selector(cancelPlayback); |
| + NSString* notificationName = UIApplicationDidEnterBackgroundNotification; |
| + id sender = [UIApplication sharedApplication]; |
| + [[NSNotificationCenter defaultCenter] addObserver:self |
| + selector:handler |
| + name:notificationName |
| + object:sender]; |
| + } |
| + return self; |
| +} |
| + |
| +- (void)dealloc { |
| + [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| + [self cancelPlayback]; |
| + [super dealloc]; |
| +} |
| + |
| +#pragma mark - Accessors |
| + |
| +- (BOOL)isReadyForPlayback { |
| + return [_audioData length] > 0; |
| +} |
| + |
| +- (BOOL)isPlayingAudio { |
| + return [_player isPlaying]; |
| +} |
| + |
| +- (AVAudioPlayer*)player { |
| + return _player; |
| +} |
| + |
| +#pragma mark - Public |
| + |
| +- (void)prepareToPlayAudioData:(NSData*)audioData { |
| + if (self.playingAudio) |
| + [self cancelPlayback]; |
| + _audioData.reset([audioData retain]); |
| + [[NSNotificationCenter defaultCenter] |
| + postNotificationName:kTTSAudioReadyForPlaybackNotification |
| + object:self]; |
| +} |
| + |
| +- (void)beginPlayback { |
| + // no-op when audio is already playing. |
| + if (self.playingAudio || !self.readyForPlayback) |
| + return; |
| + // Create the AVAudioPlayer and initiate playback. |
| + _player.reset([[AVAudioPlayer alloc] initWithData:_audioData error:nil]); |
| + [_player setMeteringEnabled:YES]; |
| + [_player setDelegate:self]; |
| + [_player setNumberOfLoops:0]; |
| + [_player setVolume:1.0]; |
| + if ([_player prepareToPlay] && [_player play]) { |
| + [[NSNotificationCenter defaultCenter] |
| + postNotificationName:kTTSWillStartPlayingNotification |
| + object:self]; |
| + } else { |
| + _player.reset(); |
| + } |
| +} |
| + |
| +- (void)cancelPlayback { |
| + [self cancelPlaybackAndSendNotification:[_player isPlaying]]; |
| +} |
| + |
| +#pragma mark - AVAudioPlayerDelegate |
| + |
| +- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer*)player |
| + error:(NSError*)error { |
| + [self cancelPlayback]; |
| +} |
| + |
| +- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer*)player |
| + successfully:(BOOL)flag { |
| + [self cancelPlaybackAndSendNotification:flag]; |
| +} |
| + |
| +- (void)audioPlayerBeginInterruption:(AVAudioPlayer*)player { |
| + [self cancelPlayback]; |
| +} |
| + |
| +#pragma mark - |
| + |
| +- (void)cancelPlaybackAndSendNotification:(BOOL)sendNotification { |
| + if (_playbackFinished) |
| + return; |
| + _playbackFinished = YES; |
| + [_player stop]; |
| + _audioData.reset(); |
| + [_player setDelegate:nil]; |
| + _player.reset(); |
| + if (sendNotification) { |
| + [[NSNotificationCenter defaultCenter] |
| + postNotificationName:kTTSDidStopPlayingNotification |
| + object:self]; |
| + } |
| +} |
| + |
| +@end |