Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public enum ALExtension {
ALC_SOFT_OUTPUT_MODE("ALC_SOFT_output_mode", true),
ALC_SOFT_PAUSE_DEVICE("ALC_SOFT_pause_device", true),
ALC_SOFT_REOPEN_DEVICE("ALC_SOFT_reopen_device", true),
ALC_SOFT_SYSTEM_EVENTS("ALC_SOFT_system_events", true),
AL_EXT_ALAW("AL_EXT_ALAW", false),
AL_EXT_BFORMAT("AL_EXT_BFORMAT", false),
AL_EXT_DOUBLE("AL_EXT_DOUBLE", false),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

import org.lwjgl.openal.ALC10;
import org.lwjgl.openal.EnumerateAllExt;
import org.lwjgl.openal.SOFTSystemEventProcI;
import org.lwjgl.openal.SOFTSystemEvents;
import org.lwjgl.openal.SOFTReopenDevice;
import org.lwjgl.system.MemoryUtil;

Expand All @@ -25,8 +27,9 @@
import de.pottgames.tuningfork.misc.Objects;

/**
* The SmartDeviceRerouter checks every 1.5 seconds (configurable) whether the connection to the audio device still exists and whether it is the optimal
* connection. If not, it tries to establish a connection with the following prioritization:<br>
* The SmartDeviceRerouter tries to keep the connection to the optimal audio device alive. When the ALC_SOFT_system_events extension is available,
* callbacks are used to react to device changes. Otherwise, a background thread checks every 1.5 seconds (configurable) whether the connection still
* exists and whether it is the optimal connection. If not, it tries to establish a connection with the following prioritization:<br>
* <ul>
* <li>desired device</li>
* <li>current default device</li>
Expand All @@ -45,6 +48,8 @@ public class SmartDeviceRerouter implements AudioDeviceRerouter {
private final long checkInterval;

private volatile boolean active = false;
private volatile boolean useSystemEvents = false;
private SOFTSystemEventProcI systemEventProc = null;
private long device;
private volatile ContextAttributes attributes;
private volatile String desiredDeviceSpecifier = null;
Expand Down Expand Up @@ -76,6 +81,16 @@ public void setup(long device, String desiredDeviceSpecifier, ContextAttributes
this.attributes = attributes;
currentDeviceSpecifier = fetchCurrentDeviceSpecifier();
updateDesiredDevice(desiredDeviceSpecifier);
useSystemEvents = ALC10.alcIsExtensionPresent(device, "ALC_SOFT_system_events");
if (useSystemEvents) {
SOFTSystemEvents.alcEventControlSOFT(new int[] {
SOFTSystemEvents.ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT,
SOFTSystemEvents.ALC_EVENT_TYPE_DEVICE_ADDED_SOFT,
SOFTSystemEvents.ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT }, true);

systemEventProc = (eventType, deviceType, eventDevice, length, message, userParam) -> onSystemEvent(eventType);
SOFTSystemEvents.alcEventCallbackSOFT(systemEventProc, MemoryUtil.NULL);
}
setup = true;
}

Expand Down Expand Up @@ -103,10 +118,12 @@ public void start() {
}

active = true;
final Thread thread = new Thread(SmartDeviceRerouter.this::loop);
thread.setName("TuningFork-SmartDeviceRerouter-Thread");
thread.setDaemon(true);
thread.start();
if (!useSystemEvents) {
final Thread thread = new Thread(SmartDeviceRerouter.this::loop);
thread.setName("TuningFork-SmartDeviceRerouter-Thread");
thread.setDaemon(true);
thread.start();
}
}


Expand All @@ -132,6 +149,22 @@ private void loop() {
}
}

private void onSystemEvent(int eventType) {
if (!active) {
return;
}

switch (eventType) {
case SOFTSystemEvents.ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT:
case SOFTSystemEvents.ALC_EVENT_TYPE_DEVICE_ADDED_SOFT:
case SOFTSystemEvents.ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT:
tryReopen();
break;
default:
break;
}
}


private synchronized void tryReopen() {
if (desiredDeviceSpecifier == null) {
Expand Down Expand Up @@ -182,6 +215,13 @@ private void reopen(String deviceSpecifier) {
@Override
public void dispose() {
active = false;
if (useSystemEvents) {
SOFTSystemEvents.alcEventCallbackSOFT(null, MemoryUtil.NULL);
SOFTSystemEvents.alcEventControlSOFT(new int[] {
SOFTSystemEvents.ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT,
SOFTSystemEvents.ALC_EVENT_TYPE_DEVICE_ADDED_SOFT,
SOFTSystemEvents.ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT }, false);
}
}

}
Loading