Add media service implementation for iOS

This commit is contained in:
Chinmay Garde
2015-08-24 12:36:15 -07:00
parent 1646afe3c2
commit bd80be7e2f
8 changed files with 298 additions and 4 deletions
+6 -1
View File
@@ -145,7 +145,12 @@ template("ios_app") {
bin_gen_target_name = target_name + "_bin"
executable(bin_gen_target_name) {
libs = [ "UIKit.framework", "QuartzCore.framework", "OpenGLES.framework" ]
libs = [
"UIKit.framework",
"AVFoundation.framework",
"QuartzCore.framework",
"OpenGLES.framework"
]
deps = invoker.deps
output_name = app_name
}
+17 -3
View File
@@ -5,13 +5,11 @@
import("//mojo/public/tools/bindings/mojom.gni")
group("media") {
testonly = true
deps = [
":interfaces",
]
if (is_android) {
if (is_android || is_ios) {
deps += [ ":media_lib" ]
}
}
@@ -40,4 +38,20 @@ if (is_android) {
":interfaces_java",
]
}
} else if (is_ios) {
source_set("media_lib") {
sources = [
"ios/media_player_impl.h",
"ios/media_player_impl.mm",
"ios/media_service_impl.h",
"ios/media_service_impl.mm",
]
deps = [
":interfaces",
"//base:base",
"//mojo/common",
"//mojo/public/cpp/application",
]
}
}
@@ -0,0 +1,54 @@
// 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.
#ifndef SKY_SERVICES_MEDIA_IOS_MEDIA_PLAYER_IMPL_H_
#define SKY_SERVICES_MEDIA_IOS_MEDIA_PLAYER_IMPL_H_
#include "base/macros.h"
#include "mojo/public/cpp/application/interface_factory.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "sky/services/media/media.mojom.h"
#if __OBJC__
@class AudioClient;
#else // __OBJC__
class AudioClient;
#endif // __OBJC__
namespace sky {
namespace services {
namespace media {
class MediaPlayerImpl : public ::media::MediaPlayer {
public:
explicit MediaPlayerImpl(
mojo::InterfaceRequest<::media::MediaPlayer> request);
~MediaPlayerImpl() override;
void Prepare(mojo::ScopedDataPipeConsumerHandle data_source,
const ::media::MediaPlayer::PrepareCallback& callback) override;
void Start() override;
void Pause() override;
void SeekTo(uint32_t msec) override;
private:
mojo::StrongBinding<::media::MediaPlayer> binding_;
AudioClient* audio_client_;
void reset();
DISALLOW_COPY_AND_ASSIGN(MediaPlayerImpl);
};
class MediaPlayerFactory : public mojo::InterfaceFactory<::media::MediaPlayer> {
public:
void Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<::media::MediaPlayer> request) override;
};
} // namespace media
} // namespace services
} // namespace sky
#endif // SKY_SERVICES_MEDIA_IOS_MEDIA_PLAYER_IMPL_H_
+134
View File
@@ -0,0 +1,134 @@
// 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/files/file_path.h"
#include "mojo/common/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* path = reinterpret_cast<char*>(calloc(256, sizeof(char)));
snprintf(path, 256, "%smedia.XXXXXX", NSTemporaryDirectory().UTF8String);
path = mktemp(path);
if (path == NULL) {
free(path);
return NULL;
}
NSString* pathString = [NSString stringWithUTF8String:path];
free(path);
return pathString;
}
- (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);
mojo::common::BlockingCopyToFile(data_source.Pass(), path);
audio_client_ = [[AudioClient alloc] initWithPath:filePath];
callback.Run(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
@@ -0,0 +1,44 @@
// 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.
#ifndef SKY_SERVICES_MEDIA_IOS_MEDIA_SERVICE_IMPL_H_
#define SKY_SERVICES_MEDIA_IOS_MEDIA_SERVICE_IMPL_H_
#include "base/macros.h"
#include "mojo/public/cpp/application/interface_factory.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "sky/services/media/media.mojom.h"
#include "sky/services/media/ios/media_player_impl.h"
namespace sky {
namespace services {
namespace media {
class MediaServiceImpl : public ::media::MediaService {
public:
MediaServiceImpl(mojo::InterfaceRequest<::media::MediaService> request);
~MediaServiceImpl() override;
void CreatePlayer(
mojo::InterfaceRequest<::media::MediaPlayer> player) override;
private:
mojo::StrongBinding<::media::MediaService> binding_;
MediaPlayerFactory media_player_;
DISALLOW_COPY_AND_ASSIGN(MediaServiceImpl);
};
class MediaServiceFactory
: public mojo::InterfaceFactory<::media::MediaService> {
public:
void Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<::media::MediaService> request) override;
};
} // namespace media
} // namespace services
} // namespace sky
#endif // SKY_SERVICES_MEDIA_IOS_MEDIA_SERVICE_IMPL_H_
@@ -0,0 +1,30 @@
// 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 "sky/services/media/ios/media_service_impl.h"
namespace sky {
namespace services {
namespace media {
MediaServiceImpl::MediaServiceImpl(
mojo::InterfaceRequest<::media::MediaService> request)
: binding_(this, request.Pass()) {}
MediaServiceImpl::~MediaServiceImpl() {}
void MediaServiceImpl::CreatePlayer(
mojo::InterfaceRequest<::media::MediaPlayer> player) {
media_player_.Create(nullptr, player.Pass());
}
void MediaServiceFactory::Create(
mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<::media::MediaService> request) {
new MediaServiceImpl(request.Pass());
}
} // namespace media
} // namespace services
} // namespace sky
+1
View File
@@ -212,6 +212,7 @@ if (is_android) {
":common",
"//sky/services/ns_net",
"//sky/services/keyboard",
"//sky/services/media",
]
}
@@ -14,6 +14,8 @@
#if TARGET_OS_IPHONE
#include "sky/services/keyboard/ios/keyboard_service_impl.h"
#include "sky/services/media/ios/media_service_impl.h"
#include "sky/services/media/ios/media_player_impl.h"
#endif
#if !TARGET_OS_IPHONE
@@ -39,6 +41,14 @@ class PlatformServiceProvider : public mojo::ServiceProvider {
keyboard_.Create(nullptr, mojo::MakeRequest<::keyboard::KeyboardService>(
client_handle.Pass()));
}
if (service_name == ::media::MediaPlayer::Name_) {
media_player_.Create(nullptr, mojo::MakeRequest<::media::MediaPlayer>(
client_handle.Pass()));
}
if (service_name == ::media::MediaService::Name_) {
media_service_.Create(nullptr, mojo::MakeRequest<::media::MediaService>(
client_handle.Pass()));
}
#endif
#if !TARGET_OS_IPHONE
if (service_name == TestHarness::Name_) {
@@ -53,6 +63,8 @@ class PlatformServiceProvider : public mojo::ServiceProvider {
mojo::NetworkServiceFactory network_;
#if TARGET_OS_IPHONE
sky::services::keyboard::KeyboardServiceFactory keyboard_;
sky::services::media::MediaPlayerFactory media_player_;
sky::services::media::MediaServiceFactory media_service_;
#endif
};