Implemented shuffle functionality. Not able to reproduce the bug with repeating the song.

This commit is contained in:
kdeng00
2019-11-05 22:02:43 -05:00
parent 2ba9dfd57a
commit 76a6a763c6
11 changed files with 239 additions and 231 deletions
+46 -10
View File
@@ -25,6 +25,7 @@
#include "APIRepository.h"
#include "RepeatRepository.h"
#include "ShuffleRepository.h"
#include "SongRepository.h"
#include "Tok.h"
#include "TokenRepository.h"
@@ -92,15 +93,6 @@ model::APIInfo retrieveAPIInfo(const std::string& path)
}
model::Song retrieveSong(const std::string& token, const std::string& baseUri, const int songId)
{
repository::SongRepository songRepo;
model::Song song(songId, "Smooth", "Amaze", "The Herb", "Blazing",
420, 420);
return songRepo.retrieveSong(token, song, baseUri);
}
model::Song retrieveSong(const model::Token& token, const model::Song& song,
const std::string& baseUri)
{
@@ -148,6 +140,18 @@ int retrieveRepeatMode(const std::string& path)
return static_cast<int>(repeatMode);
}
int retrieveShuffleMode(const std::string& path)
{
repository::local::ShuffleRepository shuffleRepo;
if (!shuffleRepo.doesTableExist(path)) {
shuffleRepo.createShuffleTable(path);
}
auto shuffleMode = shuffleRepo.retrieveShuffleMode(path);
return static_cast<int>(shuffleMode);
}
bool doesDatabaseExist(const std::string& dataPath)
{
@@ -185,7 +189,7 @@ void saveAPIInfo(const model::APIInfo& apiInfo, const std::string& path)
if (!apiRepo.databaseExist(path)) {
apiRepo.initializedDatabase(path);
}
if (!apiRepo.doesAPIInfoTableExist(path)) {
if (!apiRepo.doesTableExist(path)) {
apiRepo.createAPiInfoTable(path);
}
if (!apiRepo.isTableEmpty(path)) {
@@ -235,6 +239,12 @@ void updateRepeatMode(const std::string& path)
repeatRepo.updateRepeat(path);
}
void updateShuffleMode(const std::string& path)
{
repository::local::ShuffleRepository shuffleRepo;
shuffleRepo.updateShuffle(path);
}
extern "C"
JNIEXPORT jobjectArray
@@ -422,6 +432,20 @@ Java_com_example_mear_repositories_RepeatRepository_retrieveRepeatMode(
return repeatMode;
}
extern "C"
JNIEXPORT jint
JNICALL
Java_com_example_mear_repositories_ShuffleRepository_retrieveShuffleMode(
JNIEnv *env,
jobject thisObj,
jstring pathStr
) {
const auto dataPath = jstringToString(env, pathStr);
auto shuffleMode = retrieveShuffleMode(dataPath);
return shuffleMode;
}
extern "C"
JNIEXPORT jboolean
@@ -555,4 +579,16 @@ Java_com_example_mear_repositories_RepeatRepository_updateRepeatMode(
) {
const auto dataPath = jstringToString(env, pathStr);
updateRepeatMode(dataPath);
}
extern "C"
JNIEXPORT void
JNICALL
Java_com_example_mear_repositories_ShuffleRepository_updateShuffle(
JNIEnv *env,
jobject thisObj,
jstring pathStr
) {
const auto dataPath = jstringToString(env, pathStr);
updateShuffleMode(dataPath);
}
+2 -1
View File
@@ -23,7 +23,6 @@ std::string jstringToString(JNIEnv*, jstring&);
model::APIInfo retrieveAPIInfo(const std::string&);
model::Song retrieveSong(const std::string&, const std::string&, const int);
model::Song retrieveSong(const model::Token&, const model::Song&, const std::string&);
model::Token fetchToken(const model::User&, const std::string&);
@@ -32,6 +31,7 @@ model::Token retrieveSavedToken(const std::string&);
model::User retrieveCredentials(const std::string&);
int retrieveRepeatMode(const std::string&);
int retrieveShuffleMode(const std::string&);
bool doesDatabaseExist(const std::string&);
bool apiInformationExist(const std::string&);
@@ -42,6 +42,7 @@ void saveAPIInfo(const model::APIInfo&, const std::string&);
void saveCredentials(const model::User&, const std::string&);
void saveToken(const model::Token&, const std::string&);
void updateRepeatMode(const std::string&);
void updateShuffleMode(const std::string&);
+93
View File
@@ -3,3 +3,96 @@
//
#include "ShuffleRepository.h"
namespace repository { namespace local {
ShuffleRepository::ShuffleRepository() {
m_tableName = shuffleTable();
}
ShuffleTypes ShuffleRepository::retrieveShuffleMode(const std::string& path) {
try {
auto db = getDbConn(path, ConnType::ReadOnly);
std::string queryString("SELECT * FROM ");
queryString.append(m_tableName);
queryString.append(" LIMIT 1");
SQLite::Statement query(db, queryString);
const auto result = query.executeStep();
auto shuffleType = query.getColumn(1).getInt();
auto val = static_cast<ShuffleTypes>(shuffleType);
return val;
} catch (std::exception &ex) {
auto msg = ex.what();
}
return ShuffleTypes::ShuffleOff;
}
void ShuffleRepository::createShuffleTable(const std::string& path) {
try {
auto db = getDbConn(path, ConnType::ReadWrite);
std::string queryString("CREATE TABLE ");
queryString.append(m_tableName);
queryString.append(" (Id INTEGER PRIMARY KEY, ShuffleMode INT)");
db.exec(queryString);
queryString = "INSERT INTO ";
queryString.append(m_tableName);
queryString.append(" (ShuffleMode) VALUES(?)");
SQLite::Statement query(db, queryString);
query.bind(1, static_cast<int>(ShuffleTypes::ShuffleOff));
query.exec();
} catch (std::exception& ex) {
auto msg = ex.what();
}
}
void ShuffleRepository::updateShuffle(const std::string& path) {
try {
auto db = getDbConn(path, ConnType::ReadWrite);
if (!doesTableExist(path)) {
createShuffleTable(path);
}
if (isTableEmpty(path)) {
constexpr auto queryString = "INSERT INTO ? (ShuffleMode) VALUES(?)";
SQLite::Statement query(db, queryString);
query.bind(1, m_tableName);
query.bind(2, static_cast<int>(ShuffleTypes::ShuffleOff));
query.exec();
} else {
std::string queryString("UPDATE ");
queryString.append(m_tableName);
queryString.append(" SET ShuffleMode = ?");
auto shuffleMode = retrieveShuffleMode(path);
SQLite::Statement query(db, queryString);
switch (shuffleMode) {
case ShuffleTypes::ShuffleOff:
query.bind(1, static_cast<int>(ShuffleTypes::ShuffleOn));
break;
case ShuffleTypes ::ShuffleOn:
query.bind(1, static_cast<int>(ShuffleTypes::ShuffleOff));
break;
default:
break;
}
query.exec();
}
} catch (std::exception& ex) {
auto msg = ex.what();
}
}
std::string ShuffleRepository::shuffleTable() noexcept { return "Shuffle"; }
}}
+16 -2
View File
@@ -5,10 +5,24 @@
#ifndef MEAR_SHUFFLEREPOSITORY_H
#define MEAR_SHUFFLEREPOSITORY_H
#include <string>
class ShuffleRepository {
#include "BaseRepository.h"
#include "ShuffleTypes.h"
};
namespace repository { namespace local {
class ShuffleRepository : public BaseRepository {
public:
ShuffleRepository();
ShuffleTypes retrieveShuffleMode(const std::string&);
void createShuffleTable(const std::string&);
void updateShuffle(const std::string&);
private:
std::string shuffleTable() noexcept;
};
}}
#endif //MEAR_SHUFFLEREPOSITORY_H
+2 -2
View File
@@ -6,8 +6,8 @@
#define MEAR_SHUFFLETYPES_H
enum class ShuffleTypes {
ShuffleQueue = 0,
ShuffleOff
ShuffleOn = 0,
ShuffleOff = 1
};
#endif //MEAR_SHUFFLETYPES_H
@@ -1,19 +1,13 @@
package com.example.mear.activities
import android.os.Build
import android.os.Bundle
import android.support.annotation.RequiresApi
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.app.AppCompatActivity
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.activities.BaseServiceActivity
import com.example.mear.adapters.RecyclerAdapter
import com.example.mear.adapters.SongAdapter
import com.example.mear.models.TrackItems
import com.example.mear.models.APIInfo
import com.example.mear.models.Song
import com.example.mear.models.Token
@@ -26,16 +26,14 @@ import android.widget.PopupMenu
import android.widget.Toast
import org.jetbrains.anko.imageBitmap
import com.example.mear.constants.ControlTypes
import com.example.mear.listeners.TrackElaspingChange
import com.example.mear.models.PlayControls
import com.example.mear.models.PlayCount
import com.example.mear.models.Song
import com.example.mear.R
import com.example.mear.repositories.PlayCountRepository
import com.example.mear.repositories.RepeatRepository
import com.example.mear.repositories.RepeatRepository.RepeatTypes
import com.example.mear.repositories.ShuffleRepository
import com.example.mear.repositories.ShuffleRepository.ShuffleTypes
class MainActivity : BaseServiceActivity() {
@@ -149,14 +147,15 @@ class MainActivity : BaseServiceActivity() {
doBindService()
}
private fun initializeShuffle() {
val shuffleMode = ShuffleRepository(this).getShuffleMode()
val shuffleRepo = ShuffleRepository(null)
val shuffleMode = shuffleRepo.shuffleMode(appDirectory())
when (shuffleMode) {
ControlTypes.SHUFFLE_ON -> {
ShuffleTracks.setText(R.string.shuffle_on)
}
ControlTypes.SHUFFLE_OFF -> {
ShuffleTypes.ShuffleOff -> {
ShuffleTracks.setText(R.string.shuffle_off)
}
ShuffleTypes.ShuffleOn -> {
ShuffleTracks.setText(R.string.shuffle_on)
}
}
}
private fun initializeRepeat() {
@@ -173,48 +172,23 @@ class MainActivity : BaseServiceActivity() {
}
private fun toggleShuffle() {
val shuffleText = ShuffleTracks.text.toString()
val on = getString(R.string.shuffle_on)
val off = getString(R.string.shuffle_off)
when (shuffleText) {
on -> {
val shuffleRepo = ShuffleRepository(null)
shuffleRepo.alterShuffleMode(appDirectory())
val shuffleMode = shuffleRepo.shuffleMode(appDirectory())
when (shuffleMode) {
ShuffleTypes.ShuffleOff -> {
shuffleOn = false
ShuffleTracks.setText(R.string.shuffle_off)
ShuffleTracks.text = getString(R.string.shuffle_off)
}
off -> {
ShuffleTypes.ShuffleOn -> {
shuffleOn = true
ShuffleTracks.setText(R.string.shuffle_on)
}
else -> {
shuffleOn = false
ShuffleTracks.setText(R.string.shuffle_off)
ShuffleTracks.text = getString(R.string.shuffle_on)
}
}
val playC = PlayControls(shuffleOn!!, null)
ShuffleRepository(this).updateShuffleMode(playC)
}
private fun toggleRepeat() {
/**
val repeatText = RepeatTrack.text.toString()
val on = resources.getString(R.string.repeat_on)
val off = resources.getString(R.string.repeat_off)
when (repeatText) {
on -> {
repeatOn = false
RepeatTrack.text = off
}
off -> {
repeatOn = true
RepeatTrack.text = on
}
else -> {
repeatOn = false
RepeatTrack.text = off
}
}
val playC = PlayControls(null, repeatOn)
RepeatRepository(this).updateRepeatMode(playC)
*/
val repeatRepo = RepeatRepository(null)
val appPath = appDirectory()
@@ -275,6 +249,8 @@ class MainActivity : BaseServiceActivity() {
PreviousTrack.isEnabled = true
playCountUpdated = false
}
override fun configureTrackDisplay() {
try {
runOnUiThread {
@@ -372,6 +348,7 @@ class MainActivity : BaseServiceActivity() {
private var musicTrackTimeUpdateTask = object: Runnable {
override fun run() {
try {
configureTrackDisplay()
val currentPosition = musicService!!.currentPositionOfTrack() / 1000
val dur = String.format( "%02d:%02d", TimeUnit.SECONDS.toMinutes(currentPosition.toLong()),
(currentPosition % 60) )
@@ -4,26 +4,19 @@ import java.lang.Exception
import kotlin.random.Random
import android.app.Service
import android.content.Context
import android.content.Intent
import android.media.MediaPlayer
import android.net.Uri
import android.os.Binder
import android.os.Environment
import android.os.IBinder
import android.widget.Toast
import com.example.mear.constants.ControlTypes
import com.example.mear.constants.Interval
import com.example.mear.management.MusicFiles
import com.example.mear.management.TrackManager
import com.example.mear.models.PlayControls
import com.example.mear.models.APIInfo
import com.example.mear.models.Song
import com.example.mear.models.Token
import com.example.mear.models.Track
import com.example.mear.repositories.*
import com.example.mear.repositories.RepeatRepository.RepeatTypes
import com.example.mear.repositories.ShuffleRepository.ShuffleTypes
class MusicService(var appPath: String = ""): Service() {
@@ -131,34 +124,30 @@ class MusicService(var appPath: String = ""): Service() {
val token = tokenRepo.retrieveToken(appPath)
val apiInfo = apiRepo.retrieveRecord(appPath)
if (parseRepeatMode(repeatMode) || duration > seconds) {
/**
trackPlayer!!.setDataSource(this,
APIRepository.retrieveSongStreamUri(apiInfo, currentSong),
APIRepository.retrieveSongStreamHeader(token))
*/
//trackPlayer!!.prepare()
trackPlayer!!.pause()
trackPlayer!!.seekTo(0)
trackPlayer!!.start()
}
else {
if (currentSongIndex == 0) {
currentSongIndex = songQueue.size - 1
}
else {
currentSongIndex = currentSongIndex!! - 1
if (retrieveShuffleMode()!! && !parseRepeatMode(repeatMode)) {
currentSongIndex = Random.nextInt(0, songQueue.size - 1)
} else if (!parseRepeatMode(repeatMode)) {
if (currentSongIndex == 0) {
currentSongIndex = songQueue.size - 1
} else {
currentSongIndex = currentSongIndex!! - 1
}
}
currentSong = songQueue[currentSongIndex!!]
val uri = APIRepository.retrieveSongStreamUri(apiInfo, currentSong)
val hddr = APIRepository.retrieveSongStreamHeader(token)
trackPlayer!!.reset()
trackPlayer!!.setDataSource(this,
uri, hddr)
/**
APIRepository.retrieveSongStreamUri(apiInfo, currentSong),
APIRepository.retrieveSongStreamHeader(token))
*/
trackPlayer!!.prepare()
trackPlayer!!.start()
}
@@ -179,19 +168,17 @@ class MusicService(var appPath: String = ""): Service() {
val repeatMode = repeatRepo.repeatMode(appPath)
val apiInfo = apiRepo.retrieveRecord(appPath)
/**
if (parseRepeatMode(repeatMode)) {
//trackPlayer!!.pause()
trackPlayer!!.seekTo(0)
//trackPlayer!!.start()
return
}
else*/ if ((currentSongIndex!! + 1) == songQueue.size) {
currentSongIndex = 0
}
else {
currentSongIndex = currentSongIndex!! + 1
if (retrieveShuffleMode()!! && !parseRepeatMode(repeatMode)) {
currentSongIndex = Random.nextInt(0, songQueue.size - 1)
} else if (!parseRepeatMode(repeatMode)) {
if ((currentSongIndex!! + 1) == songQueue.size) {
currentSongIndex = 0
}
else {
currentSongIndex = currentSongIndex!! + 1
}
}
currentSong = songQueue[currentSongIndex!!]
trackPlayer!!.setDataSource(this,
@@ -205,13 +192,6 @@ class MusicService(var appPath: String = ""): Service() {
}
}
/**
fun configureControl(controls: PlayControls) {
shuffleOn = controls.shuffleOn
repeatOn = controls.repeatOn
}
*/
fun getCurrentSong(): Song { return currentSong }
@@ -241,7 +221,12 @@ class MusicService(var appPath: String = ""): Service() {
val songs = trackRepo.fetchSongs(token, apiInfo.uri)
songQueue = songs.toMutableList()
currentSongIndex = Random.nextInt(0, songs.size - 1)
if (retrieveShuffleMode()!!) {
currentSongIndex = Random.nextInt(0, songs.size - 1)
} else {
currentSongIndex = 0
}
currentSong = songQueue[currentSongIndex!!]
trackPlayer!!.setDataSource(this,
APIRepository.retrieveSongStreamUri(apiInfo, currentSong),
@@ -256,55 +241,18 @@ class MusicService(var appPath: String = ""): Service() {
}
}
/**
private fun initializeShuffleMode() {
try {
val shuffleMode = ShuffleRepository(this).getShuffleMode()
when (shuffleMode) {
ControlTypes.SHUFFLE_ON -> {
shuffleOn = true
}
ControlTypes.SHUFFLE_OFF -> {
shuffleOn = false
}
}
}
catch (ex: Exception) {
val exMsg = ex.message
}
}
private fun initializeRepeatMode() {
try {
val repeatMode = RepeatRepository(this).getRepeatMode()
when (repeatMode) {
ControlTypes.REPEAT_ON -> {
repeatOn = true
}
ControlTypes.REPEAT_OFF -> {
repeatOn = false
}
}
}
catch (ex: Exception) {
val exMsg = ex.message
}
}
*/
private fun retrieveShuffleMode(): Boolean? {
val shuffleMode = ShuffleRepository(this).getShuffleMode()
val shuffleRepo = ShuffleRepository(null)
val shuffleMode = shuffleRepo.shuffleMode(appPath)
var shuffleOn = false
when (shuffleMode) {
ControlTypes.SHUFFLE_ON -> {
return true
}
ControlTypes.SHUFFLE_OFF -> {
return false
}
else -> {
return false
}
ShuffleTypes.ShuffleOn -> shuffleOn = true
ShuffleTypes.ShuffleOff -> shuffleOn = false
}
return shuffleOn
}
private fun parseRepeatMode(repeatMode: RepeatTypes): Boolean {
@@ -316,21 +264,4 @@ class MusicService(var appPath: String = ""): Service() {
return repeatOn!!
}
/**
private fun retrieveRepeatMode(): Boolean? {
val repeatMode = RepeatRepository(this).getRepeatMode()
when (repeatMode) {
ControlTypes.REPEAT_ON -> {
return true
}
ControlTypes.REPEAT_OFF -> {
return false
}
else -> {
return false
}
}
}
*/
}
@@ -11,6 +11,7 @@ open class BaseRepository {
private external fun doesDatabaseExist(path: String): Boolean
fun databaseExist(path: String): Boolean {
return doesDatabaseExist(path)
}
@@ -2,12 +2,7 @@ package com.example.mear.repositories
import android.content.Context
import org.jetbrains.anko.db.*
import com.example.mear.constants.ControlTypes
import com.example.mear.constants.CPPLib
import com.example.mear.database
import com.example.mear.models.PlayControls
class RepeatRepository(var context: Context?) {
@@ -23,19 +18,6 @@ class RepeatRepository(var context: Context?) {
private external fun updateRepeatMode(path: String)
/**
fun getRepeatMode(): String = context!!.database.use {
select("Repeat").limit(1)
.parseSingle(object: MapRowParser<String>{
override fun parseRow(columns: Map<String, Any?>): String {
return columns.getValue("Mode").toString()
}
})
}
*/
fun repeatMode(path: String): RepeatTypes {
val repeatType = RepeatTypes.valueOf(retrieveRepeatMode(path))
@@ -48,17 +30,6 @@ class RepeatRepository(var context: Context?) {
}
/**
fun updateRepeatMode(playControls: PlayControls?) = context!!.database.use {
var repeatMode = ControlTypes.REPEAT_OFF
if (playControls!!.repeatOn!!) {
repeatMode = ControlTypes.REPEAT_ON
}
update("Repeat",
"Mode" to repeatMode).exec()
}
*/
enum class RepeatTypes(val value: Int) {
RepeatSong(0),
RepeatOff(1);
@@ -2,51 +2,41 @@ package com.example.mear.repositories
import android.content.Context
import org.jetbrains.anko.db.*
import com.example.mear.constants.ControlTypes
import com.example.mear.database
import com.example.mear.models.PlayControls
class ShuffleRepository {
private var context: Context? = null
import com.example.mear.constants.CPPLib
constructor(context: Context) {
this.context = context
}
class ShuffleRepository(var context: Context?) {
companion object {
init {
System.loadLibrary("native-lib")
System.loadLibrary(CPPLib.NATIVE_LIB)
}
}
fun getShuffleMode(): String = context!!.database.use {
select("Shuffle").limit(1)
.parseSingle(object : MapRowParser<String> {
override fun parseRow(columns: Map<String, Any?>): String {
return columns.getValue("Mode").toString()
}
})
private external fun retrieveShuffleMode(path: String): Int
private external fun updateShuffle(path: String)
fun shuffleMode(path: String): ShuffleTypes {
val shuffleType = ShuffleTypes.valueOf(retrieveShuffleMode(path))
return shuffleType!!
}
fun insertShuffleMode(shuffleControls: PlayControls) = context!!.database.use {
var shuffleMode: String? = ControlTypes.SHUFFLE_OFF
if (shuffleControls.shuffleOn!!) {
shuffleMode = ControlTypes.SHUFFLE_ON
}
insert("Shuffle",
"Mode" to shuffleMode)
fun alterShuffleMode(path: String) {
updateShuffle(path)
}
fun updateShuffleMode(shuffleControls: PlayControls) = context!!.database.use {
var shuffleMode: String? = ControlTypes.SHUFFLE_OFF
if (shuffleControls.shuffleOn!!) {
shuffleMode = ControlTypes.SHUFFLE_ON
enum class ShuffleTypes(val value: Int) {
ShuffleOn(0),
ShuffleOff(1);
companion object {
fun valueOf(value: Int) = values().find { it.value == value }
}
update("Shuffle",
"Mode" to shuffleMode).exec()
}
}