Skip to content

Commit f01850e

Browse files
committed
[MINOR] New cmd-line-arg + fix taglib addn prop issue + completions
1 parent 689e1e3 commit f01850e

10 files changed

+193
-96
lines changed

README.md

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -159,43 +159,56 @@ inLimbo --update-cache-run --print-song-tree # will create a new song map and pr
159159

160160
Note that this will result in slower song map times as the song map is generated dynamically on each run.
161161

162-
---
163-
164162
## **Command-Line Arguments**
165163

166-
### `--help`
164+
- `--help`
167165
**Description**: Display help information about available arguments for inLimbo.
168166

169-
### `--version`
167+
- `--version`
170168
**Description**: Display the version number of inLimbo.
171169

172-
### `--clear-cache`
170+
- `--clear-cache`
173171
**Description**: Clear cached data, which includes the song map and other temporary data stored by the application.
174172

175-
### `--show-config-file`
173+
- `--show-config-file`
176174
**Description**: Display the path to the configuration file used by inLimbo.
177175

178-
### `--show-log-dir`
176+
- `--show-log-dir`
179177
**Description**: Show the directory path where logs are stored for inLimbo.
180178

181-
### `--show-dbus-name`
179+
- `--show-dbus-name`
182180
**Description**: Show the DBus service name used by inLimbo.
183181

184-
### `--update-cache-run`
182+
- `--update-cache-run`
185183
**Description**: Update the cache file and run the application. This will make inLimbo load the directory dynamically every time (note that this will result in slower song map times).
186184

187-
### `--print-song-tree`
185+
- `--print-song-tree`
188186
**Description**: Print the song map parsed from the directory. This shows the structure of the song tree and how songs are organized.
189187

190-
### `--print-artists-all`
188+
- `--print-artists-all`
191189
**Description**: Print all parsed artists from the song map. This will list all artists found in the directory and their corresponding songs.
192190

193-
### `--print-songs-by-artist`
191+
- `--print-songs-by-artist`
194192
**Description**: Print all the songs of a given artist. This argument requires you to specify the artist’s name, and it will list all songs by that artist.
195193

196-
### `--print-songs-by-genre-all`
194+
- `--print-songs-by-genre-all`
197195
**Description**: Print all parsed genres and their song mappings. This will show all the genres available in the song map and list songs under each genre.
198196

197+
- `--print-song-info`
198+
**Description**: Print every parsed information (even default info) regarding a song (Arguments: Can take **SONG NAME** or **FILE PATH**)
199+
200+
> [!NOTE]
201+
>
202+
> To utilize these arguments to the fullest, it is **HIGHLY** recommended to use something like `less`/`bat`
203+
> that allows for neat terminal output traversal (will allow for you to view the entire song tree parsing)
204+
>
205+
> ```bash
206+
> inLimbo --print-song-tree | bat # an example of using bat to view the song tree (can traverse the output easily)
207+
> ```
208+
>
209+
> This ensures that you do not have any struggle with viewing the entire console output.
210+
>
211+
199212
There will be more command-line arguments in the future...
200213
201214
## **CONFIGURATION**
@@ -231,8 +244,6 @@ There is quite a lot to configure in the inLimbo project. A basic config file wi
231244
| `?` | **Show or hide the help menu** |
232245
| `/` | **Open the search menu** |
233246
234-
---
235-
236247
### **Scrolling and Selection**
237248
| Keybind | Action |
238249
|---------|--------|
@@ -241,8 +252,6 @@ There is quite a lot to configure in the inLimbo project. A basic config file wi
241252
| `0` | **Move to the next search result** (if search is active) |
242253
| `9` | **Move to the previous search result** (if search is active) |
243254
244-
---
245-
246255
### **Playback Controls**
247256
| Keybind | Action |
248257
|---------|--------|
@@ -253,8 +262,6 @@ There is quite a lot to configure in the inLimbo project. A basic config file wi
253262
| `r` | **Replay the current song** |
254263
| `m` | **Toggle mute** on/off |
255264
256-
---
257-
258265
### **Seeking and Volume Control**
259266
| Keybind | Action |
260267
|---------|--------|
@@ -264,8 +271,6 @@ There is quite a lot to configure in the inLimbo project. A basic config file wi
264271
| `-` | **Decrease volume** |
265272
| `w` | **Toggle between available audio devices** |
266273
267-
---
268-
269274
### **Song and Queue Management**
270275
| Keybind | Action |
271276
|---------|--------|
@@ -275,17 +280,13 @@ There is quite a lot to configure in the inLimbo project. A basic config file wi
275280
| `d` | **Remove the currently selected song from the queue** |
276281
| `3` | **View the current song queue** |
277282
278-
---
279-
280283
### **Song Information and UI Navigation**
281284
| Keybind | Action |
282285
|---------|--------|
283286
| `1` | **Go to the main UI screen** |
284287
| `2` or `L` | **View lyrics of the currently playing song** |
285288
| `i` | **View detailed information about the current song** |
286289
287-
---
288-
289290
### **Status Bar & UI Settings**
290291
| Keybind | Action |
291292
|---------|--------|

