Working more on downloading a song and the ability to retrieve where to is stored at on the filesystem
This commit is contained in:
@@ -265,7 +265,7 @@ void updateShuffleMode(const std::string& path) {
|
|||||||
|
|
||||||
template<class Song = model::Song, class Token = model::Token, typename Str = std::string>
|
template<class Song = model::Song, class Token = model::Token, typename Str = std::string>
|
||||||
void downloadSong(Song& song, const Token& token, const Str& path) {
|
void downloadSong(Song& song, const Token& token, const Str& path) {
|
||||||
song.filename = song.title;
|
song.filename = "track";
|
||||||
song.path = path;
|
song.path = path;
|
||||||
repository::local::APIRepository apiRepo;
|
repository::local::APIRepository apiRepo;
|
||||||
auto apiInfo = apiRepo.retrieveAPIInfo(path);
|
auto apiInfo = apiRepo.retrieveAPIInfo(path);
|
||||||
@@ -273,16 +273,26 @@ void downloadSong(Song& song, const Token& token, const Str& path) {
|
|||||||
auto downloadedSong = songRepo.downloadSong(token, song, apiInfo);
|
auto downloadedSong = songRepo.downloadSong(token, song, apiInfo);
|
||||||
manager::DirectoryManager dirMgr;
|
manager::DirectoryManager dirMgr;
|
||||||
if (dirMgr.doesSongExist(song, path)) {
|
if (dirMgr.doesSongExist(song, path)) {
|
||||||
auto a = 0;
|
|
||||||
std::cout << "song already exists\n";
|
std::cout << "song already exists\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dirMgr.createSongDirectory(song, path);
|
dirMgr.createSongDirectory(song, path);
|
||||||
const auto fullSongPath = dirMgr.fullSongPath(song, path);
|
downloadedSong.path = dirMgr.fullSongPath(song, path);
|
||||||
std::fstream saveSong(fullSongPath, std::ios::out | std::ios::binary);
|
std::fstream saveSong(downloadedSong.path, std::ios::out | std::ios::binary);
|
||||||
saveSong.write((char*)&downloadedSong.data[0], downloadedSong.data.size());
|
saveSong.write((char*)&downloadedSong.data[0], downloadedSong.data.size());
|
||||||
saveSong.close();
|
saveSong.close();
|
||||||
|
|
||||||
|
repository::local::SongRepository localSongRepo;
|
||||||
|
if (!localSongRepo.databaseExist(path)) {
|
||||||
|
localSongRepo.initializedDatabase(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!localSongRepo.doesTableExist(path)) {
|
||||||
|
localSongRepo.createSongTable(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
localSongRepo.saveSong(downloadedSong, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -367,6 +377,43 @@ Java_com_example_mear_repositories_TrackRepository_retrieveSongs(
|
|||||||
return songs;
|
return songs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jobjectArray
|
||||||
|
JNICALL
|
||||||
|
Java_com_example_mear_repositories_TrackRepository_retrieveSongsIncludingDownloaded(
|
||||||
|
JNIEnv *env,
|
||||||
|
jobject thisOnj,
|
||||||
|
jobject token,
|
||||||
|
jstring baseUri,
|
||||||
|
jstring appPathStr
|
||||||
|
) {
|
||||||
|
jclass tokenClass = env->FindClass("com/example/mear/models/Token");
|
||||||
|
jclass songClass = env->FindClass( "com/example/mear/models/Song");
|
||||||
|
|
||||||
|
auto tokField = env->GetFieldID(tokenClass, "accessToken", "Ljava/lang/String;");
|
||||||
|
auto tokObj = env->GetObjectField(token, tokField);
|
||||||
|
std::string tokStr = env->GetStringUTFChars((jstring)tokObj, nullptr);
|
||||||
|
std::string appPath = env->GetStringUTFChars((jstring)appPathStr, nullptr);
|
||||||
|
model::Token tk(tokStr);
|
||||||
|
|
||||||
|
const std::string uri = env->GetStringUTFChars(baseUri, nullptr);
|
||||||
|
env->DeleteLocalRef(baseUri);
|
||||||
|
|
||||||
|
auto allSongs = retrieveSongs(tk, uri);
|
||||||
|
jobjectArray songs = env->NewObjectArray(allSongs.size(), songClass, nullptr);
|
||||||
|
auto i = 0;
|
||||||
|
for (auto& sng: allSongs) {
|
||||||
|
try {
|
||||||
|
auto song = songToObj<model::Song>(env, sng);
|
||||||
|
env->SetObjectArrayElement(songs, i++, song);
|
||||||
|
} catch (std::exception& ex) {
|
||||||
|
auto msg = ex.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return songs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jbyteArray
|
JNIEXPORT jbyteArray
|
||||||
|
|||||||
@@ -27,7 +27,23 @@ namespace manager {
|
|||||||
s.append("/");
|
s.append("/");
|
||||||
s.append(song.album);
|
s.append(song.album);
|
||||||
s.append("/");
|
s.append("/");
|
||||||
s.append(song.filename);
|
|
||||||
|
if (song.disc == 0) {
|
||||||
|
s.append("disc1");
|
||||||
|
} else {
|
||||||
|
s.append("disc");
|
||||||
|
s.append(std::to_string(song.disc));
|
||||||
|
}
|
||||||
|
|
||||||
|
s.append("/");
|
||||||
|
s.append("track");
|
||||||
|
if (song.track < 10) {
|
||||||
|
s.append("0");
|
||||||
|
s.append(std::to_string(song.track));
|
||||||
|
} else {
|
||||||
|
s.append(std::to_string(song.track));
|
||||||
|
}
|
||||||
|
|
||||||
s.append(".mp3");
|
s.append(".mp3");
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
@@ -45,6 +61,19 @@ namespace manager {
|
|||||||
return ss.c_str();
|
return ss.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Str = std::string>
|
||||||
|
Str albumDiscPath(const Song& song, const Str& path) {
|
||||||
|
std::string songPath = albumPath(song, path);
|
||||||
|
songPath.append("/disc");
|
||||||
|
if (song.disc == 0) {
|
||||||
|
songPath.append("1");
|
||||||
|
} else {
|
||||||
|
songPath.append(std::to_string(song.disc));
|
||||||
|
}
|
||||||
|
|
||||||
|
return songPath.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Str = std::string>
|
template<typename Str = std::string>
|
||||||
Str artistPath(const Song& song, const Str& path) {
|
Str artistPath(const Song& song, const Str& path) {
|
||||||
Str s = utility::GeneralUtility::appendForwardSlashToUri<std::string>(path);
|
Str s = utility::GeneralUtility::appendForwardSlashToUri<std::string>(path);
|
||||||
@@ -56,9 +85,7 @@ namespace manager {
|
|||||||
|
|
||||||
template<typename Str = std::string, typename B = bool>
|
template<typename Str = std::string, typename B = bool>
|
||||||
B doesSongExist(const Song& song, const Str& path) {
|
B doesSongExist(const Song& song, const Str& path) {
|
||||||
std::string s = albumPath(song, path);
|
std::string s = fullSongPath(song, path);
|
||||||
s.append("/");
|
|
||||||
s.append(song.filename);
|
|
||||||
|
|
||||||
struct stat buffer;
|
struct stat buffer;
|
||||||
return (stat (s.c_str(), &buffer) == 0);
|
return (stat (s.c_str(), &buffer) == 0);
|
||||||
@@ -85,6 +112,9 @@ namespace manager {
|
|||||||
if (!albumDirectoryExists(song, path)) {
|
if (!albumDirectoryExists(song, path)) {
|
||||||
auto status = mkdir(albumPath(song, path), 0777);
|
auto status = mkdir(albumPath(song, path), 0777);
|
||||||
}
|
}
|
||||||
|
if (!albumDiscDirectoryExists(song, path)) {
|
||||||
|
auto status = mkdir(albumDiscPath(song, path), 0777);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Str = std::string>
|
template<typename Str = std::string>
|
||||||
@@ -98,6 +128,16 @@ namespace manager {
|
|||||||
albumPath.append(song.albumArtist);
|
albumPath.append(song.albumArtist);
|
||||||
albumPath.append("/");
|
albumPath.append("/");
|
||||||
albumPath.append(song.album);
|
albumPath.append(song.album);
|
||||||
|
/**
|
||||||
|
if (song.disc == 0) {
|
||||||
|
albumPath.append("/");
|
||||||
|
albumPath.append("disc1");
|
||||||
|
} else {
|
||||||
|
albumPath.append("/");
|
||||||
|
albumPath.append("disc");
|
||||||
|
albumPath.append(std::to_string(song.disc));
|
||||||
|
}
|
||||||
|
*/
|
||||||
DIR* dir = opendir(albumPath.c_str());
|
DIR* dir = opendir(albumPath.c_str());
|
||||||
|
|
||||||
if (dir) {
|
if (dir) {
|
||||||
@@ -110,6 +150,28 @@ namespace manager {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Str = std::string, typename B = bool>
|
||||||
|
B albumDiscDirectoryExists(const Song& song, const Str& path) {
|
||||||
|
std::string albumDistPath = albumPath(song, path);
|
||||||
|
albumDistPath.append("/disc");
|
||||||
|
if (song.disc == 0) {
|
||||||
|
albumDistPath.append("1");
|
||||||
|
} else {
|
||||||
|
albumDistPath.append(std::to_string(song.disc));
|
||||||
|
}
|
||||||
|
|
||||||
|
DIR *dir = opendir(albumDistPath.c_str());
|
||||||
|
|
||||||
|
if (dir) {
|
||||||
|
closedir(dir);
|
||||||
|
return true;
|
||||||
|
} else if (ENOENT == errno) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Str = std::string, typename B = bool>
|
template<typename Str = std::string, typename B = bool>
|
||||||
B artistDirectoryExists(const Song song, const Str& path) {
|
B artistDirectoryExists(const Song song, const Str& path) {
|
||||||
auto artistPath = utility::GeneralUtility::appendForwardSlashToUri<std::string>(path);
|
auto artistPath = utility::GeneralUtility::appendForwardSlashToUri<std::string>(path);
|
||||||
|
|||||||
@@ -128,11 +128,11 @@ namespace repository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Token = model::Token, typename API = model::APIInfo>
|
template<typename Token = model::Token, typename API = model::APIInfo>
|
||||||
Song downloadSong(const Token &token, const Song song, const API& uri) {
|
Song downloadSong(const Token &token, const Song& song, const API& uri) {
|
||||||
auto fullUri = utility::GeneralUtility::appendForwardSlashToUri(uri.uri);
|
auto fullUri = utility::GeneralUtility::appendForwardSlashToUri(uri.uri);
|
||||||
fullUri.append(songDownloadEndpoint());
|
fullUri.append(songDownloadEndpoint());
|
||||||
fullUri.append(std::to_string(song.id));
|
fullUri.append(std::to_string(song.id));
|
||||||
Song downloadedSong;
|
Song downloadedSong = song;
|
||||||
|
|
||||||
CURL *curl = curl_easy_init();
|
CURL *curl = curl_easy_init();
|
||||||
struct curl_slist *chunk = nullptr;
|
struct curl_slist *chunk = nullptr;
|
||||||
@@ -151,6 +151,7 @@ namespace repository {
|
|||||||
auto res = curl_easy_perform(curl);
|
auto res = curl_easy_perform(curl);
|
||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
downloadedSong.data = std::move(std::vector<char>(data.begin(), data.end()));
|
downloadedSong.data = std::move(std::vector<char>(data.begin(), data.end()));
|
||||||
|
/**
|
||||||
downloadedSong.filename = "track";
|
downloadedSong.filename = "track";
|
||||||
if (song.track < 10) {
|
if (song.track < 10) {
|
||||||
downloadedSong.filename.append("0");
|
downloadedSong.filename.append("0");
|
||||||
@@ -159,6 +160,7 @@ namespace repository {
|
|||||||
downloadedSong.filename.append(std::to_string(song.track));
|
downloadedSong.filename.append(std::to_string(song.track));
|
||||||
}
|
}
|
||||||
downloadedSong.filename.append(".mp3");
|
downloadedSong.filename.append(".mp3");
|
||||||
|
*/
|
||||||
|
|
||||||
return downloadedSong;
|
return downloadedSong;
|
||||||
}
|
}
|
||||||
@@ -186,7 +188,33 @@ namespace repository {
|
|||||||
std::vector<Song> downloadedSongs;
|
std::vector<Song> downloadedSongs;
|
||||||
try {
|
try {
|
||||||
// TODO: left off here
|
// TODO: left off here
|
||||||
|
const auto dbPath = pathOfDatabase(appPath);
|
||||||
|
SQLite::Database db(dbPath, SQLite::OPEN_READONLY);
|
||||||
|
|
||||||
|
std::string queryString("SELECT * FROM ");
|
||||||
|
queryString.append(m_tableName);
|
||||||
|
|
||||||
|
SQLite::Statement query(db, queryString);
|
||||||
|
|
||||||
|
while (query.executeStep()) {
|
||||||
|
Song song;
|
||||||
|
song.id = query.getColumn(0).getInt();
|
||||||
|
song.title = query.getColumn(1).getString();
|
||||||
|
song.artist = query.getColumn(2).getString();
|
||||||
|
song.album = query.getColumn(3).getString();
|
||||||
|
song.albumArtist = query.getColumn(4).getString();
|
||||||
|
song.genre = query.getColumn(5).getString();
|
||||||
|
song.year = query.getColumn(6).getInt();
|
||||||
|
song.duration = query.getColumn(7).getInt();
|
||||||
|
song.track = query.getColumn(8).getInt();
|
||||||
|
song.disc = query.getColumn(9).getInt();
|
||||||
|
song.filename = query.getColumn(10).getString();
|
||||||
|
song.path = query.getColumn(11).getString();
|
||||||
|
song.coverArtId = query.getColumn(12).getInt();
|
||||||
|
song.downloaded = true;
|
||||||
|
|
||||||
|
downloadedSongs.push_back(song);
|
||||||
|
}
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
auto msg = ex.what();
|
auto msg = ex.what();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import kotlinx.android.synthetic.main.content_settings.*
|
|||||||
import com.example.mear.adapters.SettingsAdapter
|
import com.example.mear.adapters.SettingsAdapter
|
||||||
import com.example.mear.R
|
import com.example.mear.R
|
||||||
import com.example.mear.management.MusicFiles
|
import com.example.mear.management.MusicFiles
|
||||||
import com.example.mear.management.TrackManager
|
|
||||||
import com.example.mear.ui.popups.AboutPopup
|
import com.example.mear.ui.popups.AboutPopup
|
||||||
import com.example.mear.repositories.TrackRepository
|
import com.example.mear.repositories.TrackRepository
|
||||||
import kotlinx.android.synthetic.main.popup_layout.*
|
import kotlinx.android.synthetic.main.popup_layout.*
|
||||||
@@ -56,23 +55,9 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
return allSongs!!
|
return allSongs!!
|
||||||
}
|
}
|
||||||
private fun loadTracks(allSongs: MutableList<String>) {
|
|
||||||
try {
|
|
||||||
TrackRepository(this).delete()
|
|
||||||
val trackMgr = TrackManager(allSongs)
|
|
||||||
trackMgr.configureTracks(this)
|
|
||||||
}
|
|
||||||
catch (ex: Exception) {
|
|
||||||
val exMsg = ex.message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private fun updateLibrary() {
|
|
||||||
loadTracks(loadSongPaths())
|
|
||||||
}
|
|
||||||
|
|
||||||
class AboutListener(var layout: LinearLayout?, val ctx: Context): View.OnClickListener {
|
class AboutListener(var layout: LinearLayout?, val ctx: Context): View.OnClickListener {
|
||||||
override fun onClick(v: View?) {
|
override fun onClick(v: View?) {
|
||||||
val ss = 10
|
val ss = 10
|
||||||
|
|||||||
@@ -1,314 +0,0 @@
|
|||||||
package com.example.mear.management
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.media.MediaMetadataRetriever
|
|
||||||
import android.widget.Toast
|
|
||||||
|
|
||||||
import java.io.FileInputStream
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
|
|
||||||
import com.example.mear.constants.Filenames
|
|
||||||
import com.example.mear.constants.SongSearch
|
|
||||||
import com.example.mear.models.Track
|
|
||||||
import com.example.mear.repositories.PlayCountRepository
|
|
||||||
import com.example.mear.repositories.TrackRepository
|
|
||||||
import com.example.mear.util.ConvertByteArray
|
|
||||||
import org.jetbrains.anko.custom.async
|
|
||||||
import kotlin.Exception
|
|
||||||
|
|
||||||
class TrackManager(var allSongPath: MutableList<String>?) {
|
|
||||||
|
|
||||||
private var allTracks: MutableList<Track>? = null
|
|
||||||
private var ctx: Context? = null
|
|
||||||
private var songCount: Int? = null
|
|
||||||
private var songIndex: Int? = null
|
|
||||||
private var moreSongs = true
|
|
||||||
var allTracksAdded = false
|
|
||||||
|
|
||||||
fun initializeContext(context: Context) {
|
|
||||||
ctx = context
|
|
||||||
}
|
|
||||||
|
|
||||||
fun configureTracks(ctx: Context): Int {
|
|
||||||
var id = 0
|
|
||||||
try {
|
|
||||||
allTracks = mutableListOf()
|
|
||||||
for (musicPath in allSongPath!!) {
|
|
||||||
var mmr = MediaMetadataRetriever()
|
|
||||||
mmr.setDataSource(musicPath)
|
|
||||||
val trackTitle = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)
|
|
||||||
val trackArtist = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST)
|
|
||||||
val trackAlbum = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM)
|
|
||||||
var trackLength: Int?
|
|
||||||
val trackLenghStr = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
|
|
||||||
trackLength = (trackLenghStr.toInt()/1000)
|
|
||||||
|
|
||||||
if (trackTitle == null || trackArtist == null || trackAlbum == null ||
|
|
||||||
trackLenghStr == null) {
|
|
||||||
}
|
|
||||||
|
|
||||||
val track = Track(id, trackTitle, trackArtist, trackAlbum, trackLength,
|
|
||||||
ByteArray(0), musicPath)
|
|
||||||
dumpToDatabase(ctx, track)
|
|
||||||
if (mmr.embeddedPicture!=null) {
|
|
||||||
saveTrackCoverToDisk(ctx, id, mmr.embeddedPicture)
|
|
||||||
}
|
|
||||||
id++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (ex: Exception) {
|
|
||||||
val exMsg = ex.message
|
|
||||||
}
|
|
||||||
TrackRepository(ctx).createSongCount(id)
|
|
||||||
return id.dec()
|
|
||||||
}
|
|
||||||
fun initializeLibrary() {
|
|
||||||
var initTrack = initialTracks()
|
|
||||||
addToDatabase(initTrack)
|
|
||||||
}
|
|
||||||
fun addSongs() {
|
|
||||||
var initTracks = initialTracks()
|
|
||||||
addToDatabase(initTracks)
|
|
||||||
|
|
||||||
if (moreSongs) {
|
|
||||||
GlobalScope.launch {
|
|
||||||
val allSongCount = allSongPath!!.size -1
|
|
||||||
for (i in songIndex!! .. (allSongCount)) {
|
|
||||||
val songPath = allSongPath!![i]
|
|
||||||
val track = configureTrack(songPath, i)
|
|
||||||
songCount = songCount!!.inc()
|
|
||||||
addToDatabase(track)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fun addnewSongs(trackPaths: List<String>, resumeIndex: Int) {
|
|
||||||
var resumeIndex = resumeIndex
|
|
||||||
|
|
||||||
try {
|
|
||||||
//launchB
|
|
||||||
for (tPath in trackPaths) {
|
|
||||||
val track = configureTrack(tPath, resumeIndex)
|
|
||||||
addToDatabase(track)
|
|
||||||
resumeIndex = resumeIndex.inc()
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
catch (ex: Exception) {
|
|
||||||
val exMsg = ex.message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fun addTracks() {
|
|
||||||
var initTracks = initialTracks()
|
|
||||||
addToDatabase(initTracks)
|
|
||||||
|
|
||||||
if (moreSongs) {
|
|
||||||
GlobalScope.launch {
|
|
||||||
val remainingTracks = remainingTracks()
|
|
||||||
addToDatabase(remainingTracks)
|
|
||||||
allTracksAdded = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fun addTracksKx() {
|
|
||||||
var initTracks = initialTracks()
|
|
||||||
addToDatabase(initTracks)
|
|
||||||
|
|
||||||
if (moreSongs) {
|
|
||||||
GlobalScope.launch {
|
|
||||||
addRemainingTracks()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fun addRemainingTracks() = runBlocking {
|
|
||||||
val remainder = allSongPath!!.size - songCount!!
|
|
||||||
|
|
||||||
if (remainder > 10) {
|
|
||||||
val rangeAmount = remainder / 10
|
|
||||||
val rg = addRanges(rangeAmount)
|
|
||||||
|
|
||||||
val remainingT = remainingTracks(rg)
|
|
||||||
addToDatabase(remainingT)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addRanges(rangeAmount: Int): MutableList<AddMusicRange> {
|
|
||||||
var ranges = mutableListOf<AddMusicRange>()
|
|
||||||
try {
|
|
||||||
var rangeCounter = 0
|
|
||||||
val songAmount = allSongPath!!.size
|
|
||||||
while (songIndex!! < songAmount) {
|
|
||||||
val startIndex = songIndex
|
|
||||||
var endIndex = songIndex!! + rangeAmount
|
|
||||||
if ((songIndex!! + rangeAmount) > songAmount ) {
|
|
||||||
endIndex = (songAmount - songIndex!!) + songIndex!!
|
|
||||||
}
|
|
||||||
|
|
||||||
val range = AddMusicRange(startIndex!!, endIndex)
|
|
||||||
ranges.add(range)
|
|
||||||
|
|
||||||
songIndex = endIndex + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (ex: Exception) {
|
|
||||||
val exMsg = ex.message
|
|
||||||
}
|
|
||||||
|
|
||||||
return ranges
|
|
||||||
}
|
|
||||||
private fun initialTracks(): MutableList<Track> {
|
|
||||||
var tracks = mutableListOf<Track>()
|
|
||||||
|
|
||||||
try {
|
|
||||||
var initSongSearch = SongSearch.INITIAL_SEARCH_AMOUNT -1
|
|
||||||
|
|
||||||
if (allSongPath!!!!.size < SongSearch.INITIAL_SEARCH_AMOUNT) {
|
|
||||||
initSongSearch = allSongPath!!.size
|
|
||||||
moreSongs = false
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i in 0.. initSongSearch) {
|
|
||||||
var songPath = allSongPath!![i]
|
|
||||||
val track = configureTrack(songPath, i)
|
|
||||||
tracks.add(track)
|
|
||||||
}
|
|
||||||
|
|
||||||
songCount = tracks.size
|
|
||||||
songIndex = songCount!!
|
|
||||||
}
|
|
||||||
catch (ex: Exception) {
|
|
||||||
val exMsg = ex.message
|
|
||||||
}
|
|
||||||
|
|
||||||
return tracks
|
|
||||||
}
|
|
||||||
private fun remainingTracks(): MutableList<Track> {
|
|
||||||
val tracks = mutableListOf<Track>()
|
|
||||||
try {
|
|
||||||
for (i in songIndex!! .. (allSongPath!!.size - 1)) {
|
|
||||||
val songPath = allSongPath!![i]
|
|
||||||
val track = configureTrack(songPath, i)
|
|
||||||
if (track.id != Int.MAX_VALUE) {
|
|
||||||
tracks.add(track)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
songCount = songCount!!.plus(tracks.size)
|
|
||||||
}
|
|
||||||
catch (ex: Exception) {
|
|
||||||
val exMsg = ex.message
|
|
||||||
}
|
|
||||||
|
|
||||||
return tracks
|
|
||||||
}
|
|
||||||
private fun remainingTracks(rangeobjects: AddMusicRange): MutableList<Track> {
|
|
||||||
val tracks = mutableListOf<Track>()
|
|
||||||
try {
|
|
||||||
val startIndex = rangeobjects.startIndex
|
|
||||||
var endIndex = rangeobjects.endIndex
|
|
||||||
if (endIndex == allSongPath!!.size) {
|
|
||||||
endIndex--
|
|
||||||
}
|
|
||||||
|
|
||||||
for (songPathIndex in startIndex.. endIndex) {
|
|
||||||
val songPath = allSongPath!![songPathIndex]
|
|
||||||
val track = configureTrack(songPath, songPathIndex)
|
|
||||||
if (track.id != Int.MAX_VALUE) {
|
|
||||||
tracks.add(track)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
songCount = songCount!!.plus(tracks.size)
|
|
||||||
}
|
|
||||||
catch (ex: Exception) {
|
|
||||||
val exMsg = ex.message
|
|
||||||
}
|
|
||||||
|
|
||||||
return tracks
|
|
||||||
}
|
|
||||||
suspend private fun remainingTracks(obj: MutableList<AddMusicRange>): MutableList<Track> {
|
|
||||||
val tracks = mutableListOf<Track>()
|
|
||||||
var rangeRecords = mutableListOf<Boolean>()
|
|
||||||
try {
|
|
||||||
for (rgObj in obj) {
|
|
||||||
coroutineScope {
|
|
||||||
launch {
|
|
||||||
val remainingTracks = remainingTracks(rgObj)
|
|
||||||
tracks.addAll(remainingTracks)
|
|
||||||
rangeRecords.add(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
runBlocking {
|
|
||||||
while (rangeRecords.size != obj.size) {
|
|
||||||
delay(10)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (ex: java.lang.Exception) {
|
|
||||||
val exMsg = ex.message
|
|
||||||
}
|
|
||||||
|
|
||||||
return tracks
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun configureTrack(songPath: String, id: Int): Track {
|
|
||||||
try {
|
|
||||||
val metaData = MediaMetadataRetriever()
|
|
||||||
val fp = FileInputStream(songPath)
|
|
||||||
metaData.setDataSource(fp.fd)
|
|
||||||
|
|
||||||
val title = metaData.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)
|
|
||||||
val artist = metaData.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST)
|
|
||||||
val album = metaData.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM)
|
|
||||||
val duration = (metaData.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION).toInt()) / 1000
|
|
||||||
|
|
||||||
fp.close()
|
|
||||||
metaData.release()
|
|
||||||
|
|
||||||
return Track(id, title, artist, album, duration, ByteArray(0), songPath)
|
|
||||||
}
|
|
||||||
catch (ex: Exception) {
|
|
||||||
val exMsg = ex.message
|
|
||||||
}
|
|
||||||
|
|
||||||
return Track()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addToDatabase(tracks: List<Track>) {
|
|
||||||
TrackRepository(ctx!!).insertTracks(tracks)
|
|
||||||
PlayCountRepository(ctx!!).insertPlayCounts(tracks)
|
|
||||||
TrackRepository(ctx!!).createSongCount(songCount!!)
|
|
||||||
}
|
|
||||||
private fun addToDatabase(track: Track) {
|
|
||||||
try {
|
|
||||||
TrackRepository(ctx!!).insertTrack(track)
|
|
||||||
PlayCountRepository(ctx!!).insertPlayCount(track)
|
|
||||||
//TrackRepository(ctx!!).createSongCount(songCount!!)
|
|
||||||
}
|
|
||||||
catch (ex: Exception) {
|
|
||||||
val exMsg = ex.message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private fun addToDatabase(ctx: Context, tracks: List<Track>) {
|
|
||||||
TrackRepository(ctx).insertTracks(tracks)
|
|
||||||
PlayCountRepository(ctx).insertPlayCounts(tracks)
|
|
||||||
}
|
|
||||||
private fun dumpToDatabase(ctx: Context, track: Track) {
|
|
||||||
TrackRepository(ctx).insertTrack(track)
|
|
||||||
PlayCountRepository(ctx).insertPlayCount(track)
|
|
||||||
}
|
|
||||||
private fun saveTrackCoverToDisk(context: Context, id: Int, trackCover: ByteArray) {
|
|
||||||
val filename = "${Filenames.TRACK_COVERS}$id.bmp"
|
|
||||||
val fileContents = trackCover
|
|
||||||
var img = ConvertByteArray(trackCover).convertToBmp()
|
|
||||||
|
|
||||||
context.openFileOutput(filename, Context.MODE_PRIVATE).use {
|
|
||||||
it.write(fileContents)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class AddMusicRange(val startIndex: Int, val endIndex: Int) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -19,6 +19,7 @@ class TrackRepository(var context: Context? = null) {
|
|||||||
|
|
||||||
|
|
||||||
private external fun retrieveSongs(token: Token, uri: String): Array<Song>
|
private external fun retrieveSongs(token: Token, uri: String): Array<Song>
|
||||||
|
private external fun retrieveSongsIncludingDownloaded(token: Token, uri: String, path: String): Array<Song>
|
||||||
|
|
||||||
private external fun retrieveSong(token: Token, song: Song, uri: String): Song
|
private external fun retrieveSong(token: Token, song: Song, uri: String): Song
|
||||||
|
|
||||||
@@ -29,6 +30,10 @@ class TrackRepository(var context: Context? = null) {
|
|||||||
return retrieveSongs(token, uri)
|
return retrieveSongs(token, uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun fetchSongsIncludingDownloaded(token: Token, uri: String, path: String): Array<Song> {
|
||||||
|
return retrieveSongsIncludingDownloaded(token, uri, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun fetchSong(token: Token, song: Song, uri: String): Song {
|
fun fetchSong(token: Token, song: Song, uri: String): Song {
|
||||||
return retrieveSong(token, song, uri)
|
return retrieveSong(token, song, uri)
|
||||||
@@ -42,35 +47,4 @@ class TrackRepository(var context: Context? = null) {
|
|||||||
downloadSong(token, song, path)
|
downloadSong(token, song, path)
|
||||||
val s = 4
|
val s = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun insertTracks(tracks: List<Track>) = context!!.database.use {
|
|
||||||
transaction {
|
|
||||||
for (track in tracks) {
|
|
||||||
insert("Track",
|
|
||||||
"Id" to track.id, "Title" to track.title, "Album" to track.album,
|
|
||||||
"Artist" to track.artist, "Duration" to track.length,
|
|
||||||
"FilePath" to track.songPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun insertTrack(track: Track) = context!!.database.use {
|
|
||||||
insert("Track",
|
|
||||||
"Id" to track.id,
|
|
||||||
"Title" to track.title,
|
|
||||||
"Album" to track.album,
|
|
||||||
"Artist" to track.artist,
|
|
||||||
"Duration" to track.length,
|
|
||||||
"FilePath" to track.songPath)
|
|
||||||
}
|
|
||||||
fun createSongCount(songCount: Int) = context!!.database.use {
|
|
||||||
delete("TrackCount")
|
|
||||||
insert("TrackCount",
|
|
||||||
"Id" to 0,
|
|
||||||
"TotalSongs" to songCount)
|
|
||||||
}
|
|
||||||
fun delete() = context!!.database.use {
|
|
||||||
delete("Track")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user