From 096c676ce25da36a475d468f1685fefba41abdea Mon Sep 17 00:00:00 2001 From: David Madl Date: Wed, 3 Jun 2026 18:13:55 +0200 Subject: [PATCH] feat: LibPasada player using stretcher --- .gitignore | 2 + .../at/lockstep/player/pasada/LibPasada.java | 5 +- .../player/pasada/PasadaPlaybackListener.java | 2 + .../player/playback/PlaybackService.kt | 4 +- .../engine/PasadaMusicPlayerEngine.kt | 14 ++++ .../main/java/com/rex/logger/NdkLogger.java | 64 +++++++++++++++++++ 6 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/rex/logger/NdkLogger.java diff --git a/.gitignore b/.gitignore index beab9c9..86146aa 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ captures/ *.apk *.ap_ *.aab +# David +app/src/main/jniLibs diff --git a/app/src/main/java/at/lockstep/player/pasada/LibPasada.java b/app/src/main/java/at/lockstep/player/pasada/LibPasada.java index 9ff393b..478c092 100644 --- a/app/src/main/java/at/lockstep/player/pasada/LibPasada.java +++ b/app/src/main/java/at/lockstep/player/pasada/LibPasada.java @@ -21,7 +21,7 @@ public final class LibPasada { if (loaded) { return; } - System.loadLibrary("pasada"); + System.loadLibrary("lockstep-native"); loaded = true; } @@ -72,4 +72,7 @@ public final class LibPasada { /** Register listener for async events raised from the audio/native thread. */ public static native void setPlaybackListener(PasadaPlaybackListener listener); + + /** native version string */ + public static native String getVersion(); } diff --git a/app/src/main/java/at/lockstep/player/pasada/PasadaPlaybackListener.java b/app/src/main/java/at/lockstep/player/pasada/PasadaPlaybackListener.java index 48e9009..54c4cbc 100644 --- a/app/src/main/java/at/lockstep/player/pasada/PasadaPlaybackListener.java +++ b/app/src/main/java/at/lockstep/player/pasada/PasadaPlaybackListener.java @@ -9,6 +9,8 @@ public interface PasadaPlaybackListener { /** Current track reached end; service should advance queue and call {@link LibPasada#play}. */ void onTrackFinished(); + void onTrackClosed(int fd); + /** Decode / Oboe / pipeline failure; service should stop safely and surface error. */ void onError(int errorCode, String message); } diff --git a/app/src/main/java/at/lockstep/player/playback/PlaybackService.kt b/app/src/main/java/at/lockstep/player/playback/PlaybackService.kt index 08e9a5b..89171a5 100644 --- a/app/src/main/java/at/lockstep/player/playback/PlaybackService.kt +++ b/app/src/main/java/at/lockstep/player/playback/PlaybackService.kt @@ -17,6 +17,7 @@ import at.lockstep.player.LockstepApplication import at.lockstep.player.MainActivity import at.lockstep.player.R import at.lockstep.player.playback.engine.ExoPlayerMusicPlayerEngine +import at.lockstep.player.playback.engine.PasadaMusicPlayerEngine import at.lockstep.player.playback.engine.MusicPlayerEngine import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -204,7 +205,8 @@ class PlaybackService : Service() { engine?.let { return it } - return ExoPlayerMusicPlayerEngine(this) + //return ExoPlayerMusicPlayerEngine(this) + return PasadaMusicPlayerEngine(this) .also { it.setListener(engineListener) it.initSession() diff --git a/app/src/main/java/at/lockstep/player/playback/engine/PasadaMusicPlayerEngine.kt b/app/src/main/java/at/lockstep/player/playback/engine/PasadaMusicPlayerEngine.kt index fab66f9..61f06ba 100644 --- a/app/src/main/java/at/lockstep/player/playback/engine/PasadaMusicPlayerEngine.kt +++ b/app/src/main/java/at/lockstep/player/playback/engine/PasadaMusicPlayerEngine.kt @@ -6,6 +6,7 @@ import android.net.Uri import android.os.Handler import android.os.Looper import android.os.ParcelFileDescriptor +import android.util.Log import at.lockstep.player.pasada.LibPasada import at.lockstep.player.pasada.PasadaPlaybackListener import java.io.IOException @@ -35,12 +36,18 @@ class PasadaMusicPlayerEngine( private val nativeListener = object : PasadaPlaybackListener { override fun onTrackFinished() { + Log.i(TAG, "PasadaPlaybackListener.onTrackFinished()") pendingStart = false mainHandler.post { listener?.onPlaybackEnded() } } + override fun onTrackClosed(fd: Int) { + Log.i(TAG, "onTrackClosed: native returned fd=$fd") + // we handle parcel close() separately + } + override fun onError( errorCode: Int, message: String, @@ -51,13 +58,18 @@ class PasadaMusicPlayerEngine( } } + val TAG = "PasadaMusicPlayerEngine" + override fun initSession() { if (sessionInitialized) { return } + Log.i(TAG, "LibPasada.loadNative() ...") LibPasada.loadNative() LibPasada.setPlaybackListener(nativeListener) + Log.i(TAG, "LibPasada.init() ...") LibPasada.init() + Log.i(TAG, "LibPasada.init() done.") sessionInitialized = true } @@ -131,7 +143,9 @@ class PasadaMusicPlayerEngine( private fun startPendingTrack() { val fd = trackFd ?: return + Log.i(TAG, "LibPasada.play(fd=$fd, offset=$trackOffset, length=$trackLength) ...") LibPasada.play(fd, trackOffset, trackLength) + Log.i(TAG, "LibPasada.play() done.") pendingStart = false } diff --git a/app/src/main/java/com/rex/logger/NdkLogger.java b/app/src/main/java/com/rex/logger/NdkLogger.java new file mode 100644 index 0000000..9dcf93e --- /dev/null +++ b/app/src/main/java/com/rex/logger/NdkLogger.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.rex.logger; + +import android.util.Log; + +//import proguard.annotation.KeepName; + +//@KeepName + +/** + * Gather native log into logback, for easy control save log into SDCard + */ +public class NdkLogger { + private static final String TAG = "NDK"; + + //@KeepName + public static void logWrite(int level, String message) { + //sLogger.trace("level:{} message:{}", level, message); + switch (level) { + case Log.VERBOSE: + Log.v(TAG, message); + break; + case Log.DEBUG: + Log.d(TAG, message); + break; + case Log.INFO: + Log.i(TAG, message); + break; + case Log.WARN: + Log.w(TAG, message); + break; + case Log.ERROR: + Log.e(TAG, message); + break; + } + } + + static { + try { + System.loadLibrary("ndk-logger"); + } catch (UnsatisfiedLinkError ex) { + Log.e(TAG, "Failed to load library.", ex); + } + } + + public static String getABI() { return native_getABI(); } + private static native String native_getABI(); +} \ No newline at end of file