assets/completions/inLimbo-completions.bash

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ _inLimbo_completions() {
1818
"--print-artists-all Print all parsed artists from Song Map"
1919
"--print-songs-by-artist Print all the songs of a given artist"
2020
"--print-songs-by-genre-all Print all parsed genre and their song mappings"
21+
"--print-song-info Print every parsed field of a song name / filepath"
2122
)
2223

2324
# Provide completion for options

assets/completions/inLimbo-completions.fish

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ function _inLimbo_completions
1111
"--print-song-tree" "Print the Song Map parsed from directory" \
1212
"--print-artists-all" "Print all parsed artists from Song Map" \
1313
"--print-songs-by-artist" "Print all the songs of a given artist" \
14-
"--print-songs-by-genre-all" "Print all parsed genre and their song mappings"
14+
"--print-songs-by-genre-all" "Print all parsed genre and their song mappings" \
15+
"--print-song-info" "Print every parsed field of a song name / filepath"
1516
for i in (seq 1 2 (count $opts))
1617
set -l opt (string trim -- $opts[$i])
1718
set -l desc $opts[(math $i + 1)]

assets/completions/inLimbo-completions.zsh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ _inLimbo_completions() {
1212
"--print-artists-all:Print all parsed artists from Song Map"
1313
"--print-songs-by-artist:Print all the songs of a given artist"
1414
"--print-songs-by-genre-all:Print all parsed genre and their song mappings"
15+
"--print-song-info:Print every parsed field of a song name / filepath"
1516
)
1617
_describe -t options "inLimbo options" opts
1718
}

src/arg-handler.hpp

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ struct SongTreeState
3131
bool printArtistsAll = false;
3232
bool printSongsByArtist = false;
3333
bool printSongsGenreAll = false;
34+
bool printSongInfo = false;
3435
std::string artist;
36+
std::string song;
3537
};
3638

