audio player (for mac)

Change-Id: I491df748d22dfa566000c265a61f62f81755e5a0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/309792
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2020-08-13 09:14:24 -04:00 committed by Skia Commit-Bot
parent 984d49667a
commit 8a8be22597
7 changed files with 319 additions and 0 deletions

View File

@ -459,6 +459,7 @@ optional("fontmgr_mac_ct") {
# AppKit symbols NSFontWeightXXX may be dlsym'ed.
"AppKit.framework",
"ApplicationServices.framework",
"AVFoundation.framework",
]
}
@ -2500,6 +2501,7 @@ if (skia_enable_tools) {
test_app("viewer") {
is_shared_library = is_android
sources = [
"src/ports/SkAudioPlayer.cpp",
"tools/viewer/AnimTimer.h",
"tools/viewer/BisectSlide.cpp",
"tools/viewer/GMSlide.cpp",
@ -2552,6 +2554,11 @@ if (skia_enable_tools) {
"//third_party/spirv-tools:spvtools_val",
]
}
if (is_mac) {
sources += [ "src/ports/SkAudioPlayer_mac.mm" ]
} else {
sources += [ "src/ports/SkAudioPlayer_none.cpp" ]
}
}
}

View File

@ -22,6 +22,7 @@ samples_sources = [
"$_samplecode/SampleAnimatedText.cpp",
"$_samplecode/SampleArc.cpp",
"$_samplecode/SampleAtlas.cpp",
"$_samplecode/SampleAudio.cpp",
"$_samplecode/SampleBackdropBounds.cpp",
"$_samplecode/SampleBitmapRect.cpp",
"$_samplecode/SampleCamera.cpp",

View File

@ -0,0 +1,63 @@
/*
* Copyright 2020 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#pragma once
#include "include/core/SkData.h"
#include <memory>
class SK_API SkAudioPlayer {
public:
virtual ~SkAudioPlayer();
// Returns null on failure (possibly unknown format?)
static std::unique_ptr<SkAudioPlayer> Make(sk_sp<SkData>);
// in seconds
double duration() const { return this->onGetDuration(); }
double time() const { return this->onGetTime(); } // 0...duration()
double setTime(double); // returns actual time
double normalizedTime() const { return this->time() / this->duration(); }
double setNormalizedTime(double t);
enum class State {
kPlaying,
kStopped,
kPaused,
};
State state() const { return fState; }
float volume() const { return fVolume; } // 0...1
float rate() const { return fRate; } // multiplier (e.g. 1.0 is default)
State setState(State); // returns actual State
float setRate(float); // returns actual rate
float setVolume(float); // returns actual volume
void play() { this->setState(State::kPlaying); }
void pause() { this->setState(State::kPaused); }
void stop() { this->setState(State::kStopped); }
bool isPlaying() const { return this->state() == State::kPlaying; }
bool isPaused() const { return this->state() == State::kPaused; }
bool isStopped() const { return this->state() == State::kStopped; }
protected:
SkAudioPlayer() {} // only called by subclasses
virtual double onGetDuration() const = 0;
virtual double onGetTime() const = 0;
virtual double onSetTime(double) = 0;
virtual State onSetState(State) = 0;
virtual float onSetRate(float) = 0;
virtual float onSetVolume(float) = 0;
private:
State fState = State::kStopped;
float fRate = 1.0f;
float fVolume = 1.0f;
};

View File

@ -0,0 +1,95 @@
/*
* Copyright 2020 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkCanvas.h"
#include "include/core/SkData.h"
#include "include/ports/SkAudioPlayer.h"
#include "samplecode/Sample.h"
#include "src/core/SkUtils.h"
#include "tools/Resources.h"
class AudioView : public Sample {
std::unique_ptr<SkAudioPlayer> fPlayer;
SkRect fBar;
public:
AudioView() {}
protected:
SkString name() override { return SkString("Audio"); }
void onOnceBeforeDraw() override {
auto data = SkData::MakeFromFileName("/Users/reed/skia/mp3/scott-joplin-peacherine-rag.mp3");
if (data) {
fPlayer = SkAudioPlayer::Make(data);
SkDebugf("make: dur:%g time%g state:%d",
fPlayer->duration(),
fPlayer->time(),
fPlayer->state());
}
fBar = { 10, 10, 510, 30 };
}
void onDrawContent(SkCanvas* canvas) override {
if (!fPlayer) {
return;
}
SkPaint p;
p.setColor(0xFFCCCCCC);
canvas->drawRect(fBar, p);
p.setColor(fPlayer->isPlaying() ? SK_ColorBLUE : 0xFF8888FF);
SkRect r = fBar;
r.fRight = r.fLeft + (float)fPlayer->normalizedTime() * r.width();
canvas->drawRect(r, p);
}
bool onChar(SkUnichar c) override {
if (c == ' ') {
switch (fPlayer->state()) {
case SkAudioPlayer::State::kPlaying: fPlayer->pause(); break;
case SkAudioPlayer::State::kPaused: fPlayer->play(); break;
case SkAudioPlayer::State::kStopped: fPlayer->play(); break;
}
return true;
}
return this->INHERITED::onChar(c);
}
Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) override {
if (fPlayer && fBar.contains(x, y)) {
bool wasPlaying = fPlayer->isPlaying();
if (wasPlaying) {
fPlayer->pause();
}
return new Click([this, wasPlaying](Click* click) {
if (fBar.contains(click->fCurr.fX, click->fCurr.fY)) {
fPlayer->setNormalizedTime((click->fCurr.fX - fBar.fLeft) / fBar.width());
}
if (click->fState == skui::InputState::kUp) {
if (wasPlaying) {
fPlayer->play();
}
}
return true;
});
}
return nullptr;
}
bool onAnimate(double /*nanos*/) override {
return true;
}
private:
typedef Sample INHERITED;
};
DEF_SAMPLE( return new AudioView; )

