feat: update build tasks, enhance metadata handling, and improve GUI text display
This commit is contained in:
120
source/main.c
120
source/main.c
@@ -11,6 +11,7 @@
|
||||
#include <dirent.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@@ -146,6 +147,125 @@ static int cmpstringp(const void *p1, const void *p2)
|
||||
return strcasecmp(* (char * const *) p1, * (char * const *) p2);
|
||||
}
|
||||
|
||||
/* Check filename extension against supported audio types. Case-insensitive. */
|
||||
static bool isMusicFilename(const char *name)
|
||||
{
|
||||
if(name == NULL)
|
||||
return false;
|
||||
|
||||
const char *ext = strrchr(name, '.');
|
||||
if(ext == NULL || *(ext + 1) == '\0')
|
||||
return false;
|
||||
|
||||
ext++; /* skip dot */
|
||||
char lext[16];
|
||||
size_t i = 0;
|
||||
for(; i < sizeof(lext)-1 && ext[i]; i++)
|
||||
lext[i] = tolower((unsigned char)ext[i]);
|
||||
lext[i] = '\0';
|
||||
|
||||
const char *allowed[] = {"mp3","wav","flac","ogg","opus","sid","m4a","aac", NULL};
|
||||
for(int j = 0; allowed[j] != NULL; j++)
|
||||
if(strcmp(lext, allowed[j]) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Build a list of music filenames (basenames) in the given directory. Caller must free array and each string. */
|
||||
static int buildMusicFileListInDir(const char *dirpath, char ***outFiles)
|
||||
{
|
||||
DIR *dp;
|
||||
struct dirent *ep;
|
||||
char **files = NULL;
|
||||
int fileNum = 0;
|
||||
|
||||
if((dp = opendir(dirpath)) == NULL)
|
||||
return -1;
|
||||
|
||||
while((ep = readdir(dp)) != NULL)
|
||||
{
|
||||
if(ep->d_type == DT_DIR)
|
||||
continue;
|
||||
|
||||
if(!isMusicFilename(ep->d_name))
|
||||
continue;
|
||||
|
||||
files = realloc(files, (fileNum + 1) * sizeof(char*));
|
||||
files[fileNum] = strdup(ep->d_name);
|
||||
fileNum++;
|
||||
}
|
||||
|
||||
if(fileNum > 0)
|
||||
qsort(files, fileNum, sizeof(char*), cmpstringp);
|
||||
|
||||
closedir(dp);
|
||||
*outFiles = files;
|
||||
return fileNum;
|
||||
}
|
||||
|
||||
/* Play next file in the same folder as the currently-playing file. Returns 0 on success, -1 on failure or no-next. */
|
||||
static int playNextFromPath(struct playbackInfo_t *playbackInfo)
|
||||
{
|
||||
if(playbackInfo == NULL || playbackInfo->file[0] == '\0')
|
||||
return -1;
|
||||
|
||||
char fullcpy[PATH_MAX];
|
||||
strncpy(fullcpy, playbackInfo->file, sizeof(fullcpy));
|
||||
fullcpy[sizeof(fullcpy)-1] = '\0';
|
||||
|
||||
/* find last slash */
|
||||
char *slash = strrchr(fullcpy, '/');
|
||||
char dirpath[PATH_MAX];
|
||||
char *basename = NULL;
|
||||
|
||||
if(slash == NULL)
|
||||
{
|
||||
/* No directory component; assume current dir */
|
||||
if(getcwd(dirpath, sizeof(dirpath)) == NULL)
|
||||
return -1;
|
||||
basename = fullcpy;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t dirlen = slash - fullcpy;
|
||||
if(dirlen >= sizeof(dirpath))
|
||||
return -1;
|
||||
memcpy(dirpath, fullcpy, dirlen);
|
||||
dirpath[dirlen] = '\0';
|
||||
basename = slash + 1;
|
||||
}
|
||||
|
||||
char **files = NULL;
|
||||
int count = buildMusicFileListInDir(dirpath, &files);
|
||||
if(count <= 0)
|
||||
return -1;
|
||||
|
||||
int index = -1;
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
if(strcmp(files[i], basename) == 0)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int result = -1;
|
||||
if(index >= 0 && index + 1 < count)
|
||||
{
|
||||
char nextpath[PATH_MAX];
|
||||
snprintf(nextpath, sizeof(nextpath), "%s/%s", dirpath, files[index+1]);
|
||||
result = changeFile(nextpath, playbackInfo);
|
||||
}
|
||||
|
||||
for(int i = 0; i < count; i++)
|
||||
free(files[i]);
|
||||
free(files);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the list of files and folders in current directory to an array.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user