diff --git a/pom.xml b/pom.xml
index b6285ef..4a4519b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -73,6 +73,11 @@
org.apache.commons
commons-lang3
+
+ org.apache.commons
+ commons-collections4
+ 4.4
+
net.java.dev.jna
diff --git a/src/main/java/com/getpcpanel/cpp/linux/PulseAudioEventListener.java b/src/main/java/com/getpcpanel/cpp/linux/PulseAudioEventListener.java
index 63a782a..27fbe95 100644
--- a/src/main/java/com/getpcpanel/cpp/linux/PulseAudioEventListener.java
+++ b/src/main/java/com/getpcpanel/cpp/linux/PulseAudioEventListener.java
@@ -3,7 +3,10 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import org.apache.commons.collections4.queue.CircularFifoQueue;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
@@ -23,6 +26,8 @@
public class PulseAudioEventListener extends Thread {
private final ApplicationEventPublisher eventPublisher;
private final ProcessHelper processHelper;
+ private final CircularFifoQueue latestEvents = new CircularFifoQueue<>(50);
+
private boolean running = true;
@PostConstruct
@@ -44,9 +49,11 @@ public void run() {
var process = processHelper.builder("pactl", "subscribe").start();
var reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ var dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String line;
//noinspection NestedAssignment
while ((line = reader.readLine()) != null) {
+ latestEvents.add(dateFormat.format(new Date()) + " - " + line);
checkTrigger(line);
}
} catch (IOException e) {
@@ -55,6 +62,10 @@ public void run() {
}
}
+ String getDebugOutput() {
+ return "pactl subscribe:\n" + String.join("\n", latestEvents);
+ }
+
private void checkTrigger(String line) {
if (StringUtils.containsIgnoreCase(line, "Event 'new' on sink-input") || StringUtils.containsIgnoreCase(line, "Event 'remove' on sink-input")) {
eventPublisher.publishEvent(new LinuxSessionChangedEvent());
diff --git a/src/main/java/com/getpcpanel/cpp/linux/PulseAudioWrapper.java b/src/main/java/com/getpcpanel/cpp/linux/PulseAudioWrapper.java
index cc9cf46..bb62b91 100644
--- a/src/main/java/com/getpcpanel/cpp/linux/PulseAudioWrapper.java
+++ b/src/main/java/com/getpcpanel/cpp/linux/PulseAudioWrapper.java
@@ -7,6 +7,8 @@
import java.util.Map;
import java.util.regex.Pattern;
+import javax.annotation.Nonnull;
+
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
@@ -143,6 +145,17 @@ private String idxOrDefaultDevice(int idx) {
return idx == DEFAULT_DEVICE ? "@DEFAULT_SINK@" : String.valueOf(idx);
}
+ @Nonnull
+ List getDebugOutput() {
+ return StreamEx.of(InOutput.values())
+ .map(t -> new String[] { "pactl", "list", t.pulseType })
+ .mapToEntry(cmd -> runAndRead(processHelper.builder(cmd)))
+ .mapKeys(cmd -> String.join(" ", cmd))
+ .mapValues(lines -> String.join("\n", lines))
+ .mapKeyValue((cmd, lns) -> cmd + ":\n" + lns)
+ .toList();
+ }
+
@Builder
record PulseAudioTarget(int index, boolean isDefault, Map metas, Map properties, InOutput type) {
}
diff --git a/src/main/java/com/getpcpanel/cpp/linux/SndCtrlLinuxDebug.java b/src/main/java/com/getpcpanel/cpp/linux/SndCtrlLinuxDebug.java
new file mode 100644
index 0000000..52210f3
--- /dev/null
+++ b/src/main/java/com/getpcpanel/cpp/linux/SndCtrlLinuxDebug.java
@@ -0,0 +1,29 @@
+package com.getpcpanel.cpp.linux;
+
+import java.awt.Toolkit;
+import java.awt.datatransfer.StringSelection;
+
+import org.springframework.stereotype.Service;
+
+import com.getpcpanel.spring.ConditionalOnLinux;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+import one.util.streamex.StreamEx;
+
+@Log4j2
+@Service
+@ConditionalOnLinux
+@RequiredArgsConstructor
+public class SndCtrlLinuxDebug {
+ private final PulseAudioWrapper paWrapper;
+ private final PulseAudioEventListener paEventListener;
+
+ public void copyDebugOutput() {
+ var output = StreamEx.of(paWrapper.getDebugOutput())
+ .append(paEventListener.getDebugOutput())
+ .joining("\n".repeat(5));
+ var content = new StringSelection(output);
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(content, null);
+ }
+}
diff --git a/src/main/java/com/getpcpanel/spring/OsHelper.java b/src/main/java/com/getpcpanel/spring/OsHelper.java
index 6a14950..649c8fd 100644
--- a/src/main/java/com/getpcpanel/spring/OsHelper.java
+++ b/src/main/java/com/getpcpanel/spring/OsHelper.java
@@ -1,5 +1,6 @@
package com.getpcpanel.spring;
+import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
@@ -7,6 +8,7 @@
import org.springframework.stereotype.Service;
import javafx.css.Styleable;
+import javafx.scene.Node;
import one.util.streamex.StreamEx;
@Service
@@ -38,6 +40,13 @@ public boolean isSupported(Styleable elem) {
return toHideClasses.stream().noneMatch(toHideClass -> elem.getStyleClass().contains(toHideClass));
}
+ public void hideUnsupportedChildren(List children) {
+ StreamEx.of(children).remove(this::isSupported).forEach(c -> {
+ c.setVisible(false);
+ c.setManaged(false);
+ });
+ }
+
public boolean isOs(String os) {
return StringUtils.equalsAny(os, "*", osString());
}
diff --git a/src/main/java/com/getpcpanel/ui/SettingsDialog.java b/src/main/java/com/getpcpanel/ui/SettingsDialog.java
index 4ce420a..5aab389 100644
--- a/src/main/java/com/getpcpanel/ui/SettingsDialog.java
+++ b/src/main/java/com/getpcpanel/ui/SettingsDialog.java
@@ -12,6 +12,7 @@
import org.springframework.stereotype.Component;
import com.getpcpanel.MainFX;
+import com.getpcpanel.cpp.linux.SndCtrlLinuxDebug;
import com.getpcpanel.cpp.windows.SndCtrlWindows;
import com.getpcpanel.obs.OBS;
import com.getpcpanel.profile.Save;
@@ -36,6 +37,7 @@
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.layout.Pane;
+import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Modality;
import javafx.stage.Stage;
@@ -82,6 +84,8 @@ public class SettingsDialog extends Application implements UIInitializer args) {
@@ -217,6 +221,7 @@ private void initOverlayColors(Save save) {
private void postInit() {
initFields();
+ osHelper.hideUnsupportedChildren(debug.getChildrenUnmodifiable());
}
public void doTest(ActionEvent ignored) {
@@ -246,4 +251,10 @@ public void doTest(ActionEvent ignored) {
public void triggerAv(ActionEvent ignored) {
MainFX.getBean(SndCtrlWindows.class).triggerAv();
}
+
+ public void copyAudioOutput(ActionEvent ignored) {
+ copied.setText("Preparing output");
+ MainFX.getBean(SndCtrlLinuxDebug.class).copyDebugOutput();
+ copied.setText("Output was copied to your clipboard");
+ }
}
diff --git a/src/main/resources/assets/SettingsDialog.fxml b/src/main/resources/assets/SettingsDialog.fxml
index 0b01d4f..d28f31e 100644
--- a/src/main/resources/assets/SettingsDialog.fxml
+++ b/src/main/resources/assets/SettingsDialog.fxml
@@ -122,13 +122,21 @@
-
-
+
+
-
+
+
+
+
+