Skip to content

Commit 4417c3a

Browse files
committed
[FEAT] lots of new things - basic cmd line PoC setup is done
1 parent 095f7fa commit 4417c3a

13 files changed

Lines changed: 709 additions & 506 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
cmake_minimum_required(VERSION 3.20)
2-
project(dirsort-test LANGUAGES CXX)
2+
project(inLimbo LANGUAGES CXX)
33

44
# -----------------------------------------------------------
55
# Build configuration

include/inlimbo/Config.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,24 @@
162162

163163
#define STATIC_ASSERT(expr, msg) static_assert((expr), msg)
164164

165+
#ifdef NDEBUG
166+
#define ASSERT_MSG(expr, msg) ((void)0)
167+
#else
168+
#define ASSERT_MSG(expr, msg) do { \
169+
if (!(expr)) { \
170+
std::ostringstream _oss; \
171+
_oss << "\n🚨 Assertion failed!\n" \
172+
<< " Expression : " << #expr << "\n" \
173+
<< " Message : " << msg << "\n" \
174+
<< " Function : " << __func__ << "\n" \
175+
<< " Location : " << __FILE__ << ":" << __LINE__ << "\n" \
176+
<< "----------- IGNORE BACKTRACE -----------\n\n"; \
177+
std::cerr << _oss.str() << std::flush; \
178+
std::abort(); \
179+
} \
180+
} while (0)
181+
#endif
182+
165183
// ============================================================
166184
// Build Config
167185
// ============================================================

include/inlimbo/audio/Playback.hpp

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,16 @@
99
#include <vector>
1010
#include <memory>
1111
#include <stdexcept>
12-
#include <cassert>
1312
#include "Logger.hpp"
1413

1514
namespace audio {
1615

16+
struct DeviceInfo {
17+
std::string name;
18+
ma_device_id id;
19+
};
20+
1721
class AudioEngine {
18-
public:
19-
struct DeviceInfo {
20-
std::string name;
21-
ma_device_id id;
22-
};
2322

2423
private:
2524
ma_context context_{};
@@ -91,7 +90,7 @@ class AudioEngine {
9190
RECORD_FUNC_TO_BACKTRACE("AudioEngine::initEngineForDevice");
9291
LOG_INFO("Initializing playback device...");
9392

94-
assert(deviceId != nullptr && "initEngineForDevice called with nullptr deviceId");
93+
ASSERT_MSG(deviceId != nullptr, "initEngineForDevice called with nullptr deviceId");
9594

9695
auto device = std::make_unique<ma_device>();
9796
auto engine = std::make_unique<ma_engine>();
@@ -105,7 +104,7 @@ class AudioEngine {
105104
deviceConfig.pUserData = nullptr;
106105

107106
ma_result result = ma_device_init(&context_, &deviceConfig, device.get());
108-
assert(result == MA_SUCCESS && "ma_device_init failed");
107+
ASSERT_MSG(result == MA_SUCCESS, "ma_device_init failed");
109108
if (result != MA_SUCCESS) {
110109
LOG_CRITICAL("Failed to initialize playback device.");
111110
throw std::runtime_error("Failed to initialize playback device");
@@ -117,18 +116,18 @@ class AudioEngine {
117116
engineConfig.noAutoStart = MA_TRUE;
118117

119118
result = ma_engine_init(&engineConfig, engine.get());
120-
assert(result == MA_SUCCESS && "ma_engine_init failed");
119+
ASSERT_MSG(result == MA_SUCCESS, "ma_engine_init failed");
121120
if (result != MA_SUCCESS) {
122121
LOG_ERROR("Failed to initialize engine for device.");
123122
ma_device_uninit(device.get());
124123
throw std::runtime_error("Failed to initialize engine for device");
125124
}
126125

127126
device->pUserData = engine.get();
128-
assert(device->pUserData == engine.get() && "pUserData pointer assignment failed!");
127+
ASSERT_MSG(device->pUserData == engine.get(), "pUserData pointer assignment failed!");
129128

130129
result = ma_engine_start(engine.get());
131-
assert(result == MA_SUCCESS && "ma_engine_start failed");
130+
ASSERT_MSG(result == MA_SUCCESS, "ma_engine_start failed");
132131
if (result != MA_SUCCESS) {
133132
LOG_ERROR("Failed to start audio engine.");
134133
ma_engine_uninit(engine.get());
@@ -141,14 +140,14 @@ class AudioEngine {
141140
devices_.push_back(std::move(device));
142141
engines_.push_back(std::move(engine));
143142

144-
assert(devices_.size() == engines_.size() && "Device/Engine arrays should match 1:1");
145-
assert(devices_.back()->pUserData != nullptr && "Device pUserData should not be null after init");
143+
ASSERT_MSG(devices_.size() == engines_.size(), "Device/Engine arrays should match 1:1");
144+
ASSERT_MSG(devices_.back()->pUserData != nullptr, "Device pUserData should not be null after init");
146145
}
147146

148147
void loadSound(const std::string& filepath, size_t engineIndex = 0) {
149148
RECORD_FUNC_TO_BACKTRACE("AudioEngine::loadSound");
150-
assert(!filepath.empty() && "Empty filepath passed to loadSound()");
151-
assert(engineIndex < engines_.size() && "Engine index out of range before loadSound");
149+
ASSERT_MSG(!filepath.empty(), "Empty filepath passed to loadSound()");
150+
ASSERT_MSG(engineIndex < engines_.size(), "Engine index out of range before loadSound");
152151

153152
LOG_INFO("Loading sound: {}", filepath);
154153

@@ -160,7 +159,7 @@ class AudioEngine {
160159
MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM,
161160
nullptr, nullptr, sound.get());
162161

163-
assert(result == MA_SUCCESS && "ma_sound_init_from_file failed");
162+
ASSERT_MSG(result == MA_SUCCESS, "ma_sound_init_from_file failed");
164163
if (result != MA_SUCCESS) {
165164
LOG_ERROR("Failed to load sound: {}", filepath);
166165
throw std::runtime_error("Failed to load sound: " + filepath);
@@ -174,26 +173,26 @@ class AudioEngine {
174173

175174
void play(size_t soundIndex = 0) {
176175
RECORD_FUNC_TO_BACKTRACE("AudioEngine::play");
177-
assert(soundIndex < sounds_.size() && "Invalid sound index in play()");
176+
ASSERT_MSG(soundIndex < sounds_.size(), "Invalid sound index in play()");
178177
LOG_INFO("Playing sound index {}", soundIndex);
179178
ma_sound_start(sounds_[soundIndex].get());
180179
}
181180

182181
void pause(size_t soundIndex = 0) {
183-
assert(soundIndex < sounds_.size() && "Invalid sound index in pause()");
182+
ASSERT_MSG(soundIndex < sounds_.size(), "Invalid sound index in pause()");
184183
LOG_INFO("Pausing sound index {}", soundIndex);
185184
ma_sound_stop(sounds_[soundIndex].get());
186185
}
187186

188187
void restart(size_t soundIndex = 0) {
189-
assert(soundIndex < sounds_.size() && "Invalid sound index in restart()");
188+
ASSERT_MSG(soundIndex < sounds_.size(), "Invalid sound index in restart()");
190189
LOG_INFO("Restarting sound index {}", soundIndex);
191190
ma_sound_seek_to_pcm_frame(sounds_[soundIndex].get(), 0);
192191
ma_sound_start(sounds_[soundIndex].get());
193192
}
194193

195194
[[nodiscard]] auto getPlaybackTime(size_t soundIndex = 0) const -> std::pair<double, double> {
196-
assert(soundIndex < sounds_.size() && "Invalid sound index in getPlaybackTime()");
195+
ASSERT_MSG(soundIndex < sounds_.size(), "Invalid sound index in getPlaybackTime()");
197196
ma_uint64 cursor{}, total{};
198197
ma_sound_get_cursor_in_pcm_frames(sounds_[soundIndex].get(), &cursor);
199198
ma_sound_get_length_in_pcm_frames(sounds_[soundIndex].get(), &total);
@@ -204,7 +203,7 @@ class AudioEngine {
204203

205204
void seekTo(double seconds, size_t soundIndex = 0) {
206205
RECORD_FUNC_TO_BACKTRACE("AudioEngine::seekTo");
207-
assert(soundIndex < sounds_.size() && "Invalid sound index in seekTo()");
206+
ASSERT_MSG(soundIndex < sounds_.size(), "Invalid sound index in seekTo()");
208207

209208
ma_uint64 frame = secondsToFrames(seconds);
210209

@@ -218,7 +217,7 @@ class AudioEngine {
218217

219218
void seekForward(double seconds, size_t soundIndex = 0) {
220219
RECORD_FUNC_TO_BACKTRACE("AudioEngine::seekForward");
221-
assert(soundIndex < sounds_.size() && "Invalid sound index in seekForward()");
220+
ASSERT_MSG(soundIndex < sounds_.size(), "Invalid sound index in seekForward()");
222221

223222
ma_uint64 offsetFrames = secondsToFrames(seconds);
224223

@@ -234,7 +233,7 @@ class AudioEngine {
234233

235234
void seekBackward(double seconds, size_t soundIndex = 0) {
236235
RECORD_FUNC_TO_BACKTRACE("AudioEngine::seekBackward");
237-
assert(soundIndex < sounds_.size() && "Invalid sound index in seekBackward()");
236+
ASSERT_MSG(soundIndex < sounds_.size(), "Invalid sound index in seekBackward()");
238237

239238
ma_uint64 offsetFrames = secondsToFrames(seconds);
240239

@@ -249,15 +248,15 @@ class AudioEngine {
249248

250249
void setVolume(float volume, size_t soundIndex = 0) {
251250
RECORD_FUNC_TO_BACKTRACE("AudioEngine::setVolume");
252-
assert(soundIndex < sounds_.size() && "Invalid sound index in setVolume()");
253-
assert(volume >= 0.0f && volume <= 1.5f && "Volume out of safe range (0.0 - 1.5)");
251+
ASSERT_MSG(soundIndex < sounds_.size(), "Invalid sound index in setVolume()");
252+
ASSERT_MSG(volume >= 0.0f && volume <= 1.5f, "Volume out of safe range (0.0 - 1.5)");
254253
LOG_INFO("Setting volume of sound {} to {:.2f}", soundIndex, volume);
255254
ma_sound_set_volume(sounds_[soundIndex].get(), volume);
256255
}
257256

258257
void printDeviceInfo(size_t deviceIndex = 0) const {
259258
RECORD_FUNC_TO_BACKTRACE("AudioEngine::printDeviceInfo");
260-
assert(deviceIndex < devices_.size() && "Invalid device index in printDeviceInfo()");
259+
ASSERT_MSG(deviceIndex < devices_.size(), "Invalid device index in printDeviceInfo()");
261260
const auto& dev = *devices_[deviceIndex];
262261
LOG_INFO("Device Info -> Name: {}, Channels: {}, SampleRate: {}",
263262
dev.playback.name, dev.playback.channels, dev.sampleRate);
@@ -281,7 +280,7 @@ class AudioEngine {
281280
sounds_.clear();
282281

283282
for (auto& engine : engines_) {
284-
assert(engine->pDevice != nullptr && "Engine has null device pointer during cleanup");
283+
ASSERT_MSG(engine->pDevice != nullptr, "Engine has null device pointer during cleanup");
285284
ma_engine_uninit(engine.get());
286285
}
287286
engines_.clear();
@@ -330,9 +329,9 @@ class AudioEngine {
330329

331330
static void dataCallback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) {
332331
(void)pInput;
333-
assert(pDevice != nullptr && "dataCallback got null device pointer");
332+
ASSERT_MSG(pDevice != nullptr, "dataCallback got null device pointer");
334333
auto* engine = recast<ma_engine*>(pDevice->pUserData);
335-
assert(engine != nullptr && "dataCallback: pUserData is null!");
334+
ASSERT_MSG(engine != nullptr, "dataCallback: pUserData is null!");
336335
ma_engine_read_pcm_frames(engine, pOutput, frameCount, nullptr);
337336
}
338337

include/inlimbo/core/SongTree.hpp

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include "Config.hpp"
34
#include "taglib/Parser.hpp"
45
#include "StackTrace.hpp"
56
#include "helpers/levenshtein.hpp"
@@ -11,7 +12,6 @@
1112

1213
#include <fstream>
1314
#include <iomanip>
14-
#include <iostream>
1515
#include <map>
1616
#include <optional>
1717
#include <set>
@@ -35,10 +35,10 @@ enum class DisplayMode {
3535
// ============================================================
3636
struct Song
3737
{
38-
unsigned int inode; /**< The inode of the file representing the song */
38+
uint inode; /**< The inode of the file representing the song */
3939
Metadata metadata; /**< Metadata information for the song */
4040

41-
Song(unsigned int inode, Metadata metadata);
41+
Song(uint inode, Metadata metadata);
4242
Song();
4343

4444
template <class Archive>
@@ -48,6 +48,24 @@ struct Song
4848
}
4949
};
5050

51+
//
52+
// NOTE:
53+
//
54+
// If you have the entire song map, use the inode map (that is NOT in the Song structure)
55+
//
56+
// If you only have the Song struct at your disposal (say for printing, etc.) just Song.inode instead.
57+
//
58+
// Theoretically there should be no difference between the two but this can be a bit confusing.
59+
//
60+
// This was initially done to account for duplicated metadata files.
61+
//
62+
using SongMap = std::map<Artist, std::map<Album, std::map<Disc, std::map<Track ,std::map<ino_t, Song>>>>>;
63+
64+
using InodeMap = std::map<ino_t, Song>;
65+
using TrackMap = std::map<Track, InodeMap>;
66+
using DiscMap = std::map<Disc, TrackMap>;
67+
using AlbumMap = std::map<Album, DiscMap>;
68+
5169
// ============================================================
5270
// SongTree Declaration (NOT THREAD SAFE)
5371
// ============================================================
@@ -56,14 +74,13 @@ struct Song
5674
// The in-memory representation used during runtime is a threads::SafeMap<SongMap>.
5775
//
5876
// This is majorly also used for cmdline querying and printing the song library.
59-
using SongMap = std::map<Artist, std::map<Album, std::map<Disc, std::map<Track, Song>>>>;
6077

6178
class SongTree
6279
{
6380
private:
64-
SongMap tree;
65-
std::string musicPath;
66-
81+
SongMap map;
82+
std::string musicPath;
83+
6784
public:
6885
// Core methods
6986
void addSong(const Song& song);
@@ -73,7 +90,7 @@ class SongTree
7390
void clear()
7491
{
7592
RECORD_FUNC_TO_BACKTRACE("SongTree::clear");
76-
tree.clear();
93+
map.clear();
7794
musicPath.clear();
7895
}
7996

@@ -83,14 +100,20 @@ class SongTree
83100
auto getSongsByArtist(const std::string& artist);
84101
[[nodiscard]] auto getSongsByAlbum(const std::string& artist, const std::string& album) const;
85102
void getSongsByGenreAndPrint() const;
86-
[[nodiscard]] auto returnSongMap() const { return tree; }
103+
[[nodiscard]] auto returnSongMap() const { return map; }
104+
// note that this replaces the entire song map and newMap is no longer valid after this call
105+
[[nodiscard]] auto newSongMap(const SongMap& newMap)
106+
{
107+
RECORD_FUNC_TO_BACKTRACE("SongTree::replaceSongMap");
108+
map = std::move(newMap);
109+
}
87110
[[nodiscard]] auto returnMusicPath() const { return musicPath; }
88111

89112
// Persistence
90113
template <class Archive>
91114
void serialize(Archive& ar)
92115
{
93-
ar(tree, musicPath);
116+
ar(map, musicPath);
94117
}
95118

96119
void saveToFile(const std::string& filename) const;

include/inlimbo/core/taglib/Parser.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class TagLibParser {
5454

5555
auto parseFile(const std::string& filePath, Metadata& metadata) -> bool;
5656
auto parseFromInode(ino_t inode, const std::string& directory) -> std::unordered_map<std::string, Metadata>;
57+
58+
auto modifyMetadata(const std::string& filePath, const Metadata& newData) -> bool;
5759

5860
private:
5961
void sendErrMsg(const std::string& errMsg);

0 commit comments

Comments
 (0)