Added functionality to retrieve the song cover's art from Icarus
This commit is contained in:
@@ -21,6 +21,7 @@ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O3 -std=c++17 -DNDEBUG")
|
|||||||
set (SOURCES
|
set (SOURCES
|
||||||
APIRepository.cpp
|
APIRepository.cpp
|
||||||
BaseRepository.cpp
|
BaseRepository.cpp
|
||||||
|
CoverArtRepository.cpp
|
||||||
Demo.cpp
|
Demo.cpp
|
||||||
RepeatRepository.cpp
|
RepeatRepository.cpp
|
||||||
ShuffleRepository.cpp
|
ShuffleRepository.cpp
|
||||||
@@ -33,6 +34,8 @@ set (SOURCES
|
|||||||
set (HEADERS
|
set (HEADERS
|
||||||
APIRepository.h
|
APIRepository.h
|
||||||
BaseRepository.h
|
BaseRepository.h
|
||||||
|
model/CoverArt.h
|
||||||
|
CoverArtRepository.h
|
||||||
Demo.h
|
Demo.h
|
||||||
model/APIInfo.h
|
model/APIInfo.h
|
||||||
model/Song.h
|
model/Song.h
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
//
|
||||||
|
// Created by brahmix on 11/8/19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "CoverArtRepository.h"
|
||||||
|
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
namespace repository {
|
||||||
|
|
||||||
|
/**
|
||||||
|
template<typename C>
|
||||||
|
std::vector<C> CoverArtRepository<C>::retrieveCoverArtRecords(const model::Token& token,
|
||||||
|
const std::string& uri) {
|
||||||
|
std::vector<std::string> vals;
|
||||||
|
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
std::vector<data> CoverArtRepository<C>::retrieveCoverArtData(const model::Token& token,
|
||||||
|
const C& cover,
|
||||||
|
const std::string& uri) {
|
||||||
|
std::string fullUri(uri);
|
||||||
|
if (fullUri.at(fullUri.size() - 1) != '/') {
|
||||||
|
fullUri.append("/");
|
||||||
|
}
|
||||||
|
fullUri.append(downloadEndpoint());
|
||||||
|
fullUri.append(std::to_string(cover.id));
|
||||||
|
|
||||||
|
CURL *curl;
|
||||||
|
CURLcode res;
|
||||||
|
struct curl_slist *chunk = nullptr;
|
||||||
|
curl = curl_easy_init();
|
||||||
|
|
||||||
|
std::vector<data> vals;
|
||||||
|
|
||||||
|
if (!curl) {
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string data;
|
||||||
|
std::string authHeader("Authorization: Bearer ");
|
||||||
|
authHeader.append(token.accessToken);
|
||||||
|
constexpr auto keepAliveHeader = "Content-type: Keep-alive";
|
||||||
|
chunk = curl_slist_append(chunk, authHeader.c_str());
|
||||||
|
chunk = curl_slist_append(chunk, keepAliveHeader);
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, fullUri.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, respBodyRetriever);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
|
|
||||||
|
std::copy(data.begin(), data.end(), vals);
|
||||||
|
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
C CoverArtRepository<C>::retrieveCoverArtRecord(const model::Token& token,
|
||||||
|
const C& cover,
|
||||||
|
const std::string& uri) {
|
||||||
|
model::CoverArt cov;
|
||||||
|
|
||||||
|
return cov;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
constexpr auto CoverArtRepository<C>::downloadEndpoint() noexcept {
|
||||||
|
return "api/v1/coverart/download";
|
||||||
|
}
|
||||||
|
template<typename C>
|
||||||
|
constexpr auto CoverArtRepository<C>::recordsEndpoint() noexcept {
|
||||||
|
return "api/v1/coverart/";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
size_t CoverArtRepository<C>::respBodyRetriever(void *ptr, size_t size, size_t nmemb, char *e) {
|
||||||
|
((std::string*)e)->append((char*)ptr, size * nmemb);
|
||||||
|
|
||||||
|
return size * nmemb;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
//
|
||||||
|
// Created by brahmix on 11/8/19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MEAR_COVERARTREPOSITORY_H
|
||||||
|
#define MEAR_COVERARTREPOSITORY_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
#include "model/CoverArt.h"
|
||||||
|
#include "model/Token.h"
|
||||||
|
|
||||||
|
using data = char;
|
||||||
|
|
||||||
|
namespace repository {
|
||||||
|
template<typename C>
|
||||||
|
class CoverArtRepository {
|
||||||
|
public:
|
||||||
|
std::vector<C> retrieveCoverArtRecords(const model::Token&, const std::string&);
|
||||||
|
std::vector<data> retrieveCoverArtData(const model::Token&, const C&, const std::string&);
|
||||||
|
|
||||||
|
C retrieveCoverArtRecord(const model::Token&, const C&, const std::string&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
constexpr auto downloadEndpoint() noexcept;
|
||||||
|
constexpr auto recordsEndpoint() noexcept;
|
||||||
|
|
||||||
|
static size_t respBodyRetriever(void*, size_t, size_t, char*);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
std::vector<C> CoverArtRepository<C>::retrieveCoverArtRecords(const model::Token& token,
|
||||||
|
const std::string& uri) {
|
||||||
|
std::vector<std::string> vals;
|
||||||
|
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
std::vector<data> CoverArtRepository<C>::retrieveCoverArtData(const model::Token& token,
|
||||||
|
const C& cover,
|
||||||
|
const std::string& uri) {
|
||||||
|
std::string fullUri(uri);
|
||||||
|
if (fullUri.at(fullUri.size() - 1) != '/') {
|
||||||
|
fullUri.append("/");
|
||||||
|
}
|
||||||
|
fullUri.append(downloadEndpoint());
|
||||||
|
fullUri.append(std::to_string(cover.id));
|
||||||
|
|
||||||
|
CURL *curl;
|
||||||
|
CURLcode res;
|
||||||
|
struct curl_slist *chunk = nullptr;
|
||||||
|
curl = curl_easy_init();
|
||||||
|
|
||||||
|
if (!curl) {
|
||||||
|
return std::vector<data>();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string data;
|
||||||
|
std::string authHeader("Authorization: Bearer ");
|
||||||
|
authHeader.append(token.accessToken);
|
||||||
|
constexpr auto keepAliveHeader = "Content-type: Keep-alive";
|
||||||
|
chunk = curl_slist_append(chunk, authHeader.c_str());
|
||||||
|
chunk = curl_slist_append(chunk, keepAliveHeader);
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, fullUri.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, respBodyRetriever);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
|
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
|
std::stringstream buff(data);
|
||||||
|
std::vector<char> vals(data.begin(), data.end());
|
||||||
|
//vals.reserve(data.size());
|
||||||
|
//vals.assign(data.begin(), data.end());
|
||||||
|
/**
|
||||||
|
vals.assign(std::istream_iterator<unsigned char>(buff),
|
||||||
|
std::istream_iterator<unsigned char>());
|
||||||
|
*/
|
||||||
|
//std::copy(data.begin(), data.end(), &vals);
|
||||||
|
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
C CoverArtRepository<C>::retrieveCoverArtRecord(const model::Token& token,
|
||||||
|
const C& cover,
|
||||||
|
const std::string& uri) {
|
||||||
|
model::CoverArt cov;
|
||||||
|
|
||||||
|
return cov;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
constexpr auto CoverArtRepository<C>::downloadEndpoint() noexcept {
|
||||||
|
return "api/v1/coverart/download/";
|
||||||
|
}
|
||||||
|
template<typename C>
|
||||||
|
constexpr auto CoverArtRepository<C>::recordsEndpoint() noexcept {
|
||||||
|
return "api/v1/coverart/";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
size_t CoverArtRepository<C>::respBodyRetriever(void *ptr, size_t size, size_t nmemb, char *e) {
|
||||||
|
((std::string*)e)->append((char*)ptr, size * nmemb);
|
||||||
|
|
||||||
|
return size * nmemb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //MEAR_COVERARTREPOSITORY_H
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
#include "APIRepository.h"
|
#include "APIRepository.h"
|
||||||
|
#include "CoverArtRepository.h"
|
||||||
#include "RepeatRepository.h"
|
#include "RepeatRepository.h"
|
||||||
#include "ShuffleRepository.h"
|
#include "ShuffleRepository.h"
|
||||||
#include "SongRepository.h"
|
#include "SongRepository.h"
|
||||||
@@ -51,6 +52,7 @@ jobject songToObj(JNIEnv *env, const model::Song& song)
|
|||||||
jmethodID songId = env->GetMethodID( songClass, "setId", "(I)V" );
|
jmethodID songId = env->GetMethodID( songClass, "setId", "(I)V" );
|
||||||
jmethodID songTitle = env->GetMethodID( songClass, "setTitle", "(Ljava/lang/String;)V" );
|
jmethodID songTitle = env->GetMethodID( songClass, "setTitle", "(Ljava/lang/String;)V" );
|
||||||
jmethodID songAlbum = env->GetMethodID( songClass, "setAlbum", "(Ljava/lang/String;)V" );
|
jmethodID songAlbum = env->GetMethodID( songClass, "setAlbum", "(Ljava/lang/String;)V" );
|
||||||
|
jmethodID songAlbumArtist = env->GetMethodID(songClass, "setAlbumArtist", "(Ljava/lang/String;)V");
|
||||||
jmethodID songArtist = env->GetMethodID( songClass, "setArtist", "(Ljava/lang/String;)V" );
|
jmethodID songArtist = env->GetMethodID( songClass, "setArtist", "(Ljava/lang/String;)V" );
|
||||||
jmethodID songGenre = env->GetMethodID( songClass, "setGenre", "(Ljava/lang/String;)V" );
|
jmethodID songGenre = env->GetMethodID( songClass, "setGenre", "(Ljava/lang/String;)V" );
|
||||||
jmethodID songDuration = env->GetMethodID( songClass, "setDuration", "(I)V" );
|
jmethodID songDuration = env->GetMethodID( songClass, "setDuration", "(I)V" );
|
||||||
@@ -60,6 +62,7 @@ jobject songToObj(JNIEnv *env, const model::Song& song)
|
|||||||
jint id = song.id;
|
jint id = song.id;
|
||||||
jstring title = env->NewStringUTF(song.title.c_str());
|
jstring title = env->NewStringUTF(song.title.c_str());
|
||||||
jstring album = env->NewStringUTF(song.album.c_str());
|
jstring album = env->NewStringUTF(song.album.c_str());
|
||||||
|
jstring albumArtist = env->NewStringUTF(song.albumArtist.c_str());
|
||||||
jstring artist = env->NewStringUTF(song.artist.c_str());
|
jstring artist = env->NewStringUTF(song.artist.c_str());
|
||||||
jstring genre = env->NewStringUTF(song.genre.c_str());
|
jstring genre = env->NewStringUTF(song.genre.c_str());
|
||||||
jint duration = song.duration;
|
jint duration = song.duration;
|
||||||
@@ -69,6 +72,7 @@ jobject songToObj(JNIEnv *env, const model::Song& song)
|
|||||||
env->CallVoidMethod( songObj, songId, id );
|
env->CallVoidMethod( songObj, songId, id );
|
||||||
env->CallVoidMethod(songObj, songTitle, title);
|
env->CallVoidMethod(songObj, songTitle, title);
|
||||||
env->CallVoidMethod(songObj, songAlbum, album);
|
env->CallVoidMethod(songObj, songAlbum, album);
|
||||||
|
env->CallVoidMethod(songObj, songAlbumArtist, albumArtist);
|
||||||
env->CallVoidMethod(songObj, songArtist, artist);
|
env->CallVoidMethod(songObj, songArtist, artist);
|
||||||
env->CallVoidMethod(songObj, songGenre, genre);
|
env->CallVoidMethod(songObj, songGenre, genre);
|
||||||
env->CallVoidMethod(songObj, songDuration, duration);
|
env->CallVoidMethod(songObj, songDuration, duration);
|
||||||
@@ -113,6 +117,9 @@ model::Token fetchToken(const model::User& user, const std::string& apiUri)
|
|||||||
model::Token retrieveSavedToken(const std::string& path)
|
model::Token retrieveSavedToken(const std::string& path)
|
||||||
{
|
{
|
||||||
repository::local::TokenRepository tokenRepo;
|
repository::local::TokenRepository tokenRepo;
|
||||||
|
if (!tokenRepo.databaseExist(path)) {
|
||||||
|
tokenRepo.initializedDatabase(path);
|
||||||
|
}
|
||||||
auto token = tokenRepo.retrieveToken(path);
|
auto token = tokenRepo.retrieveToken(path);
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
@@ -122,6 +129,9 @@ model::Token retrieveSavedToken(const std::string& path)
|
|||||||
model::User retrieveCredentials(const std::string& dataPath)
|
model::User retrieveCredentials(const std::string& dataPath)
|
||||||
{
|
{
|
||||||
repository::local::UserRepository userRepo;
|
repository::local::UserRepository userRepo;
|
||||||
|
if (!userRepo.databaseExist(dataPath)) {
|
||||||
|
userRepo.initializedDatabase(dataPath);
|
||||||
|
}
|
||||||
auto user = userRepo.retrieveUserCredentials(dataPath);
|
auto user = userRepo.retrieveUserCredentials(dataPath);
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
@@ -131,6 +141,9 @@ model::User retrieveCredentials(const std::string& dataPath)
|
|||||||
int retrieveRepeatMode(const std::string& path)
|
int retrieveRepeatMode(const std::string& path)
|
||||||
{
|
{
|
||||||
repository::local::RepeatRepository repeatRepo;
|
repository::local::RepeatRepository repeatRepo;
|
||||||
|
if (!repeatRepo.databaseExist(path)) {
|
||||||
|
repeatRepo.initializedDatabase(path);
|
||||||
|
}
|
||||||
if (!repeatRepo.doesTableExist(path)) {
|
if (!repeatRepo.doesTableExist(path)) {
|
||||||
repeatRepo.createRepeatTable(path);
|
repeatRepo.createRepeatTable(path);
|
||||||
}
|
}
|
||||||
@@ -143,6 +156,9 @@ int retrieveRepeatMode(const std::string& path)
|
|||||||
int retrieveShuffleMode(const std::string& path)
|
int retrieveShuffleMode(const std::string& path)
|
||||||
{
|
{
|
||||||
repository::local::ShuffleRepository shuffleRepo;
|
repository::local::ShuffleRepository shuffleRepo;
|
||||||
|
if (!shuffleRepo.databaseExist(path)) {
|
||||||
|
shuffleRepo.initializedDatabase(path);
|
||||||
|
}
|
||||||
if (!shuffleRepo.doesTableExist(path)) {
|
if (!shuffleRepo.doesTableExist(path)) {
|
||||||
shuffleRepo.createShuffleTable(path);
|
shuffleRepo.createShuffleTable(path);
|
||||||
}
|
}
|
||||||
@@ -236,12 +252,18 @@ void saveToken(const model::Token& token, const std::string& path)
|
|||||||
void updateRepeatMode(const std::string& path)
|
void updateRepeatMode(const std::string& path)
|
||||||
{
|
{
|
||||||
repository::local::RepeatRepository repeatRepo;
|
repository::local::RepeatRepository repeatRepo;
|
||||||
|
if (!repeatRepo.databaseExist(path)) {
|
||||||
|
repeatRepo.initializedDatabase(path);
|
||||||
|
}
|
||||||
repeatRepo.updateRepeat(path);
|
repeatRepo.updateRepeat(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateShuffleMode(const std::string& path)
|
void updateShuffleMode(const std::string& path)
|
||||||
{
|
{
|
||||||
repository::local::ShuffleRepository shuffleRepo;
|
repository::local::ShuffleRepository shuffleRepo;
|
||||||
|
if (!shuffleRepo.databaseExist(path)) {
|
||||||
|
shuffleRepo.initializedDatabase(path);
|
||||||
|
}
|
||||||
shuffleRepo.updateShuffle(path);
|
shuffleRepo.updateShuffle(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,6 +440,47 @@ Java_com_example_mear_repositories_UserRepository_logUser(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jbyteArray
|
||||||
|
JNICALL
|
||||||
|
Java_com_example_mear_repositories_CoverArtRepository_retrieveCoverArtImage(
|
||||||
|
JNIEnv *env,
|
||||||
|
jobject thisObj,
|
||||||
|
jobject tokenObj,
|
||||||
|
jobject coverArt,
|
||||||
|
jstring apiUri
|
||||||
|
) {
|
||||||
|
jclass coverArtClass = env->GetObjectClass(coverArt);
|
||||||
|
auto idField = env->GetFieldID(coverArtClass, "id", "I");
|
||||||
|
auto titleField = env->GetFieldID(coverArtClass, "title", "Ljava/lang/String;");
|
||||||
|
auto id = env->GetIntField(coverArt, idField);
|
||||||
|
auto title = (jstring)env->GetObjectField(coverArt, titleField);
|
||||||
|
|
||||||
|
jclass tokenClass = env->GetObjectClass(tokenObj);
|
||||||
|
auto accessTokenId = env->GetFieldID(tokenClass, "accessToken", "Ljava/lang/String;");
|
||||||
|
auto accessTokenVal = (jstring) env->GetObjectField(tokenObj, accessTokenId);
|
||||||
|
|
||||||
|
model::Token token;
|
||||||
|
token.accessToken = env->GetStringUTFChars(accessTokenVal, nullptr);
|
||||||
|
|
||||||
|
model::CoverArt cover(id, env->GetStringUTFChars(title, nullptr));
|
||||||
|
repository::CoverArtRepository<model::CoverArt> coverArtRepo;
|
||||||
|
auto data = coverArtRepo.retrieveCoverArtData(token, cover, env->GetStringUTFChars(apiUri, nullptr));
|
||||||
|
|
||||||
|
jbyteArray image = env->NewByteArray(data.size());
|
||||||
|
//for (auto& b: data) {
|
||||||
|
env->SetByteArrayRegion(image, 0, data.size(), (jbyte*) data.data());
|
||||||
|
//}
|
||||||
|
//constexpr auto testImagePath = "/data/data/com.example.mear/image.png";
|
||||||
|
//std::ofstream out(testImagePath, std::ios::out | std::ios::binary);
|
||||||
|
//out.write(reinterpret_cast<char*>(data.data()), data.size());
|
||||||
|
//out.close();
|
||||||
|
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jint
|
JNIEXPORT jint
|
||||||
JNICALL
|
JNICALL
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
|
||||||
#include "model/APIInfo.h"
|
#include "model/APIInfo.h"
|
||||||
|
#include "model/CoverArt.h"
|
||||||
#include "model/Song.h"
|
#include "model/Song.h"
|
||||||
#include "model/Token.h"
|
#include "model/Token.h"
|
||||||
#include "model/User.h"
|
#include "model/User.h"
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ namespace repository {
|
|||||||
if (fullUri.at(fullUri.size()-1) != '/') {
|
if (fullUri.at(fullUri.size()-1) != '/') {
|
||||||
fullUri.append("/");
|
fullUri.append("/");
|
||||||
}
|
}
|
||||||
fullUri.append("api/v1/song");
|
//fullUri.append("api/v1/song");
|
||||||
|
fullUri.append(songRecordEndpoint());
|
||||||
std::vector<model::Song> songs;
|
std::vector<model::Song> songs;
|
||||||
|
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
@@ -27,29 +28,31 @@ namespace repository {
|
|||||||
return songs;
|
return songs;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr auto EXPECTED_CHAR_AMOUNT = 100000;
|
std::string resp;
|
||||||
auto resp = std::make_unique<char[]>(EXPECTED_CHAR_AMOUNT);
|
|
||||||
|
|
||||||
std::string authInfo("Authorization: Bearer ");
|
std::string authInfo("Authorization: Bearer ");
|
||||||
authInfo.append(token.accessToken);
|
authInfo.append(token.accessToken);
|
||||||
|
constexpr auto contentType = "Content-type: Keep-alive";
|
||||||
chunk = curl_slist_append(chunk, authInfo.c_str());
|
chunk = curl_slist_append(chunk, authInfo.c_str());
|
||||||
|
chunk = curl_slist_append(chunk, contentType);
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, fullUri.c_str());
|
curl_easy_setopt(curl, CURLOPT_URL, fullUri.c_str());
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, respBodyRetriever);
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, respBodyRetriever);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, resp.get());
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
|
|
||||||
res = curl_easy_perform(curl);
|
res = curl_easy_perform(curl);
|
||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
if (res == CURLE_OK) {
|
if (res == CURLE_OK) {
|
||||||
auto songsJson = nlohmann::json::parse(resp.get());
|
auto songsJson = nlohmann::json::parse(resp.c_str());
|
||||||
for (auto& songJson: songsJson) {
|
for (auto& songJson: songsJson) {
|
||||||
model::Song song(songJson["id"].get<int>(), songJson["title"].get<std::string>(),
|
model::Song song(songJson["id"].get<int>(), songJson["title"].get<std::string>(),
|
||||||
songJson["artist"].get<std::string>(), songJson["album"].get<std::string>(),
|
songJson["artist"].get<std::string>(), songJson["album"].get<std::string>(),
|
||||||
songJson["genre"].get<std::string>(), songJson["duration"].get<int>(),
|
songJson["genre"].get<std::string>(), songJson["duration"].get<int>(),
|
||||||
songJson["year"].get<int>());
|
songJson["year"].get<int>());
|
||||||
|
song.albumArtist = songJson["album_artist"].get<std::string>();
|
||||||
song.coverArtId = songJson["coverart_id"].get<int>();
|
song.coverArtId = songJson["coverart_id"].get<int>();
|
||||||
|
|
||||||
songs.push_back(song);
|
songs.push_back(song);
|
||||||
@@ -63,13 +66,13 @@ namespace repository {
|
|||||||
model::Song SongRepository::retrieveSong(const model::Token& token, const model::Song& sng,
|
model::Song SongRepository::retrieveSong(const model::Token& token, const model::Song& sng,
|
||||||
const std::string& baseUri) {
|
const std::string& baseUri) {
|
||||||
std::string uri(baseUri);
|
std::string uri(baseUri);
|
||||||
uri.append("/api/v1/song/");
|
uri.append(songRecordEndpoint());
|
||||||
uri.append(std::to_string(sng.id));
|
uri.append(std::to_string(sng.id));
|
||||||
model::Song song;
|
model::Song song;
|
||||||
|
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
CURLcode res;
|
CURLcode res;
|
||||||
struct curl_slist *chunk = NULL;
|
struct curl_slist *chunk = nullptr;
|
||||||
curl = curl_easy_init();
|
curl = curl_easy_init();
|
||||||
|
|
||||||
if (!curl) {
|
if (!curl) {
|
||||||
@@ -80,7 +83,9 @@ namespace repository {
|
|||||||
|
|
||||||
std::string authInfo("Authorization: Bearer ");
|
std::string authInfo("Authorization: Bearer ");
|
||||||
authInfo.append(token.accessToken);
|
authInfo.append(token.accessToken);
|
||||||
|
constexpr auto contentType = "Content-type: Keep-alive";
|
||||||
chunk = curl_slist_append(chunk, authInfo.c_str());
|
chunk = curl_slist_append(chunk, authInfo.c_str());
|
||||||
|
chunk = curl_slist_append(chunk, contentType);
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, uri.c_str());
|
curl_easy_setopt(curl, CURLOPT_URL, uri.c_str());
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
||||||
@@ -96,6 +101,7 @@ namespace repository {
|
|||||||
song.id = s["id"].get<int>();
|
song.id = s["id"].get<int>();
|
||||||
song.title = s["title"].get<std::string>();
|
song.title = s["title"].get<std::string>();
|
||||||
song.album = s["album"].get<std::string>();
|
song.album = s["album"].get<std::string>();
|
||||||
|
song.albumArtist = s["album_artist"].get<std::string>();
|
||||||
song.artist = s["artist"].get<std::string>();
|
song.artist = s["artist"].get<std::string>();
|
||||||
song.genre = s["genre"].get<std::string>();
|
song.genre = s["genre"].get<std::string>();
|
||||||
song.duration = s["duration"].get<int>();
|
song.duration = s["duration"].get<int>();
|
||||||
@@ -111,9 +117,14 @@ namespace repository {
|
|||||||
|
|
||||||
size_t SongRepository::respBodyRetriever(void* ptr, size_t size, size_t nmemb, char *e)
|
size_t SongRepository::respBodyRetriever(void* ptr, size_t size, size_t nmemb, char *e)
|
||||||
{
|
{
|
||||||
std::memcpy(e, ptr, nmemb);
|
((std::string*)e)->append((char*)ptr, size * nmemb);
|
||||||
e[nmemb] = '\0';
|
return size * nmemb;
|
||||||
|
|
||||||
return nmemb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
constexpr auto SongRepository::songRecordEndpoint() noexcept {
|
||||||
|
return "api/v1/song";
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,13 @@ namespace repository {
|
|||||||
model::Song retrieveSong(const model::Token&, const model::Song&, const std::string&);
|
model::Song retrieveSong(const model::Token&, const model::Song&, const std::string&);
|
||||||
private:
|
private:
|
||||||
static size_t respBodyRetriever(void*, size_t, size_t, char*);
|
static size_t respBodyRetriever(void*, size_t, size_t, char*);
|
||||||
|
|
||||||
|
constexpr auto songRecordEndpoint() noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr auto SongRepository::songRecordEndpoint() noexcept {
|
||||||
|
return "api/v1/song/";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+24
-45
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "Tok.h"
|
#include "Tok.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@
|
|||||||
namespace manager {
|
namespace manager {
|
||||||
model::Token Tok::fetchTokenTrans(const model::User &user, const std::string& uri) {
|
model::Token Tok::fetchTokenTrans(const model::User &user, const std::string& uri) {
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
|
struct curl_slist *chunk = nullptr;
|
||||||
CURLcode res;
|
CURLcode res;
|
||||||
|
|
||||||
curl = curl_easy_init();
|
curl = curl_easy_init();
|
||||||
@@ -21,71 +23,49 @@ namespace manager {
|
|||||||
return model::Token("none");
|
return model::Token("none");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto resp = std::make_unique<char[]>(10000);
|
std::string resp;
|
||||||
|
|
||||||
const auto loginUri = fetchLoginUri(uri);
|
const auto loginUri = fetchLoginUri(uri);
|
||||||
const auto obj = userJsonString(user);
|
const auto obj = userJsonString(user);
|
||||||
|
|
||||||
|
constexpr auto contentType = "Content-type: Keep-alive";
|
||||||
|
chunk = curl_slist_append(chunk , contentType);
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, loginUri.c_str());
|
curl_easy_setopt(curl, CURLOPT_URL, loginUri.c_str());
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, obj.c_str());
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, obj.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, respBodyRetriever);
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, respBodyRetriever);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, resp.get());
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
|
|
||||||
res = curl_easy_perform(curl);
|
res = curl_easy_perform(curl);
|
||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
if (res == CURLE_OK) {
|
if (res == CURLE_OK) {
|
||||||
auto s = nlohmann::json::parse(resp.get());
|
auto s = nlohmann::json::parse(resp);
|
||||||
|
const auto tokenStr = std::move(s["token"].get<std::string>());
|
||||||
|
|
||||||
return model::Token(s["token"].get<std::string>());
|
return model::Token(std::move(tokenStr));
|
||||||
}
|
}
|
||||||
|
|
||||||
return model::Token("failure");
|
return model::Token("failure");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string Tok::fetchToken(const model::User &user, const std::string& uri) {
|
constexpr auto Tok::loginEndpoint() noexcept
|
||||||
CURL *curl;
|
|
||||||
CURLcode res;
|
|
||||||
|
|
||||||
curl = curl_easy_init();
|
|
||||||
|
|
||||||
if (!curl) {
|
|
||||||
return "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
auto resp = std::make_unique<char[]>(10000);
|
|
||||||
|
|
||||||
const auto loginUri = fetchLoginUri(uri);
|
|
||||||
const auto obj = userJsonString(user);
|
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, loginUri.c_str());
|
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, obj.c_str());
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, respBodyRetriever);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, resp.get());
|
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
|
||||||
|
|
||||||
res = curl_easy_perform(curl);
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
|
|
||||||
if (res == CURLE_OK) {
|
|
||||||
auto s = nlohmann::json::parse(resp.get());
|
|
||||||
return s["token"].get<std::string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return "failure";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string Tok::fetchLoginUri(const std::string& baseUri)
|
|
||||||
{
|
{
|
||||||
std::string uri(baseUri);
|
return "api/v1/login";
|
||||||
uri.append("/api/v1/login");
|
}
|
||||||
|
|
||||||
|
std::string Tok::fetchLoginUri(const std::string& uriBase) noexcept
|
||||||
|
{
|
||||||
|
std::string uri(uriBase);
|
||||||
|
if (uri.at(uri.size() - 1) != '/') {
|
||||||
|
uri.append("/");
|
||||||
|
}
|
||||||
|
uri.append(loginEndpoint());
|
||||||
|
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Tok::userJsonString(const model::User& user)
|
std::string Tok::userJsonString(const model::User& user)
|
||||||
{
|
{
|
||||||
nlohmann::json usr;
|
nlohmann::json usr;
|
||||||
@@ -98,9 +78,8 @@ namespace manager {
|
|||||||
|
|
||||||
size_t Tok::respBodyRetriever(void* ptr, size_t size, size_t nmemb, char *e)
|
size_t Tok::respBodyRetriever(void* ptr, size_t size, size_t nmemb, char *e)
|
||||||
{
|
{
|
||||||
std::memcpy(e, ptr, nmemb);
|
((std::string*)e)->append((char*)ptr, size * nmemb);
|
||||||
e[nmemb] = '\0';
|
|
||||||
|
|
||||||
return nmemb;
|
return size * nmemb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,9 @@ namespace manager {
|
|||||||
class Tok {
|
class Tok {
|
||||||
public:
|
public:
|
||||||
model::Token fetchTokenTrans(const model::User&, const std::string&);
|
model::Token fetchTokenTrans(const model::User&, const std::string&);
|
||||||
|
|
||||||
std::string fetchToken(const model::User&, const std::string&);
|
|
||||||
private:
|
private:
|
||||||
std::string fetchLoginUri(const std::string&);
|
std::string fetchLoginUri(const std::string&) noexcept;
|
||||||
|
constexpr auto loginEndpoint() noexcept;
|
||||||
std::string userJsonString(const model::User&);
|
std::string userJsonString(const model::User&);
|
||||||
|
|
||||||
static size_t respBodyRetriever(void*, size_t, size_t, char*);
|
static size_t respBodyRetriever(void*, size_t, size_t, char*);
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ namespace repository { namespace local {
|
|||||||
SQLite::Statement query(db, queryString);
|
SQLite::Statement query(db, queryString);
|
||||||
|
|
||||||
auto result = query.executeStep();
|
auto result = query.executeStep();
|
||||||
model::Token token(query.getColumn(1).getString());
|
//const std::string t(query.getColumn(1).getString());
|
||||||
|
token.accessToken = std::move(query.getColumn(1).getString());
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// Created by brahmix on 11/8/19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MEAR_COVERART_H
|
||||||
|
#define MEAR_COVERART_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace model {
|
||||||
|
class CoverArt {
|
||||||
|
public:
|
||||||
|
CoverArt() = default;
|
||||||
|
CoverArt(const int id, const std::string& title) :
|
||||||
|
id(id), title(title) { }
|
||||||
|
|
||||||
|
int id;
|
||||||
|
std::string title;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //MEAR_COVERART_H
|
||||||
@@ -30,6 +30,7 @@ public:
|
|||||||
int id;
|
int id;
|
||||||
std::string title;
|
std::string title;
|
||||||
std::string artist;
|
std::string artist;
|
||||||
|
std::string albumArtist;
|
||||||
std::string album;
|
std::string album;
|
||||||
std::string genre;
|
std::string genre;
|
||||||
int duration;
|
int duration;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace model {
|
|||||||
Token() = default;
|
Token() = default;
|
||||||
Token(const std::string& accessToken) : accessToken(accessToken) { }
|
Token(const std::string& accessToken) : accessToken(accessToken) { }
|
||||||
Token(const std::string&& accessToken) :
|
Token(const std::string&& accessToken) :
|
||||||
accessToken(std::move(accessToken)) { }
|
accessToken(accessToken) { }
|
||||||
|
|
||||||
std::string accessToken;
|
std::string accessToken;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ class IcarusSongActivity : BaseServiceActivity() {
|
|||||||
//setSupportActionBar(toolbar)
|
//setSupportActionBar(toolbar)
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
|
||||||
val colr = R.color.track_seek
|
|
||||||
window.statusBarColor = resources.getColor(R.color.track_seek)
|
window.statusBarColor = resources.getColor(R.color.track_seek)
|
||||||
doBindService()
|
doBindService()
|
||||||
initializeAdapter()
|
initializeAdapter()
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package com.example.mear.activities
|
package com.example.mear.activities
|
||||||
|
|
||||||
|
import kotlinx.android.synthetic.main.activity_login.*
|
||||||
|
import kotlinx.android.synthetic.main.content_login.*
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.design.widget.Snackbar
|
import android.support.design.widget.Snackbar
|
||||||
import com.example.mear.R
|
|
||||||
import com.example.mear.models.*
|
|
||||||
|
|
||||||
import kotlinx.android.synthetic.main.activity_login.*
|
|
||||||
import kotlinx.android.synthetic.main.content_login.*
|
|
||||||
import org.jetbrains.anko.toast
|
import org.jetbrains.anko.toast
|
||||||
|
|
||||||
|
import com.example.mear.models.*
|
||||||
|
import com.example.mear.R
|
||||||
import com.example.mear.repositories.*
|
import com.example.mear.repositories.*
|
||||||
|
|
||||||
class LoginActivity : BaseServiceActivity() {
|
class LoginActivity : BaseServiceActivity() {
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ import org.jetbrains.anko.imageBitmap
|
|||||||
import com.example.mear.listeners.TrackElaspingChange
|
import com.example.mear.listeners.TrackElaspingChange
|
||||||
import com.example.mear.models.Song
|
import com.example.mear.models.Song
|
||||||
import com.example.mear.R
|
import com.example.mear.R
|
||||||
import com.example.mear.repositories.PlayCountRepository
|
import com.example.mear.repositories.*
|
||||||
import com.example.mear.repositories.RepeatRepository
|
|
||||||
import com.example.mear.repositories.RepeatRepository.RepeatTypes
|
import com.example.mear.repositories.RepeatRepository.RepeatTypes
|
||||||
import com.example.mear.repositories.ShuffleRepository
|
|
||||||
import com.example.mear.repositories.ShuffleRepository.ShuffleTypes
|
import com.example.mear.repositories.ShuffleRepository.ShuffleTypes
|
||||||
|
import com.example.mear.util.ConvertByteArray
|
||||||
|
import org.jetbrains.anko.image
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : BaseServiceActivity() {
|
class MainActivity : BaseServiceActivity() {
|
||||||
@@ -44,6 +44,7 @@ class MainActivity : BaseServiceActivity() {
|
|||||||
private var updateLibraryHandler: Handler? = Handler()
|
private var updateLibraryHandler: Handler? = Handler()
|
||||||
private var playCountUpdated: Boolean? = false
|
private var playCountUpdated: Boolean? = false
|
||||||
private var serviceBinded: Boolean? = false
|
private var serviceBinded: Boolean? = false
|
||||||
|
private var metadataInitialized: Boolean = false
|
||||||
private var repeatOn: Boolean? = false
|
private var repeatOn: Boolean? = false
|
||||||
private var shuffleOn: Boolean? = false
|
private var shuffleOn: Boolean? = false
|
||||||
|
|
||||||
@@ -262,12 +263,25 @@ class MainActivity : BaseServiceActivity() {
|
|||||||
(currSong.duration % 60)
|
(currSong.duration % 60)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val coverArtRepo = CoverArtRepository()
|
||||||
|
val apiRepo = APIRepository()
|
||||||
|
val tokenRepo = TokenRepository()
|
||||||
|
val path = appDirectory()
|
||||||
|
val apiUri = apiRepo.retrieveRecord(path)
|
||||||
|
val myToken = tokenRepo.retrieveToken(path)
|
||||||
|
val coverArt = CoverArtRepository.CoverArt(currSong.coverArtId, currSong.title)
|
||||||
|
val imgData = coverArtRepo.fetchCoverArtImage(myToken, coverArt, apiUri.uri)
|
||||||
|
val ImageConvByte = ConvertByteArray(imgData)
|
||||||
|
val convertedImage = ImageConvByte.convertToBmp(imgData)
|
||||||
|
|
||||||
|
|
||||||
resetControls()
|
resetControls()
|
||||||
|
|
||||||
TrackTitle.text = currSong.title
|
TrackTitle.text = currSong.title
|
||||||
ArtistTitle.text = currSong.artist
|
ArtistTitle.text = currSong.artist
|
||||||
AlbumTitle.text = currSong.album
|
AlbumTitle.text = currSong.album
|
||||||
TrackDuration.text = dur
|
TrackDuration.text = dur
|
||||||
|
TrackCover.imageBitmap = convertedImage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ex: Exception) {
|
catch (ex: Exception) {
|
||||||
@@ -298,6 +312,32 @@ class MainActivity : BaseServiceActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun songMetadataLoaded(): Boolean {
|
||||||
|
if (TrackTitle.text.isEmpty()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (ArtistTitle.text.isEmpty()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (AlbumTitle.text.isEmpty()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (TrackCover.image == null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val currSong = musicService!!.getCurrentSong()
|
||||||
|
|
||||||
|
if (!TrackTitle.text.equals(currSong.title)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ((ArtistTitle.text != currSong.artist)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Might need this down the road for playing songs off an external
|
// TODO: Might need this down the road for playing songs off an external
|
||||||
// storage
|
// storage
|
||||||
private fun permissionPrompt() {
|
private fun permissionPrompt() {
|
||||||
@@ -348,7 +388,9 @@ class MainActivity : BaseServiceActivity() {
|
|||||||
private var musicTrackTimeUpdateTask = object: Runnable {
|
private var musicTrackTimeUpdateTask = object: Runnable {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
try {
|
try {
|
||||||
|
if (!songMetadataLoaded()) {
|
||||||
configureTrackDisplay()
|
configureTrackDisplay()
|
||||||
|
}
|
||||||
val currentPosition = musicService!!.currentPositionOfTrack() / 1000
|
val currentPosition = musicService!!.currentPositionOfTrack() / 1000
|
||||||
val dur = String.format( "%02d:%02d", TimeUnit.SECONDS.toMinutes(currentPosition.toLong()),
|
val dur = String.format( "%02d:%02d", TimeUnit.SECONDS.toMinutes(currentPosition.toLong()),
|
||||||
(currentPosition % 60) )
|
(currentPosition % 60) )
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class SongAdapter(val mOnClickListener: (Song) -> Unit,
|
|||||||
this.songItem = songItems
|
this.songItem = songItems
|
||||||
|
|
||||||
v.trackTitle.setText(songItems.title)
|
v.trackTitle.setText(songItems.title)
|
||||||
v.trackArtist.setText(songItems.artist)
|
v.trackArtist.setText(songItems.albumArtist)
|
||||||
|
|
||||||
v.setOnClickListener { clickList(songItem!!)}
|
v.setOnClickListener { clickList(songItem!!)}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.example.mear.models
|
package com.example.mear.models
|
||||||
|
|
||||||
class Song (var id: Int = 3, var title: String = "", var album: String = "", var artist: String = "",
|
class Song (var id: Int = 3, var title: String = "", var album: String = "",
|
||||||
|
var albumArtist: 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)
|
var coverArtId: Int = 0)
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.example.mear.repositories
|
||||||
|
|
||||||
|
import com.example.mear.models.Token
|
||||||
|
|
||||||
|
class CoverArtRepository : BaseRepository() {
|
||||||
|
|
||||||
|
private external fun retrieveCoverArtImage(token: Token, coverArt: CoverArt, apiUri: String): ByteArray
|
||||||
|
|
||||||
|
|
||||||
|
fun fetchCoverArtImage(token: Token, coverArt: CoverArt, apiUri: String): ByteArray {
|
||||||
|
val img = retrieveCoverArtImage(token, coverArt, apiUri)
|
||||||
|
|
||||||
|
return img
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Move this to it's own file later on
|
||||||
|
class CoverArt (var id: Int = 0, var title: String = "")
|
||||||
|
}
|
||||||
@@ -7,7 +7,12 @@ class ConvertByteArray(private val byteArray: ByteArray?) {
|
|||||||
|
|
||||||
fun convertToBmp(): Bitmap {
|
fun convertToBmp(): Bitmap {
|
||||||
val songImage = BitmapFactory
|
val songImage = BitmapFactory
|
||||||
.decodeByteArray(byteArray, 0, byteArray!!.size)
|
.decodeByteArray(byteArray!!, 0, byteArray!!.size)
|
||||||
|
|
||||||
|
return songImage
|
||||||
|
}
|
||||||
|
fun convertToBmp(rawData: ByteArray): Bitmap {
|
||||||
|
val songImage = BitmapFactory.decodeByteArray(rawData, 0, rawData.size)
|
||||||
|
|
||||||
return songImage
|
return songImage
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user