Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package kew for openSUSE:Factory checked in at 2024-03-13 22:18:29 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/kew (Old) and /work/SRC/openSUSE:Factory/.kew.new.1770 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "kew" Wed Mar 13 22:18:29 2024 rev:15 rq:1157156 version:2.4.3 Changes: -------- --- /work/SRC/openSUSE:Factory/kew/kew.changes 2024-02-29 21:50:46.802926930 +0100 +++ /work/SRC/openSUSE:Factory/.kew.new.1770/kew.changes 2024-03-13 22:19:37.130572109 +0100 @@ -1,0 +2,10 @@ +Tue Mar 12 10:40:54 UTC 2024 - Muhammad Akbar Yanuar Mantari <mantari...@pm.me> + +- Update to version 2.4.3 + * Fixed covers not being perfectly square on some terminals. + * Fixed playlist selector could get 'stuck'. + * Code refactoring and minor improvements to playlist view. + * Moved the files kewrc and kewlibrary config files from + XDG_CONFIG_HOME into XDG_CONFIG_HOME/kew/ or ~/.config/kew. + +------------------------------------------------------------------- Old: ---- kew-2.4.2.tar.gz New: ---- kew-2.4.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ kew.spec ++++++ --- /var/tmp/diff_new_pack.Jkb2dq/_old 2024-03-13 22:19:37.702593196 +0100 +++ /var/tmp/diff_new_pack.Jkb2dq/_new 2024-03-13 22:19:37.706593344 +0100 @@ -17,7 +17,7 @@ Name: kew -Version: 2.4.2 +Version: 2.4.3 Release: 0 Summary: A command-line music player License: GPL-2.0-only ++++++ kew-2.4.2.tar.gz -> kew-2.4.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/Makefile new/kew-2.4.3/Makefile --- old/kew-2.4.2/Makefile 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/Makefile 2024-03-09 09:59:46.000000000 +0100 @@ -13,7 +13,7 @@ OBJDIR = src/obj PREFIX = /usr -SRCS = src/sound.c src/directorytree.c src/soundcommon.c src/player.c src/soundbuiltin.c src/mpris.c src/playerops.c src/utils.c src/file.c src/chafafunc.c src/cache.c src/songloader.c src/playlist.c src/term.c src/settings.c src/visuals.c src/kew.c +SRCS = src/sound.c src/directorytree.c src/soundcommon.c src/playlist_ui.c src/player.c src/soundbuiltin.c src/mpris.c src/playerops.c src/utils.c src/file.c src/chafafunc.c src/cache.c src/songloader.c src/playlist.c src/term.c src/settings.c src/visuals.c src/kew.c OBJS = $(SRCS:src/%.c=$(OBJDIR)/%.o) MAN_PAGE = kew.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/README.md new/kew-2.4.3/README.md --- old/kew-2.4.2/README.md 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/README.md 2024-03-09 09:59:46.000000000 +0100 @@ -177,10 +177,10 @@ * Use <kbd>â</kbd>, <kbd>â</kbd> or <kbd>h</kbd>, <kbd>l</kbd> keys to switch tracks. * <kbd>Space</kbd>, <kbd>P</kbd> to toggle pause. * <kbd>F2</kbd> to show/hide the playlist and information about kew. -* <kbd>F3</kbd> to show/hide library. -* <kbd>F4</kbd> to show/hide track view. +* <kbd>F3</kbd> to show/hide the library. +* <kbd>F4</kbd> to show/hide the track view. * <kbd>F5</kbd> to show/hide key bindings. -* <kbd>u</kbd> to update library. +* <kbd>u</kbd> to update the library. * <kbd>v</kbd> to toggle the spectrum visualizer. * <kbd>c</kbd> to toggle album covers. * <kbd>i</kbd> to switch between using your regular color scheme or colors derived from the track cover. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/docs/kew-manpage.mdoc new/kew-2.4.3/docs/kew-manpage.mdoc --- old/kew-2.4.2/docs/kew-manpage.mdoc 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/docs/kew-manpage.mdoc 2024-03-09 09:59:46.000000000 +0100 @@ -142,6 +142,8 @@ .Bl -tag -width -compact .It Pa "~/<configfolder>/kewrc" Config file. +.It Pa "~/<configfolder>/kew/kewlibrary" +Music library directory tree cache. .It Pa "/<musicfolder>/kew.m3u" The .Nm diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/docs/kew.1 new/kew-2.4.3/docs/kew.1 --- old/kew-2.4.2/docs/kew.1 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/docs/kew.1 2024-03-09 09:59:46.000000000 +0100 @@ -169,9 +169,12 @@ \fBkew\fR. .SH "FILES" .TP 10n -\fI~/<configfolder>/kewrc\fR +\fI~/<configfolder>/kew/kewrc\fR Config file. .TP 10n +\fI~/<configfolder>/kew/kewlibrary\fR +Music library directory tree cache. +.TP 10n \fI/<musicfolder>/kew.m3u\fR The \fBkew\fR diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/chafafunc.c new/kew-2.4.3/src/chafafunc.c --- old/kew-2.4.2/src/chafafunc.c 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/src/chafafunc.c 2024-03-09 09:59:46.000000000 +0100 @@ -358,16 +358,66 @@ chafa_calc_canvas_geometry(pix_width, pix_height, &width_cells, &height_cells, font_ratio, TRUE, FALSE); - /* Convert the image to a printable string */ + // Convert image to a printable string printable = convert_image(pixels, pix_width, pix_height, pix_width * n_channels, CHAFA_PIXEL_BGRA8_UNASSOCIATED, width, height, cell_width, cell_height); - /* Print the string */ - fwrite(printable->str, sizeof(char), printable->len, stdout); g_string_free(printable, TRUE); } +void printSquareBitmapCentered(FIBITMAP *bitmap, int baseHeight) +{ + if (bitmap == NULL) + { + return; + } + int pix_width = FreeImage_GetWidth(bitmap); + int pix_height = FreeImage_GetHeight(bitmap); + int n_channels = FreeImage_GetBPP(bitmap) / 8; + unsigned char *pixels = (unsigned char *)FreeImage_GetBits(bitmap); + + TermSize term_size; + GString *printable; + gint cell_width = -1, cell_height = -1; + + tty_init(); + get_tty_size(&term_size); + + if (term_size.width_cells > 0 && term_size.height_cells > 0 && term_size.width_pixels > 0 && term_size.height_pixels > 0) + { + cell_width = term_size.width_pixels / term_size.width_cells; + cell_height = term_size.height_pixels / term_size.height_cells; + } + + // Set default for some terminals + if (cell_width == -1 && cell_height == -1) + { + cell_width = 8; + cell_height = 16; + } + float aspect_ratio_correction = (float)cell_height / (float)cell_width; + + int correctedWidth = (int)(baseHeight * aspect_ratio_correction); + + // Convert image to a printable string + printable = convert_image(pixels, pix_width, pix_height, pix_width * n_channels, CHAFA_PIXEL_BGRA8_UNASSOCIATED, + correctedWidth, baseHeight, cell_width, cell_height); + g_string_append_c(printable, '\0'); + const gchar *delimiters = "\n"; + gchar **lines = g_strsplit(printable->str, delimiters, -1); + + int indentation = ((term_size.width_cells - correctedWidth) / 2) + 1; + + for (int i = 0; lines[i] != NULL; i++) + { + printf("\n%*s%s", indentation, "", lines[i]); + } + + g_strfreev(lines); + g_string_free(printable, TRUE); +} + void printBitmapCentered(FIBITMAP *bitmap, int width, int height) { if (bitmap == NULL) @@ -392,6 +442,7 @@ cell_height = term_size.height_pixels / term_size.height_cells; } + // Convert image to a printable string printable = convert_image(pixels, pix_width, pix_height, pix_width * n_channels, CHAFA_PIXEL_BGRA8_UNASSOCIATED, width, height, cell_width, cell_height); g_string_append_c(printable, '\0'); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/chafafunc.h new/kew-2.4.3/src/chafafunc.h --- old/kew-2.4.2/src/chafafunc.h 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/src/chafafunc.h 2024-03-09 09:59:46.000000000 +0100 @@ -11,4 +11,5 @@ FIBITMAP *getBitmap(const char *image_path); void printBitmap(FIBITMAP *bitmap, int width, int height); void printBitmapCentered(FIBITMAP *bitmap, int width, int height); +void printSquareBitmapCentered(FIBITMAP *bitmap, int baseHeight); int getCoverColor(FIBITMAP *bitmap, unsigned char *r, unsigned char *g, unsigned char *b); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/directorytree.h new/kew-2.4.3/src/directorytree.h --- old/kew-2.4.2/src/directorytree.h 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/src/directorytree.h 2024-03-09 09:59:46.000000000 +0100 @@ -1,3 +1,6 @@ +#ifndef DIRECTORYTREE_H +#define DIRECTORYTREE_H + #include <ctype.h> #include <dirent.h> #include <regex.h> @@ -34,3 +37,5 @@ void freeTree(FileSystemEntry *root); void freeAndWriteTree(FileSystemEntry *root, const char *filename); FileSystemEntry *reconstructTreeFromFile(const char *filename, const char *startMusicPath, int *numDirectoryEntries); + +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/kew.c new/kew-2.4.3/src/kew.c --- old/kew-2.4.2/src/kew.c 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/src/kew.c 2024-03-09 09:59:46.000000000 +0100 @@ -942,8 +942,8 @@ pthread_mutex_init(&(loadingdata.mutex), NULL); pthread_mutex_init(&(playlist.mutex), NULL); nerdFontsEnabled = hasNerdFonts(); - fflush(stdout); createLibrary(&settings); + fflush(stdout); #ifdef DEBUG g_setenv("G_MESSAGES_DEBUG", "all", TRUE); @@ -1083,6 +1083,7 @@ exit(0); } + moveConfigFiles(); // move from old location to new getConfig(&settings); if (argc == 3 && (strcmp(argv[1], "path") == 0)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/player.c new/kew-2.4.3/src/player.c --- old/kew-2.4.2/src/player.c 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/src/player.c 2024-03-09 09:59:46.000000000 +0100 @@ -22,7 +22,7 @@ } PixelData; #endif -const char VERSION[] = "2.4.2"; +const char VERSION[] = "2.4.3"; int mainColor = 6; int titleColor = 6; int artistColor = 6; @@ -48,7 +48,6 @@ int elapsedBars = 0; int chosenRow = 0; int chosenSong = 0; -int startIter = 0; int aboutHeight = 8; int visualizerHeight = 5; int minWidth = ABSOLUTE_MIN_WIDTH; @@ -183,16 +182,6 @@ calcIdealImgSize(&preferredWidth, &preferredHeight, (visualizerEnabled ? visualizerHeight : 0), calcMetadataHeight()); } -void shortenString(char *str, size_t maxLength) -{ - size_t length = strlen(str); - - if (length > maxLength) - { - str[maxLength] = '\0'; - } -} - void printHelp() { printf(" kew - a command-line music player.\n"); @@ -313,7 +302,7 @@ if (!ansii) { - printBitmapCentered(cover, width, height); + printSquareBitmapCentered(cover, height); } else { @@ -624,38 +613,6 @@ return numRows; } -void removeUnneededChars(char *str) -{ - if (strlen(str) < 6) - { - return; - } - - int i; - for (i = 0; i < 3 && str[i] != '\0' && str[i] != ' '; i++) - { - if (isdigit(str[i]) || str[i] == '-' || str[i] == ' ') - { - int j; - for (j = i; str[j] != '\0'; j++) - { - str[j] = str[j + 1]; - } - str[j] = '\0'; - i--; // Decrement i to re-check the current index - } - } - i = 0; - while (str[i] != '\0') - { - if (str[i] == '-' || str[i] == '_') - { - str[i] = ' '; - } - i++; - } -} - int showKeyBindings(SongData *songdata, AppSettings *settings) { int numPrintedRows = 0; @@ -765,6 +722,7 @@ else if (appState.currentView == PLAYLIST_VIEW) { chosenRow += maxListSize - 1; + chosenRow = (chosenRow >= originalPlaylist->count) ? originalPlaylist->count - 1 : chosenRow; refresh = true; } } @@ -780,6 +738,7 @@ else if (appState.currentView == PLAYLIST_VIEW) { chosenRow -= maxListSize; + chosenRow = (chosenRow > 0) ? chosenRow : 0; refresh = true; } } @@ -789,6 +748,7 @@ if (appState.currentView == PLAYLIST_VIEW) { chosenRow++; + chosenRow = (chosenRow >= originalPlaylist->count) ? originalPlaylist->count - 1 : chosenRow; refresh = true; } else if (appState.currentView == LIBRARY_VIEW) @@ -803,6 +763,7 @@ if (appState.currentView == PLAYLIST_VIEW) { chosenRow--; + chosenRow = (chosenRow > 0) ? chosenRow : 0; refresh = true; } else if (appState.currentView == LIBRARY_VIEW) @@ -825,180 +786,34 @@ return row; } -int showPlaylist(SongData *songData) +int printLogoAndAdjustments(SongData *songData, int termWidth, bool hideHelp, int indentation) { - Node *node = originalPlaylist->head; - Node *foundNode = NULL; - bool startFromCurrent = false; - int term_w, term_h; - getTermSize(&term_w, &term_h); - int totalHeight = term_h; - maxListSize = totalHeight - 3; - int numRows = 0; - int numPrintedRows = 0; - int foundAt = -1; - - numRows++; - int aboutRows = printLogo(songData); - maxListSize -= aboutRows - 1; - - setDefaultTextColor(); - - printBlankSpaces(indent); - if (term_w > 52 && !hideHelp) + if (termWidth > 52 && !hideHelp) { - maxListSize -= 3; - printf(" Use â, â or k, j to choose. Enter to accept.\n"); + setDefaultTextColor(); printBlankSpaces(indent); + printf(" Use â, â or k, j to choose. Enter to accept.\n"); + printBlankSpaces(indentation); printf(" Pg Up and Pg Dn to scroll. Del to remove entry.\n\n"); + return aboutRows + 3; } + return aboutRows; +} - int numSongs = 0; - for (int i = 0; i < originalPlaylist->count; i++) - { - if (node == NULL) - break; - - if (currentSong != NULL && currentSong->id == node->id) - { - foundAt = numSongs; - foundNode = node; - } - - node = node->next; - numSongs++; - if (numSongs > maxListSize) - { - startFromCurrent = true; - if (foundAt > -1) - break; - } - } - - if (startFromCurrent) - node = foundNode; - else - node = originalPlaylist->head; - - if (chosenRow >= originalPlaylist->count) - { - chosenRow = originalPlaylist->count - 1; - } - - chosenSong = chosenRow; - chosenSong = (chosenSong < 0) ? 0 : chosenSong; - - if (chosenSong < startIter) - { - startIter = chosenSong; - } - - if (chosenRow > startIter + maxListSize - round(maxListSize / 2)) - { - startIter = chosenRow - maxListSize + round(maxListSize / 2); - } - - if (startIter == 0 && chosenRow < 0) - { - chosenRow = 0; - } - - if (resetPlaylistDisplay && !audioData.endOfListReached) - { - startIter = chosenRow = chosenSong = foundAt; - } - - for (int i = foundAt; i > startIter; i--) - { - if (i > 0 && node->prev != NULL) - node = node->prev; - } - - if (foundAt > -1) - { - for (int i = foundAt; i < startIter; i++) - { - if (node->next != NULL) - node = node->next; - } - } - - for (int i = (startFromCurrent ? startIter : 0); i < (startFromCurrent ? startIter : 0) + maxListSize; i++) - { - setDefaultTextColor(); - - if (node == NULL) - break; - char filePath[MAXPATHLEN]; - c_strcpy(filePath, sizeof(filePath), node->song.filePath); - char *lastSlash = strrchr(filePath, '/'); - char *lastDot = strrchr(filePath, '.'); - printf("\r"); - printBlankSpaces(indent); - - if (lastSlash != NULL && lastDot != NULL && lastDot > lastSlash) - { - char copiedString[256]; - strncpy(copiedString, lastSlash + 1, lastDot - lastSlash - 1); - copiedString[lastDot - lastSlash - 1] = '\0'; - removeUnneededChars(copiedString); - - if (i == chosenSong) - { - chosenNodeId = node->id; - - printf("\x1b[7m"); - } - - if (foundNode != NULL && foundNode->id == node->id) - { - printf("\e[1m\e[39m"); - } - - shortenString(copiedString, term_w - 10 - indent); - trim(copiedString); - - if (i + 1 < 10) - printf(" "); - - if (startFromCurrent) - { - printf(" %d. %s \n", i + 1, copiedString); - } - else - { - printf(" %d. %s \n", numRows, copiedString); - } +void showPlaylist(SongData *songData, PlayList *list, int *chosenSong, int *chosenNodeId) +{ + int term_w, term_h; + getTermSize(&term_w, &term_h); + maxListSize = term_h - 2; - numPrintedRows++; - numRows++; + int aboutRows = printLogoAndAdjustments(songData, term_w, hideHelp, indent); + maxListSize -= aboutRows; - setTextColorRGB2(color.r, color.g, color.b); + displayPlaylist(list, maxListSize, indent, chosenSong, chosenNodeId, resetPlaylistDisplay); - setDefaultTextColor(); - } - node = node->next; - } printf("\n"); - numPrintedRows++; printLastRow(); - if (numRows > 1) - { - while (numPrintedRows < maxListSize) - { - printf("\n"); - numPrintedRows++; - } - } - numPrintedRows += 2; - numPrintedRows += aboutRows; - if (term_w > 46) - { - numPrintedRows += 2; - } - resetPlaylistDisplay = false; - return numPrintedRows; } void printElapsedBars(int elapsedBars) @@ -1407,9 +1222,8 @@ else if (appState.currentView == PLAYLIST_VIEW && refresh) { clearScreen(); - int height = showPlaylist(songdata); - cursorJump(height); - saveCursorPosition(); + showPlaylist(songdata, originalPlaylist, &chosenRow, &chosenNodeId); + resetPlaylistDisplay = false; refresh = false; } else if (appState.currentView == LIBRARY_VIEW && refresh) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/player.h new/kew-2.4.3/src/player.h --- old/kew-2.4.2/src/player.h 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/src/player.h 2024-03-09 09:59:46.000000000 +0100 @@ -10,6 +10,7 @@ #include "chafafunc.h" #include "directorytree.h" #include "playlist.h" +#include "playlist_ui.h" #include "songloader.h" #include "sound.h" #include "term.h" @@ -93,4 +94,3 @@ void resetChosenDir(); #endif - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/playerops.c new/kew-2.4.3/src/playerops.c --- old/kew-2.4.2/src/playerops.c 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/src/playerops.c 2024-03-09 09:59:46.000000000 +0100 @@ -12,7 +12,7 @@ #endif #ifndef ASK_IF_USE_CACHE_LIMIT_SECONDS -#define ASK_IF_USE_CACHE_LIMIT_SECONDS 1 +#define ASK_IF_USE_CACHE_LIMIT_SECONDS 4 #endif struct timespec current_time; @@ -328,7 +328,7 @@ if (currentSong == NULL) return NULL; - return (audioData.currentFileIndex == 0) ? userData.songdataA : userData.songdataB; + return (audioData.currentFileIndex == 0) ? userData.songdataA : userData.songdataB; } void calcElapsedTime() @@ -362,7 +362,6 @@ if (currentSong != NULL && timeSinceLastUpdate >= 1.0) { updatePlaybackPosition(elapsedSeconds); - // Update the last update time to the current time lastUpdateTime = current_time; } } @@ -778,6 +777,12 @@ bool rebuild = false; Node *node = findSelectedEntry(originalPlaylist, chosenRow); + + if (node == NULL) + { + return; + } + Node *song = getNextSong(); int id = node->id; @@ -1125,7 +1130,7 @@ songLoading = true; forceSkip = false; - playbackPlay(&totalPauseSeconds, &pauseSeconds); + playbackPlay(&totalPauseSeconds, &pauseSeconds); loadingdata.loadA = !usingSongDataA; loadingdata.loadingFirstDecoder = true; @@ -1325,7 +1330,7 @@ enableInputBuffering(); showCursor(); - printf("Would you like to enable the library cache for quicker startup times?\nYou can update the cache at any time by pressing 'u'. (y/n): "); + printf("Would you like to enable a (local) library cache for quicker startup times?\nYou can update the cache at any time by pressing 'u'. (y/n): "); fflush(stdout); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/playlist_ui.c new/kew-2.4.3/src/playlist_ui.c --- old/kew-2.4.2/src/playlist_ui.c 1970-01-01 01:00:00.000000000 +0100 +++ new/kew-2.4.3/src/playlist_ui.c 2024-03-09 09:59:46.000000000 +0100 @@ -0,0 +1,176 @@ +#include "playlist_ui.h" + +int startIter = 0; + +void getTerminalSize(int *width, int *height) +{ + getTermSize(width, height); +} + +Node *determineStartNode(Node *head, int *foundAt, bool *startFromCurrent, int listSize) +{ + Node *node = head; + Node *foundNode = NULL; + int numSongs = 0; + *foundAt = -1; + + while (node != NULL && numSongs <= listSize) + { + if (currentSong != NULL && currentSong->id == node->id) + { + *foundAt = numSongs; + foundNode = node; + break; + } + node = node->next; + numSongs++; + } + + *startFromCurrent = (*foundAt > -1) ? true : false; + return foundNode ? foundNode : head; +} + +void preparePlaylistString(Node *node, char *buffer, int bufferSize, int shortenAmount) +{ + if (node == NULL || buffer == NULL) + { + buffer[0] = '\0'; + return; + } + + char filePath[MAXPATHLEN]; + c_strcpy(filePath, sizeof(filePath), node->song.filePath); + char *lastSlash = strrchr(filePath, '/'); + char *lastDot = strrchr(filePath, '.'); + + if (lastSlash != NULL && lastDot != NULL && lastDot > lastSlash) + { + int nameLength = lastDot - lastSlash - 1; + nameLength = (nameLength < bufferSize - 1) ? nameLength : bufferSize - 1; + + strncpy(buffer, lastSlash + 1, nameLength); + buffer[nameLength] = '\0'; + removeUnneededChars(buffer); + shortenString(buffer, shortenAmount); + trim(buffer); + } + else + { + buffer[0] = '\0'; + } +} + +int displayPlaylistItems(Node *startNode, int startIter, int maxListSize, int termWidth, int indent, bool startFromCurrent, int chosenSong, int *chosenNodeId) +{ + int numPrintedRows = 0; + Node *node = startNode; + + char *buffer = (char *)malloc(MAXPATHLEN * sizeof(char)); + + if (!buffer) + { + return 0; + } + + for (int i = startIter; node != NULL && i < startIter + maxListSize; i++) + { + preparePlaylistString(node, buffer, MAXPATHLEN, termWidth - indent - 10); + if (buffer[0] != '\0') + { + setDefaultTextColor(); + printBlankSpaces(indent); + + if (i == chosenSong) + { + *chosenNodeId = node->id; + + printf("\x1b[7m"); + } + + if (currentSong != NULL && currentSong->id == node->id) + { + printf("\e[1m\e[39m"); + } + + if (i + 1 < 10) + printf(" "); + + printf(" %d. %s \n", i + 1, buffer); + + numPrintedRows++; + } + + node = node->next; + } + + free(buffer); + return numPrintedRows; +} + +int displayPlaylist(PlayList *list, int maxListSize, int indent, int *chosenSong, int *chosenNodeId, bool reset) +{ + int termWidth, termHeight; + getTerminalSize(&termWidth, &termHeight); + + int foundAt = -1; + bool startFromCurrent = false; + Node *startNode = determineStartNode(list->head, &foundAt, &startFromCurrent, list->count); + + // Determine chosen song + if (*chosenSong >= list->count) + { + *chosenSong = list->count - 1; + } + + if (*chosenSong < 0) + { + *chosenSong = 0; + } + + int startIter = 0; + + // Determine where to start iterating + startIter = (startFromCurrent && (foundAt < startIter || foundAt > startIter + maxListSize)) ? foundAt : startIter; + + if (*chosenSong < startIter) + { + startIter = *chosenSong; + } + + if (*chosenSong > startIter + maxListSize - round(maxListSize / 2)) + { + startIter = *chosenSong - maxListSize + round(maxListSize / 2); + } + + if (reset && !audioData.endOfListReached) + { + startIter = *chosenSong = foundAt; + } + + // Go up to find the starting node + for (int i = foundAt; i > startIter; i--) + { + if (i > 0 && startNode->prev != NULL) + startNode = startNode->prev; + } + + // Go down to adjust the startNode + for (int i = (foundAt == -1) ? 0 : foundAt; i < startIter; i++) + { + if (startNode->next != NULL) + startNode = startNode->next; + } + + int printedRows = displayPlaylistItems(startNode, startIter, maxListSize, termWidth, indent, startFromCurrent, *chosenSong, chosenNodeId); + + if (printedRows > 1) + { + while (printedRows < maxListSize) + { + printf("\n"); + printedRows++; + } + } + + return printedRows; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/playlist_ui.h new/kew-2.4.3/src/playlist_ui.h --- old/kew-2.4.2/src/playlist_ui.h 1970-01-01 01:00:00.000000000 +0100 +++ new/kew-2.4.3/src/playlist_ui.h 2024-03-09 09:59:46.000000000 +0100 @@ -0,0 +1,11 @@ +#ifndef PLAYLIST_UI_H +#define PLAYLIST_UI_H + +#include "playlist.h" +#include "songloader.h" +#include "term.h" +#include "utils.h" + +int displayPlaylist(PlayList *list, int maxListSize, int indent, int *chosenSong, int *chosenNodeId, bool reset); + +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/settings.c new/kew-2.4.3/src/settings.c --- old/kew-2.4.2/src/settings.c 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/src/settings.c 2024-03-09 09:59:46.000000000 +0100 @@ -434,7 +434,7 @@ fprintf(file, "hideHelp=%s\n", settings->hideHelp); fprintf(file, "lastVolume=%s\n", settings->lastVolume); - fprintf(file, "\n# Cache: Set to 1 to use cache of the library for faster startup times.\n"); + fprintf(file, "\n# Cache: Set to 1 to use cache of the music library directory tree for faster startup times.\n"); fprintf(file, "cacheLibrary=%s\n", settings->cacheLibrary); fprintf(file, "\n# Color values are 0=Black, 1=Red, 2=Green, 3=Yellow, 4=Blue, 5=Magenta, 6=Cyan, 7=White\n"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/soundcommon.c new/kew-2.4.3/src/soundcommon.c --- old/kew-2.4.2/src/soundcommon.c 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/src/soundcommon.c 2024-03-09 09:59:46.000000000 +0100 @@ -1126,33 +1126,49 @@ return output; } -int displaySongNotification(const char *artist, const char *title, const char *cover) -{ - if (!allowNotifications) - return 0; - - char command[MAXPATHLEN + 1024]; - char sanitized_cover[MAXPATHLEN]; - - const char *blacklist = "&;`|*~<>^()[]{}$\\\""; - char *sanitizedArtist = remove_blacklisted_chars(artist, blacklist); - char *sanitizedTitle = remove_blacklisted_chars(title, blacklist); +int displaySongNotification(const char *artist, const char *title, const char *cover) { + if (!allowNotifications) + return 0; - sanitize_filepath(cover, sanitized_cover, sizeof(sanitized_cover)); + char sanitized_cover[MAXPATHLEN]; - if (strlen(artist) <= 0) - { - snprintf(command, sizeof(command), "notify-send -a \"kew\" \"%s\" --icon \"%s\"", sanitizedTitle, sanitized_cover); - } - else - { - snprintf(command, sizeof(command), "notify-send -a \"kew\" \"%s - %s\" --icon \"%s\"", sanitizedArtist, sanitizedTitle, sanitized_cover); + const char *blacklist = "&;`|*~<>^()[]{}$\\\""; + char *sanitizedArtist = remove_blacklisted_chars(artist, blacklist); + char *sanitizedTitle = remove_blacklisted_chars(title, blacklist); + + sanitize_filepath(cover, sanitized_cover, sizeof(sanitized_cover)); + + char message[MAXPATHLEN + 1024]; + if (strlen(artist) > 0) { + snprintf(message, sizeof(message), "%s - %s", sanitizedArtist, sanitizedTitle); + } else { + snprintf(message, sizeof(message), "%s", sanitizedTitle); + } + + char *args[] = {"notify-send", "-a", "kew", message, "--icon", sanitized_cover, NULL}; + + pid_t pid = fork(); + if (pid == -1) { + // Handle error + perror("fork"); + } else if (pid > 0) { + // Parent process + int status; + waitpid(pid, &status, 0); + } else { + // Child process + extern char **environ; + if (execve("/usr/bin/notify-send", args, environ) == -1) { + // Handle error + perror("execve"); + _Exit(EXIT_FAILURE); } + } - free(sanitizedArtist); - free(sanitizedTitle); + free(sanitizedArtist); + free(sanitizedTitle); - return system(command); + return 0; } void executeSwitch(AudioData *pAudioData) @@ -1222,12 +1238,12 @@ { int sysVol = getSystemVolume(); - if (sysVol == 0) + if (sysVol == 0) return 0; int step = 100 / sysVol * 5; - int relativeVolChange = volumeChange / 5 * step; + int relativeVolChange = volumeChange / 5 * step; soundVolume += relativeVolChange; @@ -1239,15 +1255,15 @@ ma_uint64 lastCursor = 0; void m4a_read_pcm_frames(ma_data_source *pDataSource, void *pFramesOut, ma_uint64 frameCount, ma_uint64 *pFramesRead) -{ +{ m4a_decoder *m4a = (m4a_decoder *)pDataSource; - AudioData *pAudioData = (AudioData *)m4a->pReadSeekTellUserData; + AudioData *pAudioData = (AudioData *)m4a->pReadSeekTellUserData; ma_uint64 framesRead = 0; while (framesRead < frameCount) { if (doQuit) - return; + return; if (isImplSwitchReached()) return; @@ -1255,7 +1271,7 @@ if (pthread_mutex_trylock(&dataSourceMutex) != 0) { return; - } + } // Check if a file switch is required if (pAudioData->switchFiles) @@ -1372,7 +1388,7 @@ while (framesRead < frameCount) { if (doQuit) - return; + return; if (isImplSwitchReached()) return; @@ -1380,7 +1396,7 @@ if (pthread_mutex_trylock(&dataSourceMutex) != 0) { return; - } + } // Check if a file switch is required if (pAudioData->switchFiles) @@ -1498,11 +1514,10 @@ if (isImplSwitchReached()) return; - if (pthread_mutex_trylock(&dataSourceMutex) != 0) { return; - } + } // Check if a file switch is required if (pAudioData->switchFiles) @@ -1512,7 +1527,7 @@ break; // Exit the loop after the file switch } - ma_libvorbis *decoder = getCurrentVorbisDecoder(); + ma_libvorbis *decoder = getCurrentVorbisDecoder(); if ((getCurrentImplementationType() != VORBIS && !isSkipToNext()) || (decoder == NULL)) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/soundcommon.h new/kew-2.4.3/src/soundcommon.h --- old/kew-2.4.2/src/soundcommon.h 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/src/soundcommon.h 2024-03-09 09:59:46.000000000 +0100 @@ -6,6 +6,7 @@ #include <miniaudio.h> #include <miniaudio_libopus.h> #include <miniaudio_libvorbis.h> +#include <sys/wait.h> #include "m4a.h" #include <stdatomic.h> #include <stdbool.h> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/utils.c new/kew-2.4.3/src/utils.c --- old/kew-2.4.2/src/utils.c 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/src/utils.c 2024-03-09 09:59:46.000000000 +0100 @@ -4,7 +4,7 @@ utils.c Utility functions for instance for replacing some standard functions with safer alterantives. - + */ void c_sleep(int milliseconds) { @@ -135,15 +135,15 @@ int startsWith(const char *str, const char *prefix) { - size_t strLength = strlen(str); - size_t prefixLength = strlen(prefix); + size_t strLength = strlen(str); + size_t prefixLength = strlen(prefix); - if (prefixLength > strLength) - { - return 0; - } + if (prefixLength > strLength) + { + return 0; + } - return strncmp(str, prefix, prefixLength) == 0; + return strncmp(str, prefix, prefixLength) == 0; } void trim(char *str) @@ -186,7 +186,7 @@ return xdgHome; } -char *getConfigPath() +char *getConfigPathOld() { char *configPath = malloc(MAXPATHLEN); if (!configPath) @@ -221,3 +221,132 @@ return configPath; } + +char *getConfigPath() +{ + char *configPath = malloc(MAXPATHLEN); + if (!configPath) + return NULL; + + const char *xdgConfig = getenv("XDG_CONFIG_HOME"); + if (xdgConfig) + { + snprintf(configPath, MAXPATHLEN, "%s/kew", xdgConfig); + } + else + { + const char *home = getHomePath(); + if (home) + { + snprintf(configPath, MAXPATHLEN, "%s/.config/kew", home); + } + else + { + struct passwd *pw = getpwuid(getuid()); + if (pw) + { + snprintf(configPath, MAXPATHLEN, "%s/.config/kew", pw->pw_dir); + } + else + { + free(configPath); + return NULL; + } + } + } + + return configPath; +} + +int moveConfigFiles() +{ + char *oldPath = getConfigPathOld(); + char *newPath = getConfigPath(); + if (!oldPath || !newPath) + { + + free(oldPath); + free(newPath); + return -1; + } + + struct stat st = {0}; + if (stat(newPath, &st) == -1) + { + mkdir(newPath, 0700); + } + + char oldFileLibrary[MAXPATHLEN]; + char newFileLibrary[MAXPATHLEN]; + char oldFileRc[MAXPATHLEN]; + char newFileRc[MAXPATHLEN]; + + snprintf(oldFileLibrary, MAXPATHLEN, "%s/kewlibrary", oldPath); + snprintf(newFileLibrary, MAXPATHLEN, "%s/kewlibrary", newPath); + snprintf(oldFileRc, MAXPATHLEN, "%s/kewrc", oldPath); + snprintf(newFileRc, MAXPATHLEN, "%s/kewrc", newPath); + + if (access(oldFileLibrary, F_OK) == 0) + { + rename(oldFileLibrary, newFileLibrary); + } + if (access(oldFileRc, F_OK) == 0) + { + rename(oldFileRc, newFileRc); + } + + free(oldPath); + free(newPath); + + return 0; +} + +void removeUnneededChars(char *str) +{ + if (strlen(str) < 6) + { + return; + } + + int i; + for (i = 0; i < 3 && str[i] != '\0' && str[i] != ' '; i++) + { + if (isdigit(str[i]) || str[i] == '-' || str[i] == ' ') + { + int j; + for (j = i; str[j] != '\0'; j++) + { + str[j] = str[j + 1]; + } + str[j] = '\0'; + i--; // Decrement i to re-check the current index + } + } + i = 0; + while (str[i] != '\0') + { + if (str[i] == '-' || str[i] == '_') + { + str[i] = ' '; + } + i++; + } +} + +void shortenString(char *str, size_t maxLength) +{ + size_t length = strlen(str); + + if (length > maxLength) + { + str[maxLength] = '\0'; + } +} + +void printBlankSpaces(int numSpaces) +{ + for (int i = 0; i < numSpaces; i++) + { + printf(" "); + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/utils.h new/kew-2.4.3/src/utils.h --- old/kew-2.4.2/src/utils.h 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/src/utils.h 2024-03-09 09:59:46.000000000 +0100 @@ -14,6 +14,7 @@ #include <stdio.h> #include <stdlib.h> #include <sys/param.h> +#include <sys/stat.h> #include <unistd.h> #include <string.h> #include <time.h> @@ -46,6 +47,16 @@ const char *getHomePath(); +char *getConfigPathOld(); + char *getConfigPath(); +int moveConfigFiles(void); + +void removeUnneededChars(char *str); + +void shortenString(char *str, size_t maxLength); + +void printBlankSpaces(int numSpaces); + #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/visuals.c new/kew-2.4.3/src/visuals.c --- old/kew-2.4.2/src/visuals.c 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/src/visuals.c 2024-03-09 09:59:46.000000000 +0100 @@ -33,14 +33,6 @@ unicodeSupport = true; } -void printBlankSpaces(int numSpaces) -{ - for (int i = 0; i < numSpaces; i++) - { - printf(" "); - } -} - void updateMagnitudes(int height, int width, float maxMagnitude, float *magnitudes) { float exponent = 1.0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.4.2/src/visuals.h new/kew-2.4.3/src/visuals.h --- old/kew-2.4.2/src/visuals.h 2024-02-29 11:18:12.000000000 +0100 +++ new/kew-2.4.3/src/visuals.h 2024-03-09 09:59:46.000000000 +0100 @@ -9,6 +9,7 @@ #include <stdlib.h> #include "sound.h" #include "term.h" +#include "utils.h" #ifndef PIXELDATA_STRUCT #define PIXELDATA_STRUCT @@ -27,5 +28,3 @@ void drawSpectrumVisualizer(int height, int width, PixelData c, int indentation, bool useProfileColors); PixelData increaseLuminosity(PixelData pixel, int amount); - -void printBlankSpaces(int numSpaces);