Initial check-in of variable speed playback library.

Contains an implementation of time-domain audio scaler, for
pitch-invariant speed up and slow-down of audio.

Contains wrapper library using OpenSLES to pump audio from
encoded stream (mp3 file etc) through audio decoder then
through time scaler and out to media player.

This is written as a jni library with jni hooks to allow
driving of this from the Java side.

The other part of this cl is the Java wrapper.  There is a
new interface MediaPlayerProxy, containing a subset of the
methods found on the MediaPlayer.  The VariableSpeed class
provides a concrete implementation of this interface
adapting to the jni code.

Change-Id: I518d8bf703488628c00730241a08ebfb67588ca6
diff --git a/variablespeed/jni/jni_entry.cc b/variablespeed/jni/jni_entry.cc
new file mode 100644
index 0000000..d751b09
--- /dev/null
+++ b/variablespeed/jni/jni_entry.cc
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include <jni.h>
+#include <variablespeed.h>
+
+// Quick #define to make sure I get all the JNI method calls right.
+#define JNI_METHOD(x, y) \
+JNIEXPORT y JNICALL \
+Java_com_android_ex_variablespeed_VariableSpeedNative_##x
+
+class MethodLog {
+ public:
+  explicit MethodLog(const char* name) : name_(name) {
+    LOGD("+ %s", name);
+  }
+  virtual ~MethodLog() {
+    LOGD("- %s", name_);
+  }
+
+ private:
+  const char* name_;
+};
+
+extern "C" {
+JNI_METHOD(playFileDescriptor, void) (JNIEnv*, jclass, int fd, jlong offset,
+    jlong length) {
+  MethodLog _("playFileDescriptor");
+  AudioEngine::GetEngine()->PlayFileDescriptor(fd, offset, length);
+}
+
+JNI_METHOD(playUri, void) (JNIEnv* env, jclass, jstring uri) {
+  MethodLog _("playUri");
+  const char* utf8 = env->GetStringUTFChars(uri, NULL);
+  CHECK(NULL != utf8);
+  AudioEngine::GetEngine()->PlayUri(utf8);
+}
+
+JNI_METHOD(setVariableSpeed, void) (JNIEnv*, jclass, float speed) {
+  MethodLog _("setVariableSpeed");
+  AudioEngine::GetEngine()->SetVariableSpeed(speed);
+}
+
+JNI_METHOD(startPlayback, void) (JNIEnv*, jclass) {
+  MethodLog _("startPlayback");
+  AudioEngine::GetEngine()->RequestStart();
+}
+
+JNI_METHOD(stopPlayback, void) (JNIEnv*, jclass) {
+  MethodLog _("stopPlayback");
+  AudioEngine::GetEngine()->RequestStop();
+}
+
+JNI_METHOD(getCurrentPosition, int) (JNIEnv*, jclass) {
+  MethodLog _("getCurrentPosition");
+  return AudioEngine::GetEngine()->GetCurrentPosition();
+}
+
+JNI_METHOD(getTotalDuration, int) (JNIEnv*, jclass) {
+  MethodLog _("getTotalDuration");
+  return AudioEngine::GetEngine()->GetTotalDuration();
+}
+
+JNI_METHOD(initializeEngine, void) (JNIEnv*, jclass, int channels,
+    int sampleRate, int targetFrames, float windowDuration,
+    float windowOverlapDuration, size_t maxPlayBufferCount,
+    float initialRate, size_t decodeInitialSize, size_t decodeMaxSize,
+    size_t startPositionMillis) {
+  MethodLog _("initializeEngine");
+  AudioEngine::SetEngine(new AudioEngine(channels, sampleRate, targetFrames,
+      windowDuration, windowOverlapDuration, maxPlayBufferCount, initialRate,
+      decodeInitialSize, decodeMaxSize, startPositionMillis));
+}
+
+JNI_METHOD(shutdownEngine, void) (JNIEnv*, jclass) {
+  MethodLog _("shutdownEngine");
+  AudioEngine::DeleteEngine();
+}
+}  // extern "C"