10#include <ftxui/component/captured_mouse.hpp>
11#include <ftxui/component/component.hpp>
12#include <ftxui/component/component_base.hpp>
13#include <ftxui/component/event.hpp>
14#include <ftxui/component/screen_interactive.hpp>
15#include <ftxui/dom/elements.hpp>
20#define MAX_LENGTH_SONG_NAME 50
21#define MAX_LENGTH_ARTIST_NAME 30
23#define SONG_TITLE_DELIM " • "
24#define LYRICS_AVAIL "L*"
25#define ADDN_PROPS_AVAIL "&*"
26#define STATUS_BAR_DELIM " | "
33 *lastVolume = *volume;
38 *volume = *lastVolume;
45 std::string formatted_info =
46 " " + std::to_string(disc_number) +
"-" + std::to_string(track_number) +
" ";
48 return formatted_info;
53 std::vector<std::string> lines;
54 std::string currentLine;
55 bool insideSquareBrackets =
false;
56 bool insideCurlBrackets =
false;
57 bool lastWasUppercase =
false;
58 bool lastWasSpecialChar =
false;
59 char previousChar =
'\0';
63 if (c ==
'[' || c ==
'(')
65 if (!currentLine.empty())
67 lines.push_back(currentLine);
71 insideSquareBrackets =
true;
73 insideCurlBrackets =
true;
78 if (insideSquareBrackets || insideCurlBrackets)
81 if (c ==
']' && insideSquareBrackets)
83 lines.push_back(currentLine);
85 insideSquareBrackets =
false;
88 else if (c ==
')' && insideCurlBrackets)
90 lines.push_back(currentLine);
92 insideCurlBrackets =
false;
97 if (c ==
'\'' || c ==
'-')
100 lastWasSpecialChar =
true;
104 if (std::isupper(c) && !lastWasUppercase && !lastWasSpecialChar && !currentLine.empty() &&
105 previousChar !=
'\n' && previousChar !=
' ')
107 lines.push_back(currentLine);
115 if (!currentLine.empty())
117 lines.push_back(currentLine);
122 lastWasUppercase = std::isupper(c);
123 lastWasSpecialChar =
false;
127 if (!currentLine.empty())
129 lines.push_back(currentLine);
133 lines.erase(std::remove_if(lines.begin(), lines.end(),
134 [](
const std::string& line) { return line.empty(); }),
141 const bool& show_bitrate,
const int& bitrate) -> std::string
143 std::string additional_info =
"";
144 if (genre !=
"Unknown Genre")
160 additional_info += std::to_string(bitrate) +
" kbps";
164 return additional_info;
180 return std::string(1,
static_cast<char>(ch));
186 int minutes = seconds / 60;
187 seconds = seconds % 60;
188 std::stringstream ss;
189 ss << std::setfill(
'0') << std::setw(2) << minutes <<
":" << std::setfill(
'0') << std::setw(2)
198auto renderAlbumName(
const std::string& album_name,
const int& year, ftxui::Color sel_color,
199 ftxui::Color sel_color_fg)
201 auto albumText = vbox(text(album_name) | color(sel_color_fg) | bold);
202 return hbox({text(
" "), albumText, filler(),
203 text(std::to_string(year)) | color(sel_color_fg) | bold | align_right, text(
" ")}) |
198auto renderAlbumName(
const std::string& album_name,
const int& year, ftxui::Color sel_color, {
…}
207auto renderSongName(
const std::string& disc_track_info,
const std::string& song_name,
210 return hbox({text(disc_track_info), text(song_name) | bold | flex_grow,
207auto renderSongName(
const std::string& disc_track_info,
const std::string& song_name, {
…}
217 std::vector<Element> artist_names_elements;
219 for (
const auto& a : artist_list)
221 auto artistElement = hbox({text(
" "), text(a) | bold});
222 artist_names_elements.push_back(artistElement);
225 return artist_names_elements;
228auto CreateMenu(
const std::vector<std::string>* vecLines,
int* currLine)
230 MenuOption menu_options;
231 menu_options.on_change = [&]() {};
232 menu_options.focused_entry = currLine;
234 return Menu(vecLines, currLine, menu_options);
228auto CreateMenu(
const std::vector<std::string>* vecLines,
int* currLine) {
…}
239 Elements rendered_items;
240 for (
const auto& item : items)
242 rendered_items.push_back(item | frame);
245 return vbox(std::move(rendered_items));
251 Elements rendered_items;
252 for (
const auto& item : items)
254 rendered_items.push_back(item | frame);
257 return vbox(std::move(rendered_items));
263 static std::map<std::string, std::string> mimeTypes = {
264 {
".mp3",
"audio/mpeg"}, {
".flac",
"audio/flac"}, {
".wav",
"audio/wav"},
265 {
".ogg",
"audio/ogg"}, {
".aac",
"audio/aac"}, {
".m4a",
"audio/mp4"},
266 {
".opus",
"audio/opus"}, {
".wma",
"audio/x-ms-wma"}, {
".alac",
"audio/alac"}};
269 std::string::size_type idx = filePath.rfind(
'.');
270 if (idx != std::string::npos)
272 std::string extension = filePath.substr(idx);
273 auto it = mimeTypes.find(extension);
274 if (it != mimeTypes.end())
281 return "application/octet-stream";
285 const std::string& songTitle,
const std::string& artistName,
286 const std::string& albumName,
const std::string& genre,
unsigned int year,
287 unsigned int trackNumber,
unsigned int discNumber,
290 auto thumbnailFilePath = cacheDirPath +
"thumbnail.png";
294 auto thumbnail = Renderer(
298 image_view(thumbnailFilePath) | size(WIDTH, LESS_THAN, 50) |
299 size(HEIGHT, LESS_THAN, 50),
307 hbox({text(artistName) | dim}) | center,
309 text(std::to_string(year)) | dim}) |
311 hbox({text(
"Track ") | dim, text(std::to_string(trackNumber)) | bold, text(
" on Disc "),
312 text(std::to_string(discNumber)) | bold}) |
315 hbox({text(
"Genre: "), text(genre) | bold}) | center,
320 auto progressBar = vbox({
322 hbox({text(
"Playback Progress") | bold}) | center,
323 hbox({gauge(progress) | flex,
324 text(
" " + std::to_string(
static_cast<int>(progress * 100)) +
"%")}),
327 auto modernUI = vbox({
328 thumbnail->Render() | flex_shrink,
340 auto errorView = vbox({
341 text(
"⚠ Thumbnail Unavailable") | bold | center | color(Color::Red),
343 text(
"Ensure the file has embedded artwork.") | dim | center,
353 text(
"/") | color(Color::GrayLight),
354 text(user_input) | color(Color::LightSteelBlue) | bold | inverted,
356 color(Color::GrayDark) | bgcolor(Color::Black) | size(HEIGHT, EQUAL, 1);
361 return window(text(
" inLimbo Information ") | bold | center |
365 separator() | color(Color::GrayLight),
369 size(WIDTH, LESS_THAN, 60) | size(HEIGHT, LESS_THAN, 8) |
379 [](
const std::string& key,
const std::string& description,
TrueColors::Color color)
389 std::vector<std::tuple<std::string, std::string, TrueColors::Color>> keybinds = {
390 {
charToStr(global_keybinds.scroll_up),
"Scroll up in the current view",
392 {
charToStr(global_keybinds.scroll_down),
"Scroll down in the current view",
394 {
charToStr(global_keybinds.toggle_focus),
"Switch focus between panes",
400 {
charToStr(global_keybinds.play_song_prev),
"Go back to previous song",
406 {
charToStr(global_keybinds.seek_ahead_5),
"Seek forward by 5 seconds",
408 {
charToStr(global_keybinds.seek_behind_5),
"Seek backward by 5 seconds",
410 {
charToStr(global_keybinds.view_lyrics),
"View lyrics for the current song",
414 {
charToStr(global_keybinds.add_song_to_queue),
"Add selected song to queue",
416 {
charToStr(global_keybinds.add_artists_songs_to_queue),
"Queue all songs by the artist",
418 {
charToStr(global_keybinds.remove_song_from_queue),
"Remove selected song from queue",
420 {
charToStr(global_keybinds.play_this_song_next),
"Play selected song next",
422 {
charToStr(global_keybinds.view_song_queue),
"View currently queued songs",
424 {
charToStr(global_keybinds.view_current_song_info),
"View info of the currently playing song",
426 {
charToStr(global_keybinds.toggle_audio_devices),
"Switch between available audio devices",
435 std::vector<Element> control_elements;
436 for (
const auto& [key, description, color] : keybinds)
438 control_elements.push_back(createRow(key, description, color));
445 auto symbols_explanation = vbox({
446 hbox({text(
LYRICS_AVAIL), text(
" -> "), text(
"The current song has lyrics metadata.")}) |
449 text(
"The current song has additional properties metadata.")}) |
454 auto app_name = text(
"inLimbo - Music player that keeps you in Limbo...") | bold |
458 auto github_link = hbox({
464 std::string footer_text =
465 "Press '" +
charToStr(global_keybinds.show_help) +
"' to return to inLimbo.";
476 controls_list | border | flex,
478 symbols_explanation | border | flex,
485 std::vector<int>& search_indices)
487 auto start = lower_bound(words.begin(), words.end(), prefix);
489 for (
auto it = start; it != words.end(); ++it)
491 if (it->substr(0, prefix.size()) != prefix)
493 search_indices.push_back(std::distance(words.begin(), it));
501 index = move_down ? (index + 1) % max_size : (index == 0 ? max_size - 1 : index - 1);
505 const std::string& additional_info,
const std::string& year_info,
506 InLimboColors& global_colors,
const std::string& current_artist) -> Element
510 text(current_artist) | color(global_colors.status_bar_artist_col) | bold |
512 text(current_song_info) | bold | color(global_colors.status_bar_song_col) |
516 text(additional_info) | bold | color(global_colors.status_bar_addn_info_col) | flex,
517 text(year_info) | color(global_colors.status_bar_addn_info_col) |
518 size(WIDTH, LESS_THAN, 15),
523 size(HEIGHT, EQUAL, 1) | bgcolor(global_colors.status_bar_bg);
529 text(
" Vol: ") | dim,
530 gauge(volume / 100.0) | size(WIDTH, EQUAL, 10) | color(volume_bar_col),
531 text(std::to_string(volume) +
"%") | dim,
constexpr const char * REPOSITORY_URL
Definition arg-handler.hpp:22
auto RenderHelpScreen(Keybinds &global_keybinds) -> Element
Definition misc.hpp:373
auto getTrueBGColor(TrueColors::Color color)
Definition misc.hpp:196
auto getTrueColor(TrueColors::Color color)
Definition misc.hpp:194
auto getMimeTypeFromExtension(const std::string &filePath) -> std::string
Definition misc.hpp:260
auto handleToggleMute(int *volume, int *lastVolume, bool *muted) -> int
Definition misc.hpp:28
auto charToStr(char ch) -> std::string
Definition misc.hpp:167
#define SONG_TITLE_DELIM
Definition misc.hpp:23
auto RenderArtistNames(const std::vector< std::string > &artist_list)
Definition misc.hpp:215
auto RenderThumbnail(const std::string &songFilePath, const std::string &cacheDirPath, const std::string &songTitle, const std::string &artistName, const std::string &albumName, const std::string &genre, unsigned int year, unsigned int trackNumber, unsigned int discNumber, float progress)
Definition misc.hpp:284
auto RenderDialog(const std::string &dialog_message) -> Element
Definition misc.hpp:359
auto RenderArtistMenu(const std::vector< std::string > &artist_list)
Definition misc.hpp:248
auto renderAlbumName(const std::string &album_name, const int &year, ftxui::Color sel_color, ftxui::Color sel_color_fg)
Definition misc.hpp:198
#define MAX_LENGTH_ARTIST_NAME
Definition misc.hpp:21
auto renderSongName(const std::string &disc_track_info, const std::string &song_name, const int &duration)
Definition misc.hpp:207
auto formatAdditionalInfo(const std::string &genre, const bool &has_comment, const bool &has_lyrics, const bool &show_bitrate, const int &bitrate) -> std::string
Definition misc.hpp:140
void UpdateSelectedIndex(int &index, int max_size, bool move_down)
Definition misc.hpp:497
auto RenderStatusBar(const std::string &status, const std::string ¤t_song_info, const std::string &additional_info, const std::string &year_info, InLimboColors &global_colors, const std::string ¤t_artist) -> Element
Definition misc.hpp:504
auto RenderSongMenu(const std::vector< Element > &items)
Definition misc.hpp:237
void searchModeIndices(const std::vector< std::string > &words, const std::string &prefix, std::vector< int > &search_indices)
Definition misc.hpp:484
auto formatDiscTrackInfo(const int &disc_number, const int &track_number)
Definition misc.hpp:43
auto RenderVolumeBar(int volume, ftxui::Color volume_bar_col) -> Element
Definition misc.hpp:526
#define LYRICS_AVAIL
Definition misc.hpp:24
auto CreateMenu(const std::vector< std::string > *vecLines, int *currLine)
Definition misc.hpp:228
#define MAX_LENGTH_SONG_NAME
Definition misc.hpp:20
auto FormatTime(int seconds)
Definition misc.hpp:184
auto formatLyrics(const std::string &lyrics)
Definition misc.hpp:51
#define ADDN_PROPS_AVAIL
Definition misc.hpp:25
auto RenderSearchBar(std::string &user_input) -> Element
Definition misc.hpp:350
#define STATUS_BAR_DELIM
Definition misc.hpp:26
auto GetColor(Color color) -> ftxui::Color
Maps a predefined color enum to its corresponding ftxui::Color::RGB value.
Definition colors.hpp:76
Color
Enumeration for predefined true colors.
Definition colors.hpp:24
@ Cyan
Definition colors.hpp:35
@ White
Definition colors.hpp:26
@ LightBlue
Definition colors.hpp:32
@ Coral
Definition colors.hpp:51
@ LightGreen
Definition colors.hpp:30
@ Pink
Definition colors.hpp:46
@ Orange
Definition colors.hpp:42
@ Gray
Definition colors.hpp:39
@ LightPink
Definition colors.hpp:47
@ LightCyan
Definition colors.hpp:36
@ Teal
Definition colors.hpp:48
@ Black
Definition colors.hpp:25
@ LightMagenta
Definition colors.hpp:38
@ LightRed
Definition colors.hpp:28
@ LightYellow
Definition colors.hpp:34
Element image_view(std::string_view url)
Definition image_view.cpp:85
Represents a collection of colors used in the application.
Definition colors.hpp:182
Struct to hold keybinding mappings.
Definition keymaps.hpp:15
A header file for the TagLibParser class and Metadata structure, used to parse metadata from audio fi...
auto extractThumbnail(const std::string &audioFilePath, const std::string &outputImagePath) -> bool
Extracts the thumbnail (album art) from an audio file and saves it to an image file....
Definition taglib_parser.h:325