Skip to content

Commit e2a611d

Browse files
committed
Refactor SharedVideoPlayer from interface to object with direct JNA mapping. Simplify native method calls across MacVideoPlayerState.
1 parent 379cdf0 commit e2a611d

File tree

2 files changed

+65
-66
lines changed

2 files changed

+65
-66
lines changed
Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,43 @@
11
package io.github.kdroidfilter.composemediaplayer.mac
22

3-
import com.sun.jna.Library
43
import com.sun.jna.Native
54
import com.sun.jna.Pointer
65

76
/**
8-
* JNA interface to the native library.
9-
* Includes new methods to retrieve frame rate information.
7+
* JNA direct mapping to the native library.
8+
* Includes methods to retrieve frame rate and metadata information.
109
*/
11-
internal interface SharedVideoPlayer : Library {
12-
fun createVideoPlayer(): Pointer?
13-
fun openUri(context: Pointer?, uri: String?)
14-
fun playVideo(context: Pointer?)
15-
fun pauseVideo(context: Pointer?)
16-
fun setVolume(context: Pointer?, volume: Float)
17-
fun getVolume(context: Pointer?): Float
18-
fun getLatestFrame(context: Pointer?): Pointer?
19-
fun getFrameWidth(context: Pointer?): Int
20-
fun getFrameHeight(context: Pointer?): Int
21-
fun getVideoFrameRate(context: Pointer?): Float
22-
fun getScreenRefreshRate(context: Pointer?): Float
23-
fun getCaptureFrameRate(context: Pointer?): Float
24-
fun getVideoDuration(context: Pointer?): Double
25-
fun getCurrentTime(context: Pointer?): Double
26-
fun seekTo(context: Pointer?, time: Double)
27-
fun disposeVideoPlayer(context: Pointer?)
28-
fun getLeftAudioLevel(context: Pointer?): Float
29-
fun getRightAudioLevel(context: Pointer?): Float
30-
fun setPlaybackSpeed(context: Pointer?, speed: Float)
31-
fun getPlaybackSpeed(context: Pointer?): Float
10+
internal object SharedVideoPlayer {
11+
init {
12+
// Register the native library for direct mapping
13+
Native.register("NativeVideoPlayer")
14+
}
3215

33-
// Metadata retrieval functions
34-
fun getVideoTitle(context: Pointer?): String?
35-
fun getVideoBitrate(context: Pointer?): Long
36-
fun getVideoMimeType(context: Pointer?): String?
37-
fun getAudioChannels(context: Pointer?): Int
38-
fun getAudioSampleRate(context: Pointer?): Int
16+
@JvmStatic external fun createVideoPlayer(): Pointer?
17+
@JvmStatic external fun openUri(context: Pointer?, uri: String?)
18+
@JvmStatic external fun playVideo(context: Pointer?)
19+
@JvmStatic external fun pauseVideo(context: Pointer?)
20+
@JvmStatic external fun setVolume(context: Pointer?, volume: Float)
21+
@JvmStatic external fun getVolume(context: Pointer?): Float
22+
@JvmStatic external fun getLatestFrame(context: Pointer?): Pointer?
23+
@JvmStatic external fun getFrameWidth(context: Pointer?): Int
24+
@JvmStatic external fun getFrameHeight(context: Pointer?): Int
25+
@JvmStatic external fun getVideoFrameRate(context: Pointer?): Float
26+
@JvmStatic external fun getScreenRefreshRate(context: Pointer?): Float
27+
@JvmStatic external fun getCaptureFrameRate(context: Pointer?): Float
28+
@JvmStatic external fun getVideoDuration(context: Pointer?): Double
29+
@JvmStatic external fun getCurrentTime(context: Pointer?): Double
30+
@JvmStatic external fun seekTo(context: Pointer?, time: Double)
31+
@JvmStatic external fun disposeVideoPlayer(context: Pointer?)
32+
@JvmStatic external fun getLeftAudioLevel(context: Pointer?): Float
33+
@JvmStatic external fun getRightAudioLevel(context: Pointer?): Float
34+
@JvmStatic external fun setPlaybackSpeed(context: Pointer?, speed: Float)
35+
@JvmStatic external fun getPlaybackSpeed(context: Pointer?): Float
3936

40-
companion object {
41-
val INSTANCE: SharedVideoPlayer =
42-
Native.load("NativeVideoPlayer", SharedVideoPlayer::class.java)
43-
}
37+
// Metadata retrieval functions
38+
@JvmStatic external fun getVideoTitle(context: Pointer?): String?
39+
@JvmStatic external fun getVideoBitrate(context: Pointer?): Long
40+
@JvmStatic external fun getVideoMimeType(context: Pointer?): String?
41+
@JvmStatic external fun getAudioChannels(context: Pointer?): Int
42+
@JvmStatic external fun getAudioSampleRate(context: Pointer?): Int
4443
}

mediaplayer/src/jvmMain/kotlin/io/github/kdroidfilter/composemediaplayer/mac/MacVideoPlayerState.kt

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
181181
private suspend fun initPlayer() = ioScope.launch {
182182
macLogger.d { "initPlayer() - Creating native player" }
183183
try {
184-
val ptr = SharedVideoPlayer.INSTANCE.createVideoPlayer()
184+
val ptr = SharedVideoPlayer.createVideoPlayer()
185185
if (ptr != null) {
186186
mainMutex.withLock { playerPtr = ptr }
187187
macLogger.d { "Native player created successfully" }
@@ -208,9 +208,9 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
208208
val ptr = mainMutex.withLock { playerPtr } ?: return
209209

210210
try {
211-
videoFrameRate = SharedVideoPlayer.INSTANCE.getVideoFrameRate(ptr)
212-
screenRefreshRate = SharedVideoPlayer.INSTANCE.getScreenRefreshRate(ptr)
213-
captureFrameRate = SharedVideoPlayer.INSTANCE.getCaptureFrameRate(ptr)
211+
videoFrameRate = SharedVideoPlayer.getVideoFrameRate(ptr)
212+
screenRefreshRate = SharedVideoPlayer.getScreenRefreshRate(ptr)
213+
captureFrameRate = SharedVideoPlayer.getCaptureFrameRate(ptr)
214214
macLogger.d { "Frame Rates - Video: $videoFrameRate, Screen: $screenRefreshRate, Capture: $captureFrameRate" }
215215
} catch (e: Exception) {
216216
if (e is CancellationException) throw e
@@ -316,7 +316,7 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
316316
// Release resources outside of the mutex lock
317317
ptrToDispose?.let {
318318
try {
319-
SharedVideoPlayer.INSTANCE.disposeVideoPlayer(it)
319+
SharedVideoPlayer.disposeVideoPlayer(it)
320320
} catch (e: Exception) {
321321
if (e is CancellationException) throw e
322322
macLogger.e { "Error disposing player: ${e.message}" }
@@ -334,7 +334,7 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
334334
val isPlayerNull = mainMutex.withLock { playerPtr == null }
335335

336336
if (isPlayerNull) {
337-
val ptr = SharedVideoPlayer.INSTANCE.createVideoPlayer()
337+
val ptr = SharedVideoPlayer.createVideoPlayer()
338338
if (ptr != null) {
339339
mainMutex.withLock { playerPtr = ptr }
340340
applyVolume()
@@ -365,7 +365,7 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
365365

366366
return try {
367367
// Open video asynchronously
368-
SharedVideoPlayer.INSTANCE.openUri(ptr, uri)
368+
SharedVideoPlayer.openUri(ptr, uri)
369369

370370
// Instead of directly calling `updateMetadata()`,
371371
// we poll until valid dimensions are available
@@ -390,8 +390,8 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
390390
*/
391391
private suspend fun pollDimensionsUntilReady(ptr: Pointer, maxAttempts: Int = 20) {
392392
for (attempt in 1..maxAttempts) {
393-
val width = SharedVideoPlayer.INSTANCE.getFrameWidth(ptr)
394-
val height = SharedVideoPlayer.INSTANCE.getFrameHeight(ptr)
393+
val width = SharedVideoPlayer.getFrameWidth(ptr)
394+
val height = SharedVideoPlayer.getFrameHeight(ptr)
395395

396396
if (width > 0 && height > 0) {
397397
macLogger.d { "Dimensions validated (w=$width, h=$height) after $attempt attempts" }
@@ -409,10 +409,10 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
409409
val ptr = mainMutex.withLock { playerPtr } ?: return
410410

411411
try {
412-
val width = SharedVideoPlayer.INSTANCE.getFrameWidth(ptr)
413-
val height = SharedVideoPlayer.INSTANCE.getFrameHeight(ptr)
414-
val duration = SharedVideoPlayer.INSTANCE.getVideoDuration(ptr).toLong()
415-
val frameRate = SharedVideoPlayer.INSTANCE.getVideoFrameRate(ptr)
412+
val width = SharedVideoPlayer.getFrameWidth(ptr)
413+
val height = SharedVideoPlayer.getFrameHeight(ptr)
414+
val duration = SharedVideoPlayer.getVideoDuration(ptr).toLong()
415+
val frameRate = SharedVideoPlayer.getVideoFrameRate(ptr)
416416

417417
// Calculate aspect ratio
418418
val newAspectRatio = if (width > 0 && height > 0) {
@@ -424,11 +424,11 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
424424
}
425425

426426
// Get additional metadata
427-
val title = SharedVideoPlayer.INSTANCE.getVideoTitle(ptr)
428-
val bitrate = SharedVideoPlayer.INSTANCE.getVideoBitrate(ptr)
429-
val mimeType = SharedVideoPlayer.INSTANCE.getVideoMimeType(ptr)
430-
val audioChannels = SharedVideoPlayer.INSTANCE.getAudioChannels(ptr)
431-
val audioSampleRate = SharedVideoPlayer.INSTANCE.getAudioSampleRate(ptr)
427+
val title = SharedVideoPlayer.getVideoTitle(ptr)
428+
val bitrate = SharedVideoPlayer.getVideoBitrate(ptr)
429+
val mimeType = SharedVideoPlayer.getVideoMimeType(ptr)
430+
val audioChannels = SharedVideoPlayer.getAudioChannels(ptr)
431+
val audioSampleRate = SharedVideoPlayer.getAudioSampleRate(ptr)
432432

433433
withContext(Dispatchers.Main) {
434434
// Update metadata
@@ -537,15 +537,15 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
537537
val ptr = mainMutex.withLock { playerPtr } ?: return
538538

539539
// Get frame dimensions
540-
val width = SharedVideoPlayer.INSTANCE.getFrameWidth(ptr)
541-
val height = SharedVideoPlayer.INSTANCE.getFrameHeight(ptr)
540+
val width = SharedVideoPlayer.getFrameWidth(ptr)
541+
val height = SharedVideoPlayer.getFrameHeight(ptr)
542542

543543
if (width <= 0 || height <= 0) {
544544
return
545545
}
546546

547547
// Get the latest frame to minimize mutex lock time
548-
val framePtr = SharedVideoPlayer.INSTANCE.getLatestFrame(ptr) ?: return
548+
val framePtr = SharedVideoPlayer.getLatestFrame(ptr) ?: return
549549

550550
// Create or reuse a buffered image on a compute thread
551551
val bufferedImage = withContext(Dispatchers.Default) {
@@ -599,8 +599,8 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
599599
try {
600600
val ptr = mainMutex.withLock { playerPtr }
601601
if (ptr != null) {
602-
val newLeft = SharedVideoPlayer.INSTANCE.getLeftAudioLevel(ptr)
603-
val newRight = SharedVideoPlayer.INSTANCE.getRightAudioLevel(ptr)
602+
val newLeft = SharedVideoPlayer.getLeftAudioLevel(ptr)
603+
val newRight = SharedVideoPlayer.getRightAudioLevel(ptr)
604604
// macLogger.d { "Audio levels fetched: L=$newLeft, R=$newRight" }
605605

606606
// Converts the linear level to a percentage on a logarithmic scale.
@@ -710,7 +710,7 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
710710
val ptr = mainMutex.withLock { playerPtr } ?: return
711711

712712
try {
713-
SharedVideoPlayer.INSTANCE.playVideo(ptr)
713+
SharedVideoPlayer.playVideo(ptr)
714714

715715
withContext(Dispatchers.Main) {
716716
isPlaying = true
@@ -737,7 +737,7 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
737737
val ptr = mainMutex.withLock { playerPtr } ?: return
738738

739739
try {
740-
SharedVideoPlayer.INSTANCE.pauseVideo(ptr)
740+
SharedVideoPlayer.pauseVideo(ptr)
741741

742742
withContext(Dispatchers.Main) {
743743
isPlaying = false
@@ -803,10 +803,10 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
803803
lastFrameUpdateTime = System.currentTimeMillis()
804804

805805
val ptr = mainMutex.withLock { playerPtr } ?: return
806-
SharedVideoPlayer.INSTANCE.seekTo(ptr, seekTime.toDouble())
806+
SharedVideoPlayer.seekTo(ptr, seekTime.toDouble())
807807

808808
if (isPlaying) {
809-
SharedVideoPlayer.INSTANCE.playVideo(ptr)
809+
SharedVideoPlayer.playVideo(ptr)
810810
// Reduce delay to update frame faster for local videos
811811
delay(10)
812812
updateFrameAsync()
@@ -854,7 +854,7 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
854854
ptrToDispose?.let {
855855
macLogger.d { "dispose() - Disposing native player" }
856856
try {
857-
SharedVideoPlayer.INSTANCE.disposeVideoPlayer(it)
857+
SharedVideoPlayer.disposeVideoPlayer(it)
858858
} catch (e: Exception) {
859859
if (e is CancellationException) throw e
860860
macLogger.e { "Error disposing player: ${e.message}" }
@@ -919,7 +919,7 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
919919
private suspend fun getPositionSafely(): Double {
920920
val ptr = mainMutex.withLock { playerPtr } ?: return 0.0
921921
return try {
922-
SharedVideoPlayer.INSTANCE.getCurrentTime(ptr)
922+
SharedVideoPlayer.getCurrentTime(ptr)
923923
} catch (e: Exception) {
924924
if (e is CancellationException) throw e
925925
macLogger.e { "Error getting position: ${e.message}" }
@@ -931,7 +931,7 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
931931
private suspend fun getDurationSafely(): Double {
932932
val ptr = mainMutex.withLock { playerPtr } ?: return 0.0
933933
return try {
934-
SharedVideoPlayer.INSTANCE.getVideoDuration(ptr)
934+
SharedVideoPlayer.getVideoDuration(ptr)
935935
} catch (e: Exception) {
936936
if (e is CancellationException) throw e
937937
macLogger.e { "Error getting duration: ${e.message}" }
@@ -948,7 +948,7 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
948948
mainMutex.withLock {
949949
playerPtr?.let { ptr ->
950950
try {
951-
SharedVideoPlayer.INSTANCE.setVolume(ptr, _volumeState.value)
951+
SharedVideoPlayer.setVolume(ptr, _volumeState.value)
952952
} catch (e: Exception) {
953953
if (e is CancellationException) throw e
954954
macLogger.e { "Error applying volume: ${e.message}" }
@@ -966,7 +966,7 @@ class MacVideoPlayerState : PlatformVideoPlayerState {
966966
mainMutex.withLock {
967967
playerPtr?.let { ptr ->
968968
try {
969-
SharedVideoPlayer.INSTANCE.setPlaybackSpeed(ptr, _playbackSpeedState.value)
969+
SharedVideoPlayer.setPlaybackSpeed(ptr, _playbackSpeedState.value)
970970
} catch (e: Exception) {
971971
if (e is CancellationException) throw e
972972
macLogger.e { "Error applying playback speed: ${e.message}" }

0 commit comments

Comments
 (0)