View File

@ -0,0 +1,57 @@
/*
* Copyright 2020 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/ports/SkAudioPlayer.h"
#include <algorithm>
#include <cmath>
SkAudioPlayer::~SkAudioPlayer() {}
double SkAudioPlayer::setTime(double t) {
t = std::min(std::max(t, 0.0), this->duration());
if (!std::isfinite(t)) {
t = this->time();
}
if (t != this->time()) {
t = this->onSetTime(t);
}
return t;
}
double SkAudioPlayer::setNormalizedTime(double t) {
this->setTime(t * this->duration());
return this->normalizedTime();
}
SkAudioPlayer::State SkAudioPlayer::setState(State s) {
if (s != fState) {
fState = this->onSetState(s);
}
return fState;
}
float SkAudioPlayer::setRate(float r) {
r = std::min(std::max(r, 0.f), 1.f);
if (!std::isfinite(r)) {
r = fRate;
}
if (r != fRate) {
fRate = this->onSetRate(r);
}
return fRate;
}
float SkAudioPlayer::setVolume(float v) {
v = std::min(std::max(v, 0.f), 1.f);
if (!std::isfinite(v)) {
v = fVolume;
}
if (v != fVolume) {
fVolume = this->onSetVolume(v);
}
return fVolume;
}

View File

@ -0,0 +1,83 @@
/*
* Copyright 2020 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkData.h"
#include "include/ports/SkAudioPlayer.h"
#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
#ifdef SK_BUILD_FOR_MAC
#include <AVFoundation/AVFoundation.h>
#endif
#ifdef SK_BUILD_FOR_IOS
// ???
#endif
class SkAudioPlayer_Mac : public SkAudioPlayer {
public:
SkAudioPlayer_Mac(AVAudioPlayer* player, sk_sp<SkData> data)
: fPlayer(player)
, fData(std::move(data))
{
fPlayer.enableRate = YES;
[fPlayer prepareToPlay];
}
~SkAudioPlayer_Mac() override {
// [fPlayer release];
}
double onGetDuration() const override { return [fPlayer duration]; }
double onGetTime() const override { return fPlayer.currentTime; }
double onSetTime(double t) override {
bool wasPlaying = this->isPlaying();
if (wasPlaying) {
[fPlayer pause];
}
fPlayer.currentTime = t;
if (wasPlaying) {
[fPlayer play];
}
return fPlayer.currentTime;
}
State onSetState(State state) override {
switch (state) {
case State::kPlaying: [fPlayer play]; break;
case State::kStopped: [fPlayer stop]; break;
case State::kPaused: [fPlayer pause]; break;
}
return state;
}
float onSetRate(float r) override { fPlayer.rate = r; return r; }
float onSetVolume(float v) override { fPlayer.volume = v; return v; }
private:
AVAudioPlayer* fPlayer;
sk_sp<SkData> fData; // we hold this onbehalf of the player's NSData
};
std::unique_ptr<SkAudioPlayer> SkAudioPlayer::Make(sk_sp<SkData> src) {
// The NSData does not own the actual buffer (src), but our subclass will
NSData* data = [[NSData alloc] initWithBytesNoCopy:(void*)src->data() length:src->size()];
AVAudioPlayer* player = [[AVAudioPlayer alloc] initWithData:data error:nil];
[data release];
if (player) {
return std::unique_ptr<SkAudioPlayer>(new SkAudioPlayer_Mac(player, std::move(src)));
}
return nullptr;
}
#endif

View File

@ -0,0 +1,13 @@
/*
* Copyright 2020 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkData.h"
#include "include/ports/SkAudioPlayer.h"
std::unique_ptr<SkAudioPlayer> SkAudioPlayer::Make(sk_sp<SkData> src) {
return nullptr;
}