Skip to content

Commit

Permalink
feat: [MEDIUM] CHANGELOG v6
Browse files Browse the repository at this point in the history
  • Loading branch information
nots1dd committed Jun 30, 2024
1 parent 7a01267 commit f7b0652
Show file tree
Hide file tree
Showing 6 changed files with 314 additions and 190 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# Add the executable
add_executable(Litemus ncurses_lmus.cpp headers/src/executeCmd.cpp headers/src/lmus_cache.cpp headers/src/sfml_helpers.cpp headers/src/ncurses_helpers.cpp headers/src/parsers.cpp)
add_executable(Litemus litemus.cpp headers/src/executeCmd.cpp headers/src/lmus_cache.cpp headers/src/sfml_helpers.cpp headers/src/ncurses_helpers.cpp headers/src/parsers.cpp)

# Find and include SFML
find_package(SFML 2.5 COMPONENTS audio REQUIRED)
Expand Down
20 changes: 20 additions & 0 deletions changelog/v6.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Change type: MEDIUM

Summary

-> lmus_cache process is now within a clean TUI with a progress bar and time remaining (time remaining is not perfect but it will do for now)

-> Tried to remove the while loop for lyrics_win to scroll but didnt work (will try and itemize each line in a duplicate of artistMenu and display it to avoid any loops)

-> Updated a few functions to make code more modular

-> Renamed main cpp file to litemus.cpp

-> Added mute function

-> Updated lyrics win to have song name and its artist for better UX

-> The lyrics_win while loop now has play/pause and +- vol control (aim is if we cannot remove this loop, only player vol control is accessible when in lyrics view)

-> Fixed some flickering issues when in lyrics view

2 changes: 1 addition & 1 deletion headers/ncurses_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ void displayHelpWindow(WINDOW* menu_win);
void updateStatusBar(WINDOW* status_win, const std::string& songName, const std::string& artistName, const std::string& songGenre, const sf::Music& music, bool firstEnterPressed, bool showingLyrics);
bool showExitConfirmation(WINDOW* parent_win);
void highlightFocusedWindow(MENU* menu, bool focused);
void printMultiLine(WINDOW* win, const std::vector<std::string>& lines, int start_line);
void printMultiLine(WINDOW* win, const std::vector<std::string>& lines, int start_line, std::string& currentSong, std::string& currentArtist);
void ncursesMenuSetup(MENU* Menu, WINDOW* win, int menu_height, int menu_width);
void move_menu_down(MENU* artistMenu, MENU* songMenu, bool showingArtists);
void move_menu_up(MENU* artistMenu, MENU* songMenu, bool showingArtists);
Expand Down
91 changes: 83 additions & 8 deletions headers/src/lmus_cache.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <ncurses.h>
#include "../lmus_cache.hpp"

using json = nlohmann::json;
Expand All @@ -12,7 +13,7 @@ const string PINK = "\033[35m";
const string YELLOW = "\033[33m";
const string BOLD = "\033[1m";

// FILE EXTENSION TO CACHE
// FILE EXTENSION TO CACHE
const string extension = ".mp3";

