mirror of
https://github.com/MaintainTeam/LastPipeBender.git
synced 2025-03-02 22:38:20 +03:00
Merge pull request #90 from Atemu/player-queue-seekbar-markers
PlayQueue: Mark SponsorBlock segments in seekbar
This commit is contained in:
commit
2af884e777
5 changed files with 128 additions and 104 deletions
|
@ -4,6 +4,7 @@ import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
@ -17,6 +18,7 @@ import android.widget.SeekBar;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
@ -47,6 +49,7 @@ import java.util.List;
|
||||||
|
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
|
import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
|
||||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||||
|
import static org.schabi.newpipe.util.SponsorBlockUtils.markSegments;
|
||||||
import static org.schabi.newpipe.util.external_communication.ShareUtils.shareText;
|
import static org.schabi.newpipe.util.external_communication.ShareUtils.shareText;
|
||||||
|
|
||||||
public final class PlayQueueActivity extends AppCompatActivity
|
public final class PlayQueueActivity extends AppCompatActivity
|
||||||
|
@ -225,6 +228,12 @@ public final class PlayQueueActivity extends AppCompatActivity
|
||||||
} else {
|
} else {
|
||||||
buildComponents();
|
buildComponents();
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
|
final PlayQueueItem item = player.getPlayQueue().getItem();
|
||||||
|
final Context context = getApplicationContext();
|
||||||
|
final SharedPreferences prefs =
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
markSegments(item, queueControlBinding.seekBar, context, prefs);
|
||||||
|
|
||||||
player.setActivityListener(PlayQueueActivity.this);
|
player.setActivityListener(PlayQueueActivity.this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,6 @@ import org.schabi.newpipe.util.external_communication.ShareUtils;
|
||||||
import org.schabi.newpipe.util.SponsorBlockMode;
|
import org.schabi.newpipe.util.SponsorBlockMode;
|
||||||
import org.schabi.newpipe.util.VideoSegment;
|
import org.schabi.newpipe.util.VideoSegment;
|
||||||
import org.schabi.newpipe.views.ExpandableSurfaceView;
|
import org.schabi.newpipe.views.ExpandableSurfaceView;
|
||||||
import org.schabi.newpipe.views.SeekBarMarker;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -192,6 +191,7 @@ import static org.schabi.newpipe.util.ListHelper.getPopupResolutionIndex;
|
||||||
import static org.schabi.newpipe.util.ListHelper.getResolutionIndex;
|
import static org.schabi.newpipe.util.ListHelper.getResolutionIndex;
|
||||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||||
import static org.schabi.newpipe.util.Localization.containsCaseInsensitive;
|
import static org.schabi.newpipe.util.Localization.containsCaseInsensitive;
|
||||||
|
import static org.schabi.newpipe.util.SponsorBlockUtils.markSegments;
|
||||||
|
|
||||||
public final class Player implements
|
public final class Player implements
|
||||||
EventListener,
|
EventListener,
|
||||||
|
@ -2132,7 +2132,7 @@ public final class Player implements
|
||||||
audioReactor.requestAudioFocus();
|
audioReactor.requestAudioFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
markSegments();
|
markSegments(currentItem, binding.playbackSeekBar, context, prefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onBlocked() {
|
private void onBlocked() {
|
||||||
|
@ -4438,106 +4438,6 @@ public final class Player implements
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void markSegments() {
|
|
||||||
binding.playbackSeekBar.clearMarkers();
|
|
||||||
|
|
||||||
if (currentItem == null) {
|
|
||||||
Log.w(TAG, "markSegments() - currentItem was null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final VideoSegment[] segments = currentItem.getVideoSegments();
|
|
||||||
|
|
||||||
if (segments == null || segments.length == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final VideoSegment segment : segments) {
|
|
||||||
final Integer color = parseSegmentCategory(segment.category);
|
|
||||||
|
|
||||||
// if null, then this category should not be marked
|
|
||||||
if (color == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final SeekBarMarker seekBarMarker =
|
|
||||||
new SeekBarMarker(segment.startTime, segment.endTime,
|
|
||||||
(int) simpleExoPlayer.getDuration(), color);
|
|
||||||
binding.playbackSeekBar.seekBarMarkers.add(seekBarMarker);
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.playbackSeekBar.drawMarkers();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Integer parseSegmentCategory(final String category) {
|
|
||||||
String key;
|
|
||||||
final String colorStr;
|
|
||||||
switch (category) {
|
|
||||||
case "sponsor":
|
|
||||||
key = context.getString(R.string.sponsor_block_category_sponsor_key);
|
|
||||||
if (prefs.getBoolean(key, false)) {
|
|
||||||
key = context.getString(R.string.sponsor_block_category_sponsor_color_key);
|
|
||||||
colorStr = prefs.getString(key, null);
|
|
||||||
return colorStr == null
|
|
||||||
? context.getResources().getColor(R.color.sponsor_segment)
|
|
||||||
: Color.parseColor(colorStr);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "intro":
|
|
||||||
key = context.getString(R.string.sponsor_block_category_intro_key);
|
|
||||||
if (prefs.getBoolean(key, false)) {
|
|
||||||
key = context.getString(R.string.sponsor_block_category_intro_color_key);
|
|
||||||
colorStr = prefs.getString(key, null);
|
|
||||||
return colorStr == null
|
|
||||||
? context.getResources().getColor(R.color.intro_segment)
|
|
||||||
: Color.parseColor(colorStr);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "outro":
|
|
||||||
key = context.getString(R.string.sponsor_block_category_outro_key);
|
|
||||||
if (prefs.getBoolean(key, false)) {
|
|
||||||
key = context.getString(R.string.sponsor_block_category_outro_color_key);
|
|
||||||
colorStr = prefs.getString(key, null);
|
|
||||||
return colorStr == null
|
|
||||||
? context.getResources().getColor(R.color.outro_segment)
|
|
||||||
: Color.parseColor(colorStr);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "interaction":
|
|
||||||
key = context.getString(R.string.sponsor_block_category_interaction_key);
|
|
||||||
if (prefs.getBoolean(key, false)) {
|
|
||||||
key = context.getString(R.string.sponsor_block_category_interaction_color_key);
|
|
||||||
colorStr = prefs.getString(key, null);
|
|
||||||
return colorStr == null
|
|
||||||
? context.getResources().getColor(R.color.interaction_segment)
|
|
||||||
: Color.parseColor(colorStr);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "selfpromo":
|
|
||||||
key = context.getString(R.string.sponsor_block_category_self_promo_key);
|
|
||||||
if (prefs.getBoolean(key, false)) {
|
|
||||||
key = context.getString(R.string.sponsor_block_category_self_promo_color_key);
|
|
||||||
colorStr = prefs.getString(key, null);
|
|
||||||
return colorStr == null
|
|
||||||
? context.getResources().getColor(R.color.self_promo_segment)
|
|
||||||
: Color.parseColor(colorStr);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "music_offtopic":
|
|
||||||
key = context.getString(R.string.sponsor_block_category_non_music_key);
|
|
||||||
if (prefs.getBoolean(key, false)) {
|
|
||||||
key = context.getString(R.string.sponsor_block_category_non_music_color_key);
|
|
||||||
colorStr = prefs.getString(key, null);
|
|
||||||
return colorStr == null
|
|
||||||
? context.getResources().getColor(R.color.non_music_segment)
|
|
||||||
: Color.parseColor(colorStr);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setBlockSponsorsButton(final ImageButton button) {
|
protected void setBlockSponsorsButton(final ImageButton button) {
|
||||||
if (button == null) {
|
if (button == null) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.schabi.newpipe.util;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -18,6 +19,9 @@ import org.schabi.newpipe.DownloaderImpl;
|
||||||
import org.schabi.newpipe.MainActivity;
|
import org.schabi.newpipe.MainActivity;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||||
|
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
|
||||||
|
import org.schabi.newpipe.views.MarkableSeekBar;
|
||||||
|
import org.schabi.newpipe.views.SeekBarMarker;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
|
@ -195,4 +199,115 @@ public final class SponsorBlockUtils {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Integer parseSegmentCategory(
|
||||||
|
final String category,
|
||||||
|
final Context context,
|
||||||
|
final SharedPreferences prefs
|
||||||
|
) {
|
||||||
|
String key;
|
||||||
|
final String colorStr;
|
||||||
|
switch (category) {
|
||||||
|
case "sponsor":
|
||||||
|
key = context.getString(R.string.sponsor_block_category_sponsor_key);
|
||||||
|
if (prefs.getBoolean(key, false)) {
|
||||||
|
key = context.getString(R.string.sponsor_block_category_sponsor_color_key);
|
||||||
|
colorStr = prefs.getString(key, null);
|
||||||
|
return colorStr == null
|
||||||
|
? context.getResources().getColor(R.color.sponsor_segment)
|
||||||
|
: Color.parseColor(colorStr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "intro":
|
||||||
|
key = context.getString(R.string.sponsor_block_category_intro_key);
|
||||||
|
if (prefs.getBoolean(key, false)) {
|
||||||
|
key = context.getString(R.string.sponsor_block_category_intro_color_key);
|
||||||
|
colorStr = prefs.getString(key, null);
|
||||||
|
return colorStr == null
|
||||||
|
? context.getResources().getColor(R.color.intro_segment)
|
||||||
|
: Color.parseColor(colorStr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "outro":
|
||||||
|
key = context.getString(R.string.sponsor_block_category_outro_key);
|
||||||
|
if (prefs.getBoolean(key, false)) {
|
||||||
|
key = context.getString(R.string.sponsor_block_category_outro_color_key);
|
||||||
|
colorStr = prefs.getString(key, null);
|
||||||
|
return colorStr == null
|
||||||
|
? context.getResources().getColor(R.color.outro_segment)
|
||||||
|
: Color.parseColor(colorStr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "interaction":
|
||||||
|
key = context.getString(R.string.sponsor_block_category_interaction_key);
|
||||||
|
if (prefs.getBoolean(key, false)) {
|
||||||
|
key = context.getString(R.string.sponsor_block_category_interaction_color_key);
|
||||||
|
colorStr = prefs.getString(key, null);
|
||||||
|
return colorStr == null
|
||||||
|
? context.getResources().getColor(R.color.interaction_segment)
|
||||||
|
: Color.parseColor(colorStr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "selfpromo":
|
||||||
|
key = context.getString(R.string.sponsor_block_category_self_promo_key);
|
||||||
|
if (prefs.getBoolean(key, false)) {
|
||||||
|
key = context.getString(R.string.sponsor_block_category_self_promo_color_key);
|
||||||
|
colorStr = prefs.getString(key, null);
|
||||||
|
return colorStr == null
|
||||||
|
? context.getResources().getColor(R.color.self_promo_segment)
|
||||||
|
: Color.parseColor(colorStr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "music_offtopic":
|
||||||
|
key = context.getString(R.string.sponsor_block_category_non_music_key);
|
||||||
|
if (prefs.getBoolean(key, false)) {
|
||||||
|
key = context.getString(R.string.sponsor_block_category_non_music_color_key);
|
||||||
|
colorStr = prefs.getString(key, null);
|
||||||
|
return colorStr == null
|
||||||
|
? context.getResources().getColor(R.color.non_music_segment)
|
||||||
|
: Color.parseColor(colorStr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void markSegments(
|
||||||
|
final PlayQueueItem currentItem,
|
||||||
|
final MarkableSeekBar seekBar,
|
||||||
|
final Context context,
|
||||||
|
final SharedPreferences prefs
|
||||||
|
) {
|
||||||
|
seekBar.clearMarkers();
|
||||||
|
|
||||||
|
if (currentItem == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final VideoSegment[] segments = currentItem.getVideoSegments();
|
||||||
|
|
||||||
|
if (segments == null || segments.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final VideoSegment segment : segments) {
|
||||||
|
final Integer color = parseSegmentCategory(segment.category, context, prefs);
|
||||||
|
|
||||||
|
// if null, then this category should not be marked
|
||||||
|
if (color == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duration is in seconds, we need millis
|
||||||
|
final int length = (int) currentItem.getDuration() * 1000;
|
||||||
|
|
||||||
|
final SeekBarMarker seekBarMarker =
|
||||||
|
new SeekBarMarker(segment.startTime, segment.endTime,
|
||||||
|
length, color);
|
||||||
|
seekBar.seekBarMarkers.add(seekBarMarker);
|
||||||
|
}
|
||||||
|
|
||||||
|
seekBar.drawMarkers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,7 +280,7 @@
|
||||||
tools:ignore="HardcodedText"
|
tools:ignore="HardcodedText"
|
||||||
tools:text="1:06:29" />
|
tools:text="1:06:29" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatSeekBar
|
<org.schabi.newpipe.views.FocusAwareSeekBar
|
||||||
android:id="@+id/seek_bar"
|
android:id="@+id/seek_bar"
|
||||||
style="@style/Widget.AppCompat.SeekBar"
|
style="@style/Widget.AppCompat.SeekBar"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
|
|
@ -122,7 +122,7 @@
|
||||||
tools:text="1:06:29" />
|
tools:text="1:06:29" />
|
||||||
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatSeekBar
|
<org.schabi.newpipe.views.FocusAwareSeekBar
|
||||||
android:id="@+id/seek_bar"
|
android:id="@+id/seek_bar"
|
||||||
style="@style/Widget.AppCompat.SeekBar"
|
style="@style/Widget.AppCompat.SeekBar"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
|
Loading…
Add table
Reference in a new issue