diff --git a/src/main/java/eu/siacs/conversations/ui/service/AudioPlayer.java b/src/main/java/eu/siacs/conversations/ui/service/AudioPlayer.java index 07507c77d..d5f78ad0c 100644 --- a/src/main/java/eu/siacs/conversations/ui/service/AudioPlayer.java +++ b/src/main/java/eu/siacs/conversations/ui/service/AudioPlayer.java @@ -43,8 +43,10 @@ public class AudioPlayer private static final int REFRESH_INTERVAL = 250; private static final Object LOCK = new Object(); + private static final float[] SPEED_STEPS = {1.0f, 1.25f, 1.5f, 2.0f}; private static MediaPlayer player = null; private static Message currentlyPlayingMessage = null; + private static int currentSpeedIndex = 0; private static PowerManager.WakeLock wakeLock; private final MessageAdapter messageAdapter; private final WeakReferenceSet audioPlayerLayouts = new WeakReferenceSet<>(); @@ -118,6 +120,8 @@ private boolean init(final ViewHolder viewHolder, final Message message) { viewHolder.progress.setThumbTintList(color); viewHolder.progress.setProgressTintList(color); viewHolder.playPause.setOnClickListener(this); + viewHolder.playbackSpeed.setOnClickListener(this); + updateSpeedButton(viewHolder); final Context context = viewHolder.playPause.getContext(); if (message == currentlyPlayingMessage) { if (AudioPlayer.player != null && AudioPlayer.player.isPlaying()) { @@ -146,6 +150,10 @@ public synchronized void onClick(View v) { synchronized (LOCK) { startStop((MaterialButton) v); } + } else if (v.getId() == R.id.playback_speed) { + synchronized (LOCK) { + cycleSpeed(); + } } } @@ -411,6 +419,7 @@ public void onSensorChanged(SensorEvent event) { currentlyPlayingMessage, streamType == AudioManager.STREAM_VOICE_CALL, progress); + applySpeed(); } } catch (Exception e) { Log.w(Config.LOGTAG, e); @@ -439,6 +448,37 @@ private void releaseProximityWakeLock() { messageAdapter.setVolumeControl(AudioManager.STREAM_MUSIC); } + private void cycleSpeed() { + currentSpeedIndex = (currentSpeedIndex + 1) % SPEED_STEPS.length; + applySpeed(); + for (WeakReference audioPlayer : audioPlayerLayouts) { + final RelativeLayout layout = audioPlayer.get(); + if (layout != null) { + updateSpeedButton(ViewHolder.get(layout)); + } + } + } + + private void applySpeed() { + if (player != null && player.isPlaying()) { + player.setPlaybackParams( + player.getPlaybackParams() + .setSpeed(SPEED_STEPS[currentSpeedIndex]) + .setPitch(1.0f)); + } + } + + private void updateSpeedButton(final ViewHolder viewHolder) { + if (viewHolder.playbackSpeed == null) { + return; + } + final Context context = viewHolder.playbackSpeed.getContext(); + final int[] labelRes = { + R.string.speed_1x, R.string.speed_1_25x, R.string.speed_1_5x, R.string.speed_2x + }; + viewHolder.playbackSpeed.setText(context.getString(labelRes[currentSpeedIndex])); + } + private ViewHolder getCurrentViewHolder() { for (WeakReference audioPlayer : audioPlayerLayouts) { final Message message = (Message) audioPlayer.get().getTag(); @@ -453,6 +493,7 @@ public static class ViewHolder { private TextView runtime; private SeekBar progress; private MaterialButton playPause; + private MaterialButton playbackSpeed; private MessageAdapter.BubbleColor bubbleColor = MessageAdapter.BubbleColor.SURFACE; public static ViewHolder get(final RelativeLayout audioPlayer) { @@ -465,6 +506,7 @@ public static ViewHolder get(final RelativeLayout audioPlayer) { viewHolder.runtime = audioPlayer.findViewById(R.id.runtime); viewHolder.progress = audioPlayer.findViewById(R.id.progress); viewHolder.playPause = audioPlayer.findViewById(R.id.play_pause); + viewHolder.playbackSpeed = audioPlayer.findViewById(R.id.playback_speed); audioPlayer.setTag(R.id.TAG_AUDIO_PLAYER_VIEW_HOLDER, viewHolder); return viewHolder; } diff --git a/src/main/res/drawable/ic_speed_24dp.xml b/src/main/res/drawable/ic_speed_24dp.xml new file mode 100644 index 000000000..6d20a869b --- /dev/null +++ b/src/main/res/drawable/ic_speed_24dp.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/src/main/res/layout/item_message_content.xml b/src/main/res/layout/item_message_content.xml index 822faf534..6a27bb495 100644 --- a/src/main/res/layout/item_message_content.xml +++ b/src/main/res/layout/item_message_content.xml @@ -63,12 +63,25 @@ app:icon="@drawable/ic_play_arrow_24dp" app:iconSize="26dp" /> + + @@ -79,6 +92,7 @@ android:layout_below="@+id/runtime" android:layout_centerVertical="true" android:layout_toEndOf="@+id/play_pause" + android:layout_toStartOf="@+id/playback_speed" android:progress="100" /> diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 756729dd0..1eb39e902 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -991,6 +991,11 @@ Record voice mail Play audio Pause audio + + 1.25× + 1.5× + + Playback speed Add contact, create or join group chat, or discover channels View %1$d Participant