Skip to content

Commit ff195d3

Browse files
committed
- ffi cpu check for apple silicon
1 parent da58a4f commit ff195d3

File tree

1 file changed

+42
-16
lines changed

1 file changed

+42
-16
lines changed

src/main/java/mediathek/mac/MediathekGuiMac.kt

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@ package mediathek.mac
22

33
import com.formdev.flatlaf.FlatClientProperties
44
import com.formdev.flatlaf.util.SystemInfo
5-
import com.sun.jna.Memory
6-
import com.sun.jna.platform.mac.SystemB
7-
import com.sun.jna.ptr.IntByReference
85
import mediathek.config.Konstanten
96
import mediathek.gui.actions.ShowAboutAction
107
import mediathek.gui.messages.DownloadFinishedEvent
@@ -29,6 +26,7 @@ import java.awt.Taskbar
2926
import java.awt.desktop.QuitEvent
3027
import java.awt.desktop.QuitResponse
3128
import java.io.IOException
29+
import java.lang.foreign.*
3230
import java.util.*
3331
import java.util.concurrent.TimeUnit
3432
import javax.swing.JOptionPane
@@ -44,20 +42,48 @@ class MediathekGuiMac : MediathekGui {
4442
TimerPool.timerPool.schedule({ checkForCorrectArchitecture() }, 15, TimeUnit.SECONDS)
4543
}
4644

47-
@Throws(IllegalStateException::class)
48-
private fun getProcessorBrand(): String {
49-
val name = "machdep.cpu.brand_string" // Common name for processor type/brand on macOS
45+
@Throws(Throwable::class)
46+
private fun processorBrand(): String {
47+
val linker = Linker.nativeLinker()
48+
val sysctl = linker.defaultLookup().find("sysctlbyname").orElseThrow()
49+
val sysctlbyname = linker.downcallHandle(
50+
sysctl, FunctionDescriptor.of(
51+
ValueLayout.JAVA_INT, // return type
52+
ValueLayout.ADDRESS, // name (const char *)
53+
ValueLayout.ADDRESS, // oldp (void *)
54+
ValueLayout.ADDRESS, // oldlenp (size_t *)
55+
ValueLayout.ADDRESS, // newp (const void *)
56+
ValueLayout.JAVA_LONG // newlen (size_t)
57+
)
58+
)
59+
60+
val sysctlName = "machdep.cpu.brand_string"
61+
62+
Arena.ofConfined().use { arena ->
63+
// Allocate memory for the size output
64+
val sizePtr = arena.allocate(ValueLayout.JAVA_LONG)
65+
// First call: get the size of the result buffer
66+
var res = sysctlbyname.invoke(
67+
arena.allocateFrom(sysctlName), MemorySegment.NULL,
68+
sizePtr, MemorySegment.NULL, 0L
69+
) as Int
70+
if (res != 0) {
71+
throw RuntimeException("sysctlbyname failed to get size")
72+
}
5073

51-
// First call to get the size
52-
val size = IntByReference(0)
53-
var ret = SystemB.INSTANCE.sysctlbyname(name, null, size, null, 0)
54-
check(ret == 0) { "size query failed" }
74+
val len = sizePtr.get(ValueLayout.JAVA_LONG, 0)
75+
val buffer = arena.allocate(len)
76+
// Second call: get the actual value
77+
res = sysctlbyname.invoke(
78+
arena.allocateFrom(sysctlName), buffer, sizePtr, MemorySegment.NULL,
79+
0L
80+
) as Int
81+
if (res != 0) {
82+
throw RuntimeException("sysctlbyname failed to get value")
83+
}
5584

56-
val buffer = Memory(size.value.toLong())
57-
// Second call to get the actual value
58-
ret = SystemB.INSTANCE.sysctlbyname(name, buffer, size, null, 0)
59-
check(ret == 0) { "value query failed" }
60-
return buffer.getString(0)
85+
return buffer.getString(0)
86+
}
6187
}
6288

6389
/**
@@ -68,7 +94,7 @@ class MediathekGuiMac : MediathekGui {
6894
logger.trace("Checking for correct JVM architecture on macOS...")
6995
try {
7096
val jvmBinaryArch = SystemUtils.OS_ARCH.lowercase(Locale.getDefault())
71-
val isAppleSilicon = getProcessorBrand().lowercase().contains("apple")
97+
val isAppleSilicon = processorBrand().lowercase().contains("apple")
7298
//println("isAppleSilicon: $isAppleSilicon")
7399
val isJVMIntel = jvmBinaryArch == "x86_64" || jvmBinaryArch == "amd64"
74100
//println("isJVMIntel: $isJVMIntel")

0 commit comments

Comments
 (0)