diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 69b0bc407..70f4d0237 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,8 +13,8 @@ android { targetSdkVersion(29) // Release version - versionCode = 909 - versionName = "0.11.4" + versionCode = 910 + versionName = "0.11.5" } compileOptions { @@ -67,7 +67,7 @@ dependencies { // Media players implementation("com.amazon.android:exoplayer:2.11.3") - implementation("org.videolan.android:libvlc-all:3.2.5") + implementation("org.videolan.android:libvlc-all:3.3.2") // Image utility implementation("com.squareup.picasso:picasso:2.3.2") diff --git a/app/src/main/java/org/jellyfin/androidtv/base/KeyboardFocusChangeListener.kt b/app/src/main/java/org/jellyfin/androidtv/base/KeyboardFocusChangeListener.kt new file mode 100644 index 000000000..ce732be25 --- /dev/null +++ b/app/src/main/java/org/jellyfin/androidtv/base/KeyboardFocusChangeListener.kt @@ -0,0 +1,14 @@ +package org.jellyfin.androidtv.ui.shared + +import android.content.Context +import android.view.View +import android.view.inputmethod.InputMethodManager + +class KeyboardFocusChangeListener : View.OnFocusChangeListener { + override fun onFocusChange(v : View, hasFocus : Boolean) { + (v.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).apply { + if (!hasFocus) hideSoftInputFromWindow(v.windowToken, 0) + else showSoftInput(v, 0) + } + } +} diff --git a/app/src/main/java/org/jellyfin/androidtv/playback/MediaManager.java b/app/src/main/java/org/jellyfin/androidtv/playback/MediaManager.java index 21976ecb9..3224490eb 100644 --- a/app/src/main/java/org/jellyfin/androidtv/playback/MediaManager.java +++ b/app/src/main/java/org/jellyfin/androidtv/playback/MediaManager.java @@ -227,8 +227,14 @@ public class MediaManager { mLibVLC = new LibVLC(TvApp.getApplication(), options); mVlcPlayer = new org.videolan.libvlc.MediaPlayer(mLibVLC); - mVlcPlayer.setAudioOutput(Utils.downMixAudio() ? "opensles_android" : "android_audiotrack"); - mVlcPlayer.setAudioOutputDevice("hdmi"); + if(!Utils.downMixAudio()) { + mVlcPlayer.setAudioOutput("android_audiotrack"); + mVlcPlayer.setAudioDigitalOutputEnabled(true); + } else { + mVlcPlayer.setAudioOutput("opensles_android"); + mVlcPlayer.setAudioOutputDevice("hdmi"); + } + mVlcHandler.setOnProgressListener(new PlaybackListener() { @Override diff --git a/app/src/main/java/org/jellyfin/androidtv/playback/VideoManager.java b/app/src/main/java/org/jellyfin/androidtv/playback/VideoManager.java index cca73a127..daaa36d9c 100644 --- a/app/src/main/java/org/jellyfin/androidtv/playback/VideoManager.java +++ b/app/src/main/java/org/jellyfin/androidtv/playback/VideoManager.java @@ -31,9 +31,9 @@ import org.jellyfin.androidtv.util.Utils; import org.jellyfin.apiclient.model.dto.MediaSourceInfo; import org.jellyfin.apiclient.model.entities.MediaStream; import org.jellyfin.apiclient.model.entities.MediaStreamType; -import org.videolan.libvlc.IVLCVout; import org.videolan.libvlc.LibVLC; import org.videolan.libvlc.Media; +import org.videolan.libvlc.interfaces.IVLCVout; import java.util.ArrayList; import java.util.List; @@ -105,6 +105,7 @@ public class VideoManager implements IVLCVout.OnNewVideoLayoutListener { } }).build(); + mExoPlayerView = view.findViewById(R.id.exoPlayerView); mExoPlayerView.setPlayer(mExoPlayer); mExoPlayer.addListener(new Player.EventListener() { @@ -437,16 +438,25 @@ public class VideoManager implements IVLCVout.OnNewVideoLayoutListener { public long getAudioDelay() { return mVlcPlayer != null ? mVlcPlayer.getAudioDelay() / 1000 : 0;} public void setCompatibleAudio() { - if (!nativeMode) { - mVlcPlayer.setAudioOutput("opensles_android"); - mVlcPlayer.setAudioOutputDevice("hdmi"); - } + if (!nativeMode) { + mVlcPlayer.setAudioOutput("opensles_android"); + mVlcPlayer.setAudioOutputDevice("hdmi"); + } } public void setAudioMode() { if (!nativeMode) { - mVlcPlayer.setAudioOutput(Utils.downMixAudio() ? "opensles_android" : "android_audiotrack"); - mVlcPlayer.setAudioOutputDevice("hdmi"); + setVlcAudioOptions(); + } + } + + private void setVlcAudioOptions() { + + if(!Utils.downMixAudio()) { + mVlcPlayer.setAudioOutput("android_audiotrack"); + mVlcPlayer.setAudioDigitalOutputEnabled(true); + } else { + setCompatibleAudio(); } } @@ -502,8 +512,7 @@ public class VideoManager implements IVLCVout.OnNewVideoLayoutListener { TvApp.getApplication().getLogger().Info("Network buffer set to %d", buffer); mVlcPlayer = new org.videolan.libvlc.MediaPlayer(mLibVLC); - mVlcPlayer.setAudioOutput(Utils.downMixAudio() ? "opensles_android" : "android_audiotrack"); - mVlcPlayer.setAudioOutputDevice("hdmi"); + setVlcAudioOptions(); mSurfaceHolder.addCallback(mSurfaceCallback); diff --git a/app/src/main/java/org/jellyfin/androidtv/util/ImageUtils.java b/app/src/main/java/org/jellyfin/androidtv/util/ImageUtils.java index 823c4faa5..39862a1c8 100644 --- a/app/src/main/java/org/jellyfin/androidtv/util/ImageUtils.java +++ b/app/src/main/java/org/jellyfin/androidtv/util/ImageUtils.java @@ -45,6 +45,9 @@ public class ImageUtils { } } + if (item.getBaseItemType() == BaseItemType.UserView && item.getHasPrimaryImage()) + return ImageUtils.ASPECT_RATIO_16_9; + return item.getPrimaryImageAspectRatio() != null ? item.getPrimaryImageAspectRatio() : ASPECT_RATIO_7_9; } diff --git a/app/src/main/java/org/jellyfin/androidtv/util/ProfileHelper.java b/app/src/main/java/org/jellyfin/androidtv/util/ProfileHelper.java index 4cd5b430d..d8266d0b1 100644 --- a/app/src/main/java/org/jellyfin/androidtv/util/ProfileHelper.java +++ b/app/src/main/java/org/jellyfin/androidtv/util/ProfileHelper.java @@ -172,7 +172,6 @@ public class ProfileHelper { ContainerTypes.OGM, ContainerTypes.OGV, ContainerTypes.M2V, - ContainerTypes.AVI, ContainerTypes.MPG, ContainerTypes.MPEG, ContainerTypes.MP4, @@ -236,33 +235,24 @@ public class ProfileHelper { new ProfileCondition(ProfileConditionType.GreaterThanEqual, ProfileConditionValue.RefFrames, "2"), }); - ContainerProfile videoContainerProfile = new ContainerProfile(); - videoContainerProfile.setType(DlnaProfileType.Video); - videoContainerProfile.setContainer(ContainerTypes.AVI); - videoContainerProfile.setConditions(new ProfileCondition[] - { - new ProfileCondition(ProfileConditionType.NotEquals, ProfileConditionValue.VideoCodecTag, "xvid"), - }); - CodecProfile videoAudioCodecProfile = new CodecProfile(); videoAudioCodecProfile.setType(CodecType.VideoAudio); - videoAudioCodecProfile.setConditions(new ProfileCondition[]{new ProfileCondition(ProfileConditionType.LessThanEqual, ProfileConditionValue.AudioChannels, "6")}); + videoAudioCodecProfile.setConditions(new ProfileCondition[]{new ProfileCondition(ProfileConditionType.LessThanEqual, ProfileConditionValue.AudioChannels, "8")}); profile.setCodecProfiles(new CodecProfile[]{getHevcProfile(), h264MainProfile, videoAudioCodecProfile}); - profile.setContainerProfiles(new ContainerProfile[] {videoContainerProfile}); profile.setSubtitleProfiles(new SubtitleProfile[]{ - getSubtitleProfile("srt", SubtitleDeliveryMethod.External), - getSubtitleProfile("srt", SubtitleDeliveryMethod.Embed), - getSubtitleProfile("subrip", SubtitleDeliveryMethod.Embed), - getSubtitleProfile("ass", SubtitleDeliveryMethod.Embed), - getSubtitleProfile("ssa", SubtitleDeliveryMethod.Embed), - getSubtitleProfile("pgs", SubtitleDeliveryMethod.Embed), - getSubtitleProfile("pgssub", SubtitleDeliveryMethod.Embed), - getSubtitleProfile("dvdsub", SubtitleDeliveryMethod.Embed), - getSubtitleProfile("vtt", SubtitleDeliveryMethod.Embed), - getSubtitleProfile("sub", SubtitleDeliveryMethod.Embed), - getSubtitleProfile("smi", SubtitleDeliveryMethod.Embed), - getSubtitleProfile("idx", SubtitleDeliveryMethod.Embed) + getSubtitleProfile("srt", SubtitleDeliveryMethod.External), + getSubtitleProfile("srt", SubtitleDeliveryMethod.Embed), + getSubtitleProfile("subrip", SubtitleDeliveryMethod.Embed), + getSubtitleProfile("ass", SubtitleDeliveryMethod.Embed), + getSubtitleProfile("ssa", SubtitleDeliveryMethod.Embed), + getSubtitleProfile("pgs", SubtitleDeliveryMethod.Embed), + getSubtitleProfile("pgssub", SubtitleDeliveryMethod.Embed), + getSubtitleProfile("dvdsub", SubtitleDeliveryMethod.Embed), + getSubtitleProfile("vtt", SubtitleDeliveryMethod.Embed), + getSubtitleProfile("sub", SubtitleDeliveryMethod.Embed), + getSubtitleProfile("smi", SubtitleDeliveryMethod.Embed), + getSubtitleProfile("idx", SubtitleDeliveryMethod.Embed) }); } diff --git a/app/src/main/java/org/jellyfin/androidtv/util/apiclient/AuthenticationHelper.java b/app/src/main/java/org/jellyfin/androidtv/util/apiclient/AuthenticationHelper.java index cf381e6e2..9e9a4e49b 100644 --- a/app/src/main/java/org/jellyfin/androidtv/util/apiclient/AuthenticationHelper.java +++ b/app/src/main/java/org/jellyfin/androidtv/util/apiclient/AuthenticationHelper.java @@ -16,6 +16,7 @@ import org.jellyfin.androidtv.model.LogonCredentials; import org.jellyfin.androidtv.startup.SelectServerActivity; import org.jellyfin.androidtv.startup.SelectUserActivity; import org.jellyfin.androidtv.util.DelayedMessage; +import org.jellyfin.androidtv.ui.shared.KeyboardFocusChangeListener; import org.jellyfin.androidtv.util.Utils; import java.io.IOException; @@ -39,6 +40,7 @@ public class AuthenticationHelper { final EditText address = new EditText(activity); address.setHint(activity.getString(R.string.lbl_ip_hint)); address.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI); + address.setOnFocusChangeListener(new KeyboardFocusChangeListener()); new AlertDialog.Builder(activity) .setTitle(activity.getString(R.string.lbl_enter_server_address)) .setMessage(activity.getString(R.string.lbl_valid_server_address)) @@ -61,6 +63,7 @@ public class AuthenticationHelper { public static void enterManualUser(final Activity activity) { final EditText userName = new EditText(activity); userName.setInputType(InputType.TYPE_CLASS_TEXT); + userName.setOnFocusChangeListener(new KeyboardFocusChangeListener()); new AlertDialog.Builder(activity) .setTitle(activity.getString(R.string.lbl_enter_user_name)) .setView(userName) @@ -74,6 +77,7 @@ public class AuthenticationHelper { TvApp.getApplication().getLogger().Debug("Entered user: %s", userValue); final EditText userPw = new EditText(activity); userPw.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); + userPw.setOnFocusChangeListener(new KeyboardFocusChangeListener()); new AlertDialog.Builder(activity) .setTitle(activity.getString(R.string.lbl_enter_user_pw)) .setView(userPw)