struct SongMetadata {
Expand Down Expand Up @@ -59,6 +60,7 @@ string getFileNameFromInode(const string& inode) {

return fileName;
}

// Function to escape special characters in filename
string escapeSpecialCharacters(const string& fileName) {
string escapedFileName;
Expand All @@ -70,6 +72,7 @@ string escapeSpecialCharacters(const string& fileName) {
}
return escapedFileName;
}

// Function to store metadata in JSON format
void storeMetadataJSON(const string& inode, const string& fileName, json& artistsArray, vector<SongMetadata>& songMetadata) {
// Escape special characters in the filename
Expand All @@ -88,7 +91,7 @@ void storeMetadataJSON(const string& inode, const string& fileName, json& artist
int track = metadata["format"]["tags"].contains("track") ? stoi(metadata["format"]["tags"]["track"].get<string>()) : 0;
string genre = metadata["format"]["tags"].contains("genre") ? metadata["format"]["tags"]["genre"].get<string>() : "";
string date = metadata["format"]["tags"].contains("date") ? metadata["format"]["tags"]["date"].get<string>() : "";
string lyrics = metadata["format"]["tags"].contains("lyrics-XXX") ? metadata["format"]["tags"]["lyrics-XXX"].get<string>() : "";
string lyrics = metadata["format"]["tags"].contains("lyrics-XXX") ? metadata["format"]["tags"]["lyrics-XXX"].get<string>() : "";

// Check if artist is already in the array
if (find(artistsArray.begin(), artistsArray.end(), artist) == artistsArray.end()) {
Expand All @@ -98,6 +101,7 @@ void storeMetadataJSON(const string& inode, const string& fileName, json& artist
// Store metadata
songMetadata.push_back({fileName, inode, artist, album, title, disc, track, genre, date, lyrics});
}

// Function to save artists to a file
void saveArtistsToFile(const json& artistsArray, const string& filePath) {
ofstream outFile(filePath, ios::trunc);
Expand All @@ -109,6 +113,15 @@ void saveArtistsToFile(const json& artistsArray, const string& filePath) {
}
}

void saveSongDirToFile(const std::string& songDirectory) {
std::fstream songDirFile(".cache/litemus/songDirectory.txt", std::ios::out);
if (!songDirFile) {
printErrorAndExit("[ERROR] Unable to save song directory to file: songDirectory.txt");
}
songDirFile << songDirectory;
songDirFile.close();
}

// Function to print artists
void printArtists(const json& artistsArray) {
cout << "Artists List:" << endl;
Expand All @@ -117,8 +130,6 @@ void printArtists(const json& artistsArray) {
}
}



void storeSongsJSON(const string& filePath, const vector<SongMetadata>& songMetadata) {
json songsJson;

Expand Down Expand Up @@ -213,7 +224,20 @@ void saveCurrentInodes(const vector<string>& inodes, const string& filePath) {
}
}

void drawProgressBar(WINDOW* win, int y, int x, float progress) {
int barWidth = 50; // Width of the progress bar
int pos = barWidth * progress;
mvwprintw(win, y, x, "[");
for (int i = 0; i < barWidth; ++i) {
if (i < pos) mvwprintw(win, y, x + 1 + i, "=");
else mvwprintw(win, y, x + 1 + i, " ");
}
mvwprintw(win, y, x + 1 + barWidth, "]");
wrefresh(win);
}

int lmus_cache_main(const std::string songDirectory) {

// DIRECTORY VARIABLES
const string cacheDirectory = songDirectory + ".cache/";
const string cacheLitemusDirectory = cacheDirectory + "litemus/";
Expand All @@ -237,18 +261,65 @@ int lmus_cache_main(const std::string songDirectory) {
// Load previous inodes from song_cache_info_file if it exists
vector<string> previousInodes = loadPreviousInodes(songCacheInfoFile);
json artistsArray;

// Compare current inodes with previous inodes
if (compareInodeVectors(inodes, previousInodes)) {
cout << PINK << BOLD << "[CACHE] No changes in song files. Exiting without caching." << RESET << endl;
} else {
int cachedSongCount = 0;

for (const string& inode : inodes) {
time_t startTime = time(nullptr); // record the start time
setlocale(LC_ALL, "");
initscr();
noecho();
cbreak();
curs_set(0);

// Create windows for TUI
int height = 10;
int width = 60;
int start_y = 1;
int start_x = (COLS - width) / 2;
WINDOW* progressWin = newwin(height, width, start_y, start_x);
box(progressWin, 0, 0);
mvwprintw(progressWin, 1, 1, "LiteMus Cache Process");
wrefresh(progressWin);

int fileWinHeight = 3;
int fileWinWidth = 100;
int fileWinStartY = start_y + height + 1;
int fileWinStartX = start_x - 20;
WINDOW* fileWin = newwin(fileWinHeight, fileWinWidth, fileWinStartY, fileWinStartX);
box(fileWin, 0, 0);
wrefresh(fileWin);

for (const std::string& inode : inodes) {
string fileName = getFileNameFromInode(inode);
cout << BLUE << "==> " << fileName << RESET << endl;

// Clear previous filename and print new filename
wclear(fileWin);
box(fileWin, 0, 0);
mvwprintw(fileWin, 1, 1, "==> %s", fileName.c_str());
wrefresh(fileWin);

storeMetadataJSON(inode, fileName, artistsArray, songMetadata);
cachedSongCount++;
time_t currentTime = time(nullptr);

double elapsedSeconds = difftime(currentTime, startTime);
double songsPerSecond = cachedSongCount / elapsedSeconds;
double remainingSongs = inodes.size() - cachedSongCount;
double estimatedTimeRemaining = remainingSongs / songsPerSecond;

// format the estimated time remaining
int minutes = static_cast<int>(estimatedTimeRemaining) % 3600 / 60;
int seconds = static_cast<int>(estimatedTimeRemaining) % 60;
char timeRemainingStr[32];
sprintf(timeRemainingStr, "Time to cook: %02d:%02d", minutes, seconds);
mvwprintw(progressWin, 3, 1, timeRemainingStr);

float progress = static_cast<float>(cachedSongCount) / inodes.size();
mvwprintw(progressWin, 2, 1, "Progress: %0.2f%%", progress*100);
drawProgressBar(progressWin, 5, 1, progress);
}

saveArtistsToFile(artistsArray, artistsFilePath);
Expand All @@ -265,6 +336,10 @@ int lmus_cache_main(const std::string songDirectory) {

// Save current inodes for future comparison
saveCurrentInodes(inodes, songCacheInfoFile);
saveSongDirToFile(songDirectory);

endwin();


cout << endl << GREEN << BOLD << "[SUCCESS] Total of " << cachedSongCount << " songs have been cached!!" << endl;
cout << PINK << BOLD << "[CACHE] Songs' cache has been stored in " << cacheInfoDirectory << RESET << endl;
Expand Down
21 changes: 11 additions & 10 deletions headers/src/ncurses_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,12 @@ void displayHelpWindow(WINDOW* menu_win) {
mvwprintw(menu_win, 13, 2, "b - Previous Song");
mvwprintw(menu_win, 14, 2, "9 - Increase Volume");
mvwprintw(menu_win, 15, 2, "0 - Decrease Volume");
mvwprintw(menu_win, 16, 2, "/ - String search in focused window");
mvwprintw(menu_win, 17, 2, "Tab - Toggle Focused Window");
mvwprintw(menu_win, 19, 2, "2 - To show help menu");
mvwprintw(menu_win, 16, 2, "m - Mute all Volume");
mvwprintw(menu_win, 17, 2, "/ - String search in focused window");
mvwprintw(menu_win, 18, 2, "Tab - Toggle Focused Window");
mvwprintw(menu_win, 20, 2, "2 - To show help menu");
init_pair(GREY_BACKGROUND_COLOR, COLOR_BLACK, COLOR_WHITE); // Grey background and black text for title
mvwprintw(menu_win, 21, 2, "Press '1' to go back to the menu");
mvwprintw(menu_win, 22, 2, "Press '1' to go back to the menu");
wrefresh(menu_win);
}

Expand Down Expand Up @@ -132,7 +133,7 @@ bool showExitConfirmation(WINDOW* parent_win) {
int start_x = (COLS - width) / 2;

WINDOW* confirm_win = newwin(height, width, start_y, start_x);
wattron(confirm_win, COLOR_PAIR(COLOR_GREEN));
wattron(confirm_win, COLOR_PAIR(COLOR_RED));
box(confirm_win, 0, 0);
mvwprintw(confirm_win, 1, 9, "Do you really want to exit LITEMUS?");
mvwprintw(confirm_win, 4, 8, " Yes (Y) No (N)");
Expand All @@ -141,10 +142,10 @@ bool showExitConfirmation(WINDOW* parent_win) {

int ch;
bool exitConfirmed = false;
while ((ch = wgetch(confirm_win)) != 'y' && ch != 'Y' && ch != 'n' && ch != 'N' && ch != 27 && ch != 10) {
while ((ch = wgetch(confirm_win)) != 'y' && ch != 'Y' && ch != 'n' && ch != 'N' && ch != 27 && ch != 10 && ch != 'q' && ch != 'Q') {
// Wait for valid input
}
if (ch == 'y' || ch == 'Y' || ch == 10) {
if (ch == 'y' || ch == 'Y' || ch == 10 || ch == 'q' || ch == 'Q') {
exitConfirmed = true;
}

Expand All @@ -154,11 +155,11 @@ bool showExitConfirmation(WINDOW* parent_win) {
return exitConfirmed;
}

void printMultiLine(WINDOW* win, const std::vector<std::string>& lines, int start_line) {
void printMultiLine(WINDOW* win, const std::vector<std::string>& lines, int start_line, std::string& currentSong, std::string& currentArtist) {
int max_y, max_x;
getmaxyx(win, max_y, max_x);

for (int i = 1; i < max_y && (start_line + i) < lines.size(); ++i) {
mvwprintw(win, 1, 2, " %s by %s", currentSong.c_str(), currentArtist.c_str());
for (int i = 3; i < max_y && (start_line + i) < lines.size(); ++i) {
mvwprintw(win, i, 0, "%s", lines[start_line + i].c_str());
}
}
Expand Down
Loading

0 comments on commit f7b0652

Please sign in to comment.