Initial commit retro music app
This commit is contained in:
parent
ab332473bc
commit
fe890632fd
932 changed files with 83126 additions and 0 deletions
|
@ -0,0 +1,28 @@
|
|||
package code.name.monkey.retromusic.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
|
||||
|
||||
|
||||
public abstract class AbsCustomPlaylist extends Playlist {
|
||||
public AbsCustomPlaylist(int id, String name) {
|
||||
super(id, name);
|
||||
}
|
||||
|
||||
public AbsCustomPlaylist() {
|
||||
}
|
||||
|
||||
public AbsCustomPlaylist(Parcel in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public abstract Observable<ArrayList<Song>> getSongs(Context context);
|
||||
}
|
||||
|
103
app/src/main/java/code/name/monkey/retromusic/model/Album.java
Normal file
103
app/src/main/java/code/name/monkey/retromusic/model/Album.java
Normal file
|
@ -0,0 +1,103 @@
|
|||
package code.name.monkey.retromusic.model;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
public class Album implements Parcelable {
|
||||
|
||||
public static final Creator<Album> CREATOR = new Creator<Album>() {
|
||||
public Album createFromParcel(Parcel source) {
|
||||
return new Album(source);
|
||||
}
|
||||
|
||||
public Album[] newArray(int size) {
|
||||
return new Album[size];
|
||||
}
|
||||
};
|
||||
public final ArrayList<Song> songs;
|
||||
|
||||
public Album(ArrayList<Song> songs) {
|
||||
this.songs = songs;
|
||||
}
|
||||
|
||||
public Album() {
|
||||
this.songs = new ArrayList<>();
|
||||
}
|
||||
|
||||
protected Album(Parcel in) {
|
||||
this.songs = in.createTypedArrayList(Song.CREATOR);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return safeGetFirstSong().albumId;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return safeGetFirstSong().albumName;
|
||||
}
|
||||
|
||||
public int getArtistId() {
|
||||
return safeGetFirstSong().artistId;
|
||||
}
|
||||
|
||||
public String getArtistName() {
|
||||
return safeGetFirstSong().artistName;
|
||||
}
|
||||
|
||||
public int getYear() {
|
||||
return safeGetFirstSong().year;
|
||||
}
|
||||
|
||||
public long getDateModified() {
|
||||
return safeGetFirstSong().dateModified;
|
||||
}
|
||||
|
||||
public int getSongCount() {
|
||||
return songs.size();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Song safeGetFirstSong() {
|
||||
return songs.isEmpty() ? Song.EMPTY_SONG : songs.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Album that = (Album) o;
|
||||
|
||||
return songs != null ? songs.equals(that.songs) : that.songs == null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return songs != null ? songs.hashCode() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Album{" +
|
||||
"songs=" + songs +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeTypedList(songs);
|
||||
}
|
||||
}
|
110
app/src/main/java/code/name/monkey/retromusic/model/Artist.java
Normal file
110
app/src/main/java/code/name/monkey/retromusic/model/Artist.java
Normal file
|
@ -0,0 +1,110 @@
|
|||
package code.name.monkey.retromusic.model;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.util.MusicUtil;
|
||||
|
||||
|
||||
public class Artist implements Parcelable {
|
||||
public static final String UNKNOWN_ARTIST_DISPLAY_NAME = "Unknown Artist";
|
||||
public final ArrayList<Album> albums;
|
||||
|
||||
public Artist(ArrayList<Album> albums) {
|
||||
this.albums = albums;
|
||||
}
|
||||
|
||||
public Artist() {
|
||||
this.albums = new ArrayList<>();
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return safeGetFirstAlbum().getArtistId();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
String name = safeGetFirstAlbum().getArtistName();
|
||||
if (MusicUtil.isArtistNameUnknown(name)) {
|
||||
return UNKNOWN_ARTIST_DISPLAY_NAME;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getSongCount() {
|
||||
int songCount = 0;
|
||||
for (Album album : albums) {
|
||||
songCount += album.getSongCount();
|
||||
}
|
||||
return songCount;
|
||||
}
|
||||
|
||||
public int getAlbumCount() {
|
||||
return albums.size();
|
||||
}
|
||||
|
||||
public ArrayList<Song> getSongs() {
|
||||
ArrayList<Song> songs = new ArrayList<>();
|
||||
for (Album album : albums) {
|
||||
songs.addAll(album.songs);
|
||||
}
|
||||
return songs;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Album safeGetFirstAlbum() {
|
||||
return albums.isEmpty() ? new Album() : albums.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Artist artist = (Artist) o;
|
||||
|
||||
return albums != null ? albums.equals(artist.albums) : artist.albums == null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return albums != null ? albums.hashCode() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Artist{" +
|
||||
"albums=" + albums +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeTypedList(this.albums);
|
||||
}
|
||||
|
||||
protected Artist(Parcel in) {
|
||||
this.albums = in.createTypedArrayList(Album.CREATOR);
|
||||
}
|
||||
|
||||
public static final Creator<Artist> CREATOR = new Creator<Artist>() {
|
||||
@Override
|
||||
public Artist createFromParcel(Parcel source) {
|
||||
return new Artist(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Artist[] newArray(int size) {
|
||||
return new Artist[size];
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package code.name.monkey.retromusic.model;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
|
||||
|
||||
public class CategoryInfo implements Parcelable {
|
||||
public static final Parcelable.Creator<CategoryInfo> CREATOR = new Parcelable.Creator<CategoryInfo>() {
|
||||
public CategoryInfo createFromParcel(Parcel source) {
|
||||
return new CategoryInfo(source);
|
||||
}
|
||||
|
||||
public CategoryInfo[] newArray(int size) {
|
||||
return new CategoryInfo[size];
|
||||
}
|
||||
};
|
||||
public Category category;
|
||||
public boolean visible;
|
||||
|
||||
public CategoryInfo(Category category, boolean visible) {
|
||||
this.category = category;
|
||||
this.visible = visible;
|
||||
}
|
||||
|
||||
|
||||
private CategoryInfo(Parcel source) {
|
||||
category = (Category) source.readSerializable();
|
||||
visible = source.readInt() == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeSerializable(category);
|
||||
dest.writeInt(visible ? 1 : 0);
|
||||
}
|
||||
|
||||
public enum Category {
|
||||
SONGS(R.string.songs),
|
||||
ALBUMS(R.string.albums),
|
||||
ARTISTS(R.string.artists),
|
||||
GENRES(R.string.genres),
|
||||
PLAYLISTS(R.string.playlists);
|
||||
|
||||
public final int stringRes;
|
||||
|
||||
Category(int stringRes) {
|
||||
this.stringRes = stringRes;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package code.name.monkey.retromusic.model;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
public class Genre implements Parcelable {
|
||||
|
||||
public static final Creator<Genre> CREATOR = new Creator<Genre>() {
|
||||
@Override
|
||||
public Genre createFromParcel(Parcel in) {
|
||||
return new Genre(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Genre[] newArray(int size) {
|
||||
return new Genre[size];
|
||||
}
|
||||
};
|
||||
public final int id;
|
||||
public final String name;
|
||||
public final int songCount;
|
||||
|
||||
public Genre(final int id, final String name, int songCount) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.songCount = songCount;
|
||||
}
|
||||
|
||||
|
||||
// For unknown genre
|
||||
public Genre(final String name, final int songCount) {
|
||||
this.id = -1;
|
||||
this.name = name;
|
||||
this.songCount = songCount;
|
||||
}
|
||||
|
||||
protected Genre(Parcel in) {
|
||||
id = in.readInt();
|
||||
name = in.readString();
|
||||
songCount = in.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(id);
|
||||
dest.writeString(name);
|
||||
dest.writeInt(songCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Genre genre = (Genre) o;
|
||||
|
||||
if (id != genre.id) return false;
|
||||
return name != null ? name.equals(genre.name) : genre.name == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id;
|
||||
result = 31 * result + (name != null ? name.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Genre{" +
|
||||
"id=" + id +
|
||||
", name='" + name + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
}
|
50
app/src/main/java/code/name/monkey/retromusic/model/Home.java
Executable file
50
app/src/main/java/code/name/monkey/retromusic/model/Home.java
Executable file
|
@ -0,0 +1,50 @@
|
|||
package code.name.monkey.retromusic.model;
|
||||
|
||||
import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
/**
|
||||
* Created by BlackFootSanji on 5/22/2017.
|
||||
*/
|
||||
|
||||
public class Home {
|
||||
public String sectionTitle;
|
||||
public ArrayList<Object> list;
|
||||
public AbsSmartPlaylist playlist;
|
||||
|
||||
public Home(String sectionTitle, AbsSmartPlaylist playlist) {
|
||||
this.sectionTitle = sectionTitle;
|
||||
this.playlist = playlist;
|
||||
}
|
||||
|
||||
public Home(String sectionTitle, ArrayList<Object> list) {
|
||||
this.sectionTitle = sectionTitle;
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public Home(AbsSmartPlaylist playlist) {
|
||||
this.playlist = playlist;
|
||||
}
|
||||
|
||||
public AbsSmartPlaylist getPlaylist() {
|
||||
return playlist;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Home{" +
|
||||
"sectionTitle='" + sectionTitle + '\'' +
|
||||
", songs=" + list +
|
||||
'}';
|
||||
}
|
||||
|
||||
public String getSectionTitle() {
|
||||
return sectionTitle;
|
||||
}
|
||||
|
||||
public ArrayList<Object> getList() {
|
||||
return list;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package code.name.monkey.retromusic.model;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
|
||||
public class Playlist implements Parcelable {
|
||||
public static final Creator<Playlist> CREATOR = new Creator<Playlist>() {
|
||||
public Playlist createFromParcel(Parcel source) {
|
||||
return new Playlist(source);
|
||||
}
|
||||
|
||||
public Playlist[] newArray(int size) {
|
||||
return new Playlist[size];
|
||||
}
|
||||
};
|
||||
public final int id;
|
||||
public final String name;
|
||||
|
||||
public Playlist(final int id, final String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Playlist() {
|
||||
this.id = -1;
|
||||
this.name = "";
|
||||
}
|
||||
|
||||
protected Playlist(Parcel in) {
|
||||
this.id = in.readInt();
|
||||
this.name = in.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Playlist playlist = (Playlist) o;
|
||||
|
||||
if (id != playlist.id) return false;
|
||||
return name != null ? name.equals(playlist.name) : playlist.name == null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id;
|
||||
result = 31 * result + (name != null ? name.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Playlist{" +
|
||||
"id=" + id +
|
||||
", name='" + name + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(this.id);
|
||||
dest.writeString(this.name);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package code.name.monkey.retromusic.model;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class PlaylistSong extends Song {
|
||||
public static final PlaylistSong EMPTY_PLAYLIST_SONG = new PlaylistSong(-1, "", -1, -1, -1, "", -1, -1, "", -1, "", -1, -1);
|
||||
|
||||
public final int playlistId;
|
||||
public final int idInPlayList;
|
||||
|
||||
public PlaylistSong(int id, String title, int trackNumber, int year, long duration, String data, int dateModified, int albumId, String albumName, int artistId, String artistName, final int playlistId, final int idInPlayList) {
|
||||
super(id, title, trackNumber, year, duration, data, dateModified, albumId, albumName, artistId, artistName);
|
||||
this.playlistId = playlistId;
|
||||
this.idInPlayList = idInPlayList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
|
||||
PlaylistSong that = (PlaylistSong) o;
|
||||
|
||||
if (playlistId != that.playlistId) return false;
|
||||
return idInPlayList == that.idInPlayList;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + playlistId;
|
||||
result = 31 * result + idInPlayList;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() +
|
||||
"PlaylistSong{" +
|
||||
"playlistId=" + playlistId +
|
||||
", idInPlayList=" + idInPlayList +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeInt(this.playlistId);
|
||||
dest.writeInt(this.idInPlayList);
|
||||
}
|
||||
|
||||
protected PlaylistSong(Parcel in) {
|
||||
super(in);
|
||||
this.playlistId = in.readInt();
|
||||
this.idInPlayList = in.readInt();
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<PlaylistSong> CREATOR = new Parcelable.Creator<PlaylistSong>() {
|
||||
public PlaylistSong createFromParcel(Parcel source) {
|
||||
return new PlaylistSong(source);
|
||||
}
|
||||
|
||||
public PlaylistSong[] newArray(int size) {
|
||||
return new PlaylistSong[size];
|
||||
}
|
||||
};
|
||||
}
|
135
app/src/main/java/code/name/monkey/retromusic/model/Song.java
Normal file
135
app/src/main/java/code/name/monkey/retromusic/model/Song.java
Normal file
|
@ -0,0 +1,135 @@
|
|||
package code.name.monkey.retromusic.model;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
|
||||
public class Song implements Parcelable {
|
||||
public static final Song EMPTY_SONG = new Song(-1, "", -1, -1, -1, "", -1, -1, "", -1, "");
|
||||
|
||||
public final int id;
|
||||
public final String title;
|
||||
public final int trackNumber;
|
||||
public final int year;
|
||||
public final long duration;
|
||||
public final String data;
|
||||
public final long dateModified;
|
||||
public final int albumId;
|
||||
public final String albumName;
|
||||
public final int artistId;
|
||||
public final String artistName;
|
||||
|
||||
public Song(int id, String title, int trackNumber, int year, long duration, String data, long dateModified, int albumId, String albumName, int artistId, String artistName) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.trackNumber = trackNumber;
|
||||
this.year = year;
|
||||
this.duration = duration;
|
||||
this.data = data;
|
||||
this.dateModified = dateModified;
|
||||
this.albumId = albumId;
|
||||
this.albumName = albumName;
|
||||
this.artistId = artistId;
|
||||
this.artistName = artistName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Song song = (Song) o;
|
||||
|
||||
if (id != song.id) return false;
|
||||
if (trackNumber != song.trackNumber) return false;
|
||||
if (year != song.year) return false;
|
||||
if (duration != song.duration) return false;
|
||||
if (dateModified != song.dateModified) return false;
|
||||
if (albumId != song.albumId) return false;
|
||||
if (artistId != song.artistId) return false;
|
||||
if (title != null ? !title.equals(song.title) : song.title != null) return false;
|
||||
if (data != null ? !data.equals(song.data) : song.data != null) return false;
|
||||
if (albumName != null ? !albumName.equals(song.albumName) : song.albumName != null)
|
||||
return false;
|
||||
return artistName != null ? artistName.equals(song.artistName) : song.artistName == null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id;
|
||||
result = 31 * result + (title != null ? title.hashCode() : 0);
|
||||
result = 31 * result + trackNumber;
|
||||
result = 31 * result + year;
|
||||
result = 31 * result + (int) (duration ^ (duration >>> 32));
|
||||
result = 31 * result + (data != null ? data.hashCode() : 0);
|
||||
result = 31 * result + (int) (dateModified ^ (dateModified >>> 32));
|
||||
result = 31 * result + albumId;
|
||||
result = 31 * result + (albumName != null ? albumName.hashCode() : 0);
|
||||
result = 31 * result + artistId;
|
||||
result = 31 * result + (artistName != null ? artistName.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Song{" +
|
||||
"id=" + id +
|
||||
", title='" + title + '\'' +
|
||||
", trackNumber=" + trackNumber +
|
||||
", year=" + year +
|
||||
", duration=" + duration +
|
||||
", data='" + data + '\'' +
|
||||
", dateModified=" + dateModified +
|
||||
", albumId=" + albumId +
|
||||
", albumName='" + albumName + '\'' +
|
||||
", artistId=" + artistId +
|
||||
", artistName='" + artistName + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(this.id);
|
||||
dest.writeString(this.title);
|
||||
dest.writeInt(this.trackNumber);
|
||||
dest.writeInt(this.year);
|
||||
dest.writeLong(this.duration);
|
||||
dest.writeString(this.data);
|
||||
dest.writeLong(this.dateModified);
|
||||
dest.writeInt(this.albumId);
|
||||
dest.writeString(this.albumName);
|
||||
dest.writeInt(this.artistId);
|
||||
dest.writeString(this.artistName);
|
||||
}
|
||||
|
||||
protected Song(Parcel in) {
|
||||
this.id = in.readInt();
|
||||
this.title = in.readString();
|
||||
this.trackNumber = in.readInt();
|
||||
this.year = in.readInt();
|
||||
this.duration = in.readLong();
|
||||
this.data = in.readString();
|
||||
this.dateModified = in.readLong();
|
||||
this.albumId = in.readInt();
|
||||
this.albumName = in.readString();
|
||||
this.artistId = in.readInt();
|
||||
this.artistName = in.readString();
|
||||
}
|
||||
|
||||
public static final Creator<Song> CREATOR = new Creator<Song>() {
|
||||
public Song createFromParcel(Parcel source) {
|
||||
return new Song(source);
|
||||
}
|
||||
|
||||
public Song[] newArray(int size) {
|
||||
return new Song[size];
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package code.name.monkey.retromusic.model.lyrics;
|
||||
|
||||
import android.util.SparseArray;
|
||||
|
||||
public abstract class AbsSynchronizedLyrics extends Lyrics {
|
||||
private static final int TIME_OFFSET_MS = 500; // time adjustment to display line before it actually starts
|
||||
|
||||
protected final SparseArray<String> lines = new SparseArray<>();
|
||||
protected int offset = 0;
|
||||
|
||||
public String getLine(int time) {
|
||||
time += offset + AbsSynchronizedLyrics.TIME_OFFSET_MS;
|
||||
|
||||
int lastLineTime = lines.keyAt(0);
|
||||
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
int lineTime = lines.keyAt(i);
|
||||
|
||||
if (time >= lineTime) {
|
||||
lastLineTime = lineTime;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return lines.get(lastLineTime);
|
||||
}
|
||||
|
||||
public boolean isSynchronized() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
parse(true);
|
||||
return valid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
parse(false);
|
||||
|
||||
if (valid) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
String line = lines.valueAt(i);
|
||||
sb.append(line).append("\r\n");
|
||||
}
|
||||
|
||||
return sb.toString().trim().replaceAll("(\r?\n){3,}", "\r\n\r\n");
|
||||
}
|
||||
|
||||
return super.getText();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package code.name.monkey.retromusic.model.lyrics;
|
||||
|
||||
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
public class Lyrics {
|
||||
private static final ArrayList<Class<? extends Lyrics>> FORMATS = new ArrayList<>();
|
||||
|
||||
public Song song;
|
||||
public String data;
|
||||
|
||||
protected boolean parsed = false;
|
||||
protected boolean valid = false;
|
||||
|
||||
public Lyrics setData(Song song, String data) {
|
||||
this.song = song;
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Lyrics parse(Song song, String data) {
|
||||
for (Class<? extends Lyrics> format : Lyrics.FORMATS) {
|
||||
try {
|
||||
Lyrics lyrics = format.newInstance().setData(song, data);
|
||||
if (lyrics.isValid()) return lyrics.parse(false);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return new Lyrics().setData(song, data).parse(false);
|
||||
}
|
||||
|
||||
public static boolean isSynchronized(String data) {
|
||||
for (Class<? extends Lyrics> format : Lyrics.FORMATS) {
|
||||
try {
|
||||
Lyrics lyrics = format.newInstance().setData(null, data);
|
||||
if (lyrics.isValid()) return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Lyrics parse(boolean check) {
|
||||
this.valid = true;
|
||||
this.parsed = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isSynchronized() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
this.parse(true);
|
||||
return this.valid;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return this.data.trim().replaceAll("(\r?\n){3,}", "\r\n\r\n");
|
||||
}
|
||||
|
||||
static {
|
||||
Lyrics.FORMATS.add(SynchronizedLyricsLRC.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package code.name.monkey.retromusic.model.lyrics;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class SynchronizedLyricsLRC extends AbsSynchronizedLyrics {
|
||||
private static final Pattern LRC_LINE_PATTERN = Pattern.compile("((?:\\[.*?\\])+)(.*)");
|
||||
private static final Pattern LRC_TIME_PATTERN = Pattern.compile("\\[(\\d+):(\\d{2}(?:\\.\\d+)?)\\]");
|
||||
private static final Pattern LRC_ATTRIBUTE_PATTERN = Pattern.compile("\\[(\\D+):(.+)\\]");
|
||||
|
||||
private static final float LRC_SECONDS_TO_MS_MULTIPLIER = 1000f;
|
||||
private static final int LRC_MINUTES_TO_MS_MULTIPLIER = 60000;
|
||||
|
||||
@Override
|
||||
public SynchronizedLyricsLRC parse(boolean check) {
|
||||
if (this.parsed || this.data == null || this.data.isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
String[] lines = this.data.split("\r?\n");
|
||||
|
||||
for (String line : lines) {
|
||||
line = line.trim();
|
||||
if (line.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Matcher attrMatcher = SynchronizedLyricsLRC.LRC_ATTRIBUTE_PATTERN.matcher(line);
|
||||
if (attrMatcher.find()) {
|
||||
try {
|
||||
String attr = attrMatcher.group(1).toLowerCase().trim();
|
||||
String value = attrMatcher.group(2).toLowerCase().trim();
|
||||
switch (attr) {
|
||||
case "offset":
|
||||
this.offset = Integer.parseInt(value);
|
||||
break;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
Matcher matcher = SynchronizedLyricsLRC.LRC_LINE_PATTERN.matcher(line);
|
||||
if (matcher.find()) {
|
||||
String time = matcher.group(1);
|
||||
String text = matcher.group(2);
|
||||
|
||||
Matcher timeMatcher = SynchronizedLyricsLRC.LRC_TIME_PATTERN.matcher(time);
|
||||
while (timeMatcher.find()) {
|
||||
int m = 0;
|
||||
float s = 0f;
|
||||
try {
|
||||
m = Integer.parseInt(timeMatcher.group(1));
|
||||
s = Float.parseFloat(timeMatcher.group(2));
|
||||
} catch (NumberFormatException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
int ms = (int) (s * LRC_SECONDS_TO_MS_MULTIPLIER) + m * LRC_MINUTES_TO_MS_MULTIPLIER;
|
||||
|
||||
this.valid = true;
|
||||
if (check) return this;
|
||||
|
||||
this.lines.append(ms, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.parsed = true;
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package code.name.monkey.retromusic.model.smartplaylist;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.model.AbsCustomPlaylist;
|
||||
|
||||
|
||||
public abstract class AbsSmartPlaylist extends AbsCustomPlaylist {
|
||||
@DrawableRes
|
||||
public final int iconRes;
|
||||
|
||||
public AbsSmartPlaylist(final String name, final int iconRes) {
|
||||
super(-Math.abs(31 * name.hashCode() + (iconRes * name.hashCode() * 31 * 31)), name);
|
||||
this.iconRes = iconRes;
|
||||
}
|
||||
|
||||
public AbsSmartPlaylist() {
|
||||
super();
|
||||
this.iconRes = R.drawable.ic_playlist_play_white_24dp;
|
||||
}
|
||||
|
||||
protected AbsSmartPlaylist(Parcel in) {
|
||||
super(in);
|
||||
this.iconRes = in.readInt();
|
||||
}
|
||||
|
||||
public abstract void clear(Context context);
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = super.hashCode();
|
||||
result = prime * result + iconRes;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable final Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final AbsSmartPlaylist other = (AbsSmartPlaylist) obj;
|
||||
return iconRes == other.iconRes;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeInt(this.iconRes);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package code.name.monkey.retromusic.model.smartplaylist;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.loaders.TopAndRecentlyPlayedTracksLoader;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.providers.HistoryStore;
|
||||
import io.reactivex.Observable;
|
||||
|
||||
|
||||
public class HistoryPlaylist extends AbsSmartPlaylist {
|
||||
|
||||
public static final Parcelable.Creator<HistoryPlaylist> CREATOR = new Parcelable.Creator<HistoryPlaylist>() {
|
||||
public HistoryPlaylist createFromParcel(Parcel source) {
|
||||
return new HistoryPlaylist(source);
|
||||
}
|
||||
|
||||
public HistoryPlaylist[] newArray(int size) {
|
||||
return new HistoryPlaylist[size];
|
||||
}
|
||||
};
|
||||
|
||||
public HistoryPlaylist(@NonNull Context context) {
|
||||
super(context.getString(R.string.history), R.drawable.ic_access_time_white_24dp);
|
||||
}
|
||||
|
||||
protected HistoryPlaylist(Parcel in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Observable<ArrayList<Song>> getSongs(@NonNull Context context) {
|
||||
return TopAndRecentlyPlayedTracksLoader.getRecentlyPlayedTracks(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(@NonNull Context context) {
|
||||
HistoryStore.getInstance(context).clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package code.name.monkey.retromusic.model.smartplaylist;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.loaders.LastAddedSongsLoader;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
|
||||
|
||||
public class LastAddedPlaylist extends AbsSmartPlaylist {
|
||||
|
||||
public static final Parcelable.Creator<LastAddedPlaylist> CREATOR = new Parcelable.Creator<LastAddedPlaylist>() {
|
||||
public LastAddedPlaylist createFromParcel(Parcel source) {
|
||||
return new LastAddedPlaylist(source);
|
||||
}
|
||||
|
||||
public LastAddedPlaylist[] newArray(int size) {
|
||||
return new LastAddedPlaylist[size];
|
||||
}
|
||||
};
|
||||
|
||||
public LastAddedPlaylist(@NonNull Context context) {
|
||||
super(context.getString(R.string.last_added), R.drawable.ic_library_add_white_24dp);
|
||||
}
|
||||
|
||||
protected LastAddedPlaylist(Parcel in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Observable<ArrayList<Song>> getSongs(@NonNull Context context) {
|
||||
return LastAddedSongsLoader.getLastAddedSongs(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(@NonNull Context context) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package code.name.monkey.retromusic.model.smartplaylist;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.loaders.TopAndRecentlyPlayedTracksLoader;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.providers.SongPlayCountStore;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
|
||||
|
||||
public class MyTopTracksPlaylist extends AbsSmartPlaylist implements Parcelable {
|
||||
public static final Creator<MyTopTracksPlaylist> CREATOR = new Creator<MyTopTracksPlaylist>() {
|
||||
public MyTopTracksPlaylist createFromParcel(Parcel source) {
|
||||
return new MyTopTracksPlaylist(source);
|
||||
}
|
||||
|
||||
public MyTopTracksPlaylist[] newArray(int size) {
|
||||
return new MyTopTracksPlaylist[size];
|
||||
}
|
||||
};
|
||||
|
||||
public MyTopTracksPlaylist(@NonNull Context context) {
|
||||
super(context.getString(R.string.my_top_tracks), R.drawable.ic_trending_up_white_24dp);
|
||||
}
|
||||
|
||||
protected MyTopTracksPlaylist(Parcel in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Observable<ArrayList<Song>> getSongs(@NonNull Context context) {
|
||||
return TopAndRecentlyPlayedTracksLoader.getTopTracks(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(@NonNull Context context) {
|
||||
SongPlayCountStore.getInstance(context).clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package code.name.monkey.retromusic.model.smartplaylist;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.loaders.SongLoader;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
|
||||
public class ShuffleAllPlaylist extends AbsSmartPlaylist {
|
||||
|
||||
public static final Parcelable.Creator<ShuffleAllPlaylist> CREATOR = new Parcelable.Creator<ShuffleAllPlaylist>() {
|
||||
public ShuffleAllPlaylist createFromParcel(Parcel source) {
|
||||
return new ShuffleAllPlaylist(source);
|
||||
}
|
||||
|
||||
public ShuffleAllPlaylist[] newArray(int size) {
|
||||
return new ShuffleAllPlaylist[size];
|
||||
}
|
||||
};
|
||||
|
||||
public ShuffleAllPlaylist(@NonNull Context context) {
|
||||
super(context.getString(R.string.action_shuffle_all), R.drawable.ic_shuffle_white_24dp);
|
||||
}
|
||||
|
||||
protected ShuffleAllPlaylist(Parcel in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Observable<ArrayList<Song>> getSongs(@NonNull Context context) {
|
||||
return SongLoader.getAllSongs(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(@NonNull Context context) {
|
||||
// Shuffle all is not a real "Smart Playlist"
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue