diff --git a/.CMakeLists.txt.swp b/.CMakeLists.txt.swp
deleted file mode 100644
index 5de03fd..0000000
Binary files a/.CMakeLists.txt.swp and /dev/null differ
diff --git a/.forgejo/workflows/compile.yaml b/.forgejo/workflows/compile.yaml
index fd2e322..cc4c031 100644
--- a/.forgejo/workflows/compile.yaml
+++ b/.forgejo/workflows/compile.yaml
@@ -9,7 +9,7 @@ jobs:
- name: Download and cache system dependencies
uses: https://complecwaft.com/catmeow/cache-apt-pkgs-action@latest
with:
- packages: zstd cmake build-essential python3 python3-pip python3-venv wget gcc-mingw-w64 g++-mingw-w64 ninja-build binutils-mingw-w64-x86_64
+ packages: zstd cmake build-essential python3 python3-pip python3-venv wget gcc-mingw-w64 g++-mingw-w64 ninja-build binutils-mingw-w64-x86-64
version: 1.0
get-source-code:
runs-on: ubuntu-latest
@@ -137,7 +137,7 @@ jobs:
- name: Download and cache system dependencies
uses: https://complecwaft.com/catmeow/cache-apt-pkgs-action@latest
with:
- packages: zstd cmake build-essential gcc-mingw-w64 g++-mingw-w64 ninja-build binutils-mingw-w64-x86_64
+ packages: zstd cmake build-essential gcc-mingw-w64 g++-mingw-w64 ninja-build binutils-mingw-w64-x86-64
version: 1.0
- name: Download repository code
uses: actions/download-artifact@v3
@@ -154,7 +154,7 @@ jobs:
- name: Build protoc
run: ./build-protoc.sh
- name: Build with CMake
- run: mkdir -p build-windows && cd build-windows && cmake .. -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-gcc -G Ninja -DDISABLE_GTK_UI=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_LIBFMT=ON -DUSE_PORTALS=OFF -DENABLE_DBUS=OFF -DBUILD_STATIC=ON -DDOWNLOAD_AUDIO_CODECS_DEPENDENCY=ON -DSDL_MIXER_X_SHARED=OFF -DSDL_MIXER_X_STATIC=ON -DUSE_OGG_VORBIS_STB=ON -DUSE_OPUS=OFF -DUSE_MODPLUG=OFF -DUSE_GME=OFF -DUSE_WAVPACK=OFF -DUSE_XMP=OFF -DUSE_MIDI_EDMIDI=OFF -DUSE_SYSTEM_SDL2=ON -DBUILD_PROTOC=OFF -DBUILD_SDL=ON -DBUILD_SDL_IMAGE=ON -DBUILD_JSONCPP=ON -DBUILD_SOUNDTOUCH=ON -DBUILD_PROTOBUF=ON -DDISABLE_IMGUI_UI=OFF -D BUILD_FMT=ON && env PATH="/usr/x86_64-w64-mingw32/bin:$PATH" ninja && cd ..
+ run: mkdir -p build-windows && cd build-windows && cmake .. -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-gcc -G Ninja -DDISABLE_GTK_UI=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_LIBFMT=ON -DUSE_PORTALS=OFF -DENABLE_DBUS=OFF -DBUILD_STATIC=ON -DDOWNLOAD_AUDIO_CODECS_DEPENDENCY=ON -DSDL_MIXER_X_SHARED=OFF -DSDL_MIXER_X_STATIC=ON -DUSE_OGG_VORBIS_STB=ON -DUSE_OPUS=OFF -DUSE_MODPLUG=OFF -DUSE_GME=OFF -DUSE_WAVPACK=OFF -DUSE_XMP=OFF -DUSE_MIDI_EDMIDI=OFF -DUSE_SYSTEM_SDL2=ON -DBUILD_PROTOC=OFF -DBUILD_SDL=ON -DBUILD_SDL_IMAGE=ON -DBUILD_JSONCPP=ON -DBUILD_SOUNDTOUCH=ON -DBUILD_PROTOBUF=ON -DDISABLE_IMGUI_UI=OFF -D BUILD_FMT=ON && ninja && cd ..
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
diff --git a/sdl-android-project/.gitmodules b/sdl-android-project/.gitmodules
new file mode 100644
index 0000000..8bbb40f
--- /dev/null
+++ b/sdl-android-project/.gitmodules
@@ -0,0 +1,28 @@
+[submodule "../backends/ui/imgui/imgui"]
+ commit = 99109c0b3b052cffa154a9295440f68868a39f74
+[submodule "../subprojects/SDL"]
+ commit = 79ec168f3c1e2fe27335cb8886439f7ef676fb49
+[submodule "../subprojects/SDL-Mixer-X"]
+ commit = 22aed1f6bcfa6912a34d3241edf3bd90498a6bc2
+[submodule "../subprojects/SDL_image"]
+ commit = abcf63aa71b4e3ac32120fa9870a6500ddcdcc89
+[submodule "../subprojects/fmt"]
+ commit = 0379bf3a5d52d8542aec1874677c9df5ff9ba5f9
+[submodule "../subprojects/googletest"]
+ commit = 6dae7eb4a5c3a169f3e298392bff4680224aa94a
+[submodule "../subprojects/grpc"]
+ commit = e821cdc231bda9ee93139a6daab6311dd8953832
+[submodule "../subprojects/jsoncpp"]
+ commit = 8214f717e7c7d361f002b6c3d1b1086ddd096315
+[submodule "../subprojects/libintl-lite"]
+ commit = 44035a0c3fe20ef28f071b35b9f5a653fbfe5e6d
+[submodule "../subprojects/oboe"]
+ commit = 86165b8249bc22b9ef70b69e20323244b6f08d88
+[submodule "../subprojects/protobuf"]
+ commit = 63def39e881afa496502d9c410f4ea948e59490d
+[submodule "../subprojects/protobuf-c"]
+ commit = 8c201f6e47a53feaab773922a743091eb6c8972a
+[submodule "../subprojects/soundtouch"]
+ commit = e83424d5928ab8513d2d082779c275765dee31b9
+[submodule "../subprojects/vgmstream"]
+ commit = 1d836a3693541811d4a5089cf8c68d6acd4b1eeb
diff --git a/sdl-android-project/.project b/sdl-android-project/.project
deleted file mode 100644
index 3a3984c..0000000
--- a/sdl-android-project/.project
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
- sdl-android-project
- Project sdl-android-project created by Buildship.
-
-
-
-
- org.eclipse.buildship.core.gradleprojectbuilder
-
-
-
-
-
- org.eclipse.buildship.core.gradleprojectnature
-
-
-
- 1729361463965
-
- 30
-
- org.eclipse.core.resources.regexFilterMatcher
- node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
-
-
-
-
diff --git a/sdl-android-project/.settings/org.eclipse.buildship.core.prefs b/sdl-android-project/.settings/org.eclipse.buildship.core.prefs
deleted file mode 100644
index 1382021..0000000
--- a/sdl-android-project/.settings/org.eclipse.buildship.core.prefs
+++ /dev/null
@@ -1,13 +0,0 @@
-arguments=--init-script /home/catmeow/.local/share/zed/extensions/work/java/jdt-language-server-1.40.0/configuration/org.eclipse.osgi/57/0/.cp/gradle/init/init.gradle
-auto.sync=false
-build.scans.enabled=false
-connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
-connection.project.dir=
-eclipse.preferences.version=1
-gradle.user.home=
-java.home=/opt/openjdk-bin-21.0.4_p7
-jvm.arguments=
-offline.mode=false
-override.workspace.settings=true
-show.console.view=true
-show.executions.view=true
diff --git a/sdl-android-project/app/.classpath b/sdl-android-project/app/.classpath
deleted file mode 100644
index 0a3280e..0000000
--- a/sdl-android-project/app/.classpath
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/sdl-android-project/app/.project b/sdl-android-project/app/.project
deleted file mode 100644
index 7e1aa36..0000000
--- a/sdl-android-project/app/.project
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
- app
- Project app created by Buildship.
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- org.eclipse.buildship.core.gradleprojectbuilder
-
-
-
-
-
- org.eclipse.jdt.core.javanature
- org.eclipse.buildship.core.gradleprojectnature
-
-
-
- 1729361463958
-
- 30
-
- org.eclipse.core.resources.regexFilterMatcher
- node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
-
-
-
-
diff --git a/sdl-android-project/app/.settings/org.eclipse.jdt.core.prefs b/sdl-android-project/app/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..e9186c3
--- /dev/null
+++ b/sdl-android-project/app/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.source=21
diff --git a/sdl-android-project/app/build.gradle b/sdl-android-project/app/build.gradle
index 982eb82..5c09d9f 100644
--- a/sdl-android-project/app/build.gradle
+++ b/sdl-android-project/app/build.gradle
@@ -6,7 +6,6 @@ if (buildAsApplication) {
else {
apply plugin: 'com.android.library'
}
-
android {
buildFeatures {
prefab true
@@ -19,8 +18,26 @@ android {
defaultConfig {
minSdkVersion 30
targetSdkVersion 34
- versionCode 1
- versionName "1.0"
+ def revListStdout = new ByteArrayOutputStream();
+ exec {
+ executable "git"
+ commandLine "git", "rev-list", "--count", "HEAD"
+ standardOutput revListStdout
+ }
+ def revParseStdout = new ByteArrayOutputStream();
+ def versionNameData = ""
+ exec {
+ commandLine "git", "rev-parse", "--abbref-rev", "HEAD"
+ standardOutput revParseStdout
+ }
+ versionNameData = revParseStdout.toString() + "-"
+ revParseStdout = new ByteArrayOutputStream()
+ exec {
+ commandLine "git", "rev-parse", "--short", "HEAD"
+ standardOutput revParseStdout
+ }
+ versionCode revListStdout.toString() as Integer
+ versionName versionNameData + revParseStdout.toString()
externalNativeBuild {
cmake {
arguments "-DUSE_GLES=ON", "-DUSE_PORTALS=OFF", "-DDOWNLOAD_AUDIO_CODECS_DEPENDENCY=ON", "-DENABLE_DBUS=OFF", "-DBUILD_SDL=ON", "-DBUILD_SDL_IMAGE=ON", "-DDISABLE_GTK_UI=ON", "-DDISABLE_IMGUI_UI=OFF"
@@ -66,6 +83,7 @@ android {
}
dependencies {
+ implementation "androidx.core:core:1.13.1"
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation group: 'com.getkeepsafe.relinker', name: 'relinker', version: '1.4.5'
}
diff --git a/sdl-android-project/app/src/main/AndroidManifest.xml b/sdl-android-project/app/src/main/AndroidManifest.xml
index bbf805c..691b902 100644
--- a/sdl-android-project/app/src/main/AndroidManifest.xml
+++ b/sdl-android-project/app/src/main/AndroidManifest.xml
@@ -1,10 +1,7 @@
-
+ >
@@ -53,13 +50,15 @@
-
+
+
+
-
+
= 0) {
- os.write(buf, 0, len);
- pos += len;
- }
- } catch (IOException e) {
- e.printStackTrace();
- PickedFile = null;
- loading = false;
- return;
- }
- loading = false;
- PickedFile = file.getAbsolutePath();
- } else {
- PickedFile = null;
- }
- }
- }
- private static boolean loading;
- public static boolean IsLoading() {
- return loading;
- }
- private static String PickedFile = null;
- public static String GetPickedFile() {
- if (openDocumentIntent == null) {
- return "";
- } else if (PickedFile == null) {
- return "";
- } else {
- return PickedFile;
- }
- }
- public static void ClearSelected() {
- PickedFile = null;
- }
+public class MainActivity extends SDLActivity {
+
+ public static MainActivity mSingleton;
+ private static Intent mediaPlaybackService;
+ private static Intent requestPermissionLauncher;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ if (
+ this.getBaseContext().checkSelfPermission(
+ Manifest.permission.POST_NOTIFICATIONS
+ ) ==
+ PackageManager.PERMISSION_GRANTED
+ ) {
+ this.onRequestPermissionsResult(PERMISSION_REQUEST, new String[] {Manifest.permission.POST_NOTIFICATIONS}, new int[] {PackageManager.PERMISSION_GRANTED});
+ } else {
+ // You can directly ask for the permission.
+ // The registered ActivityResultCallback gets the result of this request.
+ this.requestPermissions(
+ new String[] {Manifest.permission.POST_NOTIFICATIONS},
+ PERMISSION_REQUEST
+ );
+ }
+ mSingleton = this;
+ super.onCreate(savedInstanceState);
+ }
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ int importance = NotificationManager.IMPORTANCE_DEFAULT;
+ NotificationChannel channel = new NotificationChannel(
+ "com.complecwaft.looper.MediaPlayback",
+ "Media Playback",
+ importance
+ );
+ channel.setDescription(
+ "Notification for keeping playback in the foreground"
+ );
+ NotificationManager notificationManager = getSystemService(
+ NotificationManager.class
+ );
+ notificationManager.createNotificationChannel(channel);
+ }
+ mediaPlaybackService = new Intent(this, PlaybackService.class);
+ startService(mediaPlaybackService);
+ }
+
+ @Override
+ protected void onDestroy() {
+ stopService(mediaPlaybackService);
+ super.onDestroy();
+ mSingleton = null;
+ }
+
+ private static Intent openDocumentIntent = null;
+
+ public static String GetUserDir() {
+ return System.getProperty("user.home");
+ }
+
+ private static final int PICK_FILE = 0x33;
+ private static final int PERMISSION_REQUEST = 0x34;
+
+ public static void OpenFilePicker(Object extraInitialUri) {
+ openDocumentIntent = new Intent(Intent.ACTION_GET_CONTENT);
+ openDocumentIntent.addCategory(Intent.CATEGORY_OPENABLE);
+ openDocumentIntent.setType("*/*");
+ if (extraInitialUri instanceof String) {
+ openDocumentIntent.putExtra(
+ DocumentsContract.EXTRA_INITIAL_URI,
+ (String) extraInitialUri
+ );
+ }
+ if (
+ openDocumentIntent.resolveActivity(
+ mSingleton.getPackageManager()
+ ) !=
+ null
+ ) {
+ mSingleton.startActivityForResult(
+ Intent.createChooser(openDocumentIntent, "Open a file..."),
+ PICK_FILE
+ );
+ } else {
+ Log.d("Looper", "Unable to resolve Intent.ACTION_OPEN_DOCUMENT {}");
+ }
+ }
+
+ @Override
+ public void onActivityResult(
+ int requestCode,
+ int resultCode,
+ Intent resultData
+ ) {
+ if (requestCode == PICK_FILE && resultCode == RESULT_OK) {
+ Uri uri = null;
+ if (resultData != null) {
+ uri = resultData.getData();
+ InputStream input = null;
+ loading = true;
+ try {
+ input = getApplication()
+ .getContentResolver()
+ .openInputStream(uri);
+ } catch (FileNotFoundException ex) {
+ ex.printStackTrace();
+ PickedFile = null;
+
+ loading = false;
+ return;
+ }
+ File file = new File(getCacheDir(), uri.getLastPathSegment());
+ try {
+ file.getParentFile().mkdirs();
+ file.createNewFile();
+ FileOutputStream os = null;
+ os = new FileOutputStream(file);
+ int len = 0;
+ int pos = 0;
+ byte[] buf = new byte[1024 * 4];
+
+ while ((len = input.read(buf)) >= 0) {
+ os.write(buf, 0, len);
+ pos += len;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ PickedFile = null;
+ loading = false;
+ return;
+ }
+ loading = false;
+ PickedFile = file.getAbsolutePath();
+ } else {
+ PickedFile = null;
+ }
+ }
+ }
+
+ private static boolean loading;
+
+ public static boolean IsLoading() {
+ return loading;
+ }
+
+ private static String PickedFile = null;
+
+ public static String GetPickedFile() {
+ if (openDocumentIntent == null) {
+ return "";
+ } else if (PickedFile == null) {
+ return "";
+ } else {
+ return PickedFile;
+ }
+ }
+
+ public static void ClearSelected() {
+ PickedFile = null;
+ }
}
diff --git a/sdl-android-project/app/src/main/java/com/complecwaft/looper/PlaybackService.java b/sdl-android-project/app/src/main/java/com/complecwaft/looper/PlaybackService.java
new file mode 100644
index 0000000..5dee927
--- /dev/null
+++ b/sdl-android-project/app/src/main/java/com/complecwaft/looper/PlaybackService.java
@@ -0,0 +1,57 @@
+package com.complecwaft.looper;
+
+import android.app.ForegroundServiceStartNotAllowedException;
+import android.app.Notification;
+import android.app.Service;
+import android.content.Intent;
+import android.content.pm.ServiceInfo;
+import android.os.Build;
+import android.os.Binder;
+import android.os.IBinder;
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.ServiceCompat;
+
+public class PlaybackService extends Service {
+
+ private void startForeground() {
+ try {
+ Notification notification = new NotificationCompat.Builder(
+ this,
+ "com.complecwaft.looper.MediaPlayback"
+ ).build();
+ int type = 0;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ type = ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK;
+ }
+ ServiceCompat.startForeground(
+ this,
+ 100, // Cannot be 0
+ notification,
+ type
+ );
+ } catch (Exception e) {
+ if (
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
+ e instanceof ForegroundServiceStartNotAllowedException
+ ) {
+ // App not in a valid state to start foreground service
+ // (e.g started from bg)
+ }
+ }
+ }
+
+ @Override
+ public void onCreate() {
+ startForeground();
+ }
+
+ @Override
+ public void onDestroy() {
+ ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE);
+ }
+
+ @Override
+ public IBinder onBind(Intent arg0) {
+ return new Binder();
+ }
+}
diff --git a/sdl-android-project/gradle.properties b/sdl-android-project/gradle.properties
index 3390091..a8b3067 100644
--- a/sdl-android-project/gradle.properties
+++ b/sdl-android-project/gradle.properties
@@ -16,3 +16,4 @@ ndk_version=27.2.12479018
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
+android.useAndroidX=true
\ No newline at end of file