Add settings menu and sorting options

- Settings to toggle metadata for FLAC/MP3 (sometimes loading the cover images can take a while - which is the reason for introducing this feature).

- Sort alphabetically in ascending/descending order and by smallest/largest file size.

- Also display the back button as long as the CWD is not the root path
This commit is contained in:
Joel16 2019-05-07 12:40:00 -05:00
parent 515d78b749
commit 576d84766e
17 changed files with 295 additions and 26 deletions

View File

@ -75,8 +75,9 @@ add_executable(${PROJECT_NAME}
source/audio/vitaaudiolib.c
source/audio/wav.c
source/audio/xm.c
source/menus/menu_displayfiles.c
source/menus/menu_audioplayer.c
source/menus/menu_displayfiles.c
source/menus/menu_settings.c
)
target_link_libraries(${PROJECT_NAME}

View File

@ -0,0 +1,6 @@
#ifndef _ELEVENMPV_MENU_SETTINGS_H_
#define _ELEVENMPV_MENU_SETTINGS_H_
void Menu_DisplaySettings(void);
#endif

View File

@ -6,7 +6,7 @@
vita2d_texture *icon_dir, *icon_file, *icon_audio, *battery_20, *battery_20_charging, *battery_30, *battery_30_charging, *battery_50, *battery_50_charging, \
*battery_60, *battery_60_charging, *battery_80, *battery_80_charging, *battery_90, *battery_90_charging, *battery_full, *battery_full_charging, \
*battery_low, *battery_unknown, *default_artwork, *default_artwork_blur, *btn_play, *btn_pause, *btn_rewind, *btn_forward, *btn_repeat, \
*btn_shuffle, *btn_repeat_overlay, *btn_shuffle_overlay, *icon_back;
*btn_shuffle, *btn_repeat_overlay, *btn_shuffle_overlay, *icon_back, *toggle_on, *toggle_off, *radio_on, *radio_off;
void Textures_Load(void);
void Textures_Free(void);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 B

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
res/toggle_off.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 B

BIN
res/toggle_on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 899 B

View File

@ -1,4 +1,5 @@
#include "audio.h"
#include "config.h"
#define DR_FLAC_IMPLEMENTATION
#include "dr_flac.h"
@ -19,7 +20,7 @@ static void FLAC_MetaCallback(void *pUserData, drflac_metadata *pMetadata) {
}
int FLAC_Init(const char *path) {
flac = drflac_open_file_with_metadata(path, FLAC_MetaCallback, NULL);
flac = config.meta_flac? drflac_open_file_with_metadata(path, FLAC_MetaCallback, NULL) : drflac_open_file(path);
if (flac == NULL)
return -1;

View File

@ -3,6 +3,7 @@
#include <string.h>
#include "audio.h"
#include "config.h"
// For MP3 ID3 tags
struct genre {
@ -142,18 +143,20 @@ int MP3_Init(const char *path) {
if (v2 != NULL) {
print_v2(&metadata, v2);
for (size_t count = 0; count < v2->pictures; count++) {
mpg123_picture *pic = &v2->picture[count];
char *str = pic->mime_type.p;
if (config.meta_mp3) {
for (size_t count = 0; count < v2->pictures; count++) {
mpg123_picture *pic = &v2->picture[count];
char *str = pic->mime_type.p;
if ((pic->type == 3 ) || (pic->type == 0)) {
if ((!strcasecmp(str, "image/jpg")) || (!strcasecmp(str, "image/jpeg"))) {
metadata.cover_image = vita2d_load_JPEG_buffer(pic->data, pic->size);
break;
}
else if (!strcasecmp(str, "image/png")) {
metadata.cover_image = vita2d_load_PNG_buffer(pic->data);
break;
if ((pic->type == 3 ) || (pic->type == 0)) {
if ((!strcasecmp(str, "image/jpg")) || (!strcasecmp(str, "image/jpeg"))) {
metadata.cover_image = vita2d_load_JPEG_buffer(pic->data, pic->size);
break;
}
else if (!strcasecmp(str, "image/png")) {
metadata.cover_image = vita2d_load_PNG_buffer(pic->data);
break;
}
}
}
}

View File

@ -24,7 +24,7 @@ int Config_Save(config_t config) {
char *buf = malloc(64);
int len = snprintf(buf, 64, config_file, CONFIG_VERSION, config.meta_flac, config.meta_mp3, config.sort);
if (R_FAILED(ret = FS_WriteFile("ux0:data/elevenmpv/config.cfg", buf, len))) {
if (R_FAILED(ret = FS_WriteFile("ux0:data/ElevenMPV/config.cfg", buf, len))) {
free(buf);
return ret;
}
@ -36,7 +36,7 @@ int Config_Save(config_t config) {
int Config_Load(void) {
int ret = 0;
if (!FS_FileExists("ux0:data/elevenmpv/config.cfg")) {
if (!FS_FileExists("ux0:data/ElevenMPV/config.cfg")) {
// set these to the following by default:
config.meta_flac = SCE_FALSE;
config.meta_mp3 = SCE_FALSE;
@ -45,10 +45,10 @@ int Config_Load(void) {
}
SceOff size = 0;
FS_GetFileSize("ux0:data/elevenmpv/config.cfg", &size);
FS_GetFileSize("ux0:data/ElevenMPV/config.cfg", &size);
char *buf = malloc(size + 1);
if (R_FAILED(ret = FS_ReadFile("ux0:data/elevenmpv/config.cfg", buf, size))) {
if (R_FAILED(ret = FS_ReadFile("ux0:data/ElevenMPV/config.cfg", buf, size))) {
free(buf);
return ret;
}
@ -59,7 +59,7 @@ int Config_Load(void) {
// Delete config file if config file is updated. This will rarely happen.
if (config_version_holder < CONFIG_VERSION) {
sceIoRemove("ux0:data/elevenmpv/config.cfg");
sceIoRemove("ux0:data/ElevenMPV/config.cfg");
config.meta_flac = SCE_FALSE;
config.meta_mp3 = SCE_FALSE;
config.sort = 0;
@ -72,17 +72,17 @@ int Config_Load(void) {
int Config_GetLastDirectory(void) {
int ret = 0;
if (!FS_FileExists("ux0:data/elevenmpv/lastdir.txt")) {
FS_WriteFile("ux0:data/elevenmpv/lastdir.txt", ROOT_PATH, strlen(ROOT_PATH) + 1);
if (!FS_FileExists("ux0:data/ElevenMPV/lastdir.txt")) {
FS_WriteFile("ux0:data/ElevenMPV/lastdir.txt", ROOT_PATH, strlen(ROOT_PATH) + 1);
strcpy(cwd, ROOT_PATH); // Set Start Path to "sdmc:/" if lastDir.txt hasn't been created.
}
else {
SceOff size = 0;
FS_GetFileSize("ux0:data/elevenmpv/lastdir.txt", &size);
FS_GetFileSize("ux0:data/ElevenMPV/lastdir.txt", &size);
char *buf = malloc(size + 1);
if (R_FAILED(ret = FS_ReadFile("ux0:data/elevenmpv/lastdir.txt", buf, size))) {
if (R_FAILED(ret = FS_ReadFile("ux0:data/ElevenMPV/lastdir.txt", buf, size))) {
free(buf);
return ret;
}

View File

@ -6,6 +6,7 @@
#include <string.h>
#include "common.h"
#include "config.h"
#include "dirbrowse.h"
#include "fs.h"
#include "menu_audioplayer.h"
@ -29,6 +30,28 @@ static void Dirbrowse_SaveLastDirectory(void) {
free(buf);
}
static int cmpstringp(const void *p1, const void *p2) {
SceIoDirent *entryA = (SceIoDirent *)p1;
SceIoDirent *entryB = (SceIoDirent *)p2;
if ((SCE_S_ISDIR(entryA->d_stat.st_mode)) && !(SCE_S_ISDIR(entryB->d_stat.st_mode)))
return -1;
else if (!(SCE_S_ISDIR(entryA->d_stat.st_mode)) && (SCE_S_ISDIR(entryB->d_stat.st_mode)))
return 1;
else {
if (config.sort == 0) // Sort alphabetically (ascending - A to Z)
return strcasecmp(entryA->d_name, entryB->d_name);
else if (config.sort == 1) // Sort alphabetically (descending - Z to A)
return strcasecmp(entryB->d_name, entryA->d_name);
else if (config.sort == 2) // Sort by file size (largest first)
return entryA->d_stat.st_size > entryB->d_stat.st_size ? -1 : entryA->d_stat.st_size < entryB->d_stat.st_size ? 1 : 0;
else if (config.sort == 3) // Sort by file size (smallest first)
return entryB->d_stat.st_size > entryA->d_stat.st_size ? -1 : entryB->d_stat.st_size < entryA->d_stat.st_size ? 1 : 0;
}
return 0;
}
int Dirbrowse_PopulateFiles(SceBool refresh) {
SceUID dir = 0;
Dirbrowse_RecursiveFree(files);
@ -43,7 +66,7 @@ int Dirbrowse_PopulateFiles(SceBool refresh) {
entryCount++;
sceIoDclose(dir);
qsort(entries, entryCount, sizeof(SceIoDirent), Utils_Alphasort);
qsort(entries, entryCount, sizeof(SceIoDirent), cmpstringp);
for (i = 0; i < entryCount; i++) {
// Ingore null filename
@ -103,6 +126,9 @@ int Dirbrowse_PopulateFiles(SceBool refresh) {
void Dirbrowse_DisplayFiles(void) {
vita2d_font_draw_text(font, 102, 40 + ((72 - vita2d_font_text_height(font, 25, cwd)) / 2) + 20, RGBA8(255, 255, 255, 255), 25, cwd);
if (!(!strcmp(cwd, ROOT_PATH)))
vita2d_draw_texture(icon_back, 25, 54);
int i = 0, printed = 0;
File *file = files; // Draw file list

View File

@ -20,7 +20,7 @@ int main(int argc, char *argv[]) {
font = vita2d_load_font_file("app0:Roboto-Regular.ttf");
Textures_Load();
sceIoMkdir("ux0:data/elevenmpv", 0777);
sceIoMkdir("ux0:data/ElevenMPV", 0777);
Config_Load();
Config_GetLastDirectory();

View File

@ -147,7 +147,7 @@ void Menu_PlayAudio(char *path) {
vita2d_draw_texture(default_artwork_blur, 0, 0);
vita2d_draw_rectangle(0, 0, 960, 40, RGBA8(97, 97, 97, 255));
vita2d_draw_texture(icon_back, 10, 57);
vita2d_draw_texture(icon_back, 10, 60);
StatusBar_Display();
if ((metadata.has_meta) && (metadata.title[0] != '\0') && (metadata.artist[0] != '\0')) {

View File

@ -2,6 +2,7 @@
#include "common.h"
#include "dirbrowse.h"
#include "menu_settings.h"
#include "status_bar.h"
#include "textures.h"
#include "utils.h"
@ -50,6 +51,9 @@ void Menu_DisplayFiles(void) {
Utils_ReadControls();
Menu_HandleControls();
if (pressed & SCE_CTRL_SELECT)
Menu_DisplaySettings();
if (pressed & SCE_CTRL_START)
break;
}

View File

@ -0,0 +1,213 @@
#include "config.h"
#include "common.h"
#include "dirbrowse.h"
#include "menu_settings.h"
#include "status_bar.h"
#include "textures.h"
#include "utils.h"
static void Menu_DisplaySortSettings(void) {
int selection = 0, max_items = 3;
const char *menu_items[] = {
"By name (ascending)",
"By name (descending)",
"By size (largest first)",
"By size (smallest first)"
};
while (SCE_TRUE) {
vita2d_start_drawing();
vita2d_clear_screen();
vita2d_draw_rectangle(0, 0, 960, 40, RGBA8(40, 40, 40, 255));
vita2d_draw_rectangle(0, 40, 960, 72, RGBA8(51, 51, 51, 255));
StatusBar_Display();
vita2d_draw_texture(icon_back, 25, 54);
vita2d_font_draw_text(font, 102, 40 + ((72 - vita2d_font_text_height(font, 25, "Sort Settings")) / 2) + 20, RGBA8(255, 255, 255, 255), 25, "Sort Settings");
int printed = 0;
for (int i = 0; i < max_items + 1; i++) {
if (printed == FILES_PER_PAGE)
break;
if (selection < FILES_PER_PAGE || i > (selection - FILES_PER_PAGE)) {
if (i == selection)
vita2d_draw_rectangle(0, 112 + (72 * printed), 960, 72, RGBA8(230, 230, 230, 255));
vita2d_font_draw_text(font, 30, 120 + (72 / 2) + (72 * printed), RGBA8(51, 51, 51, 255), 25, menu_items[i]);
printed++;
}
}
vita2d_draw_texture(config.sort == 0? radio_on : radio_off, 850, 126);
vita2d_draw_texture(config.sort == 1? radio_on : radio_off, 850, 198);
vita2d_draw_texture(config.sort == 2? radio_on : radio_off, 850, 270);
vita2d_draw_texture(config.sort == 3? radio_on : radio_off, 850, 342);
vita2d_end_drawing();
vita2d_swap_buffers();
Utils_ReadControls();
if (pressed & SCE_CTRL_CIRCLE)
break;
if (pressed & SCE_CTRL_UP)
selection--;
else if (pressed & SCE_CTRL_DOWN)
selection++;
Utils_SetMax(&selection, 0, max_items);
Utils_SetMin(&selection, max_items, 0);
if (pressed & SCE_CTRL_ENTER) {
config.sort = selection;
Config_Save(config);
Dirbrowse_PopulateFiles(SCE_TRUE);
}
}
}
static void Menu_DisplayMetadataSettings(void) {
int selection = 0, max_items = 1;
const char *menu_items[] = {
"Enable FLAC metadata",
"Enable MP3 metadata"
};
while (SCE_TRUE) {
vita2d_start_drawing();
vita2d_clear_screen();
vita2d_draw_rectangle(0, 0, 960, 40, RGBA8(40, 40, 40, 255));
vita2d_draw_rectangle(0, 40, 960, 72, RGBA8(51, 51, 51, 255));
StatusBar_Display();
vita2d_draw_texture(icon_back, 25, 54);
vita2d_font_draw_text(font, 102, 40 + ((72 - vita2d_font_text_height(font, 25, "Metadata Settings")) / 2) + 20, RGBA8(255, 255, 255, 255), 25, "Metadata Settings");
int printed = 0;
for (int i = 0; i < max_items + 1; i++) {
if (printed == FILES_PER_PAGE)
break;
if (selection < FILES_PER_PAGE || i > (selection - FILES_PER_PAGE)) {
if (i == selection)
vita2d_draw_rectangle(0, 112 + (72 * printed), 960, 72, RGBA8(230, 230, 230, 255));
vita2d_font_draw_text(font, 30, 120 + (72 / 2) + (72 * printed), RGBA8(51, 51, 51, 255), 25, menu_items[i]);
printed++;
}
}
vita2d_draw_texture(config.meta_flac == SCE_TRUE? toggle_on : toggle_off, 850, 118);
vita2d_draw_texture(config.meta_mp3 == SCE_TRUE? toggle_on : toggle_off, 850, 190);
vita2d_end_drawing();
vita2d_swap_buffers();
Utils_ReadControls();
if (pressed & SCE_CTRL_CIRCLE)
break;
if (pressed & SCE_CTRL_UP)
selection--;
else if (pressed & SCE_CTRL_DOWN)
selection++;
Utils_SetMax(&selection, 0, max_items);
Utils_SetMin(&selection, max_items, 0);
if (pressed & SCE_CTRL_ENTER) {
switch (selection) {
case 0:
config.meta_flac = !config.meta_flac;
Config_Save(config);
break;
case 1:
config.meta_mp3 = !config.meta_mp3;
Config_Save(config);
break;
}
}
}
}
/*static void Menu_DisplayAbout(void) {
}*/
void Menu_DisplaySettings(void) {
int selection = 0, max_items = 2;
const char *menu_items[] = {
"Sort settings",
"Metadata settings",
"About"
};
while (SCE_TRUE) {
vita2d_start_drawing();
vita2d_clear_screen();
vita2d_draw_rectangle(0, 0, 960, 40, RGBA8(40, 40, 40, 255));
vita2d_draw_rectangle(0, 40, 960, 72, RGBA8(51, 51, 51, 255));
StatusBar_Display();
vita2d_draw_texture(icon_back, 25, 54);
vita2d_font_draw_text(font, 102, 40 + ((72 - vita2d_font_text_height(font, 25, "Settings")) / 2) + 20, RGBA8(255, 255, 255, 255), 25, "Settings");
int printed = 0;
for (int i = 0; i < max_items + 1; i++) {
if (printed == FILES_PER_PAGE)
break;
if (selection < FILES_PER_PAGE || i > (selection - FILES_PER_PAGE)) {
if (i == selection)
vita2d_draw_rectangle(0, 112 + (72 * printed), 960, 72, RGBA8(230, 230, 230, 255));
vita2d_font_draw_text(font, 30, 120 + (72 / 2) + (72 * printed), RGBA8(51, 51, 51, 255), 25, menu_items[i]);
printed++;
}
}
vita2d_end_drawing();
vita2d_swap_buffers();
Utils_ReadControls();
if (pressed & SCE_CTRL_CIRCLE)
break;
if (pressed & SCE_CTRL_UP)
selection--;
else if (pressed & SCE_CTRL_DOWN)
selection++;
Utils_SetMax(&selection, 0, max_items);
Utils_SetMin(&selection, max_items, 0);
if (pressed & SCE_CTRL_ENTER) {
switch (selection) {
case 0:
Menu_DisplaySortSettings();
break;
case 1:
Menu_DisplayMetadataSettings();
break;
case 2:
break;
}
}
}
}

View File

@ -37,6 +37,11 @@ extern SceUChar8 _binary_res_btn_playback_shuffle_overlay_png_start;
extern SceUChar8 _binary_res_default_artwork_png_start;
extern SceUChar8 _binary_res_default_artwork_blur_png_start;
extern SceUChar8 _binary_res_toggle_off_png_start;
extern SceUChar8 _binary_res_toggle_on_png_start;
extern SceUChar8 _binary_res_radio_button_checked_png_start;
extern SceUChar8 _binary_res_radio_button_unchecked_png_start;
static vita2d_texture *Texture_LoadImageBilinear(SceUChar8 *buffer) {
vita2d_texture *texture = vita2d_load_PNG_buffer(buffer);
vita2d_texture_set_filters(texture, SCE_GXM_TEXTURE_FILTER_LINEAR, SCE_GXM_TEXTURE_FILTER_LINEAR);
@ -78,9 +83,19 @@ void Textures_Load(void) {
btn_shuffle_overlay = Texture_LoadImageBilinear(&_binary_res_btn_playback_shuffle_overlay_png_start);
default_artwork = Texture_LoadImageBilinear(&_binary_res_default_artwork_png_start);
default_artwork_blur = Texture_LoadImageBilinear(&_binary_res_default_artwork_blur_png_start);
toggle_on = Texture_LoadImageBilinear(&_binary_res_toggle_on_png_start);
toggle_off = Texture_LoadImageBilinear(&_binary_res_toggle_off_png_start);
radio_on = Texture_LoadImageBilinear(&_binary_res_radio_button_checked_png_start);
radio_off = Texture_LoadImageBilinear(&_binary_res_radio_button_unchecked_png_start);
}
void Textures_Free(void) {
vita2d_free_texture(radio_off);
vita2d_free_texture(radio_on);
vita2d_free_texture(toggle_off);
vita2d_free_texture(toggle_on);
vita2d_free_texture(default_artwork_blur);
vita2d_free_texture(default_artwork);
vita2d_free_texture(btn_shuffle_overlay);