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