Inital source commit
108
CMakeLists.txt
Normal file
@ -0,0 +1,108 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||
if(DEFINED ENV{VITASDK})
|
||||
set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file")
|
||||
else()
|
||||
message(FATAL_ERROR "Please define VITASDK to point to your SDK path!")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
project(eleven_music_player_vita)
|
||||
include("${VITASDK}/share/vita.cmake" REQUIRED)
|
||||
|
||||
set(VITA_APP_NAME "Eleven Music Player")
|
||||
set(VITA_TITLEID "ELEVENMPV")
|
||||
set(VITA_VERSION "01.00")
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Wall -Werror -ffast-math")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
set(VITA_MKSFOEX_FLAGS "${VITA_MKSFOEX_FLAGS} -d PARENTAL_LEVEL=1")
|
||||
|
||||
FUNCTION(ADD_RESOURCES out_var)
|
||||
SET(result)
|
||||
FOREACH(in_f ${ARGN})
|
||||
SET(out_f "${CMAKE_CURRENT_BINARY_DIR}/${in_f}.o")
|
||||
GET_FILENAME_COMPONENT(out_dir ${out_f} DIRECTORY)
|
||||
ADD_CUSTOM_COMMAND(OUTPUT ${out_f}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${out_dir}
|
||||
COMMAND ${CMAKE_LINKER} -r -b binary -o ${out_f} ${in_f}
|
||||
DEPENDS ${in_f}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMENT "Building resource ${out_f}"
|
||||
VERBATIM
|
||||
)
|
||||
LIST(APPEND result ${out_f})
|
||||
ENDFOREACH()
|
||||
SET(${out_var} "${result}" PARENT_SCOPE)
|
||||
ENDFUNCTION()
|
||||
|
||||
file(GLOB res_files RELATIVE
|
||||
${CMAKE_SOURCE_DIR}
|
||||
res/*.png
|
||||
)
|
||||
add_resources(elevenmp_res ${res_files})
|
||||
|
||||
include_directories(
|
||||
include
|
||||
include/audio
|
||||
include/menus
|
||||
)
|
||||
|
||||
link_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
${elevenmp_res}
|
||||
source/common.c
|
||||
source/dirbrowse.c
|
||||
source/fs.c
|
||||
source/main.c
|
||||
source/status_bar.c
|
||||
source/textures.c
|
||||
source/utils.c
|
||||
source/audio/audio.c
|
||||
source/audio/flac.c
|
||||
source/audio/mp3.c
|
||||
source/audio/ogg.c
|
||||
source/audio/stb_vorbis.c
|
||||
source/audio/vitaaudiolib.c
|
||||
source/audio/wav.c
|
||||
source/audio/xm.c
|
||||
source/menus/menu_displayfiles.c
|
||||
source/menus/menu_audioplayer.c
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
vita2d
|
||||
freetype
|
||||
png
|
||||
jpeg
|
||||
z
|
||||
m
|
||||
c
|
||||
mpg123
|
||||
SceAppUtil_stub
|
||||
SceAudio_stub
|
||||
SceAudiodec_stub
|
||||
SceCommonDialog_stub
|
||||
SceCtrl_stub
|
||||
SceDisplay_stub
|
||||
SceGxm_stub
|
||||
ScePower_stub
|
||||
SceRtc_stub
|
||||
SceSysmodule_stub
|
||||
SceTouch_stub
|
||||
)
|
||||
|
||||
vita_create_self(${PROJECT_NAME}.self ${PROJECT_NAME})
|
||||
vita_create_vpk(${PROJECT_NAME}.vpk ${VITA_TITLEID} ${PROJECT_NAME}.self
|
||||
VERSION ${VITA_VERSION}
|
||||
NAME ${VITA_APP_NAME}
|
||||
FILE sce_sys/icon0.png sce_sys/icon0.png
|
||||
FILE sce_sys/livearea/contents/bg.png sce_sys/livearea/contents/bg.png
|
||||
FILE sce_sys/livearea/contents/startup.png sce_sys/livearea/contents/startup.png
|
||||
FILE sce_sys/livearea/contents/template.xml sce_sys/livearea/contents/template.xml
|
||||
FILE res/Roboto-Regular.ttf Roboto-Regular.ttf
|
||||
)
|
18
README.md
@ -1 +1,17 @@
|
||||
# ElevenMPV
|
||||
# ElevenMPV - Eleven Music Player VITA
|
||||
|
||||
A homebrew music player for Playstation VITA that aims to support many different audio formats compared to the offical PS VITA music application.
|
||||
|
||||
# Currently supported formats: (16 bit signed samples)
|
||||
- FLAC
|
||||
- MP3
|
||||
- OGG
|
||||
- WAV (A-law and u-law, Microsoft ADPCM, IMA ADPCM)
|
||||
- XM (Extended module)
|
||||
|
||||
# Features:
|
||||
- Browse ux0:/ to play the above audio formats.
|
||||
- Pause/Play audio.
|
||||
- Shuffle/Repeat audio.
|
||||
- Next/Previous track in current working directory.
|
||||
- Display ID3v1 and ID3v2 metadata for MP3 files.
|
||||
|
32
include/audio/audio.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef _ELEVENMPV_AUDIO_H_
|
||||
#define _ELEVENMPV_AUDIO_H_
|
||||
|
||||
#include <psp2/types.h>
|
||||
#include <vita2d.h>
|
||||
|
||||
extern SceBool playing, paused;
|
||||
|
||||
typedef struct {
|
||||
SceBool has_meta;
|
||||
char title[31];
|
||||
char album[31];
|
||||
char artist[31];
|
||||
char year[5];
|
||||
char comment[31];
|
||||
char genre[31];
|
||||
vita2d_texture *cover_image;
|
||||
} Audio_Metadata;
|
||||
|
||||
extern Audio_Metadata metadata;
|
||||
|
||||
int Audio_Init(const char *path);
|
||||
SceBool Audio_IsPaused(void);
|
||||
void Audio_Pause(void);
|
||||
void Audio_Stop(void);
|
||||
SceUInt64 Audio_GetPosition(void);
|
||||
SceUInt64 Audio_GetLength(void);
|
||||
SceUInt64 Audio_GetPositionSeconds(void);
|
||||
SceUInt64 Audio_GetLengthSeconds(void);
|
||||
void Audio_Term(void);
|
||||
|
||||
#endif
|
8196
include/audio/dr_flac.h
Normal file
4377
include/audio/dr_wav.h
Normal file
14
include/audio/flac.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef _ELEVENMPV_AUDIO_FLAC_H_
|
||||
#define _ELEVENMPV_AUDIO_FLAC_H_
|
||||
|
||||
#include <psp2/types.h>
|
||||
|
||||
int FLAC_Init(const char *path);
|
||||
SceUInt32 FLAC_GetSampleRate(void);
|
||||
SceUInt8 FLAC_GetChannels(void);
|
||||
void FLAC_Decode(void *buf, unsigned int length, void *userdata);
|
||||
SceUInt64 FLAC_GetPosition(void);
|
||||
SceUInt64 FLAC_GetLength(void);
|
||||
void FLAC_Term(void);
|
||||
|
||||
#endif
|
2667
include/audio/jar_xm.h
Normal file
14
include/audio/mp3.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef _ELEVENMPV_AUDIO_MP3_H_
|
||||
#define _ELEVENMPV_AUDIO_MP3_H_
|
||||
|
||||
#include <psp2/types.h>
|
||||
|
||||
int MP3_Init(const char *path);
|
||||
SceUInt32 MP3_GetSampleRate(void);
|
||||
SceUInt8 MP3_GetChannels(void);
|
||||
void MP3_Decode(void *buf, unsigned int length, void *userdata);
|
||||
SceUInt64 MP3_GetPosition(void);
|
||||
SceUInt64 MP3_GetLength(void);
|
||||
void MP3_Term(void);
|
||||
|
||||
#endif
|
14
include/audio/ogg.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef _ELEVENMPV_AUDIO_OGG_H_
|
||||
#define _ELEVENMPV_AUDIO_OGG_H_
|
||||
|
||||
#include <psp2/types.h>
|
||||
|
||||
int OGG_Init(const char *path);
|
||||
SceUInt32 OGG_GetSampleRate(void);
|
||||
SceUInt8 OGG_GetChannels(void);
|
||||
void OGG_Decode(void *buf, unsigned int length, void *userdata);
|
||||
SceUInt64 OGG_GetPosition(void);
|
||||
SceUInt64 OGG_GetLength(void);
|
||||
void OGG_Term(void);
|
||||
|
||||
#endif
|
40
include/audio/vitaaudiolib.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef _ELEVENMPV_AUDIO_LIB_H_
|
||||
#define _ELEVENMPV_AUDIO_LIB_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <psp2/audioout.h>
|
||||
|
||||
#define VITA_NUM_AUDIO_CHANNELS 1
|
||||
#define VITA_NUM_AUDIO_SAMPLES 1024
|
||||
#define VITA_VOLUME_MAX 0x8000
|
||||
|
||||
typedef void (* vitaAudioCallback_t)(void *buf, unsigned int reqn, void *pdata);
|
||||
|
||||
typedef struct {
|
||||
int threadhandle;
|
||||
int handle;
|
||||
int volumeleft;
|
||||
int volumeright;
|
||||
vitaAudioCallback_t callback;
|
||||
void *pdata;
|
||||
} VITA_audio_channelinfo;
|
||||
|
||||
typedef int (* vitaAudioThreadfunc_t)(int args, void *argp);
|
||||
|
||||
void vitaAudioSetVolume(int channel, int left, int right);
|
||||
int vitaAudioSetFrequency(int channel, int frequency);
|
||||
void vitaAudioChannelThreadCallback(int channel, void *buf, unsigned int reqn);
|
||||
void vitaAudioSetChannelCallback(int channel, vitaAudioCallback_t callback, void *pdata);
|
||||
int vitaAudioOutBlocking(unsigned int channel, unsigned int vol1, unsigned int vol2, void *buf);
|
||||
int vitaAudioInit(int frequency, SceAudioOutMode mode);
|
||||
void vitaAudioEndPre(void);
|
||||
void vitaAudioEnd(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
14
include/audio/wav.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef _ELEVENMPV_AUDIO_WAV_H_
|
||||
#define _ELEVENMPV_AUDIO_WAV_H_
|
||||
|
||||
#include <psp2/types.h>
|
||||
|
||||
int WAV_Init(const char *path);
|
||||
SceUInt32 WAV_GetSampleRate(void);
|
||||
SceUInt8 WAV_GetChannels(void);
|
||||
void WAV_Decode(void *buf, unsigned int length, void *userdata);
|
||||
SceUInt64 WAV_GetPosition(void);
|
||||
SceUInt64 WAV_GetLength(void);
|
||||
void WAV_Term(void);
|
||||
|
||||
#endif
|
14
include/audio/xm.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef _ELEVENMPV_AUDIO_XM_H_
|
||||
#define _ELEVENMPV_AUDIO_XM_H_
|
||||
|
||||
#include <psp2/types.h>
|
||||
|
||||
int XM_Init(const char *path);
|
||||
SceUInt32 XM_GetSampleRate(void);
|
||||
SceUInt8 XM_GetChannels(void);
|
||||
void XM_Decode(void *buf, unsigned int length, void *userdata);
|
||||
SceUInt64 XM_GetPosition(void);
|
||||
SceUInt64 XM_GetLength(void);
|
||||
void XM_Term(void);
|
||||
|
||||
#endif
|
26
include/common.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef _ELEVENMPV_COMMON_H_
|
||||
#define _ELEVENMPV_COMMON_H_
|
||||
|
||||
#include <psp2/ctrl.h>
|
||||
#include <psp2/types.h>
|
||||
#include <vita2d.h>
|
||||
|
||||
/// Checks whether a result code indicates success.
|
||||
#define R_SUCCEEDED(res) ((res)>=0)
|
||||
/// Checks whether a result code indicates failure.
|
||||
#define R_FAILED(res) ((res)<0)
|
||||
/// Returns the level of a result code.
|
||||
|
||||
#define MAX_FILES 1024
|
||||
#define ROOT_PATH "ux0:/"
|
||||
|
||||
#define FILES_PER_PAGE 6
|
||||
|
||||
extern vita2d_font *font;
|
||||
extern enum SceCtrlButtons SCE_CTRL_ENTER, SCE_CTRL_CANCEL;
|
||||
extern SceUInt32 pressed;
|
||||
extern int position;
|
||||
extern int file_count;
|
||||
extern char cwd[512];
|
||||
|
||||
#endif
|
21
include/dirbrowse.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef _ELEVENMPV_DIRBROWSE_H_
|
||||
#define _ELEVENMPV_DIRBROWSE_H_
|
||||
|
||||
#include <psp2/types.h>
|
||||
|
||||
typedef struct File {
|
||||
struct File *next; // Next item
|
||||
int is_dir; // Folder flag
|
||||
char name[256]; // File name
|
||||
char ext[5]; // File extension
|
||||
} File;
|
||||
|
||||
extern File *files;
|
||||
|
||||
int Dirbrowse_PopulateFiles(SceBool clear);
|
||||
void Dirbrowse_DisplayFiles(void);
|
||||
File *Dirbrowse_GetFileIndex(int index);
|
||||
void Dirbrowse_OpenFile(void);
|
||||
int Dirbrowse_Navigate(SceBool parent);
|
||||
|
||||
#endif
|
13
include/fs.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef _ELEVENMPV_FS_H_
|
||||
#define _ELEVENMPV_FS_H_
|
||||
|
||||
#include <psp2/types.h>
|
||||
|
||||
SceBool FS_FileExists(const char *path);
|
||||
SceBool FS_DirExists(const char *path);
|
||||
const char *FS_GetFileExt(const char *filename);
|
||||
int FS_GetFileSize(const char *path, SceOff *size);
|
||||
int FS_ReadFile(const char *path, void *buf, int size);
|
||||
int FS_WriteFile(char *path, void *buf, int size);
|
||||
|
||||
#endif
|
6
include/menus/menu_audioplayer.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef _ELEVENMPV_MENU_PLAYAUDIO_H_
|
||||
#define _ELEVENMPV_MENU_PLAYAUDIO_H_
|
||||
|
||||
void Menu_PlayAudio(char *path);
|
||||
|
||||
#endif
|
6
include/menus/menu_displayfiles.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef _ELEVENMPV_MENU_DISPLAYFILES_H_
|
||||
#define _ELEVENMPV_MENU_DISPLAYFILES_H_
|
||||
|
||||
void Menu_DisplayFiles(void);
|
||||
|
||||
#endif
|
6
include/status_bar.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef _ELEVENMPV_STATUS_BAR_H_
|
||||
#define _ELEVENMPV_STATUS_BAR_H_
|
||||
|
||||
void StatusBar_Display(void);
|
||||
|
||||
#endif
|
14
include/textures.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef _ELEVENMPV_TEXTURES_H_
|
||||
#define _ELEVENMPV_TEXTURES_H_
|
||||
|
||||
#include <vita2d.h>
|
||||
|
||||
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;
|
||||
|
||||
void Textures_Load(void);
|
||||
void Textures_Free(void);
|
||||
|
||||
#endif
|
14
include/utils.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef _ELEVENMPV_UTILS_H_
|
||||
#define _ELEVENMPV_UTILS_H_
|
||||
|
||||
void Utils_SetMax(int *set, int value, int max);
|
||||
void Utils_SetMin(int *set, int value, int min);
|
||||
int Utils_ReadControls(void);
|
||||
int Utils_InitAppUtil(void);
|
||||
int Utils_TermAppUtil(void);
|
||||
int Utils_GetEnterButton(void);
|
||||
int Utils_GetCancelButton(void);
|
||||
int Utils_Alphasort(const void *p1, const void *p2);
|
||||
char *Utils_Basename(const char *filename);
|
||||
|
||||
#endif
|
BIN
res/Roboto-Regular.ttf
Normal file
BIN
res/battery_20.png
Normal file
After Width: | Height: | Size: 273 B |
BIN
res/battery_20_charging.png
Normal file
After Width: | Height: | Size: 449 B |
BIN
res/battery_30.png
Normal file
After Width: | Height: | Size: 274 B |
BIN
res/battery_30_charging.png
Normal file
After Width: | Height: | Size: 467 B |
BIN
res/battery_50.png
Normal file
After Width: | Height: | Size: 269 B |
BIN
res/battery_50_charging.png
Normal file
After Width: | Height: | Size: 462 B |
BIN
res/battery_60.png
Normal file
After Width: | Height: | Size: 269 B |
BIN
res/battery_60_charging.png
Normal file
After Width: | Height: | Size: 449 B |
BIN
res/battery_80.png
Normal file
After Width: | Height: | Size: 277 B |
BIN
res/battery_80_charging.png
Normal file
After Width: | Height: | Size: 464 B |
BIN
res/battery_90.png
Normal file
After Width: | Height: | Size: 276 B |
BIN
res/battery_90_charging.png
Normal file
After Width: | Height: | Size: 482 B |
BIN
res/battery_full.png
Normal file
After Width: | Height: | Size: 236 B |
BIN
res/battery_full_charging.png
Normal file
After Width: | Height: | Size: 436 B |
BIN
res/battery_low.png
Normal file
After Width: | Height: | Size: 258 B |
BIN
res/battery_unknown.png
Normal file
After Width: | Height: | Size: 592 B |
BIN
res/btn_playback_forward.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
res/btn_playback_pause.png
Normal file
After Width: | Height: | Size: 174 B |
BIN
res/btn_playback_play.png
Normal file
After Width: | Height: | Size: 608 B |
BIN
res/btn_playback_repeat.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
res/btn_playback_repeat_overlay.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
res/btn_playback_rewind.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
res/btn_playback_shuffle.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
res/btn_playback_shuffle_overlay.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
res/default_artwork.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
res/default_artwork_blur.png
Normal file
After Width: | Height: | Size: 789 KiB |
BIN
res/icon_audio.png
Normal file
After Width: | Height: | Size: 669 B |
BIN
res/icon_back.png
Normal file
After Width: | Height: | Size: 397 B |
BIN
res/icon_file.png
Normal file
After Width: | Height: | Size: 575 B |
BIN
res/icon_folder.png
Normal file
After Width: | Height: | Size: 476 B |
BIN
sce_sys/icon0.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
sce_sys/livearea/contents/bg.png
Normal file
After Width: | Height: | Size: 321 KiB |
BIN
sce_sys/livearea/contents/startup.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
11
sce_sys/livearea/contents/template.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<livearea style="a1" format-ver="01.00" content-rev="1">
|
||||
<livearea-background>
|
||||
<image>bg.png</image>
|
||||
</livearea-background>
|
||||
|
||||
<gate>
|
||||
<startup-image>startup.png</startup-image>
|
||||
</gate>
|
||||
</livearea>
|
289
source/audio/audio.c
Normal file
@ -0,0 +1,289 @@
|
||||
#include <psp2/kernel/threadmgr.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "audio.h"
|
||||
#include "vitaaudiolib.h"
|
||||
#include "fs.h"
|
||||
|
||||
#include "flac.h"
|
||||
#include "mp3.h"
|
||||
#include "ogg.h"
|
||||
#include "wav.h"
|
||||
#include "xm.h"
|
||||
|
||||
enum Audio_FileType {
|
||||
FILE_TYPE_NONE = 0,
|
||||
FILE_TYPE_FLAC = 1,
|
||||
FILE_TYPE_MP3 = 2,
|
||||
FILE_TYPE_OGG = 3,
|
||||
FILE_TYPE_WAV = 4,
|
||||
FILE_TYPE_XM = 5
|
||||
};
|
||||
|
||||
static enum Audio_FileType file_type = FILE_TYPE_NONE;
|
||||
Audio_Metadata metadata;
|
||||
SceBool playing = SCE_TRUE, paused = SCE_FALSE;
|
||||
|
||||
static SceUInt32 Audio_GetSampleRate(void) {
|
||||
SceUInt32 sample_rate = 0;
|
||||
|
||||
switch(file_type) {
|
||||
case FILE_TYPE_FLAC:
|
||||
sample_rate = FLAC_GetSampleRate();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_MP3:
|
||||
sample_rate = MP3_GetSampleRate();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_OGG:
|
||||
sample_rate = OGG_GetSampleRate();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_WAV:
|
||||
sample_rate = WAV_GetSampleRate();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_XM:
|
||||
sample_rate = XM_GetSampleRate();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return sample_rate;
|
||||
}
|
||||
|
||||
static SceUInt8 Audio_GetChannels(void) {
|
||||
SceUInt8 channels = 0;
|
||||
|
||||
switch(file_type) {
|
||||
case FILE_TYPE_FLAC:
|
||||
channels = FLAC_GetChannels();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_MP3:
|
||||
channels = MP3_GetChannels();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_OGG:
|
||||
channels = OGG_GetChannels();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_WAV:
|
||||
channels = WAV_GetChannels();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_XM:
|
||||
channels = XM_GetChannels();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
||||
static void Audio_Decode(void *buf, unsigned int length, void *userdata) {
|
||||
if (playing == SCE_FALSE || paused == SCE_TRUE) {
|
||||
short *buf_short = (short *)buf;
|
||||
unsigned int count;
|
||||
for (count = 0; count < length * 2; count++)
|
||||
*(buf_short + count) = 0;
|
||||
}
|
||||
else {
|
||||
switch(file_type) {
|
||||
case FILE_TYPE_FLAC:
|
||||
FLAC_Decode(buf, length, userdata);
|
||||
break;
|
||||
|
||||
case FILE_TYPE_MP3:
|
||||
MP3_Decode(buf, length, userdata);
|
||||
break;
|
||||
|
||||
case FILE_TYPE_OGG:
|
||||
OGG_Decode(buf, length, userdata);
|
||||
break;
|
||||
|
||||
case FILE_TYPE_WAV:
|
||||
WAV_Decode(buf, length, userdata);
|
||||
break;
|
||||
|
||||
case FILE_TYPE_XM:
|
||||
XM_Decode(buf, length, userdata);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Audio_Init(const char *path) {
|
||||
playing = SCE_TRUE;
|
||||
paused = SCE_FALSE;
|
||||
|
||||
// Clear struct
|
||||
static const Audio_Metadata empty;
|
||||
metadata = empty;
|
||||
|
||||
if (!strncasecmp(FS_GetFileExt(path), "flac", 4))
|
||||
file_type = FILE_TYPE_FLAC;
|
||||
else if (!strncasecmp(FS_GetFileExt(path), "mp3", 3))
|
||||
file_type = FILE_TYPE_MP3;
|
||||
else if (!strncasecmp(FS_GetFileExt(path), "ogg", 3))
|
||||
file_type = FILE_TYPE_OGG;
|
||||
else if (!strncasecmp(FS_GetFileExt(path), "wav", 3))
|
||||
file_type = FILE_TYPE_WAV;
|
||||
else if (!strncasecmp(FS_GetFileExt(path), "xm", 2))
|
||||
file_type = FILE_TYPE_XM;
|
||||
|
||||
switch(file_type) {
|
||||
case FILE_TYPE_FLAC:
|
||||
FLAC_Init(path);
|
||||
break;
|
||||
|
||||
case FILE_TYPE_MP3:
|
||||
MP3_Init(path);
|
||||
break;
|
||||
|
||||
case FILE_TYPE_OGG:
|
||||
OGG_Init(path);
|
||||
break;
|
||||
|
||||
case FILE_TYPE_WAV:
|
||||
WAV_Init(path);
|
||||
break;
|
||||
|
||||
case FILE_TYPE_XM:
|
||||
XM_Init(path);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
vitaAudioInit(Audio_GetSampleRate(), Audio_GetChannels() == 2? SCE_AUDIO_OUT_MODE_STEREO : SCE_AUDIO_OUT_MODE_MONO);
|
||||
vitaAudioSetChannelCallback(0, Audio_Decode, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SceBool Audio_IsPaused(void) {
|
||||
return paused;
|
||||
}
|
||||
|
||||
void Audio_Pause(void) {
|
||||
paused = !paused;
|
||||
}
|
||||
|
||||
void Audio_Stop(void) {
|
||||
playing = !playing;
|
||||
}
|
||||
|
||||
SceUInt64 Audio_GetPosition(void) {
|
||||
SceUInt64 position = 0;
|
||||
|
||||
switch(file_type) {
|
||||
case FILE_TYPE_FLAC:
|
||||
position = FLAC_GetPosition();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_MP3:
|
||||
position = MP3_GetPosition();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_OGG:
|
||||
position = OGG_GetPosition();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_WAV:
|
||||
position = WAV_GetPosition();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_XM:
|
||||
position = XM_GetPosition();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
SceUInt64 Audio_GetLength(void) {
|
||||
SceUInt64 length = 0;
|
||||
|
||||
switch(file_type) {
|
||||
case FILE_TYPE_FLAC:
|
||||
length = FLAC_GetLength();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_MP3:
|
||||
length = MP3_GetLength();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_WAV:
|
||||
length = WAV_GetLength();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_OGG:
|
||||
length = OGG_GetLength();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_XM:
|
||||
length = XM_GetLength();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
SceUInt64 Audio_GetPositionSeconds(void) {
|
||||
return (Audio_GetPosition() / Audio_GetSampleRate());
|
||||
}
|
||||
|
||||
SceUInt64 Audio_GetLengthSeconds(void) {
|
||||
return (Audio_GetLength() / Audio_GetSampleRate());
|
||||
}
|
||||
|
||||
void Audio_Term(void) {
|
||||
switch(file_type) {
|
||||
case FILE_TYPE_FLAC:
|
||||
FLAC_Term();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_MP3:
|
||||
MP3_Term();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_OGG:
|
||||
OGG_Term();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_WAV:
|
||||
WAV_Term();
|
||||
break;
|
||||
|
||||
case FILE_TYPE_XM:
|
||||
XM_Term();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
playing = SCE_TRUE;
|
||||
paused = SCE_FALSE;
|
||||
|
||||
vitaAudioSetChannelCallback(0, NULL, NULL); // Clear channel callback
|
||||
vitaAudioEndPre();
|
||||
sceKernelDelayThread(50 * 1000);
|
||||
vitaAudioEnd();
|
||||
}
|
42
source/audio/flac.c
Normal file
@ -0,0 +1,42 @@
|
||||
#include "audio.h"
|
||||
#define DR_FLAC_IMPLEMENTATION
|
||||
#include "dr_flac.h"
|
||||
|
||||
static drflac *flac;
|
||||
static drflac_uint64 frames_read = 0;
|
||||
|
||||
int FLAC_Init(const char *path) {
|
||||
flac = drflac_open_file(path);
|
||||
if (flac == NULL)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SceUInt32 FLAC_GetSampleRate(void) {
|
||||
return flac->sampleRate;
|
||||
}
|
||||
|
||||
SceUInt8 FLAC_GetChannels(void) {
|
||||
return flac->channels;
|
||||
}
|
||||
|
||||
void FLAC_Decode(void *buf, unsigned int length, void *userdata) {
|
||||
frames_read += drflac_read_pcm_frames_s16(flac, (drflac_uint64)length, (drflac_int16 *)buf);
|
||||
|
||||
if (frames_read == flac->totalPCMFrameCount)
|
||||
playing = SCE_FALSE;
|
||||
}
|
||||
|
||||
SceUInt64 FLAC_GetPosition(void) {
|
||||
return frames_read;
|
||||
}
|
||||
|
||||
SceUInt64 FLAC_GetLength(void) {
|
||||
return flac->totalPCMFrameCount;
|
||||
}
|
||||
|
||||
void FLAC_Term(void) {
|
||||
frames_read = 0;
|
||||
drflac_close(flac);
|
||||
}
|
204
source/audio/mp3.c
Normal file
@ -0,0 +1,204 @@
|
||||
#include <mpg123.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
// For MP3 ID3 tags
|
||||
struct genre {
|
||||
int code;
|
||||
char text[112];
|
||||
};
|
||||
|
||||
// For MP3 ID3 tags
|
||||
struct genre genreList[] = {
|
||||
{0 , "Blues"}, {1 , "Classic Rock"}, {2 , "Country"}, {3 , "Dance"}, {4 , "Disco"}, {5 , "Funk"}, {6 , "Grunge"}, {7 , "Hip-Hop"}, {8 , "Jazz"}, {9 , "Metal"}, {10 , "New Age"},
|
||||
{11 , "Oldies"}, {12 , "Other"}, {13 , "Pop"}, {14 , "R&B"}, {15 , "Rap"}, {16 , "Reggae"}, {17 , "Rock"}, {18 , "Techno"}, {19 , "Industrial"}, {20 , "Alternative"},
|
||||
{21 , "Ska"}, {22 , "Death Metal"}, {23 , "Pranks"}, {24 , "Soundtrack"}, {25 , "Euro-Techno"}, {26 , "Ambient"}, {27 , "Trip-Hop"}, {28 , "Vocal"}, {29 , "Jazz+Funk"}, {30 , "Fusion"},
|
||||
{31 , "Trance"}, {32 , "Classical"}, {33 , "Instrumental"}, {34 , "Acid"}, {35 , "House"}, {36 , "Game"}, {37 , "Sound Clip"}, {38 , "Gospel"}, {39 , "Noise"}, {40 , "Alternative Rock"},
|
||||
{41 , "Bass"}, {42 , "Soul"}, {43 , "Punk"}, {44 , "Space"}, {45 , "Meditative"}, {46 , "Instrumental Pop"}, {47 , "Instrumental Rock"}, {48 , "Ethnic"}, {49 , "Gothic"}, {50 , "Darkwave"},
|
||||
{51 , "Techno-Industrial"}, {52 , "Electronic"}, {53 , "Pop-Folk"}, {54 , "Eurodance"}, {55 , "Dream"}, {56 , "Southern Rock"}, {57 , "Comedy"}, {58 , "Cult"}, {59 , "Gangsta"}, {60 , "Top 40"},
|
||||
{61 , "Christian Rap"}, {62 , "Pop/Funk"}, {63 , "Jungle"}, {64 , "Native US"}, {65 , "Cabaret"}, {66 , "New Wave"}, {67 , "Psychadelic"}, {68 , "Rave"}, {69 , "Showtunes"}, {70 , "Trailer"},
|
||||
{71 , "Lo-Fi"}, {72 , "Tribal"}, {73 , "Acid Punk"}, {74 , "Acid Jazz"}, {75 , "Polka"}, {76 , "Retro"}, {77 , "Musical"}, {78 , "Rock & Roll"}, {79 , "Hard Rock"}, {80 , "Folk"},
|
||||
{81 , "Folk-Rock"}, {82 , "National Folk"}, {83 , "Swing"}, {84 , "Fast Fusion"}, {85 , "Bebob"}, {86 , "Latin"}, {87 , "Revival"}, {88 , "Celtic"}, {89 , "Bluegrass"}, {90 , "Avantgarde"},
|
||||
{91 , "Gothic Rock"}, {92 , "Progressive Rock"}, {93 , "Psychedelic Rock"}, {94 , "Symphonic Rock"}, {95 , "Slow Rock"}, {96 , "Big Band"}, {97 , "Chorus"}, {98 , "Easy Listening"}, {99 , "Acoustic"},
|
||||
{100 , "Humour"}, {101 , "Speech"}, {102 , "Chanson"}, {103 , "Opera"}, {104 , "Chamber Music"}, {105 , "Sonata"}, {106 , "Symphony"}, {107 , "Booty Bass"}, {108 , "Primus"}, {109 , "Porn Groove"},
|
||||
{110 , "Satire"}, {111 , "Slow Jam"}, {112 , "Club"}, {113 , "Tango"}, {114 , "Samba"}, {115 , "Folklore"}, {116 , "Ballad"}, {117 , "Power Ballad"}, {118 , "Rhytmic Soul"}, {119 , "Freestyle"}, {120 , "Duet"},
|
||||
{121 , "Punk Rock"}, {122 , "Drum Solo"}, {123 , "A capella"}, {124 , "Euro-House"}, {125 , "Dance Hall"}, {126 , "Goa"}, {127 , "Drum & Bass"}, {128 , "Club-House"}, {129 , "Hardcore"}, {130 , "Terror"},
|
||||
{131 , "Indie"}, {132 , "BritPop"}, {133 , "Negerpunk"}, {134 , "Polsk Punk"}, {135 , "Beat"}, {136 , "Christian Gangsta"}, {137 , "Heavy Metal"}, {138 , "Black Metal"}, {139 , "Crossover"}, {140 , "Contemporary C"},
|
||||
{141 , "Christian Rock"}, {142 , "Merengue"}, {143 , "Salsa"}, {144 , "Thrash Metal"}, {145 , "Anime"}, {146 , "JPop"}, {147 , "SynthPop"}
|
||||
};
|
||||
|
||||
static mpg123_handle *mp3;
|
||||
static SceUInt64 frames_read = 0, total_samples = 0;
|
||||
static long sample_rate = 0;
|
||||
static int channels = 0;
|
||||
|
||||
// For MP3 ID3 tags
|
||||
// Helper for v1 printing, get these strings their zero byte.
|
||||
static void safe_print(char *tag, char *name, char *data, size_t size) {
|
||||
char safe[31];
|
||||
if (size > 30)
|
||||
return;
|
||||
memcpy(safe, data, size);
|
||||
safe[size] = 0;
|
||||
snprintf(tag, 34, "%s: %s\n", name, safe);
|
||||
}
|
||||
|
||||
// For MP3 ID3 tags
|
||||
// Print out ID3v1 info.
|
||||
static void print_v1(Audio_Metadata *ID3tag, mpg123_id3v1 *v1) {
|
||||
safe_print(ID3tag->title, "", v1->title, sizeof(v1->title));
|
||||
safe_print(ID3tag->artist, "", v1->artist, sizeof(v1->artist));
|
||||
safe_print(ID3tag->album, "", v1->album, sizeof(v1->album));
|
||||
safe_print(ID3tag->year, "", v1->year, sizeof(v1->year));
|
||||
safe_print(ID3tag->comment, "", v1->comment, sizeof(v1->comment));
|
||||
safe_print(ID3tag->genre, "", genreList[v1->genre].text, sizeof(genreList[v1->genre].text));
|
||||
}
|
||||
|
||||
// For MP3 ID3 tags
|
||||
// Split up a number of lines separated by \n, \r, both or just zero byte
|
||||
// and print out each line with specified prefix.
|
||||
static void print_lines(char *data, const char *prefix, mpg123_string *inlines) {
|
||||
size_t i;
|
||||
int hadcr = 0, hadlf = 0;
|
||||
char *lines = NULL;
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
if (inlines != NULL && inlines->fill) {
|
||||
lines = inlines->p;
|
||||
len = inlines->fill;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
line = lines;
|
||||
for (i = 0; i < len; ++i) {
|
||||
if (lines[i] == '\n' || lines[i] == '\r' || lines[i] == 0) {
|
||||
char save = lines[i]; /* saving, changing, restoring a byte in the data */
|
||||
if (save == '\n')
|
||||
++hadlf;
|
||||
if (save == '\r')
|
||||
++hadcr;
|
||||
if ((hadcr || hadlf) && (hadlf % 2 == 0) && (hadcr % 2 == 0))
|
||||
line = "";
|
||||
|
||||
if (line) {
|
||||
lines[i] = 0;
|
||||
if (data == NULL)
|
||||
printf("%s%s\n", prefix, line);
|
||||
else
|
||||
snprintf(data, 0x1F, "%s%s\n", prefix, line);
|
||||
line = NULL;
|
||||
lines[i] = save;
|
||||
}
|
||||
}
|
||||
else {
|
||||
hadlf = hadcr = 0;
|
||||
if (line == NULL)
|
||||
line = lines + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For MP3 ID3 tags
|
||||
// Print out the named ID3v2 fields.
|
||||
static void print_v2(Audio_Metadata *ID3tag, mpg123_id3v2 *v2) {
|
||||
print_lines(ID3tag->title, "", v2->title);
|
||||
print_lines(ID3tag->artist, "", v2->artist);
|
||||
print_lines(ID3tag->album, "", v2->album);
|
||||
print_lines(ID3tag->year, "", v2->year);
|
||||
print_lines(ID3tag->comment, "", v2->comment);
|
||||
print_lines(ID3tag->genre, "", v2->genre);
|
||||
}
|
||||
|
||||
int MP3_Init(const char *path) {
|
||||
int error = mpg123_init();
|
||||
if (error != MPG123_OK)
|
||||
return error;
|
||||
|
||||
mp3 = mpg123_new(NULL, &error);
|
||||
if (error != MPG123_OK)
|
||||
return error;
|
||||
|
||||
error = mpg123_param(mp3, MPG123_ADD_FLAGS, MPG123_PICTURE, 0.0);
|
||||
if (error != MPG123_OK)
|
||||
return error;
|
||||
|
||||
error = mpg123_open(mp3, path);
|
||||
if (error != MPG123_OK)
|
||||
return error;
|
||||
|
||||
mpg123_seek(mp3, 0, SEEK_SET);
|
||||
metadata.has_meta = mpg123_meta_check(mp3);
|
||||
|
||||
mpg123_id3v1 *v1;
|
||||
mpg123_id3v2 *v2;
|
||||
|
||||
if (metadata.has_meta & MPG123_ID3 && mpg123_id3(mp3, &v1, &v2) == MPG123_OK) {
|
||||
if (v1 != NULL)
|
||||
print_v1(&metadata, v1);
|
||||
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 ((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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
total_samples = mpg123_length(mp3);
|
||||
mpg123_getformat(mp3, &sample_rate, &channels, NULL);
|
||||
mpg123_format_none(mp3);
|
||||
mpg123_format(mp3, sample_rate, channels, MPG123_ENC_SIGNED_16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SceUInt32 MP3_GetSampleRate(void) {
|
||||
return sample_rate;
|
||||
}
|
||||
|
||||
SceUInt8 MP3_GetChannels(void) {
|
||||
return channels;
|
||||
}
|
||||
|
||||
void MP3_Decode(void *buf, unsigned int length, void *userdata) {
|
||||
size_t done = 0;
|
||||
mpg123_read(mp3, buf, length * (sizeof(SceInt16) * 2), &done);
|
||||
frames_read += done/(sizeof(SceInt16) * 2);
|
||||
|
||||
if (frames_read == total_samples)
|
||||
playing = SCE_FALSE;
|
||||
}
|
||||
|
||||
SceUInt64 MP3_GetPosition(void) {
|
||||
return frames_read;
|
||||
}
|
||||
|
||||
SceUInt64 MP3_GetLength(void) {
|
||||
return total_samples;
|
||||
}
|
||||
|
||||
void MP3_Term(void) {
|
||||
frames_read = 0;
|
||||
|
||||
if (metadata.has_meta)
|
||||
metadata.has_meta = SCE_FALSE;
|
||||
|
||||
mpg123_close(mp3);
|
||||
mpg123_delete(mp3);
|
||||
mpg123_exit();
|
||||
}
|
48
source/audio/ogg.c
Normal file
@ -0,0 +1,48 @@
|
||||
#include "audio.h"
|
||||
#define STB_VORBIS_HEADER_ONLY
|
||||
#define STB_VORBIS_NO_PUSHDATA_API
|
||||
#include "stb_vorbis.c"
|
||||
|
||||
static stb_vorbis *ogg;
|
||||
static stb_vorbis_info ogg_info;
|
||||
static unsigned int samples_read = 0, max_lenth = 0;
|
||||
|
||||
int OGG_Init(const char *path) {
|
||||
int error = 0;
|
||||
ogg = stb_vorbis_open_filename(path, &error, NULL);
|
||||
|
||||
if (!ogg)
|
||||
return -1;
|
||||
|
||||
ogg_info = stb_vorbis_get_info(ogg);
|
||||
max_lenth = stb_vorbis_stream_length_in_samples(ogg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SceUInt32 OGG_GetSampleRate(void) {
|
||||
return ogg_info.sample_rate;
|
||||
}
|
||||
|
||||
SceUInt8 OGG_GetChannels(void) {
|
||||
return ogg_info.channels;
|
||||
}
|
||||
|
||||
void OGG_Decode(void *buf, unsigned int length, void *userdata) {
|
||||
samples_read += stb_vorbis_get_samples_short_interleaved(ogg, ogg_info.channels, (short *)buf, (int)length * ogg_info.channels);
|
||||
|
||||
if (samples_read == max_lenth)
|
||||
playing = SCE_FALSE;
|
||||
}
|
||||
|
||||
SceUInt64 OGG_GetPosition(void) {
|
||||
return samples_read;
|
||||
}
|
||||
|
||||
SceUInt64 OGG_GetLength(void) {
|
||||
return max_lenth;
|
||||
}
|
||||
|
||||
void OGG_Term(void) {
|
||||
samples_read = 0;
|
||||
stb_vorbis_close(ogg);
|
||||
}
|
5494
source/audio/stb_vorbis.c
Normal file
169
source/audio/vitaaudiolib.c
Normal file
@ -0,0 +1,169 @@
|
||||
#include <psp2/kernel/threadmgr.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "vitaaudiolib.h"
|
||||
|
||||
static int audio_ready = 0;
|
||||
static short vitaAudioSoundBuffer[VITA_NUM_AUDIO_CHANNELS][2][VITA_NUM_AUDIO_SAMPLES][2];
|
||||
static VITA_audio_channelinfo vitaAudioStatus[VITA_NUM_AUDIO_CHANNELS];
|
||||
static volatile int audio_terminate = 0;
|
||||
|
||||
void vitaAudioSetVolume(int channel, int left, int right) {
|
||||
vitaAudioStatus[channel].volumeleft = left;
|
||||
vitaAudioStatus[channel].volumeright = right;
|
||||
}
|
||||
|
||||
int vitaAudioSetFrequency(int channel, int frequency) {
|
||||
return sceAudioOutSetConfig(vitaAudioStatus[channel].handle, VITA_NUM_AUDIO_SAMPLES, frequency, SCE_AUDIO_OUT_MODE_STEREO);
|
||||
}
|
||||
|
||||
void vitaAudioSetChannelCallback(int channel, vitaAudioCallback_t callback, void *data) {
|
||||
volatile VITA_audio_channelinfo *pci = &vitaAudioStatus[channel];
|
||||
|
||||
if (callback == 0)
|
||||
pci->callback = 0;
|
||||
else
|
||||
pci->callback = callback;
|
||||
}
|
||||
|
||||
int vitaAudioOutBlocking(unsigned int channel, unsigned int vol1, unsigned int vol2, void *buf) {
|
||||
if (!audio_ready)
|
||||
return(-1);
|
||||
|
||||
if (channel >= VITA_NUM_AUDIO_CHANNELS)
|
||||
return(-1);
|
||||
|
||||
if (vol1 > VITA_VOLUME_MAX)
|
||||
vol1 = VITA_VOLUME_MAX;
|
||||
|
||||
if (vol2 > VITA_VOLUME_MAX)
|
||||
vol2 = VITA_VOLUME_MAX;
|
||||
|
||||
int vols2[2] = { vol1, vol2 };
|
||||
sceAudioOutSetVolume(vitaAudioStatus[channel].handle, SCE_AUDIO_VOLUME_FLAG_L_CH | SCE_AUDIO_VOLUME_FLAG_R_CH, vols2);
|
||||
return sceAudioOutOutput(vitaAudioStatus[channel].handle, buf);
|
||||
}
|
||||
|
||||
static int vitaAudioChannelThread(int args, void *argp) {
|
||||
volatile int bufidx = 0;
|
||||
|
||||
int channel = *(int *) argp;
|
||||
|
||||
while (audio_terminate == 0) {
|
||||
void *bufptr = &vitaAudioSoundBuffer[channel][bufidx];
|
||||
vitaAudioCallback_t callback;
|
||||
callback = vitaAudioStatus[channel].callback;
|
||||
|
||||
if (callback)
|
||||
callback(bufptr, VITA_NUM_AUDIO_SAMPLES, vitaAudioStatus[channel].pdata);
|
||||
else {
|
||||
unsigned int *ptr = bufptr;
|
||||
int i;
|
||||
for (i = 0; i < VITA_NUM_AUDIO_SAMPLES; ++i)
|
||||
*(ptr++) = 0;
|
||||
}
|
||||
|
||||
vitaAudioOutBlocking(channel, vitaAudioStatus[channel].volumeleft, vitaAudioStatus[channel].volumeright, bufptr);
|
||||
bufidx = (bufidx ? 0:1);
|
||||
}
|
||||
|
||||
sceKernelExitThread(0);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int vitaAudioInit(int frequency, SceAudioOutMode mode) {
|
||||
int i, ret;
|
||||
int failed = 0;
|
||||
char str[32];
|
||||
|
||||
audio_terminate = 0;
|
||||
audio_ready = 0;
|
||||
|
||||
for (i = 0; i < VITA_NUM_AUDIO_CHANNELS; i++) {
|
||||
vitaAudioStatus[i].handle = -1;
|
||||
vitaAudioStatus[i].threadhandle = -1;
|
||||
vitaAudioStatus[i].volumeright = VITA_VOLUME_MAX;
|
||||
vitaAudioStatus[i].volumeleft = VITA_VOLUME_MAX;
|
||||
vitaAudioStatus[i].callback = 0;
|
||||
vitaAudioStatus[i].pdata = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < VITA_NUM_AUDIO_CHANNELS; i++) {
|
||||
if ((vitaAudioStatus[i].handle = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_BGM, VITA_NUM_AUDIO_SAMPLES, frequency, mode)) < 0)
|
||||
failed = 1;
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
for (i = 0; i < VITA_NUM_AUDIO_CHANNELS; i++) {
|
||||
if (vitaAudioStatus[i].handle != -1)
|
||||
sceAudioOutReleasePort(vitaAudioStatus[i].handle);
|
||||
|
||||
vitaAudioStatus[i].handle = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
audio_ready = 1;
|
||||
|
||||
strcpy(str, "audiot0");
|
||||
|
||||
for (i = 0; i < VITA_NUM_AUDIO_CHANNELS; i++) {
|
||||
str[6]= '0' + i;
|
||||
vitaAudioStatus[i].threadhandle = sceKernelCreateThread(str, (void*)&vitaAudioChannelThread, 0x40, 0x10000, 0, 0, NULL);
|
||||
|
||||
if (vitaAudioStatus[i].threadhandle < 0) {
|
||||
vitaAudioStatus[i].threadhandle = -1;
|
||||
failed = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = sceKernelStartThread(vitaAudioStatus[i].threadhandle, sizeof(i), &i);
|
||||
|
||||
if (ret != 0) {
|
||||
failed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
audio_terminate = 1;
|
||||
|
||||
for (i = 0; i < VITA_NUM_AUDIO_CHANNELS; i++) {
|
||||
if (vitaAudioStatus[i].threadhandle != -1)
|
||||
sceKernelDeleteThread(vitaAudioStatus[i].threadhandle);
|
||||
|
||||
vitaAudioStatus[i].threadhandle = -1;
|
||||
}
|
||||
|
||||
audio_ready = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void vitaAudioEndPre(void) {
|
||||
audio_ready = 0;
|
||||
audio_terminate = 1;
|
||||
}
|
||||
|
||||
void vitaAudioEnd(void) {
|
||||
int i = 0;
|
||||
audio_ready = 0;
|
||||
audio_terminate = 1;
|
||||
|
||||
for (i = 0; i < VITA_NUM_AUDIO_CHANNELS; i++) {
|
||||
if (vitaAudioStatus[i].threadhandle != -1)
|
||||
sceKernelDeleteThread(vitaAudioStatus[i].threadhandle);
|
||||
|
||||
vitaAudioStatus[i].threadhandle = -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < VITA_NUM_AUDIO_CHANNELS; i++) {
|
||||
if (vitaAudioStatus[i].handle != -1) {
|
||||
sceAudioOutReleasePort(vitaAudioStatus[i].handle);
|
||||
vitaAudioStatus[i].handle = -1;
|
||||
}
|
||||
}
|
||||
}
|
41
source/audio/wav.c
Normal file
@ -0,0 +1,41 @@
|
||||
#include "audio.h"
|
||||
#define DR_WAV_IMPLEMENTATION
|
||||
#include "dr_wav.h"
|
||||
|
||||
static drwav wav;
|
||||
static drwav_uint64 frames_read = 0;
|
||||
|
||||
int WAV_Init(const char *path) {
|
||||
if (!drwav_init_file(&wav, path))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SceUInt32 WAV_GetSampleRate(void) {
|
||||
return wav.sampleRate;
|
||||
}
|
||||
|
||||
SceUInt8 WAV_GetChannels(void) {
|
||||
return wav.channels;
|
||||
}
|
||||
|
||||
void WAV_Decode(void *buf, unsigned int length, void *userdata) {
|
||||
frames_read += drwav_read_pcm_frames_s16(&wav, (drwav_uint64)length, (drwav_int16 *)buf);
|
||||
|
||||
if (frames_read == wav.totalPCMFrameCount)
|
||||
playing = SCE_FALSE;
|
||||
}
|
||||
|
||||
SceUInt64 WAV_GetPosition(void) {
|
||||
return frames_read;
|
||||
}
|
||||
|
||||
SceUInt64 WAV_GetLength(void) {
|
||||
return wav.totalPCMFrameCount;
|
||||
}
|
||||
|
||||
void WAV_Term(void) {
|
||||
frames_read = 0;
|
||||
drwav_uninit(&wav);
|
||||
}
|
57
source/audio/xm.c
Normal file
@ -0,0 +1,57 @@
|
||||
#include "audio.h"
|
||||
#include "common.h"
|
||||
#include "fs.h"
|
||||
#define JAR_XM_IMPLEMENTATION
|
||||
#include "jar_xm.h"
|
||||
|
||||
static jar_xm_context_t *xm;
|
||||
static SceUInt64 samples_read = 0, total_samples = 0;
|
||||
static char *data = NULL;
|
||||
|
||||
int XM_Init(const char *path) {
|
||||
int ret = 0;
|
||||
char *xm_data = NULL;
|
||||
SceUInt64 xm_size_bytes = 0;
|
||||
|
||||
if (R_FAILED(ret = FS_GetFileSize(path, (SceOff *)&xm_size_bytes)))
|
||||
return ret;
|
||||
|
||||
xm_data = malloc(xm_size_bytes);
|
||||
if (R_FAILED(ret = FS_ReadFile(path, xm_data, xm_size_bytes)))
|
||||
return ret;
|
||||
|
||||
jar_xm_create_context_safe(&xm, xm_data, (size_t)xm_size_bytes, (SceUInt32)48000);
|
||||
total_samples = jar_xm_get_remaining_samples(xm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SceUInt32 XM_GetSampleRate(void) {
|
||||
return 48000;
|
||||
}
|
||||
|
||||
SceUInt8 XM_GetChannels(void) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
void XM_Decode(void *buf, unsigned int length, void *userdata) {
|
||||
jar_xm_generate_samples_16bit(xm, (short *)buf, (size_t)length);
|
||||
jar_xm_get_position(xm, NULL, NULL, NULL, &samples_read);
|
||||
|
||||
if (samples_read == total_samples)
|
||||
playing = SCE_FALSE;
|
||||
}
|
||||
|
||||
SceUInt64 XM_GetPosition(void) {
|
||||
return samples_read;
|
||||
}
|
||||
|
||||
SceUInt64 XM_GetLength(void) {
|
||||
return total_samples;
|
||||
}
|
||||
|
||||
void XM_Term(void) {
|
||||
samples_read = 0;
|
||||
jar_xm_free_context(xm);
|
||||
free(data);
|
||||
}
|
8
source/common.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include "common.h"
|
||||
|
||||
vita2d_font *font;
|
||||
enum SceCtrlButtons SCE_CTRL_ENTER, SCE_CTRL_CANCEL;
|
||||
SceUInt32 pressed = 0;
|
||||
int position = 0;
|
||||
int file_count = 0;
|
||||
char cwd[512];
|
205
source/dirbrowse.c
Normal file
@ -0,0 +1,205 @@
|
||||
#include <psp2/io/dirent.h>
|
||||
#include <psp2/io/fcntl.h>
|
||||
#include <psp2/io/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "dirbrowse.h"
|
||||
#include "fs.h"
|
||||
#include "menu_audioplayer.h"
|
||||
#include "textures.h"
|
||||
#include "utils.h"
|
||||
|
||||
File *files = NULL;
|
||||
|
||||
static void Dirbrowse_RecursiveFree(File *node) {
|
||||
if (node == NULL) // End of list
|
||||
return;
|
||||
|
||||
Dirbrowse_RecursiveFree(node->next); // Nest further
|
||||
free(node); // Free memory
|
||||
}
|
||||
|
||||
static void Dirbrowse_SaveLastDirectory(void) {
|
||||
char *buf = malloc(256);
|
||||
int len = snprintf(buf, 256, "%s\n", cwd);
|
||||
FS_WriteFile("ux0:data/elevenmpv/lastdir.txt", buf, len);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
int Dirbrowse_PopulateFiles(SceBool refresh) {
|
||||
SceUID dir = 0;
|
||||
Dirbrowse_RecursiveFree(files);
|
||||
files = NULL;
|
||||
file_count = 0;
|
||||
|
||||
if (R_SUCCEEDED(dir = sceIoDopen(cwd))) {
|
||||
int entryCount = 0, i = 0;
|
||||
SceIoDirent *entries = (SceIoDirent *)calloc(MAX_FILES, sizeof(SceIoDirent));
|
||||
|
||||
while (sceIoDread(dir, &entries[entryCount]) > 0)
|
||||
entryCount++;
|
||||
|
||||
sceIoDclose(dir);
|
||||
qsort(entries, entryCount, sizeof(SceIoDirent), Utils_Alphasort);
|
||||
|
||||
for (i = 0; i < entryCount; i++) {
|
||||
// Ingore null filename
|
||||
if (entries[i].d_name[0] == '\0')
|
||||
continue;
|
||||
|
||||
// Ignore "." in all directories
|
||||
if (!strcmp(entries[i].d_name, "."))
|
||||
continue;
|
||||
|
||||
// Ignore ".." in Root Directory
|
||||
if ((!strcmp(cwd, ROOT_PATH)) && (!strncmp(entries[i].d_name, "..", 2))) // Ignore ".." in Root Directory
|
||||
continue;
|
||||
|
||||
// Allocate Memory
|
||||
File *item = (File *)malloc(sizeof(File));
|
||||
memset(item, 0, sizeof(File));
|
||||
|
||||
item->is_dir = SCE_S_ISDIR(entries[i].d_stat.st_mode);
|
||||
|
||||
// Copy File Name
|
||||
strcpy(item->name, entries[i].d_name);
|
||||
strcpy(item->ext, FS_GetFileExt(item->name));
|
||||
|
||||
// New List
|
||||
if (files == NULL)
|
||||
files = item;
|
||||
|
||||
// Existing List
|
||||
else {
|
||||
File *list = files;
|
||||
|
||||
while(list->next != NULL)
|
||||
list = list->next;
|
||||
|
||||
list->next = item;
|
||||
}
|
||||
|
||||
file_count++;
|
||||
}
|
||||
|
||||
free(entries);
|
||||
}
|
||||
else
|
||||
return dir;
|
||||
|
||||
if (!refresh) {
|
||||
if (position >= file_count)
|
||||
position = file_count - 1; // Keep index
|
||||
}
|
||||
else
|
||||
position = 0; // Refresh position
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
int i = 0, printed = 0;
|
||||
File *file = files; // Draw file list
|
||||
|
||||
for(; file != NULL; file = file->next) {
|
||||
if (printed == FILES_PER_PAGE) // Limit the files per page
|
||||
break;
|
||||
|
||||
if (position < FILES_PER_PAGE || i > (position - FILES_PER_PAGE)) {
|
||||
if (i == position)
|
||||
vita2d_draw_rectangle(0, 112 + (72 * printed), 960, 72, RGBA8(230, 230, 230, 255));
|
||||
|
||||
if (file->is_dir)
|
||||
vita2d_draw_texture(icon_dir, 15, 117 + (72 * printed));
|
||||
else if ((!strncasecmp(file->ext, "flac", 4)) || (!strncasecmp(file->ext, "mp3", 3)) || (!strncasecmp(file->ext, "ogg", 3))
|
||||
|| (!strncasecmp(file->ext, "wav", 3)) || (!strncasecmp(file->ext, "xm", 2)))
|
||||
vita2d_draw_texture(icon_audio, 15, 117 + (72 * printed));
|
||||
else
|
||||
vita2d_draw_texture(icon_file, 15, 117 + (72 * printed));
|
||||
|
||||
if (strncmp(file->name, "..", 2) == 0)
|
||||
vita2d_font_draw_text(font, 102, 120 + (72 / 2) + (72 * printed), RGBA8(51, 51, 51, 255), 25, "Parent folder");
|
||||
else
|
||||
vita2d_font_draw_text(font, 102, 120 + (72 / 2) + (72 * printed), RGBA8(51, 51, 51, 255), 25, file->name);
|
||||
|
||||
printed++; // Increase printed counter
|
||||
}
|
||||
|
||||
i++; // Increase counter
|
||||
}
|
||||
}
|
||||
|
||||
File *Dirbrowse_GetFileIndex(int index) {
|
||||
int i = 0;
|
||||
File *file = files; // Find file Item
|
||||
|
||||
for(; file != NULL && i != index; file = file->next)
|
||||
i++;
|
||||
|
||||
return file; // Return file
|
||||
}
|
||||
|
||||
void Dirbrowse_OpenFile(void) {
|
||||
char path[512];
|
||||
File *file = Dirbrowse_GetFileIndex(position);
|
||||
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
strcpy(path, cwd);
|
||||
strcpy(path + strlen(path), file->name);
|
||||
|
||||
if (file->is_dir) {
|
||||
// Attempt to navigate to target
|
||||
if (R_SUCCEEDED(Dirbrowse_Navigate(SCE_FALSE))) {
|
||||
Dirbrowse_SaveLastDirectory();
|
||||
Dirbrowse_PopulateFiles(SCE_TRUE);
|
||||
}
|
||||
}
|
||||
else if ((!strncasecmp(file->ext, "flac", 4)) || (!strncasecmp(file->ext, "mp3", 3)) || (!strncasecmp(file->ext, "ogg", 3))
|
||||
|| (!strncasecmp(file->ext, "wav", 3)) || (!strncasecmp(file->ext, "xm", 2)))
|
||||
Menu_PlayAudio(path);
|
||||
}
|
||||
|
||||
// Navigate to Folder
|
||||
int Dirbrowse_Navigate(SceBool parent) {
|
||||
File *file = Dirbrowse_GetFileIndex(position); // Get index
|
||||
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
|
||||
// Special case ".."
|
||||
if ((parent) || (!strncmp(file->name, "..", 2))) {
|
||||
char *slash = NULL;
|
||||
|
||||
// Find last '/' in working directory
|
||||
int i = strlen(cwd) - 2; for(; i >= 0; i--) {
|
||||
// Slash discovered
|
||||
if (cwd[i] == '/') {
|
||||
slash = cwd + i + 1; // Save pointer
|
||||
break; // Stop search
|
||||
}
|
||||
}
|
||||
|
||||
slash[0] = 0; // Terminate working directory
|
||||
}
|
||||
|
||||
// Normal folder
|
||||
else {
|
||||
if (file->is_dir) {
|
||||
// Append folder to working directory
|
||||
strcpy(cwd + strlen(cwd), file->name);
|
||||
cwd[strlen(cwd) + 1] = 0;
|
||||
cwd[strlen(cwd)] = '/';
|
||||
}
|
||||
}
|
||||
|
||||
Dirbrowse_SaveLastDirectory();
|
||||
|
||||
return 0; // Return success
|
||||
}
|
74
source/fs.c
Normal file
@ -0,0 +1,74 @@
|
||||
#include <psp2/io/dirent.h>
|
||||
#include <psp2/io/fcntl.h>
|
||||
#include <psp2/io/stat.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "fs.h"
|
||||
|
||||
SceBool FS_FileExists(const char *path) {
|
||||
SceUID file = 0;
|
||||
|
||||
if (R_SUCCEEDED(file = sceIoOpen(path, SCE_O_RDONLY, 0777))) {
|
||||
sceIoClose(file);
|
||||
return SCE_TRUE;
|
||||
}
|
||||
|
||||
return SCE_FALSE;
|
||||
}
|
||||
|
||||
SceBool FS_DirExists(const char *path) {
|
||||
SceUID dir = 0;
|
||||
|
||||
if (R_SUCCEEDED(dir = sceIoDopen(path))) {
|
||||
sceIoDclose(dir);
|
||||
return SCE_TRUE;
|
||||
}
|
||||
|
||||
return SCE_FALSE;
|
||||
}
|
||||
|
||||
const char *FS_GetFileExt(const char *filename) {
|
||||
const char *dot = strrchr(filename, '.');
|
||||
|
||||
if (!dot || dot == filename)
|
||||
return "";
|
||||
|
||||
return dot + 1;
|
||||
}
|
||||
|
||||
int FS_GetFileSize(const char *path, SceOff *size) {
|
||||
SceIoStat stat;
|
||||
int ret = 0;
|
||||
|
||||
if (R_FAILED(ret = sceIoGetstat(path, &stat)))
|
||||
return ret;
|
||||
|
||||
*size = stat.st_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FS_ReadFile(const char *path, void *buf, int size) {
|
||||
SceUID file = 0;
|
||||
|
||||
if (R_SUCCEEDED(file = sceIoOpen(path, SCE_O_RDONLY, 0))) {
|
||||
int bytes_read = sceIoRead(file, buf, size);
|
||||
sceIoClose(file);
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
int FS_WriteFile(char *path, void *buf, int size) {
|
||||
SceUID file = 0;
|
||||
|
||||
if (R_SUCCEEDED(file = sceIoOpen(path, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777))) {
|
||||
int bytes_written = sceIoWrite(file, buf, size);
|
||||
sceIoClose(file);
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
77
source/main.c
Normal file
@ -0,0 +1,77 @@
|
||||
#include <psp2/io/stat.h>
|
||||
#include <psp2/kernel/processmgr.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "fs.h"
|
||||
#include "menu_displayfiles.h"
|
||||
#include "textures.h"
|
||||
#include "utils.h"
|
||||
|
||||
static int GetLastDirectory(void) {
|
||||
int ret = 0;
|
||||
|
||||
if (!FS_DirExists("ux0:data/elevenmpv"))
|
||||
sceIoMkdir("ux0:data/elevenmpv", 0777);
|
||||
|
||||
if (!FS_FileExists("ux0:data/elevenmpv/lastdir.txt")) {
|
||||
char *buf = malloc(8);
|
||||
int length = snprintf(buf, 8, ROOT_PATH);
|
||||
|
||||
if (R_FAILED(ret = FS_WriteFile("ux0:data/elevenmpv/lastdir.txt", buf, length))) {
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
char *buf = malloc(size + 1);
|
||||
|
||||
if (R_FAILED(ret = FS_ReadFile("ux0:data/elevenmpv/lastdir.txt", buf, size))) {
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
buf[size] = '\0';
|
||||
char path[513];
|
||||
sscanf(buf, "%[^\n]s", path);
|
||||
|
||||
if (FS_DirExists(path)) // Incase a directory previously visited had been deleted, set start path to sdmc:/ to avoid errors.
|
||||
strcpy(cwd, path);
|
||||
else
|
||||
strcpy(cwd, ROOT_PATH);
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
vita2d_init();
|
||||
font = vita2d_load_font_file("app0:Roboto-Regular.ttf");
|
||||
Textures_Load();
|
||||
|
||||
Utils_InitAppUtil();
|
||||
SCE_CTRL_ENTER = Utils_GetEnterButton();
|
||||
SCE_CTRL_CANCEL = Utils_GetCancelButton();
|
||||
|
||||
GetLastDirectory();
|
||||
|
||||
Menu_DisplayFiles();
|
||||
|
||||
Utils_TermAppUtil();
|
||||
|
||||
Textures_Free();
|
||||
vita2d_free_font(font);
|
||||
vita2d_fini();
|
||||
|
||||
sceKernelExitProcess(0);
|
||||
return 0;
|
||||
}
|
238
source/menus/menu_audioplayer.c
Normal file
@ -0,0 +1,238 @@
|
||||
#include <psp2/io/dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "audio.h"
|
||||
#include "common.h"
|
||||
#include "fs.h"
|
||||
#include "menu_displayfiles.h"
|
||||
#include "status_bar.h"
|
||||
#include "textures.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define BUTTON_WIDTH 68
|
||||
#define BUTTON_HEIGHT 68
|
||||
|
||||
typedef enum {
|
||||
MUSIC_STATE_NONE, // 0
|
||||
MUSIC_STATE_REPEAT, // 1
|
||||
MUSIC_STATE_SHUFFLE // 2
|
||||
} Music_State;
|
||||
|
||||
static char playlist[1024][512];
|
||||
static int count = 0, selection = 0, state = 0;
|
||||
static int length_time_width = 0;
|
||||
char *position_time = NULL, *length_time = NULL, *filename = NULL;
|
||||
|
||||
static int Menu_GetMusicList(void) {
|
||||
SceUID dir = 0;
|
||||
|
||||
if (R_SUCCEEDED(dir = sceIoDopen(cwd))) {
|
||||
int entryCount = 0, i = 0;
|
||||
SceIoDirent *entries = (SceIoDirent *)calloc(MAX_FILES, sizeof(SceIoDirent));
|
||||
|
||||
while (sceIoDread(dir, &entries[entryCount]) > 0)
|
||||
entryCount++;
|
||||
|
||||
sceIoDclose(dir);
|
||||
qsort(entries, entryCount, sizeof(SceIoDirent), Utils_Alphasort);
|
||||
|
||||
for (i = 0; i < entryCount; i++) {
|
||||
if ((!strncasecmp(FS_GetFileExt(entries[i].d_name), "flac", 4)) || (!strncasecmp(FS_GetFileExt(entries[i].d_name), "mp3", 3)) || (!strncasecmp(FS_GetFileExt(entries[i].d_name), "ogg", 3))
|
||||
|| (!strncasecmp(FS_GetFileExt(entries[i].d_name), "wav", 3)) || (!strncasecmp(FS_GetFileExt(entries[i].d_name), "xm", 2))) {
|
||||
strcpy(playlist[count], cwd);
|
||||
strcpy(playlist[count] + strlen(playlist[count]), entries[i].d_name);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
free(entries);
|
||||
}
|
||||
else {
|
||||
sceIoDclose(dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Music_GetCurrentIndex(char *path) {
|
||||
for(int i = 0; i < count; ++i) {
|
||||
if (!strcmp(playlist[i], path))
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Menu_ConvertSecondsToString(char *string, SceUInt64 seconds) {
|
||||
int h = 0, m = 0, s = 0;
|
||||
h = (seconds / 3600);
|
||||
m = (seconds - (3600 * h)) / 60;
|
||||
s = (seconds - (3600 * h) - (m * 60));
|
||||
|
||||
if (h > 0)
|
||||
snprintf(string, 35, "%02d:%02d:%02d", h, m, s);
|
||||
else
|
||||
snprintf(string, 35, "%02d:%02d", m, s);
|
||||
}
|
||||
|
||||
static void Menu_InitMusic(char *path) {
|
||||
Audio_Init(path);
|
||||
|
||||
filename = malloc(128);
|
||||
snprintf(filename, 128, Utils_Basename(path));
|
||||
position_time = malloc(35);
|
||||
length_time = malloc(35);
|
||||
length_time_width = 0;
|
||||
|
||||
Menu_ConvertSecondsToString(length_time, Audio_GetLengthSeconds());
|
||||
length_time_width = vita2d_font_text_width(font, 25, length_time);
|
||||
selection = Music_GetCurrentIndex(path);
|
||||
}
|
||||
|
||||
static void Music_HandleNext(SceBool forward, int state) {
|
||||
if (state == MUSIC_STATE_NONE) {
|
||||
if (forward)
|
||||
selection++;
|
||||
else
|
||||
selection--;
|
||||
}
|
||||
else if (state == MUSIC_STATE_SHUFFLE) {
|
||||
int old_selection = selection;
|
||||
time_t t;
|
||||
srand((unsigned) time(&t));
|
||||
selection = rand() % (count - 1);
|
||||
|
||||
if (selection == old_selection)
|
||||
selection--;
|
||||
}
|
||||
|
||||
Utils_SetMax(&selection, 0, (count - 1));
|
||||
Utils_SetMin(&selection, (count - 1), 0);
|
||||
|
||||
Audio_Stop();
|
||||
|
||||
free(filename);
|
||||
free(length_time);
|
||||
free(position_time);
|
||||
|
||||
if ((metadata.has_meta) && (metadata.cover_image)) {
|
||||
vita2d_wait_rendering_done();
|
||||
vita2d_free_texture(metadata.cover_image);
|
||||
}
|
||||
|
||||
Audio_Term();
|
||||
Menu_InitMusic(playlist[selection]);
|
||||
}
|
||||
|
||||
void Menu_PlayAudio(char *path) {
|
||||
Menu_GetMusicList();
|
||||
Menu_InitMusic(path);
|
||||
|
||||
while(SCE_TRUE) {
|
||||
vita2d_start_drawing();
|
||||
vita2d_clear_screen();
|
||||
|
||||
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);
|
||||
StatusBar_Display();
|
||||
|
||||
if ((metadata.has_meta) && (strlen(metadata.title) != 0) && (strlen(metadata.artist) != 0)) {
|
||||
vita2d_font_draw_text(font, 80, 22 + (80 - vita2d_font_text_height(font, 25, strupr(metadata.title))) + 20, RGBA8(255, 255, 255, 255), 25, strupr(metadata.title));
|
||||
vita2d_font_draw_text(font, 80, 22 + (80 - vita2d_font_text_height(font, 25, strupr(metadata.artist))) + 55, RGBA8(255, 255, 255, 255), 25, strupr(metadata.artist));
|
||||
}
|
||||
else if ((metadata.has_meta) && (strlen(metadata.title) != 0))
|
||||
vita2d_font_draw_text(font, 80, 22 + (80 - vita2d_font_text_height(font, 25, strupr(metadata.title))) + 15, RGBA8(255, 255, 255, 255), 25, strupr(metadata.title));
|
||||
else if (!metadata.has_meta)
|
||||
vita2d_font_draw_text(font, 80, 22 + (80 - vita2d_font_text_height(font, 25, strupr(filename))) + 15, RGBA8(255, 255, 255, 255), 25, filename);
|
||||
|
||||
vita2d_draw_rectangle(0, 124, 400, 400, RGBA8(97, 97, 97, 255));
|
||||
|
||||
if ((metadata.has_meta) && (metadata.cover_image))
|
||||
vita2d_draw_texture_scale(metadata.cover_image, 0, 124, 400.0f/vita2d_texture_get_width(metadata.cover_image), 400.0f/vita2d_texture_get_height(metadata.cover_image));
|
||||
else
|
||||
vita2d_draw_texture(default_artwork, 0, 124); // Default album art
|
||||
|
||||
vita2d_draw_rectangle(410, 124, 550, 400, RGBA8(45, 48, 50, 255)); // Draw info box (outer)
|
||||
vita2d_draw_rectangle(420, 134, 530, 380, RGBA8(46, 49, 51, 255)); // Draw info box (inner)
|
||||
|
||||
if (!Audio_IsPaused())
|
||||
vita2d_draw_texture(btn_pause, 410 + ((550 - BUTTON_WIDTH) / 2), 124 + ((400 - BUTTON_HEIGHT) / 2)); // Playing
|
||||
else
|
||||
vita2d_draw_texture(btn_play, 410 + ((550 - BUTTON_WIDTH) / 2), 124 + ((400 - BUTTON_HEIGHT) / 2)); // Paused
|
||||
|
||||
vita2d_draw_texture(btn_rewind, 410 + ((550 - BUTTON_WIDTH) / 2) - 136, 124 + ((400 - BUTTON_HEIGHT) / 2));
|
||||
vita2d_draw_texture(btn_forward, 410 + ((550 - BUTTON_WIDTH) / 2) + 136, 124 + ((400 - BUTTON_HEIGHT) / 2));
|
||||
|
||||
vita2d_draw_texture(state == MUSIC_STATE_SHUFFLE? btn_shuffle_overlay : btn_shuffle, 410 + ((550 - BUTTON_WIDTH) / 2) - 90, 124 + ((400 - BUTTON_HEIGHT) / 2) + 100);
|
||||
vita2d_draw_texture(state == MUSIC_STATE_REPEAT? btn_repeat_overlay : btn_repeat, 410 + ((550 - BUTTON_WIDTH) / 2) + 90, 124 + ((400 - BUTTON_HEIGHT) / 2) + 100);
|
||||
|
||||
Menu_ConvertSecondsToString(position_time, Audio_GetPositionSeconds());
|
||||
vita2d_font_draw_text(font, 460, 480, RGBA8(255, 255, 255, 255), 25, position_time);
|
||||
vita2d_font_draw_text(font, 910 - length_time_width, 480, RGBA8(255, 255, 255, 255), 25, length_time);
|
||||
vita2d_draw_rectangle(460, 490, 450, 4, RGBA8(97, 97, 97, 255));
|
||||
vita2d_draw_rectangle(460, 490, (((double)Audio_GetPosition()/(double)Audio_GetLength()) * 450.0), 4, RGBA8(255, 255, 255, 255));
|
||||
|
||||
vita2d_end_drawing();
|
||||
vita2d_swap_buffers();
|
||||
|
||||
if (!playing) {
|
||||
if (state == MUSIC_STATE_NONE)
|
||||
break;
|
||||
else if (state == MUSIC_STATE_REPEAT)
|
||||
Music_HandleNext(SCE_FALSE, MUSIC_STATE_REPEAT);
|
||||
else if (state == MUSIC_STATE_SHUFFLE) {
|
||||
if (count != 0)
|
||||
Music_HandleNext(SCE_FALSE, MUSIC_STATE_SHUFFLE);
|
||||
}
|
||||
}
|
||||
|
||||
Utils_ReadControls();
|
||||
|
||||
if (pressed & SCE_CTRL_ENTER)
|
||||
Audio_Pause();
|
||||
|
||||
if (pressed & SCE_CTRL_TRIANGLE) {
|
||||
if (state == MUSIC_STATE_SHUFFLE)
|
||||
state = MUSIC_STATE_NONE;
|
||||
else
|
||||
state = MUSIC_STATE_SHUFFLE;
|
||||
}
|
||||
else if (pressed & SCE_CTRL_SQUARE) {
|
||||
if (state == MUSIC_STATE_REPEAT)
|
||||
state = MUSIC_STATE_NONE;
|
||||
else
|
||||
state = MUSIC_STATE_REPEAT;
|
||||
}
|
||||
|
||||
if (pressed & SCE_CTRL_LTRIGGER) {
|
||||
if (count != 0)
|
||||
Music_HandleNext(SCE_FALSE, MUSIC_STATE_NONE);
|
||||
}
|
||||
else if (pressed & SCE_CTRL_RTRIGGER) {
|
||||
if (count != 0)
|
||||
Music_HandleNext(SCE_TRUE, MUSIC_STATE_NONE);
|
||||
}
|
||||
|
||||
if (pressed & SCE_CTRL_CANCEL)
|
||||
break;
|
||||
}
|
||||
|
||||
free(filename);
|
||||
free(length_time);
|
||||
free(position_time);
|
||||
|
||||
if ((metadata.has_meta) && (metadata.cover_image)) {
|
||||
vita2d_wait_rendering_done();
|
||||
vita2d_free_texture(metadata.cover_image);
|
||||
}
|
||||
|
||||
Audio_Stop();
|
||||
Audio_Term();
|
||||
count = 0;
|
||||
Menu_DisplayFiles();
|
||||
}
|
56
source/menus/menu_displayfiles.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "dirbrowse.h"
|
||||
#include "status_bar.h"
|
||||
#include "textures.h"
|
||||
#include "utils.h"
|
||||
|
||||
static void Menu_HandleControls(void) {
|
||||
if (file_count > 0) {
|
||||
if (pressed & SCE_CTRL_UP)
|
||||
position--;
|
||||
else if (pressed & SCE_CTRL_DOWN)
|
||||
position++;
|
||||
|
||||
Utils_SetMax(&position, 0, file_count - 1);
|
||||
Utils_SetMin(&position, file_count - 1, 0);
|
||||
|
||||
if (pressed & SCE_CTRL_LEFT)
|
||||
position = 0;
|
||||
else if (pressed & SCE_CTRL_RIGHT)
|
||||
position = file_count - 1;
|
||||
|
||||
if (pressed & SCE_CTRL_ENTER)
|
||||
Dirbrowse_OpenFile();
|
||||
|
||||
if ((strcmp(cwd, ROOT_PATH) != 0) && (pressed & SCE_CTRL_CANCEL)) {
|
||||
Dirbrowse_Navigate(SCE_TRUE);
|
||||
Dirbrowse_PopulateFiles(SCE_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Menu_DisplayFiles(void) {
|
||||
Dirbrowse_PopulateFiles(SCE_FALSE);
|
||||
vita2d_set_clear_color(RGBA8(250, 250, 250, 255));
|
||||
|
||||
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();
|
||||
Dirbrowse_DisplayFiles();
|
||||
|
||||
vita2d_end_drawing();
|
||||
vita2d_swap_buffers();
|
||||
|
||||
Utils_ReadControls();
|
||||
Menu_HandleControls();
|
||||
|
||||
if (pressed & SCE_CTRL_START)
|
||||
break;
|
||||
}
|
||||
}
|
105
source/status_bar.c
Normal file
@ -0,0 +1,105 @@
|
||||
#include <psp2/power.h>
|
||||
#include <psp2/rtc.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "textures.h"
|
||||
|
||||
static int percent_width = 0;
|
||||
|
||||
static char *StatusBar_GetCurrentTime(void) {
|
||||
static char buffer[27];
|
||||
|
||||
SceDateTime time;
|
||||
sceRtcGetCurrentClockLocalTime(&time);
|
||||
int hours = sceRtcGetHour(&time);
|
||||
int am_or_pm = 0;
|
||||
|
||||
if (hours < 12)
|
||||
am_or_pm = 1;
|
||||
if (hours == 0)
|
||||
hours = 12;
|
||||
else if (hours > 12)
|
||||
hours = hours - 12;
|
||||
|
||||
if ((hours >= 1) && (hours < 10))
|
||||
snprintf(buffer, 27, "%2i:%02i %s", hours, sceRtcGetMinute(&time), am_or_pm ? "AM" : "PM");
|
||||
else
|
||||
snprintf(buffer, 27, "%2i:%02i %s", hours, sceRtcGetMinute(&time), am_or_pm ? "AM" : "PM");
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void StatusBar_GetBatteryStatus(int x, int y) {
|
||||
int percent = 0;
|
||||
SceBool state = SCE_FALSE;
|
||||
char buf[13];
|
||||
|
||||
if (R_FAILED(state = scePowerIsBatteryCharging()))
|
||||
state = SCE_FALSE;
|
||||
|
||||
if (R_SUCCEEDED(percent = scePowerGetBatteryLifePercent())) {
|
||||
if (percent < 20)
|
||||
vita2d_draw_texture(battery_low, x, 4);
|
||||
else if ((percent >= 20) && (percent < 30)) {
|
||||
if (state)
|
||||
vita2d_draw_texture(battery_20_charging, x, 4);
|
||||
else
|
||||
vita2d_draw_texture(battery_20, x, 4);
|
||||
}
|
||||
else if ((percent >= 30) && (percent < 50)) {
|
||||
if (state)
|
||||
vita2d_draw_texture(battery_50_charging, x, 4);
|
||||
else
|
||||
vita2d_draw_texture(battery_50, x, 4);
|
||||
}
|
||||
else if ((percent >= 50) && (percent < 60)) {
|
||||
if (state)
|
||||
vita2d_draw_texture(battery_50_charging, x, 4);
|
||||
else
|
||||
vita2d_draw_texture(battery_50, x, 4);
|
||||
}
|
||||
else if ((percent >= 60) && (percent < 80)) {
|
||||
if (state)
|
||||
vita2d_draw_texture(battery_60_charging, x, 4);
|
||||
else
|
||||
vita2d_draw_texture(battery_60, x, 4);
|
||||
}
|
||||
else if ((percent >= 80) && (percent < 90)) {
|
||||
if (state)
|
||||
vita2d_draw_texture(battery_80_charging, x, 4);
|
||||
else
|
||||
vita2d_draw_texture(battery_80, x, 4);
|
||||
}
|
||||
else if ((percent >= 90) && (percent < 100)) {
|
||||
if (state)
|
||||
vita2d_draw_texture(battery_90_charging, x, 4);
|
||||
else
|
||||
vita2d_draw_texture(battery_90, x, 4);
|
||||
}
|
||||
else if (percent == 100) {
|
||||
if (state)
|
||||
vita2d_draw_texture(battery_full_charging, x, 4);
|
||||
else
|
||||
vita2d_draw_texture(battery_full, x, 4);
|
||||
}
|
||||
|
||||
snprintf(buf, 13, "%d%%", percent);
|
||||
percent_width = vita2d_font_text_width(font, 25, buf);
|
||||
vita2d_font_draw_text(font, (x - percent_width - 5), y, RGBA8(255, 255, 255, 255), 25, buf);
|
||||
}
|
||||
else {
|
||||
snprintf(buf, 13, "%d%%", percent);
|
||||
percent_width = vita2d_font_text_width(font, 25, buf);
|
||||
vita2d_font_draw_text(font, (x - percent_width - 5), y, RGBA8(255, 255, 255, 255), 25, buf);
|
||||
vita2d_draw_texture(battery_unknown, x, 4);
|
||||
}
|
||||
}
|
||||
|
||||
void StatusBar_Display(void) {
|
||||
int width = 0, height = 0;
|
||||
vita2d_font_text_dimensions(font, 25, StatusBar_GetCurrentTime(), &width, &height);
|
||||
|
||||
StatusBar_GetBatteryStatus(((950 - width) - (32 + 10)), ((40 - height) / 2) + 25);
|
||||
vita2d_font_draw_text(font, (950 - width), ((40 - height) / 2) + 25, RGBA8(255, 255, 255, 255), 25, StatusBar_GetCurrentTime());
|
||||
}
|
118
source/textures.c
Normal file
@ -0,0 +1,118 @@
|
||||
#include <psp2/types.h>
|
||||
|
||||
#include "textures.h"
|
||||
|
||||
extern SceUChar8 _binary_res_battery_20_png_start;
|
||||
extern SceUChar8 _binary_res_battery_30_png_start;
|
||||
extern SceUChar8 _binary_res_battery_50_png_start;
|
||||
extern SceUChar8 _binary_res_battery_60_png_start;
|
||||
extern SceUChar8 _binary_res_battery_80_png_start;
|
||||
extern SceUChar8 _binary_res_battery_90_png_start;
|
||||
extern SceUChar8 _binary_res_battery_full_png_start;
|
||||
|
||||
extern SceUChar8 _binary_res_battery_20_charging_png_start;
|
||||
extern SceUChar8 _binary_res_battery_30_charging_png_start;
|
||||
extern SceUChar8 _binary_res_battery_50_charging_png_start;
|
||||
extern SceUChar8 _binary_res_battery_60_charging_png_start;
|
||||
extern SceUChar8 _binary_res_battery_80_charging_png_start;
|
||||
extern SceUChar8 _binary_res_battery_90_charging_png_start;
|
||||
extern SceUChar8 _binary_res_battery_full_charging_png_start;
|
||||
|
||||
extern SceUChar8 _binary_res_battery_low_png_start;
|
||||
extern SceUChar8 _binary_res_battery_unknown_png_start;
|
||||
|
||||
extern SceUChar8 _binary_res_icon_audio_png_start;
|
||||
extern SceUChar8 _binary_res_icon_file_png_start;
|
||||
extern SceUChar8 _binary_res_icon_folder_png_start;
|
||||
extern SceUChar8 _binary_res_icon_back_png_start;
|
||||
|
||||
extern SceUChar8 _binary_res_btn_playback_forward_png_start;
|
||||
extern SceUChar8 _binary_res_btn_playback_pause_png_start;
|
||||
extern SceUChar8 _binary_res_btn_playback_play_png_start;
|
||||
extern SceUChar8 _binary_res_btn_playback_repeat_png_start;
|
||||
extern SceUChar8 _binary_res_btn_playback_repeat_overlay_png_start;
|
||||
extern SceUChar8 _binary_res_btn_playback_rewind_png_start;
|
||||
extern SceUChar8 _binary_res_btn_playback_shuffle_png_start;
|
||||
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;
|
||||
|
||||
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);
|
||||
return texture;
|
||||
}
|
||||
|
||||
void Textures_Load(void) {
|
||||
battery_20 = Texture_LoadImageBilinear(&_binary_res_battery_20_png_start);
|
||||
battery_30 = Texture_LoadImageBilinear(&_binary_res_battery_30_png_start);
|
||||
battery_50 = Texture_LoadImageBilinear(&_binary_res_battery_50_png_start);
|
||||
battery_60 = Texture_LoadImageBilinear(&_binary_res_battery_60_png_start);
|
||||
battery_80 = Texture_LoadImageBilinear(&_binary_res_battery_80_png_start);
|
||||
battery_90 = Texture_LoadImageBilinear(&_binary_res_battery_90_png_start);
|
||||
battery_full = Texture_LoadImageBilinear(&_binary_res_battery_full_png_start);
|
||||
|
||||
battery_20_charging = Texture_LoadImageBilinear(&_binary_res_battery_20_charging_png_start);
|
||||
battery_30_charging = Texture_LoadImageBilinear(&_binary_res_battery_30_charging_png_start);
|
||||
battery_50_charging = Texture_LoadImageBilinear(&_binary_res_battery_50_charging_png_start);
|
||||
battery_60_charging = Texture_LoadImageBilinear(&_binary_res_battery_60_charging_png_start);
|
||||
battery_80_charging = Texture_LoadImageBilinear(&_binary_res_battery_80_charging_png_start);
|
||||
battery_90_charging = Texture_LoadImageBilinear(&_binary_res_battery_90_charging_png_start);
|
||||
battery_full_charging = Texture_LoadImageBilinear(&_binary_res_battery_full_charging_png_start);
|
||||
|
||||
battery_low = Texture_LoadImageBilinear(&_binary_res_battery_low_png_start);
|
||||
battery_unknown = Texture_LoadImageBilinear(&_binary_res_battery_unknown_png_start);
|
||||
|
||||
icon_audio = Texture_LoadImageBilinear(&_binary_res_icon_audio_png_start);
|
||||
icon_file = Texture_LoadImageBilinear(&_binary_res_icon_file_png_start);
|
||||
icon_dir = Texture_LoadImageBilinear(&_binary_res_icon_folder_png_start);
|
||||
icon_back = Texture_LoadImageBilinear(&_binary_res_icon_back_png_start);
|
||||
|
||||
btn_forward = Texture_LoadImageBilinear(&_binary_res_btn_playback_forward_png_start);
|
||||
btn_pause = Texture_LoadImageBilinear(&_binary_res_btn_playback_pause_png_start);
|
||||
btn_play = Texture_LoadImageBilinear(&_binary_res_btn_playback_play_png_start);
|
||||
btn_repeat = Texture_LoadImageBilinear(&_binary_res_btn_playback_repeat_png_start);
|
||||
btn_repeat_overlay = Texture_LoadImageBilinear(&_binary_res_btn_playback_repeat_overlay_png_start);
|
||||
btn_rewind = Texture_LoadImageBilinear(&_binary_res_btn_playback_rewind_png_start);
|
||||
btn_shuffle = Texture_LoadImageBilinear(&_binary_res_btn_playback_shuffle_png_start);
|
||||
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);
|
||||
}
|
||||
|
||||
void Textures_Free(void) {
|
||||
vita2d_free_texture(default_artwork_blur);
|
||||
vita2d_free_texture(default_artwork);
|
||||
vita2d_free_texture(btn_shuffle_overlay);
|
||||
vita2d_free_texture(btn_shuffle);
|
||||
vita2d_free_texture(btn_rewind);
|
||||
vita2d_free_texture(btn_repeat_overlay);
|
||||
vita2d_free_texture(btn_repeat);
|
||||
vita2d_free_texture(btn_play);
|
||||
vita2d_free_texture(btn_pause);
|
||||
vita2d_free_texture(btn_forward);
|
||||
|
||||
vita2d_free_texture(icon_back);
|
||||
vita2d_free_texture(icon_dir);
|
||||
vita2d_free_texture(icon_file);
|
||||
vita2d_free_texture(icon_audio);
|
||||
|
||||
vita2d_free_texture(battery_unknown);
|
||||
vita2d_free_texture(battery_low);
|
||||
|
||||
vita2d_free_texture(battery_full_charging);
|
||||
vita2d_free_texture(battery_90_charging);
|
||||
vita2d_free_texture(battery_80_charging);
|
||||
vita2d_free_texture(battery_60_charging);
|
||||
vita2d_free_texture(battery_50_charging);
|
||||
vita2d_free_texture(battery_30_charging);
|
||||
vita2d_free_texture(battery_20_charging);
|
||||
|
||||
vita2d_free_texture(battery_full);
|
||||
vita2d_free_texture(battery_90);
|
||||
vita2d_free_texture(battery_80);
|
||||
vita2d_free_texture(battery_60);
|
||||
vita2d_free_texture(battery_50);
|
||||
vita2d_free_texture(battery_30);
|
||||
vita2d_free_texture(battery_20);
|
||||
}
|
92
source/utils.c
Normal file
@ -0,0 +1,92 @@
|
||||
#include <psp2/apputil.h>
|
||||
#include <psp2/io/dirent.h>
|
||||
#include <psp2/system_param.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static SceCtrlData pad, old_pad;
|
||||
|
||||
void Utils_SetMax(int *set, int value, int max) {
|
||||
if (*set > max)
|
||||
*set = value;
|
||||
}
|
||||
|
||||
void Utils_SetMin(int *set, int value, int min) {
|
||||
if (*set < min)
|
||||
*set = value;
|
||||
}
|
||||
|
||||
int Utils_ReadControls(void) {
|
||||
memset(&pad, 0, sizeof(SceCtrlData));
|
||||
sceCtrlPeekBufferPositive(0, &pad, 1);
|
||||
|
||||
pressed = pad.buttons & ~old_pad.buttons;
|
||||
|
||||
old_pad = pad;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Utils_InitAppUtil(void) {
|
||||
SceAppUtilInitParam init;
|
||||
SceAppUtilBootParam boot;
|
||||
memset(&init, 0, sizeof(SceAppUtilInitParam));
|
||||
memset(&boot, 0, sizeof(SceAppUtilBootParam));
|
||||
|
||||
int ret = 0;
|
||||
|
||||
if (R_FAILED(ret = sceAppUtilInit(&init, &boot)))
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Utils_TermAppUtil(void) {
|
||||
int ret = 0;
|
||||
|
||||
if (R_FAILED(ret = sceAppUtilShutdown()))
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Utils_GetEnterButton(void) {
|
||||
int button = 0;
|
||||
sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_ENTER_BUTTON, &button);
|
||||
|
||||
if (button == SCE_SYSTEM_PARAM_ENTER_BUTTON_CIRCLE)
|
||||
return SCE_CTRL_CIRCLE;
|
||||
else
|
||||
return SCE_CTRL_CROSS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Utils_GetCancelButton(void) {
|
||||
int button = 0;
|
||||
sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_ENTER_BUTTON, &button);
|
||||
|
||||
if (button == SCE_SYSTEM_PARAM_ENTER_BUTTON_CIRCLE)
|
||||
return SCE_CTRL_CROSS;
|
||||
else
|
||||
return SCE_CTRL_CIRCLE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Utils_Alphasort(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;
|
||||
|
||||
return strcasecmp(entryA->d_name, entryB->d_name);
|
||||
}
|
||||
|
||||
char *Utils_Basename(const char *filename) {
|
||||
char *p = strrchr (filename, '/');
|
||||
return p ? p + 1 : (char *) filename;
|
||||
}
|