initial functional file indexer, added Qt / C++ port of Cartographer
This commit is contained in:
parent
fae3d30dbd
commit
c52386abb4
19 changed files with 721 additions and 149 deletions
|
@ -11,25 +11,29 @@ include(ECMQmlModule)
|
|||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(koto
|
||||
main.cpp
|
||||
config/config.cpp
|
||||
config/library.cpp
|
||||
config/ui_prefs.cpp
|
||||
datalake/indexer.cpp
|
||||
datalake/track.cpp
|
||||
main.cpp
|
||||
config/config.cpp
|
||||
config/library.cpp
|
||||
config/ui_prefs.cpp
|
||||
datalake/indexer.cpp
|
||||
datalake/track.cpp
|
||||
datalake/album.cpp
|
||||
datalake/artist.cpp
|
||||
datalake/cartographer.cpp
|
||||
datalake/cartographer.hpp
|
||||
)
|
||||
|
||||
ecm_add_qml_module(koto URI "com.github.joshstrobl.koto" GENERATE_PLUGIN_SOURCE)
|
||||
|
||||
ecm_target_qml_sources(koto
|
||||
SOURCES
|
||||
qml/PrimaryNavigation.qml
|
||||
qml/HomePage.qml
|
||||
qml/Main.qml
|
||||
SOURCES
|
||||
qml/PrimaryNavigation.qml
|
||||
qml/HomePage.qml
|
||||
qml/Main.qml
|
||||
)
|
||||
|
||||
target_link_libraries(koto
|
||||
PRIVATE KF6::Baloo KF6::FileMetaData Qt6::Quick Qt6::QuickControls2
|
||||
PRIVATE KF6::Baloo KF6::FileMetaData Qt6::Quick Qt6::QuickControls2
|
||||
)
|
||||
|
||||
install(FILES com.github.joshstrobl.koto.desktop DESTINATION ${KDE_INSTALL_APPDIR})
|
||||
|
|
|
@ -1,40 +1,43 @@
|
|||
#include "config.hpp"
|
||||
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
KotoConfig::KotoConfig() {
|
||||
// Define our application's config location
|
||||
auto configDir = QDir(QStandardPaths::writableLocation(QStandardPaths::StandardLocation::AppConfigLocation));
|
||||
auto configDirPath = configDir.absolutePath();
|
||||
fs::path filePath {};
|
||||
auto configPathStd = configDirPath.toStdString();
|
||||
filePath /= configPathStd;
|
||||
filePath /= "config.toml";
|
||||
// Define our application's config location
|
||||
auto configDir = QDir(QStandardPaths::writableLocation(QStandardPaths::StandardLocation::AppConfigLocation));
|
||||
auto configDirPath = configDir.absolutePath();
|
||||
fs::path filePath {};
|
||||
auto configPathStd = configDirPath.toStdString();
|
||||
filePath /= configPathStd;
|
||||
filePath /= "config.toml";
|
||||
|
||||
auto data = toml::parse(filePath);
|
||||
std::optional<toml::value> ui_prefs;
|
||||
auto data = toml::parse(filePath);
|
||||
std::optional<toml::value> ui_prefs;
|
||||
|
||||
if (data.contains("preferences.ui")) {
|
||||
auto ui_prefs_at = data.at("preferences.ui");
|
||||
if (ui_prefs_at.is_table()) ui_prefs = ui_prefs_at.as_table();
|
||||
}
|
||||
if (data.contains("preferences.ui")) {
|
||||
auto ui_prefs_at = data.at("preferences.ui");
|
||||
if (ui_prefs_at.is_table()) ui_prefs = ui_prefs_at.as_table();
|
||||
}
|
||||
|
||||
auto prefs = KotoUiPreferences(ui_prefs);
|
||||
this->i_uiPreferences = &prefs;
|
||||
auto prefs = KotoUiPreferences(ui_prefs);
|
||||
this->i_uiPreferences = &prefs;
|
||||
|
||||
this->i_libraries = {};
|
||||
for (const auto& lib_value : toml::find<std::vector<toml::value>>(data, "libraries")) {
|
||||
auto lib = KotoLibraryConfig(lib_value);
|
||||
this->i_libraries.push_back(lib);
|
||||
}
|
||||
this->i_libraries = {};
|
||||
for (const auto& lib_value : toml::find<std::vector<toml::value>>(data, "libraries")) {
|
||||
auto lib = KotoLibraryConfig(lib_value);
|
||||
this->i_libraries.push_back(lib);
|
||||
}
|
||||
}
|
||||
|
||||
KotoUiPreferences * KotoConfig::getUiPreferences() {
|
||||
return this->i_uiPreferences;
|
||||
KotoConfig::~KotoConfig() {}
|
||||
|
||||
KotoUiPreferences* KotoConfig::getUiPreferences() {
|
||||
return this->i_uiPreferences;
|
||||
}
|
||||
|
||||
std::vector<KotoLibraryConfig> KotoConfig::getLibraries() {
|
||||
return this->i_libraries;
|
||||
return this->i_libraries;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,25 @@
|
|||
#include "library.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
#include <string>
|
||||
|
||||
KotoLibraryConfig::KotoLibraryConfig(const toml::value &v) {
|
||||
this->i_name = toml::find<std::string>(v, "name");
|
||||
this->i_path = toml::find<std::string>(v, "path");
|
||||
KotoLibraryConfig::KotoLibraryConfig(std::string name, fs::path path) {
|
||||
this->i_name = name;
|
||||
this->i_path = path;
|
||||
qDebug() << "Library: " << this->i_name.c_str() << " at " << this->i_path.c_str();
|
||||
}
|
||||
|
||||
KotoLibraryConfig::~KotoLibraryConfig() {}
|
||||
|
||||
KotoLibraryConfig::KotoLibraryConfig(const toml::value& v) {
|
||||
this->i_name = toml::find<std::string>(v, "name");
|
||||
this->i_path = toml::find<std::string>(v, "path");
|
||||
}
|
||||
|
||||
std::string KotoLibraryConfig::getName() {
|
||||
return this->i_name;
|
||||
return this->i_name;
|
||||
}
|
||||
|
||||
fs::path KotoLibraryConfig::getPath() {
|
||||
return this->i_path;
|
||||
return this->i_path;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
#pragma once
|
||||
#include "includes/toml.hpp"
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
#include "includes/toml.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
class KotoLibraryConfig {
|
||||
public:
|
||||
KotoLibraryConfig(const toml::value &v);
|
||||
~KotoLibraryConfig();
|
||||
std::string getName();
|
||||
fs::path getPath();
|
||||
private:
|
||||
std::string i_name;
|
||||
fs::path i_path;
|
||||
public:
|
||||
KotoLibraryConfig(std::string name, fs::path path);
|
||||
KotoLibraryConfig(const toml::value& v);
|
||||
~KotoLibraryConfig();
|
||||
std::string getName();
|
||||
fs::path getPath();
|
||||
|
||||
private:
|
||||
std::string i_name;
|
||||
fs::path i_path;
|
||||
};
|
||||
|
|
|
@ -1,38 +1,40 @@
|
|||
#include "ui_prefs.hpp"
|
||||
|
||||
KotoUiPreferences::KotoUiPreferences(std::optional<toml::value> v) {
|
||||
this->i_albumInfoShowDescription = true;
|
||||
this->i_albumInfoShowGenre = true;
|
||||
this->i_albumInfoShowNarrator = true;
|
||||
this->i_albumInfoShowYear = true;
|
||||
this->i_lastUsedVolume = 0.5;
|
||||
this->i_albumInfoShowDescription = true;
|
||||
this->i_albumInfoShowGenre = true;
|
||||
this->i_albumInfoShowNarrator = true;
|
||||
this->i_albumInfoShowYear = true;
|
||||
this->i_lastUsedVolume = 0.5;
|
||||
|
||||
// No UI prefs provided
|
||||
if (!v.has_value()) return;
|
||||
toml::value& uiPrefs = v.value();
|
||||
this->i_albumInfoShowDescription = toml::find_or<bool>(uiPrefs, "album_info_show_description", false);
|
||||
this->i_albumInfoShowGenre = toml::find_or<bool>(uiPrefs, "album_info_show_genre", false);
|
||||
this->i_albumInfoShowNarrator = toml::find_or<bool>(uiPrefs, "album_info_show_narrator", false);
|
||||
this->i_albumInfoShowYear = toml::find_or<bool>(uiPrefs, "album_info_show_year", false);
|
||||
this->i_lastUsedVolume = toml::find_or<float>(uiPrefs, "last_used_volume", 0.5);
|
||||
// No UI prefs provided
|
||||
if (!v.has_value()) return;
|
||||
toml::value& uiPrefs = v.value();
|
||||
this->i_albumInfoShowDescription = toml::find_or<bool>(uiPrefs, "album_info_show_description", false);
|
||||
this->i_albumInfoShowGenre = toml::find_or<bool>(uiPrefs, "album_info_show_genre", false);
|
||||
this->i_albumInfoShowNarrator = toml::find_or<bool>(uiPrefs, "album_info_show_narrator", false);
|
||||
this->i_albumInfoShowYear = toml::find_or<bool>(uiPrefs, "album_info_show_year", false);
|
||||
this->i_lastUsedVolume = toml::find_or<float>(uiPrefs, "last_used_volume", 0.5);
|
||||
}
|
||||
|
||||
KotoUiPreferences::~KotoUiPreferences() {}
|
||||
|
||||
bool KotoUiPreferences::getAlbumInfoShowDescription() {
|
||||
return this->i_albumInfoShowDescription;
|
||||
return this->i_albumInfoShowDescription;
|
||||
}
|
||||
|
||||
bool KotoUiPreferences::getAlbumInfoShowGenre() {
|
||||
return this->i_albumInfoShowGenre;
|
||||
return this->i_albumInfoShowGenre;
|
||||
}
|
||||
|
||||
bool KotoUiPreferences::getAlbumInfoShowNarrator() {
|
||||
return this->i_albumInfoShowNarrator;
|
||||
return this->i_albumInfoShowNarrator;
|
||||
}
|
||||
|
||||
bool KotoUiPreferences::getAlbumInfoShowYear() {
|
||||
return this->i_albumInfoShowYear;
|
||||
return this->i_albumInfoShowYear;
|
||||
}
|
||||
|
||||
float KotoUiPreferences::getLastUsedVolume() {
|
||||
return this->i_lastUsedVolume;
|
||||
return this->i_lastUsedVolume;
|
||||
}
|
||||
|
|
|
@ -1,30 +1,32 @@
|
|||
#pragma once
|
||||
#include "includes/toml.hpp"
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "includes/toml.hpp"
|
||||
|
||||
class KotoUiPreferences {
|
||||
public:
|
||||
KotoUiPreferences(std::optional<toml::value> v);
|
||||
~KotoUiPreferences();
|
||||
public:
|
||||
KotoUiPreferences(std::optional<toml::value> v);
|
||||
~KotoUiPreferences();
|
||||
|
||||
bool getAlbumInfoShowDescription();
|
||||
bool getAlbumInfoShowGenre();
|
||||
bool getAlbumInfoShowNarrator();
|
||||
bool getAlbumInfoShowYear();
|
||||
float getLastUsedVolume();
|
||||
bool getAlbumInfoShowDescription();
|
||||
bool getAlbumInfoShowGenre();
|
||||
bool getAlbumInfoShowNarrator();
|
||||
bool getAlbumInfoShowYear();
|
||||
float getLastUsedVolume();
|
||||
|
||||
void setAlbumInfoShowDescription(bool show);
|
||||
void setAlbumInfoShowGenre(bool show);
|
||||
void setAlbumInfoShowNarrator(bool show);
|
||||
void setAlbumInfoShowYear(bool show);
|
||||
void setLastUsedVolume(float volume);
|
||||
private:
|
||||
bool i_albumInfoShowDescription;
|
||||
bool i_albumInfoShowGenre;
|
||||
bool i_albumInfoShowNarrator;
|
||||
bool i_albumInfoShowYear;
|
||||
float i_lastUsedVolume;
|
||||
void setAlbumInfoShowDescription(bool show);
|
||||
void setAlbumInfoShowGenre(bool show);
|
||||
void setAlbumInfoShowNarrator(bool show);
|
||||
void setAlbumInfoShowYear(bool show);
|
||||
void setLastUsedVolume(float volume);
|
||||
|
||||
private:
|
||||
bool i_albumInfoShowDescription;
|
||||
bool i_albumInfoShowGenre;
|
||||
bool i_albumInfoShowNarrator;
|
||||
bool i_albumInfoShowYear;
|
||||
float i_lastUsedVolume;
|
||||
};
|
||||
|
|
83
desktop/datalake/album.cpp
Normal file
83
desktop/datalake/album.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
#include "structs.hpp"
|
||||
|
||||
KotoAlbum::KotoAlbum() {
|
||||
this->uuid = QUuid::createUuid();
|
||||
this->tracks = QList<KotoTrack*>();
|
||||
}
|
||||
|
||||
KotoAlbum* KotoAlbum::fromDb() {
|
||||
return new KotoAlbum();
|
||||
}
|
||||
|
||||
KotoAlbum::~KotoAlbum() {
|
||||
for (auto track : this->tracks) { delete track; }
|
||||
this->tracks.clear();
|
||||
}
|
||||
|
||||
void KotoAlbum::addTrack(KotoTrack* track) {
|
||||
this->tracks.append(track);
|
||||
}
|
||||
|
||||
QString KotoAlbum::getAlbumArtPath() {
|
||||
return QString {this->album_art_path};
|
||||
}
|
||||
|
||||
QString KotoAlbum::getDescription() {
|
||||
return QString {this->description};
|
||||
}
|
||||
|
||||
QList<QString> KotoAlbum::getGenres() {
|
||||
return QList {this->genres};
|
||||
}
|
||||
|
||||
QString KotoAlbum::getPath() {
|
||||
return this->path;
|
||||
}
|
||||
|
||||
QString KotoAlbum::getNarrator() {
|
||||
return QString {this->narrator};
|
||||
}
|
||||
|
||||
QString KotoAlbum::getTitle() {
|
||||
return QString {this->title};
|
||||
}
|
||||
|
||||
QList<KotoTrack*> KotoAlbum::getTracks() {
|
||||
return QList {this->tracks};
|
||||
}
|
||||
|
||||
int KotoAlbum::getYear() {
|
||||
return this->year;
|
||||
}
|
||||
|
||||
void KotoAlbum::removeTrack(KotoTrack* track) {
|
||||
this->tracks.removeOne(track);
|
||||
}
|
||||
|
||||
void KotoAlbum::setAlbumArtPath(QString str) {
|
||||
this->album_art_path = QString {path};
|
||||
}
|
||||
|
||||
void KotoAlbum::setDescription(QString str) {
|
||||
this->description = QString {str};
|
||||
}
|
||||
|
||||
void KotoAlbum::setGenres(QList<QString> list) {
|
||||
this->genres = QList {list};
|
||||
}
|
||||
|
||||
void KotoAlbum::setNarrator(QString str) {
|
||||
this->narrator = QString {str};
|
||||
}
|
||||
|
||||
void KotoAlbum::setPath(QString str) {
|
||||
this->path = QString {str};
|
||||
}
|
||||
|
||||
void KotoAlbum::setTitle(QString str) {
|
||||
this->title = QString {str};
|
||||
}
|
||||
|
||||
void KotoAlbum::setYear(int num) {
|
||||
this->year = num;
|
||||
}
|
60
desktop/datalake/artist.cpp
Normal file
60
desktop/datalake/artist.cpp
Normal file
|
@ -0,0 +1,60 @@
|
|||
#include "structs.hpp"
|
||||
|
||||
KotoArtist::KotoArtist() {
|
||||
this->uuid = QUuid::createUuid();
|
||||
}
|
||||
|
||||
KotoArtist* KotoArtist::fromDb() {
|
||||
return new KotoArtist();
|
||||
}
|
||||
|
||||
KotoArtist::~KotoArtist() {
|
||||
for (auto album : this->albums) { delete album; }
|
||||
for (auto track : this->tracks) { delete track; }
|
||||
this->albums.clear();
|
||||
this->tracks.clear();
|
||||
}
|
||||
|
||||
void KotoArtist::addAlbum(KotoAlbum* album) {
|
||||
this->albums.append(album);
|
||||
}
|
||||
|
||||
void KotoArtist::addTrack(KotoTrack* track) {
|
||||
this->tracks.append(track);
|
||||
}
|
||||
|
||||
QList<KotoAlbum*> KotoArtist::getAlbums() {
|
||||
return QList {this->albums};
|
||||
}
|
||||
|
||||
std::optional<KotoAlbum*> KotoArtist::getAlbumByName(QString name) {
|
||||
for (auto album : this->albums) {
|
||||
if (album->getTitle().contains(name)) { return std::optional {album}; }
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QString KotoArtist::getName() {
|
||||
return QString {this->name};
|
||||
}
|
||||
|
||||
QList<KotoTrack*> KotoArtist::getTracks() {
|
||||
return QList {this->tracks};
|
||||
}
|
||||
|
||||
void KotoArtist::removeAlbum(KotoAlbum* album) {
|
||||
this->albums.removeOne(album);
|
||||
}
|
||||
|
||||
void KotoArtist::removeTrack(KotoTrack* track) {
|
||||
this->tracks.removeOne(track);
|
||||
}
|
||||
|
||||
void KotoArtist::setName(QString str) {
|
||||
this->name = QString {str};
|
||||
}
|
||||
|
||||
void KotoArtist::setPath(QString str) {
|
||||
this->path = QString {str};
|
||||
}
|
45
desktop/datalake/cartographer.cpp
Normal file
45
desktop/datalake/cartographer.cpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#include "cartographer.hpp"
|
||||
|
||||
Cartographer::Cartographer()
|
||||
: i_albums(QHash<QUuid, KotoAlbum*>()),
|
||||
i_artists(QHash<QUuid, KotoArtist*>()),
|
||||
i_artists_by_name(QHash<QString, KotoArtist*>()),
|
||||
i_tracks(QHash<QUuid, KotoTrack*>()) {}
|
||||
|
||||
Cartographer& Cartographer::instance() {
|
||||
static Cartographer _instance;
|
||||
return _instance;
|
||||
}
|
||||
|
||||
void Cartographer::addAlbum(KotoAlbum* album) {
|
||||
this->i_albums.insert(album->uuid, album);
|
||||
}
|
||||
|
||||
void Cartographer::addArtist(KotoArtist* artist) {
|
||||
this->i_artists.insert(artist->uuid, artist);
|
||||
this->i_artists_by_name.insert(artist->getName(), artist);
|
||||
}
|
||||
|
||||
void Cartographer::addTrack(KotoTrack* track) {
|
||||
this->i_tracks.insert(track->uuid, track);
|
||||
}
|
||||
|
||||
std::optional<KotoAlbum*> Cartographer::getAlbum(QUuid uuid) {
|
||||
auto album = this->i_albums.value(uuid, nullptr);
|
||||
return album ? std::optional {album} : std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<KotoArtist*> Cartographer::getArtist(QUuid uuid) {
|
||||
auto artist = this->i_artists.value(uuid, nullptr);
|
||||
return artist ? std::optional {artist} : std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<KotoArtist*> Cartographer::getArtist(QString name) {
|
||||
auto artist = this->i_artists_by_name.value(name, nullptr);
|
||||
return artist ? std::optional {artist} : std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<KotoTrack*> Cartographer::getTrack(QUuid uuid) {
|
||||
auto track = this->i_tracks.value(uuid, nullptr);
|
||||
return track ? std::optional {track} : std::nullopt;
|
||||
}
|
30
desktop/datalake/cartographer.hpp
Normal file
30
desktop/datalake/cartographer.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
#include <QUuid>
|
||||
#include <optional>
|
||||
|
||||
#include "structs.hpp"
|
||||
|
||||
class Cartographer {
|
||||
public:
|
||||
Cartographer();
|
||||
static Cartographer& instance();
|
||||
static Cartographer* create() { return &instance(); }
|
||||
|
||||
void addAlbum(KotoAlbum* album);
|
||||
void addArtist(KotoArtist* artist);
|
||||
void addTrack(KotoTrack* track);
|
||||
std::optional<KotoAlbum*> getAlbum(QUuid uuid);
|
||||
//.std::optional<KotoAlbum*> getAlbum(QString name);
|
||||
std::optional<KotoArtist*> getArtist(QUuid uuid);
|
||||
std::optional<KotoArtist*> getArtist(QString name);
|
||||
std::optional<KotoTrack*> getTrack(QUuid uuid);
|
||||
|
||||
private:
|
||||
QHash<QUuid, KotoAlbum*> i_albums;
|
||||
QHash<QUuid, KotoArtist*> i_artists;
|
||||
QHash<QString, KotoArtist*> i_artists_by_name;
|
||||
QHash<QUuid, KotoTrack*> i_tracks;
|
||||
};
|
|
@ -1,6 +1,90 @@
|
|||
#include "indexer.hpp"
|
||||
|
||||
#include <KFileMetaData/ExtractorCollection>
|
||||
#include <QDebug>
|
||||
#include <QDirIterator>
|
||||
#include <QMimeDatabase>
|
||||
#include <iostream>
|
||||
|
||||
FileIndexer::FileIndexer(KotoLibraryConfig * config) {
|
||||
|
||||
FileIndexer::FileIndexer(KotoLibraryConfig* config) {
|
||||
this->i_root = QString {config->getPath().c_str()};
|
||||
}
|
||||
|
||||
FileIndexer::~FileIndexer() = default;
|
||||
|
||||
void FileIndexer::index() {
|
||||
QMimeDatabase db;
|
||||
KFileMetaData::ExtractorCollection extractors;
|
||||
|
||||
QStringList root_dirs {this->i_root.split(QDir::separator())};
|
||||
|
||||
QDirIterator it {this->i_root, QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot, QDirIterator::Subdirectories};
|
||||
|
||||
// std::cout << "Indexing " << this->i_root.toStdString();
|
||||
|
||||
while (it.hasNext()) {
|
||||
QString path = it.next();
|
||||
QFileInfo info {path};
|
||||
|
||||
if (info.isDir()) {
|
||||
auto diffPath = info.dir().relativeFilePath(this->i_root);
|
||||
auto diffDirs = diffPath.split("..");
|
||||
auto diffDirsSize = diffDirs.size() - 1;
|
||||
|
||||
// This is going to be an artist
|
||||
if (diffDirsSize == 0) {
|
||||
auto artist = new KotoArtist();
|
||||
artist->setName(info.fileName());
|
||||
artist->setPath(path);
|
||||
this->i_artists.append(artist);
|
||||
Cartographer::instance().addArtist(artist);
|
||||
continue;
|
||||
} else if (diffDirsSize == 1) {
|
||||
auto album = new KotoAlbum();
|
||||
album->setTitle(info.fileName());
|
||||
|
||||
auto artistDir = QDir(info.dir());
|
||||
auto artistName = artistDir.dirName();
|
||||
auto artistOptional = Cartographer::instance().getArtist(artistName);
|
||||
|
||||
if (artistOptional.has_value()) {
|
||||
auto artist = artistOptional.value();
|
||||
album->artist_uuid = artist->uuid;
|
||||
artist->addAlbum(album);
|
||||
}
|
||||
|
||||
Cartographer::instance().addAlbum(album);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// This is a file
|
||||
QMimeType mime = db.mimeTypeForFile(info);
|
||||
if (mime.name().startsWith("audio/")) {
|
||||
auto extractorList = extractors.fetchExtractors(mime.name());
|
||||
if (extractorList.isEmpty()) { continue; }
|
||||
|
||||
auto result = KFileMetaData::SimpleExtractionResult(path, mime.name(), KFileMetaData::ExtractionResult::ExtractMetaData);
|
||||
extractorList.first()->extract(&result);
|
||||
|
||||
if (!result.types().contains(KFileMetaData::Type::Audio)) { continue; }
|
||||
|
||||
auto track = KotoTrack::fromMetadata(result);
|
||||
track->setPath(path);
|
||||
|
||||
this->i_tracks.append(track);
|
||||
Cartographer::instance().addTrack(track);
|
||||
} else if (mime.name().startsWith("image/")) {
|
||||
// This is an image, TODO add cover art to album
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "===== Summary =====" << std::endl;
|
||||
for (auto artist : this->i_artists) {
|
||||
std::cout << "Artist: " << artist->getName().toStdString() << std::endl;
|
||||
for (auto album : artist->getAlbums()) {
|
||||
std::cout << " Album: " << album->getTitle().toStdString() << std::endl;
|
||||
for (auto track : album->getTracks()) { std::cout << " Track: " << track->getTitle().toStdString() << std::endl; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "cartographer.hpp"
|
||||
#include "config/library.hpp"
|
||||
#include "track.hpp"
|
||||
#include "structs.hpp"
|
||||
|
||||
class FileIndexer {
|
||||
public:
|
||||
FileIndexer(KotoLibraryConfig * config);
|
||||
~FileIndexer();
|
||||
public:
|
||||
FileIndexer(KotoLibraryConfig* config);
|
||||
~FileIndexer();
|
||||
|
||||
std::vector<KotoTrack *> getFiles();
|
||||
std::string getRoot();
|
||||
QList<KotoArtist*> getArtists();
|
||||
QList<KotoTrack*> getFiles();
|
||||
QString getRoot();
|
||||
|
||||
void index();
|
||||
protected:
|
||||
std::vector<KotoTrack *> i_tracks;
|
||||
std::string i_root;
|
||||
void index();
|
||||
|
||||
protected:
|
||||
void indexDirectory(QString path, int depth);
|
||||
QList<KotoArtist*> i_artists;
|
||||
QList<KotoTrack*> i_tracks;
|
||||
QString i_root;
|
||||
};
|
||||
|
|
125
desktop/datalake/structs.hpp
Normal file
125
desktop/datalake/structs.hpp
Normal file
|
@ -0,0 +1,125 @@
|
|||
#pragma once
|
||||
#include <KFileMetaData/SimpleExtractionResult>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QUuid>
|
||||
#include <filesystem>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
class KotoArtist;
|
||||
class KotoAlbum;
|
||||
class KotoTrack;
|
||||
|
||||
class KotoArtist {
|
||||
public:
|
||||
KotoArtist();
|
||||
static KotoArtist* fromDb();
|
||||
~KotoArtist();
|
||||
|
||||
QUuid uuid;
|
||||
|
||||
void addAlbum(KotoAlbum* album);
|
||||
void addTrack(KotoTrack* track);
|
||||
QList<KotoAlbum*> getAlbums();
|
||||
std::optional<KotoAlbum*> getAlbumByName(QString name);
|
||||
QString getName();
|
||||
QString getPath();
|
||||
QList<KotoTrack*> getTracks();
|
||||
void removeAlbum(KotoAlbum* album);
|
||||
void removeTrack(KotoTrack* track);
|
||||
void setName(QString str);
|
||||
void setPath(QString str);
|
||||
|
||||
private:
|
||||
QString path;
|
||||
QString name;
|
||||
|
||||
QList<KotoAlbum*> albums;
|
||||
QList<KotoTrack*> tracks;
|
||||
};
|
||||
|
||||
class KotoAlbum {
|
||||
public:
|
||||
KotoAlbum();
|
||||
static KotoAlbum* fromDb();
|
||||
~KotoAlbum();
|
||||
|
||||
QUuid uuid;
|
||||
QUuid artist_uuid;
|
||||
|
||||
QString getAlbumArtPath();
|
||||
QString getDescription();
|
||||
QList<QString> getGenres();
|
||||
QString getNarrator();
|
||||
QString getPath();
|
||||
QString getTitle();
|
||||
QList<KotoTrack*> getTracks();
|
||||
int getYear();
|
||||
|
||||
void addTrack(KotoTrack* track);
|
||||
void removeTrack(KotoTrack* track);
|
||||
void setAlbumArtPath(QString str);
|
||||
void setDescription(QString str);
|
||||
void setGenres(QList<QString> list);
|
||||
void setNarrator(QString str);
|
||||
void setPath(QString str);
|
||||
void setTitle(QString str);
|
||||
void setYear(int num);
|
||||
|
||||
private:
|
||||
QString title;
|
||||
QString description;
|
||||
QString narrator;
|
||||
int year;
|
||||
|
||||
QList<QString> genres;
|
||||
QList<KotoTrack*> tracks;
|
||||
|
||||
QString path;
|
||||
QString album_art_path;
|
||||
};
|
||||
|
||||
class KotoTrack {
|
||||
public:
|
||||
KotoTrack(); // No-op constructor
|
||||
static KotoTrack* fromDb();
|
||||
static KotoTrack* fromMetadata(const KFileMetaData::SimpleExtractionResult& metadata);
|
||||
~KotoTrack();
|
||||
|
||||
std::optional<QUuid> album_uuid;
|
||||
QUuid artist_uuid;
|
||||
QUuid uuid;
|
||||
|
||||
int getDuration();
|
||||
QStringList getGenres();
|
||||
QString getLyrics();
|
||||
QString getNarrator();
|
||||
QString getPath();
|
||||
QString getTitle();
|
||||
int getTrackNumber();
|
||||
int getYear();
|
||||
|
||||
void setAlbum(KotoAlbum* album);
|
||||
void setArtist(KotoArtist* artist);
|
||||
void setDiscNumber(int num);
|
||||
void setDuration(int num);
|
||||
void setGenres(QList<QString> list);
|
||||
void setLyrics(QString str);
|
||||
void setNarrator(QString str);
|
||||
void setPath(QString path);
|
||||
void setTitle(QString str);
|
||||
void setTrackNumber(int num);
|
||||
void setYear(int num);
|
||||
|
||||
private:
|
||||
int disc_number;
|
||||
int duration;
|
||||
QStringList genres;
|
||||
QString lyrics;
|
||||
QString narrator;
|
||||
QString path;
|
||||
QString title;
|
||||
int track_number;
|
||||
int year;
|
||||
};
|
|
@ -0,0 +1,140 @@
|
|||
#include <iostream>
|
||||
|
||||
#include "cartographer.hpp"
|
||||
#include "structs.hpp"
|
||||
|
||||
KotoTrack::KotoTrack() {
|
||||
this->uuid = QUuid::createUuid();
|
||||
}
|
||||
|
||||
KotoTrack* KotoTrack::fromDb() {
|
||||
return new KotoTrack();
|
||||
}
|
||||
|
||||
KotoTrack::~KotoTrack() {}
|
||||
|
||||
KotoTrack* KotoTrack::fromMetadata(const KFileMetaData::SimpleExtractionResult& metadata) {
|
||||
auto props = metadata.properties();
|
||||
KotoTrack* track = new KotoTrack();
|
||||
track->disc_number = props.value(KFileMetaData::Property::DiscNumber, 0).toInt();
|
||||
track->duration = props.value(KFileMetaData::Property::Duration, 0).toInt();
|
||||
|
||||
QStringList genres;
|
||||
for (auto v : props.values(KFileMetaData::Property::Genre)) { genres.append(v.toString()); }
|
||||
|
||||
track->genres = genres;
|
||||
|
||||
track->lyrics = props.value(KFileMetaData::Property::Lyrics).toString();
|
||||
track->narrator = props.value(KFileMetaData::Property::Performer).toString();
|
||||
track->title = props.value(KFileMetaData::Property::Title).toString();
|
||||
track->track_number = props.value(KFileMetaData::Property::TrackNumber, 0).toInt();
|
||||
track->year = props.value(KFileMetaData::Property::ReleaseYear, 0).toInt();
|
||||
|
||||
auto artistResult = props.value(KFileMetaData::Property::Artist);
|
||||
auto artistOptional = std::optional<KotoArtist*>();
|
||||
if (artistResult.isValid()) {
|
||||
artistOptional = Cartographer::instance().getArtist(artistResult.toString());
|
||||
|
||||
if (artistOptional.has_value()) {
|
||||
auto artist = artistOptional.value();
|
||||
track->artist_uuid = QUuid(artist->uuid);
|
||||
artist->addTrack(track);
|
||||
}
|
||||
}
|
||||
|
||||
auto albumResult = props.value(KFileMetaData::Property::Album);
|
||||
if (albumResult.isValid() && artistOptional.has_value()) {
|
||||
auto artist = artistOptional.value();
|
||||
std::cout << "Album: " << albumResult.toString().toStdString() << std::endl;
|
||||
|
||||
auto albumMetaName = albumResult.toString();
|
||||
auto albumOptional = artist->getAlbumByName(albumMetaName);
|
||||
|
||||
if (albumOptional.has_value()) {
|
||||
auto album = albumOptional.value();
|
||||
track->album_uuid = QUuid(album->uuid);
|
||||
album->addTrack(track);
|
||||
if (album->getTitle() != albumMetaName) album->setTitle(albumMetaName);
|
||||
}
|
||||
}
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
int KotoTrack::getDuration() {
|
||||
return this->duration;
|
||||
}
|
||||
|
||||
QList<QString> KotoTrack::getGenres() {
|
||||
return QList {this->genres};
|
||||
}
|
||||
|
||||
QString KotoTrack::getLyrics() {
|
||||
return QString {this->lyrics};
|
||||
}
|
||||
|
||||
QString KotoTrack::getNarrator() {
|
||||
return QString {this->narrator};
|
||||
}
|
||||
|
||||
QString KotoTrack::getPath() {
|
||||
return QString {this->path};
|
||||
}
|
||||
|
||||
QString KotoTrack::getTitle() {
|
||||
return QString {this->title};
|
||||
}
|
||||
|
||||
int KotoTrack::getTrackNumber() {
|
||||
return this->track_number;
|
||||
}
|
||||
|
||||
int KotoTrack::getYear() {
|
||||
return this->year;
|
||||
}
|
||||
|
||||
void KotoTrack::setAlbum(KotoAlbum* album) {
|
||||
this->album_uuid = QUuid(album->uuid);
|
||||
|
||||
if (this->artist_uuid.isNull()) QUuid(album->artist_uuid);
|
||||
}
|
||||
|
||||
void KotoTrack::setArtist(KotoArtist* artist) {
|
||||
this->artist_uuid = QUuid(artist->uuid);
|
||||
}
|
||||
|
||||
void KotoTrack::setDiscNumber(int num) {
|
||||
this->disc_number = num;
|
||||
}
|
||||
|
||||
void KotoTrack::setDuration(int num) {
|
||||
this->duration = num;
|
||||
}
|
||||
|
||||
void KotoTrack::setGenres(QList<QString> list) {
|
||||
this->genres = QList {list};
|
||||
}
|
||||
|
||||
void KotoTrack::setLyrics(QString str) {
|
||||
this->lyrics = QString {str};
|
||||
}
|
||||
|
||||
void KotoTrack::setNarrator(QString str) {
|
||||
this->narrator = QString {str};
|
||||
}
|
||||
|
||||
void KotoTrack::setPath(QString str) {
|
||||
this->path = QString {str};
|
||||
}
|
||||
|
||||
void KotoTrack::setTitle(QString str) {
|
||||
this->title = QString {str};
|
||||
}
|
||||
|
||||
void KotoTrack::setTrackNumber(int num) {
|
||||
this->track_number = num;
|
||||
}
|
||||
|
||||
void KotoTrack::setYear(int num) {
|
||||
this->year = num;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
#pragma once
|
||||
#include <KFileMetaData/SimpleExtractionResult>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class KotoTrack {
|
||||
public:
|
||||
KotoTrack(); // No-op constructor
|
||||
static KotoTrack * fromDb();
|
||||
static KotoTrack * fromMetadata(KFileMetaData::SimpleExtractionResult metadata);
|
||||
~KotoTrack();
|
||||
|
||||
private:
|
||||
std::string album;
|
||||
std::string album_artist;
|
||||
std::string artist;
|
||||
int disc_number;
|
||||
int duration;
|
||||
std::vector<std::string> genres;
|
||||
std::string lyrics;
|
||||
std::string narrator;
|
||||
std::string path;
|
||||
std::string title;
|
||||
int track_number;
|
||||
int year;
|
||||
};
|
|
@ -9,18 +9,6 @@ last_used_volume = 0.5
|
|||
jump_backwards_seconds = 30
|
||||
jump_forward_seconds = 30
|
||||
|
||||
[[libraries]]
|
||||
name = "Audiobooks"
|
||||
path = "/home/joshua/Audiobooks"
|
||||
|
||||
[[libraries]]
|
||||
name = "Music"
|
||||
path = "/home/joshua/Music"
|
||||
|
||||
[[libraries]]
|
||||
name = "Streaming"
|
||||
path = "/home/joshua/StreamingMusic"
|
||||
|
||||
[[libraries]]
|
||||
name = "Podcasts"
|
||||
path = "/home/joshua/Podcasts"
|
||||
|
|
|
@ -1,21 +1,32 @@
|
|||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQuickStyle>
|
||||
#include <thread>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QQuickStyle::setStyle(QStringLiteral("org.kde.breeze"));
|
||||
QGuiApplication app(argc, argv);
|
||||
app.setApplicationDisplayName("Koto");
|
||||
app.setDesktopFileName("com.github.joshstrobl.koto.desktop");
|
||||
#include "config/library.hpp"
|
||||
#include "datalake/indexer.hpp"
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
int main(int argc, char* argv[]) {
|
||||
QQuickStyle::setStyle(QStringLiteral("org.kde.breeze"));
|
||||
QGuiApplication app(argc, argv);
|
||||
app.setApplicationDisplayName("Koto");
|
||||
app.setDesktopFileName("com.github.joshstrobl.koto.desktop");
|
||||
|
||||
engine.loadFromModule("com.github.joshstrobl.koto", "Main");
|
||||
QQmlApplicationEngine engine;
|
||||
|
||||
if (engine.rootObjects().isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
engine.loadFromModule("com.github.joshstrobl.koto", "Main");
|
||||
|
||||
return app.exec();
|
||||
if (engine.rootObjects().isEmpty()) { return -1; }
|
||||
|
||||
// std::thread([]() {
|
||||
// auto config = KotoLibraryConfig("Music", "/home/joshua/Music");
|
||||
//
|
||||
// auto indexExample = FileIndexer(&config);
|
||||
// indexExample.index();
|
||||
// }).detach();
|
||||
Cartographer::create();
|
||||
auto config = KotoLibraryConfig("Music", "/home/joshua/Music");
|
||||
auto indexExample = FileIndexer(&config);
|
||||
indexExample.index();
|
||||
return app.exec();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue