Commit 31012402 authored by camilo higuita's avatar camilo higuita

further work on the mir system

parent e0e31f6a
......@@ -3,8 +3,6 @@
#include "db/collectionDB.h"
//#include "db/conthread.h"
#include "settings/BabeSettings.h"
#include "pulpo/pulpo.h"
#include <QPalette>
#include <QColor>
#include <QIcon>
......@@ -35,21 +33,20 @@ Babe::Babe(QObject *parent) : QObject(parent)
/*use another thread for the db to perfom heavy dutty actions*/
// this->thread = new ConThread;
this->pulpo = new Pulpo(this);
this->db = CollectionDB::getInstance();
connect(pulpo, &Pulpo::infoReady, [&](const FMH::MODEL &track, const PULPO::RESPONSE &res)
{
qDebug()<<"GOT THE LYRICS";
// connect(pulpo, &Pulpo::infoReady, [&](const FMH::MODEL &track, const PULPO::RESPONSES &res)
// {
// qDebug()<<"GOT THE LYRICS";
if(!res[PULPO::ONTOLOGY::TRACK][PULPO::INFO::LYRICS].isEmpty())
{
auto lyrics = res[PULPO::ONTOLOGY::TRACK][PULPO::INFO::LYRICS][PULPO::CONTEXT::LYRIC].toString();
// if(!res[PULPO::ONTOLOGY::TRACK][PULPO::INFO::LYRICS].isEmpty())
// {
// auto lyrics = res[PULPO::ONTOLOGY::TRACK][PULPO::INFO::LYRICS][PULPO::CONTEXT::LYRIC].toString();
this->db->lyricsTrack(track, lyrics);
emit this->trackLyricsReady(lyrics, track[FMH::MODEL_KEY::URL]);
}
});
// this->db->lyricsTrack(track, lyrics);
// emit this->trackLyricsReady(lyrics, track[FMH::MODEL_KEY::URL]);
// }
// });
connect(settings, &BabeSettings::refreshTables, [this](int size)
......@@ -485,27 +482,27 @@ void Babe::loadCover(const QString &url)
void Babe::fetchCoverArt(FMH::MODEL &song)
{
auto pulpo = new Pulpo;
// auto pulpo = new Pulpo;
if(BAE::artworkCache(song, FMH::MODEL_KEY::ALBUM)) emit this->coverReady(song[FMH::MODEL_KEY::ARTWORK]);
if(BAE::artworkCache(song, FMH::MODEL_KEY::ARTIST)) emit this->coverReady(song[FMH::MODEL_KEY::ARTWORK]);
// if(BAE::artworkCache(song, FMH::MODEL_KEY::ALBUM)) emit this->coverReady(song[FMH::MODEL_KEY::ARTWORK]);
// if(BAE::artworkCache(song, FMH::MODEL_KEY::ARTIST)) emit this->coverReady(song[FMH::MODEL_KEY::ARTWORK]);
pulpo->registerServices({SERVICES::LastFm, SERVICES::Spotify});
pulpo->setOntology(PULPO::ONTOLOGY::ALBUM);
pulpo->setInfo(PULPO::INFO::ARTWORK);
// pulpo->registerServices({SERVICES::LastFm, SERVICES::Spotify});
// pulpo->setOntology(PULPO::ONTOLOGY::ALBUM);
// pulpo->setInfo(PULPO::INFO::ARTWORK);
connect(pulpo, &Pulpo::infoReady, [&](const FMH::MODEL &track,const PULPO::RESPONSE &res)
{
Q_UNUSED(track);
if(!res[PULPO::ONTOLOGY::ALBUM][PULPO::INFO::ARTWORK].isEmpty())
{
auto artwork = res[PULPO::ONTOLOGY::ALBUM][PULPO::INFO::ARTWORK][PULPO::CONTEXT::IMAGE].toByteArray();
BAE::saveArt(song, artwork, BAE::CachePath);
emit this->coverReady(song[FMH::MODEL_KEY::ARTWORK]);
}
});
// connect(pulpo, &Pulpo::infoReady, [&](const FMH::MODEL &track,const PULPO::RESPONSE &res)
// {
// Q_UNUSED(track);
// if(!res[PULPO::ONTOLOGY::ALBUM][PULPO::INFO::ARTWORK].isEmpty())
// {
// auto artwork = res[PULPO::ONTOLOGY::ALBUM][PULPO::INFO::ARTWORK][PULPO::CONTEXT::IMAGE].toByteArray();
// BAE::saveArt(song, artwork, BAE::CachePath);
// emit this->coverReady(song[FMH::MODEL_KEY::ARTWORK]);
// }
// });
pulpo->feed(song, PULPO::RECURSIVE::OFF);
// pulpo->feed(song, PULPO::RECURSIVE::OFF);
}
QVariantList Babe::transformData(const FMH::MODEL_LIST &dbList)
......
......@@ -84,7 +84,6 @@ public:
public slots:
private:
Pulpo *pulpo;
// ConThread *thread;
CollectionDB *db;
......
#ifndef ENUMS_H
#define ENUMS_H
#ifdef STATIC_MAUIKIT
#include "../mauikit/src/fm/fmh.h"
#else
#include <MauiKit/fmh.h>
#endif
#include <QMap>
#include <QVariant>
#include <functional>
namespace PULPO
{
enum class SERVICES : uint8_t
{
LastFm,
Spotify,
iTunes,
MusicBrainz,
Genius,
LyricWikia,
Wikipedia,
WikiLyrics,
Deezer,
ALL,
NONE
};
enum class ONTOLOGY : uint8_t
{
ARTIST,
ALBUM,
TRACK,
NONE
};
enum class INFO : uint8_t
{
ARTWORK,
WIKI,
TAGS,
METADATA,
LYRICS,
ALL,
NONE
};
/*Generic context names. It's encouraged to use these instead of a unkown string*/
enum class CONTEXT : uint8_t
{
TRACK_STAT,
TRACK_NUMBER,
TRACK_TITLE,
TRACK_DATE,
TRACK_TEAM,
TRACK_AUTHOR,
TRACK_LANGUAGE,
TRACK_SIMILAR,
ALBUM_TEAM,
ALBUM_STAT,
ALBUM_TITLE,
ALBUM_DATE,
ALBUM_LANGUAGE,
ALBUM_SIMILAR,
ALBUM_LABEL,
ARTIST_STAT,
ARTIST_TITLE,
ARTIST_DATE,
ARTIST_LANGUAGE,
ARTIST_PLACE,
ARTIST_SIMILAR,
ARTIST_TEAM,
ARTIST_ALIAS,
ARTIST_GENDER,
GENRE,
TAG,
WIKI,
IMAGE,
LYRIC,
SOURCE
};
static const QMap<CONTEXT,QString> CONTEXT_MAP =
{
{CONTEXT::ALBUM_STAT, "album_stat"},
{CONTEXT::ALBUM_TITLE, "album_title"},
{CONTEXT::ALBUM_DATE, "album_date"},
{CONTEXT::ALBUM_LANGUAGE, "album_language"},
{CONTEXT::ALBUM_SIMILAR, "album_similar"},
{CONTEXT::ALBUM_LABEL, "album_label"},
{CONTEXT::ALBUM_TEAM, "album_team"},
{CONTEXT::ARTIST_STAT, "artist_stat"},
{CONTEXT::ARTIST_TITLE, "artist_title"},
{CONTEXT::ARTIST_DATE, "artist_date"},
{CONTEXT::ARTIST_LANGUAGE, "artist_language"},
{CONTEXT::ARTIST_PLACE, "artist_place"},
{CONTEXT::ARTIST_SIMILAR, "artist_similar"},
{CONTEXT::ARTIST_ALIAS, "artist_alias"},
{CONTEXT::ARTIST_GENDER, "artist_gender"},
{CONTEXT::ARTIST_TEAM, "artist_team"},
{CONTEXT::TRACK_STAT, "track_stat"},
{CONTEXT::TRACK_DATE, "track_date"},
{CONTEXT::TRACK_TITLE, "track_title"},
{CONTEXT::TRACK_NUMBER, "track_number"},
{CONTEXT::TRACK_TEAM, "track_team"},
{CONTEXT::TRACK_AUTHOR, "track_author"},
{CONTEXT::TRACK_LANGUAGE, "track_language"},
{CONTEXT::TRACK_SIMILAR, "track_similar"},
{CONTEXT::GENRE, "genre"},
{CONTEXT::TAG, "tag"},
{CONTEXT::WIKI, "wiki"},
{CONTEXT::IMAGE, "image"},
{CONTEXT::LYRIC, "lyric"},
{CONTEXT::SOURCE, "source"}
};
enum class RECURSIVE : bool
{
ON = true,
OFF = false
};
typedef QMap<CONTEXT, QVariant> VALUE;
typedef QMap<INFO, VALUE> INFO_K;
typedef QMap<ONTOLOGY, INFO_K> RESPONSE;
typedef QMap<ONTOLOGY, QList<INFO>> AVAILABLE;
enum class SERVICES : uint8_t
{
LastFm,
Spotify,
iTunes,
MusicBrainz,
Genius,
LyricWikia,
Wikipedia,
WikiLyrics,
Deezer,
ALL,
NONE
};
enum class ONTOLOGY : uint8_t
{
ARTIST,
ALBUM,
TRACK
};
enum class INFO : uint8_t
{
ARTWORK,
WIKI,
TAGS,
METADATA,
LYRICS,
ALL,
NONE
};
/*Generic context names. It's encouraged to use these instead of a unkown string*/
enum class CONTEXT : uint8_t
{
TRACK_STAT,
TRACK_NUMBER,
TRACK_TITLE,
TRACK_DATE,
TRACK_TEAM,
TRACK_AUTHOR,
TRACK_LANGUAGE,
TRACK_SIMILAR,
ALBUM_TEAM,
ALBUM_STAT,
ALBUM_TITLE,
ALBUM_DATE,
ALBUM_LANGUAGE,
ALBUM_SIMILAR,
ALBUM_LABEL,
ARTIST_STAT,
ARTIST_TITLE,
ARTIST_DATE,
ARTIST_LANGUAGE,
ARTIST_PLACE,
ARTIST_SIMILAR,
ARTIST_TEAM,
ARTIST_ALIAS,
ARTIST_GENDER,
GENRE,
TAG,
WIKI,
IMAGE,
LYRIC,
SOURCE
};
static const QMap<CONTEXT,QString> CONTEXT_MAP =
{
{CONTEXT::ALBUM_STAT, "album_stat"},
{CONTEXT::ALBUM_TITLE, "album_title"},
{CONTEXT::ALBUM_DATE, "album_date"},
{CONTEXT::ALBUM_LANGUAGE, "album_language"},
{CONTEXT::ALBUM_SIMILAR, "album_similar"},
{CONTEXT::ALBUM_LABEL, "album_label"},
{CONTEXT::ALBUM_TEAM, "album_team"},
{CONTEXT::ARTIST_STAT, "artist_stat"},
{CONTEXT::ARTIST_TITLE, "artist_title"},
{CONTEXT::ARTIST_DATE, "artist_date"},
{CONTEXT::ARTIST_LANGUAGE, "artist_language"},
{CONTEXT::ARTIST_PLACE, "artist_place"},
{CONTEXT::ARTIST_SIMILAR, "artist_similar"},
{CONTEXT::ARTIST_ALIAS, "artist_alias"},
{CONTEXT::ARTIST_GENDER, "artist_gender"},
{CONTEXT::ARTIST_TEAM, "artist_team"},
{CONTEXT::TRACK_STAT, "track_stat"},
{CONTEXT::TRACK_DATE, "track_date"},
{CONTEXT::TRACK_TITLE, "track_title"},
{CONTEXT::TRACK_NUMBER, "track_number"},
{CONTEXT::TRACK_TEAM, "track_team"},
{CONTEXT::TRACK_AUTHOR, "track_author"},
{CONTEXT::TRACK_LANGUAGE, "track_language"},
{CONTEXT::TRACK_SIMILAR, "track_similar"},
{CONTEXT::GENRE, "genre"},
{CONTEXT::TAG, "tag"},
{CONTEXT::WIKI, "wiki"},
{CONTEXT::IMAGE, "image"},
{CONTEXT::LYRIC, "lyric"},
{CONTEXT::SOURCE, "source"}
};
enum class RECURSIVE : bool
{
ON = true,
OFF = false
};
typedef QMap<CONTEXT, QVariant> VALUE;
typedef QMap<INFO, VALUE> INFO_K;
// typedef QMap<ONTOLOGY, INFO_K> RESPONSE;
typedef QMap<ONTOLOGY, QList<INFO>> SCOPE;
struct RESPONSE
{
CONTEXT context;
QVariant value;
};
typedef QList<PULPO::RESPONSE> RESPONSES;
struct REQUEST
{
FMH::MODEL track;
PULPO::ONTOLOGY ontology;
QList<PULPO::INFO> info;
QList<PULPO::SERVICES> services;
std::function<void(REQUEST request, RESPONSES responses)> callback;
};
}
......
......@@ -17,289 +17,70 @@
#include "pulpo.h"
#include "services/lastfmService.h"
#include "services/spotifyService.h"
#include "services/lyricwikiaService.h"
#include "services/geniusService.h"
#include "services/musicbrainzService.h"
#include "services/deezerService.h"
//#include "services/spotifyService.h"
//#include "services/lyricwikiaService.h"
//#include "services/geniusService.h"
//#include "services/musicbrainzService.h"
//#include "services/deezerService.h"
//#include "qgumbodocument.h"
//#include "qgumbodocument.h"p
//#include "qgumbonode.h"
Pulpo::Pulpo(const FMH::MODEL &song, QObject *parent)
: QObject(parent), track(song) {}
Pulpo::Pulpo(QObject *parent): QObject(parent) {}
Pulpo::~Pulpo()
{
qDebug()<< "DELETING PULPO INSTANCE";
for(auto &instance : this->serviceInstances)
delete instance;
}
bool Pulpo::feed(const FMH::MODEL &song, const RECURSIVE &recursive)
void Pulpo::request(const PULPO::REQUEST &request)
{
if(song.isEmpty())
return false;
this->track = song;
this->recursive = recursive;
if(this->registeredServices.isEmpty()) return false;
this->initServices();
this->req = request;
return true;
}
void Pulpo::registerServices(const QList<PULPO::SERVICES> &services)
{
this->registeredServices = services;
}
void Pulpo::setInfo(const PULPO::INFO &info)
{
this->info = info;
}
void Pulpo::setOntology(const PULPO::ONTOLOGY &ontology)
{
this->ontology = ontology;
}
if(this->req.track.isEmpty())
{
emit this->error();
return;
}
ONTOLOGY Pulpo::getOntology()
{
return this->ontology;
}
if(this->req.services.isEmpty())
{
qWarning()<< "Please register at least one Pulpo Service";
emit this->error();
return;
}
void Pulpo::setRecursive(const RECURSIVE &state)
{
this->recursive=state;
this->start();
}
QStringList Pulpo::queryHtml(const QByteArray &array, const QString &className)
{
QStringList res;
// auto doc = QGumboDocument::parse(array);
// auto root = doc.rootNode();
// auto nodes = root.getElementsByTagName(HtmlTag::TITLE);
// Q_ASSERT(nodes.size() == 1);
// auto title = nodes.front();
// qDebug() << "title is: " << title.innerText();
// auto container = root.getElementsByClassName(className);
// // if(container.size() == 1)
// // return res;
// auto children = container.front().children();
// for(const auto &i : children)
// res << i.innerText();
return res;
}
void Pulpo::initServices()
void Pulpo::start()
{
for(auto service : this->registeredServices)
for(const auto &service : this->req.services)
switch (service)
{
case SERVICES::LastFm:
{
auto lastfm = new class lastfm(this->track);
this->serviceInstances.push_back(lastfm);
connect(lastfm, &lastfm::infoReady,[=](FMH::MODEL track, PULPO::RESPONSE response)
{
this->passSignal(track, response);
// lastfm->deleteLater();
});
if(lastfm->setUpService(this->ontology, this->info))
{
if(recursive == RECURSIVE::OFF) return;
}else qDebug()<<"Error settingUp lastfm service";
break;
}
case SERVICES::Spotify:
{
spotify spotify(this->track);
connect(&spotify, &spotify::infoReady, this, &Pulpo::passSignal);
if(spotify.setUpService(this->ontology,this->info))
{
if(recursive== RECURSIVE::OFF) return;
}else qDebug()<<"Error settingUp spotify service";
break;
}
case SERVICES::Genius:
{
auto genius = new class genius(this->track);
connect(genius, &genius::infoReady, this, &Pulpo::passSignal);
if(genius->setUpService(this->ontology,this->info))
{
if(recursive== RECURSIVE::OFF) return;
}else qDebug()<<"Error settingUp genius service";
break;
}
case SERVICES::MusicBrainz:
{
musicBrainz musicbrainz(this->track);
connect(&musicbrainz, &musicBrainz::infoReady, this, &Pulpo::passSignal);
if(musicbrainz.setUpService(this->ontology,this->info))
{
if(recursive== RECURSIVE::OFF) return;
}else qDebug()<<"Error settingUp musicBrainz service";
break;
}
case SERVICES::iTunes:
{
break;
}
case SERVICES::WikiLyrics:
{
break;
}
case SERVICES::LyricWikia:
{
auto lyricwikia = new lyricWikia(this->track);
connect(lyricwikia, &lyricWikia::infoReady, this, &Pulpo::passSignal);
if(lyricwikia->setUpService(this->ontology, this->info))
{
if(recursive == RECURSIVE::OFF) return;
}else qDebug()<<"Error settingUp lyricwikia service";
break;
}
case SERVICES::Wikipedia:
{
break;
}
case SERVICES::Deezer:
case SERVICES::LastFm:
{
auto lastfm = new class lastfm();
connect(lastfm, &lastfm::responseReady,[=](PULPO::REQUEST request, PULPO::RESPONSES responses)
{
deezer deezer(this->track);
connect(&deezer, &deezer::infoReady, this, &Pulpo::passSignal);
if(deezer.setUpService(this->ontology, this->info))
{
if(recursive== RECURSIVE::OFF) return;
this->passSignal(request, responses);
lastfm->deleteLater();
});
}else qDebug()<<"Error settingUp deezer service";
break;
}
case SERVICES::ALL:
{
break;
}
case SERVICES::NONE:
{
break;
}
lastfm->set(this->req);
break;
}
}
void Pulpo::passSignal(const FMH::MODEL &track, const PULPO::RESPONSE &response)
{
emit this->infoReady(track, response);
}
PULPO::RESPONSE Pulpo::packResponse(const PULPO::ONTOLOGY ontology, const PULPO::INFO &infoKey, const PULPO::CONTEXT &context, const QVariant &value)
{
return {{ ontology, {{ infoKey, {{ context, value }} }} }};
}
PULPO::RESPONSE Pulpo::packResponse(const ONTOLOGY ontology, const PULPO::INFO &infoKey, const PULPO::VALUE &map)
{
return {{ ontology, { {infoKey, map} }} };
}
bool Pulpo::parseArray()
{
if(this->ontology == PULPO::ONTOLOGY::NONE)
return false;
switch(this->ontology)
{
case PULPO::ONTOLOGY::ALBUM: return this->parseAlbum();
case PULPO::ONTOLOGY::ARTIST: return this->parseArtist();
case PULPO::ONTOLOGY::TRACK: return this->parseTrack();
default: return false;
}
}
QByteArray Pulpo::startConnection(const QString &url, const QMap<QString,QString> &headers)
{
if(!url.isEmpty())
{
QUrl mURL(url);
QNetworkAccessManager manager;
QNetworkRequest request (mURL);
if(!headers.isEmpty())
for(auto key: headers.keys())
request.setRawHeader(key.toLocal8Bit(), headers[key].toLocal8Bit());
QNetworkReply *reply = manager.get(request);
QEventLoop loop;
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
loop.exec();
if(reply->error())
{
qDebug() << reply->error();
return QByteArray();
}
if(reply->bytesAvailable())
{
auto data = reply->readAll();
reply->deleteLater();
return data;
}
}
return QByteArray();
}
void Pulpo::startConnectionAsync(const QString &url, const QMap<QString,QString> &headers)
void Pulpo::passSignal(REQUEST request, RESPONSES responses)
{
if(!url.isEmpty())
{
auto downloader = new FMH::Downloader;
connect(downloader, &FMH::Downloader::dataReady, [=](QByteArray array)
{
// qDebug()<< "DATA READY << " << array;
emit this->arrayReady(array);
downloader->deleteLater();
});
// qDebug()<< "trying to get ASYNC DOWNLOADER for "<< url;
downloader->getArray(url);
}
}
if(request.callback)
request.callback(request, responses);
else
emit this->infoReady(request, responses);
emit this->finished();
}
......@@ -6,14 +6,8 @@
#include <QDebug>
#include <QImage>
#include <QtCore>
#include <QtNetwork>
#include <QUrl>
#include <QObject>
#include <QNetworkAccessManager>
#include <QDomDocument>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QJsonDocument>
#include <QVariantMap>
#include "../utils/bae.h"
......@@ -26,54 +20,23 @@ class Pulpo : public QObject
Q_OBJECT
public:
explicit Pulpo(const FMH::MODEL &song, QObject *parent = nullptr);
explicit Pulpo(QObject *parent = nullptr);
~Pulpo();
bool feed(const FMH::MODEL &song, const PULPO::RECURSIVE &recursive = PULPO::RECURSIVE::ON );
void registerServices(const QList<PULPO::SERVICES> &services);
void setInfo(const PULPO::INFO &info);
void setOntology(const PULPO::ONTOLOGY &ontology);
PULPO::ONTOLOGY getOntology();
void setRecursive(const PULPO::RECURSIVE &state);
QStringList queryHtml(const QByteArray &array, const QString &className = QString());
void request(const PULPO::REQUEST &request);
private:
void initServices();
PULPO::RECURSIVE recursive = PULPO::RECURSIVE::ON;
QList<SERVICES> registeredServices = {};
void passSignal(const FMH::MODEL &track, const PULPO::RESPONSE &response);
QNetworkAccessManager *manager;
QNetworkReply *reply;
QList<Pulpo *> serviceInstances;