diff --git a/app/src/main/cpp/Demo.cpp b/app/src/main/cpp/Demo.cpp index e5e6db0..06ef48f 100644 --- a/app/src/main/cpp/Demo.cpp +++ b/app/src/main/cpp/Demo.cpp @@ -54,6 +54,7 @@ jobject songToObj(JNIEnv *env, const model::Song& song) jmethodID songGenre = env->GetMethodID( songClass, "setGenre", "(Ljava/lang/String;)V" ); jmethodID songDuration = env->GetMethodID( songClass, "setDuration", "(I)V" ); jmethodID songYear = env->GetMethodID( songClass, "setYear", "(I)V" ); + jmethodID songCoverArtId = env->GetMethodID(songClass, "setCoverArtId", "(I)V"); jint id = song.id; jstring title = env->NewStringUTF(song.title.c_str()); @@ -62,6 +63,7 @@ jobject songToObj(JNIEnv *env, const model::Song& song) jstring genre = env->NewStringUTF(song.genre.c_str()); jint duration = song.duration; jint year = song.year; + jint coverArtId = song.coverArtId; env->CallVoidMethod( songObj, songId, id ); env->CallVoidMethod(songObj, songTitle, title); @@ -70,6 +72,7 @@ jobject songToObj(JNIEnv *env, const model::Song& song) env->CallVoidMethod(songObj, songGenre, genre); env->CallVoidMethod(songObj, songDuration, duration); env->CallVoidMethod(songObj, songYear, year); + env->CallVoidMethod(songObj, songCoverArtId, coverArtId); return songObj; } diff --git a/app/src/main/cpp/RepeatRepository.cpp b/app/src/main/cpp/RepeatRepository.cpp index 8724713..d46d539 100644 --- a/app/src/main/cpp/RepeatRepository.cpp +++ b/app/src/main/cpp/RepeatRepository.cpp @@ -22,7 +22,7 @@ namespace repository { namespace local { const auto result = query.executeStep(); auto repeatType = query.getColumn(1).getInt(); - auto val = static_cast(result); + auto val = static_cast(repeatType); return val; } catch (std::exception& ex) { auto msg = ex.what(); @@ -40,6 +40,12 @@ namespace repository { namespace local { queryString.append(" (Id INTEGER PRIMARY KEY, RepeatMode INT)"); db.exec(queryString); + + queryString = "INSERT INTO " + m_tableName + " (RepeatMode) VALUES(?)"; + SQLite::Statement query(db, queryString); + query.bind(1, static_cast(RepeatTypes::RepeatOff)); + query.exec(); + } catch (std::exception& ex) { auto msg = ex.what(); } diff --git a/app/src/main/java/com/example/mear/activities/MainActivity.kt b/app/src/main/java/com/example/mear/activities/MainActivity.kt index 87ecac0..12146e6 100644 --- a/app/src/main/java/com/example/mear/activities/MainActivity.kt +++ b/app/src/main/java/com/example/mear/activities/MainActivity.kt @@ -1,20 +1,5 @@ package com.example.mear.activities -import android.Manifest -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.graphics.Color -import android.os.Bundle -import android.os.Handler -import android.R as RDroid -import android.support.v4.app.ActivityCompat -import android.support.v4.content.ContextCompat -import android.view.MenuItem -import android.view.View -import android.widget.PopupMenu -import android.widget.Toast - import java.lang.Exception import java.lang.Runnable import java.util.concurrent.TimeUnit @@ -26,21 +11,31 @@ import kotlinx.android.synthetic.main.fragment_track_details.* import kotlinx.android.synthetic.main.fragment_track_elapsing.* import kotlinx.android.synthetic.main.fragment_track_flow.* +import android.Manifest +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import android.graphics.Color +import android.os.Bundle +import android.os.Handler +import android.support.v4.app.ActivityCompat +import android.support.v4.content.ContextCompat +import android.view.MenuItem +import android.view.View +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.R 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.TrackRepository -import com.example.mear.util.ConvertByteArray -import com.example.mear.util.ExtractCover -import kotlinx.coroutines.delay class MainActivity : BaseServiceActivity() { @@ -111,6 +106,7 @@ class MainActivity : BaseServiceActivity() { initializeRepeat() initializeServices() initializeClickListeners() + configurePlayControlsDisplay() } catch (ex: Exception) { val exMsg = ex.message @@ -167,10 +163,10 @@ class MainActivity : BaseServiceActivity() { val repeatRepo = RepeatRepository(null) val repeatMode = repeatRepo.repeatMode(appDirectory()) when (repeatMode) { - RepeatRepository.RepeatTypes.RepeatSong -> { + RepeatTypes.RepeatSong -> { RepeatTrack.text = resources.getText(R.string.repeat_on) } - RepeatRepository.RepeatTypes.RepeatOff -> { + RepeatTypes.RepeatOff -> { RepeatTrack.text = resources.getText(R.string.repeat_off) } } @@ -223,14 +219,13 @@ class MainActivity : BaseServiceActivity() { val appPath = appDirectory() repeatRepo.alterRepeatMode(appPath) - val repeatMode = repeatRepo.repeatMode(appPath) - when (repeatMode) { - RepeatRepository.RepeatTypes.RepeatOff -> { + when (repeatRepo.repeatMode(appPath)) { + RepeatTypes.RepeatOff -> { repeatOn = false RepeatTrack.text = resources.getText(R.string.repeat_off) } - RepeatRepository.RepeatTypes.RepeatSong -> { + RepeatTypes.RepeatSong -> { repeatOn = true RepeatTrack.text = resources.getText(R.string.repeat_on) } @@ -317,14 +312,14 @@ class MainActivity : BaseServiceActivity() { PlayTrack.background = null PlayTrack.colorFilter = null - if (!musicService!!.isPlaying()) { - PlayTrack.setImageResource(android.R.drawable.ic_media_pause) - PlayTrack.setColorFilter(Color.RED) - } - else { + if ((musicService == null || !musicService!!.isPlaying())) { PlayTrack.setImageResource(android.R.drawable.ic_media_play) PlayTrack.setColorFilter(Color.GREEN) } + else { + PlayTrack.setImageResource(android.R.drawable.ic_media_pause) + PlayTrack.setColorFilter(Color.RED) + } } // TODO: Might need this down the road for playing songs off an external diff --git a/app/src/main/java/com/example/mear/models/Song.kt b/app/src/main/java/com/example/mear/models/Song.kt index ac4b124..894b100 100644 --- a/app/src/main/java/com/example/mear/models/Song.kt +++ b/app/src/main/java/com/example/mear/models/Song.kt @@ -1,4 +1,5 @@ package com.example.mear.models class Song (var id: Int = 3, var title: String = "", var album: String = "", var artist: String = "", - var genre: String = "", var year: Int = 0, var duration: Int = 0) + var genre: String = "", var year: Int = 0, var duration: Int = 0, + var coverArtId: Int = 0) 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 000e7b6..c915dc4 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 @@ -1,5 +1,8 @@ package com.example.mear.playback.service +import java.lang.Exception +import kotlin.random.Random + import android.app.Service import android.content.Context import android.content.Intent @@ -10,9 +13,6 @@ import android.os.Environment import android.os.IBinder import android.widget.Toast -import java.lang.Exception -import kotlin.random.Random - import com.example.mear.constants.ControlTypes import com.example.mear.constants.Interval import com.example.mear.management.MusicFiles @@ -23,8 +23,7 @@ import com.example.mear.models.Song import com.example.mear.models.Token import com.example.mear.models.Track import com.example.mear.repositories.* -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch +import com.example.mear.repositories.RepeatRepository.RepeatTypes class MusicService(var appPath: String = ""): Service() { @@ -34,14 +33,14 @@ class MusicService(var appPath: String = ""): Service() { } private var trackPlayer: MediaPlayer? = null - private var trackMgr: TrackManager? = null + //private var trackMgr: TrackManager? = null private var songQueue = mutableListOf() - private var currentTrack = Track() + //private var currentTrack = Track() private var currentSong = Song() private var currentSongIndex: Int? = null - private var addingMusic: Boolean? = false + //private var addingMusic: Boolean? = false private var shuffleOn: Boolean? = null - private var repeatOn: Boolean? = null + //private var repeatOn: Boolean? = null private val mBinder = LocalBinder() private val seconds = Interval.SONG_REWIND @@ -87,6 +86,7 @@ class MusicService(var appPath: String = ""): Service() { fun icarusPlaySong(token: Token, song: Song, apiInfo: APIInfo) { val uri = APIRepository.retrieveSongStreamUri(apiInfo, song) val hddr = APIRepository.retrieveSongStreamHeader(token) + currentSong = song try { trackPlayer!!.reset() @@ -99,10 +99,8 @@ class MusicService(var appPath: String = ""): Service() { } } + fun goToPosition(progress: Int) { trackPlayer!!.seekTo(progress) } - fun goToPosition(progress: Int) { - trackPlayer!!.seekTo(progress) - } fun playSongTrack() { try { trackPlayer!!.start() @@ -111,6 +109,7 @@ class MusicService(var appPath: String = ""): Service() { val exMsg = ex.message } } + fun pauseSongTrack() { try { trackPlayer!!.pause() @@ -119,30 +118,47 @@ class MusicService(var appPath: String = ""): Service() { val exMsg = ex.message } } + fun playPreviousTrack() { try { val duration = trackPlayer!!.currentPosition / 1000 shuffleOn = retrieveShuffleMode() val apiRepo = APIRepository() + val repeatRepo = RepeatRepository(null) val tokenRepo = TokenRepository() + val repeatMode = repeatRepo.repeatMode(appPath) val token = tokenRepo.retrieveToken(appPath) val apiInfo = apiRepo.retrieveRecord(appPath) - currentSong = songQueue[Random.nextInt(0, songQueue.size - 1)] - - trackPlayer!!.reset() - if (duration > seconds) { + if (parseRepeatMode(repeatMode) || duration > seconds) { + /** trackPlayer!!.setDataSource(this, APIRepository.retrieveSongStreamUri(apiInfo, currentSong), APIRepository.retrieveSongStreamHeader(token)) - trackPlayer!!.prepare() + */ + //trackPlayer!!.prepare() + trackPlayer!!.pause() + trackPlayer!!.seekTo(0) trackPlayer!!.start() } else { + 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() } @@ -156,11 +172,27 @@ class MusicService(var appPath: String = ""): Service() { trackPlayer!!.reset() shuffleOn = retrieveShuffleMode() val apiRepo = APIRepository() + val repeatRepo = RepeatRepository(null) val tokenRepo = TokenRepository() val token = tokenRepo.retrieveToken(appPath) + val repeatMode = repeatRepo.repeatMode(appPath) val apiInfo = apiRepo.retrieveRecord(appPath) - currentSong = songQueue[Random.nextInt(0, songQueue.size - 1)] + + /** + if (parseRepeatMode(repeatMode)) { + //trackPlayer!!.pause() + trackPlayer!!.seekTo(0) + //trackPlayer!!.start() + return + } + else*/ if ((currentSongIndex!! + 1) == songQueue.size) { + currentSongIndex = 0 + } + else { + currentSongIndex = currentSongIndex!! + 1 + } + currentSong = songQueue[currentSongIndex!!] trackPlayer!!.setDataSource(this, APIRepository.retrieveSongStreamUri(apiInfo, currentSong), @@ -173,26 +205,22 @@ class MusicService(var appPath: String = ""): Service() { } } + /** fun configureControl(controls: PlayControls) { shuffleOn = controls.shuffleOn repeatOn = controls.repeatOn } + */ - fun getCurrentSong(): Song { - return currentSong - } + fun getCurrentSong(): Song { return currentSong } - fun currentPositionOfTrack(): Int { - return trackPlayer!!.currentPosition - } - fun durationOfTrack(): Int { - return trackPlayer!!.duration - } + fun currentPositionOfTrack(): Int { return trackPlayer!!.currentPosition } - fun isPlaying(): Boolean { - return trackPlayer!!.isPlaying - } + fun durationOfTrack(): Int { return trackPlayer!!.duration } + + + fun isPlaying(): Boolean { return trackPlayer!!.isPlaying } private fun initializeMediaPlayer() { @@ -213,7 +241,8 @@ class MusicService(var appPath: String = ""): Service() { val songs = trackRepo.fetchSongs(token, apiInfo.uri) songQueue = songs.toMutableList() - currentSong = songQueue[Random.nextInt(0, songs.size - 1)] + currentSongIndex = Random.nextInt(0, songs.size - 1) + currentSong = songQueue[currentSongIndex!!] trackPlayer!!.setDataSource(this, APIRepository.retrieveSongStreamUri(apiInfo, currentSong), APIRepository.retrieveSongStreamHeader(token)) @@ -227,6 +256,7 @@ class MusicService(var appPath: String = ""): Service() { } } + /** private fun initializeShuffleMode() { try { val shuffleMode = ShuffleRepository(this).getShuffleMode() @@ -259,6 +289,7 @@ class MusicService(var appPath: String = ""): Service() { val exMsg = ex.message } } + */ private fun retrieveShuffleMode(): Boolean? { @@ -276,6 +307,17 @@ class MusicService(var appPath: String = ""): Service() { } } + private fun parseRepeatMode(repeatMode: RepeatTypes): Boolean { + var repeatOn: Boolean? = null + when (repeatMode) { + RepeatTypes.RepeatOff -> repeatOn = false + RepeatTypes.RepeatSong -> repeatOn = true + } + + return repeatOn!! + } + + /** private fun retrieveRepeatMode(): Boolean? { val repeatMode = RepeatRepository(this).getRepeatMode() when (repeatMode) { @@ -290,4 +332,5 @@ class MusicService(var appPath: String = ""): Service() { } } } + */ } diff --git a/app/src/main/java/com/example/mear/repositories/RepeatRepository.kt b/app/src/main/java/com/example/mear/repositories/RepeatRepository.kt index a88b25e..fb1accb 100644 --- a/app/src/main/java/com/example/mear/repositories/RepeatRepository.kt +++ b/app/src/main/java/com/example/mear/repositories/RepeatRepository.kt @@ -23,6 +23,7 @@ class RepeatRepository(var context: Context?) { private external fun updateRepeatMode(path: String) + /** fun getRepeatMode(): String = context!!.database.use { select("Repeat").limit(1) .parseSingle(object: MapRowParser{ @@ -33,6 +34,8 @@ class RepeatRepository(var context: Context?) { }) } + */ + fun repeatMode(path: String): RepeatTypes { val repeatType = RepeatTypes.valueOf(retrieveRepeatMode(path)) @@ -45,6 +48,7 @@ class RepeatRepository(var context: Context?) { } + /** fun updateRepeatMode(playControls: PlayControls?) = context!!.database.use { var repeatMode = ControlTypes.REPEAT_OFF if (playControls!!.repeatOn!!) { @@ -53,6 +57,7 @@ class RepeatRepository(var context: Context?) { update("Repeat", "Mode" to repeatMode).exec() } + */ enum class RepeatTypes(val value: Int) { RepeatSong(0),