kotlin conversion
This commit is contained in:
parent
8e6ab40d93
commit
b2c15ef186
316 changed files with 13055 additions and 22983 deletions
|
@ -1,171 +0,0 @@
|
|||
package code.name.monkey.retromusic.helper;
|
||||
|
||||
import android.media.audiofx.BassBoost;
|
||||
import android.media.audiofx.Equalizer;
|
||||
import android.media.audiofx.Virtualizer;
|
||||
import android.util.Log;
|
||||
|
||||
import code.name.monkey.retromusic.interfaces.EqualizerInterface;
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
public class EqualizerHelper implements EqualizerInterface {
|
||||
private static final String TAG = "EqualizerHelper";
|
||||
private static volatile EqualizerHelper ourInstance;
|
||||
private Equalizer mEqualizer;
|
||||
private BassBoost mBassBoost;
|
||||
private Virtualizer mVirtualizer;
|
||||
|
||||
private int mMaxLevel, mMinLevel;
|
||||
private boolean isRunning = false;
|
||||
|
||||
private EqualizerHelper() {
|
||||
|
||||
//Prevent form the reflection api.
|
||||
if (ourInstance != null) {
|
||||
throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
|
||||
}
|
||||
|
||||
int i = MusicPlayerRemote.getAudioSessionId();
|
||||
|
||||
mEqualizer = new Equalizer(100, i);
|
||||
if (mEqualizer == null) {
|
||||
Log.i(TAG, "onCreate: Equalizer is null");
|
||||
return;
|
||||
}
|
||||
mEqualizer.setEnabled(true);
|
||||
|
||||
|
||||
mBassBoost = new BassBoost(100, i);
|
||||
if (mBassBoost == null) {
|
||||
Log.i(TAG, "onCreate: BassBoost is null");
|
||||
return;
|
||||
}
|
||||
|
||||
mVirtualizer = new Virtualizer(100, i);
|
||||
if (mVirtualizer == null) {
|
||||
Log.i(TAG, "onCreate: Virtualizer is null");
|
||||
return;
|
||||
}
|
||||
|
||||
mMaxLevel = (int) mEqualizer.getBandLevelRange()[1];
|
||||
mMinLevel = (int) mEqualizer.getBandLevelRange()[0];
|
||||
|
||||
Log.i(TAG, "onCreate: " + mMaxLevel + " " + mMinLevel);
|
||||
isRunning = true;
|
||||
}
|
||||
|
||||
public static EqualizerHelper getInstance() {
|
||||
//Double check locking pattern
|
||||
if (ourInstance == null) {//Check for the first time
|
||||
|
||||
synchronized (EqualizerHelper.class) {//Check for the second time.
|
||||
|
||||
//if there is no instance available... create new one
|
||||
if (ourInstance == null) {
|
||||
ourInstance = new EqualizerHelper();
|
||||
}
|
||||
}
|
||||
}
|
||||
return ourInstance;
|
||||
}
|
||||
|
||||
//Make singleton from serialize and deserialize operation.
|
||||
protected EqualizerHelper readResolve() {
|
||||
return getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Equalizer getEqualizer() {
|
||||
return mEqualizer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BassBoost getBassBoost() {
|
||||
return mBassBoost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Virtualizer getVirtualizer() {
|
||||
return mVirtualizer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBandLevelLow() {
|
||||
return mMinLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBandLevelHigh() {
|
||||
return mMaxLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfBands() {
|
||||
return (int) mEqualizer.getNumberOfBands();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCenterFreq(int band) {
|
||||
return (int) mEqualizer.getCenterFreq((short) band);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getBandLevel(int band) {
|
||||
return (int) mEqualizer.getBandLevel((short) band);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBandLevel(int band, int level) {
|
||||
mEqualizer.setBandLevel((short) band, (short) level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBassBoostEnabled() {
|
||||
return mBassBoost.getEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBassBoostEnabled(boolean isEnabled) {
|
||||
mBassBoost.setEnabled(isEnabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBassBoostStrength() {
|
||||
return (int) mBassBoost.getRoundedStrength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBassBoostStrength(int strength) {
|
||||
mBassBoost.setStrength((short) strength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtualizerEnabled() {
|
||||
return mVirtualizer.getEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVirtualizerEnabled(boolean isEnabled) {
|
||||
mVirtualizer.setEnabled(isEnabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVirtualizerStrength() {
|
||||
return mVirtualizer.getRoundedStrength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVirtualizerStrength(int strength) {
|
||||
mVirtualizer.setStrength((short) strength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return isRunning;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package code.name.monkey.retromusic.helper
|
||||
|
||||
import android.media.audiofx.BassBoost
|
||||
import android.media.audiofx.Equalizer
|
||||
import android.media.audiofx.Virtualizer
|
||||
import android.util.Log
|
||||
|
||||
import code.name.monkey.retromusic.interfaces.EqualizerInterface
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
class EqualizerHelper private constructor() : EqualizerInterface {
|
||||
override val equalizer: Equalizer
|
||||
override val bassBoost: BassBoost
|
||||
override val virtualizer: Virtualizer
|
||||
|
||||
override val bandLevelHigh: Int
|
||||
override val bandLevelLow: Int
|
||||
override var isRunning = false
|
||||
|
||||
override val numberOfBands: Int
|
||||
get() = equalizer.numberOfBands.toInt()
|
||||
|
||||
override var isBassBoostEnabled: Boolean
|
||||
get() = bassBoost.enabled
|
||||
set(isEnabled) {
|
||||
bassBoost.enabled = isEnabled
|
||||
}
|
||||
|
||||
override var bassBoostStrength: Int
|
||||
get() = bassBoost.roundedStrength.toInt()
|
||||
set(strength) = bassBoost.setStrength(strength.toShort())
|
||||
|
||||
override var isVirtualizerEnabled: Boolean
|
||||
get() = virtualizer.enabled
|
||||
set(isEnabled) {
|
||||
virtualizer.enabled = isEnabled
|
||||
}
|
||||
|
||||
override var virtualizerStrength: Int
|
||||
get() = virtualizer.roundedStrength.toInt()
|
||||
set(strength) = virtualizer.setStrength(strength.toShort())
|
||||
|
||||
init {
|
||||
|
||||
//Prevent form the reflection api.
|
||||
if (ourInstance != null) {
|
||||
throw RuntimeException("Use getInstance() method to get the single instance of this class.")
|
||||
}
|
||||
|
||||
val i = MusicPlayerRemote.audioSessionId
|
||||
|
||||
equalizer = Equalizer(100, i)
|
||||
|
||||
equalizer.enabled = true
|
||||
bassBoost = BassBoost(100, i)
|
||||
virtualizer = Virtualizer(100, i)
|
||||
|
||||
bandLevelHigh = equalizer.bandLevelRange[1].toInt()
|
||||
bandLevelLow = equalizer.bandLevelRange[0].toInt()
|
||||
|
||||
Log.i(TAG, "onCreate: $bandLevelHigh $bandLevelLow")
|
||||
isRunning = true
|
||||
}
|
||||
|
||||
//Make singleton from serialize and deserialize operation.
|
||||
protected fun readResolve(): EqualizerHelper? {
|
||||
return instance
|
||||
}
|
||||
|
||||
override fun getCenterFreq(band: Int): Int {
|
||||
return equalizer.getCenterFreq(band.toShort())
|
||||
}
|
||||
|
||||
|
||||
override fun getBandLevel(band: Int): Int {
|
||||
return equalizer.getBandLevel(band.toShort()).toInt()
|
||||
}
|
||||
|
||||
override fun setBandLevel(band: Int, level: Int) {
|
||||
equalizer.setBandLevel(band.toShort(), level.toShort())
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = "EqualizerHelper"
|
||||
@Volatile
|
||||
private var ourInstance: EqualizerHelper? = null
|
||||
|
||||
//Double check locking pattern
|
||||
//Check for the first time
|
||||
//Check for the second time.
|
||||
//if there is no instance available... create new one
|
||||
val instance: EqualizerHelper?
|
||||
get() {
|
||||
if (ourInstance == null) {
|
||||
|
||||
synchronized(EqualizerHelper::class.java) {
|
||||
if (ourInstance == null) {
|
||||
ourInstance = EqualizerHelper()
|
||||
}
|
||||
}
|
||||
}
|
||||
return ourInstance
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package code.name.monkey.retromusic.helper;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.ViewGroup;
|
||||
import code.name.monkey.retromusic.R;
|
||||
|
||||
|
||||
public class HorizontalAdapterHelper {
|
||||
|
||||
public static final int LAYOUT_RES = R.layout.item_image;
|
||||
|
||||
public static final int TYPE_FIRST = 1;
|
||||
public static final int TYPE_MIDDLE = 2;
|
||||
public static final int TYPE_LAST = 3;
|
||||
|
||||
public static void applyMarginToLayoutParams(Context context,
|
||||
ViewGroup.MarginLayoutParams layoutParams, int viewType) {
|
||||
int listMargin = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.now_playing_top_margin);
|
||||
if (viewType == TYPE_FIRST) {
|
||||
layoutParams.leftMargin = listMargin;
|
||||
} else if (viewType == TYPE_LAST) {
|
||||
layoutParams.rightMargin = listMargin;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getItemViewtype(int position, int itemCount) {
|
||||
if (position == 0) {
|
||||
return TYPE_FIRST;
|
||||
} else if (position == itemCount - 1) {
|
||||
return TYPE_LAST;
|
||||
} else {
|
||||
return TYPE_MIDDLE;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package code.name.monkey.retromusic.helper
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import code.name.monkey.retromusic.R
|
||||
|
||||
|
||||
object HorizontalAdapterHelper {
|
||||
|
||||
val LAYOUT_RES = R.layout.item_image
|
||||
|
||||
val TYPE_FIRST = 1
|
||||
val TYPE_MIDDLE = 2
|
||||
val TYPE_LAST = 3
|
||||
|
||||
fun applyMarginToLayoutParams(context: Context,
|
||||
layoutParams: ViewGroup.MarginLayoutParams, viewType: Int) {
|
||||
val listMargin = context.resources
|
||||
.getDimensionPixelSize(R.dimen.now_playing_top_margin)
|
||||
if (viewType == TYPE_FIRST) {
|
||||
layoutParams.leftMargin = listMargin
|
||||
} else if (viewType == TYPE_LAST) {
|
||||
layoutParams.rightMargin = listMargin
|
||||
}
|
||||
}
|
||||
|
||||
fun getItemViewtype(position: Int, itemCount: Int): Int {
|
||||
return if (position == 0) {
|
||||
TYPE_FIRST
|
||||
} else if (position == itemCount - 1) {
|
||||
TYPE_LAST
|
||||
} else {
|
||||
TYPE_MIDDLE
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package code.name.monkey.retromusic.helper;
|
||||
|
||||
public interface M3UConstants {
|
||||
String EXTENSION = "m3u";
|
||||
String HEADER = "#EXTM3U";
|
||||
String ENTRY = "#EXTINF:";
|
||||
String DURATION_SEPARATOR = ",";
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package code.name.monkey.retromusic.helper
|
||||
|
||||
interface M3UConstants {
|
||||
companion object {
|
||||
val EXTENSION = "m3u"
|
||||
val HEADER = "#EXTM3U"
|
||||
val ENTRY = "#EXTINF:"
|
||||
val DURATION_SEPARATOR = ","
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
package code.name.monkey.retromusic.helper;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader;
|
||||
import code.name.monkey.retromusic.model.AbsCustomPlaylist;
|
||||
import code.name.monkey.retromusic.model.Playlist;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.ObservableEmitter;
|
||||
|
||||
public class M3UWriter implements M3UConstants {
|
||||
public static final String TAG = M3UWriter.class.getSimpleName();
|
||||
|
||||
public static Observable<File> write(@NonNull Context context,
|
||||
@NonNull File dir, @NonNull Playlist playlist) {
|
||||
if (!dir.exists()) //noinspection ResultOfMethodCallIgnored
|
||||
dir.mkdirs();
|
||||
File file = new File(dir, playlist.name.concat("." + EXTENSION));
|
||||
|
||||
if (playlist instanceof AbsCustomPlaylist) {
|
||||
return Observable.create(e -> {
|
||||
((AbsCustomPlaylist) playlist).getSongs(context).subscribe(songs -> {
|
||||
saveSongsToFile(file, e, songs);
|
||||
});
|
||||
});
|
||||
} else
|
||||
return Observable.create(e ->
|
||||
PlaylistSongsLoader.getPlaylistSongList(context, playlist.id)
|
||||
.subscribe(songs -> {
|
||||
saveSongsToFile(file, e, songs);
|
||||
}));
|
||||
}
|
||||
|
||||
private static void saveSongsToFile(File file, ObservableEmitter<File> e, ArrayList<Song> songs) throws IOException {
|
||||
if (songs.size() > 0) {
|
||||
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
|
||||
bw.write(HEADER);
|
||||
for (Song song : songs) {
|
||||
bw.newLine();
|
||||
bw.write(ENTRY + song.duration + DURATION_SEPARATOR + song.artistName + " - " + song.title);
|
||||
bw.newLine();
|
||||
bw.write(song.data);
|
||||
}
|
||||
|
||||
bw.close();
|
||||
}
|
||||
e.onNext(file);
|
||||
e.onComplete();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package code.name.monkey.retromusic.helper
|
||||
|
||||
import android.content.Context
|
||||
|
||||
import java.io.BufferedWriter
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
import java.io.IOException
|
||||
import java.util.ArrayList
|
||||
|
||||
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
|
||||
import code.name.monkey.retromusic.model.AbsCustomPlaylist
|
||||
import code.name.monkey.retromusic.model.Playlist
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.ObservableEmitter
|
||||
|
||||
class M3UWriter : M3UConstants {
|
||||
companion object {
|
||||
val TAG: String = M3UWriter::class.java.simpleName
|
||||
|
||||
fun write(context: Context,
|
||||
dir: File, playlist: Playlist): Observable<File> {
|
||||
if (!dir.exists())
|
||||
|
||||
dir.mkdirs()
|
||||
val file = File(dir, playlist.name + ("." + M3UConstants.EXTENSION))
|
||||
|
||||
return if (playlist is AbsCustomPlaylist) {
|
||||
Observable.create { e -> playlist.getSongs(context).subscribe { songs -> saveSongsToFile(file, e, songs) } }
|
||||
} else
|
||||
Observable.create { e -> PlaylistSongsLoader.getPlaylistSongList(context, playlist.id).subscribe { songs -> saveSongsToFile(file, e, songs) } }
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun saveSongsToFile(file: File, e: ObservableEmitter<File>, songs: ArrayList<Song>) {
|
||||
if (songs.size > 0) {
|
||||
val bw = BufferedWriter(FileWriter(file))
|
||||
bw.write(M3UConstants.HEADER)
|
||||
for (song in songs) {
|
||||
bw.newLine()
|
||||
bw.write(M3UConstants.ENTRY + song.duration + M3UConstants.DURATION_SEPARATOR + song.artistName + " - " + song.title)
|
||||
bw.newLine()
|
||||
bw.write(song.data)
|
||||
}
|
||||
|
||||
bw.close()
|
||||
}
|
||||
e.onNext(file)
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,496 +0,0 @@
|
|||
package code.name.monkey.retromusic.helper;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.IBinder;
|
||||
import android.provider.DocumentsContract;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.gms.cast.framework.CastContext;
|
||||
import com.google.android.gms.cast.framework.CastSession;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.RetroApplication;
|
||||
import code.name.monkey.retromusic.loaders.SongLoader;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.service.MusicService;
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
|
||||
public class MusicPlayerRemote {
|
||||
public static final String TAG = MusicPlayerRemote.class.getSimpleName();
|
||||
private static final WeakHashMap<Context, ServiceBinder> mConnectionMap = new WeakHashMap<>();
|
||||
@Nullable
|
||||
public static MusicService musicService;
|
||||
private static int playbackLocation = PlaybackLocation.LOCAL;
|
||||
|
||||
|
||||
private static CastSession getCastSession() {
|
||||
CastSession castSession = CastContext.getSharedInstance(RetroApplication.getInstance()).getSessionManager().getCurrentCastSession();
|
||||
if (castSession != null) {
|
||||
playbackLocation = PlaybackLocation.REMOTE;
|
||||
} else {
|
||||
playbackLocation = PlaybackLocation.LOCAL;
|
||||
}
|
||||
return castSession;
|
||||
}
|
||||
|
||||
public static ServiceToken bindToService(@NonNull final Context context,
|
||||
final ServiceConnection callback) {
|
||||
|
||||
Activity realActivity = ((Activity) context).getParent();
|
||||
if (realActivity == null) {
|
||||
realActivity = (Activity) context;
|
||||
}
|
||||
|
||||
final ContextWrapper contextWrapper = new ContextWrapper(realActivity);
|
||||
contextWrapper.startService(new Intent(contextWrapper, MusicService.class));
|
||||
|
||||
final ServiceBinder binder = new ServiceBinder(callback);
|
||||
|
||||
if (contextWrapper.bindService(new Intent().setClass(contextWrapper, MusicService.class), binder, Context.BIND_AUTO_CREATE)) {
|
||||
mConnectionMap.put(contextWrapper, binder);
|
||||
return new ServiceToken(contextWrapper);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void unbindFromService(@Nullable final ServiceToken token) {
|
||||
if (token == null) {
|
||||
return;
|
||||
}
|
||||
final ContextWrapper mContextWrapper = token.mWrappedContext;
|
||||
final ServiceBinder mBinder = mConnectionMap.remove(mContextWrapper);
|
||||
if (mBinder == null) {
|
||||
return;
|
||||
}
|
||||
mContextWrapper.unbindService(mBinder);
|
||||
if (mConnectionMap.isEmpty()) {
|
||||
musicService = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getFilePathFromUri(Context context, Uri uri) {
|
||||
|
||||
final String column = "_data";
|
||||
final String[] projection = {
|
||||
column
|
||||
};
|
||||
try (Cursor cursor = context.getContentResolver().query(uri, projection, null, null,
|
||||
null)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
final int column_index = cursor.getColumnIndexOrThrow(column);
|
||||
return cursor.getString(column_index);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Async
|
||||
*/
|
||||
public static void playSongAt(final int position) {
|
||||
if (musicService != null) {
|
||||
musicService.playSongAt(position);
|
||||
}
|
||||
}
|
||||
|
||||
public static void pauseSong() {
|
||||
if (musicService != null) {
|
||||
musicService.pause();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Async
|
||||
*/
|
||||
public static void playNextSong() {
|
||||
if (musicService != null) {
|
||||
musicService.playNextSong(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Async
|
||||
*/
|
||||
public static void playPreviousSong() {
|
||||
if (musicService != null) {
|
||||
musicService.playPreviousSong(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Async
|
||||
*/
|
||||
public static void back() {
|
||||
if (musicService != null) {
|
||||
musicService.back(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPlaying() {
|
||||
return musicService != null && musicService.isPlaying();
|
||||
}
|
||||
|
||||
public static void resumePlaying() {
|
||||
if (musicService != null) {
|
||||
musicService.play();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Async
|
||||
*/
|
||||
public static void openQueue(final ArrayList<Song> queue, final int startPosition, final boolean startPlaying) {
|
||||
if (!tryToHandleOpenPlayingQueue(queue, startPosition, startPlaying) && musicService != null) {
|
||||
musicService.openQueue(queue, startPosition, startPlaying);
|
||||
if (PreferenceUtil.getInstance().isShuffleModeOn())
|
||||
setShuffleMode(MusicService.SHUFFLE_MODE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Async
|
||||
*/
|
||||
public static void openAndShuffleQueue(final ArrayList<Song> queue, boolean startPlaying) {
|
||||
int startPosition = 0;
|
||||
if (!queue.isEmpty()) {
|
||||
startPosition = new Random().nextInt(queue.size());
|
||||
}
|
||||
|
||||
if (!tryToHandleOpenPlayingQueue(queue, startPosition, startPlaying) && musicService != null) {
|
||||
openQueue(queue, startPosition, startPlaying);
|
||||
setShuffleMode(MusicService.SHUFFLE_MODE_SHUFFLE);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean tryToHandleOpenPlayingQueue(final ArrayList<Song> queue, final int startPosition, final boolean startPlaying) {
|
||||
if (getPlayingQueue() == queue) {
|
||||
if (startPlaying) {
|
||||
playSongAt(startPosition);
|
||||
} else {
|
||||
setPosition(startPosition);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Song getCurrentSong() {
|
||||
if (musicService != null) {
|
||||
return musicService.getCurrentSong();
|
||||
}
|
||||
return Song.EMPTY_SONG;
|
||||
}
|
||||
|
||||
public static int getPosition() {
|
||||
if (musicService != null) {
|
||||
return musicService.getPosition();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Async
|
||||
*/
|
||||
public static void setPosition(final int position) {
|
||||
if (musicService != null) {
|
||||
musicService.setPosition(position);
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayList<Song> getPlayingQueue() {
|
||||
if (musicService != null) {
|
||||
return musicService.getPlayingQueue();
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public static int getSongProgressMillis() {
|
||||
if (musicService != null) {
|
||||
return musicService.getSongProgressMillis();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int getSongDurationMillis() {
|
||||
if (musicService != null) {
|
||||
return musicService.getSongDurationMillis();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static long getQueueDurationMillis(int position) {
|
||||
if (musicService != null) {
|
||||
return musicService.getQueueDurationMillis(position);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int seekTo(int millis) {
|
||||
if (musicService != null) {
|
||||
return musicService.seek(millis);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int getRepeatMode() {
|
||||
if (musicService != null) {
|
||||
return musicService.getRepeatMode();
|
||||
}
|
||||
return MusicService.REPEAT_MODE_NONE;
|
||||
}
|
||||
|
||||
public static int getShuffleMode() {
|
||||
if (musicService != null) {
|
||||
return musicService.getShuffleMode();
|
||||
}
|
||||
return MusicService.SHUFFLE_MODE_NONE;
|
||||
}
|
||||
|
||||
public static boolean cycleRepeatMode() {
|
||||
if (musicService != null) {
|
||||
musicService.cycleRepeatMode();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean toggleShuffleMode() {
|
||||
if (musicService != null) {
|
||||
musicService.toggleShuffle();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean setShuffleMode(final int shuffleMode) {
|
||||
if (musicService != null) {
|
||||
musicService.setShuffleMode(shuffleMode);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean playNext(Song song) {
|
||||
if (musicService != null) {
|
||||
if (getPlayingQueue().size() > 0) {
|
||||
musicService.addSong(getPosition() + 1, song);
|
||||
} else {
|
||||
ArrayList<Song> queue = new ArrayList<>();
|
||||
queue.add(song);
|
||||
openQueue(queue, 0, false);
|
||||
}
|
||||
Toast.makeText(musicService, musicService.getResources().getString(R.string.added_title_to_playing_queue), Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean playNext(@NonNull ArrayList<Song> songs) {
|
||||
if (musicService != null) {
|
||||
if (getPlayingQueue().size() > 0) {
|
||||
musicService.addSongs(getPosition() + 1, songs);
|
||||
} else {
|
||||
openQueue(songs, 0, false);
|
||||
}
|
||||
final String toast = songs.size() == 1 ? musicService.getResources().getString(R.string.added_title_to_playing_queue) : musicService.getResources().getString(R.string.added_x_titles_to_playing_queue, songs.size());
|
||||
Toast.makeText(musicService, toast, Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean enqueue(Song song) {
|
||||
if (musicService != null) {
|
||||
if (getPlayingQueue().size() > 0) {
|
||||
musicService.addSong(song);
|
||||
} else {
|
||||
ArrayList<Song> queue = new ArrayList<>();
|
||||
queue.add(song);
|
||||
openQueue(queue, 0, false);
|
||||
}
|
||||
Toast.makeText(musicService, musicService.getResources().getString(R.string.added_title_to_playing_queue), Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean enqueue(@NonNull ArrayList<Song> songs) {
|
||||
if (musicService != null) {
|
||||
if (getPlayingQueue().size() > 0) {
|
||||
musicService.addSongs(songs);
|
||||
} else {
|
||||
openQueue(songs, 0, false);
|
||||
}
|
||||
final String toast = songs.size() == 1 ? musicService.getResources().getString(R.string.added_title_to_playing_queue) : musicService.getResources().getString(R.string.added_x_titles_to_playing_queue, songs.size());
|
||||
Toast.makeText(musicService, toast, Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean removeFromQueue(@NonNull Song song) {
|
||||
if (musicService != null) {
|
||||
musicService.removeSong(song);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean removeFromQueue(int position) {
|
||||
if (musicService != null && position >= 0 && position < getPlayingQueue().size()) {
|
||||
musicService.removeSong(position);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean moveSong(int from, int to) {
|
||||
if (musicService != null && from >= 0 && to >= 0 && from < getPlayingQueue().size() && to < getPlayingQueue().size()) {
|
||||
musicService.moveSong(from, to);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean clearQueue() {
|
||||
if (musicService != null) {
|
||||
musicService.clearQueue();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int getAudioSessionId() {
|
||||
if (musicService != null) {
|
||||
return musicService.getAudioSessionId();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void playFromUri(Uri uri) {
|
||||
if (musicService != null) {
|
||||
ArrayList<Song> songs = null;
|
||||
if (uri.getScheme() != null && uri.getAuthority() != null) {
|
||||
if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
|
||||
String songId = null;
|
||||
if (uri.getAuthority().equals("com.android.providers.media.documents")) {
|
||||
songId = getSongIdFromMediaProvider(uri);
|
||||
} else if (uri.getAuthority().equals("media")) {
|
||||
songId = uri.getLastPathSegment();
|
||||
}
|
||||
if (songId != null) {
|
||||
/* songs = SongLoader.getSongs(SongLoader.makeSongCursor(
|
||||
musicService,
|
||||
MediaStore.Audio.AudioColumns._ID + "=?",
|
||||
new String[]{songId}
|
||||
));*/
|
||||
songs = SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(
|
||||
musicService,
|
||||
MediaStore.Audio.AudioColumns._ID + "=?",
|
||||
new String[]{songId}))
|
||||
.subscribeOn(Schedulers.io()).blockingFirst();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (songs == null) {
|
||||
File songFile = null;
|
||||
if (uri.getAuthority() != null && uri.getAuthority().equals("com.android.externalstorage.documents")) {
|
||||
songFile = new File(Environment.getExternalStorageDirectory(), uri.getPath().split(":", 2)[1]);
|
||||
}
|
||||
if (songFile == null) {
|
||||
String path = getFilePathFromUri(musicService, uri);
|
||||
if (path != null)
|
||||
songFile = new File(path);
|
||||
}
|
||||
if (songFile == null && uri.getPath() != null) {
|
||||
songFile = new File(uri.getPath());
|
||||
}
|
||||
if (songFile != null) {
|
||||
songs = SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(
|
||||
musicService,
|
||||
MediaStore.Audio.AudioColumns.DATA + "=?",
|
||||
new String[]{songFile.getAbsolutePath()}
|
||||
)).blockingFirst();
|
||||
}
|
||||
}
|
||||
if (songs != null && !songs.isEmpty()) {
|
||||
openQueue(songs, 0, true);
|
||||
} else {
|
||||
//TODO the file is not listed in the media store
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
private static String getSongIdFromMediaProvider(Uri uri) {
|
||||
return DocumentsContract.getDocumentId(uri).split(":")[1];
|
||||
}
|
||||
|
||||
public static boolean isServiceConnected() {
|
||||
return musicService != null;
|
||||
}
|
||||
|
||||
@interface PlaybackLocation {
|
||||
int REMOTE = 0;
|
||||
int LOCAL = 1;
|
||||
}
|
||||
|
||||
public static final class ServiceBinder implements ServiceConnection {
|
||||
private final ServiceConnection mCallback;
|
||||
|
||||
ServiceBinder(final ServiceConnection callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName className, final IBinder service) {
|
||||
MusicService.MusicBinder binder = (MusicService.MusicBinder) service;
|
||||
musicService = binder.getService();
|
||||
if (mCallback != null) {
|
||||
mCallback.onServiceConnected(className, service);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(final ComponentName className) {
|
||||
if (mCallback != null) {
|
||||
mCallback.onServiceDisconnected(className);
|
||||
}
|
||||
musicService = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ServiceToken {
|
||||
ContextWrapper mWrappedContext;
|
||||
|
||||
ServiceToken(final ContextWrapper context) {
|
||||
mWrappedContext = context;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,440 @@
|
|||
package code.name.monkey.retromusic.helper
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.app.Activity
|
||||
import android.content.*
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.os.IBinder
|
||||
import android.provider.DocumentsContract
|
||||
import android.provider.MediaStore
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.RetroApplication
|
||||
import code.name.monkey.retromusic.loaders.SongLoader
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import com.google.android.gms.cast.framework.CastContext
|
||||
import com.google.android.gms.cast.framework.CastSession
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
|
||||
object MusicPlayerRemote {
|
||||
val TAG = MusicPlayerRemote::class.java.simpleName
|
||||
private val mConnectionMap = WeakHashMap<Context, ServiceBinder>()
|
||||
var musicService: MusicService? = null
|
||||
private var playbackLocation = PlaybackLocation.LOCAL
|
||||
|
||||
|
||||
private val castSession: CastSession?
|
||||
get() {
|
||||
val castSession = CastContext.getSharedInstance(RetroApplication.instance).sessionManager.currentCastSession
|
||||
if (castSession != null) {
|
||||
playbackLocation = PlaybackLocation.REMOTE
|
||||
} else {
|
||||
playbackLocation = PlaybackLocation.LOCAL
|
||||
}
|
||||
return castSession
|
||||
}
|
||||
|
||||
val isPlaying: Boolean
|
||||
get() = musicService != null && musicService!!.isPlaying
|
||||
|
||||
val currentSong: Song
|
||||
get() = if (musicService != null) {
|
||||
musicService!!.currentSong
|
||||
} else Song.EMPTY_SONG
|
||||
|
||||
/**
|
||||
* Async
|
||||
*/
|
||||
var position: Int
|
||||
get() = if (musicService != null) {
|
||||
musicService!!.position
|
||||
} else -1
|
||||
set(position) {
|
||||
if (musicService != null) {
|
||||
musicService!!.position = position
|
||||
}
|
||||
}
|
||||
|
||||
val playingQueue: ArrayList<Song>
|
||||
get() = if (musicService != null) {
|
||||
musicService!!.playingQueue
|
||||
} else ArrayList()
|
||||
|
||||
val songProgressMillis: Int
|
||||
get() = if (musicService != null) {
|
||||
musicService!!.songProgressMillis
|
||||
} else -1
|
||||
|
||||
val songDurationMillis: Int
|
||||
get() = if (musicService != null) {
|
||||
musicService!!.songDurationMillis
|
||||
} else -1
|
||||
|
||||
val repeatMode: Int
|
||||
get() = if (musicService != null) {
|
||||
musicService!!.repeatMode
|
||||
} else MusicService.REPEAT_MODE_NONE
|
||||
|
||||
val shuffleMode: Int
|
||||
get() = if (musicService != null) {
|
||||
musicService!!.shuffleMode
|
||||
} else MusicService.SHUFFLE_MODE_NONE
|
||||
|
||||
val audioSessionId: Int
|
||||
get() = if (musicService != null) {
|
||||
musicService!!.audioSessionId
|
||||
} else -1
|
||||
|
||||
val isServiceConnected: Boolean
|
||||
get() = musicService != null
|
||||
|
||||
fun bindToService(context: Context,
|
||||
callback: ServiceConnection): ServiceToken? {
|
||||
|
||||
var realActivity: Activity? = (context as Activity).parent
|
||||
if (realActivity == null) {
|
||||
realActivity = context
|
||||
}
|
||||
|
||||
val contextWrapper = ContextWrapper(realActivity)
|
||||
contextWrapper.startService(Intent(contextWrapper, MusicService::class.java))
|
||||
|
||||
val binder = ServiceBinder(callback)
|
||||
|
||||
if (contextWrapper.bindService(Intent().setClass(contextWrapper, MusicService::class.java), binder, Context.BIND_AUTO_CREATE)) {
|
||||
mConnectionMap[contextWrapper] = binder
|
||||
return ServiceToken(contextWrapper)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun unbindFromService(token: ServiceToken?) {
|
||||
if (token == null) {
|
||||
return
|
||||
}
|
||||
val mContextWrapper = token.mWrappedContext
|
||||
val mBinder = mConnectionMap.remove(mContextWrapper) ?: return
|
||||
mContextWrapper.unbindService(mBinder)
|
||||
if (mConnectionMap.isEmpty()) {
|
||||
musicService = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFilePathFromUri(context: Context, uri: Uri): String? {
|
||||
|
||||
val column = "_data"
|
||||
val projection = arrayOf(column)
|
||||
try {
|
||||
context.contentResolver.query(uri, projection, null, null, null)!!.use { cursor ->
|
||||
if (cursor.moveToFirst()) {
|
||||
val column_index = cursor.getColumnIndexOrThrow(column)
|
||||
return cursor.getString(column_index)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, e.message)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Async
|
||||
*/
|
||||
fun playSongAt(position: Int) {
|
||||
if (musicService != null) {
|
||||
musicService!!.playSongAt(position)
|
||||
}
|
||||
}
|
||||
|
||||
fun pauseSong() {
|
||||
if (musicService != null) {
|
||||
musicService!!.pause()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Async
|
||||
*/
|
||||
fun playNextSong() {
|
||||
if (musicService != null) {
|
||||
musicService!!.playNextSong(true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Async
|
||||
*/
|
||||
fun playPreviousSong() {
|
||||
if (musicService != null) {
|
||||
musicService!!.playPreviousSong(true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Async
|
||||
*/
|
||||
fun back() {
|
||||
if (musicService != null) {
|
||||
musicService!!.back(true)
|
||||
}
|
||||
}
|
||||
|
||||
fun resumePlaying() {
|
||||
if (musicService != null) {
|
||||
musicService!!.play()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Async
|
||||
*/
|
||||
fun openQueue(queue: ArrayList<Song>, startPosition: Int, startPlaying: Boolean) {
|
||||
if (!tryToHandleOpenPlayingQueue(queue, startPosition, startPlaying) && musicService != null) {
|
||||
musicService!!.openQueue(queue, startPosition, startPlaying)
|
||||
if (PreferenceUtil.getInstance().isShuffleModeOn)
|
||||
setShuffleMode(MusicService.SHUFFLE_MODE_NONE)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Async
|
||||
*/
|
||||
fun openAndShuffleQueue(queue: ArrayList<Song>, startPlaying: Boolean) {
|
||||
var startPosition = 0
|
||||
if (!queue.isEmpty()) {
|
||||
startPosition = Random().nextInt(queue.size)
|
||||
}
|
||||
|
||||
if (!tryToHandleOpenPlayingQueue(queue, startPosition, startPlaying) && musicService != null) {
|
||||
openQueue(queue, startPosition, startPlaying)
|
||||
setShuffleMode(MusicService.SHUFFLE_MODE_SHUFFLE)
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryToHandleOpenPlayingQueue(queue: ArrayList<Song>, startPosition: Int, startPlaying: Boolean): Boolean {
|
||||
if (playingQueue === queue) {
|
||||
if (startPlaying) {
|
||||
playSongAt(startPosition)
|
||||
} else {
|
||||
position = startPosition
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun getQueueDurationMillis(position: Int): Long {
|
||||
return if (musicService != null) {
|
||||
musicService!!.getQueueDurationMillis(position)
|
||||
} else -1
|
||||
}
|
||||
|
||||
fun seekTo(millis: Int): Int {
|
||||
return if (musicService != null) {
|
||||
musicService!!.seek(millis)
|
||||
} else -1
|
||||
}
|
||||
|
||||
fun cycleRepeatMode(): Boolean {
|
||||
if (musicService != null) {
|
||||
musicService!!.cycleRepeatMode()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun toggleShuffleMode(): Boolean {
|
||||
if (musicService != null) {
|
||||
musicService!!.toggleShuffle()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun setShuffleMode(shuffleMode: Int): Boolean {
|
||||
if (musicService != null) {
|
||||
musicService!!.shuffleMode = shuffleMode
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun playNext(song: Song): Boolean {
|
||||
if (musicService != null) {
|
||||
if (playingQueue.size > 0) {
|
||||
musicService!!.addSong(position + 1, song)
|
||||
} else {
|
||||
val queue = ArrayList<Song>()
|
||||
queue.add(song)
|
||||
openQueue(queue, 0, false)
|
||||
}
|
||||
Toast.makeText(musicService, musicService!!.resources.getString(R.string.added_title_to_playing_queue), Toast.LENGTH_SHORT).show()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun playNext(songs: ArrayList<Song>): Boolean {
|
||||
if (musicService != null) {
|
||||
if (playingQueue.size > 0) {
|
||||
musicService!!.addSongs(position + 1, songs)
|
||||
} else {
|
||||
openQueue(songs, 0, false)
|
||||
}
|
||||
val toast = if (songs.size == 1) musicService!!.resources.getString(R.string.added_title_to_playing_queue) else musicService!!.resources.getString(R.string.added_x_titles_to_playing_queue, songs.size)
|
||||
Toast.makeText(musicService, toast, Toast.LENGTH_SHORT).show()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun enqueue(song: Song): Boolean {
|
||||
if (musicService != null) {
|
||||
if (playingQueue.size > 0) {
|
||||
musicService!!.addSong(song)
|
||||
} else {
|
||||
val queue = ArrayList<Song>()
|
||||
queue.add(song)
|
||||
openQueue(queue, 0, false)
|
||||
}
|
||||
Toast.makeText(musicService, musicService!!.resources.getString(R.string.added_title_to_playing_queue), Toast.LENGTH_SHORT).show()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun enqueue(songs: ArrayList<Song>): Boolean {
|
||||
if (musicService != null) {
|
||||
if (playingQueue.size > 0) {
|
||||
musicService!!.addSongs(songs)
|
||||
} else {
|
||||
openQueue(songs, 0, false)
|
||||
}
|
||||
val toast = if (songs.size == 1) musicService!!.resources.getString(R.string.added_title_to_playing_queue) else musicService!!.resources.getString(R.string.added_x_titles_to_playing_queue, songs.size)
|
||||
Toast.makeText(musicService, toast, Toast.LENGTH_SHORT).show()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun removeFromQueue(song: Song): Boolean {
|
||||
if (musicService != null) {
|
||||
musicService!!.removeSong(song)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun removeFromQueue(position: Int): Boolean {
|
||||
if (musicService != null && position >= 0 && position < playingQueue.size) {
|
||||
musicService!!.removeSong(position)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun moveSong(from: Int, to: Int): Boolean {
|
||||
if (musicService != null && from >= 0 && to >= 0 && from < playingQueue.size && to < playingQueue.size) {
|
||||
musicService!!.moveSong(from, to)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun clearQueue(): Boolean {
|
||||
if (musicService != null) {
|
||||
musicService!!.clearQueue()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun playFromUri(uri: Uri) {
|
||||
if (musicService != null) {
|
||||
var songs: ArrayList<Song>? = null
|
||||
if (uri.scheme != null && uri.authority != null) {
|
||||
if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
|
||||
var songId: String? = null
|
||||
if (uri.authority == "com.android.providers.media.documents") {
|
||||
songId = getSongIdFromMediaProvider(uri)
|
||||
} else if (uri.authority == "media") {
|
||||
songId = uri.lastPathSegment
|
||||
}
|
||||
if (songId != null) {
|
||||
/* songs = SongLoader.getSongs(SongLoader.makeSongCursor(
|
||||
musicService,
|
||||
MediaStore.Audio.AudioColumns._ID + "=?",
|
||||
new String[]{songId}
|
||||
));*/
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(
|
||||
musicService!!,
|
||||
MediaStore.Audio.AudioColumns._ID + "=?",
|
||||
arrayOf(songId)))
|
||||
.subscribeOn(Schedulers.io()).blockingFirst()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (songs == null) {
|
||||
var songFile: File? = null
|
||||
if (uri.authority != null && uri.authority == "com.android.externalstorage.documents") {
|
||||
songFile = File(Environment.getExternalStorageDirectory(), uri.path!!.split(":".toRegex(), 2).toTypedArray()[1])
|
||||
}
|
||||
if (songFile == null) {
|
||||
val path = getFilePathFromUri(musicService!!, uri)
|
||||
if (path != null)
|
||||
songFile = File(path)
|
||||
}
|
||||
if (songFile == null && uri.path != null) {
|
||||
songFile = File(uri.path)
|
||||
}
|
||||
if (songFile != null) {
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(musicService!!, MediaStore.Audio.AudioColumns.DATA + "=?", arrayOf(songFile.absolutePath)
|
||||
)).blockingFirst()
|
||||
}
|
||||
}
|
||||
if (songs != null && !songs.isEmpty()) {
|
||||
openQueue(songs, 0, true)
|
||||
} else {
|
||||
//TODO the file is not listed in the media store
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
private fun getSongIdFromMediaProvider(uri: Uri): String {
|
||||
return DocumentsContract.getDocumentId(uri).split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1]
|
||||
}
|
||||
|
||||
internal annotation class PlaybackLocation {
|
||||
companion object {
|
||||
val REMOTE = 0
|
||||
val LOCAL = 1
|
||||
}
|
||||
}
|
||||
|
||||
class ServiceBinder internal constructor(private val mCallback: ServiceConnection?) : ServiceConnection {
|
||||
|
||||
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
||||
val binder = service as MusicService.MusicBinder
|
||||
musicService = binder.service
|
||||
mCallback?.onServiceConnected(className, service)
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(className: ComponentName) {
|
||||
mCallback?.onServiceDisconnected(className)
|
||||
musicService = null
|
||||
}
|
||||
}
|
||||
|
||||
class ServiceToken internal constructor(internal var mWrappedContext: ContextWrapper)
|
||||
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
package code.name.monkey.retromusic.helper;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
|
||||
public class MusicProgressViewUpdateHelper extends Handler {
|
||||
private static final int CMD_REFRESH_PROGRESS_VIEWS = 1;
|
||||
|
||||
private static final int MIN_INTERVAL = 20;
|
||||
private static final int UPDATE_INTERVAL_PLAYING = 1000;
|
||||
private static final int UPDATE_INTERVAL_PAUSED = 500;
|
||||
|
||||
private Callback callback;
|
||||
private int intervalPlaying;
|
||||
private int intervalPaused;
|
||||
|
||||
public void start() {
|
||||
queueNextRefresh(1);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
removeMessages(CMD_REFRESH_PROGRESS_VIEWS);
|
||||
}
|
||||
|
||||
public MusicProgressViewUpdateHelper(Callback callback) {
|
||||
this.callback = callback;
|
||||
this.intervalPlaying = UPDATE_INTERVAL_PLAYING;
|
||||
this.intervalPaused = UPDATE_INTERVAL_PAUSED;
|
||||
}
|
||||
|
||||
public MusicProgressViewUpdateHelper(Callback callback, int intervalPlaying, int intervalPaused) {
|
||||
this.callback = callback;
|
||||
this.intervalPlaying = intervalPlaying;
|
||||
this.intervalPaused = intervalPaused;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(@NonNull Message msg) {
|
||||
super.handleMessage(msg);
|
||||
if (msg.what == CMD_REFRESH_PROGRESS_VIEWS) {
|
||||
queueNextRefresh(refreshProgressViews());
|
||||
}
|
||||
}
|
||||
|
||||
private int refreshProgressViews() {
|
||||
final int progressMillis = MusicPlayerRemote.getSongProgressMillis();
|
||||
final int totalMillis = MusicPlayerRemote.getSongDurationMillis();
|
||||
|
||||
callback.onUpdateProgressViews(progressMillis, totalMillis);
|
||||
|
||||
if (!MusicPlayerRemote.isPlaying()) {
|
||||
return intervalPaused;
|
||||
}
|
||||
|
||||
final int remainingMillis = intervalPlaying - progressMillis % intervalPlaying;
|
||||
|
||||
return Math.max(MIN_INTERVAL, remainingMillis);
|
||||
}
|
||||
|
||||
private void queueNextRefresh(final long delay) {
|
||||
final Message message = obtainMessage(CMD_REFRESH_PROGRESS_VIEWS);
|
||||
removeMessages(CMD_REFRESH_PROGRESS_VIEWS);
|
||||
sendMessageDelayed(message, delay);
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
void onUpdateProgressViews(int progress, int total);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package code.name.monkey.retromusic.helper
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Message
|
||||
|
||||
|
||||
class MusicProgressViewUpdateHelper : Handler {
|
||||
|
||||
private var callback: Callback? = null
|
||||
private var intervalPlaying: Int = 0
|
||||
private var intervalPaused: Int = 0
|
||||
|
||||
fun start() {
|
||||
queueNextRefresh(1)
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
removeMessages(CMD_REFRESH_PROGRESS_VIEWS)
|
||||
}
|
||||
|
||||
constructor(callback: Callback) {
|
||||
this.callback = callback
|
||||
this.intervalPlaying = UPDATE_INTERVAL_PLAYING
|
||||
this.intervalPaused = UPDATE_INTERVAL_PAUSED
|
||||
}
|
||||
|
||||
constructor(callback: Callback, intervalPlaying: Int, intervalPaused: Int) {
|
||||
this.callback = callback
|
||||
this.intervalPlaying = intervalPlaying
|
||||
this.intervalPaused = intervalPaused
|
||||
}
|
||||
|
||||
override fun handleMessage(msg: Message) {
|
||||
super.handleMessage(msg)
|
||||
if (msg.what == CMD_REFRESH_PROGRESS_VIEWS) {
|
||||
queueNextRefresh(refreshProgressViews().toLong())
|
||||
}
|
||||
}
|
||||
|
||||
private fun refreshProgressViews(): Int {
|
||||
val progressMillis = MusicPlayerRemote.songProgressMillis
|
||||
val totalMillis = MusicPlayerRemote.songDurationMillis
|
||||
|
||||
callback!!.onUpdateProgressViews(progressMillis, totalMillis)
|
||||
|
||||
if (!MusicPlayerRemote.isPlaying) {
|
||||
return intervalPaused
|
||||
}
|
||||
|
||||
val remainingMillis = intervalPlaying - progressMillis % intervalPlaying
|
||||
|
||||
return Math.max(MIN_INTERVAL, remainingMillis)
|
||||
}
|
||||
|
||||
private fun queueNextRefresh(delay: Long) {
|
||||
val message = obtainMessage(CMD_REFRESH_PROGRESS_VIEWS)
|
||||
removeMessages(CMD_REFRESH_PROGRESS_VIEWS)
|
||||
sendMessageDelayed(message, delay)
|
||||
}
|
||||
|
||||
interface Callback {
|
||||
fun onUpdateProgressViews(progress: Int, total: Int)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val CMD_REFRESH_PROGRESS_VIEWS = 1
|
||||
|
||||
private val MIN_INTERVAL = 20
|
||||
private val UPDATE_INTERVAL_PLAYING = 1000
|
||||
private val UPDATE_INTERVAL_PAUSED = 500
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package code.name.monkey.retromusic.helper;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
|
||||
public class PlayPauseButtonOnClickHandler implements View.OnClickListener {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (MusicPlayerRemote.isPlaying()) {
|
||||
MusicPlayerRemote.pauseSong();
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package code.name.monkey.retromusic.helper
|
||||
|
||||
import android.view.View
|
||||
|
||||
|
||||
class PlayPauseButtonOnClickHandler : View.OnClickListener {
|
||||
override fun onClick(v: View) {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
package code.name.monkey.retromusic.helper;
|
||||
|
||||
import android.app.SearchManager;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.provider.MediaStore;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.loaders.SongLoader;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
|
||||
|
||||
public class SearchQueryHelper {
|
||||
private static final String TITLE_SELECTION = "lower(" + MediaStore.Audio.AudioColumns.TITLE + ") = ?";
|
||||
private static final String ALBUM_SELECTION = "lower(" + MediaStore.Audio.AudioColumns.ALBUM + ") = ?";
|
||||
private static final String ARTIST_SELECTION = "lower(" + MediaStore.Audio.AudioColumns.ARTIST + ") = ?";
|
||||
private static final String AND = " AND ";
|
||||
private static ArrayList<Song> songs = new ArrayList<>();
|
||||
|
||||
public static ArrayList<Song> getSongs() {
|
||||
return songs;
|
||||
}
|
||||
|
||||
public static void setSongs(ArrayList<Song> songs) {
|
||||
SearchQueryHelper.songs = songs;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static ArrayList<Song> getSongs(@NonNull final Context context, @NonNull final Bundle extras) {
|
||||
final String query = extras.getString(SearchManager.QUERY, null);
|
||||
final String artistName = extras.getString(MediaStore.EXTRA_MEDIA_ARTIST, null);
|
||||
final String albumName = extras.getString(MediaStore.EXTRA_MEDIA_ALBUM, null);
|
||||
final String titleName = extras.getString(MediaStore.EXTRA_MEDIA_TITLE, null);
|
||||
|
||||
ArrayList<Song> songs = new ArrayList<>();
|
||||
if (artistName != null && albumName != null && titleName != null) {
|
||||
songs = SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(context, ARTIST_SELECTION + AND + ALBUM_SELECTION + AND + TITLE_SELECTION, new String[]{artistName.toLowerCase(), albumName.toLowerCase(), titleName.toLowerCase()})).blockingFirst();
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
if (artistName != null && titleName != null) {
|
||||
songs = SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(context, ARTIST_SELECTION + AND + TITLE_SELECTION, new String[]{artistName.toLowerCase(), titleName.toLowerCase()})).blockingFirst();
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
if (albumName != null && titleName != null) {
|
||||
songs = SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(context, ALBUM_SELECTION + AND + TITLE_SELECTION, new String[]{albumName.toLowerCase(), titleName.toLowerCase()})).blockingFirst();
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
if (artistName != null) {
|
||||
songs = SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(context, ARTIST_SELECTION, new String[]{artistName.toLowerCase()})).blockingFirst();
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
if (albumName != null) {
|
||||
songs = SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(context, ALBUM_SELECTION, new String[]{albumName.toLowerCase()})).blockingFirst();
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
if (titleName != null) {
|
||||
songs = SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(context, TITLE_SELECTION, new String[]{titleName.toLowerCase()})).blockingFirst();
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
songs = SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(context, ARTIST_SELECTION, new String[]{query.toLowerCase()})).blockingFirst();
|
||||
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
songs = SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(context, ALBUM_SELECTION, new String[]{query.toLowerCase()})).blockingFirst();
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
songs = SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(context, TITLE_SELECTION, new String[]{query.toLowerCase()})).blockingFirst();
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
return new ArrayList<Song>();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package code.name.monkey.retromusic.helper
|
||||
|
||||
import android.app.SearchManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.provider.MediaStore
|
||||
import code.name.monkey.retromusic.loaders.SongLoader
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import java.util.*
|
||||
|
||||
|
||||
object SearchQueryHelper {
|
||||
private val TITLE_SELECTION = "lower(" + MediaStore.Audio.AudioColumns.TITLE + ") = ?"
|
||||
private val ALBUM_SELECTION = "lower(" + MediaStore.Audio.AudioColumns.ALBUM + ") = ?"
|
||||
private val ARTIST_SELECTION = "lower(" + MediaStore.Audio.AudioColumns.ARTIST + ") = ?"
|
||||
private val AND = " AND "
|
||||
var songs = ArrayList<Song>()
|
||||
|
||||
fun getSongs(context: Context, extras: Bundle): ArrayList<Song> {
|
||||
val query = extras.getString(SearchManager.QUERY, null)
|
||||
val artistName = extras.getString(MediaStore.EXTRA_MEDIA_ARTIST, null)
|
||||
val albumName = extras.getString(MediaStore.EXTRA_MEDIA_ALBUM, null)
|
||||
val titleName = extras.getString(MediaStore.EXTRA_MEDIA_TITLE, null)
|
||||
|
||||
var songs = ArrayList<Song>()
|
||||
if (artistName != null && albumName != null && titleName != null) {
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, ARTIST_SELECTION + AND + ALBUM_SELECTION + AND + TITLE_SELECTION, arrayOf(artistName.toLowerCase(), albumName.toLowerCase(), titleName.toLowerCase()))).blockingFirst()
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs
|
||||
}
|
||||
if (artistName != null && titleName != null) {
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, ARTIST_SELECTION + AND + TITLE_SELECTION, arrayOf(artistName.toLowerCase(), titleName.toLowerCase()))).blockingFirst()
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs
|
||||
}
|
||||
if (albumName != null && titleName != null) {
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, ALBUM_SELECTION + AND + TITLE_SELECTION, arrayOf(albumName.toLowerCase(), titleName.toLowerCase()))).blockingFirst()
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs
|
||||
}
|
||||
if (artistName != null) {
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, ARTIST_SELECTION, arrayOf(artistName.toLowerCase()))).blockingFirst()
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs
|
||||
}
|
||||
if (albumName != null) {
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, ALBUM_SELECTION, arrayOf(albumName.toLowerCase()))).blockingFirst()
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs
|
||||
}
|
||||
if (titleName != null) {
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, TITLE_SELECTION, arrayOf(titleName.toLowerCase()))).blockingFirst()
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs
|
||||
}
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, ARTIST_SELECTION, arrayOf(query.toLowerCase()))).blockingFirst()
|
||||
|
||||
if (!songs.isEmpty()) {
|
||||
return songs
|
||||
}
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, ALBUM_SELECTION, arrayOf(query.toLowerCase()))).blockingFirst()
|
||||
if (!songs.isEmpty()) {
|
||||
return songs
|
||||
}
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, TITLE_SELECTION, arrayOf(query.toLowerCase()))).blockingFirst()
|
||||
return if (!songs.isEmpty()) {
|
||||
songs
|
||||
} else ArrayList()
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package code.name.monkey.retromusic.helper;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
|
||||
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);
|
||||
listToShuffle.add(0, song);
|
||||
} else {
|
||||
Collections.shuffle(listToShuffle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package code.name.monkey.retromusic.helper
|
||||
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
|
||||
import java.util.Collections
|
||||
|
||||
|
||||
object ShuffleHelper {
|
||||
|
||||
fun makeShuffleList(listToShuffle: MutableList<Song>, current: Int) {
|
||||
if (listToShuffle.isEmpty()) return
|
||||
if (current >= 0) {
|
||||
val song = listToShuffle.removeAt(current)
|
||||
listToShuffle.shuffle()
|
||||
listToShuffle.add(0, song)
|
||||
} else {
|
||||
listToShuffle.shuffle()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,173 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Andrew Neal 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 code.name.monkey.retromusic.helper;
|
||||
|
||||
import android.provider.MediaStore;
|
||||
|
||||
/**
|
||||
* Holds all of the sort orders for each list type.
|
||||
*
|
||||
* @author Andrew Neal (andrewdneal@gmail.com)
|
||||
*/
|
||||
public final class SortOrder {
|
||||
|
||||
/**
|
||||
* This class is never instantiated
|
||||
*/
|
||||
public SortOrder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Artist sort order entries.
|
||||
*/
|
||||
public interface ArtistSortOrder {
|
||||
|
||||
/* Artist sort order A-Z */
|
||||
String ARTIST_A_Z = MediaStore.Audio.Artists.DEFAULT_SORT_ORDER;
|
||||
|
||||
/* Artist sort order Z-A */
|
||||
String ARTIST_Z_A = ARTIST_A_Z + " DESC";
|
||||
|
||||
/* Artist sort order number of songs */
|
||||
String ARTIST_NUMBER_OF_SONGS = MediaStore.Audio.Artists.NUMBER_OF_TRACKS
|
||||
+ " DESC";
|
||||
|
||||
/* Artist sort order number of albums */
|
||||
String ARTIST_NUMBER_OF_ALBUMS = MediaStore.Audio.Artists.NUMBER_OF_ALBUMS
|
||||
+ " DESC";
|
||||
}
|
||||
|
||||
/**
|
||||
* Album sort order entries.
|
||||
*/
|
||||
public interface AlbumSortOrder {
|
||||
|
||||
/* Album sort order A-Z */
|
||||
String ALBUM_A_Z = MediaStore.Audio.Albums.DEFAULT_SORT_ORDER;
|
||||
|
||||
/* Album sort order Z-A */
|
||||
String ALBUM_Z_A = ALBUM_A_Z + " DESC";
|
||||
|
||||
/* Album sort order songs */
|
||||
String ALBUM_NUMBER_OF_SONGS = MediaStore.Audio.Albums.NUMBER_OF_SONGS
|
||||
+ " DESC";
|
||||
|
||||
/* Album sort order artist */
|
||||
String ALBUM_ARTIST = MediaStore.Audio.Artists.DEFAULT_SORT_ORDER
|
||||
+ ", " + MediaStore.Audio.Albums.DEFAULT_SORT_ORDER;
|
||||
|
||||
/* Album sort order year */
|
||||
String ALBUM_YEAR = MediaStore.Audio.Media.YEAR + " DESC";
|
||||
}
|
||||
|
||||
/**
|
||||
* Song sort order entries.
|
||||
*/
|
||||
public interface SongSortOrder {
|
||||
|
||||
/* Song sort order A-Z */
|
||||
String SONG_A_Z = MediaStore.Audio.Media.DEFAULT_SORT_ORDER;
|
||||
|
||||
/* Song sort order Z-A */
|
||||
String SONG_Z_A = SONG_A_Z + " DESC";
|
||||
|
||||
/* Song sort order artist */
|
||||
String SONG_ARTIST = MediaStore.Audio.Artists.DEFAULT_SORT_ORDER;
|
||||
|
||||
/* Song sort order album */
|
||||
String SONG_ALBUM = MediaStore.Audio.Albums.DEFAULT_SORT_ORDER;
|
||||
|
||||
/* Song sort order year */
|
||||
String SONG_YEAR = MediaStore.Audio.Media.YEAR + " DESC";
|
||||
|
||||
/* Song sort order duration */
|
||||
String SONG_DURATION = MediaStore.Audio.Media.DURATION + " DESC";
|
||||
|
||||
/* Song sort order date */
|
||||
String SONG_DATE = MediaStore.Audio.Media.DATE_ADDED + " DESC";
|
||||
}
|
||||
|
||||
/**
|
||||
* Album song sort order entries.
|
||||
*/
|
||||
public interface AlbumSongSortOrder {
|
||||
|
||||
/* Album song sort order A-Z */
|
||||
String SONG_A_Z = MediaStore.Audio.Media.DEFAULT_SORT_ORDER;
|
||||
|
||||
/* Album song sort order Z-A */
|
||||
String SONG_Z_A = SONG_A_Z + " DESC";
|
||||
|
||||
/* Album song sort order track list */
|
||||
String SONG_TRACK_LIST = MediaStore.Audio.Media.TRACK + ", "
|
||||
+ MediaStore.Audio.Media.DEFAULT_SORT_ORDER;
|
||||
|
||||
/* Album song sort order duration */
|
||||
String SONG_DURATION = SongSortOrder.SONG_DURATION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Artist song sort order entries.
|
||||
*/
|
||||
public interface ArtistSongSortOrder {
|
||||
|
||||
/* Artist song sort order A-Z */
|
||||
String SONG_A_Z = MediaStore.Audio.Media.DEFAULT_SORT_ORDER;
|
||||
|
||||
/* Artist song sort order Z-A */
|
||||
String SONG_Z_A = SONG_A_Z + " DESC";
|
||||
|
||||
/* Artist song sort order album */
|
||||
String SONG_ALBUM = MediaStore.Audio.Media.ALBUM;
|
||||
|
||||
/* Artist song sort order year */
|
||||
String SONG_YEAR = MediaStore.Audio.Media.YEAR + " DESC";
|
||||
|
||||
/* Artist song sort order duration */
|
||||
String SONG_DURATION = MediaStore.Audio.Media.DURATION + " DESC";
|
||||
|
||||
/* Artist song sort order date */
|
||||
String SONG_DATE = MediaStore.Audio.Media.DATE_ADDED + " DESC";
|
||||
}
|
||||
|
||||
/**
|
||||
* Artist album sort order entries.
|
||||
*/
|
||||
public interface ArtistAlbumSortOrder {
|
||||
|
||||
/* Artist album sort order A-Z */
|
||||
String ALBUM_A_Z = MediaStore.Audio.Albums.DEFAULT_SORT_ORDER;
|
||||
|
||||
/* Artist album sort order Z-A */
|
||||
String ALBUM_Z_A = ALBUM_A_Z + " DESC";
|
||||
|
||||
/* Artist album sort order year */
|
||||
String ALBUM_YEAR = MediaStore.Audio.Media.YEAR
|
||||
+ " DESC";
|
||||
|
||||
/* Artist album sort order year */
|
||||
String ALBUM_YEAR_ASC = MediaStore.Audio.Media.YEAR
|
||||
+ " ASC";
|
||||
}
|
||||
|
||||
/**
|
||||
* Genre sort order entries.
|
||||
*/
|
||||
public interface GenreSortOrder {
|
||||
|
||||
/* Genre sort order A-Z */
|
||||
String GENRE_A_Z = MediaStore.Audio.Genres.DEFAULT_SORT_ORDER;
|
||||
|
||||
/* Genre sort order Z-A */
|
||||
String ALBUM_Z_A = GENRE_A_Z + " DESC";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Andrew Neal 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 code.name.monkey.retromusic.helper
|
||||
|
||||
import android.provider.MediaStore
|
||||
|
||||
/**
|
||||
* Holds all of the sort orders for each list type.
|
||||
*
|
||||
* @author Andrew Neal (andrewdneal@gmail.com)
|
||||
*/
|
||||
/**
|
||||
* This class is never instantiated
|
||||
*/
|
||||
class SortOrder {
|
||||
|
||||
/**
|
||||
* Artist sort order entries.
|
||||
*/
|
||||
interface ArtistSortOrder {
|
||||
companion object {
|
||||
|
||||
/* Artist sort order A-Z */
|
||||
val ARTIST_A_Z = MediaStore.Audio.Artists.DEFAULT_SORT_ORDER
|
||||
|
||||
/* Artist sort order Z-A */
|
||||
val ARTIST_Z_A = "$ARTIST_A_Z DESC"
|
||||
|
||||
/* Artist sort order number of songs */
|
||||
val ARTIST_NUMBER_OF_SONGS = MediaStore.Audio.Artists.NUMBER_OF_TRACKS + " DESC"
|
||||
|
||||
/* Artist sort order number of albums */
|
||||
val ARTIST_NUMBER_OF_ALBUMS = MediaStore.Audio.Artists.NUMBER_OF_ALBUMS + " DESC"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Album sort order entries.
|
||||
*/
|
||||
interface AlbumSortOrder {
|
||||
companion object {
|
||||
|
||||
/* Album sort order A-Z */
|
||||
val ALBUM_A_Z = MediaStore.Audio.Albums.DEFAULT_SORT_ORDER
|
||||
|
||||
/* Album sort order Z-A */
|
||||
val ALBUM_Z_A = "$ALBUM_A_Z DESC"
|
||||
|
||||
/* Album sort order songs */
|
||||
val ALBUM_NUMBER_OF_SONGS = MediaStore.Audio.Albums.NUMBER_OF_SONGS + " DESC"
|
||||
|
||||
/* Album sort order artist */
|
||||
val ALBUM_ARTIST = (MediaStore.Audio.Artists.DEFAULT_SORT_ORDER
|
||||
+ ", " + MediaStore.Audio.Albums.DEFAULT_SORT_ORDER)
|
||||
|
||||
/* Album sort order year */
|
||||
val ALBUM_YEAR = MediaStore.Audio.Media.YEAR + " DESC"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Song sort order entries.
|
||||
*/
|
||||
interface SongSortOrder {
|
||||
companion object {
|
||||
|
||||
/* Song sort order A-Z */
|
||||
val SONG_A_Z = MediaStore.Audio.Media.DEFAULT_SORT_ORDER
|
||||
|
||||
/* Song sort order Z-A */
|
||||
val SONG_Z_A = "$SONG_A_Z DESC"
|
||||
|
||||
/* Song sort order artist */
|
||||
val SONG_ARTIST = MediaStore.Audio.Artists.DEFAULT_SORT_ORDER
|
||||
|
||||
/* Song sort order album */
|
||||
val SONG_ALBUM = MediaStore.Audio.Albums.DEFAULT_SORT_ORDER
|
||||
|
||||
/* Song sort order year */
|
||||
val SONG_YEAR = MediaStore.Audio.Media.YEAR + " DESC"
|
||||
|
||||
/* Song sort order duration */
|
||||
val SONG_DURATION = MediaStore.Audio.Media.DURATION + " DESC"
|
||||
|
||||
/* Song sort order date */
|
||||
val SONG_DATE = MediaStore.Audio.Media.DATE_ADDED + " DESC"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Album song sort order entries.
|
||||
*/
|
||||
interface AlbumSongSortOrder {
|
||||
companion object {
|
||||
|
||||
/* Album song sort order A-Z */
|
||||
val SONG_A_Z = MediaStore.Audio.Media.DEFAULT_SORT_ORDER
|
||||
|
||||
/* Album song sort order Z-A */
|
||||
val SONG_Z_A = "$SONG_A_Z DESC"
|
||||
|
||||
/* Album song sort order track list */
|
||||
val SONG_TRACK_LIST = (MediaStore.Audio.Media.TRACK + ", "
|
||||
+ MediaStore.Audio.Media.DEFAULT_SORT_ORDER)
|
||||
|
||||
/* Album song sort order duration */
|
||||
val SONG_DURATION = SongSortOrder.SONG_DURATION
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Artist song sort order entries.
|
||||
*/
|
||||
interface ArtistSongSortOrder {
|
||||
companion object {
|
||||
|
||||
/* Artist song sort order A-Z */
|
||||
val SONG_A_Z = MediaStore.Audio.Media.DEFAULT_SORT_ORDER
|
||||
|
||||
/* Artist song sort order Z-A */
|
||||
val SONG_Z_A = "$SONG_A_Z DESC"
|
||||
|
||||
/* Artist song sort order album */
|
||||
val SONG_ALBUM = MediaStore.Audio.Media.ALBUM
|
||||
|
||||
/* Artist song sort order year */
|
||||
val SONG_YEAR = MediaStore.Audio.Media.YEAR + " DESC"
|
||||
|
||||
/* Artist song sort order duration */
|
||||
val SONG_DURATION = MediaStore.Audio.Media.DURATION + " DESC"
|
||||
|
||||
/* Artist song sort order date */
|
||||
val SONG_DATE = MediaStore.Audio.Media.DATE_ADDED + " DESC"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Artist album sort order entries.
|
||||
*/
|
||||
interface ArtistAlbumSortOrder {
|
||||
companion object {
|
||||
|
||||
/* Artist album sort order A-Z */
|
||||
val ALBUM_A_Z = MediaStore.Audio.Albums.DEFAULT_SORT_ORDER
|
||||
|
||||
/* Artist album sort order Z-A */
|
||||
val ALBUM_Z_A = "$ALBUM_A_Z DESC"
|
||||
|
||||
/* Artist album sort order year */
|
||||
val ALBUM_YEAR = MediaStore.Audio.Media.YEAR + " DESC"
|
||||
|
||||
/* Artist album sort order year */
|
||||
val ALBUM_YEAR_ASC = MediaStore.Audio.Media.YEAR + " ASC"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Genre sort order entries.
|
||||
*/
|
||||
interface GenreSortOrder {
|
||||
companion object {
|
||||
|
||||
/* Genre sort order A-Z */
|
||||
val GENRE_A_Z = MediaStore.Audio.Genres.DEFAULT_SORT_ORDER
|
||||
|
||||
/* Genre sort order Z-A */
|
||||
val ALBUM_Z_A = "$GENRE_A_Z DESC"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
package code.name.monkey.retromusic.helper;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
isRunning = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops and resets the stop watch to zero milliseconds.
|
||||
*
|
||||
* @see #start()
|
||||
* @see #pause()
|
||||
*/
|
||||
public void reset() {
|
||||
synchronized (this) {
|
||||
startTime = 0;
|
||||
previousElapsedTime = 0;
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%d millis", getElapsedTime());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package code.name.monkey.retromusic.helper
|
||||
|
||||
/**
|
||||
* Simple thread safe stop watch.
|
||||
*
|
||||
* @author Karim Abou Zeid (kabouzeid)
|
||||
*/
|
||||
class StopWatch {
|
||||
|
||||
/**
|
||||
* The time the stop watch was last started.
|
||||
*/
|
||||
private var startTime: Long = 0
|
||||
|
||||
/**
|
||||
* The time elapsed before the current [.startTime].
|
||||
*/
|
||||
private var previousElapsedTime: Long = 0
|
||||
|
||||
/**
|
||||
* Whether the stop watch is currently running or not.
|
||||
*/
|
||||
private var isRunning: Boolean = false
|
||||
|
||||
/**
|
||||
* @return the total elapsed time in milliseconds
|
||||
*/
|
||||
val elapsedTime: Long
|
||||
get() = synchronized(this) {
|
||||
var currentElapsedTime: Long = 0
|
||||
if (isRunning) {
|
||||
currentElapsedTime = System.currentTimeMillis() - startTime
|
||||
}
|
||||
return previousElapsedTime + currentElapsedTime
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts or continues the stop watch.
|
||||
*
|
||||
* @see .pause
|
||||
* @see .reset
|
||||
*/
|
||||
fun start() {
|
||||
synchronized(this) {
|
||||
startTime = System.currentTimeMillis()
|
||||
isRunning = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses the stop watch. It can be continued later from [.start].
|
||||
*
|
||||
* @see .start
|
||||
* @see .reset
|
||||
*/
|
||||
fun pause() {
|
||||
synchronized(this) {
|
||||
previousElapsedTime += System.currentTimeMillis() - startTime
|
||||
isRunning = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops and resets the stop watch to zero milliseconds.
|
||||
*
|
||||
* @see .start
|
||||
* @see .pause
|
||||
*/
|
||||
fun reset() {
|
||||
synchronized(this) {
|
||||
startTime = 0
|
||||
previousElapsedTime = 0
|
||||
isRunning = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return String.format("%d millis", elapsedTime)
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package code.name.monkey.retromusic.helper.menu;
|
||||
|
||||
import android.app.Activity;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.loaders.GenreLoader;
|
||||
import code.name.monkey.retromusic.model.Genre;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog;
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
public class GenreMenuHelper {
|
||||
public static boolean handleMenuClick(@NonNull AppCompatActivity activity,
|
||||
@NonNull Genre genre,
|
||||
@NonNull MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_play:
|
||||
MusicPlayerRemote.openQueue(getGenreSongs(activity, genre), 0, true);
|
||||
return true;
|
||||
case R.id.action_play_next:
|
||||
MusicPlayerRemote.playNext(getGenreSongs(activity, genre));
|
||||
return true;
|
||||
case R.id.action_add_to_playlist:
|
||||
AddToPlaylistDialog.create(getGenreSongs(activity, genre))
|
||||
.show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
|
||||
return true;
|
||||
case R.id.action_add_to_current_playing:
|
||||
MusicPlayerRemote.enqueue(getGenreSongs(activity, genre));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static ArrayList<Song> getGenreSongs(@NonNull Activity activity,
|
||||
@NonNull Genre genre) {
|
||||
ArrayList<Song> songs;
|
||||
songs = GenreLoader.getSongs(activity, genre.id).blockingFirst();
|
||||
return songs;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package code.name.monkey.retromusic.helper.menu
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.view.MenuItem
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
import code.name.monkey.retromusic.loaders.GenreLoader
|
||||
import code.name.monkey.retromusic.model.Genre
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
object GenreMenuHelper {
|
||||
fun handleMenuClick(activity: AppCompatActivity,
|
||||
genre: Genre,
|
||||
item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_play -> {
|
||||
MusicPlayerRemote.openQueue(getGenreSongs(activity, genre), 0, true)
|
||||
return true
|
||||
}
|
||||
R.id.action_play_next -> {
|
||||
MusicPlayerRemote.playNext(getGenreSongs(activity, genre))
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_playlist -> {
|
||||
AddToPlaylistDialog.create(getGenreSongs(activity, genre))
|
||||
.show(activity.supportFragmentManager, "ADD_PLAYLIST")
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_current_playing -> {
|
||||
MusicPlayerRemote.enqueue(getGenreSongs(activity, genre))
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun getGenreSongs(activity: Activity,
|
||||
genre: Genre): ArrayList<Song> {
|
||||
val songs: ArrayList<Song>
|
||||
songs = GenreLoader.getSongs(activity, genre.id).blockingFirst()
|
||||
return songs
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
package code.name.monkey.retromusic.helper.menu;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.RetroApplication;
|
||||
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog;
|
||||
import code.name.monkey.retromusic.dialogs.DeletePlaylistDialog;
|
||||
import code.name.monkey.retromusic.dialogs.RenamePlaylistDialog;
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
|
||||
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader;
|
||||
import code.name.monkey.retromusic.misc.WeakContextAsyncTask;
|
||||
import code.name.monkey.retromusic.model.AbsCustomPlaylist;
|
||||
import code.name.monkey.retromusic.model.Playlist;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.util.PlaylistsUtil;
|
||||
|
||||
|
||||
public class PlaylistMenuHelper {
|
||||
|
||||
public static boolean handleMenuClick(@NonNull AppCompatActivity activity,
|
||||
@NonNull final Playlist playlist, @NonNull MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_play:
|
||||
MusicPlayerRemote.openQueue(getPlaylistSongs(activity, playlist), 9, true);
|
||||
return true;
|
||||
case R.id.action_play_next:
|
||||
MusicPlayerRemote.playNext(getPlaylistSongs(activity, playlist));
|
||||
return true;
|
||||
case R.id.action_add_to_playlist:
|
||||
AddToPlaylistDialog.create(getPlaylistSongs(activity, playlist))
|
||||
.show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
|
||||
return true;
|
||||
case R.id.action_add_to_current_playing:
|
||||
MusicPlayerRemote.enqueue(getPlaylistSongs(activity, playlist));
|
||||
return true;
|
||||
case R.id.action_rename_playlist:
|
||||
RenamePlaylistDialog.create(playlist.id)
|
||||
.show(activity.getSupportFragmentManager(), "RENAME_PLAYLIST");
|
||||
return true;
|
||||
case R.id.action_delete_playlist:
|
||||
DeletePlaylistDialog.create(playlist)
|
||||
.show(activity.getSupportFragmentManager(), "DELETE_PLAYLIST");
|
||||
return true;
|
||||
case R.id.action_save_playlist:
|
||||
new SavePlaylistAsyncTask(activity).execute(playlist);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static ArrayList<Song> getPlaylistSongs(@NonNull Activity activity,
|
||||
@NonNull Playlist playlist) {
|
||||
ArrayList<Song> songs;
|
||||
if (playlist instanceof AbsCustomPlaylist) {
|
||||
songs = ((AbsCustomPlaylist) playlist).getSongs(activity).blockingFirst();
|
||||
} else {
|
||||
songs = PlaylistSongsLoader.getPlaylistSongList(activity, playlist).blockingFirst();
|
||||
}
|
||||
return songs;
|
||||
}
|
||||
|
||||
private static class SavePlaylistAsyncTask extends WeakContextAsyncTask<Playlist, String, String> {
|
||||
SavePlaylistAsyncTask(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInBackground(Playlist... params) {
|
||||
return String.format(RetroApplication.getInstance().getApplicationContext().getString(R.string
|
||||
.saved_playlist_to), PlaylistsUtil.savePlaylist(RetroApplication.getInstance().getApplicationContext(), params[0]).blockingFirst());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String string) {
|
||||
super.onPostExecute(string);
|
||||
Context context = getContext();
|
||||
if (context != null) {
|
||||
Toast.makeText(context, string, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package code.name.monkey.retromusic.helper.menu
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.view.MenuItem
|
||||
import android.widget.Toast
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.RetroApplication
|
||||
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
|
||||
import code.name.monkey.retromusic.dialogs.DeletePlaylistDialog
|
||||
import code.name.monkey.retromusic.dialogs.RenamePlaylistDialog
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
|
||||
import code.name.monkey.retromusic.misc.WeakContextAsyncTask
|
||||
import code.name.monkey.retromusic.model.AbsCustomPlaylist
|
||||
import code.name.monkey.retromusic.model.Playlist
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.util.PlaylistsUtil
|
||||
|
||||
|
||||
object PlaylistMenuHelper {
|
||||
|
||||
fun handleMenuClick(activity: AppCompatActivity,
|
||||
playlist: Playlist, item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_play -> {
|
||||
MusicPlayerRemote.openQueue(getPlaylistSongs(activity, playlist), 9, true)
|
||||
return true
|
||||
}
|
||||
R.id.action_play_next -> {
|
||||
MusicPlayerRemote.playNext(getPlaylistSongs(activity, playlist))
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_playlist -> {
|
||||
AddToPlaylistDialog.create(getPlaylistSongs(activity, playlist))
|
||||
.show(activity.supportFragmentManager, "ADD_PLAYLIST")
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_current_playing -> {
|
||||
MusicPlayerRemote.enqueue(getPlaylistSongs(activity, playlist))
|
||||
return true
|
||||
}
|
||||
R.id.action_rename_playlist -> {
|
||||
RenamePlaylistDialog.create(playlist.id.toLong())
|
||||
.show(activity.supportFragmentManager, "RENAME_PLAYLIST")
|
||||
return true
|
||||
}
|
||||
R.id.action_delete_playlist -> {
|
||||
DeletePlaylistDialog.create(playlist)
|
||||
.show(activity.supportFragmentManager, "DELETE_PLAYLIST")
|
||||
return true
|
||||
}
|
||||
R.id.action_save_playlist -> {
|
||||
SavePlaylistAsyncTask(activity).execute(playlist)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun getPlaylistSongs(activity: Activity,
|
||||
playlist: Playlist): ArrayList<Song> {
|
||||
val songs: ArrayList<Song>
|
||||
if (playlist is AbsCustomPlaylist) {
|
||||
songs = playlist.getSongs(activity).blockingFirst()
|
||||
} else {
|
||||
songs = PlaylistSongsLoader.getPlaylistSongList(activity, playlist).blockingFirst()
|
||||
}
|
||||
return songs
|
||||
}
|
||||
|
||||
private class SavePlaylistAsyncTask internal constructor(context: Context) : WeakContextAsyncTask<Playlist, String, String>(context) {
|
||||
|
||||
override fun doInBackground(vararg params: Playlist): String {
|
||||
return String.format(RetroApplication.instance.applicationContext.getString(R.string
|
||||
.saved_playlist_to), PlaylistsUtil.savePlaylist(RetroApplication.instance.applicationContext, params[0]).blockingFirst())
|
||||
}
|
||||
|
||||
override fun onPostExecute(string: String) {
|
||||
super.onPostExecute(string)
|
||||
val context = context
|
||||
if (context != null) {
|
||||
Toast.makeText(context, string, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
package code.name.monkey.retromusic.helper.menu;
|
||||
|
||||
import android.content.Intent;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.PopupMenu;
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog;
|
||||
import code.name.monkey.retromusic.dialogs.DeleteSongsDialog;
|
||||
import code.name.monkey.retromusic.dialogs.SongDetailDialog;
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
|
||||
import code.name.monkey.retromusic.interfaces.PaletteColorHolder;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.ui.activities.tageditor.AbsTagEditorActivity;
|
||||
import code.name.monkey.retromusic.ui.activities.tageditor.SongTagEditorActivity;
|
||||
import code.name.monkey.retromusic.util.MusicUtil;
|
||||
import code.name.monkey.retromusic.util.NavigationUtil;
|
||||
|
||||
|
||||
public class SongMenuHelper {
|
||||
public static final int MENU_RES = R.menu.menu_item_song;
|
||||
|
||||
public static boolean handleMenuClick(@NonNull FragmentActivity activity, @NonNull Song song, int menuItemId) {
|
||||
switch (menuItemId) {
|
||||
case R.id.action_set_as_ringtone:
|
||||
MusicUtil.setRingtone(activity, song.id);
|
||||
return true;
|
||||
case R.id.action_share:
|
||||
activity.startActivity(Intent.createChooser(MusicUtil.createShareSongFileIntent(song, activity), null));
|
||||
return true;
|
||||
case R.id.action_delete_from_device:
|
||||
DeleteSongsDialog.create(song).show(activity.getSupportFragmentManager(), "DELETE_SONGS");
|
||||
return true;
|
||||
case R.id.action_add_to_playlist:
|
||||
AddToPlaylistDialog.create(song).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
|
||||
return true;
|
||||
case R.id.action_play_next:
|
||||
MusicPlayerRemote.playNext(song);
|
||||
return true;
|
||||
case R.id.action_add_to_current_playing:
|
||||
MusicPlayerRemote.enqueue(song);
|
||||
return true;
|
||||
case R.id.action_tag_editor:
|
||||
Intent tagEditorIntent = new Intent(activity, SongTagEditorActivity.class);
|
||||
tagEditorIntent.putExtra(AbsTagEditorActivity.EXTRA_ID, song.id);
|
||||
if (activity instanceof PaletteColorHolder)
|
||||
tagEditorIntent.putExtra(AbsTagEditorActivity.EXTRA_PALETTE, ((PaletteColorHolder) activity).getPaletteColor());
|
||||
activity.startActivity(tagEditorIntent);
|
||||
return true;
|
||||
case R.id.action_details:
|
||||
SongDetailDialog.create(song).show(activity.getSupportFragmentManager(), "SONG_DETAILS");
|
||||
return true;
|
||||
case R.id.action_go_to_album:
|
||||
NavigationUtil.goToAlbum(activity, song.albumId);
|
||||
return true;
|
||||
case R.id.action_go_to_artist:
|
||||
NavigationUtil.goToArtist(activity, song.artistId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static abstract class OnClickSongMenu implements View.OnClickListener, PopupMenu.OnMenuItemClickListener {
|
||||
private AppCompatActivity activity;
|
||||
|
||||
protected OnClickSongMenu(@NonNull AppCompatActivity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
public int getMenuRes() {
|
||||
return MENU_RES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
PopupMenu popupMenu = new PopupMenu(activity, v);
|
||||
popupMenu.inflate(getMenuRes());
|
||||
popupMenu.setOnMenuItemClickListener(this);
|
||||
popupMenu.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
return handleMenuClick(activity, getSong(), item.getItemId());
|
||||
}
|
||||
|
||||
public abstract Song getSong();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package code.name.monkey.retromusic.helper.menu
|
||||
|
||||
import android.content.Intent
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.PopupMenu
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
|
||||
import code.name.monkey.retromusic.dialogs.DeleteSongsDialog
|
||||
import code.name.monkey.retromusic.dialogs.SongDetailDialog
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.interfaces.PaletteColorHolder
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.ui.activities.tageditor.AbsTagEditorActivity
|
||||
import code.name.monkey.retromusic.ui.activities.tageditor.SongTagEditorActivity
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.NavigationUtil
|
||||
|
||||
|
||||
object SongMenuHelper {
|
||||
val MENU_RES = R.menu.menu_item_song
|
||||
|
||||
fun handleMenuClick(activity: FragmentActivity, song: Song, menuItemId: Int): Boolean {
|
||||
when (menuItemId) {
|
||||
R.id.action_set_as_ringtone -> {
|
||||
MusicUtil.setRingtone(activity, song.id)
|
||||
return true
|
||||
}
|
||||
R.id.action_share -> {
|
||||
activity.startActivity(Intent.createChooser(MusicUtil.createShareSongFileIntent(song, activity), null))
|
||||
return true
|
||||
}
|
||||
R.id.action_delete_from_device -> {
|
||||
DeleteSongsDialog.create(song).show(activity.supportFragmentManager, "DELETE_SONGS")
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_playlist -> {
|
||||
AddToPlaylistDialog.create(song).show(activity.supportFragmentManager, "ADD_PLAYLIST")
|
||||
return true
|
||||
}
|
||||
R.id.action_play_next -> {
|
||||
MusicPlayerRemote.playNext(song)
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_current_playing -> {
|
||||
MusicPlayerRemote.enqueue(song)
|
||||
return true
|
||||
}
|
||||
R.id.action_tag_editor -> {
|
||||
val tagEditorIntent = Intent(activity, SongTagEditorActivity::class.java)
|
||||
tagEditorIntent.putExtra(AbsTagEditorActivity.EXTRA_ID, song.id)
|
||||
if (activity is PaletteColorHolder)
|
||||
tagEditorIntent.putExtra(AbsTagEditorActivity.EXTRA_PALETTE, (activity as PaletteColorHolder).paletteColor)
|
||||
activity.startActivity(tagEditorIntent)
|
||||
return true
|
||||
}
|
||||
R.id.action_details -> {
|
||||
SongDetailDialog.create(song).show(activity.supportFragmentManager, "SONG_DETAILS")
|
||||
return true
|
||||
}
|
||||
R.id.action_go_to_album -> {
|
||||
NavigationUtil.goToAlbum(activity, song.albumId)
|
||||
return true
|
||||
}
|
||||
R.id.action_go_to_artist -> {
|
||||
NavigationUtil.goToArtist(activity, song.artistId)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
abstract class OnClickSongMenu protected constructor(private val activity: AppCompatActivity) : View.OnClickListener, PopupMenu.OnMenuItemClickListener {
|
||||
|
||||
open val menuRes: Int
|
||||
get() = MENU_RES
|
||||
|
||||
abstract val song: Song
|
||||
|
||||
override fun onClick(v: View) {
|
||||
val popupMenu = PopupMenu(activity, v)
|
||||
popupMenu.inflate(menuRes)
|
||||
popupMenu.setOnMenuItemClickListener(this)
|
||||
popupMenu.show()
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem): Boolean {
|
||||
return handleMenuClick(activity, song, item.itemId)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package code.name.monkey.retromusic.helper.menu;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog;
|
||||
import code.name.monkey.retromusic.dialogs.DeleteSongsDialog;
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
|
||||
|
||||
|
||||
|
||||
public class SongsMenuHelper {
|
||||
public static boolean handleMenuClick(@NonNull FragmentActivity activity, @NonNull ArrayList<Song> songs, int menuItemId) {
|
||||
switch (menuItemId) {
|
||||
case R.id.action_play_next:
|
||||
MusicPlayerRemote.playNext(songs);
|
||||
return true;
|
||||
case R.id.action_add_to_current_playing:
|
||||
MusicPlayerRemote.enqueue(songs);
|
||||
return true;
|
||||
case R.id.action_add_to_playlist:
|
||||
AddToPlaylistDialog.create(songs).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
|
||||
return true;
|
||||
case R.id.action_delete_from_device:
|
||||
DeleteSongsDialog.create(songs).show(activity.getSupportFragmentManager(), "DELETE_SONGS");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package code.name.monkey.retromusic.helper.menu
|
||||
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
|
||||
import code.name.monkey.retromusic.dialogs.DeleteSongsDialog
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import java.util.*
|
||||
|
||||
|
||||
object SongsMenuHelper {
|
||||
fun handleMenuClick(activity: FragmentActivity, songs: ArrayList<Song>, menuItemId: Int): Boolean {
|
||||
when (menuItemId) {
|
||||
R.id.action_play_next -> {
|
||||
MusicPlayerRemote.playNext(songs)
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_current_playing -> {
|
||||
MusicPlayerRemote.enqueue(songs)
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_playlist -> {
|
||||
AddToPlaylistDialog.create(songs).show(activity.supportFragmentManager, "ADD_PLAYLIST")
|
||||
return true
|
||||
}
|
||||
R.id.action_delete_from_device -> {
|
||||
DeleteSongsDialog.create(songs).show(activity.supportFragmentManager, "DELETE_SONGS")
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue