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-07-08 19:07:39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/kew (Old) and /work/SRC/openSUSE:Factory/.kew.new.2080 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "kew" Mon Jul 8 19:07:39 2024 rev:19 rq:1185940 version:2.6.0 Changes: -------- --- /work/SRC/openSUSE:Factory/kew/kew.changes 2024-07-02 18:19:27.630029487 +0200 +++ /work/SRC/openSUSE:Factory/.kew.new.2080/kew.changes 2024-07-08 19:07:57.246068280 +0200 @@ -1,0 +2,16 @@ +Sat Jul 6 09:53:39 UTC 2024 - Muhammad Akbar Yanuar Mantari <mantari...@pm.me> + +- Update to version 2.6.0 + * New command: "kew albums", similar to "kew all" but it queues + one album randomly after the other. Thank you @the-boar for the + suggestion. + * Fixed bug where sometimes kew couldn't find a suitable name for + a playlist file (created by pressing x). + * Made it so that seeking jumps in more reasonable smaller + increments when not in song view. Previously it could jump 30 + seconds at a time. + * Rolled back code related to symlinked directories, it didn't + work with freebsd, possibly others. +- Add clang BuildRequires: build for leap + +------------------------------------------------------------------- Old: ---- kew-2.5.1.tar.gz New: ---- kew-2.6.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ kew.spec ++++++ --- /var/tmp/diff_new_pack.32zE9O/_old 2024-07-08 19:07:57.982095198 +0200 +++ /var/tmp/diff_new_pack.32zE9O/_new 2024-07-08 19:07:57.986095344 +0200 @@ -17,14 +17,18 @@ Name: kew -Version: 2.5.1 +Version: 2.6.0 Release: 0 Summary: A command-line music player License: GPL-2.0-only URL: https://github.com/ravachol/kew Source: %{url}/archive/v%{version}/kew-%{version}.tar.gz BuildRequires: freeimage-devel +%if 0%{?suse_version} < 1600 +BuildRequires: clang >= 17 +%else BuildRequires: gcc >= 13 +%endif BuildRequires: pkgconfig BuildRequires: pkgconfig(chafa) BuildRequires: pkgconfig(fftw3) @@ -37,6 +41,9 @@ %prep %autosetup +%if 0%{?suse_version} < 1600 +sed -i '1s|gcc|clang|' Makefile +%endif %build %make_build ++++++ kew-2.5.1.tar.gz -> kew-2.6.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.5.1/README.md new/kew-2.6.0/README.md --- old/kew-2.5.1/README.md 2024-07-01 14:49:05.000000000 +0200 +++ new/kew-2.6.0/README.md 2024-07-04 13:23:30.000000000 +0200 @@ -106,9 +106,9 @@ sudo make install ``` -A sixel (or equivalent) capable terminal is recommended, like Konsole, Wezterm, or kitty, to display images properly. +A sixel (or equivalent) capable terminal is recommended, like Konsole or kitty, to display images properly. -For a complete list of capable terminals, see this page: [Sixels in Terminal](https://www.arewesixelyet.com/) (github.com). +For a complete list of capable terminals, see this page: [Sixels in Terminal](https://www.arewesixelyet.com/). And for @@ -140,7 +140,9 @@ ``` kew (starting kew with no arguments opens the library view where can choose what to play) -kew all (plays all songs (up to 20 000) in your library, shuffled) +kew all (plays all songs, up to 20 000, in your library, shuffled) + +kew albums (plays all albums, up to 2000, randomly one after the other) kew moonlight son (finds and plays moonlight sonata) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.5.1/docs/kew-manpage.mdoc new/kew-2.6.0/docs/kew-manpage.mdoc --- old/kew-2.5.1/docs/kew-manpage.mdoc 2024-07-01 14:49:05.000000000 +0200 +++ new/kew-2.6.0/docs/kew-manpage.mdoc 2024-07-04 13:23:30.000000000 +0200 @@ -72,6 +72,10 @@ Start .Nm with all songs loaded into a playlist. +.It kew albums +Start +.Nm +with all albums randomly added one after the other in the playlist. .It kew moonlight son Play moonlight sonata. .It kew moon diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.5.1/docs/kew.1 new/kew-2.6.0/docs/kew.1 --- old/kew-2.5.1/docs/kew.1 2024-07-01 14:49:05.000000000 +0200 +++ new/kew-2.6.0/docs/kew.1 2024-07-04 13:23:30.000000000 +0200 @@ -74,6 +74,11 @@ \fBkew\fR with all songs loaded into a playlist. .TP 9n +kew albums +Start +\fBkew\fR +with all albums randomly added one after the other in the playlist. +.TP 9n kew moonlight son Play moonlight sonata. .TP 9n diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.5.1/src/file.c new/kew-2.6.0/src/file.c --- old/kew-2.5.1/src/file.c 2024-07-01 14:49:05.000000000 +0200 +++ new/kew-2.6.0/src/file.c 2024-07-04 13:23:30.000000000 +0200 @@ -127,7 +127,7 @@ } char entryPath[MAXPATHLEN]; - char *currentDir = get_current_dir_name(); + char *currentDir = getcwd(NULL, 0); snprintf(entryPath, sizeof(entryPath), "%s/%s", currentDir, dir->d_name); free(currentDir); @@ -141,7 +141,7 @@ if (((exactSearch && (strcasecmp(dir->d_name, searching) == 0)) || (!exactSearch && c_strcasestr(dir->d_name, searching) != NULL)) && (searchType != FileOnly) && (searchType != SearchPlayList)) { - char *curDir = get_current_dir_name(); + char *curDir = getcwd(NULL, 0); snprintf(result, MAXPATHLEN, "%s/%s", curDir, dir->d_name); free(curDir); copyresult = true; @@ -187,7 +187,7 @@ if ((exactSearch && (strcasecmp(dir->d_name, searching) == 0)) || (!exactSearch && c_strcasestr(dir->d_name, searching) != NULL)) { - char *curDir = get_current_dir_name(); + char *curDir = getcwd(NULL, 0); snprintf(result, MAXPATHLEN, "%s/%s", curDir, dir->d_name); copyresult = true; free(curDir); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.5.1/src/kew.c new/kew-2.6.0/src/kew.c --- old/kew-2.5.1/src/kew.c 2024-07-01 14:49:05.000000000 +0200 +++ new/kew-2.6.0/src/kew.c 2024-07-04 13:23:30.000000000 +0200 @@ -868,7 +868,6 @@ if (res >= 0) { - logTime("createAudioDevice()"); res = createAudioDevice(&userData); } @@ -892,14 +891,12 @@ g_unix_signal_add(SIGINT, on_sigint, main_loop); - logTime("emitStartPlayingMpris()"); if (song != NULL) emitStartPlayingMpris(); else emitPlaybackStoppedMpris(); g_timeout_add(50, mainloop_callback, NULL); - logTime("g_main_loop_run()"); g_main_loop_run(main_loop); g_main_loop_unref(main_loop); } @@ -970,7 +967,7 @@ { if (originalPlaylist == NULL) { - logTime("deepCopyPlayList()"); + originalPlaylist = malloc(sizeof(PlayList)); *originalPlaylist = deepCopyPlayList(&playlist); } @@ -1012,7 +1009,6 @@ pthread_mutex_init(&(loadingdata.mutex), NULL); pthread_mutex_init(&(playlist.mutex), NULL); nerdFontsEnabled = hasNerdFonts(); - logTime("createLibrary"); createLibrary(&settings); setlocale(LC_ALL, ""); fflush(stdout); @@ -1056,19 +1052,28 @@ void playAll() { - logTime("init()"); init(); - logTime("createPlayListFromFileSystemEntry()"); createPlayListFromFileSystemEntry(library, &playlist, MAX_FILES); if (playlist.count == 0) { exit(0); - } - logTime("shufflePlaylist()"); + } shufflePlaylist(&playlist); run(); } +void playAllAlbums() +{ + init(); + addShuffledAlbumsToPlayList(library, &playlist, MAX_FILES); + if (playlist.count == 0) + { + exit(0); + } + run(); +} + + void removeArgElement(char *argv[], int index, int *argc) { if (index < 0 || index >= *argc) @@ -1188,6 +1193,10 @@ { playAll(); } + else if (argc == 2 && strcmp(argv[1], "albums") == 0) + { + playAllAlbums(); + } else if (argc == 2 && strcmp(argv[1], ".") == 0) { playSpecialPlaylist(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.5.1/src/player.c new/kew-2.6.0/src/player.c --- old/kew-2.5.1/src/player.c 2024-07-01 14:49:05.000000000 +0200 +++ new/kew-2.6.0/src/player.c 2024-07-04 13:23:30.000000000 +0200 @@ -22,7 +22,7 @@ } PixelData; #endif -const char VERSION[] = "2.5.1"; +const char VERSION[] = "2.6.0"; const int ABSOLUTE_MIN_WIDTH = 68; bool visualizerEnabled = true; bool coverEnabled = true; @@ -39,7 +39,7 @@ bool fastForwarding = false; bool rewinding = false; bool nerdFontsEnabled = true; -int numProgressBars = 15; +int numProgressBars = 35; int elapsedBars = 0; int chosenRow = 0; int chosenSong = 0; @@ -155,6 +155,7 @@ printf(" (Saves the music library path. Use this the first time. Ie: kew path \"/home/joe/Music/\")\n"); printf(" kew (no argument, opens library)\n"); printf(" kew all (loads all your songs up to 10 000)\n"); + printf(" kew albums (plays all albums up to 2000 randomly one after the other)"); printf(" kew <song name,directory or playlist words>\n"); printf(" kew --help, -? or -h\n"); printf(" kew --version or -v\n"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.5.1/src/playlist.c new/kew-2.6.0/src/playlist.c --- old/kew-2.5.1/src/playlist.c 2024-07-01 14:49:05.000000000 +0200 +++ new/kew-2.6.0/src/playlist.c 2024-07-04 13:23:30.000000000 +0200 @@ -580,6 +580,35 @@ return 0; } +// Function to generate the filename with the .m3u extension +void generateM3UFilename(const char *basePath, const char *filePath, char *m3uFilename, size_t size) { + // Find the last occurrence of '/' in the file path to get the base name + const char *baseName = strrchr(filePath, '/'); + if (baseName == NULL) { + baseName = filePath; // No '/' found, use the entire filename + } else { + baseName++; // Skip the '/' character + } + + // Find the last occurrence of '.' in the base name + const char *dot = strrchr(baseName, '.'); + if (dot == NULL) { + // No '.' found, copy the base name and append ".m3u" + if (basePath[strlen(basePath) - 1] == '/') { + snprintf(m3uFilename, size, "%s%s.m3u", basePath, baseName); + } else { + snprintf(m3uFilename, size, "%s/%s.m3u", basePath, baseName); + } + } else { + // Copy the base name up to the dot and append ".m3u" + size_t baseNameLen = dot - baseName; + if (basePath[strlen(basePath) - 1] == '/') { + snprintf(m3uFilename, size, "%s%.*s.m3u", basePath, (int)baseNameLen, baseName); + } else { + snprintf(m3uFilename, size, "%s/%.*s.m3u", basePath, (int)baseNameLen, baseName); + } + } +} void writeM3UFile(const char *filename, PlayList *playlist) { FILE *file = fopen(filename, "w"); @@ -648,22 +677,15 @@ { return; } - - char playlistPath[MAXPATHLEN]; - playlistPath[0] = '\0'; - c_strcpy(playlistPath, sizeof(playlistPath), path); - if (playlistPath[0] == '\0') - { + if (playlist.head == NULL || playlist.head->song.filePath == NULL) return; - } - - if (playlistPath[strlen(playlistPath) - 1] != '/') - strcat(playlistPath, "/"); + + char m3uFilename[MAXPATHLEN]; - strcat(playlistPath, playlistName); + generateM3UFilename(path, playlist.head->song.filePath, m3uFilename, sizeof(m3uFilename)); - writeM3UFile(playlistPath, &playlist); + writeM3UFile(m3uFilename, &playlist); } Node *deepCopyNode(Node *originalNode) @@ -817,3 +839,128 @@ { traverseFileSystemEntry(root, list, playlistMax); } + +int isMusicFile(const char *filename) +{ + const char *extensions[] = {".m4a", ".aac",".mp4", ".mp3", ".ogg", ".flac",".wav", ".opus"}; + + size_t numExtensions = sizeof(extensions) / sizeof(extensions[0]); + + for (size_t i = 0; i < numExtensions; i++) + { + if (strstr(filename, extensions[i]) != NULL) + { + return 1; + } + } + + return 0; +} + +int containsMusicFiles(FileSystemEntry *entry) +{ + if (entry == NULL) + return 0; + + FileSystemEntry *child = entry->children; + + while (child != NULL) + { + if (!child->isDirectory && isMusicFile(child->name)) + { + return 1; + } + child = child->next; + } + + return 0; +} + +void addAlbumToPlayList(PlayList *list, FileSystemEntry *album, int playlistMax) +{ + FileSystemEntry *entry = album->children; + + while (entry != NULL && list->count < playlistMax) + { + if (!entry->isDirectory && isMusicFile(entry->name)) + { + addSongToPlayList(list, entry->fullPath, playlistMax); + } + entry = entry->next; + } +} + +void addAlbumsToPlayList(FileSystemEntry *entry, PlayList *list, int playlistMax) +{ + if (entry == NULL || list->count >= playlistMax) + return; + + if (entry->isDirectory && containsMusicFiles(entry)) + { + addAlbumToPlayList(list, entry, playlistMax); + } + + if (entry->isDirectory && entry->children != NULL) + { + addAlbumsToPlayList(entry->children, list, playlistMax); + } + + if (entry->next != NULL) + { + addAlbumsToPlayList(entry->next, list, playlistMax); + } +} + +void shuffleEntries(FileSystemEntry **array, size_t n) +{ + if (n > 1) + { + size_t i; + for (i = 0; i < n - 1; i++) + { + size_t j = i + rand() / (RAND_MAX / (n - i) + 1); + FileSystemEntry *temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } + } +} + +void collectAlbums(FileSystemEntry *entry, FileSystemEntry **albums, size_t *count) +{ + if (entry == NULL) + return; + + if (entry->isDirectory && containsMusicFiles(entry)) + { + albums[*count] = entry; + (*count)++; + } + + if (entry->isDirectory && entry->children != NULL) + { + collectAlbums(entry->children, albums, count); + } + + if (entry->next != NULL) + { + collectAlbums(entry->next, albums, count); + } +} + +void addShuffledAlbumsToPlayList(FileSystemEntry *root, PlayList *list, int playlistMax) +{ + size_t maxAlbums = 2000; + FileSystemEntry *albums[maxAlbums]; + size_t albumCount = 0; + + collectAlbums(root, albums, &albumCount); + + srand(time(NULL)); + shuffleEntries(albums, albumCount); + + for (size_t i = 0; i < albumCount && list->count < playlistMax; i++) + { + addAlbumToPlayList(list, albums[i], playlistMax); + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.5.1/src/playlist.h new/kew-2.6.0/src/playlist.h --- old/kew-2.5.1/src/playlist.h 2024-07-01 14:49:05.000000000 +0200 +++ new/kew-2.6.0/src/playlist.h 2024-07-04 13:23:30.000000000 +0200 @@ -68,6 +68,8 @@ int makePlaylist(int argc, char *argv[], bool exactSearch, const char *path); +void writeCurrentPlaylistToM3UFile(PlayList *playlist); + void writeM3UFile(const char *filename, PlayList *playlist); void loadSpecialPlaylist(const char *directory); @@ -87,3 +89,5 @@ int findNodeInList(PlayList *list, int id, Node **foundNode); void createPlayListFromFileSystemEntry(FileSystemEntry *root, PlayList *list, int playlistMax); + +void addShuffledAlbumsToPlayList(FileSystemEntry *root, PlayList *list, int playlistMax); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kew-2.5.1/src/sound.c new/kew-2.6.0/src/sound.c --- old/kew-2.5.1/src/sound.c 2024-07-01 14:49:05.000000000 +0200 +++ new/kew-2.6.0/src/sound.c 2024-07-04 13:23:30.000000000 +0200 @@ -468,22 +468,18 @@ int createAudioDevice(UserData *userData) { - logTime("ma_context_init"); ma_context_init(NULL, 0, NULL, &context); - logTime("switchAudioImplementation"); if (switchAudioImplementation() >= 0) { SongData *currentSongData = userData->currentSongData; if (currentSongData != NULL && currentSongData->hasErrors == 0 && currentSongData->metadata && strlen(currentSongData->metadata->title) > 0) { - logTime("displaySongNotification"); displaySongNotification(currentSongData->metadata->artist, currentSongData->metadata->title, currentSongData->coverArtPath); gint64 length = getLengthInSec(currentSongData->duration); // update mpris - logTime("emitMetadataChanged"); emitMetadataChanged( currentSongData->metadata->title, currentSongData->metadata->artist,