utilize downloaded files within detail activities
This commit is contained in:
parent
5bde02dc8b
commit
395b1227c9
11 changed files with 100 additions and 15 deletions
|
|
@ -61,6 +61,7 @@ public class App extends Application {
|
||||||
.addMigrations(JellyDatabase.Migration2)
|
.addMigrations(JellyDatabase.Migration2)
|
||||||
.addMigrations(JellyDatabase.Migration3)
|
.addMigrations(JellyDatabase.Migration3)
|
||||||
.addMigrations(JellyDatabase.Migration4)
|
.addMigrations(JellyDatabase.Migration4)
|
||||||
|
.addMigrations(JellyDatabase.Migration5)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
29
app/src/main/java/com/dkanada/gramophone/database/Cache.java
Normal file
29
app/src/main/java/com/dkanada/gramophone/database/Cache.java
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.dkanada.gramophone.database;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.room.ColumnInfo;
|
||||||
|
import androidx.room.Entity;
|
||||||
|
import androidx.room.PrimaryKey;
|
||||||
|
|
||||||
|
import com.dkanada.gramophone.model.Song;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity(tableName = "cache")
|
||||||
|
public class Cache {
|
||||||
|
@NonNull
|
||||||
|
@PrimaryKey
|
||||||
|
public String id;
|
||||||
|
|
||||||
|
@ColumnInfo(defaultValue = "1")
|
||||||
|
public Boolean cache;
|
||||||
|
|
||||||
|
public Cache() {
|
||||||
|
this.id = UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cache(Song song) {
|
||||||
|
this.id = song.id;
|
||||||
|
this.cache = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.dkanada.gramophone.database;
|
||||||
|
|
||||||
|
import androidx.room.Dao;
|
||||||
|
import androidx.room.Insert;
|
||||||
|
import androidx.room.OnConflictStrategy;
|
||||||
|
import androidx.room.Query;
|
||||||
|
|
||||||
|
import com.dkanada.gramophone.model.Song;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
public interface CacheDao {
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
void insertCache(Cache cache);
|
||||||
|
|
||||||
|
@Query("SELECT * FROM songs LEFT JOIN cache USING(id) WHERE songs.id IN (:ids)")
|
||||||
|
List<Song> getSongs(List<String> ids);
|
||||||
|
}
|
||||||
|
|
@ -10,14 +10,16 @@ import com.dkanada.gramophone.model.User;
|
||||||
|
|
||||||
@androidx.room.Database(
|
@androidx.room.Database(
|
||||||
entities = {
|
entities = {
|
||||||
|
Cache.class,
|
||||||
Song.class,
|
Song.class,
|
||||||
QueueSong.class,
|
QueueSong.class,
|
||||||
User.class
|
User.class
|
||||||
},
|
},
|
||||||
version = 4,
|
version = 5,
|
||||||
exportSchema = false
|
exportSchema = false
|
||||||
)
|
)
|
||||||
public abstract class JellyDatabase extends RoomDatabase {
|
public abstract class JellyDatabase extends RoomDatabase {
|
||||||
|
public abstract CacheDao cacheDao();
|
||||||
public abstract SongDao songDao();
|
public abstract SongDao songDao();
|
||||||
public abstract QueueSongDao queueSongDao();
|
public abstract QueueSongDao queueSongDao();
|
||||||
public abstract UserDao userDao();
|
public abstract UserDao userDao();
|
||||||
|
|
@ -52,4 +54,12 @@ public abstract class JellyDatabase extends RoomDatabase {
|
||||||
+ "name TEXT, server TEXT, token TEXT)");
|
+ "name TEXT, server TEXT, token TEXT)");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static final Migration Migration5 = new Migration(4, 5) {
|
||||||
|
@Override
|
||||||
|
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||||
|
database.execSQL("CREATE TABLE cache (id TEXT NOT NULL PRIMARY KEY,"
|
||||||
|
+ "cache INTEGER NOT NULL)");
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import androidx.room.Dao;
|
||||||
import androidx.room.Insert;
|
import androidx.room.Insert;
|
||||||
import androidx.room.OnConflictStrategy;
|
import androidx.room.OnConflictStrategy;
|
||||||
import androidx.room.Query;
|
import androidx.room.Query;
|
||||||
|
import androidx.room.Transaction;
|
||||||
|
|
||||||
import com.dkanada.gramophone.App;
|
import com.dkanada.gramophone.App;
|
||||||
import com.dkanada.gramophone.model.Song;
|
import com.dkanada.gramophone.model.Song;
|
||||||
|
|
@ -22,6 +23,7 @@ public abstract class QueueSongDao {
|
||||||
@Query("SELECT * from queueSongs WHERE queue = :queue ORDER BY `index`")
|
@Query("SELECT * from queueSongs WHERE queue = :queue ORDER BY `index`")
|
||||||
public abstract List<QueueSong> getQueueSongs(int queue);
|
public abstract List<QueueSong> getQueueSongs(int queue);
|
||||||
|
|
||||||
|
@Transaction
|
||||||
public List<Song> getQueue(int queue) {
|
public List<Song> getQueue(int queue) {
|
||||||
List<QueueSong> queueSongs = getQueueSongs(queue);
|
List<QueueSong> queueSongs = getQueueSongs(queue);
|
||||||
List<Song> songs = new ArrayList<>();
|
List<Song> songs = new ArrayList<>();
|
||||||
|
|
@ -34,6 +36,7 @@ public abstract class QueueSongDao {
|
||||||
return songs;
|
return songs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transaction
|
||||||
public void setQueue(List<Song> songs, int queue) {
|
public void setQueue(List<Song> songs, int queue) {
|
||||||
List<QueueSong> queueSongs = new ArrayList<>();
|
List<QueueSong> queueSongs = new ArrayList<>();
|
||||||
for (int i = 0; i < songs.size(); i++) {
|
for (int i = 0; i < songs.size(); i++) {
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ public class Song implements Parcelable {
|
||||||
public int bitDepth;
|
public int bitDepth;
|
||||||
public int channels;
|
public int channels;
|
||||||
|
|
||||||
|
public boolean cache;
|
||||||
|
|
||||||
public Song() {
|
public Song() {
|
||||||
this.id = UUID.randomUUID().toString();
|
this.id = UUID.randomUUID().toString();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ package com.dkanada.gramophone.service;
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Environment;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
|
||||||
import com.dkanada.gramophone.App;
|
import com.dkanada.gramophone.App;
|
||||||
import com.dkanada.gramophone.BuildConfig;
|
import com.dkanada.gramophone.BuildConfig;
|
||||||
|
import com.dkanada.gramophone.database.Cache;
|
||||||
import com.dkanada.gramophone.model.Song;
|
import com.dkanada.gramophone.model.Song;
|
||||||
import com.dkanada.gramophone.util.MusicUtil;
|
import com.dkanada.gramophone.util.MusicUtil;
|
||||||
|
|
||||||
|
|
@ -50,11 +50,7 @@ public class DownloadService extends Service {
|
||||||
try {
|
try {
|
||||||
URL url = new URL(MusicUtil.getDownloadUri(song));
|
URL url = new URL(MusicUtil.getDownloadUri(song));
|
||||||
URLConnection connection = url.openConnection();
|
URLConnection connection = url.openConnection();
|
||||||
|
File audio = new File(MusicUtil.getFileUri(song));
|
||||||
File root = new File(App.getInstance().getCacheDir(), "music");
|
|
||||||
String path = song.artistName + "/" + song.albumName + "/";
|
|
||||||
String name = song.discNumber + "." + song.trackNumber + " - " + song.title + "." + song.container;
|
|
||||||
File audio = new File(root, path + name);
|
|
||||||
|
|
||||||
audio.getParentFile().mkdirs();
|
audio.getParentFile().mkdirs();
|
||||||
audio.createNewFile();
|
audio.createNewFile();
|
||||||
|
|
@ -64,7 +60,7 @@ public class DownloadService extends Service {
|
||||||
|
|
||||||
connection.connect();
|
connection.connect();
|
||||||
|
|
||||||
byte[] data = new byte[4096];
|
byte[] data = new byte[262144];
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
while ((count = input.read(data)) != -1) {
|
while ((count = input.read(data)) != -1) {
|
||||||
|
|
@ -73,6 +69,8 @@ public class DownloadService extends Service {
|
||||||
|
|
||||||
input.close();
|
input.close();
|
||||||
output.close();
|
output.close();
|
||||||
|
|
||||||
|
App.getDatabase().cacheDao().insertCache(new Cache(song));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,15 +96,14 @@ public class LocalPlayer implements Playback {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setDataSource(Song song) {
|
public void setDataSource(Song song) {
|
||||||
String uri = MusicUtil.getTranscodeUri(song);
|
|
||||||
MediaItem mediaItem = exoPlayer.getCurrentMediaItem();
|
MediaItem mediaItem = exoPlayer.getCurrentMediaItem();
|
||||||
|
|
||||||
if (mediaItem != null && mediaItem.playbackProperties.uri.toString().equals(uri)) {
|
if (mediaItem != null && mediaItem.mediaId.equals(song.id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
exoPlayer.clearMediaItems();
|
exoPlayer.clearMediaItems();
|
||||||
appendDataSource(MusicUtil.getTranscodeUri(song));
|
appendDataSource(song);
|
||||||
exoPlayer.seekTo(0, 0);
|
exoPlayer.seekTo(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,12 +113,19 @@ public class LocalPlayer implements Playback {
|
||||||
exoPlayer.removeMediaItem(1);
|
exoPlayer.removeMediaItem(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
appendDataSource(MusicUtil.getTranscodeUri(song));
|
appendDataSource(song);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendDataSource(Song song) {
|
||||||
|
File audio = new File(MusicUtil.getFileUri(song));
|
||||||
|
Uri uri = Uri.fromFile(audio);
|
||||||
|
|
||||||
|
if (!song.cache || !audio.exists()) {
|
||||||
|
uri = Uri.parse(MusicUtil.getTranscodeUri(song));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendDataSource(String path) {
|
|
||||||
Uri uri = Uri.parse(path);
|
|
||||||
MediaItem mediaItem = MediaItem.fromUri(uri);
|
MediaItem mediaItem = MediaItem.fromUri(uri);
|
||||||
|
mediaItem = mediaItem.buildUpon().setMediaId(song.id).build();
|
||||||
|
|
||||||
exoPlayer.addMediaItem(mediaItem);
|
exoPlayer.addMediaItem(mediaItem);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,10 @@ class UnknownMediaSourceFactory(dataSourceFactory: DataSource.Factory) : MediaSo
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createMediaSource(mediaItem: MediaItem): MediaSource {
|
override fun createMediaSource(mediaItem: MediaItem): MediaSource {
|
||||||
|
if (mediaItem.playbackProperties?.uri.toString().contains("file://")) {
|
||||||
|
return progressiveMediaSource.createMediaSource(mediaItem)
|
||||||
|
}
|
||||||
|
|
||||||
val type: String? = runBlocking {
|
val type: String? = runBlocking {
|
||||||
httpGet(mediaItem.playbackProperties!!.uri.toString())
|
httpGet(mediaItem.playbackProperties!!.uri.toString())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import org.jellyfin.apiclient.interaction.ApiClient;
|
||||||
import org.jellyfin.apiclient.interaction.Response;
|
import org.jellyfin.apiclient.interaction.Response;
|
||||||
import org.jellyfin.apiclient.model.dto.UserItemDataDto;
|
import org.jellyfin.apiclient.model.dto.UserItemDataDto;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
|
@ -82,6 +83,15 @@ public class MusicUtil {
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getFileUri(Song song) {
|
||||||
|
File root = new File(App.getInstance().getCacheDir(), "music");
|
||||||
|
|
||||||
|
String path = "/" + song.artistName + "/" + song.albumName + "/";
|
||||||
|
String name = song.discNumber + "." + song.trackNumber + " - " + song.title + "." + song.container;
|
||||||
|
|
||||||
|
return root + path + name;
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static Intent createShareSongFileIntent(@NonNull final Song song, Context context) {
|
public static Intent createShareSongFileIntent(@NonNull final Song song, Context context) {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -170,11 +170,14 @@ public class QueryUtil {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(ItemsResult result) {
|
public void onResponse(ItemsResult result) {
|
||||||
List<Song> songs = new ArrayList<>();
|
List<Song> songs = new ArrayList<>();
|
||||||
|
List<String> ids = new ArrayList<>();
|
||||||
for (BaseItemDto itemDto : result.getItems()) {
|
for (BaseItemDto itemDto : result.getItems()) {
|
||||||
songs.add(new Song(itemDto));
|
songs.add(new Song(itemDto));
|
||||||
|
ids.add(itemDto.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
callback.onLoadMedia(songs);
|
App.getDatabase().songDao().insertSongs(songs);
|
||||||
|
callback.onLoadMedia(App.getDatabase().cacheDao().getSongs(ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue