lots of code refactoring

This commit is contained in:
dkanada 2020-05-02 17:27:27 +09:00
commit 2f8b82a44e
49 changed files with 89 additions and 819 deletions

View file

@ -18,15 +18,9 @@ import org.jellyfin.apiclient.model.logging.ILogger;
import org.jellyfin.apiclient.model.serialization.IJsonSerializer;
import org.jellyfin.apiclient.model.session.ClientCapabilities;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class App extends Application {
public static final String GOOGLE_PLAY_LICENSE_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjMeADN5Ffnt/ml5SYxNPCn8kGcOYGpHEfNSCts99vVxqmCn6C01E94c17j7rUK2aeHur5uxphZylzopPlQ8P8l1fqty0GPUNRSo18FCJzfGH8HZAwZYOcnRFPaXdaq3InyFJhBiODh2oeAcVK/idH6QraQ4r9HIlzigAg6lgwzxl2wJKDh7X/GMdDntCyzDh8xDQ0wIawFgvgojHwqh2Ci8Gnq6EYRwPA9yHiIIksT8Q30QyM5ewl5QcnWepsls7enNqeHarhpmSibRUDgCsxHoOpny7SyuvZvUI3wuLckDR0ds9hrt614scHHqDOBp/qWCZiAgOPVAEQcURbV09qQIDAQAB";
public static final String PRO_VERSION_PRODUCT_ID = "pro_version";
private static App app;
private static ApiClient apiClient;
@Override

View file

@ -54,8 +54,6 @@ public class DonationsDialog extends DialogFragment implements BillingProcessor.
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
billingProcessor = new BillingProcessor(getContext(), App.GOOGLE_PLAY_LICENSE_KEY, this);
@SuppressLint("InflateParams")
View customView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_donation, null);
ProgressBar progressBar = customView.findViewById(R.id.progress);

View file

@ -32,8 +32,10 @@ import butterknife.ButterKnife;
public class SleepTimerDialog extends DialogFragment {
@BindView(R.id.seek_arc)
SeekArc seekArc;
@BindView(R.id.timer_display)
TextView timerDisplay;
@BindView(R.id.should_finish_last_song)
CheckBox shouldFinishLastSong;

View file

@ -17,9 +17,6 @@ import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.util.MusicUtil;
public class SongDetailDialog extends DialogFragment {
public static final String TAG = SongDetailDialog.class.getSimpleName();
@NonNull
public static SongDetailDialog create(Song song) {
SongDetailDialog dialog = new SongDetailDialog();

View file

@ -3,6 +3,7 @@ package com.kabouzeid.gramophone.dialogs;
import android.app.Dialog;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;

View file

@ -1,42 +0,0 @@
package com.kabouzeid.gramophone.glide.audiocover;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import org.jaudiotagger.audio.mp3.MP3File;
import org.jaudiotagger.tag.images.Artwork;
public class AudioFileCoverUtils {
public static final String[] FALLBACKS = {"cover.jpg", "album.jpg", "folder.jpg", "cover.png", "album.png", "folder.png"};
public static InputStream fallback(String path) throws FileNotFoundException {
// use embedded high resolution album art
try {
MP3File mp3File = new MP3File(path);
if (mp3File.hasID3v2Tag()) {
Artwork art = mp3File.getTag().getFirstArtwork();
if (art != null) {
byte[] imageData = art.getBinaryData();
return new ByteArrayInputStream(imageData);
}
}
} catch (Exception e) {
// log exceptions and continue to the other fallback method
e.printStackTrace();
}
// look for album art in external files
final File parent = new File(path).getParentFile();
for (String fallback : FALLBACKS) {
File cover = new File(parent, fallback);
if (cover.exists()) {
return new FileInputStream(cover);
}
}
return null;
}
}

View file

@ -22,10 +22,6 @@ import java.util.Random;
import java.util.WeakHashMap;
public class MusicPlayerRemote {
public static final String TAG = MusicPlayerRemote.class.getSimpleName();
@Nullable
public static MusicService musicService;
private static final WeakHashMap<Context, ServiceBinder> mConnectionMap = new WeakHashMap<>();

View file

@ -8,9 +8,9 @@ import java.util.Collections;
import java.util.List;
public class ShuffleHelper {
public static void makeShuffleList(@NonNull List<Song> listToShuffle, final int current) {
if (listToShuffle.isEmpty()) return;
if (current >= 0) {
Song song = listToShuffle.remove(current);
Collections.shuffle(listToShuffle);

View file

@ -302,7 +302,6 @@ public class StackBlur {
}
}
}
}
private static class BlurTask implements Callable<Void> {
@ -329,6 +328,5 @@ public class StackBlur {
blurIteration(_src, _w, _h, _radius, _totalCores, _coreIndex, _round);
return null;
}
}
}

View file

@ -2,34 +2,11 @@ package com.kabouzeid.gramophone.helper;
import java.util.Locale;
/**
* Simple thread safe stop watch.
*
* @author Karim Abou Zeid (kabouzeid)
*/
public class StopWatch {
/**
* The time the stop watch was last started.
*/
private long startTime;
/**
* The time elapsed before the current {@link #startTime}.
*/
private long previousElapsedTime;
/**
* Whether the stop watch is currently running or not.
*/
private boolean isRunning;
/**
* Starts or continues the stop watch.
*
* @see #pause()
* @see #reset()
*/
public void start() {
synchronized (this) {
startTime = System.currentTimeMillis();
@ -37,12 +14,6 @@ public class StopWatch {
}
}
/**
* Pauses the stop watch. It can be continued later from {@link #start()}.
*
* @see #start()
* @see #reset()
*/
public void pause() {
synchronized (this) {
previousElapsedTime += System.currentTimeMillis() - startTime;
@ -50,12 +21,6 @@ public class StopWatch {
}
}
/**
* Stops and resets the stop watch to zero milliseconds.
*
* @see #start()
* @see #pause()
*/
public void reset() {
synchronized (this) {
startTime = 0;
@ -64,15 +29,13 @@ public class StopWatch {
}
}
/**
* @return the total elapsed time in milliseconds
*/
public final long getElapsedTime() {
synchronized (this) {
long currentElapsedTime = 0;
if (isRunning) {
currentElapsedTime = System.currentTimeMillis() - startTime;
}
return previousElapsedTime + currentElapsedTime;
}
}

View file

@ -1,15 +0,0 @@
package com.kabouzeid.gramophone.interfaces;
public interface LoaderIds {
int ALBUM_DETAIL_ACTIVITY = 1;
int ARTIST_DETAIL_ACTIVITY = 2;
int PLAYLIST_DETAIL_ACTIVITY = 3;
int GENRE_DETAIL_ACTIVITY = 4;
int SEARCH_ACTIVITY = 5;
int FOLDERS_FRAGMENT = 6;
int ALBUMS_FRAGMENT = 7;
int ARTISTS_FRAGMENT = 8;
int PLAYLISTS_FRAGMENT = 9;
int GENRES_FRAGMENT = 10;
int SONGS_FRAGMENT = 11;
}

View file

@ -17,7 +17,6 @@ import com.kabouzeid.gramophone.util.PreferenceUtil;
import java.util.ArrayList;
import java.util.List;
public class LibraryPreferenceDialog extends DialogFragment {
public static LibraryPreferenceDialog newInstance() {
return new LibraryPreferenceDialog();

View file

@ -1,153 +0,0 @@
/*
* Copyright (C) 2014 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.kabouzeid.gramophone.provider;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class HistoryStore extends SQLiteOpenHelper {
private static final int MAX_ITEMS_IN_DB = 100;
public static final String DATABASE_NAME = "history.db";
private static final int VERSION = 1;
@Nullable
private static HistoryStore sInstance = null;
public HistoryStore(final Context context) {
super(context, DATABASE_NAME, null, VERSION);
}
@Override
public void onCreate(@NonNull final SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + RecentStoreColumns.NAME + " ("
+ RecentStoreColumns.ID + " LONG NOT NULL," + RecentStoreColumns.TIME_PLAYED
+ " LONG NOT NULL);");
}
@Override
public void onUpgrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + RecentStoreColumns.NAME);
onCreate(db);
}
@Override
public void onDowngrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + RecentStoreColumns.NAME);
onCreate(db);
}
@NonNull
public static synchronized HistoryStore getInstance(@NonNull final Context context) {
if (sInstance == null) {
sInstance = new HistoryStore(context.getApplicationContext());
}
return sInstance;
}
public void addSongId(final long songId) {
if (songId == -1) {
return;
}
final SQLiteDatabase database = getWritableDatabase();
database.beginTransaction();
try {
// remove previous entries
removeSongId(songId);
// add the entry
final ContentValues values = new ContentValues(2);
values.put(RecentStoreColumns.ID, songId);
values.put(RecentStoreColumns.TIME_PLAYED, System.currentTimeMillis());
database.insert(RecentStoreColumns.NAME, null, values);
// if our db is too large, delete the extra items
Cursor oldest = null;
try {
oldest = database.query(RecentStoreColumns.NAME,
new String[]{RecentStoreColumns.TIME_PLAYED}, null, null, null, null,
RecentStoreColumns.TIME_PLAYED + " ASC");
if (oldest != null && oldest.getCount() > MAX_ITEMS_IN_DB) {
oldest.moveToPosition(oldest.getCount() - MAX_ITEMS_IN_DB);
long timeOfRecordToKeep = oldest.getLong(0);
database.delete(RecentStoreColumns.NAME,
RecentStoreColumns.TIME_PLAYED + " < ?",
new String[]{String.valueOf(timeOfRecordToKeep)});
}
} finally {
if (oldest != null) {
oldest.close();
}
}
} finally {
database.setTransactionSuccessful();
database.endTransaction();
}
}
public void removeSongId(final long songId) {
final SQLiteDatabase database = getWritableDatabase();
database.delete(RecentStoreColumns.NAME, RecentStoreColumns.ID + " = ?", new String[]{
String.valueOf(songId)
});
}
public void clear() {
final SQLiteDatabase database = getWritableDatabase();
database.delete(RecentStoreColumns.NAME, null, null);
}
public boolean contains(long id) {
final SQLiteDatabase database = getReadableDatabase();
Cursor cursor = database.query(RecentStoreColumns.NAME,
new String[]{RecentStoreColumns.ID},
RecentStoreColumns.ID + "=?",
new String[]{String.valueOf(id)},
null, null, null, null);
boolean containsId = cursor != null && cursor.moveToFirst();
if (cursor != null) {
cursor.close();
}
return containsId;
}
public Cursor queryRecentIds() {
final SQLiteDatabase database = getReadableDatabase();
return database.query(RecentStoreColumns.NAME,
new String[]{RecentStoreColumns.ID}, null, null, null, null,
RecentStoreColumns.TIME_PLAYED + " DESC");
}
public interface RecentStoreColumns {
String NAME = "recent_history";
String ID = "song_id";
String TIME_PLAYED = "time_played";
}
}

View file

@ -1,408 +0,0 @@
/*
* Copyright (C) 2014 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.kabouzeid.gramophone.provider;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Interpolator;
/**
* This database tracks the number of play counts for an individual song. This is used to drive
* the top played tracks as well as the playlist images
*/
public class SongPlayCountStore extends SQLiteOpenHelper {
@Nullable
private static SongPlayCountStore sInstance = null;
public static final String DATABASE_NAME = "song_play_count.db";
private static final int VERSION = 2;
// interpolator curve applied for measuring the curve
@NonNull
private static Interpolator sInterpolator = new AccelerateInterpolator(1.5f);
// how many weeks worth of playback to track
private static final int NUM_WEEKS = 52;
// how high to multiply the interpolation curve
@SuppressWarnings("FieldCanBeLocal")
private static int INTERPOLATOR_HEIGHT = 50;
// how high the base value is. The ratio of the Height to Base is what really matters
@SuppressWarnings("FieldCanBeLocal")
private static int INTERPOLATOR_BASE = 25;
@SuppressWarnings("FieldCanBeLocal")
private static int ONE_WEEK_IN_MS = 1000 * 60 * 60 * 24 * 7;
@NonNull
private static String WHERE_ID_EQUALS = SongPlayCountColumns.ID + "=?";
// number of weeks since epoch time
private int mNumberOfWeeksSinceEpoch;
// used to track if we've walked through the db and updated all the rows
private boolean mDatabaseUpdated;
public SongPlayCountStore(final Context context) {
super(context, DATABASE_NAME, null, VERSION);
long msSinceEpoch = System.currentTimeMillis();
mNumberOfWeeksSinceEpoch = (int) (msSinceEpoch / ONE_WEEK_IN_MS);
mDatabaseUpdated = false;
}
@Override
public void onCreate(@NonNull final SQLiteDatabase db) {
// create the play count table
// WARNING: If you change the order of these columns
// please update getColumnIndexForWeek
StringBuilder builder = new StringBuilder();
builder.append("CREATE TABLE IF NOT EXISTS ");
builder.append(SongPlayCountColumns.NAME);
builder.append("(");
builder.append(SongPlayCountColumns.ID);
builder.append(" INT UNIQUE,");
for (int i = 0; i < NUM_WEEKS; i++) {
builder.append(getColumnNameForWeek(i));
builder.append(" INT DEFAULT 0,");
}
builder.append(SongPlayCountColumns.LAST_UPDATED_WEEK_INDEX);
builder.append(" INT NOT NULL,");
builder.append(SongPlayCountColumns.PLAY_COUNT_SCORE);
builder.append(" REAL DEFAULT 0);");
db.execSQL(builder.toString());
}
@Override
public void onUpgrade(@NonNull final SQLiteDatabase db, final int oldVersion, final int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + SongPlayCountColumns.NAME);
onCreate(db);
}
@Override
public void onDowngrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
// If we ever have downgrade, drop the table to be safe
db.execSQL("DROP TABLE IF EXISTS " + SongPlayCountColumns.NAME);
onCreate(db);
}
/**
* @param context The {@link Context} to use
* @return A new instance of this class.
*/
@NonNull
public static synchronized SongPlayCountStore getInstance(@NonNull final Context context) {
if (sInstance == null) {
sInstance = new SongPlayCountStore(context.getApplicationContext());
}
return sInstance;
}
/**
* Increases the play count of a song by 1
*
* @param songId The song id to increase the play count
*/
public void bumpPlayCount(final long songId) {
if (songId == -1) {
return;
}
final SQLiteDatabase database = getWritableDatabase();
updateExistingRow(database, songId, true);
}
/**
* This creates a new entry that indicates a song has been played once as well as its score
*
* @param database a write able database
* @param songId the id of the track
*/
private void createNewPlayedEntry(@NonNull final SQLiteDatabase database, final long songId) {
// no row exists, create a new one
float newScore = getScoreMultiplierForWeek(0);
int newPlayCount = 1;
final ContentValues values = new ContentValues(3);
values.put(SongPlayCountColumns.ID, songId);
values.put(SongPlayCountColumns.PLAY_COUNT_SCORE, newScore);
values.put(SongPlayCountColumns.LAST_UPDATED_WEEK_INDEX, mNumberOfWeeksSinceEpoch);
values.put(getColumnNameForWeek(0), newPlayCount);
database.insert(SongPlayCountColumns.NAME, null, values);
}
/**
* This function will take a song entry and update it to the latest week and increase the count
* for the current week by 1 if necessary
*
* @param database a writeable database
* @param id the id of the track to bump
* @param bumpCount whether to bump the current's week play count by 1 and adjust the score
*/
private void updateExistingRow(@NonNull final SQLiteDatabase database, final long id, boolean bumpCount) {
String stringId = String.valueOf(id);
// begin the transaction
database.beginTransaction();
// get the cursor of this content inside the transaction
final Cursor cursor = database.query(SongPlayCountColumns.NAME, null, WHERE_ID_EQUALS,
new String[]{stringId}, null, null, null);
// if we have a result
if (cursor != null && cursor.moveToFirst()) {
// figure how many weeks since we last updated
int lastUpdatedIndex = cursor.getColumnIndex(SongPlayCountColumns.LAST_UPDATED_WEEK_INDEX);
int lastUpdatedWeek = cursor.getInt(lastUpdatedIndex);
int weekDiff = mNumberOfWeeksSinceEpoch - lastUpdatedWeek;
// if it's more than the number of weeks we track, delete it and create a new entry
if (Math.abs(weekDiff) >= NUM_WEEKS) {
// this entry needs to be dropped since it is too outdated
deleteEntry(database, stringId);
if (bumpCount) {
createNewPlayedEntry(database, id);
}
} else if (weekDiff != 0) {
// else, shift the weeks
int[] playCounts = new int[NUM_WEEKS];
if (weekDiff > 0) {
// time is shifted forwards
for (int i = 0; i < NUM_WEEKS - weekDiff; i++) {
playCounts[i + weekDiff] = cursor.getInt(getColumnIndexForWeek(i));
}
} else if (weekDiff < 0) {
// time is shifted backwards (by user) - nor typical behavior but we
// will still handle it
// since weekDiff is -ve, NUM_WEEKS + weekDiff is the real # of weeks we have to
// transfer. Then we transfer the old week i - weekDiff to week i
// for example if the user shifted back 2 weeks, ie -2, then for 0 to
// NUM_WEEKS + (-2) we set the new week i = old week i - (-2) or i+2
for (int i = 0; i < NUM_WEEKS + weekDiff; i++) {
playCounts[i] = cursor.getInt(getColumnIndexForWeek(i - weekDiff));
}
}
// bump the count
if (bumpCount) {
playCounts[0]++;
}
float score = calculateScore(playCounts);
// if the score is non-existant, then delete it
if (score < .01f) {
deleteEntry(database, stringId);
} else {
// create the content values
ContentValues values = new ContentValues(NUM_WEEKS + 2);
values.put(SongPlayCountColumns.LAST_UPDATED_WEEK_INDEX, mNumberOfWeeksSinceEpoch);
values.put(SongPlayCountColumns.PLAY_COUNT_SCORE, score);
for (int i = 0; i < NUM_WEEKS; i++) {
values.put(getColumnNameForWeek(i), playCounts[i]);
}
// update the entry
database.update(SongPlayCountColumns.NAME, values, WHERE_ID_EQUALS,
new String[]{stringId});
}
} else if (bumpCount) {
// else no shifting, just update the scores
ContentValues values = new ContentValues(2);
// increase the score by a single score amount
int scoreIndex = cursor.getColumnIndex(SongPlayCountColumns.PLAY_COUNT_SCORE);
float score = cursor.getFloat(scoreIndex) + getScoreMultiplierForWeek(0);
values.put(SongPlayCountColumns.PLAY_COUNT_SCORE, score);
// increase the play count by 1
values.put(getColumnNameForWeek(0), cursor.getInt(getColumnIndexForWeek(0)) + 1);
// update the entry
database.update(SongPlayCountColumns.NAME, values, WHERE_ID_EQUALS,
new String[]{stringId});
}
cursor.close();
} else if (bumpCount) {
// if we have no existing results, create a new one
createNewPlayedEntry(database, id);
}
database.setTransactionSuccessful();
database.endTransaction();
}
public void clear() {
final SQLiteDatabase database = getWritableDatabase();
database.delete(SongPlayCountColumns.NAME, null, null);
}
/**
* Gets a cursor containing the top songs played. Note this only returns songs that have been
* played at least once in the past NUM_WEEKS
*
* @param numResults number of results to limit by. If <= 0 it returns all results
* @return the top tracks
*/
public Cursor getTopPlayedResults(int numResults) {
updateResults();
final SQLiteDatabase database = getReadableDatabase();
return database.query(SongPlayCountColumns.NAME, new String[]{SongPlayCountColumns.ID},
null, null, null, null, SongPlayCountColumns.PLAY_COUNT_SCORE + " DESC",
(numResults <= 0 ? null : String.valueOf(numResults)));
}
/**
* This updates all the results for the getTopPlayedResults so that we can get an
* accurate list of the top played results
*/
private synchronized void updateResults() {
if (mDatabaseUpdated) {
return;
}
final SQLiteDatabase database = getWritableDatabase();
database.beginTransaction();
int oldestWeekWeCareAbout = mNumberOfWeeksSinceEpoch - NUM_WEEKS + 1;
// delete rows we don't care about anymore
database.delete(SongPlayCountColumns.NAME, SongPlayCountColumns.LAST_UPDATED_WEEK_INDEX
+ " < " + oldestWeekWeCareAbout, null);
// get the remaining rows
Cursor cursor = database.query(SongPlayCountColumns.NAME,
new String[]{SongPlayCountColumns.ID},
null, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
// for each row, update it
do {
updateExistingRow(database, cursor.getLong(0), false);
} while (cursor.moveToNext());
cursor.close();
}
mDatabaseUpdated = true;
database.setTransactionSuccessful();
database.endTransaction();
}
/**
* @param songId The song Id to remove.
*/
public void removeItem(final long songId) {
final SQLiteDatabase database = getWritableDatabase();
deleteEntry(database, String.valueOf(songId));
}
/**
* Deletes the entry
*
* @param database database to use
* @param stringId id to delete
*/
private void deleteEntry(@NonNull final SQLiteDatabase database, final String stringId) {
database.delete(SongPlayCountColumns.NAME, WHERE_ID_EQUALS, new String[]{stringId});
}
/**
* Calculates the score of the song given the play counts
*
* @param playCounts an array of the # of times a song has been played for each week
* where playCounts[N] is the # of times it was played N weeks ago
* @return the score
*/
private static float calculateScore(@Nullable final int[] playCounts) {
if (playCounts == null) {
return 0;
}
float score = 0;
for (int i = 0; i < Math.min(playCounts.length, NUM_WEEKS); i++) {
score += playCounts[i] * getScoreMultiplierForWeek(i);
}
return score;
}
/**
* Gets the column name for each week #
*
* @param week number
* @return the column name
*/
@NonNull
private static String getColumnNameForWeek(final int week) {
return SongPlayCountColumns.WEEK_PLAY_COUNT + String.valueOf(week);
}
/**
* Gets the score multiplier for each week
*
* @param week number
* @return the multiplier to apply
*/
private static float getScoreMultiplierForWeek(final int week) {
return sInterpolator.getInterpolation(1 - (week / (float) NUM_WEEKS)) * INTERPOLATOR_HEIGHT
+ INTERPOLATOR_BASE;
}
/**
* For some performance gain, return a static value for the column index for a week
* WARNING: This function assumes you have selected all columns for it to work
*
* @param week number
* @return column index of that week
*/
private static int getColumnIndexForWeek(final int week) {
// ID, followed by the weeks columns
return 1 + week;
}
public interface SongPlayCountColumns {
String NAME = "song_play_count";
String ID = "song_id";
String WEEK_PLAY_COUNT = "week";
String LAST_UPDATED_WEEK_INDEX = "week_index";
String PLAY_COUNT_SCORE = "play_count_score";
}
}

View file

@ -77,8 +77,10 @@ public class MediaButtonIntentReceiver extends BroadcastReceiver {
final Context context = (Context) msg.obj;
startService(context, command);
}
break;
}
releaseWakeLockIfHandlerIdle();
}
};
@ -103,8 +105,9 @@ public class MediaButtonIntentReceiver extends BroadcastReceiver {
final int action = event.getAction();
// fallback to system time if event time is not available
final long eventTime = event.getEventTime() != 0 ?
event.getEventTime() : System.currentTimeMillis();
final long eventTime = event.getEventTime() != 0
? event.getEventTime()
: System.currentTimeMillis();
String command = null;
switch (keycode) {
@ -196,9 +199,8 @@ public class MediaButtonIntentReceiver extends BroadcastReceiver {
}
if (DEBUG) Log.v(TAG, "Acquiring wake lock and sending " + msg.what);
// Make sure we don't indefinitely hold the wake lock under any circumstances
mWakeLock.acquire(10000);
mWakeLock.acquire(10000);
mHandler.sendMessageDelayed(msg, delay);
}
@ -210,6 +212,7 @@ public class MediaButtonIntentReceiver extends BroadcastReceiver {
if (mWakeLock != null) {
if (DEBUG) Log.v(TAG, "Releasing wake lock");
mWakeLock.release();
mWakeLock = null;
}

View file

@ -23,6 +23,7 @@ public class MultiPlayer implements Playback, MediaPlayer.OnErrorListener, Media
private MediaPlayer mNextMediaPlayer;
private Context context;
@Nullable
private Playback.PlaybackCallbacks callbacks;
@ -46,6 +47,7 @@ public class MultiPlayer implements Playback, MediaPlayer.OnErrorListener, Media
if (mIsInitialized) {
setNextDataSource(null);
}
return mIsInitialized;
}
@ -60,6 +62,7 @@ public class MultiPlayer implements Playback, MediaPlayer.OnErrorListener, Media
if (context == null) {
return false;
}
try {
player.reset();
player.setOnPreparedListener(null);
@ -68,17 +71,21 @@ public class MultiPlayer implements Playback, MediaPlayer.OnErrorListener, Media
} else {
player.setDataSource(path);
}
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.prepare();
} catch (Exception e) {
return false;
}
player.setOnCompletionListener(this);
player.setOnErrorListener(this);
final Intent intent = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, getAudioSessionId());
intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.getPackageName());
intent.putExtra(AudioEffect.EXTRA_CONTENT_TYPE, AudioEffect.CONTENT_TYPE_MUSIC);
context.sendBroadcast(intent);
return true;
}
@ -94,6 +101,7 @@ public class MultiPlayer implements Playback, MediaPlayer.OnErrorListener, Media
if (context == null) {
return;
}
try {
mCurrentMediaPlayer.setNextMediaPlayer(null);
} catch (IllegalArgumentException e) {
@ -102,13 +110,16 @@ public class MultiPlayer implements Playback, MediaPlayer.OnErrorListener, Media
Log.e(TAG, "Media player not initialized!");
return;
}
if (mNextMediaPlayer != null) {
mNextMediaPlayer.release();
mNextMediaPlayer = null;
}
if (path == null) {
return;
}
if (PreferenceUtil.getInstance(context).getGaplessPlayback()) {
mNextMediaPlayer = new MediaPlayer();
mNextMediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK);
@ -161,6 +172,7 @@ public class MultiPlayer implements Playback, MediaPlayer.OnErrorListener, Media
@Override
public void release() {
stop();
mCurrentMediaPlayer.release();
if (mNextMediaPlayer != null) {
mNextMediaPlayer.release();
@ -264,11 +276,9 @@ public class MultiPlayer implements Playback, MediaPlayer.OnErrorListener, Media
mCurrentMediaPlayer = mNextMediaPlayer;
mIsInitialized = true;
mNextMediaPlayer = null;
if (callbacks != null)
callbacks.onTrackWentToNext();
if (callbacks != null) callbacks.onTrackWentToNext();
} else {
if (callbacks != null)
callbacks.onTrackEnded();
if (callbacks != null) callbacks.onTrackEnded();
}
}
}

