diff --git a/3dfx/3dfx-wrappers-2.9.5.iso b/3dfx/3dfx-wrappers-2.9.5.iso new file mode 100644 index 0000000..18f6447 Binary files /dev/null and b/3dfx/3dfx-wrappers-2.9.5.iso differ diff --git a/app/src/main/java/com/vectras/vm/core/PulseAudio.java b/app/src/main/java/com/vectras/vm/core/PulseAudio.java new file mode 100644 index 0000000..6810792 --- /dev/null +++ b/app/src/main/java/com/vectras/vm/core/PulseAudio.java @@ -0,0 +1,77 @@ +package com.vectras.vm.core; + +import android.content.Context; +import android.util.Log; +import com.termux.app.TermuxService; +import com.vectras.vm.logger.VectrasStatus; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +public class PulseAudio { + private static final String TAG = "PulseAudio"; + private Process pulseAudioProcess; + private Context context; + private ExecutorService executorService; + private Future processFuture; + + public PulseAudio(Context context) { + this.context = context; + this.executorService = Executors.newSingleThreadExecutor(); + } + + public void start() { + String tmpDir = TermuxService.PREFIX_PATH + "/tmp"; + + Runnable processRunnable = () -> { + try { + ProcessBuilder processBuilder = new ProcessBuilder( + "/system/bin/sh", "-c", + "XDG_RUNTIME_DIR=" + tmpDir + " TMPDIR=" + tmpDir + " " + + TermuxService.PREFIX_PATH + "/bin/pulseaudio --start " + + "--load=\"module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1\" " + + "--exit-idle-time=-1" + ); + + processBuilder.redirectErrorStream(true); + pulseAudioProcess = processBuilder.start(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(pulseAudioProcess.getInputStream())); + String line; + while ((line = reader.readLine()) != null) { + Log.d(TAG, line); + VectrasStatus.logInfo(TAG + " > " + line); + } + } catch (IOException e) { + Log.e(TAG, "Error starting PulseAudio", e); + VectrasStatus.logInfo(TAG + " > " + e.toString()); + } + }; + + processFuture = executorService.submit(processRunnable); + } + + public void stop() { + if (pulseAudioProcess != null) { + pulseAudioProcess.destroy(); + try { + pulseAudioProcess.waitFor(); + Log.d(TAG, "PulseAudio stopped"); + VectrasStatus.logInfo(TAG + " > PulseAudio stopped"); + } catch (InterruptedException e) { + Log.e(TAG, "Error stopping PulseAudio", e); + VectrasStatus.logInfo(TAG + " > Error stopping PulseAudio: " + e.toString()); + } + } + + if (processFuture != null) { + processFuture.cancel(true); + } + + executorService.shutdown(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vectras/vm/utils/LibraryChecker.java b/app/src/main/java/com/vectras/vm/utils/LibraryChecker.java new file mode 100644 index 0000000..a61858a --- /dev/null +++ b/app/src/main/java/com/vectras/vm/utils/LibraryChecker.java @@ -0,0 +1,150 @@ +package com.vectras.vm.utils; + +import android.app.Activity; +import android.content.Context; + +import androidx.appcompat.app.AlertDialog; + +import com.vectras.vm.AppConfig; +import com.vectras.vm.R; +import com.vectras.vterm.Terminal; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public class LibraryChecker { + private Context context; + + public LibraryChecker(Context context) { + this.context = context; + } + + public void checkMissingLibraries(Activity activity) { + // List of required libraries + String[] requiredLibraries = AppConfig.neededPkgs.split(" "); + + // Get the list of installed packages + isPackageInstalled(null, (output, errors) -> { + // Split the installed packages output into an array and convert to a set for fast lookup + Set installedPackages = new HashSet<>(); + for (String installedPackage : output.split("\n")) { + installedPackages.add(installedPackage.trim()); + } + + // StringBuilder to collect missing libraries + StringBuilder missingLibraries = new StringBuilder(); + + // Loop over required libraries and check if they're installed + for (String lib : requiredLibraries) { + if (!installedPackages.contains(lib.trim())) { + missingLibraries.append(lib).append("\n"); + } + } + + // Show dialog if any libraries are missing + if (missingLibraries.toString().trim().length() > 0) { + showMissingLibrariesDialog(activity, missingLibraries.toString()); + } else { + // show a dialog if all libraries are installed + // showAllLibrariesInstalledDialog(activity); + } + }); + } + + // Method to show the missing libraries dialog + private void showMissingLibrariesDialog(Activity activity, String missingLibraries) { + new AlertDialog.Builder(activity, R.style.MainDialogTheme) + .setTitle("Missing Libraries") + .setMessage("The following libraries are missing:\n\n" + missingLibraries) + .setCancelable(false) + .setPositiveButton("Install", (dialog, which) -> { + // Create the install command + String installCommand = "apk add " + missingLibraries.replace("\n", " "); + new Terminal(context).executeShellCommand(installCommand, true, activity); + }) + .setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss()) + .show(); + } + + // Method to show the "All Libraries Installed" dialog + private void showAllLibrariesInstalledDialog(Activity activity) { + new AlertDialog.Builder(activity, R.style.MainDialogTheme) + .setTitle("All Libraries Installed") + .setMessage("All required libraries are already installed.") + .setPositiveButton("OK", (dialog, which) -> dialog.dismiss()) + .show(); + } + + // Method to check if the package is installed + public void isPackageInstalled(String packageName, Terminal.CommandCallback callback) { + String command = "apk info"; + + Terminal terminal = new Terminal(context); + terminal.executeShellCommand(command, (Activity) context, (output, errors) -> { + if (callback != null) { + callback.onCommandCompleted(output, errors); + } + }); + } + + // Method to check if the package is installed + public static void isPackageInstalled2(Activity activity, String packageName, Terminal.CommandCallback callback) { + String command = "apk info"; + + Terminal terminal = new Terminal(activity); + terminal.executeShellCommand(command, activity, (output, errors) -> { + if (callback != null) { + callback.onCommandCompleted(output, errors); + } + }); + } + + public void checkAndInstallXFCE4(Activity activity) { + // XFCE4 meta-package + String xfce4Package = "xfce4"; + + // Check if XFCE4 is installed + isPackageInstalled(xfce4Package, (output, errors) -> { + boolean isInstalled = false; + + // Check if the package exists in the installed packages output + if (output != null) { + Set installedPackages = new HashSet<>(); + for (String installedPackage : output.split("\n")) { + installedPackages.add(installedPackage.trim()); + } + + isInstalled = installedPackages.contains(xfce4Package.trim()); + } + + // If not installed, show a dialog to install it + if (!isInstalled) { + showInstallDialog(activity, xfce4Package); + } else { + showAlreadyInstalledDialog(activity); + } + }); + } + + private void showInstallDialog(Activity activity, String packageName) { + new AlertDialog.Builder(activity, R.style.MainDialogTheme) + .setTitle("Install XFCE4") + .setMessage("XFCE4 is not installed. Would you like to install it?") + .setCancelable(false) + .setPositiveButton("Install", (dialog, which) -> { + String installCommand = "apk add " + packageName; + new Terminal(context).executeShellCommand(installCommand, true, activity); + }) + .setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss()) + .show(); + } + + private void showAlreadyInstalledDialog(Activity activity) { + new AlertDialog.Builder(activity, R.style.MainDialogTheme) + .setTitle("XFCE4 Installed") + .setMessage("XFCE4 is already installed on this system.") + .setPositiveButton("OK", (dialog, which) -> dialog.dismiss()) + .show(); + } +} diff --git a/app/src/main/res/drawable/apps_24px.xml b/app/src/main/res/drawable/apps_24px.xml new file mode 100644 index 0000000..2004718 --- /dev/null +++ b/app/src/main/res/drawable/apps_24px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/deployed_code_24px.xml b/app/src/main/res/drawable/deployed_code_24px.xml new file mode 100644 index 0000000..05593b4 --- /dev/null +++ b/app/src/main/res/drawable/deployed_code_24px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/desktop_24px.xml b/app/src/main/res/drawable/desktop_24px.xml new file mode 100644 index 0000000..e1a0d90 --- /dev/null +++ b/app/src/main/res/drawable/desktop_24px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_discord.xml b/app/src/main/res/drawable/ic_discord.xml new file mode 100644 index 0000000..cf68c2d --- /dev/null +++ b/app/src/main/res/drawable/ic_discord.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/manufacturing_24px.xml b/app/src/main/res/drawable/manufacturing_24px.xml new file mode 100644 index 0000000..0ac7d07 --- /dev/null +++ b/app/src/main/res/drawable/manufacturing_24px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/transparent_background.xml b/app/src/main/res/drawable/transparent_background.xml new file mode 100644 index 0000000..1293e15 --- /dev/null +++ b/app/src/main/res/drawable/transparent_background.xml @@ -0,0 +1,4 @@ + + + + diff --git a/app/src/main/res/layout/dialog_programs.xml b/app/src/main/res/layout/dialog_programs.xml new file mode 100644 index 0000000..3389dac --- /dev/null +++ b/app/src/main/res/layout/dialog_programs.xml @@ -0,0 +1,47 @@ + + + + + + + + +