diff --git a/Makefile b/Makefile index afb6bb4..0495ea8 100644 --- a/Makefile +++ b/Makefile @@ -2,20 +2,19 @@ TITLE_ID = VITASHELL TARGET = VitaShell OBJS = main.o init.o io_process.o package_installer.o network_update.o context_menu.o archive.o photo.o audioplayer.o file.o text.o hex.o sfo.o \ uncommon_dialog.o message_dialog.o ime_dialog.o config.o theme.o language.o utils.o sha1.o \ - minizip/unzip.o minizip/ioapi.o bm.o audio/vita_audio.o audio/player.o audio/id3.o audio/mp3player.o audio/mp3xing.o \ + minizip/unzip.o minizip/ioapi.o bm.o audio/vita_audio.o audio/player.o audio/id3.o audio/oggplayer.o audio/mp3player.o audio/mp3xing.o \ libmad/bit.o libmad/decoder.o libmad/fixed.o libmad/frame.o \ libmad/huffman.o libmad/layer12.o libmad/layer3.o \ libmad/stream.o libmad/synth.o libmad/timer.o -RESOURCES_PNG = resources/folder_icon.png resources/file_icon.png resources/archive_icon.png resources/image_icon.png \ - resources/audio_icon.png resources/sfo_icon.png resources/text_icon.png\ - resources/ftp.png resources/battery.png resources/battery_bar_green.png resources/battery_bar_red.png \ - resources/battery_bar_charge.png -RESOURCES_TXT = resources/theme.txt resources/colors.txt resources/english_us.txt resources/changeinfo.txt -RESOURCES_BIN = resources/updater_eboot.bin resources/updater_param.bin +RESOURCES = resources +RESOURCES_PNG := $(foreach dir,$(RESOURCES), $(wildcard $(dir)/*.png)) +RESOURCES_TXT := $(foreach dir,$(RESOURCES), $(wildcard $(dir)/*.txt)) +RESOURCES_BIN := $(foreach dir,$(RESOURCES), $(wildcard $(dir)/*.bin)) + OBJS += $(RESOURCES_PNG:.png=.o) $(RESOURCES_TXT:.txt=.o) $(RESOURCES_BIN:.bin=.o) -LIBS = -lftpvita -lvita2d -lpng -ljpeg -lz -lm -lc \ +LIBS = -lvorbisfile -logg -lvorbis -lftpvita -lvita2d -lpng -ljpeg -lz -lm -lc \ -lSceAppMgr_stub -lSceAppUtil_stub -lSceCommonDialog_stub \ -lSceCtrl_stub -lSceDisplay_stub -lSceGxm_stub -lSceIme_stub \ -lSceHttp_stub -lSceKernel_stub -lSceNet_stub -lSceNetCtl_stub \ diff --git a/README.md b/README.md index ddf4d8f..93ffb66 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,7 @@ Be sure you pull request your customized design or language file there. * vitasdk: https://github.com/vitasdk * vita2dlib: https://github.com/xerpi/vita2dlib * ftpvitalib https://github.com/xerpi/ftpvitalib +* EasyRPG libraries: https://ci.easyrpg.org/view/Toolchains/job/toolchain-vita/ ### Credits ### * Team Molecule for HENkaku diff --git a/audio/mp3player.c b/audio/mp3player.c index b288961..04ac793 100644 --- a/audio/mp3player.c +++ b/audio/mp3player.c @@ -16,6 +16,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include +#include #include #include #include @@ -26,7 +27,6 @@ #include "id3.h" #include "mp3xing.h" #include "player.h" -#include "vita_audio.h" #include "mp3player.h" #define FALSE 0 @@ -152,7 +152,7 @@ int fillFileBuffer() { // Read into the rest of the file buffer. unsigned char* bufferPos = fileBuffer + bytesToKeep; while (bytesToFill > 0){ - unsigned int bytesRead = sceIoRead(MP3_fd, bufferPos, bytesToFill); + int bytesRead = sceIoRead(MP3_fd, bufferPos, bytesToFill); if (bytesRead == 0x80010013) { MP3_suspend(); @@ -242,7 +242,14 @@ static void MP3Callback(void *buffer, unsigned int samplesToWrite, void *pdata){ //Check for playing speed: if (MP3_playingSpeed){ - if (sceIoLseek32(MP3_fd, 2 * INPUT_BUFFER_SIZE * MP3_playingSpeed, SCE_SEEK_CUR) != MP3_filePos){ + int res = sceIoLseek32(MP3_fd, 2 * INPUT_BUFFER_SIZE * MP3_playingSpeed, SCE_SEEK_CUR); + if (res == 0x80010013) { + MP3_suspend(); + MP3_resume(); + res = sceIoLseek32(MP3_fd, 2 * INPUT_BUFFER_SIZE * MP3_playingSpeed, SCE_SEEK_CUR); + } + + if (res != MP3_filePos){ MP3_filePos += 2 * INPUT_BUFFER_SIZE * MP3_playingSpeed; mad_timer_set(&Timer, (int)((float)MP3_info.length / 100.0 * MP3_GetPercentage()), 1, 1); }else @@ -580,6 +587,9 @@ int MP3_Load(char *filename){ return OPENING_OK; } +int MP3_IsPlaying() { + return MP3_isPlaying; +} /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // This function initialises for playing, and starts @@ -637,7 +647,7 @@ float MP3_GetPercentage(){ float perc = 0.0f; if (fileSize > 0){ - perc = ((float)MP3_filePos - (float)tagsize) / ((float)fileSize - (float)tagsize) * 100.0; + perc = ((float)MP3_filePos) / ((float)fileSize - (float)tagsize) * 100.0; if (perc > 100) perc = 100; } diff --git a/audio/mp3player.h b/audio/mp3player.h index 6898d79..fec8070 100644 --- a/audio/mp3player.h +++ b/audio/mp3player.h @@ -15,12 +15,13 @@ // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -#include +#include "../libmad/mad.h" extern int MP3_defaultCPUClock; //private functions void MP3_Init(int channel); +int MP3_IsPlaying(); int MP3_Play(); void MP3_Pause(); int MP3_Stop(); diff --git a/audio/mp3xing.h b/audio/mp3xing.h index 26e60ff..61cbc56 100644 --- a/audio/mp3xing.h +++ b/audio/mp3xing.h @@ -18,7 +18,7 @@ #ifndef __mp3xing_h #define __mp3xing_h (1) -#include +#include "../libmad/mad.h" #define XING_BUFFER_SIZE 300 #define XING_GUID (unsigned char [4]) \ diff --git a/audio/oggplayer.c b/audio/oggplayer.c new file mode 100644 index 0000000..ea31ab0 --- /dev/null +++ b/audio/oggplayer.c @@ -0,0 +1,536 @@ +// LightMP3 +// Copyright (C) 2007 Sakya +// sakya_tg@yahoo.it +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#include +#include +#include + +//#include "tremor/ivorbiscodec.h" //libtremor +//#include "tremor/ivorbisfile.h" //libtremor +#include //ogg-vorbis +#include //ogg-vorbis +#include "player.h" +#include "oggplayer.h" + +///////////////////////////////////////////////////////////////////////////////////////// +//Globals +///////////////////////////////////////////////////////////////////////////////////////// +static int OGG_audio_channel; +static int OGG_channels = 0; +static char OGG_fileName[264]; +static int OGG_file = -1; +static OggVorbis_File OGG_VorbisFile; +static int OGG_eos = 0; +static struct fileInfo OGG_info; +static int OGG_isPlaying = 0; +static unsigned int OGG_volume_boost = 0.0; +static double OGG_milliSeconds = 0.0; +static int OGG_playingSpeed = 0; // 0 = normal +static int OGG_playingDelta = 0; +static int outputInProgress = 0; +static long OGG_suspendPosition = -1; +static long OGG_suspendIsPlaying = 0; +int OGG_defaultCPUClock = 50; +static short OGG_mixBuffer[VITA_NUM_AUDIO_SAMPLES * 2 * 2]__attribute__ ((aligned(64))); +static unsigned long OGG_tempmixleft = 0; +static double OGG_newFilePos = -1; +static int OGG_tagRead = 0; + +///////////////////////////////////////////////////////////////////////////////////////// +//Audio callback +///////////////////////////////////////////////////////////////////////////////////////// +static void oggDecodeThread(void *_buf2, unsigned int numSamples, void *pdata){ + short *_buf = (short *)_buf2; + //static short OGG_mixBuffer[VITA_NUM_AUDIO_SAMPLES * 2 * 2]__attribute__ ((aligned(64))); + //static unsigned long OGG_tempmixleft = 0; + int current_section; + + if (OGG_isPlaying) { // Playing , so mix up a buffer + outputInProgress = 1; + while (OGG_tempmixleft < numSamples) { // Not enough in buffer, so we must mix more + unsigned long bytesRequired = (numSamples - OGG_tempmixleft) * 4; // 2channels, 16bit = 4 bytes per sample + //unsigned long ret = ov_read(&OGG_VorbisFile, (char *) &OGG_mixBuffer[OGG_tempmixleft * 2], bytesRequired, ¤t_section); //libtremor + unsigned long ret = ov_read(&OGG_VorbisFile, (char *) &OGG_mixBuffer[OGG_tempmixleft * 2], bytesRequired, 0, 2, 1, ¤t_section); //ogg-vorbis + if (!ret) { //EOF + OGG_isPlaying = 0; + OGG_eos = 1; + outputInProgress = 0; + return; + } else if (ret < 0) { + if (ret == OV_HOLE) + continue; + OGG_isPlaying = 0; + OGG_eos = 1; + outputInProgress = 0; + return; + } + OGG_tempmixleft += ret / 4; // back down to sample num + } + OGG_info.instantBitrate = ov_bitrate_instant(&OGG_VorbisFile); + OGG_milliSeconds = ov_time_tell(&OGG_VorbisFile); + + if (OGG_newFilePos >= 0) + { + ov_raw_seek(&OGG_VorbisFile, (ogg_int64_t)OGG_newFilePos); + OGG_newFilePos = -1; + } + + //Check for playing speed: + if (OGG_playingSpeed){ + if (ov_raw_seek(&OGG_VorbisFile, ov_raw_tell(&OGG_VorbisFile) + OGG_playingDelta) != 0) + OGG_setPlayingSpeed(0); + } + + if (OGG_tempmixleft >= numSamples) { // Buffer has enough, so copy across + int count, count2; + short *_buf2; + //Volume boost: + if (!OGG_volume_boost){ + for (count = 0; count < VITA_NUM_AUDIO_SAMPLES; count++) { + count2 = count + count; + _buf2 = _buf + count2; + *(_buf2) = OGG_mixBuffer[count2]; + *(_buf2 + 1) = OGG_mixBuffer[count2 + 1]; + } + }else{ + for (count = 0; count < VITA_NUM_AUDIO_SAMPLES; count++) { + count2 = count + count; + _buf2 = _buf + count2; + *(_buf2) = volume_boost(&OGG_mixBuffer[count2], &OGG_volume_boost); + *(_buf2 + 1) = volume_boost(&OGG_mixBuffer[count2 + 1], &OGG_volume_boost); + } + } + // Move the pointers + OGG_tempmixleft -= numSamples; + // Now shuffle the buffer along + for (count = 0; count < OGG_tempmixleft * 2; count++) + OGG_mixBuffer[count] = OGG_mixBuffer[numSamples * 2 + count]; + } + outputInProgress = 0; + } else { // Not Playing , so clear buffer + int count; + for (count = 0; count < numSamples * 2; count++) + *(_buf + count) = 0; + } +} + + +///////////////////////////////////////////////////////////////////////////////////////// +//Callback for vorbis +///////////////////////////////////////////////////////////////////////////////////////// +size_t ogg_callback_read(void *ptr, size_t size, size_t nmemb, void *datasource) +{ + int res = sceIoRead(*(int *) datasource, ptr, size * nmemb); + if (res == 0x80010013) { + OGG_suspend(); + OGG_resume(); + res = sceIoRead(*(int *) datasource, ptr, size * nmemb); + } + return res; +} +int ogg_callback_seek(void *datasource, ogg_int64_t offset, int whence) +{ + int res = sceIoLseek32(*(int *) datasource, (unsigned int) offset, whence); + if (res == 0x80010013) { + OGG_suspend(); + OGG_resume(); + res = sceIoLseek32(*(int *) datasource, (unsigned int) offset, whence); + } + return res; +} +long ogg_callback_tell(void *datasource) +{ + int res = sceIoLseek32(*(int *) datasource, 0, SEEK_CUR); + if (res == 0x80010013) { + OGG_suspend(); + OGG_resume(); + res = sceIoLseek32(*(int *) datasource, 0, SEEK_CUR); + } + return (long)res; +} +int ogg_callback_close(void *datasource) +{ + int res = sceIoClose(*(int *) datasource); + if (res == 0x80010013) { + OGG_suspend(); + OGG_resume(); + res = sceIoClose(*(int *) datasource); + } + return res; +} + +void readOggTagData(char *source, char *dest){ + int count = 0; + int i = 0; + + strcpy(dest, ""); + for (i=0; i= 0x20 && (unsigned char)source[i] <= 0xfd){ + dest[count] = source[i]; + if (++count >= 256) + break; + } + } + dest[count] = '\0'; +} + +void splitComment(char *comment, char *name, char *value){ + char *result = NULL; + result = strtok(comment, "="); + int count = 0; + + while(result != NULL && count < 2){ + if (strlen(result) > 0){ + switch (count){ + case 0: + strncpy(name, result, 30); + name[30] = '\0'; + break; + case 1: + readOggTagData(result, value); + value[256] = '\0'; + break; + } + count++; + } + result = strtok(NULL, "="); + } +} + +void getOGGTagInfo(OggVorbis_File *inVorbisFile, struct fileInfo *targetInfo){ + int i; + char name[31]; + char value[257]; + + vorbis_comment *comment = ov_comment(inVorbisFile, -1); + for (i=0;icomments; i++){ + splitComment(comment->user_comments[i], name, value); + if (!strcasecmp(name, "TITLE")) + strcpy(targetInfo->title, value); + else if(!strcasecmp(name, "ALBUM")) + strcpy(targetInfo->album, value); + else if(!strcasecmp(name, "ARTIST")) + strcpy(targetInfo->artist, value); + else if(!strcasecmp(name, "GENRE")) + strcpy(targetInfo->genre, value); + else if(!strcasecmp(name, "DATE") || !strcasecmp(name, "YEAR")){ + strncpy(targetInfo->year, value, 4); + targetInfo->year[4] = '\0'; + }else if(!strcasecmp(name, "TRACKNUMBER")){ + strncpy(targetInfo->trackNumber, value, 7); + targetInfo->trackNumber[7] = '\0'; + } + /*else if(!strcmp(name, "COVERART_UUENCODED")){ + FILE *out = fopen("ms0:/coverart.jpg", "wb"); + FILE *outEnc = fopen("ms0:/coverart.txt", "wb"); + unsigned char base64Buffer[MAX_IMAGE_DIMENSION]; + fwrite(&comment->user_comments[i][19], 1, comment->comment_lengths[i] - 19, outEnc); + int outChars = base64Decode(comment->comment_lengths[i], comment->user_comments[i], MAX_IMAGE_DIMENSION, base64Buffer); + fwrite(base64Buffer, 1, outChars, out); + fclose(outEnc); + fclose(out); + }*/ + } + + OGG_info = *targetInfo; + OGG_tagRead = 1; +} + +void OGGgetInfo(){ + //Estraggo le informazioni: + OGG_info.fileType = OGG_TYPE; + OGG_info.defaultCPUClock = OGG_defaultCPUClock; + OGG_info.needsME = 0; + + vorbis_info *vi = ov_info(&OGG_VorbisFile, -1); + OGG_info.kbit = vi->bitrate_nominal/1000; + OGG_info.instantBitrate = vi->bitrate_nominal; + OGG_info.hz = vi->rate; + OGG_info.length = (long)ov_time_total(&OGG_VorbisFile, -1)/1000; + if (vi->channels == 1){ + strcpy(OGG_info.mode, "single channel"); + OGG_channels = 1; + }else if (vi->channels == 2){ + strcpy(OGG_info.mode, "normal LR stereo"); + OGG_channels = 2; + } + strcpy(OGG_info.emphasis, "no"); + + int h = 0; + int m = 0; + int s = 0; + long secs = OGG_info.length; + h = secs / 3600; + m = (secs - h * 3600) / 60; + s = secs - h * 3600 - m * 60; + snprintf(OGG_info.strLength, sizeof(OGG_info.strLength), "%2.2i:%2.2i:%2.2i", h, m, s); + + if (!OGG_tagRead) + getOGGTagInfo(&OGG_VorbisFile, &OGG_info); +} + + +void OGG_Init(int channel){ + initAudioLib(); + MIN_PLAYING_SPEED=-119; + MAX_PLAYING_SPEED=119; + initFileInfo(&OGG_info); + OGG_tagRead = 0; + OGG_audio_channel = channel; + OGG_milliSeconds = 0.0; + OGG_tempmixleft = 0; + memset(OGG_mixBuffer, 0, sizeof(OGG_mixBuffer)); + vitaAudioSetChannelCallback(OGG_audio_channel, oggDecodeThread, NULL); +} + + +int OGG_Load(char *filename){ + outputInProgress = 0; + OGG_isPlaying = 0; + OGG_milliSeconds = 0; + OGG_eos = 0; + OGG_playingSpeed = 0; + OGG_playingDelta = 0; + strcpy(OGG_fileName, filename); + //Apro il file OGG: + OGG_file = sceIoOpen(OGG_fileName, SCE_O_RDONLY, 0777); + if (OGG_file >= 0) { + OGG_info.fileSize = sceIoLseek(OGG_file, 0, SCE_SEEK_END); + sceIoLseek(OGG_file, 0, SCE_SEEK_SET); + ov_callbacks ogg_callbacks; + + ogg_callbacks.read_func = ogg_callback_read; + ogg_callbacks.seek_func = ogg_callback_seek; + ogg_callbacks.close_func = ogg_callback_close; + ogg_callbacks.tell_func = ogg_callback_tell; + if (ov_open_callbacks(&OGG_file, &OGG_VorbisFile, NULL, 0, ogg_callbacks) < 0){ + sceIoClose(OGG_file); + OGG_file = -1; + return ERROR_OPENING; + } + }else{ + return ERROR_OPENING; + } + + OGGgetInfo(); + //Controllo il sample rate: + if (vitaAudioSetFrequency(OGG_audio_channel, OGG_info.hz) < 0){ + OGG_FreeTune(); + return ERROR_INVALID_SAMPLE_RATE; + } + return OPENING_OK; +} + +int OGG_IsPlaying() { + return OGG_isPlaying; +} + +int OGG_Play(){ + OGG_isPlaying = 1; + return 0; +} + +void OGG_Pause(){ + OGG_isPlaying = !OGG_isPlaying; +} + +int OGG_Stop(){ + OGG_isPlaying = 0; + //This is to be sure that oggDecodeThread isn't messing with &OGG_VorbisFile + while (outputInProgress == 1) + sceKernelDelayThread(100000); + return 0; +} + +void OGG_FreeTune(){ + ov_clear(&OGG_VorbisFile); + if (OGG_file >= 0) + sceIoClose(OGG_file); + OGG_file = -1; + OGG_tempmixleft = 0; + memset(OGG_mixBuffer, 0, sizeof(OGG_mixBuffer)); +} + +void OGG_GetTimeString(char *dest){ + char timeString[9]; + long secs = (long)OGG_milliSeconds/1000; + int h = secs / 3600; + int m = (secs - h * 3600) / 60; + int s = secs - h * 3600 - m * 60; + snprintf(timeString, sizeof(timeString), "%2.2i:%2.2i:%2.2i", h, m, s); + strcpy(dest, timeString); +} + + +int OGG_EndOfStream(){ + return OGG_eos; +} + +struct fileInfo *OGG_GetInfo(){ + return &OGG_info; +} + + +struct fileInfo OGG_GetTagInfoOnly(char *filename){ + int tempFile = -1; + OggVorbis_File vf; + struct fileInfo tempInfo; + + strcpy(OGG_fileName, filename); + initFileInfo(&tempInfo); + //Apro il file OGG: + tempFile = sceIoOpen(filename, SCE_O_RDONLY, 0777); + if (tempFile >= 0) { + //sceIoLseek(tempFile, 0, SCE_SEEK_SET); + ov_callbacks ogg_callbacks; + + ogg_callbacks.read_func = ogg_callback_read; + ogg_callbacks.seek_func = ogg_callback_seek; + ogg_callbacks.close_func = ogg_callback_close; + ogg_callbacks.tell_func = ogg_callback_tell; + + if (ov_open_callbacks(&tempFile, &vf, NULL, 0, ogg_callbacks) < 0){ + sceIoClose(tempFile); + return tempInfo; + } + getOGGTagInfo(&vf, &tempInfo); + ov_clear(&vf); + if (tempFile >= 0) + sceIoClose(tempFile); + } + + return tempInfo; +} + + +float OGG_GetPercentage(){ + float perc = 0.0f; + if (OGG_info.length){ + perc = (float)(OGG_milliSeconds/1000.0/(double)OGG_info.length*100.0); + if (perc > 100) + perc = 100; + } + return perc; +} + +void OGG_End(){ + OGG_Stop(); + vitaAudioSetChannelCallback(OGG_audio_channel, 0,0); + OGG_FreeTune(); + endAudioLib(); +} + +int OGG_setMute(int onOff){ + return setMute(OGG_audio_channel, onOff); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//Fade out: +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OGG_fadeOut(float seconds){ + fadeOut(OGG_audio_channel, seconds); +} + + +void OGG_setVolumeBoost(int boost){ + OGG_volume_boost = boost; +} + +int OGG_getVolumeBoost(){ + return OGG_volume_boost; +} + + +int OGG_setPlayingSpeed(int playingSpeed){ + if (playingSpeed >= MIN_PLAYING_SPEED && playingSpeed <= MAX_PLAYING_SPEED){ + OGG_playingSpeed = playingSpeed; + if (playingSpeed == 0) + setVolume(OGG_audio_channel, 0x8000); + else + setVolume(OGG_audio_channel, FASTFORWARD_VOLUME); + OGG_playingDelta = VITA_NUM_AUDIO_SAMPLES * (int)(OGG_playingSpeed/2); + return 0; + }else{ + return -1; + } +} + +int OGG_getPlayingSpeed(){ + return OGG_playingSpeed; +} + +int OGG_GetStatus(){ + return 0; +} + +void OGG_setVolumeBoostType(char *boostType){ + //Only old method supported + MAX_VOLUME_BOOST = 4; + MIN_VOLUME_BOOST = 0; +} + + +//Functions for filter (equalizer): +int OGG_setFilter(double tFilter[32], int copyFilter){ + return 0; +} + +void OGG_enableFilter(){} + +void OGG_disableFilter(){} + +int OGG_isFilterSupported(){ + return 0; +} + +int OGG_isFilterEnabled(){ + return 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//Manage suspend: +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int OGG_suspend(){ + OGG_suspendPosition = ov_raw_tell(&OGG_VorbisFile); + OGG_suspendIsPlaying = OGG_isPlaying; + //OGG_Stop(); + //OGG_FreeTune(); + OGG_End(); + return 0; +} + +int OGG_resume(){ + OGG_Init(OGG_audio_channel); + if (OGG_suspendPosition >= 0){ + if (OGG_Load(OGG_fileName) == OPENING_OK){ + if (ov_raw_seek(&OGG_VorbisFile, OGG_suspendPosition)) + OGG_isPlaying = OGG_suspendIsPlaying; + } + OGG_suspendPosition = -1; + } + return 0; +} + +double OGG_getFilePosition() +{ + return (double)ov_raw_tell(&OGG_VorbisFile); +} + +void OGG_setFilePosition(double position) +{ + OGG_newFilePos = position; +} diff --git a/audio/oggplayer.h b/audio/oggplayer.h new file mode 100644 index 0000000..c078db0 --- /dev/null +++ b/audio/oggplayer.h @@ -0,0 +1,55 @@ +// LightMP3 +// Copyright (C) 2007 Sakya +// sakya_tg@yahoo.it +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +extern int OGG_defaultCPUClock; + +//private functions +void OGG_Init(int channel); +int OGG_IsPlaying(); +int OGG_Play(); +void OGG_Pause(); +int OGG_Stop(); +void OGG_End(); +void OGG_FreeTune(); +int OGG_Load(char *filename); +void OGG_GetTimeString(char *dest); +int OGG_EndOfStream(); +struct fileInfo *OGG_GetInfo(); +struct fileInfo OGG_GetTagInfoOnly(char *filename); +int OGG_GetStatus(); +float OGG_GetPercentage(); +void OGG_setVolumeBoostType(char *boostType); +void OGG_setVolumeBoost(int boost); +int OGG_getVolumeBoost(); +int OGG_getPlayingSpeed(); +int OGG_setPlayingSpeed(int playingSpeed); +int OGG_setMute(int onOff); +void OGG_fadeOut(float seconds); + +//Functions for filter (equalizer): +int OGG_setFilter(double tFilter[32], int copyFilter); +void OGG_enableFilter(); +void OGG_disableFilter(); +int OGG_isFilterEnabled(); +int OGG_isFilterSupported(); + +//Manage suspend: +int OGG_suspend(); +int OGG_resume(); + +double OGG_getFilePosition(); +void OGG_setFilePosition(double position); diff --git a/audio/player.c b/audio/player.c index 34e568a..cc73c4c 100644 --- a/audio/player.c +++ b/audio/player.c @@ -17,16 +17,53 @@ */ #include +#include #include #include #include #include "player.h" +#include "mp3player.h" +#include "oggplayer.h" +#include "vita_audio.h" -int MAX_VOLUME_BOOST=15; -int MIN_VOLUME_BOOST=-15; -int MIN_PLAYING_SPEED=-119; -int MAX_PLAYING_SPEED=119; +#include "../file.h" + +int MUTED_VOLUME = 800; +int MAX_VOLUME_BOOST = 15; +int MIN_VOLUME_BOOST = -15; +int MIN_PLAYING_SPEED = -119; +int MAX_PLAYING_SPEED = 119; +int currentVolume = 0; + +void (* initFunct)(int); +int (* isPlayingFunct)(); +int (* loadFunct)(char *); +int (* playFunct)(); +void (* pauseFunct)(); +void (* endFunct)(); +void (* setVolumeBoostTypeFunct)(char*); +void (* setVolumeBoostFunct)(int); +struct fileInfo *(* getInfoFunct)(); +struct fileInfo (* getTagInfoFunct)(); +void (* getTimeStringFunct)(); +float (* getPercentageFunct)(); +int (* getPlayingSpeedFunct)(); +int (* setPlayingSpeedFunct)(int); +int (* endOfStreamFunct)(); + +int (* setMuteFunct)(int); +int (* setFilterFunct)(double[32], int copyFilter); +void (* enableFilterFunct)(); +void (* disableFilterFunct)(); +int (* isFilterEnabledFunct)(); +int (* isFilterSupportedFunct)(); +int (* suspendFunct)(); +int (* resumeFunct)(); +void (* fadeOutFunct)(float seconds); + +double (* getFilePositionFunct)(); +void (* setFilePositionFunct)(double positionInSecs); //Seek next valid frame //NOTE: this function comes from Music prx 0.55 source @@ -86,20 +123,136 @@ int SeekNextFrameMP3(SceUID fd) } } +int setAudioFunctions(int type) { + if (type == FILE_TYPE_OGG) { + //OGG Vorbis + initFunct = OGG_Init; + loadFunct = OGG_Load; + isPlayingFunct = OGG_IsPlaying; + playFunct = OGG_Play; + pauseFunct = OGG_Pause; + endFunct = OGG_End; + setVolumeBoostTypeFunct = OGG_setVolumeBoostType; + setVolumeBoostFunct = OGG_setVolumeBoost; + getInfoFunct = OGG_GetInfo; + getTagInfoFunct = OGG_GetTagInfoOnly; + getTimeStringFunct = OGG_GetTimeString; + getPercentageFunct = OGG_GetPercentage; + getPlayingSpeedFunct = OGG_getPlayingSpeed; + setPlayingSpeedFunct = OGG_setPlayingSpeed; + endOfStreamFunct = OGG_EndOfStream; + + setMuteFunct = OGG_setMute; + setFilterFunct = OGG_setFilter; + enableFilterFunct = OGG_enableFilter; + disableFilterFunct = OGG_disableFilter; + isFilterEnabledFunct = OGG_isFilterEnabled; + isFilterSupportedFunct = OGG_isFilterSupported; + + suspendFunct = OGG_suspend; + resumeFunct = OGG_resume; + fadeOutFunct = OGG_fadeOut; + + getFilePositionFunct = OGG_getFilePosition; + setFilePositionFunct = OGG_setFilePosition; + return 0; + } else if (type == FILE_TYPE_MP3) { + initFunct = MP3_Init; + loadFunct = MP3_Load; + isPlayingFunct = MP3_IsPlaying; + playFunct = MP3_Play; + pauseFunct = MP3_Pause; + endFunct = MP3_End; + setVolumeBoostTypeFunct = MP3_setVolumeBoostType; + setVolumeBoostFunct = MP3_setVolumeBoost; + getInfoFunct = MP3_GetInfo; + getTagInfoFunct = MP3_GetTagInfoOnly; + getTimeStringFunct = MP3_GetTimeString; + getPercentageFunct = MP3_GetPercentage; + getPlayingSpeedFunct = MP3_getPlayingSpeed; + setPlayingSpeedFunct = MP3_setPlayingSpeed; + endOfStreamFunct = MP3_EndOfStream; + + setMuteFunct = MP3_setMute; + setFilterFunct = MP3_setFilter; + enableFilterFunct = MP3_enableFilter; + disableFilterFunct = MP3_disableFilter; + isFilterEnabledFunct = MP3_isFilterEnabled; + isFilterSupportedFunct = MP3_isFilterSupported; + + suspendFunct = MP3_suspend; + resumeFunct = MP3_resume; + fadeOutFunct = MP3_fadeOut; + + getFilePositionFunct = MP3_getFilePosition; + setFilePositionFunct = MP3_setFilePosition; + + return 0; + } + + return -1; +} + +void unsetAudioFunctions() { + initFunct = NULL; + loadFunct = NULL; + playFunct = NULL; + pauseFunct = NULL; + endFunct = NULL; + setVolumeBoostTypeFunct = NULL; + setVolumeBoostFunct = NULL; + getInfoFunct = NULL; + getTagInfoFunct = NULL; + getTimeStringFunct = NULL; + getPercentageFunct = NULL; + getPlayingSpeedFunct = NULL; + setPlayingSpeedFunct = NULL; + endOfStreamFunct = NULL; + + setMuteFunct = NULL; + setFilterFunct = NULL; + enableFilterFunct = NULL; + disableFilterFunct = NULL; + isFilterEnabledFunct = NULL; + isFilterSupportedFunct = NULL; + + suspendFunct = NULL; + resumeFunct = NULL; + + getFilePositionFunct = NULL; + setFilePositionFunct = NULL; +} + short volume_boost(short *Sample, unsigned int *boost) { - return 0; + int intSample = *Sample * (*boost + 1); + if (intSample > 32767) + return 32767; + else if (intSample < -32768) + return -32768; + else + return intSample; } int setVolume(int channel, int volume) { + vitaAudioSetVolume(channel, volume, volume); return 0; } int setMute(int channel, int onOff) { + if (onOff) + setVolume(channel, MUTED_VOLUME); + else + setVolume(channel, VITA_VOLUME_MAX); return 0; } void fadeOut(int channel, float seconds) { - + int i = 0; + long timeToWait = (long)((seconds * 1000.0) / (float)currentVolume); + for (i=currentVolume; i>=0; i--){ + vitaAudioSetVolume(channel, i, i); + sceKernelDelayThread(timeToWait); + } } int initAudioLib() { diff --git a/audio/player.h b/audio/player.h index 225d7b1..7707203 100644 --- a/audio/player.h +++ b/audio/player.h @@ -19,7 +19,9 @@ #ifndef __PLAYER_H__ #define __PLAYER_H__ +#include "id3.h" #include "info.h" +#include "vita_audio.h" #define OPENING_OK 0 #define ERROR_OPENING -1 @@ -29,15 +31,9 @@ #define MP3_TYPE 0 #define OGG_TYPE 1 -#define AT3_TYPE 2 -#define FLAC_TYPE 3 -#define AAC_TYPE 4 -#define WMA_TYPE 5 #define UNK_TYPE -1 -#define FASTFORWARD_VOLUME 0x2200 -#define MAX_IMAGE_DIMENSION 300*1024 -#define DEFAULT_THREAD_STACK_SIZE 256*1024 +#define FASTFORWARD_VOLUME 0 // 0x2200 extern int MAX_VOLUME_BOOST; extern int MIN_VOLUME_BOOST; @@ -56,4 +52,36 @@ int endAudioLib(); void initFileInfo(struct fileInfo *info); +extern void (* initFunct)(int); +extern int (* loadFunct)(char *); +extern int (* isPlayingFunct)(); +extern int (* playFunct)(); +extern void (* pauseFunct)(); +extern void (* endFunct)(); +extern void (* setVolumeBoostTypeFunct)(char*); +extern void (* setVolumeBoostFunct)(int); +extern struct fileInfo *(* getInfoFunct)(); +extern struct fileInfo (* getTagInfoFunct)(); +extern void (* getTimeStringFunct)(); +extern float (* getPercentageFunct)(); +extern int (* getPlayingSpeedFunct)(); +extern int (* setPlayingSpeedFunct)(int); +extern int (* endOfStreamFunct)(); + +extern int (* setMuteFunct)(int); +extern int (* setFilterFunct)(double[32], int copyFilter); +extern void (* enableFilterFunct)(); +extern void (* disableFilterFunct)(); +extern int (* isFilterEnabledFunct)(); +extern int (* isFilterSupportedFunct)(); +extern int (* suspendFunct)(); +extern int (* resumeFunct)(); +extern void (* fadeOutFunct)(float seconds); + +extern double (* getFilePositionFunct)(); //Gets current file position in bytes +extern void (* setFilePositionFunct)(double position); //Set current file position in butes + +extern int setAudioFunctions(int type); +extern void unsetAudioFunctions(); + #endif \ No newline at end of file diff --git a/audio/vita_audio.c b/audio/vita_audio.c index 3546277..44a1c68 100644 --- a/audio/vita_audio.c +++ b/audio/vita_audio.c @@ -6,8 +6,6 @@ #include #include "vita_audio.h" -#define VITA_WAV_MAX_SLOTS 128 - static vitaWav vitaWavInfo[VITA_WAV_MAX_SLOTS]; static int vitaWavPlaying[VITA_WAV_MAX_SLOTS]; static int vitaWavId[VITA_WAV_MAX_SLOTS]; @@ -18,12 +16,6 @@ static int vitaWavIdFlag = 0; static int vitaWavInitFlag = 0; -#define VITA_NUM_AUDIO_CHANNELS 1 // 4 -#define VITA_NUM_AUDIO_SAMPLES 1024 -#define VITA_VOLUME_MAX 0x8000 - -typedef void (* vitaAudioCallback)(void *buf, unsigned int reqn, void *pdata); - typedef struct { int threadHandle; @@ -42,8 +34,13 @@ static vitaAudioChannelInfo vitaAudioStatus[VITA_NUM_AUDIO_CHANNELS]; static volatile int vitaAudioTerminate = 0; +void vitaAudioSetVolume(int channel, int left, int right) { + vitaAudioStatus[channel].volumeLeft = left; + vitaAudioStatus[channel].volumeRight = right; +} + int vitaAudioSetFrequency(int channel, unsigned short freq) { - return 0; + return sceAudioOutSetConfig(vitaAudioStatus[channel].handle, VITA_NUM_AUDIO_SAMPLES, freq, SCE_AUDIO_OUT_MODE_STEREO); } void vitaAudioSetChannelCallback(int channel, vitaAudioCallback callback, void *data) diff --git a/audio/vita_audio.h b/audio/vita_audio.h index e915421..6bf32d3 100644 --- a/audio/vita_audio.h +++ b/audio/vita_audio.h @@ -14,6 +14,14 @@ extern "C" { #endif +#define VITA_WAV_MAX_SLOTS 128 + +#define VITA_NUM_AUDIO_CHANNELS 1 // 4 +#define VITA_NUM_AUDIO_SAMPLES 1024 +#define VITA_VOLUME_MAX 0x8000 + +typedef void (* vitaAudioCallback)(void *buf, unsigned int reqn, void *pdata); + /** @defgroup vitaWav WAV Library * @{ */ @@ -109,6 +117,11 @@ void vitaWavLoop(vitaWav *wav, unsigned int loop); /** @} */ +void vitaAudioSetVolume(int channel, int left, int right); +int vitaAudioSetFrequency(int channel, unsigned short freq); +void vitaAudioSetChannelCallback(int channel, vitaAudioCallback callback, void *data); +int vitaAudioInit(int priority); + #ifdef __cplusplus } #endif // __cplusplus diff --git a/audioplayer.c b/audioplayer.c index afcbef7..02ea562 100644 --- a/audioplayer.c +++ b/audioplayer.c @@ -21,19 +21,18 @@ #include "audioplayer.h" #include "file.h" #include "theme.h" +#include "language.h" #include "utils.h" -#include "audio/id3.h" -#include "audio/info.h" -#include "audio/mp3player.h" +#include "audio/player.h" struct fileInfo *fileinfo = NULL; vita2d_texture *tex = NULL; -void getMp3Info(char *file) { +void getAudioInfo(char *file) { char *buffer = NULL; - fileinfo = MP3_GetInfo(); + fileinfo = getInfoFunct(); if (tex) { vita2d_free_texture(tex); @@ -58,6 +57,9 @@ void getMp3Info(char *file) { if (fileinfo->encapsulatedPictureType == PNG_IMAGE) tex = vita2d_load_PNG_buffer(buffer); + if (tex) + vita2d_texture_set_filters(tex, SCE_GXM_TEXTURE_FILTER_LINEAR, SCE_GXM_TEXTURE_FILTER_LINEAR); + free(buffer); } @@ -68,11 +70,20 @@ void getMp3Info(char *file) { } int audioPlayer(char *file, int type, FileList *list, FileListEntry *entry, int *base_pos, int *rel_pos) { - MP3_Init(0); - MP3_Load(file); - MP3_Play(); + static int speed_list[] = { -7, -3, -1, 0, 1, 3, 7 }; + #define N_SPEED (sizeof(speed_list) / sizeof(int)) - getMp3Info(file); + sceAppMgrAcquireBgmPort(); + + powerLock(); + + setAudioFunctions(type); + + initFunct(0); + loadFunct(file); + playFunct(); + + getAudioInfo(file); while (1) { readPad(); @@ -82,8 +93,51 @@ int audioPlayer(char *file, int type, FileList *list, FileListEntry *entry, int break; } + // Display off + if (pressed_buttons & SCE_CTRL_TRIANGLE) { + scePowerRequestDisplayOff(); + } + + // Toggle play/pause + if (pressed_buttons & SCE_CTRL_ENTER) { + if (isPlayingFunct() && getPlayingSpeedFunct() == 0) { + pauseFunct(); + } else { + setPlayingSpeedFunct(0); + playFunct(); + } + } + + if (pressed_buttons & SCE_CTRL_LEFT || pressed_buttons & SCE_CTRL_RIGHT) { + int speed = getPlayingSpeedFunct(); + + if (pressed_buttons & SCE_CTRL_LEFT) { + int i; + for (i = 0; i < N_SPEED; i++) { + if (speed_list[i] == speed) { + if (i > 0) + speed = speed_list[i - 1]; + break; + } + } + } + + if (pressed_buttons & SCE_CTRL_RIGHT) { + int i; + for (i = 0; i < N_SPEED; i++) { + if (speed_list[i] == speed) { + if (i < N_SPEED - 1) + speed = speed_list[i + 1]; + break; + } + } + } + + setPlayingSpeedFunct(speed); + } + // Previous/next song. - if (MP3_EndOfStream() || pressed_buttons & SCE_CTRL_LTRIGGER || pressed_buttons & SCE_CTRL_RTRIGGER) { + if (getPercentageFunct() == 100.0f || endOfStreamFunct() || pressed_buttons & SCE_CTRL_LTRIGGER || pressed_buttons & SCE_CTRL_RTRIGGER) { int available = 0; int old_base_pos = *base_pos; @@ -91,7 +145,11 @@ int audioPlayer(char *file, int type, FileList *list, FileListEntry *entry, int FileListEntry *old_entry = entry; int previous = pressed_buttons & SCE_CTRL_LTRIGGER; - if (MP3_EndOfStream()) + + if (getPercentageFunct() == 100.0f && !endOfStreamFunct()) + previous = 1; + + if (endOfStreamFunct()) previous = 0; while (previous ? entry->previous : entry->next) { @@ -121,12 +179,19 @@ int audioPlayer(char *file, int type, FileList *list, FileListEntry *entry, int char path[MAX_PATH_LENGTH]; snprintf(path, MAX_PATH_LENGTH, "%s%s", list->path, entry->name); int type = getFileType(path); - if (type == FILE_TYPE_MP3) { - MP3_End(); - MP3_Init(0); - MP3_Load(path); - MP3_Play(); - getMp3Info(path); + if (type == FILE_TYPE_MP3 || type == FILE_TYPE_OGG) { + file = path; + + endFunct(); + + setAudioFunctions(type); + + initFunct(0); + loadFunct(file); + playFunct(); + + getAudioInfo(file); + available = 1; break; } @@ -147,25 +212,68 @@ int audioPlayer(char *file, int type, FileList *list, FileListEntry *entry, int // Draw shell info drawShellInfo(file); - pgf_draw_textf(SHELL_MARGIN_X, START_Y + (0 * FONT_Y_SPACE), 0xFFFFFFFF, FONT_SIZE, fileinfo->artist); - pgf_draw_textf(SHELL_MARGIN_X, START_Y + (1 * FONT_Y_SPACE), 0xFFFFFFFF, FONT_SIZE, fileinfo->title); - pgf_draw_textf(SHELL_MARGIN_X, START_Y + (2 * FONT_Y_SPACE), 0xFFFFFFFF, FONT_SIZE, fileinfo->album); + float cover_size = MAX_ENTRIES * FONT_Y_SPACE; - // Picture - if (tex) - vita2d_draw_texture_scale(tex, SHELL_MARGIN_X, 200.0f, 1.0f, 1.0f); + // Cover + if (tex) { + vita2d_draw_texture_scale(tex, SHELL_MARGIN_X, START_Y, cover_size / vita2d_texture_get_width(tex), cover_size / vita2d_texture_get_height(tex)); + } else { + vita2d_draw_texture(cover_image, SHELL_MARGIN_X, START_Y); + } + + float x = 2.0f * SHELL_MARGIN_X + cover_size; + + pgf_draw_text(x, START_Y + (0 * FONT_Y_SPACE), AUDIO_INFO_ASSIGN, FONT_SIZE, language_container[TITLE]); + pgf_draw_text(x, START_Y + (1 * FONT_Y_SPACE), AUDIO_INFO_ASSIGN, FONT_SIZE, language_container[ALBUM]); + pgf_draw_text(x, START_Y + (2 * FONT_Y_SPACE), AUDIO_INFO_ASSIGN, FONT_SIZE, language_container[ARTIST]); + pgf_draw_text(x, START_Y + (3 * FONT_Y_SPACE), AUDIO_INFO_ASSIGN, FONT_SIZE, language_container[GENRE]); + pgf_draw_text(x, START_Y + (4 * FONT_Y_SPACE), AUDIO_INFO_ASSIGN, FONT_SIZE, language_container[YEAR]); + + pgf_draw_text(x + 120.0f, START_Y + (0 * FONT_Y_SPACE), AUDIO_INFO, FONT_SIZE, fileinfo->title[0] == '\0' ? "-" : fileinfo->title); + pgf_draw_text(x + 120.0f, START_Y + (1 * FONT_Y_SPACE), AUDIO_INFO, FONT_SIZE, fileinfo->album[0] == '\0' ? "-" : fileinfo->album); + pgf_draw_text(x + 120.0f, START_Y + (2 * FONT_Y_SPACE), AUDIO_INFO, FONT_SIZE, fileinfo->artist[0] == '\0' ? "-" : fileinfo->artist); + pgf_draw_text(x + 120.0f, START_Y + (3 * FONT_Y_SPACE), AUDIO_INFO, FONT_SIZE, fileinfo->genre[0] == '\0' ? "-" : fileinfo->genre); + pgf_draw_text(x + 120.0f, START_Y + (4 * FONT_Y_SPACE), AUDIO_INFO, FONT_SIZE, fileinfo->year[0] == '\0' ? "-" : fileinfo->year); + + float y = SCREEN_HEIGHT - 6.0f * SHELL_MARGIN_Y; + + // Icon + vita2d_texture *icon = NULL; + + if (getPlayingSpeedFunct() != 0) { + if (getPlayingSpeedFunct() < 0) { + icon = fastrewind_image; + } else { + icon = fastforward_image; + } + + pgf_draw_textf(x + 45.0f, y, AUDIO_SPEED, FONT_SIZE, "%dx", abs(getPlayingSpeedFunct() + (getPlayingSpeedFunct() < 0 ? -1 : 1))); + } else { + if (isPlayingFunct()) { + icon = play_image; + } else { + icon = pause_image; + } + } + + vita2d_draw_texture(icon, x, y + 3.0f); // Time - char string[12]; - MP3_GetTimeString(string); + char cur_time_string[12]; + getTimeStringFunct(cur_time_string); + + char string[32]; + sprintf(string, "%s / %s", cur_time_string, fileinfo->strLength); + float time_x = ALIGN_LEFT(SCREEN_WIDTH - SHELL_MARGIN_X, vita2d_pgf_text_width(font, FONT_SIZE, string)); + + int w = pgf_draw_text(time_x, y, AUDIO_TIME_CURRENT, FONT_SIZE, cur_time_string); + pgf_draw_text(time_x + (float)w, y, AUDIO_TIME_SLASH, FONT_SIZE, " /"); + pgf_draw_text(ALIGN_LEFT(SCREEN_WIDTH - SHELL_MARGIN_X, vita2d_pgf_text_width(font, FONT_SIZE, fileinfo->strLength)), y, AUDIO_TIME_TOTAL, FONT_SIZE, fileinfo->strLength); + + float width = SCREEN_WIDTH - 3.0f * SHELL_MARGIN_X - cover_size; + vita2d_draw_rectangle(x, (y) + FONT_Y_SPACE + 10.0f, width, 8, AUDIO_TIME_BAR_BG); + vita2d_draw_rectangle(x, (y) + FONT_Y_SPACE + 10.0f, getPercentageFunct() * width / 100.0f, 8, AUDIO_TIME_BAR); - pgf_draw_textf(SHELL_MARGIN_X, SCREEN_HEIGHT - 3.0f * SHELL_MARGIN_Y, PHOTO_ZOOM_COLOR, FONT_SIZE, "%s/%s", string, fileinfo->strLength); -/* - //float percent = MP3_GetPercentage(); - float width = uncommon_dialog.width - 2.0f * SHELL_MARGIN_X; - vita2d_draw_rectangle(uncommon_dialog.x + SHELL_MARGIN_X, string_y + 10.0f, width, UNCOMMON_DIALOG_PROGRESS_BAR_HEIGHT, PROGRESS_BAR_BG_COLOR); - vita2d_draw_rectangle(uncommon_dialog.x + SHELL_MARGIN_X, string_y + 10.0f, uncommon_dialog.progress * width / 100.0f, UNCOMMON_DIALOG_PROGRESS_BAR_HEIGHT, PROGRESS_BAR_COLOR); -*/ // End drawing endDrawing(); } @@ -175,7 +283,11 @@ int audioPlayer(char *file, int type, FileList *list, FileListEntry *entry, int tex = NULL; } - MP3_End(); + endFunct(); + + powerUnlock(); + + sceAppMgrReleaseBgmPort(); return 0; } \ No newline at end of file diff --git a/file.c b/file.c index d2b3949..76ee21f 100644 --- a/file.c +++ b/file.c @@ -538,6 +538,7 @@ static ExtensionType extension_types[] = { { ".JPG", FILE_TYPE_JPEG }, { ".JPEG", FILE_TYPE_JPEG }, { ".MP3", FILE_TYPE_MP3 }, + { ".OGG", FILE_TYPE_OGG }, { ".PNG", FILE_TYPE_PNG }, { ".SFO", FILE_TYPE_SFO }, { ".TXT", FILE_TYPE_TXT }, diff --git a/file.h b/file.h index 0c692aa..fadd9a6 100644 --- a/file.h +++ b/file.h @@ -35,6 +35,7 @@ enum FileTypes { FILE_TYPE_INI, FILE_TYPE_JPEG, FILE_TYPE_MP3, + FILE_TYPE_OGG, FILE_TYPE_PNG, FILE_TYPE_SFO, FILE_TYPE_TXT, diff --git a/init.c b/init.c index 49f179e..7d492bd 100644 --- a/init.c +++ b/init.c @@ -21,59 +21,56 @@ #include "file.h" #include "utils.h" -extern unsigned char _binary_resources_changeinfo_txt_start; -extern unsigned char _binary_resources_changeinfo_txt_size; +INCLUDE_EXTERN_RESOURCE(changeinfo_txt); -extern unsigned char _binary_resources_folder_icon_png_start; -extern unsigned char _binary_resources_folder_icon_png_size; -extern unsigned char _binary_resources_file_icon_png_start; -extern unsigned char _binary_resources_file_icon_png_size; -extern unsigned char _binary_resources_archive_icon_png_start; -extern unsigned char _binary_resources_archive_icon_png_size; -extern unsigned char _binary_resources_image_icon_png_start; -extern unsigned char _binary_resources_image_icon_png_size; -extern unsigned char _binary_resources_audio_icon_png_start; -extern unsigned char _binary_resources_audio_icon_png_size; -extern unsigned char _binary_resources_sfo_icon_png_start; -extern unsigned char _binary_resources_sfo_icon_png_size; -extern unsigned char _binary_resources_text_icon_png_start; -extern unsigned char _binary_resources_text_icon_png_size; -extern unsigned char _binary_resources_ftp_png_start; -extern unsigned char _binary_resources_ftp_png_size; -extern unsigned char _binary_resources_battery_png_start; -extern unsigned char _binary_resources_battery_png_size; -extern unsigned char _binary_resources_battery_bar_red_png_start; -extern unsigned char _binary_resources_battery_bar_red_png_size; -extern unsigned char _binary_resources_battery_bar_green_png_start; -extern unsigned char _binary_resources_battery_bar_green_png_size; -extern unsigned char _binary_resources_battery_bar_charge_png_start; -extern unsigned char _binary_resources_battery_bar_charge_png_size; - -extern unsigned char _binary_resources_theme_txt_start; -extern unsigned char _binary_resources_theme_txt_size; +INCLUDE_EXTERN_RESOURCE(folder_icon_png); +INCLUDE_EXTERN_RESOURCE(file_icon_png); +INCLUDE_EXTERN_RESOURCE(archive_icon_png); +INCLUDE_EXTERN_RESOURCE(image_icon_png); +INCLUDE_EXTERN_RESOURCE(audio_icon_png); +INCLUDE_EXTERN_RESOURCE(sfo_icon_png); +INCLUDE_EXTERN_RESOURCE(text_icon_png); +INCLUDE_EXTERN_RESOURCE(ftp_png); +INCLUDE_EXTERN_RESOURCE(battery_png); +INCLUDE_EXTERN_RESOURCE(battery_bar_red_png); +INCLUDE_EXTERN_RESOURCE(battery_bar_green_png); +INCLUDE_EXTERN_RESOURCE(battery_bar_charge_png); -extern unsigned char _binary_resources_colors_txt_start; -extern unsigned char _binary_resources_colors_txt_size; +INCLUDE_EXTERN_RESOURCE(cover_png); +INCLUDE_EXTERN_RESOURCE(play_png); +INCLUDE_EXTERN_RESOURCE(pause_png); +INCLUDE_EXTERN_RESOURCE(fastforward_png); +INCLUDE_EXTERN_RESOURCE(fastrewind_png); -extern unsigned char _binary_resources_english_us_txt_start; -extern unsigned char _binary_resources_english_us_txt_size; +INCLUDE_EXTERN_RESOURCE(theme_txt); +INCLUDE_EXTERN_RESOURCE(colors_txt); +INCLUDE_EXTERN_RESOURCE(english_us_txt); + +#define DEFAULT_FILE(pah, name) { "ux0:VitaShell/language/english_us.txt", (void *)&_binary_resources_##name##_start, (int)&_binary_resources_##name##_size } static DefaultFile default_files[] = { - { "ux0:VitaShell/language/english_us.txt", (void *)&_binary_resources_english_us_txt_start, (int)&_binary_resources_english_us_txt_size }, - { "ux0:VitaShell/theme/theme.txt", (void *)&_binary_resources_theme_txt_start, (int)&_binary_resources_theme_txt_size }, - { "ux0:VitaShell/theme/Default/colors.txt", (void *)&_binary_resources_colors_txt_start, (int)&_binary_resources_colors_txt_size }, - { "ux0:VitaShell/theme/Default/folder_icon.png", (void *)&_binary_resources_folder_icon_png_start, (int)&_binary_resources_folder_icon_png_size }, - { "ux0:VitaShell/theme/Default/file_icon.png", (void *)&_binary_resources_file_icon_png_start, (int)&_binary_resources_file_icon_png_size }, - { "ux0:VitaShell/theme/Default/archive_icon.png", (void *)&_binary_resources_archive_icon_png_start, (int)&_binary_resources_archive_icon_png_size }, - { "ux0:VitaShell/theme/Default/image_icon.png", (void *)&_binary_resources_image_icon_png_start, (int)&_binary_resources_image_icon_png_size }, - { "ux0:VitaShell/theme/Default/audio_icon.png", (void *)&_binary_resources_audio_icon_png_start, (int)&_binary_resources_audio_icon_png_size }, - { "ux0:VitaShell/theme/Default/sfo_icon.png", (void *)&_binary_resources_sfo_icon_png_start, (int)&_binary_resources_sfo_icon_png_size }, - { "ux0:VitaShell/theme/Default/text_icon.png", (void *)&_binary_resources_text_icon_png_start, (int)&_binary_resources_text_icon_png_size }, - { "ux0:VitaShell/theme/Default/ftp.png", (void *)&_binary_resources_ftp_png_start, (int)&_binary_resources_ftp_png_size }, - { "ux0:VitaShell/theme/Default/battery.png", (void *)&_binary_resources_battery_png_start, (int)&_binary_resources_battery_png_size }, - { "ux0:VitaShell/theme/Default/battery_bar_red.png", (void *)&_binary_resources_battery_bar_red_png_start, (int)&_binary_resources_battery_bar_red_png_size }, - { "ux0:VitaShell/theme/Default/battery_bar_green.png", (void *)&_binary_resources_battery_bar_green_png_start, (int)&_binary_resources_battery_bar_green_png_size }, - { "ux0:VitaShell/theme/Default/battery_bar_charge.png", (void *)&_binary_resources_battery_bar_charge_png_start, (int)&_binary_resources_battery_bar_charge_png_size }, + DEFAULT_FILE("ux0:VitaShell/language/english_us.txt", english_us_txt), + + DEFAULT_FILE("ux0:VitaShell/theme/theme.txt", theme_txt), + DEFAULT_FILE("ux0:VitaShell/theme/Default/colors.txt", colors_txt), + DEFAULT_FILE("ux0:VitaShell/theme/Default/folder_icon.png", folder_icon_png), + DEFAULT_FILE("ux0:VitaShell/theme/Default/file_icon.png", file_icon_png), + DEFAULT_FILE("ux0:VitaShell/theme/Default/archive_icon.png", archive_icon_png), + DEFAULT_FILE("ux0:VitaShell/theme/Default/image_icon.png", image_icon_png), + DEFAULT_FILE("ux0:VitaShell/theme/Default/audio_icon.png", audio_icon_png), + DEFAULT_FILE("ux0:VitaShell/theme/Default/sfo_icon.png", sfo_icon_png), + DEFAULT_FILE("ux0:VitaShell/theme/Default/text_icon.png", text_icon_png), + DEFAULT_FILE("ux0:VitaShell/theme/Default/ftp.png", ftp_png), + DEFAULT_FILE("ux0:VitaShell/theme/Default/battery.png", battery_png), + DEFAULT_FILE("ux0:VitaShell/theme/Default/battery_bar_red.png", battery_bar_red_png), + DEFAULT_FILE("ux0:VitaShell/theme/Default/battery_bar_green.png", battery_bar_green_png), + DEFAULT_FILE("ux0:VitaShell/theme/Default/battery_bar_charge.png", battery_bar_charge_png), + + DEFAULT_FILE("ux0:VitaShell/theme/Default/cover.png", cover_png), + DEFAULT_FILE("ux0:VitaShell/theme/Default/play.png", play_png), + DEFAULT_FILE("ux0:VitaShell/theme/Default/pause.png", pause_png), + DEFAULT_FILE("ux0:VitaShell/theme/Default/fastforward.png", fastforward_png), + DEFAULT_FILE("ux0:VitaShell/theme/Default/fastrewind.png", fastrewind_png), }; vita2d_pgf *font = NULL; diff --git a/language.c b/language.c index c793c47..e7e93b9 100644 --- a/language.c +++ b/language.c @@ -20,8 +20,7 @@ #include "config.h" #include "language.h" -extern unsigned char _binary_resources_english_us_txt_start; -extern unsigned char _binary_resources_english_us_txt_size; +INCLUDE_EXTERN_RESOURCE(english_us_txt); static char *lang[] ={ "japanese", @@ -80,6 +79,13 @@ void loadLanguage(int id) { LANGUAGE_ENTRY(EXTRACTING), LANGUAGE_ENTRY(HASHING), + // Audio player strings + LANGUAGE_ENTRY(TITLE), + LANGUAGE_ENTRY(ALBUM), + LANGUAGE_ENTRY(ARTIST), + LANGUAGE_ENTRY(GENRE), + LANGUAGE_ENTRY(YEAR), + // Hex editor strings LANGUAGE_ENTRY(CUT), LANGUAGE_ENTRY(OPEN_HEX_EDITOR), diff --git a/language.h b/language.h index 729408f..ec78f8f 100644 --- a/language.h +++ b/language.h @@ -37,6 +37,13 @@ enum LanguageContainer { EXTRACTING, HASHING, + // Audio player strings + TITLE, + ALBUM, + ARTIST, + GENRE, + YEAR, + // Hex editor strings OFFSET, OPEN_HEX_EDITOR, diff --git a/libmad/mad.h b/libmad/mad.h index 9ef6cc8..34423ca 100644 --- a/libmad/mad.h +++ b/libmad/mad.h @@ -24,7 +24,7 @@ extern "C" { # endif -# define FPM_INTEL +# define FPM_DEFAULT diff --git a/main.c b/main.c index 7f8f64d..b24ae7b 100644 --- a/main.c +++ b/main.c @@ -46,6 +46,8 @@ #include "utils.h" #include "sfo.h" +#include "audio/vita_audio.h" + int _newlib_heap_size_user = 64 * 1024 * 1024; #define MAX_DIR_LEVELS 1024 @@ -260,6 +262,8 @@ int handleFile(char *file, FileListEntry *entry) { int type = getFileType(file); switch (type) { + case FILE_TYPE_MP3: + case FILE_TYPE_OGG: case FILE_TYPE_VPK: case FILE_TYPE_ZIP: if (isInArchive()) @@ -283,6 +287,7 @@ int handleFile(char *file, FileListEntry *entry) { break; case FILE_TYPE_MP3: + case FILE_TYPE_OGG: res = audioPlayer(file, type, &file_list, entry, &base_pos, &rel_pos); break; @@ -1404,6 +1409,7 @@ int shellMain() { break; case FILE_TYPE_MP3: + case FILE_TYPE_OGG: color = IMAGE_COLOR; icon = audio_icon; break; @@ -1568,7 +1574,7 @@ int main(int argc, const char *argv[]) { initTextContextMenuWidth(); // Automatic network update - SceUID thid = sceKernelCreateThread("network_update_thread", (SceKernelThreadEntry)network_update_thread, 0x40, 0x10000, 0, 0, NULL); + SceUID thid = sceKernelCreateThread("network_update_thread", (SceKernelThreadEntry)network_update_thread, 0x10000100, 0x10000, 0, 0, NULL); if (thid >= 0) sceKernelStartThread(thid, 0, NULL); diff --git a/main.h b/main.h index a0a525a..335a60a 100644 --- a/main.h +++ b/main.h @@ -61,6 +61,8 @@ #include "functions.h" +#define INCLUDE_EXTERN_RESOURCE(name) extern unsigned char _binary_resources_##name##_start; extern unsigned char _binary_resources_##name##_size; \ + #define ENABLE_FILE_LOGGING 1 // VitaShell version major.minor diff --git a/network_update.c b/network_update.c index 47c086a..f802526 100644 --- a/network_update.c +++ b/network_update.c @@ -199,7 +199,7 @@ int network_update_thread(SceSize args, void *argp) { // Wait for response while (dialog_step == DIALOG_STEP_UPDATE_QUESTION) { - sceKernelDelayThread(1000); + sceKernelDelayThread(10 * 1000); } // No diff --git a/package_installer.c b/package_installer.c index 8ca8dc6..5ff2d9e 100644 --- a/package_installer.c +++ b/package_installer.c @@ -366,7 +366,7 @@ int install_thread(SceSize args_size, InstallArguments *args) { // Wait for response while (dialog_step == DIALOG_STEP_INSTALL_WARNING) { - sceKernelDelayThread(1000); + sceKernelDelayThread(10 * 1000); } // Cancelled diff --git a/resources/colors.txt b/resources/colors.txt index 9e1fdc5..5bdb24d 100644 --- a/resources/colors.txt +++ b/resources/colors.txt @@ -44,4 +44,14 @@ TEXT_LINE_NUMBER_COLOR_FOCUS = 0xFF7F7F7F # Gray TEXT_HIGHLIGHT_COLOR = 0xFF80F5FF # Yellow # Photo viewer colors -PHOTO_ZOOM_COLOR = 0xFFFFFFFF # White \ No newline at end of file +PHOTO_ZOOM_COLOR = 0xFFFFFFFF # White + +# Audio player colors +AUDIO_INFO_ASSIGN = 0xFFFFFF00 # Cyan +AUDIO_INFO = 0xFFFFFFFF # White +AUDIO_SPEED = 0xFFFFFFFF # White +AUDIO_TIME_CURRENT = 0xFF00FF00 # Green +AUDIO_TIME_SLASH = 0xFFFFFFFF # White +AUDIO_TIME_TOTAL = 0xFFFFFFFF # White +AUDIO_TIME_BAR = 0xFFFF7F00 # Azure +AUDIO_TIME_BAR_BG = 0xFF7F7F7F # Gray \ No newline at end of file diff --git a/resources/cover.png b/resources/cover.png new file mode 100644 index 0000000..5aba2c4 Binary files /dev/null and b/resources/cover.png differ diff --git a/resources/english_us.txt b/resources/english_us.txt index bd40796..061d56b 100644 --- a/resources/english_us.txt +++ b/resources/english_us.txt @@ -17,6 +17,13 @@ DOWNLOADING = "Downloading..." EXTRACTING = "Extracting..." HASHING = "Hashing..." +# Audio player strings +TITLE = "Title" +ALBUM = "Album" +ARTIST = "Artist" +GENRE = "Genre" +YEAR = "Year" + # Hex editor strings OFFSET = "Offset" OPEN_HEX_EDITOR = "Open hex editor" diff --git a/resources/fastforward.png b/resources/fastforward.png new file mode 100644 index 0000000..478939f Binary files /dev/null and b/resources/fastforward.png differ diff --git a/resources/fastrewind.png b/resources/fastrewind.png new file mode 100644 index 0000000..7465bfd Binary files /dev/null and b/resources/fastrewind.png differ diff --git a/resources/pause.png b/resources/pause.png new file mode 100644 index 0000000..ac945a0 Binary files /dev/null and b/resources/pause.png differ diff --git a/resources/play.png b/resources/play.png new file mode 100644 index 0000000..8bb7023 Binary files /dev/null and b/resources/play.png differ diff --git a/resources/stop.png b/resources/stop.png new file mode 100644 index 0000000..394dfdd Binary files /dev/null and b/resources/stop.png differ diff --git a/theme.c b/theme.c index 2c6ef26..6e0cb41 100644 --- a/theme.c +++ b/theme.c @@ -22,21 +22,27 @@ #include "theme.h" #include "utils.h" -extern unsigned char _binary_resources_folder_icon_png_start; -extern unsigned char _binary_resources_file_icon_png_start; -extern unsigned char _binary_resources_archive_icon_png_start; -extern unsigned char _binary_resources_image_icon_png_start; -extern unsigned char _binary_resources_audio_icon_png_start; -extern unsigned char _binary_resources_sfo_icon_png_start; -extern unsigned char _binary_resources_text_icon_png_start; -extern unsigned char _binary_resources_ftp_png_start; -extern unsigned char _binary_resources_battery_png_start; -extern unsigned char _binary_resources_battery_bar_red_png_start; -extern unsigned char _binary_resources_battery_bar_green_png_start; -extern unsigned char _binary_resources_battery_bar_charge_png_start; +INCLUDE_EXTERN_RESOURCE(colors_txt); +INCLUDE_EXTERN_RESOURCE(colors_txt_size); -extern unsigned char _binary_resources_colors_txt_start; -extern unsigned char _binary_resources_colors_txt_size; +INCLUDE_EXTERN_RESOURCE(folder_icon_png); +INCLUDE_EXTERN_RESOURCE(file_icon_png); +INCLUDE_EXTERN_RESOURCE(archive_icon_png); +INCLUDE_EXTERN_RESOURCE(image_icon_png); +INCLUDE_EXTERN_RESOURCE(audio_icon_png); +INCLUDE_EXTERN_RESOURCE(sfo_icon_png); +INCLUDE_EXTERN_RESOURCE(text_icon_png); +INCLUDE_EXTERN_RESOURCE(ftp_png); +INCLUDE_EXTERN_RESOURCE(battery_png); +INCLUDE_EXTERN_RESOURCE(battery_bar_red_png); +INCLUDE_EXTERN_RESOURCE(battery_bar_green_png); +INCLUDE_EXTERN_RESOURCE(battery_bar_charge_png); + +INCLUDE_EXTERN_RESOURCE(cover_png); +INCLUDE_EXTERN_RESOURCE(play_png); +INCLUDE_EXTERN_RESOURCE(pause_png); +INCLUDE_EXTERN_RESOURCE(fastforward_png); +INCLUDE_EXTERN_RESOURCE(fastrewind_png); // Shell colors int BACKGROUND_COLOR; @@ -84,10 +90,20 @@ int TEXT_HIGHLIGHT_COLOR; // Photo viewer colors int PHOTO_ZOOM_COLOR; +// Audio player colors +int AUDIO_INFO_ASSIGN; +int AUDIO_INFO; +int AUDIO_SPEED; +int AUDIO_TIME_CURRENT; +int AUDIO_TIME_SLASH; +int AUDIO_TIME_TOTAL; +int AUDIO_TIME_BAR; +int AUDIO_TIME_BAR_BG; + vita2d_texture *folder_icon = NULL, *file_icon = NULL, *archive_icon = NULL, *image_icon = NULL, *audio_icon = NULL, *sfo_icon = NULL, *text_icon = NULL, *ftp_image = NULL, *dialog_image = NULL, *context_image = NULL, *context_more_image = NULL, *battery_image = NULL, *battery_bar_red_image = NULL, *battery_bar_green_image = NULL, *battery_bar_charge_image = NULL, *bg_browser_image = NULL, *bg_hex_image = NULL, - *bg_text_image = NULL, *bg_photo_image = NULL; + *bg_text_image = NULL, *bg_photo_image = NULL, *cover_image = NULL, *play_image = NULL, *pause_image = NULL, *fastforward_image = NULL, *fastrewind_image = NULL; vita2d_texture *wallpaper_image[MAX_WALLPAPERS]; @@ -143,6 +159,16 @@ void loadTheme() { // Photo viewer colors COLOR_ENTRY(PHOTO_ZOOM_COLOR), + + // Audio player colors + COLOR_ENTRY(AUDIO_INFO_ASSIGN), + COLOR_ENTRY(AUDIO_INFO), + COLOR_ENTRY(AUDIO_SPEED), + COLOR_ENTRY(AUDIO_TIME_CURRENT), + COLOR_ENTRY(AUDIO_TIME_SLASH), + COLOR_ENTRY(AUDIO_TIME_TOTAL), + COLOR_ENTRY(AUDIO_TIME_BAR), + COLOR_ENTRY(AUDIO_TIME_BAR_BG), }; // Load default config file @@ -223,6 +249,21 @@ void loadTheme() { snprintf(path, MAX_PATH_LENGTH, "ux0:VitaShell/theme/%s/bg_photoviewer.png", theme_name); bg_photo_image = vita2d_load_PNG_file(path); + snprintf(path, MAX_PATH_LENGTH, "ux0:VitaShell/theme/%s/cover.png", theme_name); + cover_image = vita2d_load_PNG_file(path); + + snprintf(path, MAX_PATH_LENGTH, "ux0:VitaShell/theme/%s/play.png", theme_name); + play_image = vita2d_load_PNG_file(path); + + snprintf(path, MAX_PATH_LENGTH, "ux0:VitaShell/theme/%s/pause.png", theme_name); + pause_image = vita2d_load_PNG_file(path); + + snprintf(path, MAX_PATH_LENGTH, "ux0:VitaShell/theme/%s/fastforward.png", theme_name); + fastforward_image = vita2d_load_PNG_file(path); + + snprintf(path, MAX_PATH_LENGTH, "ux0:VitaShell/theme/%s/fastrewind.png", theme_name); + fastrewind_image = vita2d_load_PNG_file(path); + // Wallpapers snprintf(path, MAX_PATH_LENGTH, "ux0:VitaShell/theme/%s/wallpaper.png", theme_name); vita2d_texture *image = vita2d_load_PNG_file(path); @@ -320,4 +361,19 @@ void loadTheme() { if (!battery_bar_charge_image) battery_bar_charge_image = vita2d_load_PNG_buffer(&_binary_resources_battery_bar_charge_png_start); + + if (!cover_image) + cover_image = vita2d_load_PNG_buffer(&_binary_resources_cover_png_start); + + if (!play_image) + play_image = vita2d_load_PNG_buffer(&_binary_resources_play_png_start); + + if (!pause_image) + pause_image = vita2d_load_PNG_buffer(&_binary_resources_pause_png_start); + + if (!fastforward_image) + fastforward_image = vita2d_load_PNG_buffer(&_binary_resources_fastforward_png_start); + + if (!fastrewind_image) + fastrewind_image = vita2d_load_PNG_buffer(&_binary_resources_fastrewind_png_start); } \ No newline at end of file diff --git a/theme.h b/theme.h index ebb678d..47c8501 100644 --- a/theme.h +++ b/theme.h @@ -67,9 +67,20 @@ extern int TEXT_HIGHLIGHT_COLOR; // Photo viewer colors extern int PHOTO_ZOOM_COLOR; +// Audio player colors +extern int AUDIO_INFO_ASSIGN; +extern int AUDIO_INFO; +extern int AUDIO_SPEED; +extern int AUDIO_TIME_CURRENT; +extern int AUDIO_TIME_SLASH; +extern int AUDIO_TIME_TOTAL; +extern int AUDIO_TIME_BAR; +extern int AUDIO_TIME_BAR_BG; + extern vita2d_texture *folder_icon, *file_icon, *archive_icon, *image_icon, *audio_icon, *sfo_icon, *text_icon, - *ftp_image, *dialog_image, *context_image, *context_more_image, *battery_image, *battery_bar_red_image, *battery_bar_green_image, - *battery_bar_charge_image, *bg_browser_image, *bg_hex_image, *bg_text_image, *bg_photo_image; + *ftp_image, *dialog_image, *context_image, *context_more_image, *battery_image, *battery_bar_red_image, + *battery_bar_green_image, *battery_bar_charge_image, *bg_browser_image, *bg_hex_image, *bg_text_image, + *bg_photo_image, *cover_image, *play_image, *pause_image, *fastforward_image, *fastrewind_image; extern vita2d_texture *wallpaper_image[MAX_WALLPAPERS]; extern vita2d_texture *previous_wallpaper_image, *current_wallpaper_image;