| 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"
|
| +
|
| +@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
|
|
|