Skip to content
This repository was archived by the owner on May 18, 2025. It is now read-only.

Commit ccde0ef

Browse files
committed
Fix[audio]: hopefully solve output issue and microphone
Now this provides a fake com.sun.jna.Platform class so that voice chat mods won't override to javax implementation
1 parent 1bd2990 commit ccde0ef

File tree

2 files changed

+242
-6
lines changed

2 files changed

+242
-6
lines changed
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
/*
2+
* The contents of this file is dual-licensed under 2
3+
* alternative Open Source/Free licenses: LGPL 2.1 or later and
4+
* Apache License 2.0. (starting with JNA version 4.0.0).
5+
*
6+
* You can freely decide which license you want to apply to
7+
* the project.
8+
*
9+
* You may obtain a copy of the LGPL License at:
10+
*
11+
* http://www.gnu.org/licenses/licenses.html
12+
*
13+
* A copy is also included in the downloadable source code package
14+
* containing JNA, in file "LGPL2.1".
15+
*
16+
* You may obtain a copy of the Apache License at:
17+
*
18+
* http://www.apache.org/licenses/
19+
*
20+
* A copy is also included in the downloadable source code package
21+
* containing JNA, in file "AL2.0".
22+
*/
23+
package com.sun.jna;
24+
25+
import java.io.File;
26+
import java.io.IOException;
27+
import java.lang.reflect.*;
28+
import java.util.*;
29+
import java.util.logging.Level;
30+
import java.util.logging.Logger;
31+
32+
/** Provide simplified platform information. */
33+
public final class Platform {
34+
public static final int UNSPECIFIED = -1;
35+
public static final int MAC = 0;
36+
public static final int LINUX = 1;
37+
public static final int WINDOWS = 2;
38+
public static final int SOLARIS = 3;
39+
public static final int FREEBSD = 4;
40+
public static final int OPENBSD = 5;
41+
public static final int WINDOWSCE = 6;
42+
public static final int AIX = 7;
43+
public static final int ANDROID = 8;
44+
public static final int GNU = 9;
45+
public static final int KFREEBSD = 10;
46+
public static final int NETBSD = 11;
47+
public static final int DRAGONFLYBSD = 12;
48+
49+
/** Whether read-only (final) fields within Structures are supported. */
50+
public static final boolean RO_FIELDS;
51+
/** Whether this platform provides NIO Buffers. */
52+
public static final boolean HAS_BUFFERS;
53+
/** Whether this platform provides the AWT Component class; also false if
54+
* running headless.
55+
*/
56+
public static final boolean HAS_AWT;
57+
/** Whether this platform supports the JAWT library. */
58+
public static final boolean HAS_JAWT;
59+
/** Canonical name of this platform's math library. */
60+
public static final String MATH_LIBRARY_NAME;
61+
/** Canonical name of this platform's C runtime library. */
62+
public static final String C_LIBRARY_NAME;
63+
/** Whether in-DLL callbacks are supported. */
64+
public static final boolean HAS_DLL_CALLBACKS;
65+
/** Canonical resource prefix for the current platform. This value is
66+
* used to load bundled native libraries from the class path.
67+
*/
68+
public static final String RESOURCE_PREFIX;
69+
70+
private static final int osType;
71+
/** Current platform architecture. */
72+
public static final String ARCH;
73+
74+
private static final List<Class> matchingClasses = new ArrayList<Class>();
75+
private static Object stackWalker;
76+
private static Method stackWalkerGetCaller;
77+
private static boolean isMacFoundVoiceChatMod;
78+
private static int isMacFindRetries = 10;
79+
80+
static {
81+
osType = MAC;
82+
// NOTE: we used to do Class.forName("java.awt.Component"), but that
83+
// has the unintended side effect of actually loading AWT native libs,
84+
// which can be problematic
85+
HAS_AWT = true;
86+
HAS_JAWT = HAS_AWT && osType != MAC;
87+
HAS_BUFFERS = true;
88+
RO_FIELDS = osType != WINDOWSCE;
89+
C_LIBRARY_NAME = "c";
90+
MATH_LIBRARY_NAME = "m";
91+
ARCH = getCanonicalArchitecture(System.getProperty("os.arch"), osType);
92+
// Windows aarch64 callbacks disabled via ASMFN_OFF (no mingw support)
93+
HAS_DLL_CALLBACKS = false;
94+
RESOURCE_PREFIX = getNativeLibraryResourcePrefix();
95+
96+
try {
97+
Class cStackWalker = Class.forName("java.lang.StackWalker");
98+
Class cStackWalkerOption = Class.forName("java.lang.StackWalker$Option");
99+
Object RETAIN_CLASS_REFERENCE = cStackWalkerOption.getMethod("valueOf", String.class).invoke(null, "RETAIN_CLASS_REFERENCE");
100+
stackWalker = cStackWalker.getMethod("getInstance", cStackWalkerOption).invoke(null, RETAIN_CLASS_REFERENCE);
101+
stackWalkerGetCaller = cStackWalker.getMethod("getCallerClass");
102+
} catch (Throwable th) {
103+
isMacFindRetries = 0;
104+
}
105+
}
106+
private Platform() { }
107+
public static final int getOSType() {
108+
return osType;
109+
}
110+
public static final boolean isMac() {
111+
if (isMacFindRetries <= 0) {
112+
return true;
113+
} else if (!isMacFoundVoiceChatMod) {
114+
isMacFindRetries--;
115+
try {
116+
matchingClasses.add(Class.forName("de.maxhenkel.voicechat.config.ClientConfig"));
117+
matchingClasses.add(Class.forName("de.maxhenkel.voicechat.VoicechatClient"));
118+
isMacFoundVoiceChatMod = true;
119+
} catch (Throwable th) {}
120+
try {
121+
matchingClasses.add(Class.forName("su.plo.voice.client.audio.device.VoiceDeviceManager"));
122+
isMacFoundVoiceChatMod = true;
123+
} catch (Throwable th) {}
124+
}
125+
126+
// All voice chat mods calls this thing and straight out disable OpenAL input
127+
// so we must trick them into NOT forcefully disabling it
128+
try {
129+
Class caller = (Class)stackWalkerGetCaller.invoke(stackWalker);
130+
System.out.println("Platform.isMac called from " + caller.getName());
131+
return !matchingClasses.contains(caller);
132+
} catch (Throwable e) {
133+
// We're calling a public method, this should never happen
134+
throw new RuntimeException(e);
135+
}
136+
}
137+
public static final boolean isAndroid() {
138+
return osType == ANDROID;
139+
}
140+
public static final boolean isLinux() {
141+
return osType == LINUX;
142+
}
143+
public static final boolean isAIX() {
144+
return osType == AIX;
145+
}
146+
public static final boolean isWindowsCE() {
147+
return osType == WINDOWSCE;
148+
}
149+
/** Returns true for any windows variant. */
150+
public static final boolean isWindows() {
151+
return osType == WINDOWS || osType == WINDOWSCE;
152+
}
153+
public static final boolean isSolaris() {
154+
return osType == SOLARIS;
155+
}
156+
public static final boolean isDragonFlyBSD() {
157+
return osType == DRAGONFLYBSD;
158+
}
159+
public static final boolean isFreeBSD() {
160+
return osType == FREEBSD;
161+
}
162+
public static final boolean isOpenBSD() {
163+
return osType == OPENBSD;
164+
}
165+
public static final boolean isNetBSD() {
166+
return osType == NETBSD;
167+
}
168+
public static final boolean isGNU() {
169+
return osType == GNU;
170+
}
171+
public static final boolean iskFreeBSD() {
172+
return osType == KFREEBSD;
173+
}
174+
public static final boolean isX11() {
175+
// TODO: check filesystem for /usr/X11 or some other X11-specific test
176+
return false;
177+
}
178+
public static final boolean hasRuntimeExec() {
179+
return true;
180+
}
181+
public static final boolean is64Bit() {
182+
return true;
183+
}
184+
185+
public static final boolean isIntel() {
186+
return false;
187+
}
188+
189+
public static final boolean isPPC() {
190+
return false;
191+
}
192+
193+
public static final boolean isARM() {
194+
return true;
195+
}
196+
197+
public static final boolean isSPARC() {
198+
return false;
199+
}
200+
201+
public static final boolean isMIPS() {
202+
return false;
203+
}
204+
205+
public static final boolean isLoongArch() {
206+
return false;
207+
}
208+
209+
static String getCanonicalArchitecture(String arch, int platform) {
210+
return arch;
211+
}
212+
213+
static boolean isSoftFloat() {
214+
return false;
215+
}
216+
217+
/** Generate a canonical String prefix based on the current OS
218+
type/arch/name.
219+
*/
220+
static String getNativeLibraryResourcePrefix() {
221+
String prefix = System.getProperty("jna.prefix");
222+
if(prefix != null) {
223+
return prefix;
224+
} else {
225+
return getNativeLibraryResourcePrefix(getOSType(), System.getProperty("os.arch"), System.getProperty("os.name"));
226+
}
227+
}
228+
229+
/** Generate a canonical String prefix based on the given OS
230+
type/arch/name.
231+
@param osType from {@link #getOSType()}
232+
@param arch from <code>os.arch</code> System property
233+
@param name from <code>os.name</code> System property
234+
*/
235+
static String getNativeLibraryResourcePrefix(int osType, String arch, String name) {
236+
return "darwin-" + arch;
237+
}
238+
}

Natives/SurfaceViewController.m

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -291,20 +291,18 @@ - (void)viewDidAppear:(BOOL)animated {
291291
- (void)updateAudioSettings {
292292
NSError *sessionError = nil;
293293
AVAudioSessionCategory category;
294-
AVAudioSessionCategoryOptions options;
294+
AVAudioSessionCategoryOptions options = 0;
295295
if(getPrefBool(@"video.silence_with_switch")) {
296296
category = AVAudioSessionCategorySoloAmbient;
297297
} else {
298298
category = AVAudioSessionCategoryPlayAndRecord;
299+
options |= AVAudioSessionCategoryOptionAllowAirPlay | AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionAllowBluetoothA2DP | AVAudioSessionCategoryOptionDefaultToSpeaker;
299300
}
300-
if(getPrefBool(@"video.silence_other_audio")) {
301-
options = 0;
302-
} else {
303-
options = AVAudioSessionCategoryOptionMixWithOthers;
301+
if(!getPrefBool(@"video.silence_other_audio")) {
302+
options |= AVAudioSessionCategoryOptionMixWithOthers;
304303
}
305304
AVAudioSession *session = AVAudioSession.sharedInstance;
306305
[session setCategory:category withOptions:options error:&sessionError];
307-
[session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error: nil];
308306
[session setActive:YES error:&sessionError];
309307
}
310308

0 commit comments

Comments
 (0)