blob: 0250a93e4361e90b7f918aff2648a1693f594842 [file] [log] [blame]
// Copyright 2015 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.
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "mojo/data_pipe_utils/data_pipe_utils.h"
#include "sky/services/media/ios/media_player_impl.h"
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
@interface AudioClient : NSObject
- (instancetype)initWithPath:(NSString*)path;
- (BOOL)play;
- (void)pause;
- (BOOL)seekTo:(NSTimeInterval)interval;
+ (NSString*)temporaryFilePath;
@end
@implementation AudioClient {
AVAudioPlayer* _player;
}
- (instancetype)initWithPath:(NSString*)path {
self = [super init];
if (self) {
NSError* error = nil;
_player =
[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:path]
error:&error];
if (error != nil) {
NSLog(@"Could not initialize audio client: %@",
error.localizedDescription);
[self release];
return nil;
}
}
return self;
}
- (BOOL)play {
return [_player play];
}
- (void)pause {
[_player pause];
}
- (BOOL)seekTo:(NSTimeInterval)interval {
return [_player playAtTime:_player.deviceCurrentTime + interval];
}
+ (NSString*)temporaryFilePath {
char temp[256] = {0};
snprintf(temp, sizeof(temp), "%smedia.XXXXXX", NSTemporaryDirectory().UTF8String);
char *path = mktemp(temp);
if (path == NULL) {
return NULL;
}
return [NSString stringWithUTF8String:path];
}
- (void)dealloc {
[_player release];
[super dealloc];
}
@end
namespace sky {
namespace services {
namespace media {
MediaPlayerImpl::MediaPlayerImpl(
mojo::InterfaceRequest<::media::MediaPlayer> request)
: binding_(this, request.Pass()), audio_client_(nullptr) {}
MediaPlayerImpl::~MediaPlayerImpl() {
reset();
}
void MediaPlayerImpl::Prepare(
mojo::ScopedDataPipeConsumerHandle data_source,
const ::media::MediaPlayer::PrepareCallback& callback) {
reset();
NSString* filePath = [AudioClient temporaryFilePath];
base::FilePath path(filePath.UTF8String);
auto taskRunner = base::MessageLoop::current()->task_runner().get();
auto copyCallback = base::Bind(&MediaPlayerImpl::onCopyToTemp,
base::Unretained(this), callback, path);
mojo::common::CopyToFile(data_source.Pass(), path, taskRunner, copyCallback);
}
void MediaPlayerImpl::onCopyToTemp(
const ::media::MediaPlayer::PrepareCallback& callback,
base::FilePath path,
bool success) {
if (success) {
NSString* filePath =
[NSString stringWithUTF8String:path.AsUTF8Unsafe().c_str()];
audio_client_ = [[AudioClient alloc] initWithPath:filePath];
} else {
reset();
}
callback.Run(success && audio_client_ != nullptr);
}
void MediaPlayerImpl::Start() {
[audio_client_ play];
}
void MediaPlayerImpl::Pause() {
[audio_client_ pause];
}
void MediaPlayerImpl::SeekTo(uint32_t msec) {
[audio_client_ seekTo:msec * 1e-3];
}
void MediaPlayerImpl::reset() {
[audio_client_ release];
audio_client_ = nullptr;
}
void MediaPlayerFactory::Create(
mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<::media::MediaPlayer> request) {
new MediaPlayerImpl(request.Pass());
}
} // namespace media
} // namespace services
} // namespace sky