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 @@ - - + +