feat: SAF file picker, fd to jni code

This commit is contained in:
2026-03-19 19:17:57 +01:00
parent 02ebb17dc6
commit 198dfc1630
10 changed files with 292 additions and 9 deletions

View File

@@ -74,3 +74,11 @@ PlaybackEngine::~PlaybackEngine() {
void PlaybackEngine::playBeat() {
if(mPlayer) mPlayer->setStartBeat();
}
void PlaybackEngine::playMusic(int fd) {
//if(mPlayer) mPlayer->playMusic();
// TODO: fd is opened; dispose of fd when stopping or being discarded ...
LOGI("PlaybackEngine::playMusic(fd=%d)", fd);
close(fd); // for now, nothing is implemented. we just close it again.
// we will use mp3file_open_fd() later.
}

View File

@@ -15,6 +15,7 @@ public:
virtual ~PlaybackEngine();
/** Play a beat sound. */
virtual void playBeat();
void playMusic(int fd);
private:
MixingPlayer *mPlayer;
std::string mFilesDir;

View File

@@ -40,4 +40,13 @@ Java_at_lockstep_pb_PlaybackEngine_native_1setDefaultStreamValues(JNIEnv *env,
oboe::DefaultStreamValues::FramesPerBurst = (int32_t) framesPerBurst;
}
JNIEXPORT void JNICALL
Java_at_lockstep_pb_PlaybackEngine_native_1playMusic(JNIEnv *env,
jclass type,
jlong engineHandle,
jint fd) {
auto engine = reinterpret_cast<PlaybackEngine *>(engineHandle);
engine->playMusic(fd);
}
} // extern "C"

View File

@@ -5,6 +5,7 @@
#define LOG_TAG "mp3file"
#include "mp3file.h"
#include <unistd.h>
#include <string.h>
#include <cstdlib>
#include "logging.h"
@@ -25,6 +26,7 @@ void mp3file_delete(MP3File *mp3file) {
free(mp3file->buffer);
mp3file->buffer = 0;
}
if(mp3file->android_fd) close(mp3file->android_fd);
free(mp3file);
}
@@ -93,3 +95,70 @@ on_error:
#undef handleError
}
MP3File* mp3file_open_fd(int fd, int forceEncoding) {
const char *errorText = "";
#define handleError(text) \
do { \
errorText = text; \
goto on_error; \
} while(0)
int err = MPG123_OK;
mpg123_handle *mh = mpg123_new(NULL, &err);
if(err != MPG123_OK || mh == NULL) {
LOGE("mpg123_new() failed: %s", mpg123_plain_strerror(err));
return NULL;
}
MP3File* mp3 = mp3file_init(mh);
if(mp3 == NULL) handleError("malloc() failed");
err = mpg123_open_fd(mh, fd);
if(err != MPG123_OK) handleError("mpg123_open()");
int encoding;
err = mpg123_getformat(mh, &mp3->rate, &mp3->channels, &encoding);
if(err != MPG123_OK) handleError("mpg123_getformat()");
if(encoding != MPG123_ENC_SIGNED_16) handleError("unknown file encoding");
if(forceEncoding != 0) {
encoding = forceEncoding;
}
// Ensure that this output format will not change
// (it could, when we allow it).
mpg123_format_none(mh);
err = mpg123_format(mh, mp3->rate, mp3->channels, encoding);
if(err != MPG123_OK) handleError("could not set mpg123_format()");
mp3->buffer_size = mpg123_outblock(mh);
mp3->buffer = (unsigned char*) malloc(mp3->buffer_size);
if(mp3->buffer == NULL) handleError("malloc() failed");
mp3->num_samples = mpg123_length(mh);
mp3->samples_per_frame = mpg123_spf(mh);
mp3->secs_per_frame = mpg123_tpf(mh);
if (mp3->num_samples == MPG123_ERR || mp3->samples_per_frame < 0)
mp3->num_frames = 0;
else
mp3->num_frames = mp3->num_samples / mp3->samples_per_frame;
if (mp3->num_samples == MPG123_ERR || mp3->samples_per_frame < 0 || mp3->secs_per_frame < 0)
mp3->duration = 0;
else
mp3->duration = mp3->num_samples / mp3->samples_per_frame * mp3->secs_per_frame;
mp3->offset = 0;
mp3->remaining_samples = (int) mp3->num_samples;
LOGV("channels: %d rate: %ld num_samples: %ld", mp3->channels, mp3->rate, mp3->num_samples);
mp3->android_fd = fd;
return mp3;
on_error:
LOGE("%s, err = %s", errorText, mpg123_plain_strerror(err));
mp3file_delete(mp3);
return NULL;
#undef handleError
}

View File

@@ -10,6 +10,7 @@
struct MP3File
{
mpg123_handle* handle;
int android_fd;
int channels;
long rate;
long num_samples;
@@ -26,5 +27,6 @@ struct MP3File
MP3File* mp3file_init(mpg123_handle *handle);
void mp3file_delete(MP3File *mp3file);
MP3File* mp3file_open(const char *filename, int forceEncoding = 0);
MP3File* mp3file_open_fd(int fd, int forceEncoding = 0);
#endif //SAMPLES_MP3FILE_H