View file

@ -140,12 +140,14 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
private MediaSessionCompat mediaSession;
private PowerManager.WakeLock wakeLock;
private PlaybackHandler playerHandler;
private final AudioManager.OnAudioFocusChangeListener audioFocusListener = new AudioManager.OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(final int focusChange) {
playerHandler.obtainMessage(FOCUS_CHANGE, focusChange, 0).sendToTarget();
}
};
private QueueSaveHandler queueSaveHandler;
private HandlerThread musicPlayerHandlerThread;
private HandlerThread queueSaveHandlerThread;
@ -153,6 +155,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
private ThrottledSeekHandler throttledSeekHandler;
private boolean becomingNoisyReceiverRegistered;
private IntentFilter becomingNoisyReceiverIntentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
private final BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, @NonNull Intent intent) {
@ -161,6 +164,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
}
}
};
private ContentObserver mediaStoreObserver;
private boolean notHandledMetaChangedForCurrentTrack;
@ -200,6 +204,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
mediaStoreObserver = new MediaStoreObserver(playerHandler);
throttledSeekHandler = new ThrottledSeekHandler(playerHandler);
getContentResolver().registerContentObserver(
MediaStore.Audio.Media.INTERNAL_CONTENT_URI, true, mediaStoreObserver);
getContentResolver().registerContentObserver(
@ -339,6 +344,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
unregisterReceiver(becomingNoisyReceiver);
becomingNoisyReceiverRegistered = false;
}
mediaSession.setActive(false);
quit();
releaseResources();
@ -400,6 +406,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
private void restoreState() {
shuffleMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(SAVED_SHUFFLE_MODE, 0);
repeatMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(SAVED_REPEAT_MODE, 0);
handleAndSendChangeInternal(SHUFFLE_MODE_CHANGED);
handleAndSendChangeInternal(REPEAT_MODE_CHANGED);
@ -411,6 +418,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
if (!queuesRestored && playingQueue.isEmpty()) {
List<Song> restoredQueue = QueueStore.getInstance(this).getSavedPlayingQueue();
List<Song> restoredOriginalQueue = QueueStore.getInstance(this).getSavedOriginalPlayingQueue();
int restoredPosition = PreferenceManager.getDefaultSharedPreferences(this).getInt(SAVED_POSITION, -1);
int restoredPositionInTrack = PreferenceManager.getDefaultSharedPreferences(this).getInt(SAVED_POSITION_IN_TRACK, -1);
@ -429,6 +437,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
sendChangeInternal(QUEUE_CHANGED);
}
}
queuesRestored = true;
}
@ -448,12 +457,14 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
} else {
musicPlayerHandlerThread.quit();
}
queueSaveHandler.removeCallbacksAndMessages(null);
if (Build.VERSION.SDK_INT >= 18) {
queueSaveHandlerThread.quitSafely();
} else {
queueSaveHandlerThread.quit();
}
playback.release();
playback = null;
mediaSession.release();
@ -527,6 +538,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
} else {
playingNotification = new PlayingNotificationImpl();
}
playingNotification.init(this);
}
@ -540,8 +552,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
mediaSession.setPlaybackState(
new PlaybackStateCompat.Builder()
.setActions(MEDIA_SESSION_ACTIONS)
.setState(isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
getPosition(), 1)
.setState(isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED, getPosition(), 1)
.build());
}
@ -865,11 +876,13 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
if (!songs.isEmpty()) {
startPosition = new Random().nextInt(songs.size());
}
openQueue(songs, startPosition, false);
setShuffleMode(shuffleMode);
} else {
openQueue(songs, 0, false);
}
play();
} else {
Toast.makeText(getApplicationContext(), R.string.playlist_is_empty, Toast.LENGTH_LONG).show();

View file

@ -15,9 +15,6 @@ import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.util.ImageUtil;
import com.kabouzeid.gramophone.util.PreferenceUtil;
/**
* @author Adrian Campos
*/
@RequiresApi(Build.VERSION_CODES.N_MR1)
public final class AppShortcutIconGenerator {

View file

@ -10,10 +10,6 @@ import com.kabouzeid.gramophone.shortcuts.shortcuttype.FrequentShortcutType;
import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.service.MusicService;
/**
* @author Adrian Campos
*/
public class AppShortcutLauncherActivity extends Activity {
public static final String KEY_SHORTCUT_TYPE = "com.kabouzeid.gramophone.shortcuts.ShortcutType";

View file

@ -15,10 +15,6 @@ import com.kabouzeid.gramophone.shortcuts.shortcuttype.FrequentShortcutType;
import java.util.Arrays;
import java.util.List;
/**
* @author Adrian Campos
*/
@TargetApi(Build.VERSION_CODES.N_MR1)
public class DynamicShortcutManager {

View file

@ -9,9 +9,6 @@ import android.os.Bundle;
import com.kabouzeid.gramophone.shortcuts.AppShortcutLauncherActivity;
/**
* @author Adrian Campos
*/
@TargetApi(Build.VERSION_CODES.N_MR1)
public abstract class BaseShortcutType {

View file

@ -9,9 +9,6 @@ import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.shortcuts.AppShortcutIconGenerator;
import com.kabouzeid.gramophone.shortcuts.AppShortcutLauncherActivity;
/**
* @author Adrian Campos
*/
@TargetApi(Build.VERSION_CODES.N_MR1)
public final class FrequentShortcutType extends BaseShortcutType {
public FrequentShortcutType(Context context) {

View file

@ -9,9 +9,6 @@ import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.shortcuts.AppShortcutIconGenerator;
import com.kabouzeid.gramophone.shortcuts.AppShortcutLauncherActivity;
/**
* @author Adrian Campos
*/
@TargetApi(Build.VERSION_CODES.N_MR1)
public final class LatestShortcutType extends BaseShortcutType {
public LatestShortcutType(Context context) {

View file

@ -9,9 +9,6 @@ import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.shortcuts.AppShortcutIconGenerator;
import com.kabouzeid.gramophone.shortcuts.AppShortcutLauncherActivity;
/**
* @author Adrian Campos
*/
@TargetApi(Build.VERSION_CODES.N_MR1)
public final class ShuffleShortcutType extends BaseShortcutType {
public ShuffleShortcutType(Context context) {

View file

@ -16,7 +16,6 @@ import android.widget.TextView;
import com.kabouzeid.appthemehelper.ThemeStore;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.adapter.SearchAdapter;
import com.kabouzeid.gramophone.interfaces.LoaderIds;
import com.kabouzeid.gramophone.interfaces.MediaCallback;
import com.kabouzeid.gramophone.model.Album;
import com.kabouzeid.gramophone.model.Artist;

View file

@ -9,9 +9,6 @@ import android.view.View;
import com.kabouzeid.gramophone.interfaces.MusicServiceEventListener;
import com.kabouzeid.gramophone.ui.activities.base.AbsMusicServiceActivity;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class AbsMusicServiceFragment extends Fragment implements MusicServiceEventListener {
private AbsMusicServiceActivity activity;
@ -45,41 +42,33 @@ public class AbsMusicServiceFragment extends Fragment implements MusicServiceEve
@Override
public void onPlayingMetaChanged() {
}
@Override
public void onServiceConnected() {
}
@Override
public void onServiceDisconnected() {
}
@Override
public void onQueueChanged() {
}
@Override
public void onPlayStateChanged() {
}
@Override
public void onRepeatModeChanged() {
}
@Override
public void onShuffleModeChanged() {
}
@Override
public void onMediaStoreChanged() {
}
}

View file

@ -5,11 +5,7 @@ import androidx.fragment.app.Fragment;
import com.kabouzeid.gramophone.ui.activities.MainActivity;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public abstract class AbsMainActivityFragment extends Fragment {
public MainActivity getMainActivity() {
return (MainActivity) getActivity();
}

View file

@ -1,6 +1,5 @@
package com.kabouzeid.gramophone.ui.fragments.mainactivity.library;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
@ -207,6 +206,7 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde
menu.removeItem(R.id.action_colored_footers);
menu.removeItem(R.id.action_sort_order);
}
Activity activity = getActivity();
if (activity == null) return;
ToolbarContentTintHelper.handleOnCreateOptionsMenu(getActivity(), toolbar, menu, ATHToolbarActivity.getToolbarBackgroundColor(toolbar));
@ -234,6 +234,7 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde
if (handleGridSizeMenuItem(absLibraryRecyclerViewCustomGridSizeFragment, item)) {
return true;
}
if (handleSortOrderMenuItem(absLibraryRecyclerViewCustomGridSizeFragment, item)) {
return true;
}
@ -251,6 +252,7 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde
startActivity(new Intent(getActivity(), SearchActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
@ -330,12 +332,14 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde
gridSize = 8;
break;
}
if (gridSize > 0) {
item.setChecked(true);
fragment.setAndSaveGridSize(gridSize);
toolbar.getMenu().findItem(R.id.action_colored_footers).setEnabled(fragment.canUsePalette());
return true;
}
return false;
}
@ -434,6 +438,7 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde
cab.finish();
return true;
}
return false;
}

View file

@ -6,17 +6,7 @@ import androidx.loader.app.LoaderManager;
import com.kabouzeid.gramophone.ui.fragments.AbsMusicServiceFragment;
import com.kabouzeid.gramophone.ui.fragments.mainactivity.library.LibraryFragment;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class AbsLibraryPagerFragment extends AbsMusicServiceFragment {
/* http://stackoverflow.com/a/2888433 */
@Override
public LoaderManager getLoaderManager() {
return getParentFragment().getLoaderManager();
}
public LibraryFragment getLibraryFragment() {
return (LibraryFragment) getParentFragment();
}

View file

@ -9,9 +9,6 @@ import android.view.View;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.util.Util;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public abstract class AbsLibraryPagerRecyclerViewCustomGridSizeFragment<A extends RecyclerView.Adapter, LM extends RecyclerView.LayoutManager> extends AbsLibraryPagerRecyclerViewFragment<A, LM> {
private int gridSize;
private String sortOrder;
@ -28,6 +25,7 @@ public abstract class AbsLibraryPagerRecyclerViewCustomGridSizeFragment<A extend
gridSize = loadGridSize();
}
}
return gridSize;
}
@ -39,14 +37,12 @@ public abstract class AbsLibraryPagerRecyclerViewCustomGridSizeFragment<A extend
}
}
/**
* @return whether the palette should be used at all or not
*/
public final boolean usePalette() {
if (!usePaletteInitialized) {
usePalette = loadUsePalette();
usePaletteInitialized = true;
}
return usePalette;
}
@ -54,6 +50,7 @@ public abstract class AbsLibraryPagerRecyclerViewCustomGridSizeFragment<A extend
if (sortOrder == null) {
sortOrder = loadSortOrder();
}
return sortOrder;
}
@ -65,6 +62,7 @@ public abstract class AbsLibraryPagerRecyclerViewCustomGridSizeFragment<A extend
} else {
saveGridSize(gridSize);
}
// only recreate the adapter and layout manager if the layout currentLayoutRes has changed
if (oldLayoutRes != getItemLayoutRes()) {
invalidateLayoutManager();
@ -86,18 +84,10 @@ public abstract class AbsLibraryPagerRecyclerViewCustomGridSizeFragment<A extend
setSortOrder(sortOrder);
}
/**
* @return whether the palette option should be available for the current item layout or not
*/
public boolean canUsePalette() {
return getItemLayoutRes() == R.layout.item_grid;
}
/**
* Override to customize which item layout currentLayoutRes should be used. You might also want to override {@link #canUsePalette()} then.
*
* @see #getGridSize()
*/
@LayoutRes
protected int getItemLayoutRes() {
if (getGridSize() > getMaxGridSizeForList()) {
@ -156,6 +146,7 @@ public abstract class AbsLibraryPagerRecyclerViewCustomGridSizeFragment<A extend
if (isLandscape()) {
return getActivity().getResources().getInteger(R.integer.default_list_columns_land);
}
return getActivity().getResources().getInteger(R.integer.default_list_columns);
}

View file

@ -21,9 +21,6 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public abstract class AbsLibraryPagerRecyclerViewFragment<A extends RecyclerView.Adapter, LM extends RecyclerView.LayoutManager> extends AbsLibraryPagerFragment implements OnOffsetChangedListener {
private Unbinder unbinder;

View file

@ -17,9 +17,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class AlbumsFragment extends AbsLibraryPagerRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridLayoutManager> {
@Override
public void onActivityCreated(Bundle savedInstanceState) {

View file

@ -16,9 +16,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class ArtistsFragment extends AbsLibraryPagerRecyclerViewCustomGridSizeFragment<ArtistAdapter, GridLayoutManager> {
@Override
public void onActivityCreated(Bundle savedInstanceState) {

View file

@ -1,6 +1,5 @@
package com.kabouzeid.gramophone.ui.fragments.mainactivity.library.pager;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
@ -8,19 +7,13 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.adapter.PlaylistAdapter;
import com.kabouzeid.gramophone.interfaces.LoaderIds;
import com.kabouzeid.gramophone.interfaces.MediaCallback;
import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.util.QueryUtil;
import org.jellyfin.apiclient.model.querying.ItemQuery;
import java.util.ArrayList;
import java.util.List;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class PlaylistsFragment extends AbsLibraryPagerRecyclerViewFragment<PlaylistAdapter, LinearLayoutManager> {
@Override
public void onActivityCreated(Bundle savedInstanceState) {

View file

@ -28,17 +28,16 @@ import butterknife.ButterKnife;
import butterknife.Unbinder;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class MiniPlayerFragment extends AbsMusicServiceFragment implements MusicProgressViewUpdateHelper.Callback {
private Unbinder unbinder;
@BindView(R.id.mini_player_title)
TextView miniPlayerTitle;
@BindView(R.id.mini_player_play_pause_button)
ImageView miniPlayerPlayPauseButton;
@BindView(R.id.progress_bar)
MaterialProgressBar progressBar;

View file

@ -11,6 +11,7 @@ public enum NowPlayingScreen {
@StringRes
public final int titleRes;
@DrawableRes
public final int drawableResId;
public final int id;

View file

@ -24,9 +24,6 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class PlayerAlbumCoverFragment extends AbsMusicServiceFragment implements ViewPager.OnPageChangeListener {
public static final int VISIBILITY_ANIM_DURATION = 300;

View file

@ -30,9 +30,6 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class CardPlayerPlaybackControlsFragment extends AbsMusicServiceFragment implements MusicProgressViewUpdateHelper.Callback {
private Unbinder unbinder;

View file

@ -127,6 +127,7 @@ public class FlatPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
if (slidingUpPanelLayout != null) {
slidingUpPanelLayout.removePanelSlideListener(this);
}
if (recyclerViewDragDropManager != null) {
recyclerViewDragDropManager.release();
recyclerViewDragDropManager = null;
@ -142,6 +143,7 @@ public class FlatPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
WrapperAdapterUtils.releaseAll(wrappedAdapter);
wrappedAdapter = null;
}
playingQueueAdapter = null;
layoutManager = null;
super.onDestroyView();
@ -328,8 +330,8 @@ public class FlatPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
onPanelCollapsed(panel);
break;
case ANCHORED:
//noinspection ConstantConditions
slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); // this fixes a bug where the panel would get stuck for some reason
// this fixes a bug where the panel would get stuck for some reason
slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
break;
}
}
@ -432,6 +434,7 @@ public class FlatPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
SongShareDialog.create(getSong()).show(fragment.getFragmentManager(), "SONG_SHARE_DIALOG");
return true;
}
return super.onMenuItemClick(item);
}
});

View file

@ -34,9 +34,6 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class FlatPlayerPlaybackControlsFragment extends AbsMusicServiceFragment implements MusicProgressViewUpdateHelper.Callback {
private Unbinder unbinder;

View file

@ -14,9 +14,6 @@ import com.kabouzeid.gramophone.ui.activities.ArtistDetailActivity;
import com.kabouzeid.gramophone.ui.activities.GenreDetailActivity;
import com.kabouzeid.gramophone.ui.activities.PlaylistDetailActivity;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class NavigationUtil {
public static void goToArtist(@NonNull final Activity activity, final String artistId, @Nullable Pair... sharedElements) {
@ -24,7 +21,7 @@ public class NavigationUtil {
intent.putExtra(ArtistDetailActivity.EXTRA_ARTIST_ID, artistId);
if (sharedElements != null && sharedElements.length > 0) {
//noinspection unchecked
// noinspection unchecked
activity.startActivity(intent, ActivityOptionsCompat.makeSceneTransitionAnimation(activity, sharedElements).toBundle());
} else {
activity.startActivity(intent);
@ -36,7 +33,7 @@ public class NavigationUtil {
intent.putExtra(AlbumDetailActivity.EXTRA_ALBUM_ID, albumId);
if (sharedElements != null && sharedElements.length > 0) {
//noinspection unchecked
// noinspection unchecked
activity.startActivity(intent, ActivityOptionsCompat.makeSceneTransitionAnimation(activity, sharedElements).toBundle());
} else {
activity.startActivity(intent);

View file

@ -25,7 +25,6 @@ import com.kabouzeid.gramophone.R;
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
public class ViewUtil {
public final static int PHONOGRAPH_ANIM_TIME = 1000;
public static Animator createBackgroundColorTransition(final View v, @ColorInt final int startColor, @ColorInt final int endColor) {

View file

@ -6,9 +6,6 @@ import android.os.Build;
import android.util.AttributeSet;
import android.widget.FrameLayout;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class HeightFitSquareLayout extends FrameLayout {
private boolean forceSquare = true;
@ -32,7 +29,6 @@ public class HeightFitSquareLayout extends FrameLayout {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//noinspection SuspiciousNameCombination
super.onMeasure(forceSquare ? heightMeasureSpec : widthMeasureSpec, heightMeasureSpec);
}

View file

@ -8,9 +8,6 @@ import android.util.AttributeSet;
import com.kabouzeid.appthemehelper.util.ATHUtil;
import com.kabouzeid.gramophone.R;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class IconImageView extends AppCompatImageView {
public IconImageView(Context context) {
super(context);

View file

@ -22,18 +22,17 @@ import com.kabouzeid.gramophone.R;
public class PlayPauseDrawable extends Drawable {
private static final long PLAY_PAUSE_ANIMATION_DURATION = 250;
private static final Property<PlayPauseDrawable, Float> PROGRESS =
new Property<PlayPauseDrawable, Float>(Float.class, "progress") {
@Override
public Float get(@NonNull PlayPauseDrawable d) {
return d.getProgress();
}
private static final Property<PlayPauseDrawable, Float> PROGRESS = new Property<PlayPauseDrawable, Float>(Float.class, "progress") {
@Override
public Float get(@NonNull PlayPauseDrawable d) {
return d.getProgress();
}
@Override
public void set(@NonNull PlayPauseDrawable d, Float value) {
d.setProgress(value);
}
};
@Override
public void set(@NonNull PlayPauseDrawable d, Float value) {
d.setProgress(value);
}
};
private final Path leftPauseBar = new Path();
private final Path rightPauseBar = new Path();
@ -77,13 +76,17 @@ public class PlayPauseDrawable extends Drawable {
// The current distance between the two pause bars.
final float barDist = lerp(pauseBarDistance, 0f, progress);
// The current width of each pause bar.
float rawBarWidth = lerp(pauseBarWidth, pauseBarHeight / 1.75f, progress);
// We have to round the bar width when finishing the progress to prevent the gap
// that might occur onDraw because of a pixel is lost when casting float to int instead of rounding it.
final float barWidth = progress == 1f ? Math.round(rawBarWidth) : rawBarWidth;
// The current position of the left pause bar's top left coordinate.
final float firstBarTopLeft = lerp(0f, barWidth, progress);
// The current position of the right pause bar's top right coordinate.
final float secondBarTopRight = lerp(2f * barWidth + barDist, barWidth + barDist, progress);
@ -136,6 +139,7 @@ public class PlayPauseDrawable extends Drawable {
isPlay = !isPlay;
}
});
return anim;
}

View file

@ -7,8 +7,6 @@ import android.view.WindowInsets;
import android.widget.FrameLayout;
public class StatusBarMarginFrameLayout extends FrameLayout {
public StatusBarMarginFrameLayout(Context context) {
super(context);
}
@ -28,6 +26,7 @@ public class StatusBarMarginFrameLayout extends FrameLayout {
lp.topMargin = insets.getSystemWindowInsetTop();
setLayoutParams(lp);
}
return super.onApplyWindowInsets(insets);
}
}

View file

@ -8,7 +8,6 @@ import android.view.ViewGroup;
import android.view.WindowInsets;
public class StatusBarView extends View {
public StatusBarView(Context context) {
super(context);
}
@ -28,7 +27,7 @@ public class StatusBarView extends View {
lp.height = insets.getSystemWindowInsetTop();
setLayoutParams(lp);
}
return super.onApplyWindowInsets(insets);
}
}

View file

@ -6,9 +6,6 @@ import android.os.Build;
import android.util.AttributeSet;
import android.widget.FrameLayout;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class WidthFitSquareLayout extends FrameLayout {
private boolean forceSquare = true;
@ -32,7 +29,6 @@ public class WidthFitSquareLayout extends FrameLayout {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//noinspection SuspiciousNameCombination
super.onMeasure(widthMeasureSpec, forceSquare ? widthMeasureSpec : heightMeasureSpec);
}

View file

@ -14,13 +14,15 @@ public class BootReceiver extends BroadcastReceiver {
public void onReceive(final Context context, Intent intent) {
final AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
// Start music service if there are any existing widgets
if (widgetManager.getAppWidgetIds(new ComponentName(context, AppWidgetBig.class)).length > 0 ||
widgetManager.getAppWidgetIds(new ComponentName(context, AppWidgetClassic.class)).length > 0 ||
widgetManager.getAppWidgetIds(new ComponentName(context, AppWidgetSmall.class)).length > 0 ||
widgetManager.getAppWidgetIds(new ComponentName(context, AppWidgetCard.class)).length > 0) {
// start music service if there are any existing widgets
if (widgetManager.getAppWidgetIds(new ComponentName(context, AppWidgetBig.class)).length > 0
|| widgetManager.getAppWidgetIds(new ComponentName(context, AppWidgetClassic.class)).length > 0
|| widgetManager.getAppWidgetIds(new ComponentName(context, AppWidgetSmall.class)).length > 0
|| widgetManager.getAppWidgetIds(new ComponentName(context, AppWidgetCard.class)).length > 0) {
final Intent serviceIntent = new Intent(context, MusicService.class);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { // not allowed on Oreo
// not allowed on Oreo
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
context.startService(serviceIntent);
}
}