Commit 92197838 authored by Thomas's avatar Thomas
Browse files

- Fix #1371 Fix #1296 add volume slider and playback speed controls to video player

parent ee41339e
Loading
Loading
Loading
Loading
+102 −0
Original line number Diff line number Diff line
@@ -26,7 +26,10 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -37,6 +40,7 @@ import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.media3.common.MediaItem;
import androidx.media3.common.PlaybackException;
import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.Player;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.datasource.DataSource;
@@ -45,6 +49,8 @@ import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.source.ProgressiveMediaSource;
import androidx.preference.PreferenceManager;

import com.google.android.material.slider.Slider;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
@@ -80,6 +86,8 @@ public class FragmentMedia extends Fragment {
    private int mediaVideoTranslateAccessibilityActionId = 0;

    private boolean visible = false;
    private float currentVolume = 1.0f;
    private float currentSpeed = 1.0f;

    public FragmentMedia() {
    }
@@ -348,6 +356,7 @@ public class FragmentMedia extends Fragment {
        }
        binding.mediaVideo.setPlayer(player);
        binding.controls.setPlayer(player);
        setupExtraControls();
        binding.loader.setVisibility(View.GONE);
        binding.mediaPicture.setVisibility(View.GONE);
        player.setMediaSource(videoSource);
@@ -466,6 +475,99 @@ public class FragmentMedia extends Fragment {
        });
    }

    private void setupExtraControls() {
        if (binding == null || player == null) {
            return;
        }
        ImageButton volumeIcon = binding.controls.findViewById(R.id.exo_volume_icon);
        Slider volumeSlider = binding.controls.findViewById(R.id.exo_volume_slider);
        TextView playbackSpeed = binding.controls.findViewById(R.id.exo_playback_speed);

        if (volumeSlider != null) {
            volumeSlider.setValue(currentVolume * 100);
            volumeSlider.addOnChangeListener((slider, value, fromUser) -> {
                if (fromUser && player != null) {
                    currentVolume = value / 100f;
                    player.setVolume(currentVolume);
                    updateVolumeIcon(volumeIcon);
                }
            });
        }

        if (volumeIcon != null) {
            volumeIcon.setOnClickListener(v -> {
                if (player == null || volumeSlider == null) {
                    return;
                }
                if (currentVolume > 0) {
                    currentVolume = 0f;
                } else {
                    currentVolume = 1.0f;
                }
                player.setVolume(currentVolume);
                volumeSlider.setValue(currentVolume * 100);
                updateVolumeIcon(volumeIcon);
            });
        }

        if (playbackSpeed != null) {
            updateSpeedText(playbackSpeed);
            playbackSpeed.setOnClickListener(v -> showSpeedMenu(playbackSpeed));
        }
    }

    private void updateVolumeIcon(ImageButton volumeIcon) {
        if (volumeIcon == null) {
            return;
        }
        if (currentVolume == 0) {
            volumeIcon.setImageResource(R.drawable.ic_baseline_volume_mute_24);
        } else {
            volumeIcon.setImageResource(R.drawable.ic_baseline_volume_up_24);
        }
    }

    private void updateSpeedText(TextView playbackSpeed) {
        if (playbackSpeed == null) {
            return;
        }
        if (currentSpeed == 1.0f) {
            playbackSpeed.setText(getString(R.string.normal));
        } else if (currentSpeed == (int) currentSpeed) {
            playbackSpeed.setText(String.format("%dx", (int) currentSpeed));
        } else {
            playbackSpeed.setText(String.format("%sx", currentSpeed));
        }
    }

    private void showSpeedMenu(TextView playbackSpeed) {
        if (!isAdded() || getContext() == null) {
            return;
        }
        PopupMenu popup = new PopupMenu(requireContext(), playbackSpeed);
        float[] speeds = {0.25f, 0.5f, 0.75f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f};
        for (int i = 0; i < speeds.length; i++) {
            String label;
            if (speeds[i] == 1.0f) {
                label = getString(R.string.normal);
            } else if (speeds[i] == (int) speeds[i]) {
                label = String.format("%dx", (int) speeds[i]);
            } else {
                label = String.format("%sx", speeds[i]);
            }
            popup.getMenu().add(0, i, i, label);
        }
        popup.setOnMenuItemClickListener(item -> {
            int index = item.getItemId();
            if (index >= 0 && index < speeds.length && player != null) {
                currentSpeed = speeds[index];
                player.setPlaybackParameters(new PlaybackParameters(currentSpeed));
                updateSpeedText(playbackSpeed);
            }
            return true;
        });
        popup.show();
    }

    private void enableSliding(boolean enable) {
        if (enable && !swipeEnabled) {
+11 −0
Original line number Diff line number Diff line
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:autoMirrored="true"
    android:tint="?attr/colorControlNormal"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path
        android:fillColor="@android:color/white"
        android:pathData="M3,9v6h4l5,5V4L7,9H3zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM14,3.23v2.06c2.89,0.86 5,3.54 5,6.71s-2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77s-2.99,-7.86 -7,-8.77z" />
</vector>
+47 −1
Original line number Diff line number Diff line
@@ -48,4 +48,50 @@
            android:textSize="12sp" />

    </androidx.appcompat.widget.LinearLayoutCompat>

    <androidx.appcompat.widget.LinearLayoutCompat
        android:id="@+id/extra_controls"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:paddingStart="8dp"
        android:paddingEnd="8dp">

        <ImageButton
            android:id="@+id/exo_volume_icon"
            android:layout_width="32dp"
            android:layout_height="32dp"
            android:background="?attr/selectableItemBackgroundBorderless"
            android:contentDescription="@string/volume"
            android:src="@drawable/ic_baseline_volume_up_24"
            app:tint="?colorPrimary" />

        <com.google.android.material.slider.Slider
            android:id="@+id/exo_volume_slider"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:valueFrom="0"
            android:valueTo="100"
            android:value="100"
            android:contentDescription="@string/volume"
            app:thumbColor="?colorPrimary"
            app:trackColorActive="?colorPrimary"
            app:trackColorInactive="?colorSecondaryContainer" />

        <TextView
            android:id="@+id/exo_playback_speed"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:background="?attr/selectableItemBackgroundBorderless"
            android:padding="8dp"
            android:text="1x"
            android:textColor="?colorPrimary"
            android:textSize="14sp"
            android:textStyle="bold" />

    </androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
    <string name="open_with">Open with</string>
    <string name="validate">Validate</string>
    <string name="media">Media</string>
    <string name="volume">Volume</string>
    <string name="plus_media">+%d media</string>
    <string name="share_with">Share with</string>
    <string name="shared_via">Shared via Fedilab</string>