Skip to content

Commit

Permalink
CHANGELOG: Introduce Media Art in QS Media Tile
Browse files Browse the repository at this point in the history
  • Loading branch information
DHD2280 committed Jun 19, 2024
1 parent f0f3688 commit 8b54abb
Show file tree
Hide file tree
Showing 10 changed files with 270 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ public static class QsTilesCustomization {
public static final String QS_TILE_INACTIVE_COLOR = "qs_tile_inactive_color";
public static final String QS_TILE_DISABLED_COLOR_ENABLED = "qs_tile_disabled_color_enabled";
public static final String QS_TILE_DISABLED_COLOR = "qs_tile_disabled_color";
public static final String QS_MEDIA_SHOW_ALBUM_ART = "qs_media_show_album_art";
public static final String QS_MEDIA_ART_FILTER = "qs_media_art_filter";
public static final String QS_MEDIA_ART_BLUR_AMOUNT = "qs_media_blur_amount";
public static final String QS_MEDIA_ART_TINT_COLOR = "qs_media_art_tint_color";
public static final String QS_MEDIA_ART_TINT_AMOUNT = "qs_media_art_tint_amount";
public static final String QS_TILE_HIDE_LABELS = "qs_hide_labels";
public static final String QS_TILE_LABELS_CUSTOM_COLOR_ENABLED = "qs_tile_label_enabled";
public static final String QS_TILE_LABELS_CUSTOM_COLOR = "qs_tile_label";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsHeaderImage.QS_HEADER_IMAGE_TINT;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsHeaderImage.QS_HEADER_IMAGE_URI;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsHeaderImage.QS_HEADER_IMAGE_ZOOM_TO_FIT;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_MEDIA_ART_BLUR_AMOUNT;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_MEDIA_ART_FILTER;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_MEDIA_ART_TINT_AMOUNT;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_MEDIA_ART_TINT_COLOR;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_MEDIA_SHOW_ALBUM_ART;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_TILE_ANIMATION_DURATION;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_TILE_ANIMATION_INTERPOLATOR;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_TILE_ANIMATION_STYLE;
Expand Down Expand Up @@ -299,6 +304,19 @@ public static boolean isVisible(String key) {
case "qs_tile_label" -> {
return instance.mPreferences.getBoolean("qs_tile_label_enabled", false);
}
case QS_MEDIA_ART_FILTER -> {
return instance.mPreferences.getBoolean(QS_MEDIA_SHOW_ALBUM_ART, false);
}
case QS_MEDIA_ART_BLUR_AMOUNT -> {
return instance.mPreferences.getBoolean(QS_MEDIA_SHOW_ALBUM_ART, false) &&
(instance.mPreferences.getString(QS_MEDIA_ART_FILTER, "0").equals("3") ||
instance.mPreferences.getString(QS_MEDIA_ART_FILTER, "0").equals("4"));
}
case QS_MEDIA_ART_TINT_COLOR,
QS_MEDIA_ART_TINT_AMOUNT -> {
return instance.mPreferences.getBoolean(QS_MEDIA_SHOW_ALBUM_ART, false) &&
(instance.mPreferences.getString(QS_MEDIA_ART_FILTER, "0").equals("5"));
}

// Gesture Prefs
case "gesture_left_height_double" -> {
Expand Down Expand Up @@ -631,6 +649,8 @@ public static String getSummary(Context fragmentCompat, @NonNull String key) {
instance.mPreferences.getSliderInt(QS_TRANSPARENCY_VAL, 40) + "%";
case BLUR_RADIUS_VALUE ->
instance.mPreferences.getSliderInt(BLUR_RADIUS_VALUE, 60) + "%";
case QS_MEDIA_ART_BLUR_AMOUNT -> instance.mPreferences.getSliderInt(QS_MEDIA_ART_BLUR_AMOUNT, 35) + "%";
case QS_MEDIA_ART_TINT_AMOUNT -> instance.mPreferences.getSliderInt(QS_MEDIA_ART_TINT_AMOUNT, 30) + "%";
// Statusbar
case "status_bar_clock_size" -> instance.mPreferences.getSliderInt("status_bar_clock_size", 12) + "sp";
case "status_bar_clock_auto_hide_hduration" ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ public static ArrayList<Class<? extends XposedMods>> getMods(String packageName)
// Battery Data Provider
modPacks.add(BatteryDataProvider.class);

// Audio Data Provider
modPacks.add(AudioDataProvider.class);

// System Classes We need
modPacks.add(OpUtils.class);

Expand All @@ -85,8 +88,8 @@ public static ArrayList<Class<? extends XposedMods>> getMods(String packageName)
modPacks.add(QSTransparency.class);
modPacks.add(QSTiles.class);
modPacks.add(QsTileCustomization.class);

// Pulse View
modPacks.add(AudioDataProvider.class);
modPacks.add(PulseViewHook.class);

// Lockscreen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.media.MediaMetadata;

import java.util.ArrayList;
Expand All @@ -23,6 +24,7 @@ public class AudioDataProvider extends XposedMods {
private final ArrayList<AudioInfoCallbacks> mInfoCallbacks = new ArrayList<>();
@SuppressLint("StaticFieldLeak")
private static AudioDataProvider instance = null;
public Bitmap mArt;

public AudioDataProvider(Context context) {
super(context);
Expand All @@ -45,7 +47,11 @@ public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Th
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//log("onPrimaryMetadataOrStateChanged: PlaybackState: " + param.args[1] + " Metadata: " + param.args[0]);
mMediaMetadata = (MediaMetadata) param.args[0];
MediaMetadata metaData = (MediaMetadata) param.args[0];
if (mMediaMetadata != metaData) {
mMediaMetadata = metaData;
mArt = getArtWork();
}
mPlaybackState = (int) param.args[1];
onPrimaryMetadataOrStateChanged((int) param.args[1]);
}
Expand Down Expand Up @@ -92,4 +98,20 @@ public static int getPlaybackState() {
public static MediaMetadata getMediaMetadata() {
return instance.mMediaMetadata;
}

private Bitmap getArtWork() {
MediaMetadata mediaMetadata = instance.mMediaMetadata;
if (mediaMetadata == null) {
return null;
}
Bitmap art = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
if (art == null) {
return mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
}
return art;
}

public static Bitmap getArt() {
return instance.mArt;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_BRIGHTNESS_SLIDER_COLOR;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_BRIGHTNESS_SLIDER_COLOR_MODE;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_BRIGHTNESS_SLIDER_CUSTOMIZE;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_MEDIA_ART_BLUR_AMOUNT;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_MEDIA_ART_FILTER;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_MEDIA_ART_TINT_AMOUNT;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_MEDIA_ART_TINT_COLOR;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_MEDIA_SHOW_ALBUM_ART;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_TILE_ACTIVE_COLOR;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_TILE_ACTIVE_COLOR_ENABLED;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_TILE_ANIMATION_DURATION;
Expand All @@ -29,14 +34,19 @@
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_TILE_LABELS_CUSTOM_COLOR_ENABLED;
import static it.dhd.oxygencustomizer.utils.Constants.Preferences.QsTilesCustomization.QS_UPDATE_PREFS;
import static it.dhd.oxygencustomizer.xposed.XPrefs.Xprefs;
import static it.dhd.oxygencustomizer.xposed.hooks.systemui.AudioDataProvider.getArt;
import static it.dhd.oxygencustomizer.xposed.hooks.systemui.OpUtils.getPrimaryColor;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.TransitionDrawable;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
Expand All @@ -47,16 +57,20 @@
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.core.content.res.ResourcesCompat;
import androidx.palette.graphics.Palette;
import androidx.viewpager.widget.ViewPager;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import it.dhd.oxygencustomizer.utils.Constants;
import it.dhd.oxygencustomizer.xposed.XposedMods;
import it.dhd.oxygencustomizer.xposed.hooks.systemui.AudioDataProvider;
import it.dhd.oxygencustomizer.xposed.utils.DrawableConverter;
import it.dhd.oxygencustomizer.xposed.utils.viewpager.AccordionTransformer;
import it.dhd.oxygencustomizer.xposed.utils.viewpager.BackgroundToForegroundTransformer;
import it.dhd.oxygencustomizer.xposed.utils.viewpager.CubeInTransformer;
Expand Down Expand Up @@ -97,6 +111,11 @@ public class QsTileCustomization extends XposedMods {
private int mAnimDuration = 0;
private boolean mTrasformationsEnabled = false;
private int mTrasformations = 1;
private boolean showMediaArtMediaQs = false;
private int mMediaQsArtFilter = 0, mMediaQsTintColor = Color.WHITE, mMediaQsTintAmount = 20;
private float mMediaQsArtBlurAmount = 7.5f;
private Bitmap mArt = null;
private int mColorOnAlbum = Color.WHITE;

public QsTileCustomization(Context context) {
super(context);
Expand All @@ -114,6 +133,13 @@ public void updatePrefs(String... Key) {
qsDisabledColorEnabled = Xprefs.getBoolean(QS_TILE_DISABLED_COLOR_ENABLED, false);
qsDisabledColor = Xprefs.getInt(QS_TILE_DISABLED_COLOR, Color.DKGRAY);

// Media QS
showMediaArtMediaQs = Xprefs.getBoolean(QS_MEDIA_SHOW_ALBUM_ART, false);
mMediaQsArtFilter = Integer.parseInt(Xprefs.getString(QS_MEDIA_ART_FILTER, "0"));
mMediaQsArtBlurAmount = (Xprefs.getSliderInt(QS_MEDIA_ART_BLUR_AMOUNT, 30)/100f) * 25f;
mMediaQsTintColor = Xprefs.getInt(QS_MEDIA_ART_TINT_COLOR, Color.WHITE);
mMediaQsTintAmount = Xprefs.getSliderInt(QS_MEDIA_ART_TINT_AMOUNT, 20);

// Brightness Slider
qsBrightnessSliderCustomize = Xprefs.getBoolean(QS_BRIGHTNESS_SLIDER_CUSTOMIZE, false);
qsBrightnessSliderColorMode = Integer.parseInt(Xprefs.getString(QS_BRIGHTNESS_SLIDER_COLOR_MODE, "0"));
Expand Down Expand Up @@ -142,6 +168,14 @@ public void updatePrefs(String... Key) {
notifyQsUpdate();
}
}
if (Key[0].equals(QS_MEDIA_SHOW_ALBUM_ART) ||
Key[0].equals(QS_MEDIA_ART_FILTER) ||
Key[0].equals(QS_MEDIA_ART_BLUR_AMOUNT) ||
Key[0].equals(QS_MEDIA_ART_TINT_COLOR) ||
Key[0].equals(QS_MEDIA_ART_TINT_AMOUNT)) {
if (showMediaArtMediaQs) updateMediaQsBackground(3);
else updateMediaQs();
}
}


Expand All @@ -151,6 +185,8 @@ public void updatePrefs(String... Key) {
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals(listenerPackage)) return;

AudioDataProvider.registerInfoCallback(this::updateMediaQsBackground);

Class<?> PersonalityManager = findClass("com.oplus.systemui.qs.personality.PersonalityManager", lpparam.classLoader);
hookAllConstructors(PersonalityManager, new XC_MethodHook() {
@Override
Expand Down Expand Up @@ -318,6 +354,15 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
}
});

hookAllMethods(OplusQsMediaPanelView, "bindTitleAndText", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
if (showMediaArtMediaQs) {
setupOtherViews(mOplusQsMediaView, mColorOnAlbum);
}
}
});

Class<?> OplusQSTileView;
try {
OplusQSTileView = findClass("com.oplus.systemui.qs.qstileimpl.OplusQSTileView", lpparam.classLoader);
Expand Down Expand Up @@ -460,6 +505,77 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {

}

private void updateMediaQsBackground(int state) {
if (!showMediaArtMediaQs) return;
Bitmap oldArt = mArt;
mArt = getFilteredArt(getArt());
float radius = 0f;
try {
GradientDrawable defBg = (GradientDrawable) mOplusQsMediaDefaultBackground;
radius = defBg.getCornerRadius();
} catch (Throwable t) {
log("Oxygen Customizer - QsTileCustomization error: " + t.getMessage());
}
Bitmap artRounded = DrawableConverter.getRoundedCornerBitmap(mArt, radius);
Bitmap oldArtRounded = DrawableConverter.getRoundedCornerBitmap(oldArt, radius);
Palette.Builder builder = new Palette.Builder(artRounded);
builder.generate(palette -> {
int dominantColor = palette.getDominantColor(Color.WHITE);
mColorOnAlbum =
isColorDark(dominantColor) ?
DrawableConverter.findContrastColorAgainstDark(Color.WHITE, dominantColor, true, 2) :
DrawableConverter.findContrastColor(Color.BLACK, dominantColor, true, 2);
mOplusQsMediaView.post(() -> {
setupOtherViews(mOplusQsMediaView, mColorOnAlbum);
});
});

mOplusQsMediaView.post(() -> {
Drawable[] layers = new Drawable[]{new BitmapDrawable(mContext.getResources(), oldArtRounded), new BitmapDrawable(mContext.getResources(), artRounded)};
TransitionDrawable transitionDrawable = new TransitionDrawable(layers);
mOplusQsMediaView.setBackground(transitionDrawable);
transitionDrawable.startTransition(250);
});
}

private Bitmap getFilteredArt(Bitmap art) {
Bitmap finalArt;
switch (mMediaQsArtFilter) {
default -> finalArt = art;
case 1 -> finalArt = DrawableConverter.toGrayscale(art);
case 2 -> finalArt = DrawableConverter.getColoredBitmap(new BitmapDrawable(mContext.getResources(), art),
getPrimaryColor(mContext));
case 3 -> finalArt = DrawableConverter.getBlurredImage(mContext, art, mMediaQsArtBlurAmount);
case 4 -> finalArt = DrawableConverter.getGrayscaleBlurredImage(mContext, art, mMediaQsArtBlurAmount);
case 5 -> finalArt = DrawableConverter.getColoredBitmap(new BitmapDrawable(mContext.getResources(), art),
mMediaQsTintColor, mMediaQsTintAmount);
};
return finalArt;
}

private void setupOtherViews(View parent, int color) {
if (parent == null) return;

if (parent instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) parent).getChildCount(); i++) {
if (((ViewGroup) parent).getChildAt(i) instanceof ViewGroup) {
setupOtherViews(((ViewGroup) parent).getChildAt(i), color);
} else {
View v = ((ViewGroup) parent).getChildAt(i);
if (v instanceof ImageButton imageButton) {
imageButton.setImageTintList(ColorStateList.valueOf(color));
} else if (v instanceof TextView text) {
text.setTextColor(color);
}
}
}
}
}

private boolean isColorDark(int color) {
double darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;
return darkness >= 0.5;
}

private ViewPager.PageTransformer getCustomTransitions() {
return switch (mTrasformations) {
Expand Down Expand Up @@ -550,6 +666,7 @@ private void notifyQsUpdate() {
}

private void updateMediaQs() {
if (showMediaArtMediaQs) return;
if (qsInactiveColorEnabled) {
if (mOplusQsMediaView != null && mOplusQsMediaDrawable != null) {
mOplusQsMediaDrawable.setTint(qsInactiveColor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
Expand Down Expand Up @@ -114,6 +116,21 @@ public static Bitmap getColoredBitmap(Drawable d, int color) {
return grayscaleBitmap;
}

public static Bitmap getColoredBitmap(Drawable d, int color, int intensity) {
if (d == null) {
return null;
}
Bitmap colorBitmap = ((BitmapDrawable) d).getBitmap();
Bitmap filteredBitmap = Bitmap.createBitmap(colorBitmap.getWidth(), colorBitmap.getHeight(), colorBitmap.getConfig());
Canvas canvas = new Canvas(filteredBitmap);
Paint paint = new Paint();
int fadeFilter = ColorUtils.blendARGB(Color.TRANSPARENT, color, intensity / 100f);
paint.setColorFilter(new PorterDuffColorFilter(fadeFilter, PorterDuff.Mode.SRC_ATOP));

canvas.drawBitmap(colorBitmap, 0, 0, paint);
return filteredBitmap;
}

public static Bitmap toGrayscale(Bitmap bmpOriginal) {
int width, height;
height = bmpOriginal.getHeight();
Expand Down
Loading

0 comments on commit 8b54abb

Please sign in to comment.