Use callbacks for Midi I/O

Instead of having the Sonivox engine directly open the file and
use stdio to read from it, use caller-provided callbacks.

Change-Id: Ie55129109060a4a7862fee3177f994401e00b6c1
diff --git a/include/media/JetPlayer.h b/include/media/JetPlayer.h
index 388f767..63d1980 100644
--- a/include/media/JetPlayer.h
+++ b/include/media/JetPlayer.h
@@ -22,6 +22,7 @@
 #include <libsonivox/jet.h>
 #include <libsonivox/eas_types.h>
 #include <media/AudioTrack.h>
+#include <media/MidiIoWrapper.h>
 
 
 namespace android {
@@ -86,15 +87,13 @@
 
     int                 mMaxTracks; // max number of MIDI tracks, usually 32
     EAS_DATA_HANDLE     mEasData;
-    EAS_FILE_LOCATOR    mEasJetFileLoc;
+    sp<MidiIoWrapper>   mIoWrapper;
     EAS_PCM*            mAudioBuffer;// EAS renders the MIDI data into this buffer,
     sp<AudioTrack>      mAudioTrack; // and we play it in this audio track
     int                 mTrackBufferSize;
     S_JET_STATUS        mJetStatus;
     S_JET_STATUS        mPreviousJetStatus;
 
-    char                mJetFilePath[PATH_MAX];
-
     class JetPlayerThread : public Thread {
     public:
         JetPlayerThread(JetPlayer *player) : mPlayer(player) {
diff --git a/include/media/MidiIoWrapper.h b/include/media/MidiIoWrapper.h
new file mode 100644
index 0000000..caf1d75
--- /dev/null
+++ b/include/media/MidiIoWrapper.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef MIDI_IO_WRAPPER_H_
+#define MIDI_IO_WRAPPER_H_
+
+#include <libsonivox/eas_types.h>
+
+namespace android {
+
+class MidiIoWrapper : public RefBase {
+public:
+    MidiIoWrapper(const char *path);
+    MidiIoWrapper(int fd, off64_t offset, int64_t size);
+
+    ~MidiIoWrapper();
+
+    int readAt(void *buffer, int offset, int size);
+    int size();
+
+    EAS_FILE_LOCATOR getLocator();
+
+private:
+    int mFd;
+    off64_t mBase;
+    int64_t  mLength;
+    EAS_FILE mEasFile;
+};
+
+
+}  // namespace android
+
+#endif // MIDI_IO_WRAPPER_H_
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index ac770f1..df6eb57 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -42,6 +42,7 @@
     mediarecorder.cpp \
     IMediaMetadataRetriever.cpp \
     mediametadataretriever.cpp \
+    MidiIoWrapper.cpp \
     ToneGenerator.cpp \
     JetPlayer.cpp \
     IOMX.cpp \
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
index f0f1832..721d8d7 100644
--- a/media/libmedia/JetPlayer.cpp
+++ b/media/libmedia/JetPlayer.cpp
@@ -36,7 +36,6 @@
         mPaused(false),
         mMaxTracks(maxTracks),
         mEasData(NULL),
-        mEasJetFileLoc(NULL),
         mTrackBufferSize(trackBufferSize)
 {
     ALOGV("JetPlayer constructor");
@@ -133,10 +132,7 @@
         JET_Shutdown(mEasData);
         EAS_Shutdown(mEasData);
     }
-    if (mEasJetFileLoc) {
-        free(mEasJetFileLoc);
-        mEasJetFileLoc = NULL;
-    }
+    mIoWrapper.clear();
     if (mAudioTrack != 0) {
         mAudioTrack->stop();
         mAudioTrack->flush();
@@ -327,16 +323,9 @@
 
     Mutex::Autolock lock(mMutex);
 
-    mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE));
-    strncpy(mJetFilePath, path, sizeof(mJetFilePath));
-    mJetFilePath[sizeof(mJetFilePath) - 1] = '\0';
-    mEasJetFileLoc->path = mJetFilePath;
+    mIoWrapper = new MidiIoWrapper(path);
 
-    mEasJetFileLoc->fd = 0;
-    mEasJetFileLoc->length = 0;
-    mEasJetFileLoc->offset = 0;
-
-    EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc);
+    EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
     if (result != EAS_SUCCESS)
         mState = EAS_STATE_ERROR;
     else
@@ -352,13 +341,9 @@
 
     Mutex::Autolock lock(mMutex);
 
-    mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE));
-    mEasJetFileLoc->fd = fd;
-    mEasJetFileLoc->offset = offset;
-    mEasJetFileLoc->length = length;
-    mEasJetFileLoc->path = NULL;
+    mIoWrapper = new MidiIoWrapper(fd, offset, length);
 
