mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Beter end-of-file events
This commit is contained in:
parent
2ef095f73f
commit
b84166e2a5
5 changed files with 121 additions and 16 deletions
|
|
@ -170,6 +170,18 @@ object MPVLib {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun eventEndFile(
|
||||||
|
reason: Int,
|
||||||
|
error: Int,
|
||||||
|
) {
|
||||||
|
synchronized(observers) {
|
||||||
|
for (o in observers) {
|
||||||
|
o.eventEndFile(reason, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val log_observers = mutableListOf<LogObserver>()
|
private val log_observers = mutableListOf<LogObserver>()
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
|
@ -223,6 +235,11 @@ object MPVLib {
|
||||||
)
|
)
|
||||||
|
|
||||||
fun event(eventId: Int)
|
fun event(eventId: Int)
|
||||||
|
|
||||||
|
fun eventEndFile(
|
||||||
|
reason: Int,
|
||||||
|
error: Int,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LogObserver {
|
interface LogObserver {
|
||||||
|
|
@ -282,4 +299,36 @@ object MPVLib {
|
||||||
const val MPV_LOG_LEVEL_DEBUG: Int = 60
|
const val MPV_LOG_LEVEL_DEBUG: Int = 60
|
||||||
const val MPV_LOG_LEVEL_TRACE: Int = 70
|
const val MPV_LOG_LEVEL_TRACE: Int = 70
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object MpvEndFileReason {
|
||||||
|
const val MPV_END_FILE_REASON_EOF: Int = 0
|
||||||
|
const val MPV_END_FILE_REASON_STOP: Int = 2
|
||||||
|
const val MPV_END_FILE_REASON_QUIT: Int = 3
|
||||||
|
const val MPV_END_FILE_REASON_ERROR: Int = 4
|
||||||
|
const val MPV_END_FILE_REASON_REDIRECT: Int = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
object MpvError {
|
||||||
|
const val MPV_ERROR_SUCCESS = 0
|
||||||
|
const val MPV_ERROR_EVENT_QUEUE_FULL = -1
|
||||||
|
const val MPV_ERROR_NOMEM = -2
|
||||||
|
const val MPV_ERROR_UNINITIALIZED = -3
|
||||||
|
const val MPV_ERROR_INVALID_PARAMETER = -4
|
||||||
|
const val MPV_ERROR_OPTION_NOT_FOUND = -5
|
||||||
|
const val MPV_ERROR_OPTION_FORMAT = -6
|
||||||
|
const val MPV_ERROR_OPTION_ERROR = -7
|
||||||
|
const val MPV_ERROR_PROPERTY_NOT_FOUND = -8
|
||||||
|
const val MPV_ERROR_PROPERTY_FORMAT = -9
|
||||||
|
const val MPV_ERROR_PROPERTY_UNAVAILABLE = -10
|
||||||
|
const val MPV_ERROR_PROPERTY_ERROR = -11
|
||||||
|
const val MPV_ERROR_COMMAND = -12
|
||||||
|
const val MPV_ERROR_LOADING_FAILED = -13
|
||||||
|
const val MPV_ERROR_AO_INIT_FAILED = -14
|
||||||
|
const val MPV_ERROR_VO_INIT_FAILED = -15
|
||||||
|
const val MPV_ERROR_NOTHING_TO_PLAY = -16
|
||||||
|
const val MPV_ERROR_UNKNOWN_FORMAT = -17
|
||||||
|
const val MPV_ERROR_UNSUPPORTED = -18
|
||||||
|
const val MPV_ERROR_NOT_IMPLEMENTED = -19
|
||||||
|
const val MPV_ERROR_GENERIC = -20
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,9 @@ import androidx.media3.common.util.Util
|
||||||
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector
|
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector
|
||||||
import androidx.media3.exoplayer.trackselection.TrackSelector
|
import androidx.media3.exoplayer.trackselection.TrackSelector
|
||||||
import androidx.media3.exoplayer.upstream.DefaultBandwidthMeter
|
import androidx.media3.exoplayer.upstream.DefaultBandwidthMeter
|
||||||
|
import com.github.damontecres.wholphin.util.mpv.MPVLib.MpvEndFileReason.MPV_END_FILE_REASON_EOF
|
||||||
|
import com.github.damontecres.wholphin.util.mpv.MPVLib.MpvEndFileReason.MPV_END_FILE_REASON_ERROR
|
||||||
|
import com.github.damontecres.wholphin.util.mpv.MPVLib.MpvEndFileReason.MPV_END_FILE_REASON_STOP
|
||||||
import com.github.damontecres.wholphin.util.mpv.MPVLib.MpvEvent.MPV_EVENT_AUDIO_RECONFIG
|
import com.github.damontecres.wholphin.util.mpv.MPVLib.MpvEvent.MPV_EVENT_AUDIO_RECONFIG
|
||||||
import com.github.damontecres.wholphin.util.mpv.MPVLib.MpvEvent.MPV_EVENT_END_FILE
|
import com.github.damontecres.wholphin.util.mpv.MPVLib.MpvEvent.MPV_EVENT_END_FILE
|
||||||
import com.github.damontecres.wholphin.util.mpv.MPVLib.MpvEvent.MPV_EVENT_FILE_LOADED
|
import com.github.damontecres.wholphin.util.mpv.MPVLib.MpvEvent.MPV_EVENT_FILE_LOADED
|
||||||
|
|
@ -83,6 +86,7 @@ class MpvPlayer(
|
||||||
private var positionMs: Long = -1L
|
private var positionMs: Long = -1L
|
||||||
private var playbackState: Int = STATE_READY
|
private var playbackState: Int = STATE_READY
|
||||||
|
|
||||||
|
@Volatile
|
||||||
var isReleased = false
|
var isReleased = false
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
|
@ -277,9 +281,15 @@ class MpvPlayer(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stop() {
|
override fun stop() {
|
||||||
throwIfReleased()
|
|
||||||
if (DEBUG) Timber.v("stop")
|
if (DEBUG) Timber.v("stop")
|
||||||
|
throwIfReleased()
|
||||||
pause()
|
pause()
|
||||||
|
mediaItem = null
|
||||||
|
positionMs = -1L
|
||||||
|
durationMs = 0L
|
||||||
|
playbackState = STATE_IDLE
|
||||||
|
notifyListeners(EVENT_IS_PLAYING_CHANGED) { onIsPlayingChanged(false) }
|
||||||
|
notifyListeners(EVENT_PLAYBACK_STATE_CHANGED) { onPlaybackStateChanged(STATE_IDLE) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun release() {
|
override fun release() {
|
||||||
|
|
@ -294,6 +304,7 @@ class MpvPlayer(
|
||||||
|
|
||||||
override fun getCurrentTracks(): Tracks {
|
override fun getCurrentTracks(): Tracks {
|
||||||
if (DEBUG) Timber.v("getCurrentTracks")
|
if (DEBUG) Timber.v("getCurrentTracks")
|
||||||
|
throwIfReleased()
|
||||||
return getTracks()
|
return getTracks()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,6 +318,7 @@ class MpvPlayer(
|
||||||
|
|
||||||
override fun setTrackSelectionParameters(parameters: TrackSelectionParameters) {
|
override fun setTrackSelectionParameters(parameters: TrackSelectionParameters) {
|
||||||
Timber.v("TrackSelection: setTrackSelectionParameters %s", parameters)
|
Timber.v("TrackSelection: setTrackSelectionParameters %s", parameters)
|
||||||
|
throwIfReleased()
|
||||||
val tracks = getTracks()
|
val tracks = getTracks()
|
||||||
if (C.TRACK_TYPE_TEXT in parameters.disabledTrackTypes) {
|
if (C.TRACK_TYPE_TEXT in parameters.disabledTrackTypes) {
|
||||||
// Subtitles disabled
|
// Subtitles disabled
|
||||||
|
|
@ -352,7 +364,7 @@ class MpvPlayer(
|
||||||
|
|
||||||
override fun getMediaMetadata(): MediaMetadata {
|
override fun getMediaMetadata(): MediaMetadata {
|
||||||
if (DEBUG) Timber.v("getMediaMetadata")
|
if (DEBUG) Timber.v("getMediaMetadata")
|
||||||
return mediaItem!!.mediaMetadata
|
return MediaMetadata.EMPTY
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPlaylistMetadata(): MediaMetadata {
|
override fun getPlaylistMetadata(): MediaMetadata {
|
||||||
|
|
@ -408,6 +420,7 @@ class MpvPlayer(
|
||||||
|
|
||||||
override fun getTotalBufferedDuration(): Long {
|
override fun getTotalBufferedDuration(): Long {
|
||||||
if (DEBUG) Timber.v("getTotalBufferedDuration")
|
if (DEBUG) Timber.v("getTotalBufferedDuration")
|
||||||
|
if (isReleased) return 0
|
||||||
return MPVLib.getPropertyDouble("demuxer-cache-duration")?.seconds?.inWholeMilliseconds ?: 0
|
return MPVLib.getPropertyDouble("demuxer-cache-duration")?.seconds?.inWholeMilliseconds ?: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -426,8 +439,7 @@ class MpvPlayer(
|
||||||
|
|
||||||
override fun getAudioAttributes(): AudioAttributes = throw UnsupportedOperationException()
|
override fun getAudioAttributes(): AudioAttributes = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun setVolume(volume: Float) {
|
override fun setVolume(volume: Float): Unit = throw UnsupportedOperationException()
|
||||||
}
|
|
||||||
|
|
||||||
override fun getVolume(): Float = 1f
|
override fun getVolume(): Float = 1f
|
||||||
|
|
||||||
|
|
@ -622,16 +634,7 @@ class MpvPlayer(
|
||||||
|
|
||||||
MPV_EVENT_END_FILE -> {
|
MPV_EVENT_END_FILE -> {
|
||||||
Timber.d("event: MPV_EVENT_END_FILE")
|
Timber.d("event: MPV_EVENT_END_FILE")
|
||||||
notifyListeners(EVENT_IS_PLAYING_CHANGED) { onIsPlayingChanged(false) }
|
// Handled by eventEndFile
|
||||||
|
|
||||||
val curPos = MPVLib.getPropertyDouble("time-pos/full")
|
|
||||||
Timber.v("MPV_EVENT_END_FILE: positionMs=$positionMs, durationMs=$durationMs, curPos=$curPos")
|
|
||||||
if (positionMs >= (durationMs - 1000) && curPos == null) {
|
|
||||||
playbackState = STATE_ENDED
|
|
||||||
notifyListeners(EVENT_PLAYBACK_STATE_CHANGED) {
|
|
||||||
onPlaybackStateChanged(STATE_ENDED)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
|
|
@ -640,6 +643,42 @@ class MpvPlayer(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun eventEndFile(
|
||||||
|
reason: Int,
|
||||||
|
error: Int,
|
||||||
|
) {
|
||||||
|
Timber.d("MPV_EVENT_END_FILE: %s %s", reason, error)
|
||||||
|
notifyListeners(EVENT_IS_PLAYING_CHANGED) { onIsPlayingChanged(false) }
|
||||||
|
when (reason) {
|
||||||
|
MPV_END_FILE_REASON_EOF -> {
|
||||||
|
notifyListeners(EVENT_PLAYBACK_STATE_CHANGED) {
|
||||||
|
onPlaybackStateChanged(STATE_ENDED)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MPV_END_FILE_REASON_STOP -> {
|
||||||
|
// User initiated (eg stop, play next, etc)
|
||||||
|
}
|
||||||
|
|
||||||
|
MPV_END_FILE_REASON_ERROR -> {
|
||||||
|
Timber.e("libmpv error, error=%s", error)
|
||||||
|
notifyListeners(EVENT_PLAYER_ERROR) {
|
||||||
|
onPlayerError(
|
||||||
|
PlaybackException(
|
||||||
|
"libmpv error",
|
||||||
|
null,
|
||||||
|
error,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadFile() {
|
private fun loadFile() {
|
||||||
val url = mediaItem!!.localConfiguration?.uri.toString()
|
val url = mediaItem!!.localConfiguration?.uri.toString()
|
||||||
if (startPositionMs > 0) {
|
if (startPositionMs > 0) {
|
||||||
|
|
@ -743,8 +782,14 @@ class MpvPlayer(
|
||||||
}
|
}
|
||||||
|
|
||||||
var subtitleDelay: Double
|
var subtitleDelay: Double
|
||||||
get() = MPVLib.getPropertyDouble("sub-delay") ?: 0.0
|
get() {
|
||||||
set(value) = MPVLib.setPropertyDouble("sub-delay", value)
|
throwIfReleased()
|
||||||
|
return MPVLib.getPropertyDouble("sub-delay") ?: 0.0
|
||||||
|
}
|
||||||
|
set(value) {
|
||||||
|
throwIfReleased()
|
||||||
|
MPVLib.setPropertyDouble("sub-delay", value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MPVLib.setPropertyColor(
|
fun MPVLib.setPropertyColor(
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,11 @@ static void sendEventToJava(JNIEnv *env, int event)
|
||||||
env->CallStaticVoidMethod(mpv_MPVLib, mpv_MPVLib_event, event);
|
env->CallStaticVoidMethod(mpv_MPVLib, mpv_MPVLib_event, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sendEndFileEventToJava(JNIEnv *env, mpv_event_end_file *event)
|
||||||
|
{
|
||||||
|
env->CallStaticVoidMethod(mpv_MPVLib, mpv_MPVLib_end_file_event, event->reason, event->error);
|
||||||
|
}
|
||||||
|
|
||||||
static void sendLogMessageToJava(JNIEnv *env, mpv_event_log_message *msg)
|
static void sendLogMessageToJava(JNIEnv *env, mpv_event_log_message *msg)
|
||||||
{
|
{
|
||||||
// filter the most obvious cases of invalid utf-8, since Java would choke on it
|
// filter the most obvious cases of invalid utf-8, since Java would choke on it
|
||||||
|
|
@ -79,6 +84,7 @@ void *event_thread(void *arg)
|
||||||
mpv_event *mp_event;
|
mpv_event *mp_event;
|
||||||
mpv_event_property *mp_property = NULL;
|
mpv_event_property *mp_property = NULL;
|
||||||
mpv_event_log_message *msg = NULL;
|
mpv_event_log_message *msg = NULL;
|
||||||
|
mpv_event_end_file *mp_end_file = NULL;
|
||||||
|
|
||||||
mp_event = mpv_wait_event(g_mpv, -1.0);
|
mp_event = mpv_wait_event(g_mpv, -1.0);
|
||||||
|
|
||||||
|
|
@ -98,6 +104,9 @@ void *event_thread(void *arg)
|
||||||
mp_property = (mpv_event_property*)mp_event->data;
|
mp_property = (mpv_event_property*)mp_event->data;
|
||||||
sendPropertyUpdateToJava(env, mp_property);
|
sendPropertyUpdateToJava(env, mp_property);
|
||||||
break;
|
break;
|
||||||
|
case MPV_EVENT_END_FILE:
|
||||||
|
mp_end_file = (mpv_event_end_file*)mp_event->data;
|
||||||
|
sendEndFileEventToJava(env, mp_end_file);
|
||||||
default:
|
default:
|
||||||
ALOGV("event: %s\n", mpv_event_name(mp_event->event_id));
|
ALOGV("event: %s\n", mpv_event_name(mp_event->event_id));
|
||||||
sendEventToJava(env, mp_event->event_id);
|
sendEventToJava(env, mp_event->event_id);
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ void init_methods_cache(JNIEnv *env)
|
||||||
mpv_MPVLib_eventProperty_Sd = env->GetStaticMethodID(mpv_MPVLib, "eventProperty", "(Ljava/lang/String;D)V"); // eventProperty(String, double)
|
mpv_MPVLib_eventProperty_Sd = env->GetStaticMethodID(mpv_MPVLib, "eventProperty", "(Ljava/lang/String;D)V"); // eventProperty(String, double)
|
||||||
mpv_MPVLib_eventProperty_SS = env->GetStaticMethodID(mpv_MPVLib, "eventProperty", "(Ljava/lang/String;Ljava/lang/String;)V"); // eventProperty(String, String)
|
mpv_MPVLib_eventProperty_SS = env->GetStaticMethodID(mpv_MPVLib, "eventProperty", "(Ljava/lang/String;Ljava/lang/String;)V"); // eventProperty(String, String)
|
||||||
mpv_MPVLib_event = env->GetStaticMethodID(mpv_MPVLib, "event", "(I)V"); // event(int)
|
mpv_MPVLib_event = env->GetStaticMethodID(mpv_MPVLib, "event", "(I)V"); // event(int)
|
||||||
|
mpv_MPVLib_end_file_event = env->GetStaticMethodID(mpv_MPVLib, "eventEndFile", "(II)V"); // eventEndFile(int, int)
|
||||||
mpv_MPVLib_logMessage_SiS = env->GetStaticMethodID(mpv_MPVLib, "logMessage", "(Ljava/lang/String;ILjava/lang/String;)V"); // logMessage(String, int, String)
|
mpv_MPVLib_logMessage_SiS = env->GetStaticMethodID(mpv_MPVLib, "logMessage", "(Ljava/lang/String;ILjava/lang/String;)V"); // logMessage(String, int, String)
|
||||||
#undef FIND_CLASS
|
#undef FIND_CLASS
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,4 +26,5 @@ UTIL_EXTERN jmethodID mpv_MPVLib_eventProperty_S,
|
||||||
mpv_MPVLib_eventProperty_Sd,
|
mpv_MPVLib_eventProperty_Sd,
|
||||||
mpv_MPVLib_eventProperty_SS,
|
mpv_MPVLib_eventProperty_SS,
|
||||||
mpv_MPVLib_event,
|
mpv_MPVLib_event,
|
||||||
|
mpv_MPVLib_end_file_event,
|
||||||
mpv_MPVLib_logMessage_SiS;
|
mpv_MPVLib_logMessage_SiS;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue