Add files via upload

This commit is contained in:
Savsis 2026-07-07 18:19:47 +05:00 • committed by GitHub
parent 07f2ed525b
commit 6e7f0c1505
37 changed files with 4084 additions and 20 deletions

68
extras/cpp/audio_meta.hpp Normal file
View file

@ -0,0 +1,68 @@
// extras/cpp — decorative, separate from installer/installer.cpp (the real,
// functional C++ source). a tiny header-only audio-tag toy, mirroring
// app/backend/metadata.py in spirit.
#pragma once
#include <string>
#include <optional>
#include <sstream>
#include <vector>
namespace nexdex {
struct AudioTag {
std::string title;
std::string artist;
std::optional<std::string> album;
std::optional<int> year;
std::optional<int> trackNumber;
bool isComplete() const {
return !title.empty() && !artist.empty();
}
std::string describe() const {
std::ostringstream out;
out << artist << " -- " << title;
if (album) out << " [" << *album << "]";
if (year) out << " (" << *year << ")";
if (trackNumber) out << " track #" << *trackNumber;
return out.str();
}
};
class AudioTagBuilder {
public:
AudioTagBuilder(std::string title, std::string artist) {
tag_.title = std::move(title);
tag_.artist = std::move(artist);
}
AudioTagBuilder& album(std::string album) {
tag_.album = std::move(album);
return *this;
}
AudioTagBuilder& year(int year) {
tag_.year = year;
return *this;
}
AudioTagBuilder& trackNumber(int n) {
tag_.trackNumber = n;
return *this;
}
AudioTag build() const {
return tag_;
}
private:
AudioTag tag_;
};
inline std::vector<std::string> knownExtensions() {
return {"mp3", "flac", "wav", "m4a", "alac", "ogg", "opus"};
}
} // namespace nexdex

34
extras/cpp/demo.cpp Normal file
View file

@ -0,0 +1,34 @@
// extras/cpp/demo.cpp — decorative, not part of the build. compile with:
// cl.exe /std:c++17 /EHsc demo.cpp /Fe:demo.exe
// or: g++ -std=c++17 demo.cpp -o demo
#include <iostream>
#include "audio_meta.hpp"
#include "progress_bar.hpp"
#include "playlist.hpp"
int main() {
using nexdex::AudioTagBuilder;
using nexdex::ProgressBar;
using nexdex::Playlist;
using nexdex::Track;
auto tag = AudioTagBuilder("MATADORA (Extended)", "SUKA.")
.year(2026)
.build();
std::cout << tag.describe() << "\n\n";
ProgressBar bar("MATADORA (Extended)", 30);
for (int pct = 0; pct <= 100; pct += 20) {
std::cout << bar.render(pct) << "\n";
}
Playlist playlist;
playlist.add(Track{tag, "downloads/MATADORA (Extended).flac", 222});
std::cout << "\nplaylist: " << playlist.size() << " track(s), total "
<< Playlist::formatDuration(playlist.totalDurationSecs()) << "\n";
std::cout << "\nmade by savsis with <3\n";
return 0;
}

79
extras/cpp/playlist.hpp Normal file
View file

@ -0,0 +1,79 @@
// extras/cpp — decorative. mirrors extras/rust/src/playlist.rs, just in
// C++: a tiny in-memory playlist model with no real I/O.
#pragma once
#include <vector>
#include <string>
#include <algorithm>
#include <optional>
#include <numeric>
#include "audio_meta.hpp"
namespace nexdex {
struct Track {
AudioTag tag;
std::string path;
int durationSecs = 0;
};
class Playlist {
public:
void add(Track track) {
tracks_.push_back(std::move(track));
}
size_t size() const { return tracks_.size(); }
bool empty() const { return tracks_.empty(); }
int totalDurationSecs() const {
return std::accumulate(
tracks_.begin(), tracks_.end(), 0,
[](int sum, const Track& t) { return sum + t.durationSecs; });
}
std::vector<const Track*> byArtist(const std::string& artist) const {
std::vector<const Track*> result;
for (const auto& t : tracks_) {
if (equalsIgnoreCase(t.tag.artist, artist)) {
result.push_back(&t);
}
}
return result;
}
std::optional<const Track*> longest() const {
if (tracks_.empty()) return std::nullopt;
auto it = std::max_element(
tracks_.begin(), tracks_.end(),
[](const Track& a, const Track& b) { return a.durationSecs < b.durationSecs; });
return &(*it);
}
static std::string formatDuration(int totalSecs) {
int hours = totalSecs / 3600;
int minutes = (totalSecs % 3600) / 60;
int seconds = totalSecs % 60;
char buf[32];
if (hours > 0) {
snprintf(buf, sizeof(buf), "%d:%02d:%02d", hours, minutes, seconds);
} else {
snprintf(buf, sizeof(buf), "%d:%02d", minutes, seconds);
}
return std::string(buf);
}
private:
static bool equalsIgnoreCase(const std::string& a, const std::string& b) {
if (a.size() != b.size()) return false;
return std::equal(a.begin(), a.end(), b.begin(), [](char x, char y) {
return std::tolower(static_cast<unsigned char>(x)) ==
std::tolower(static_cast<unsigned char>(y));
});
}
std::vector<Track> tracks_;
};
} // namespace nexdex

View file

@ -0,0 +1,31 @@
// extras/cpp — decorative. a tiny console progress bar, echoing the shape
// of the /api/job/<id> polling response from backend/jobs.py.
#pragma once
#include <string>
#include <algorithm>
namespace nexdex {
class ProgressBar {
public:
ProgressBar(std::string label, int width) : label_(std::move(label)), width_(width) {}
std::string render(int percent) const {
percent = std::clamp(percent, 0, 100);
int filled = width_ * percent / 100;
int empty = width_ - filled;
std::string bar;
bar.append(filled, '#');
bar.append(empty, '-');
return label_ + " [" + bar + "] " + std::to_string(percent) + "%";
}
private:
std::string label_;
int width_;
};
} // namespace nexdex