-    EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc);
+    EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
     if (result != EAS_SUCCESS)
         mState = EAS_STATE_ERROR;
     else
@@ -459,7 +444,6 @@
 //-------------------------------------------------------------------------------------------------
 void JetPlayer::dump()
 {
-    ALOGE("JetPlayer dump: JET file=%s", mEasJetFileLoc->path);
 }
 
 void JetPlayer::dumpJetStatus(S_JET_STATUS* pJetStatus)
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
new file mode 100644
index 0000000..ef931d2
--- /dev/null
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MidiIoWrapper"
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "media/MidiIoWrapper.h"
+
+static int readAt(void *handle, void *buffer, int pos, int size) {
+    return ((android::MidiIoWrapper*)handle)->readAt(buffer, pos, size);
+}
+static int size(void *handle) {
+    return ((android::MidiIoWrapper*)handle)->size();
+}
+
+namespace android {
+
+MidiIoWrapper::MidiIoWrapper(const char *path) {
+    ALOGV("MidiIoWrapper(%s)", path);
+    mFd = open(path, O_RDONLY | O_LARGEFILE);
+    mBase = 0;
+    mLength = lseek(mFd, 0, SEEK_END);
+}
+
+MidiIoWrapper::MidiIoWrapper(int fd, off64_t offset, int64_t size) {
+    ALOGV("MidiIoWrapper(fd=%d)", fd);
+    mFd = dup(fd);
+    mBase = offset;
+    mLength = size;
+}
+
+MidiIoWrapper::~MidiIoWrapper() {
+    ALOGV("~MidiIoWrapper");
+    close(mFd);
+}
+
+int MidiIoWrapper::readAt(void *buffer, int offset, int size) {
+    ALOGV("readAt(%p, %d, %d)", buffer, offset, size);
+    lseek(mFd, mBase + offset, SEEK_SET);
+    if (offset + size > mLength) {
+        size = mLength - offset;
+    }
+    return read(mFd, buffer, size);
+}
+
+int MidiIoWrapper::size() {
+    ALOGV("size() = %d", mLength);
+    return mLength;
+}
+
+EAS_FILE_LOCATOR MidiIoWrapper::getLocator() {
+    mEasFile.handle = this;
+    mEasFile.readAt = ::readAt;
+    mEasFile.size = ::size;
+    return &mEasFile;
+}
+
+}  // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp
index 3e0fc0d..d149290 100644
--- a/media/libmediaplayerservice/MediaPlayerFactory.cpp
+++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp
@@ -15,11 +15,15 @@
 ** limitations under the License.
 */
 
+//#define LOG_NDEBUG 0
 #define LOG_TAG "MediaPlayerFactory"
 #include <utils/Log.h>
 
 #include <cutils/properties.h>
 #include <media/IMediaPlayer.h>
+#include <media/MidiIoWrapper.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/FileSource.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <utils/Errors.h>
 #include <utils/misc.h>
@@ -279,7 +283,6 @@
                 }
             }
         }
-
         return 0.0;
     }
 
@@ -295,14 +298,10 @@
 
         // Some kind of MIDI?
         EAS_DATA_HANDLE easdata;
+        sp<MidiIoWrapper> wrapper = new MidiIoWrapper(fd, offset, length);
         if (EAS_Init(&easdata) == EAS_SUCCESS) {
-            EAS_FILE locator;
-            locator.path = NULL;
-            locator.fd = fd;
-            locator.offset = offset;
-            locator.length = length;
             EAS_HANDLE  eashandle;
-            if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
+            if (EAS_OpenFile(easdata, wrapper->getLocator(), &eashandle) == EAS_SUCCESS) {
                 EAS_CloseFile(easdata, eashandle);
                 EAS_Shutdown(easdata);
                 return kOurScore;
diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp
index 749ef96..205d44f 100644
--- a/media/libmediaplayerservice/MidiFile.cpp
+++ b/media/libmediaplayerservice/MidiFile.cpp
@@ -60,11 +60,6 @@
 {
     ALOGV("constructor");
 
-    mFileLocator.path = NULL;
-    mFileLocator.fd = -1;
-    mFileLocator.offset = 0;
-    mFileLocator.length = 0;
-
     // get the library configuration and do sanity check
     if (pLibConfig == NULL)
         pLibConfig = EAS_Config();
@@ -126,11 +121,8 @@
     }
 
     // open file and set paused state
-    mFileLocator.path = strdup(path);
-    mFileLocator.fd = -1;
-    mFileLocator.offset = 0;
-    mFileLocator.length = 0;
-    EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle);
+    mIoWrapper = new MidiIoWrapper(path);
+    EAS_RESULT result = EAS_OpenFile(mEasData, mIoWrapper->getLocator(), &mEasHandle);
     if (result == EAS_SUCCESS) {
         updateState();
     }
@@ -157,10 +149,8 @@
     }
 
     // open file and set paused state
-    mFileLocator.fd = dup(fd);
-    mFileLocator.offset = offset;
-    mFileLocator.length = length;
-    EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle);
+    mIoWrapper = new MidiIoWrapper(fd, offset, length);
+    EAS_RESULT result = EAS_OpenFile(mEasData, mIoWrapper->getLocator(), &mEasHandle);
     updateState();
 
     if (result != EAS_SUCCESS) {
@@ -329,7 +319,7 @@
         EAS_HANDLE easHandle = NULL;
         EAS_RESULT result = EAS_Init(&easData);
         if (result == EAS_SUCCESS) {
-            result = EAS_OpenFile(easData, &mFileLocator, &easHandle);
+            result = EAS_OpenFile(easData, mIoWrapper->getLocator(), &easHandle);
         }
         if (result == EAS_SUCCESS) {
             result = EAS_Prepare(easData, easHandle);
@@ -395,17 +385,8 @@
         EAS_CloseFile(mEasData, mEasHandle);
         mEasHandle = NULL;
     }
-    if (mFileLocator.path) {
-        free((void*)mFileLocator.path);
-        mFileLocator.path = NULL;
-    }
-    if (mFileLocator.fd >= 0) {
-        close(mFileLocator.fd);
-    }
-    mFileLocator.fd = -1;
-    mFileLocator.offset = 0;
-    mFileLocator.length = 0;
 
+    mIoWrapper.clear();
     mPlayTime = -1;
     mDuration = -1;
     mLoop = false;
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
index 82e4e88..48a42aa 100644
--- a/media/libmediaplayerservice/MidiFile.h
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -20,6 +20,7 @@
 
 #include <media/MediaPlayerInterface.h>
 #include <libsonivox/eas.h>
+#include <media/MidiIoWrapper.h>
 
 namespace android {
 
@@ -63,7 +64,6 @@
         return INVALID_OPERATION;
     }
 
-
 private:
             status_t    createOutputTrack();
             status_t    reset_nosync();
@@ -78,7 +78,7 @@
     EAS_I32             mPlayTime;
     EAS_I32             mDuration;
     EAS_STATE           mState;
-    EAS_FILE            mFileLocator;
+    sp<MidiIoWrapper>   mIoWrapper;
     audio_stream_type_t mStreamType;
     bool                mLoop;
     volatile bool       mExit;
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 4449d57..6ded3a7 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -26,6 +26,7 @@
 
 #include <media/IMediaHTTPService.h>
 #include <media/mediametadataretriever.h>
+#include <media/MidiIoWrapper.h>
 #include <private/media/VideoFrame.h>
 
 // Sonivox includes
@@ -71,13 +72,9 @@
     EAS_DATA_HANDLE easData = NULL;
     EAS_HANDLE easHandle = NULL;
     EAS_RESULT result = EAS_Init(&easData);
+    MidiIoWrapper wrapper(filename);
     if (result == EAS_SUCCESS) {
-        EAS_FILE file;
-        file.path = filename;
-        file.fd = 0;
-        file.offset = 0;
-        file.length = 0;
-        result = EAS_OpenFile(easData, &file, &easHandle);
+        result = EAS_OpenFile(easData, wrapper.getLocator(), &easHandle);
     }
     if (result == EAS_SUCCESS) {
         result = EAS_Prepare(easData, easHandle);