rewrite recursive song search
This commit is contained in:
parent
907a53a5b4
commit
c09b5d49c4
@ -21,7 +21,8 @@ dependencies = [
|
||||
dependency('gl'),
|
||||
cc.find_library('atomic'),
|
||||
dependency('nowide'),
|
||||
dependency('nlohmann_json')
|
||||
dependency('nlohmann_json'),
|
||||
dependency('fmt')
|
||||
]
|
||||
|
||||
if host_machine.system() == 'linux'
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "Preferences.hpp"
|
||||
#include "fmt/core.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
@ -82,8 +83,8 @@ namespace Data {
|
||||
prefs_file >> j;
|
||||
j.get_to(*this);
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Error while loading data/preferences.json : " << e.what() << '\n';
|
||||
std::cerr << "Using fallback preferences instead" << '\n';
|
||||
fmt::print("Error while loading data/preferences.json : {}\n", e.what());
|
||||
fmt::print("Using fallback preferences instead\n");
|
||||
return;
|
||||
}
|
||||
key_mapping = Input::KeyMapping{key_mapping.m_button_to_key};
|
||||
|
@ -1,17 +1,20 @@
|
||||
#include "Song.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <ranges>
|
||||
#include <span>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <memon/memon.hpp>
|
||||
|
||||
#include "../Toolkit/UTF8Strings.hpp"
|
||||
#include "../Toolkit/UTF8SFMLRedefinitions.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Data {
|
||||
|
||||
bool cmp_dif_name::operator()(const std::string &a, const std::string &b) const {
|
||||
@ -46,58 +49,30 @@ namespace Data {
|
||||
}
|
||||
}
|
||||
|
||||
SongList::SongList(const std::filesystem::path& jujube_path) :
|
||||
songs()
|
||||
{
|
||||
std::filesystem::path song_folder = jujube_path/"songs";
|
||||
SongList load_song_list(const std::filesystem::path& jujube_path) {
|
||||
SongList songs;
|
||||
const std::filesystem::path song_folder = jujube_path / "songs";
|
||||
if (not std::filesystem::is_directory(song_folder)) {
|
||||
fmt::print(
|
||||
"Tried searching for songs in {} but the folder does not exist !\n",
|
||||
path_to_utf8_encoded_string(song_folder)
|
||||
);
|
||||
return songs;
|
||||
}
|
||||
|
||||
if (std::filesystem::exists(song_folder) and std::filesystem::is_directory(song_folder)) {
|
||||
for (const auto& dir_item : std::filesystem::directory_iterator(song_folder)) {
|
||||
if (dir_item.is_directory()) {
|
||||
songs.splice(songs.end(), recursiveSongSearch(dir_item.path()));
|
||||
}
|
||||
for (const auto& dir_entry : std::filesystem::recursive_directory_iterator(song_folder)) {
|
||||
if (not dir_entry.is_regular_file() or dir_entry.path().extension() != ".memon") {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
std::cout << "Loaded Data::SongList, found " << songs.size() << " songs" << '\n';
|
||||
}
|
||||
|
||||
std::list<std::shared_ptr<Song>> recursiveSongSearch(std::filesystem::path song_or_pack) {
|
||||
std::list<std::shared_ptr<Song>> res;
|
||||
|
||||
// First try : any .memo file in the folder ?
|
||||
std::filesystem::directory_iterator folder_memo{song_or_pack};
|
||||
if (
|
||||
std::any_of(
|
||||
std::filesystem::begin(folder_memo),
|
||||
std::filesystem::end(folder_memo),
|
||||
[](const std::filesystem::directory_entry& de) {return de.path().extension() == ".memo";}
|
||||
)
|
||||
) {
|
||||
throw std::invalid_argument("jujube does not support .memo files for now ...");
|
||||
}
|
||||
|
||||
// Second try : any .memon file in the folder ?
|
||||
// if yes get the first one
|
||||
std::filesystem::directory_iterator folder_memon{song_or_pack};
|
||||
auto memon_path = std::find_if(
|
||||
std::filesystem::begin(folder_memon),
|
||||
std::filesystem::end(folder_memon),
|
||||
[](const std::filesystem::directory_entry& de) {return de.path().extension() == ".memon";}
|
||||
);
|
||||
if (memon_path != std::filesystem::end(folder_memon)) {
|
||||
auto song = std::make_shared<MemonSong>(memon_path->path());
|
||||
auto song = std::make_shared<MemonSong>(dir_entry.path());
|
||||
if (not song->chart_levels.empty()) {
|
||||
res.push_back(song);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
// Nothing found : recurse in subfolders
|
||||
for (auto& p : std::filesystem::directory_iterator(song_or_pack)) {
|
||||
if (p.is_directory()) {
|
||||
res.splice(res.end(), recursiveSongSearch(p));
|
||||
songs.push_back(song);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
||||
fmt::print("Loaded song list, found {} songs\n", songs.size());
|
||||
|
||||
return songs;
|
||||
}
|
||||
|
||||
TimeBounds SongDifficulty::get_time_bounds() const {
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
#include <filesystem>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#include <SFML/Audio.hpp>
|
||||
@ -80,20 +80,12 @@ namespace Data {
|
||||
|
||||
/*
|
||||
struct MemoSong : public Song {
|
||||
explicit MemoSong(const std::unordered_map<std::string, fs::path>& memo_paths);
|
||||
explicit MemoSong(const std::unordered_map<std::string, std::filesystem::path>& memo_paths);
|
||||
private:
|
||||
std::unordered_map<std::string, fs::path> memo_paths;
|
||||
std::unordered_map<std::string, std::filesystem::path> memo_paths;
|
||||
};
|
||||
*/
|
||||
|
||||
// Class holding all the necessary song data to run the Music Select screen
|
||||
class SongList {
|
||||
public:
|
||||
SongList(const std::filesystem::path& jujube_path);
|
||||
std::list<std::shared_ptr<Song>> songs;
|
||||
};
|
||||
|
||||
// Returns the folders conscidered to contain a valid song
|
||||
// classic memo files should have the .memo extension
|
||||
std::list<std::shared_ptr<Song>> recursiveSongSearch(std::filesystem::path song_or_pack);
|
||||
using SongList = std::vector<std::shared_ptr<Song>>;
|
||||
SongList load_song_list(const std::filesystem::path& jujube_path);
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "Screens/Results/Results.hpp"
|
||||
|
||||
#include "Toolkit/UTF8Strings.hpp"
|
||||
#include "fmt/core.h"
|
||||
|
||||
#if defined(__unix__) && defined(__linux__)
|
||||
#include <X11/Xlib.h>
|
||||
@ -35,7 +36,7 @@ int main() {
|
||||
// Load prefs, music, markers
|
||||
const std::filesystem::path jujube_path = utf8_encoded_string_to_path(whereami::executable_dir());
|
||||
Data::Preferences preferences{jujube_path};
|
||||
Data::SongList song_list{jujube_path};
|
||||
auto song_list = Data::load_song_list(jujube_path);
|
||||
Resources::SharedResources shared_resources{preferences};
|
||||
MusicSelect::ScreenResources music_select_resources{shared_resources};
|
||||
if (shared_resources.markers.find(preferences.options.marker) == shared_resources.markers.end()) {
|
||||
@ -64,9 +65,9 @@ int main() {
|
||||
while (window.isOpen()) {
|
||||
auto chart = music_select.select_chart(window);
|
||||
if (chart) {
|
||||
std::cout << "Selected Chart : " << chart->song.title << " [" << chart->difficulty << "]" << '\n';
|
||||
fmt::print("Selected Chart : {} [{}]\n", chart->song.title, chart->difficulty);
|
||||
} else {
|
||||
std::cout << "Exited MusicSelect::Screen without selecting a chart" << '\n';
|
||||
fmt::print("Exited MusicSelect::Screen without selecting a chart\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -5,13 +5,13 @@
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Resources {
|
||||
LNMarker::LNMarker(const fs::path& t_folder) :
|
||||
LNMarker::LNMarker(const std::filesystem::path& t_folder) :
|
||||
folder(t_folder)
|
||||
{
|
||||
if (not fs::is_directory(folder)) {
|
||||
if (not std::filesystem::is_directory(folder)) {
|
||||
throw std::invalid_argument(folder.string()+" is not a folder");
|
||||
}
|
||||
if (not fs::exists(folder/"long.json")) {
|
||||
if (not std::filesystem::exists(folder/"long.json")) {
|
||||
throw std::invalid_argument("LNMarker folder ( "+folder.string()+" ) has no long.json file");
|
||||
}
|
||||
std::ifstream marker_json{folder/"long.json"};
|
||||
@ -128,7 +128,7 @@ namespace Resources {
|
||||
j.at("tip").at("cycle").get_to(m.tip_cycle);
|
||||
}
|
||||
|
||||
LNMarkers::LNMarkers(const fs::path& jujube_path) {
|
||||
LNMarkers::LNMarkers(const std::filesystem::path& jujube_path) {
|
||||
load_from_folder(jujube_path/"markers"/"long");
|
||||
load_from_folder(jujube_path/"assets"/"markers"/"long");
|
||||
if (empty()) {
|
||||
@ -136,9 +136,9 @@ namespace Resources {
|
||||
}
|
||||
}
|
||||
|
||||
void LNMarkers::load_from_folder(const fs::path& lnmarkers_folder) {
|
||||
if (fs::exists(lnmarkers_folder)) {
|
||||
for (auto& p : fs::directory_iterator(lnmarkers_folder)) {
|
||||
void LNMarkers::load_from_folder(const std::filesystem::path& lnmarkers_folder) {
|
||||
if (std::filesystem::exists(lnmarkers_folder)) {
|
||||
for (auto& p : std::filesystem::directory_iterator(lnmarkers_folder)) {
|
||||
if (p.is_directory()) {
|
||||
try {
|
||||
LNMarker m{p.path()};
|
||||
|
@ -11,11 +11,9 @@
|
||||
#include "SpriteSheet.hpp"
|
||||
#include "SplitSpriteSheet.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Resources {
|
||||
struct LNMarker {
|
||||
LNMarker(const fs::path& folder);
|
||||
LNMarker(const std::filesystem::path& folder);
|
||||
|
||||
std::optional<sf::Sprite> get_tail_sprite(sf::Time delta) const;
|
||||
|
||||
@ -29,7 +27,7 @@ namespace Resources {
|
||||
std::optional<sf::Sprite> get_highlight_sprite(sf::Time delta) const;
|
||||
|
||||
|
||||
fs::path folder;
|
||||
std::filesystem::path folder;
|
||||
std::string name;
|
||||
std::size_t fps;
|
||||
std::size_t size;
|
||||
@ -46,8 +44,8 @@ namespace Resources {
|
||||
|
||||
class LNMarkers : public std::map<std::string, LNMarker> {
|
||||
public:
|
||||
LNMarkers(const fs::path& jujube_path);
|
||||
LNMarkers(const std::filesystem::path& jujube_path);
|
||||
private:
|
||||
void load_from_folder(const fs::path& lnmarkers_folder);
|
||||
void load_from_folder(const std::filesystem::path& lnmarkers_folder);
|
||||
};
|
||||
}
|
@ -8,8 +8,6 @@
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Resources {
|
||||
|
||||
void from_json(const nlohmann::json& j, Marker& m) {
|
||||
@ -24,13 +22,13 @@ namespace Resources {
|
||||
j.at("perfect").get_to(m.perfect);
|
||||
}
|
||||
|
||||
Marker::Marker(const fs::path& marker_folder) :
|
||||
Marker::Marker(const std::filesystem::path& marker_folder) :
|
||||
folder(marker_folder)
|
||||
{
|
||||
if (not fs::is_directory(folder)) {
|
||||
if (not std::filesystem::is_directory(folder)) {
|
||||
throw std::invalid_argument(folder.string()+" is not a folder");
|
||||
}
|
||||
if (not fs::exists(folder/"marker.json")) {
|
||||
if (not std::filesystem::exists(folder/"marker.json")) {
|
||||
throw std::invalid_argument("Marker folder ( "+folder.string()+" ) has no marker.json file");
|
||||
}
|
||||
std::ifstream marker_json{folder/"marker.json"};
|
||||
@ -96,7 +94,7 @@ namespace Resources {
|
||||
return sprite_sheet.get_sprite(frame, size);
|
||||
}
|
||||
|
||||
Markers::Markers(const fs::path& jujube_path) {
|
||||
Markers::Markers(const std::filesystem::path& jujube_path) {
|
||||
load_from_folder(jujube_path/"markers"/"tap");
|
||||
load_from_folder(jujube_path/"assets"/"markers"/"tap");
|
||||
if (empty()) {
|
||||
@ -104,9 +102,9 @@ namespace Resources {
|
||||
}
|
||||
}
|
||||
|
||||
void Markers::load_from_folder(const fs::path& markers_folder) {
|
||||
if (fs::exists(markers_folder)) {
|
||||
for (auto& p : fs::directory_iterator(markers_folder)) {
|
||||
void Markers::load_from_folder(const std::filesystem::path& markers_folder) {
|
||||
if (std::filesystem::exists(markers_folder)) {
|
||||
for (auto& p : std::filesystem::directory_iterator(markers_folder)) {
|
||||
if (p.is_directory()) {
|
||||
try {
|
||||
Marker m{p.path()};
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
#include "SpriteSheet.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Resources {
|
||||
enum class MarkerAnimation {
|
||||
APPROACH,
|
||||
@ -23,13 +21,13 @@ namespace Resources {
|
||||
};
|
||||
|
||||
struct Marker {
|
||||
explicit Marker(const fs::path& marker_folder);
|
||||
explicit Marker(const std::filesystem::path& marker_folder);
|
||||
std::optional<sf::Sprite> get_sprite(const MarkerAnimation& state, const sf::Time seconds) const;
|
||||
std::optional<sf::Sprite> get_sprite(const MarkerAnimation& state, const float seconds) const;
|
||||
std::optional<sf::Sprite> get_sprite(const MarkerAnimation& state, const std::size_t frame) const;
|
||||
const SpriteSheet& get_sprite_sheet_from_enum(const MarkerAnimation& state) const;
|
||||
|
||||
fs::path folder;
|
||||
std::filesystem::path folder;
|
||||
std::string name;
|
||||
std::size_t size; // the side length in pixels
|
||||
std::size_t fps; // classic jubeat markers are 30 fps
|
||||
@ -45,8 +43,8 @@ namespace Resources {
|
||||
|
||||
class Markers : public std::map<std::string, Marker> {
|
||||
public:
|
||||
Markers(const fs::path& jujube_path);
|
||||
Markers(const std::filesystem::path& jujube_path);
|
||||
private:
|
||||
void load_from_folder(const fs::path& markers_folder);
|
||||
void load_from_folder(const std::filesystem::path& markers_folder);
|
||||
};
|
||||
}
|
||||
|
@ -7,14 +7,14 @@
|
||||
|
||||
namespace Resources {
|
||||
void from_json(const nlohmann::json& j, SplitSpriteSheet& s) {
|
||||
s.tex_path = fs::path{j.at("sprite_sheet").get<std::string>()};
|
||||
s.tex_path = std::filesystem::path{j.at("sprite_sheet").get<std::string>()};
|
||||
j.at("count").get_to(s.count);
|
||||
j.at("columns").get_to(s.columns);
|
||||
j.at("rows").get_to(s.rows);
|
||||
}
|
||||
|
||||
void SplitSpriteSheet::load_and_check(
|
||||
const fs::path& folder,
|
||||
const std::filesystem::path& folder,
|
||||
std::size_t size,
|
||||
std::size_t fps,
|
||||
const Toolkit::DurationInFrames& max_duration
|
||||
|
@ -9,20 +9,18 @@
|
||||
|
||||
#include "../Toolkit/DurationInFrames.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Resources {
|
||||
// SpriteSheet where individual sprites get their own texture
|
||||
// (when you cant to tile an animated sprite for ex.)
|
||||
struct SplitSpriteSheet {
|
||||
std::vector<sf::Texture> textures;
|
||||
fs::path tex_path;
|
||||
std::filesystem::path tex_path;
|
||||
std::size_t count;
|
||||
std::size_t columns;
|
||||
std::size_t rows;
|
||||
|
||||
void load_and_check(
|
||||
const fs::path& folder,
|
||||
const std::filesystem::path& folder,
|
||||
std::size_t size,
|
||||
std::size_t fps,
|
||||
const Toolkit::DurationInFrames& max_duration
|
||||
|
@ -5,14 +5,14 @@
|
||||
|
||||
namespace Resources {
|
||||
void from_json(const nlohmann::json& j, SpriteSheet& s) {
|
||||
s.tex_path = fs::path{j.at("sprite_sheet").get<std::string>()};
|
||||
s.tex_path = std::filesystem::path{j.at("sprite_sheet").get<std::string>()};
|
||||
j.at("count").get_to(s.count);
|
||||
j.at("columns").get_to(s.columns);
|
||||
j.at("rows").get_to(s.rows);
|
||||
}
|
||||
|
||||
void SpriteSheet::load_and_check(
|
||||
const fs::path& folder,
|
||||
const std::filesystem::path& folder,
|
||||
std::size_t size,
|
||||
std::size_t fps,
|
||||
const Toolkit::DurationInFrames& max_duration
|
||||
|
@ -9,18 +9,16 @@
|
||||
|
||||
#include "../Toolkit/DurationInFrames.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace Resources {
|
||||
struct SpriteSheet {
|
||||
sf::Texture tex;
|
||||
fs::path tex_path;
|
||||
std::filesystem::path tex_path;
|
||||
std::size_t count;
|
||||
std::size_t columns;
|
||||
std::size_t rows;
|
||||
|
||||
void load_and_check(
|
||||
const fs::path& folder,
|
||||
const std::filesystem::path& folder,
|
||||
std::size_t size,
|
||||
std::size_t fps,
|
||||
const Toolkit::DurationInFrames& max_duration
|
||||
|
@ -7,7 +7,7 @@ namespace MusicSelect {
|
||||
|
||||
std::mutex openFromFile_mutex;
|
||||
|
||||
MusicLoop::MusicLoop(fs::path music_path, std::optional<sf::Music::TimeSpan> t_loop) {
|
||||
MusicLoop::MusicLoop(std::filesystem::path music_path, std::optional<sf::Music::TimeSpan> t_loop) {
|
||||
music = std::make_unique<sf::Music>();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{openFromFile_mutex};
|
||||
@ -33,7 +33,7 @@ namespace MusicSelect {
|
||||
};
|
||||
}
|
||||
|
||||
void MusicPreview::play_async(std::optional<fs::path> music_path, std::optional<sf::Music::TimeSpan> loop) {
|
||||
void MusicPreview::play_async(std::optional<std::filesystem::path> music_path, std::optional<sf::Music::TimeSpan> loop) {
|
||||
if (not music_path.has_value()) {
|
||||
return;
|
||||
}
|
||||
@ -53,7 +53,7 @@ namespace MusicSelect {
|
||||
}
|
||||
}
|
||||
|
||||
void MusicPreview::play(std::optional<fs::path> music_path, std::optional<sf::Music::TimeSpan> loop) {
|
||||
void MusicPreview::play(std::optional<std::filesystem::path> music_path, std::optional<sf::Music::TimeSpan> loop) {
|
||||
std::thread(&MusicPreview::play_async, this, music_path, loop).detach();
|
||||
}
|
||||
|
||||
|
@ -9,13 +9,11 @@
|
||||
|
||||
#include "../../Toolkit/AffineTransform.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
// In this file define stuff to try to handle creating sf::Music objects
|
||||
// and starting their playback asynchronously while trying to keep some thread-safety
|
||||
namespace MusicSelect {
|
||||
struct MusicLoop {
|
||||
MusicLoop(fs::path music_path, std::optional<sf::Music::TimeSpan> t_loop);
|
||||
MusicLoop(std::filesystem::path music_path, std::optional<sf::Music::TimeSpan> t_loop);
|
||||
std::unique_ptr<sf::Music> music;
|
||||
sf::Music::TimeSpan loop;
|
||||
Toolkit::AffineTransform<float> fade_out = {0.f, 1.f, 0.f, 1.f}; // placeholder value
|
||||
@ -23,11 +21,11 @@ namespace MusicSelect {
|
||||
class MusicPreview {
|
||||
public:
|
||||
MusicPreview() = default;
|
||||
void play(std::optional<fs::path> music_path, std::optional<sf::Music::TimeSpan> loop);
|
||||
void play(std::optional<std::filesystem::path> music_path, std::optional<sf::Music::TimeSpan> loop);
|
||||
void stop();
|
||||
void update();
|
||||
private:
|
||||
void play_async(std::optional<fs::path> music_path, std::optional<sf::Music::TimeSpan> loop);
|
||||
void play_async(std::optional<std::filesystem::path> music_path, std::optional<sf::Music::TimeSpan> loop);
|
||||
std::optional<MusicLoop> m_music_loop;
|
||||
std::mutex m_music_loop_mutex;
|
||||
};
|
||||
|
@ -13,10 +13,10 @@
|
||||
#include "Panels/Panel.hpp"
|
||||
#include "PanelLayout.hpp"
|
||||
|
||||
MusicSelect::Screen::Screen(const Data::SongList& t_song_list, ScreenResources& t_resources) :
|
||||
MusicSelect::Screen::Screen(const Data::SongList& song_list_, ScreenResources& t_resources) :
|
||||
HoldsResources(t_resources),
|
||||
song_list(t_song_list),
|
||||
ribbon(PanelLayout::title_sort(t_song_list, t_resources), t_resources),
|
||||
song_list(song_list_),
|
||||
ribbon(PanelLayout::title_sort(song_list_, t_resources), t_resources),
|
||||
song_info(t_resources),
|
||||
main_option_page(t_resources),
|
||||
options_button(t_resources),
|
||||
|
@ -27,7 +27,7 @@ namespace MusicSelect {
|
||||
// it loads a cache of available songs in the song_list attribute
|
||||
class Screen : public Toolkit::Debuggable, public HoldsResources {
|
||||
public:
|
||||
Screen(const Data::SongList& t_song_list, ScreenResources& t_resources);
|
||||
Screen(const Data::SongList& song_list, ScreenResources& t_resources);
|
||||
std::optional<Data::SongDifficulty> select_chart(sf::RenderWindow& window);
|
||||
void draw_debug(sf::RenderWindow& window);
|
||||
private:
|
||||
|
@ -59,10 +59,7 @@ namespace MusicSelect {
|
||||
}
|
||||
|
||||
PanelLayout PanelLayout::title_sort(const Data::SongList& song_list, ScreenResources& t_resources) {
|
||||
std::vector<std::shared_ptr<const Data::Song>> songs;
|
||||
for (auto &&song : song_list.songs) {
|
||||
songs.push_back(song);
|
||||
}
|
||||
Data::SongList songs = song_list;
|
||||
std::sort(
|
||||
songs.begin(),
|
||||
songs.end(),
|
||||
|
13
subprojects/fmt.wrap
Normal file
13
subprojects/fmt.wrap
Normal file
@ -0,0 +1,13 @@
|
||||
[wrap-file]
|
||||
directory = fmt-9.1.0
|
||||
source_url = https://github.com/fmtlib/fmt/archive/9.1.0.tar.gz
|
||||
source_filename = fmt-9.1.0.tar.gz
|
||||
source_hash = 5dea48d1fcddc3ec571ce2058e13910a0d4a6bab4cc09a809d8b1dd1c88ae6f2
|
||||
patch_filename = fmt_9.1.0-2_patch.zip
|
||||
patch_url = https://wrapdb.mesonbuild.com/v2/fmt_9.1.0-2/get_patch
|
||||
patch_hash = 23e8c4829f3e63f509b5643fe6bb87cbed39eae9594c451b338475d14d051967
|
||||
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/fmt_9.1.0-2/fmt-9.1.0.tar.gz
|
||||
wrapdb_version = 9.1.0-2
|
||||
|
||||
[provide]
|
||||
fmt = fmt_dep
|
Loading…
x
Reference in New Issue
Block a user