diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index 36e7292..6b990e3 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -11,15 +11,8 @@ cmake_minimum_required(VERSION 3.10) # Gradle automatically packages shared libraries with your APK. -# set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) - - set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 17) -# set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=c++17") -# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") -# set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -g -O0 -std=c++17") -# set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O3 -std=c++17 -DNDEBUG") set (HEADERS Demo.hpp diff --git a/app/src/main/cpp/Demo.hpp b/app/src/main/cpp/Demo.hpp index 8b50611..1b4657f 100644 --- a/app/src/main/cpp/Demo.hpp +++ b/app/src/main/cpp/Demo.hpp @@ -6,6 +6,7 @@ #define MEAR_DEMO_H #include +#include #include #include #include @@ -402,8 +403,34 @@ Java_com_example_mear_repositories_TrackRepository_retrieveSongsIncludingDownloa auto allSongs = retrieveSongs(tk, uri); jobjectArray songs = env->NewObjectArray(allSongs.size(), songClass, nullptr); auto i = 0; + + repository::local::SongRepository localSongRepo(appPath); + auto localSongs = (localSongRepo.isTableEmpty(appPath)) ? + localSongRepo.retrieveAllSongs(appPath) : std::vector(); + for (auto& sng: allSongs) { try { + if (localSongs.size() > 0) { + auto result = std::any_of(localSongs.begin(), localSongs.end(), + [&](model::Song s) { + auto result = s.artist.compare(sng.artist) == 0 && + s.title.compare(sng.title) == 0 && + s.album.compare(sng.album) == 0 && + s.albumArtist.compare(sng.albumArtist) == 0; + + if (result) { + auto song = songToObj(env, s); + env->SetObjectArrayElement(songs, i++, song); + } + + return result; + }); + + if (result) { + continue; + } + } + auto song = songToObj(env, sng); env->SetObjectArrayElement(songs, i++, song); } catch (std::exception& ex) { @@ -750,7 +777,6 @@ Java_com_example_mear_repositories_TrackRepository_downloadSong( jobject songObj, jstring pathStr ) { -// TODO: left off here auto tokenClass = env->GetObjectClass(tokenObj); auto accessTokenId = env->GetFieldID(tokenClass, "accessToken", "Ljava/lang/String;"); auto accessTokenVal = (jstring) env->GetObjectField(tokenObj, accessTokenId); diff --git a/app/src/main/cpp/repository/BaseRepository.h b/app/src/main/cpp/repository/BaseRepository.h index 799d466..e395070 100644 --- a/app/src/main/cpp/repository/BaseRepository.h +++ b/app/src/main/cpp/repository/BaseRepository.h @@ -52,6 +52,7 @@ namespace repository { namespace local { queryStr.append(m_tableName); SQLite::Statement query(db, queryStr); + auto r = query.exec(); const auto result = query.hasRow(); diff --git a/app/src/main/cpp/repository/SongRepository.h b/app/src/main/cpp/repository/SongRepository.h index 7b9ffa2..02967bc 100644 --- a/app/src/main/cpp/repository/SongRepository.h +++ b/app/src/main/cpp/repository/SongRepository.h @@ -183,11 +183,21 @@ namespace repository { m_tableName = songTable(); } + template + SongRepository(const Str& val) { + m_tableName = songTable(); + if (!databaseExist(val)) { + initializedDatabase(val); + } + if (!doesTableExist(val)) { + createSongTable(val); + } + } + std::vector retrieveAllSongs(const std::string& appPath) { std::vector downloadedSongs; try { - // TODO: left off here const auto dbPath = pathOfDatabase(appPath); SQLite::Database db(dbPath, SQLite::OPEN_READONLY); diff --git a/app/src/main/java/com/example/mear/activities/IcarusSongActivity.kt b/app/src/main/java/com/example/mear/activities/IcarusSongActivity.kt index 44d0feb..e8252e2 100644 --- a/app/src/main/java/com/example/mear/activities/IcarusSongActivity.kt +++ b/app/src/main/java/com/example/mear/activities/IcarusSongActivity.kt @@ -4,7 +4,6 @@ import android.os.Bundle import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.SearchView -import kotlinx.android.synthetic.main.activity_icarus_song.* import kotlinx.android.synthetic.main.content_song_view.* import com.example.mear.adapters.SongAdapter @@ -58,7 +57,7 @@ class IcarusSongActivity : BaseServiceActivity() { val apiRepo = APIRepository() val token = tokenRepo.retrieveToken(pa) val apiInfo = apiRepo.retrieveRecord(pa) - val fetchedSongs = trackRepo.fetchSongs(token, apiInfo.uri).toCollection(ArrayList()) + val fetchedSongs = trackRepo.fetchSongsIncludingDownloaded(token, apiInfo.uri, pa).toCollection(ArrayList()) songs = fetchedSongs songs!!.sortedWith(compareBy{it.title}) diff --git a/app/src/main/java/com/example/mear/adapters/SongAdapter.kt b/app/src/main/java/com/example/mear/adapters/SongAdapter.kt index 3bc594e..8fd16d0 100644 --- a/app/src/main/java/com/example/mear/adapters/SongAdapter.kt +++ b/app/src/main/java/com/example/mear/adapters/SongAdapter.kt @@ -1,26 +1,17 @@ package com.example.mear.adapters -import android.app.Activity +import java.lang.Exception +import kotlinx.android.synthetic.main.fragment_song_view.view.* + import android.support.v7.widget.RecyclerView import android.view.View import android.view.ViewGroup import android.widget.Filter import android.widget.Filterable -import java.lang.Exception -import kotlinx.android.synthetic.main.fragment_song_view.view.* -import kotlinx.coroutines.GlobalScope - -import com.squareup.picasso.Picasso - -import com.example.mear.constants.Filenames import com.example.mear.inflate import com.example.mear.models.Song -import com.example.mear.models.TrackItems import com.example.mear.R -import com.example.mear.util.ConvertByteArray -import com.example.mear.util.ExtractCover -import org.jetbrains.anko.imageBitmap class SongAdapter(val mOnClickListener: (Song) -> Unit, diff --git a/app/src/main/java/com/example/mear/playback/service/MusicService.kt b/app/src/main/java/com/example/mear/playback/service/MusicService.kt index 1e4593a..cc6c4c2 100644 --- a/app/src/main/java/com/example/mear/playback/service/MusicService.kt +++ b/app/src/main/java/com/example/mear/playback/service/MusicService.kt @@ -21,19 +21,11 @@ import com.example.mear.repositories.ShuffleRepository.ShuffleTypes class MusicService(var appPath: String = ""): Service() { - companion object { - //fun curSongIndex(): Int = currentSongIndex - } - private var trackPlayer: MediaPlayer? = null - //private var trackMgr: TrackManager? = null private var songQueue = mutableListOf() - //private var currentTrack = Track() private var currentSong = Song() private var currentSongIndex: Int? = null - //private var addingMusic: Boolean? = false private var shuffleOn: Boolean? = null - //private var repeatOn: Boolean? = null private val mBinder = LocalBinder() private val seconds = Interval.SONG_REWIND @@ -77,6 +69,11 @@ class MusicService(var appPath: String = ""): Service() { fun icarusPlaySong(token: Token, song: Song, apiInfo: APIInfo) { + if (song.downloaded) { + offlinePlaySong(song) + return + } + val uri = APIRepository.retrieveSongStreamUri(apiInfo, song) val hddr = APIRepository.retrieveSongStreamHeader(token) currentSong = song @@ -142,11 +139,16 @@ class MusicService(var appPath: String = ""): Service() { } currentSong = songQueue[currentSongIndex!!] - val uri = APIRepository.retrieveSongStreamUri(apiInfo, currentSong) - val hddr = APIRepository.retrieveSongStreamHeader(token) trackPlayer!!.reset() - trackPlayer!!.setDataSource(this, - uri, hddr) + if (currentSong.downloaded) { + trackPlayer!!.setDataSource(currentSong.path) + } + else { + val uri = APIRepository.retrieveSongStreamUri(apiInfo, currentSong) + val hddr = APIRepository.retrieveSongStreamHeader(token) + trackPlayer!!.setDataSource(this, + uri, hddr) + } trackPlayer!!.prepare() trackPlayer!!.start() @@ -181,9 +183,14 @@ class MusicService(var appPath: String = ""): Service() { currentSong = songQueue[currentSongIndex!!] - trackPlayer!!.setDataSource(this, - APIRepository.retrieveSongStreamUri(apiInfo, currentSong), - APIRepository.retrieveSongStreamHeader(token)) + if (currentSong.downloaded) { + trackPlayer!!.setDataSource(currentSong.path) + } + else { + trackPlayer!!.setDataSource(this, + APIRepository.retrieveSongStreamUri(apiInfo, currentSong), + APIRepository.retrieveSongStreamHeader(token)) + } trackPlayer!!.prepare() trackPlayer!!.start() } @@ -228,9 +235,15 @@ class MusicService(var appPath: String = ""): Service() { } currentSong = songQueue[currentSongIndex!!] - trackPlayer!!.setDataSource(this, - APIRepository.retrieveSongStreamUri(apiInfo, currentSong), - APIRepository.retrieveSongStreamHeader(token)) + if (currentSong.downloaded) { + trackPlayer!!.setDataSource(currentSong.path) + } + else { + + trackPlayer!!.setDataSource(this, + APIRepository.retrieveSongStreamUri(apiInfo, currentSong), + APIRepository.retrieveSongStreamHeader(token)) + } trackPlayer!!.prepareAsync() trackPlayer!!.setOnCompletionListener { playNextTrack() @@ -264,4 +277,17 @@ class MusicService(var appPath: String = ""): Service() { return repeatOn!! } + + private fun offlinePlaySong(song: Song) { + try { + trackPlayer!!.reset() + trackPlayer!!.setDataSource(song.path) + trackPlayer!!.prepare() + trackPlayer!!.start() + } + catch (ex: Exception) { + var msg = ex.message + } + } } +