initial commit

This commit is contained in:
Joshua Strobl 2024-09-29 17:29:10 +03:00
commit fae3d30dbd
26 changed files with 18409 additions and 0 deletions

38
desktop/CMakeLists.txt Normal file
View file

@ -0,0 +1,38 @@
find_package(Qt6 6.4 REQUIRED COMPONENTS Quick QuickControls2)
find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE)
find_package(KF6Baloo)
find_package(KF6FileMetaData)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
include(KDEInstallDirs)
include(ECMFindQmlModule)
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
)
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
)
target_link_libraries(koto
PRIVATE KF6::Baloo KF6::FileMetaData Qt6::Quick Qt6::QuickControls2
)
install(FILES com.github.joshstrobl.koto.desktop DESTINATION ${KDE_INSTALL_APPDIR})
install(TARGETS koto ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
ecm_finalize_qml_module(koto)

40
desktop/config/config.cpp Normal file
View file

@ -0,0 +1,40 @@
#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";
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();
}
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);
}
}
KotoUiPreferences * KotoConfig::getUiPreferences() {
return this->i_uiPreferences;
}
std::vector<KotoLibraryConfig> KotoConfig::getLibraries() {
return this->i_libraries;
}

18
desktop/config/config.hpp Normal file
View file

@ -0,0 +1,18 @@
#pragma once
#include <vector>
#include "library.hpp"
#include "ui_prefs.hpp"
class KotoConfig {
public:
KotoConfig();
~KotoConfig();
std::vector<KotoLibraryConfig> getLibraries();
KotoUiPreferences * getUiPreferences();
private:
std::vector<KotoLibraryConfig> i_libraries;
KotoUiPreferences * i_uiPreferences;
};

View file

@ -0,0 +1,15 @@
#include "library.hpp"
#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");
}
std::string KotoLibraryConfig::getName() {
return this->i_name;
}
fs::path KotoLibraryConfig::getPath() {
return this->i_path;
}

View file

@ -0,0 +1,17 @@
#pragma once
#include "includes/toml.hpp"
#include <filesystem>
#include <string>
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;
};

View file

@ -0,0 +1,38 @@
#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;
// 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);
}
bool KotoUiPreferences::getAlbumInfoShowDescription() {
return this->i_albumInfoShowDescription;
}
bool KotoUiPreferences::getAlbumInfoShowGenre() {
return this->i_albumInfoShowGenre;
}
bool KotoUiPreferences::getAlbumInfoShowNarrator() {
return this->i_albumInfoShowNarrator;
}
bool KotoUiPreferences::getAlbumInfoShowYear() {
return this->i_albumInfoShowYear;
}
float KotoUiPreferences::getLastUsedVolume() {
return this->i_lastUsedVolume;
}

View file

@ -0,0 +1,30 @@
#pragma once
#include "includes/toml.hpp"
#include <optional>
#include <string>
#include <string_view>
#include <vector>
class KotoUiPreferences {
public:
KotoUiPreferences(std::optional<toml::value> v);
~KotoUiPreferences();
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;
};

View file

View file

@ -0,0 +1,6 @@
#include "indexer.hpp"
#include <QDirIterator>
FileIndexer::FileIndexer(KotoLibraryConfig * config) {
}

View file

@ -0,0 +1,19 @@
#pragma once
#include <string>
#include "config/library.hpp"
#include "track.hpp"
class FileIndexer {
public:
FileIndexer(KotoLibraryConfig * config);
~FileIndexer();
std::vector<KotoTrack *> getFiles();
std::string getRoot();
void index();
protected:
std::vector<KotoTrack *> i_tracks;
std::string i_root;
};

View file

View file

@ -0,0 +1,26 @@
#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;
};

View file

@ -0,0 +1,26 @@
[preferences.ui]
album_info_show_description = true
album_info_show_genre = true
album_info_show_narrator = true
album_info_show_year = true
last_used_volume = 0.5
[preferences.podcasts]
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"

17240
desktop/includes/toml.hpp Normal file

File diff suppressed because it is too large Load diff

21
desktop/main.cpp Normal file
View file

@ -0,0 +1,21 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickStyle>
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");
QQmlApplicationEngine engine;
engine.loadFromModule("com.github.joshstrobl.koto", "Main");
if (engine.rootObjects().isEmpty()) {
return -1;
}
return app.exec();
}

12
desktop/qml/HomePage.qml Normal file
View file

@ -0,0 +1,12 @@
import QtQuick
import QtQuick.Controls as Controls
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
Kirigami.Page {
ColumnLayout {
Controls.Label {
text: qsTr("blah!")
}
}
}

20
desktop/qml/Main.qml Normal file
View file

@ -0,0 +1,20 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami
Kirigami.ApplicationWindow {
id: root
width: 1000
height: 600
visible: true
title: "Koto"
// TODO: Implement an onboarding page
pageStack.initialPage: PrimaryNavigation {
Component.onCompleted: {
pageStack.push(Qt.createComponent("HomePage.qml"), {});
}
}
}

View file

@ -0,0 +1,87 @@
import QtQuick
import QtQuick.Controls as Controls
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
// Kirigami.Page {
// ColumnLayout {
// Controls.TextArea {
// Layout.alignment: Qt.AlignTop
// id: searchEntry
// placeholderText: qsTr("Search")
// }
// }
// }
Kirigami.GlobalDrawer {
width: 200
height: parent.height
edge: Qt.LeftEdge
modal: false
header: Kirigami.SearchField {
id: searchEntry
placeholderText: qsTr("Search")
}
actions: [
Kirigami.Action {
text: "Home"
icon.name: "go-home"
onTriggered: console.log("Home triggered")
},
Kirigami.Action {
text: "Audiobooks"
expandible: true
icon.name: "bookmark"
onTriggered: console.log("Audiobooks triggered")
},
Kirigami.Action {
text: "Music"
expandible: true
icon.name: "emblem-music-symbolic"
children: [
Kirigami.Action {
text: "Local Library"
onTriggered: console.log("Music Local Library triggered")
},
Kirigami.Action {
text: "Radio"
onTriggered: console.log("Music Radio triggered")
}
]
},
Kirigami.Action {
text: "Podcasts"
expandible: true
icon.name: "application-rss+xml-symbolic"
children: [
Kirigami.Action {
text: "Library"
onTriggered: console.log("Podcasts Library triggered")
},
Kirigami.Action {
text: "Find new podcasts"
onTriggered: console.log("Podcasts Find new podcasts triggered")
}
]
},
Kirigami.Action {
text: "Playlists"
expandible: true
icon.name: "music-playlist-symbolic"
children: [
Kirigami.Action {
text: "Library"
onTriggered: console.log("Playlists Library triggered")
},
Kirigami.Action {
text: "Find new playlists"
onTriggered: console.log("Playlists Find new playlists triggered")
}
]
// TODO: Generate list of playlists
}
]
}