diff --git a/.gitignore b/.gitignore index 25cf7d6..c79f2da 100644 --- a/.gitignore +++ b/.gitignore @@ -72,10 +72,12 @@ CMakeLists.txt.user* *.dll *.exe +.ccls-cache/ .qt/ .rcc/ bin/ -build/ +build*/ +cmake-build-debug/ **/qmldir **/meta_types **/qmltypes diff --git a/desktop/CMakeLists.txt b/desktop/CMakeLists.txt index 11a8b03..492f4df 100644 --- a/desktop/CMakeLists.txt +++ b/desktop/CMakeLists.txt @@ -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}) diff --git a/desktop/config/config.cpp b/desktop/config/config.cpp index 7d0c174..cbea6ab 100644 --- a/desktop/config/config.cpp +++ b/desktop/config/config.cpp @@ -1,40 +1,43 @@ #include "config.hpp" + #include #include #include 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 ui_prefs; + auto data = toml::parse(filePath); + std::optional 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>(data, "libraries")) { - auto lib = KotoLibraryConfig(lib_value); - this->i_libraries.push_back(lib); - } + this->i_libraries = {}; + for (const auto& lib_value : toml::find>(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 KotoConfig::getLibraries() { - return this->i_libraries; + return this->i_libraries; } diff --git a/desktop/config/library.cpp b/desktop/config/library.cpp index c91bc57..0c3fa18 100644 --- a/desktop/config/library.cpp +++ b/desktop/config/library.cpp @@ -1,15 +1,25 @@ #include "library.hpp" + +#include #include -KotoLibraryConfig::KotoLibraryConfig(const toml::value &v) { - this->i_name = toml::find(v, "name"); - this->i_path = toml::find(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(v, "name"); + this->i_path = toml::find(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; } diff --git a/desktop/config/library.hpp b/desktop/config/library.hpp index 375e221..1baf089 100644 --- a/desktop/config/library.hpp +++ b/desktop/config/library.hpp @@ -1,17 +1,20 @@ #pragma once -#include "includes/toml.hpp" #include #include +#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; }; diff --git a/desktop/config/ui_prefs.cpp b/desktop/config/ui_prefs.cpp index e25c901..dfc8065 100644 --- a/desktop/config/ui_prefs.cpp +++ b/desktop/config/ui_prefs.cpp @@ -1,38 +1,40 @@ #include "ui_prefs.hpp" KotoUiPreferences::KotoUiPreferences(std::optional 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(uiPrefs, "album_info_show_description", false); - this->i_albumInfoShowGenre = toml::find_or(uiPrefs, "album_info_show_genre", false); - this->i_albumInfoShowNarrator = toml::find_or(uiPrefs, "album_info_show_narrator", false); - this->i_albumInfoShowYear = toml::find_or(uiPrefs, "album_info_show_year", false); - this->i_lastUsedVolume = toml::find_or(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(uiPrefs, "album_info_show_description", false); + this->i_albumInfoShowGenre = toml::find_or(uiPrefs, "album_info_show_genre", false); + this->i_albumInfoShowNarrator = toml::find_or(uiPrefs, "album_info_show_narrator", false); + this->i_albumInfoShowYear = toml::find_or(uiPrefs, "album_info_show_year", false); + this->i_lastUsedVolume = toml::find_or(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; } diff --git a/desktop/config/ui_prefs.hpp b/desktop/config/ui_prefs.hpp index a55fc51..58f6141 100644 --- a/desktop/config/ui_prefs.hpp +++ b/desktop/config/ui_prefs.hpp @@ -1,30 +1,32 @@ #pragma once -#include "includes/toml.hpp" #include #include #include #include +#include "includes/toml.hpp" + class KotoUiPreferences { - public: - KotoUiPreferences(std::optional v); - ~KotoUiPreferences(); + public: + KotoUiPreferences(std::optional 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; }; diff --git a/desktop/datalake/album.cpp b/desktop/datalake/album.cpp new file mode 100644 index 0000000..082ad2c --- /dev/null +++ b/desktop/datalake/album.cpp @@ -0,0 +1,83 @@ +#include "structs.hpp" + +KotoAlbum::KotoAlbum() { + this->uuid = QUuid::createUuid(); + this->tracks = QList(); +} + +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 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 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 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; +} diff --git a/desktop/datalake/artist.cpp b/desktop/datalake/artist.cpp new file mode 100644 index 0000000..f473b71 --- /dev/null +++ b/desktop/datalake/artist.cpp @@ -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 KotoArtist::getAlbums() { + return QList {this->albums}; +} + +std::optional 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 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}; +} diff --git a/desktop/datalake/artist.hpp b/desktop/datalake/artist.hpp deleted file mode 100644 index e69de29..0000000 diff --git a/desktop/datalake/cartographer.cpp b/desktop/datalake/cartographer.cpp new file mode 100644 index 0000000..3c830a5 --- /dev/null +++ b/desktop/datalake/cartographer.cpp @@ -0,0 +1,45 @@ +#include "cartographer.hpp" + +Cartographer::Cartographer() + : i_albums(QHash()), + i_artists(QHash()), + i_artists_by_name(QHash()), + i_tracks(QHash()) {} + +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 Cartographer::getAlbum(QUuid uuid) { + auto album = this->i_albums.value(uuid, nullptr); + return album ? std::optional {album} : std::nullopt; +} + +std::optional Cartographer::getArtist(QUuid uuid) { + auto artist = this->i_artists.value(uuid, nullptr); + return artist ? std::optional {artist} : std::nullopt; +} + +std::optional Cartographer::getArtist(QString name) { + auto artist = this->i_artists_by_name.value(name, nullptr); + return artist ? std::optional {artist} : std::nullopt; +} + +std::optional Cartographer::getTrack(QUuid uuid) { + auto track = this->i_tracks.value(uuid, nullptr); + return track ? std::optional {track} : std::nullopt; +} diff --git a/desktop/datalake/cartographer.hpp b/desktop/datalake/cartographer.hpp new file mode 100644 index 0000000..ca7e2e5 --- /dev/null +++ b/desktop/datalake/cartographer.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include +#include + +#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 getAlbum(QUuid uuid); + //.std::optional getAlbum(QString name); + std::optional getArtist(QUuid uuid); + std::optional getArtist(QString name); + std::optional getTrack(QUuid uuid); + + private: + QHash i_albums; + QHash i_artists; + QHash i_artists_by_name; + QHash i_tracks; +}; diff --git a/desktop/datalake/indexer.cpp b/desktop/datalake/indexer.cpp index d50994a..32ce49e 100644 --- a/desktop/datalake/indexer.cpp +++ b/desktop/datalake/indexer.cpp @@ -1,6 +1,90 @@ #include "indexer.hpp" + +#include +#include #include +#include +#include -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; } + } + } } diff --git a/desktop/datalake/indexer.hpp b/desktop/datalake/indexer.hpp index a1c9c03..ed2e48e 100644 --- a/desktop/datalake/indexer.hpp +++ b/desktop/datalake/indexer.hpp @@ -1,19 +1,25 @@ #pragma once #include + +#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 getFiles(); - std::string getRoot(); + QList getArtists(); + QList getFiles(); + QString getRoot(); - void index(); - protected: - std::vector i_tracks; - std::string i_root; + void index(); + + protected: + void indexDirectory(QString path, int depth); + QList i_artists; + QList i_tracks; + QString i_root; }; diff --git a/desktop/datalake/structs.hpp b/desktop/datalake/structs.hpp new file mode 100644 index 0000000..77cdab3 --- /dev/null +++ b/desktop/datalake/structs.hpp @@ -0,0 +1,125 @@ +#pragma once +#include +#include +#include +#include +#include + +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 getAlbums(); + std::optional getAlbumByName(QString name); + QString getName(); + QString getPath(); + QList getTracks(); + void removeAlbum(KotoAlbum* album); + void removeTrack(KotoTrack* track); + void setName(QString str); + void setPath(QString str); + + private: + QString path; + QString name; + + QList albums; + QList tracks; +}; + +class KotoAlbum { + public: + KotoAlbum(); + static KotoAlbum* fromDb(); + ~KotoAlbum(); + + QUuid uuid; + QUuid artist_uuid; + + QString getAlbumArtPath(); + QString getDescription(); + QList getGenres(); + QString getNarrator(); + QString getPath(); + QString getTitle(); + QList getTracks(); + int getYear(); + + void addTrack(KotoTrack* track); + void removeTrack(KotoTrack* track); + void setAlbumArtPath(QString str); + void setDescription(QString str); + void setGenres(QList 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 genres; + QList 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 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 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; +}; diff --git a/desktop/datalake/track.cpp b/desktop/datalake/track.cpp index e69de29..b4e5b1c 100644 --- a/desktop/datalake/track.cpp +++ b/desktop/datalake/track.cpp @@ -0,0 +1,140 @@ +#include + +#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(); + 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 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 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; +} diff --git a/desktop/datalake/track.hpp b/desktop/datalake/track.hpp deleted file mode 100644 index 7b1a99b..0000000 --- a/desktop/datalake/track.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include -#include -#include - -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 genres; - std::string lyrics; - std::string narrator; - std::string path; - std::string title; - int track_number; - int year; -}; diff --git a/desktop/example-config.toml b/desktop/example-config.toml index 8e144b1..6cffb8a 100644 --- a/desktop/example-config.toml +++ b/desktop/example-config.toml @@ -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" diff --git a/desktop/main.cpp b/desktop/main.cpp index 840783f..9e5bcd0 100644 --- a/desktop/main.cpp +++ b/desktop/main.cpp @@ -1,21 +1,32 @@ #include #include #include +#include -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(); }