3739
/**
@@ -129,7 +131,8 @@ class ArgumentHandler
129131
{"--print-artists-all", [&]() { handlePrintArtistsAll(); }},
130132
{"--print-songs-by-genre-all", [&]() { handlePrintSongsByGenreAll(); }},
131133
{"--print-songs-by-artist",
132-
[&]() { handlePrintSongsByArtist(cmdArgs.get("--print-songs-by-artist")); }}};
134+
[&]() { handlePrintSongsByArtist(cmdArgs.get("--print-songs-by-artist")); }},
135+
{"--print-song-info", [&]() { handleSongInfo(cmdArgs.get("--print-song-info")); }}};
133136

134137
for (const auto& [flag, handler] : argumentHandlers)
135138
{
@@ -163,6 +166,10 @@ class ArgumentHandler
163166
{
164167
song_tree.getSongsByGenreAndPrint();
165168
}
169+
if (ArgumentHandler::song_tree_parse_state.printSongInfo)
170+
{
171+
song_tree.printSongInfo(ArgumentHandler::song_tree_parse_state.song);
172+
}
166173
}
167174

168175
private:
@@ -286,31 +293,39 @@ class ArgumentHandler
286293
shouldRunApp = true;
287294
}
288295

296+
static void parseSongMap()
297+
{
298+
parseSongTree = true;
299+
shouldRunApp = true;
300+
}
301+
289302
static void handlePrintSongTree()
290303
{
291-
parseSongTree = true;
292304
song_tree_parse_state.printSongTree = true;
293-
shouldRunApp = true;
305+
parseSongMap();
294306
}
295307

296308
static void handlePrintArtistsAll()
297309
{
298-
parseSongTree = true;
299-
shouldRunApp = true;
310+
parseSongMap();
300311
song_tree_parse_state.printArtistsAll = true;
301312
}
302313

303314
static void handlePrintSongsByArtist(std::string artistName)
304315
{
305-
parseSongTree = true;
306-
shouldRunApp = true;
316+
parseSongMap();
307317
song_tree_parse_state.printSongsByArtist = true;
308318
song_tree_parse_state.artist = artistName;
309319
}
310320
static void handlePrintSongsByGenreAll()
311321
{
312-
parseSongTree = true;
313-
shouldRunApp = true;
322+
parseSongMap();
314323
song_tree_parse_state.printSongsGenreAll = true;
315324
}
325+
static void handleSongInfo(std::string songName)
326+
{
327+
parseSongMap();
328+
song_tree_parse_state.printSongInfo = true;
329+
song_tree_parse_state.song = songName;
330+
}
316331
};

src/cmd-line-args.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,4 +241,5 @@ const std::vector<std::string> CommandLineArgs::validFlags = {"--help",
241241
"--print-song-tree",
242242
"--print-songs-by-artist",
243243
"--print-songs-by-genre-all",
244+
"--print-song-info",
244245
"--print-artists-all"};

src/dirsort/songmap.hpp

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@
2121
#pragma once
2222

2323
#include "taglib_parser.h"
24+
#include "../helpers/levenshtein.hpp"
2425
#include <cereal/archives/binary.hpp>
2526
#include <cereal/types/map.hpp>
2627
#include <cereal/types/string.hpp>
2728
#include <cereal/types/vector.hpp>
2829
#include <fstream>
2930
#include <iostream>
3031
#include <map>
32+
#include <optional>
3133
#include <set>
3234
#include <string>
3335
#include <vector>
@@ -381,4 +383,122 @@ class SongTree
381383
cereal::BinaryInputArchive archive(file);
382384
archive(*this); // Deserialize the SongTree
383385
}
386+
387+
/**
388+
* @brief Prints metadata and additional properties of a song.
389+
*
390+
* This function retrieves a song based on either a file path or a song name
391+
* and prints all relevant metadata, including title, artist, album, genre,
392+
* track number, disc number, and inode.
393+
*
394+
* @param input The file path or song name to search for.
395+
*/
396+
void printSongInfo(const std::string& input)
397+
{
398+
bool isFilePath = input.find('/') != std::string::npos || input.find('\\') != std::string::npos;
399+
400+
std::optional<Song> foundSong;
401+
402+
if (isFilePath)
403+
{
404+
// If input is a file path, retrieve its metadata using inode
405+
std::cout << std::endl << "> Taking argument as a possible audio file path..." << std::endl;
406+
struct stat fileStat;
407+
if (stat(input.c_str(), &fileStat) == 0)
408+
{
409+
unsigned int inode = fileStat.st_ino;
410+
for (const auto& artistPair : tree)
411+
{
412+
for (const auto& albumPair : artistPair.second)
413+
{
414+
for (const auto& discPair : albumPair.second)
415+
{
416+
for (const auto& trackPair : discPair.second)
417+
{
418+
if (trackPair.second.inode == inode)
419+
{
420+
foundSong = trackPair.second;
421+
break;
422+
}
423+
}
424+
}
425+
}
426+
}
427+
}
428+
}
429+
else
430+
{
431+
// If input is a song name, search by title
432+
for (const auto& artistPair : tree)
433+
{
434+
for (const auto& albumPair : artistPair.second)
435+
{
436+
for (const auto& discPair : albumPair.second)
437+
{
438+
for (const auto& trackPair : discPair.second)
439+
{
440+
if (levenshteinDistance(trackPair.second.metadata.title, input) < 3) // Recommended limit of correction (else it will go bonkers)
441+
{
442+
foundSong = trackPair.second;
443+
break;
444+
}
445+
}
446+
}
447+
}
448+
}
449+
}
450+
451+
if (foundSong)
452+
{
453+
const auto& song = *foundSong;
454+
std::cout << "\n🎵 Song Information:\n";
455+
std::cout << "──────────────────────────────────────\n";
456+
std::cout << "Title : " << song.metadata.title << "\n";
457+
std::cout << "Artist : " << song.metadata.artist << "\n";
458+
std::cout << "Album : " << song.metadata.album << "\n";
459+
std::cout << "Disc : " << song.metadata.discNumber << "\n";
460+
std::cout << "Track : " << song.metadata.track << "\n";
461+
std::cout << "Genre : " << song.metadata.genre << "\n";
462+
std::cout << "Inode : " << song.inode << "\n";
463+
464+
if (!song.metadata.additionalProperties.empty())
465+
{
466+
std::cout << "Additional Properties:\n";
467+
for (const auto& prop : song.metadata.additionalProperties)
468+
{
469+
if (prop.first == "LYRICS")
470+
{
471+
std::cout << "\n📜 Lyrics:\n";
472+
std::cout << "──────────────────────────────────────\n";
473+
474+
// Wrap and format the lyrics
475+
const std::string& lyrics = prop.second;
476+
size_t lineLength = 80;
477+
size_t start = 0;
478+
while (start < lyrics.size())
479+
{
480+
size_t end = start + lineLength;
481+
if (end > lyrics.size()) end = lyrics.size();
482+
std::cout << lyrics.substr(start, end - start) << "\n";
483+
start = end;
484+
}
485+
std::cout << "──────────────────────────────────────\n";
486+
}
487+
else
488+
{
489+
std::cout << " - " << prop.first << " : " << prop.second << "\n";
490+
}
491+
}
492+
}
493+
else
494+
{
495+
std::cout << "No additional properties found!" << std::endl;
496+
}
497+
std::cout << "──────────────────────────────────────\n";
498+
}
499+
else
500+
{
501+
std::cout << "⚠️ Song not found: " << input << "\n";
502+
}
503+
}
384504
};

src/dirsort/taglib_parser.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,8 @@ auto TagLibParser::parseFile(const std::string& filePath, Metadata& metadata) ->
238238
}
239239

240240
// Populate additional properties if needed
241-
if (debugLogBool && !properties.isEmpty()) {
242-
std::cout << "[TAG PARSE] Additional properties found!" << std::endl;
241+
if (!properties.isEmpty()) {
242+
if (debugLogBool) std::cout << "[TAG PARSE] Additional properties found!" << std::endl;
243243
for (const auto& prop : properties) {
244244
std::string key = prop.first.to8Bit(true);
245245
std::string value = prop.second.toString().to8Bit(true);

0 commit comments

Comments
 (0)