Add missing function headers
Signed-off-by: Mahyar Koshkouei <deltabeard@users.noreply.github.com>
This commit is contained in:
@@ -2,6 +2,12 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return string describing error number. Extends strerror to include some
|
||||||
|
* custom errors used in ctrmus.
|
||||||
|
*
|
||||||
|
* \param err Error number.
|
||||||
|
*/
|
||||||
char* ctrmus_strerror(int err)
|
char* ctrmus_strerror(int err)
|
||||||
{
|
{
|
||||||
char* error;
|
char* error;
|
||||||
|
|||||||
@@ -5,11 +5,25 @@
|
|||||||
#define DECODER_INIT_FAIL 1001
|
#define DECODER_INIT_FAIL 1001
|
||||||
#define FILE_NOT_SUPPORTED 1002
|
#define FILE_NOT_SUPPORTED 1002
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct to help error handling across threads.
|
||||||
|
*/
|
||||||
struct errInfo_t
|
struct errInfo_t
|
||||||
{
|
{
|
||||||
|
/* errno code or from defines listed above */
|
||||||
volatile int* error;
|
volatile int* error;
|
||||||
Handle* failEvent;
|
|
||||||
|
/* Extra information regarding error (Must be NULL if unused) */
|
||||||
volatile char* errstr;
|
volatile char* errstr;
|
||||||
|
|
||||||
|
/* Event to trigger on error */
|
||||||
|
Handle* failEvent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return string describing error number. Extends strerror to include some
|
||||||
|
* custom errors used in ctrmus.
|
||||||
|
*
|
||||||
|
* \param err Error number.
|
||||||
|
*/
|
||||||
char* ctrmus_strerror(int err);
|
char* ctrmus_strerror(int err);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#define DR_FLAC_IMPLEMENTATION
|
#define DR_FLAC_IMPLEMENTATION
|
||||||
#include <./dr_libs/dr_flac.h>
|
#include <./dr_libs/dr_flac.h>
|
||||||
|
|
||||||
#include "all.h"
|
#include "all.h"
|
||||||
#include "flac.h"
|
#include "flac.h"
|
||||||
|
|
||||||
|
|||||||
340
source/main.c
340
source/main.c
@@ -22,6 +22,185 @@
|
|||||||
|
|
||||||
volatile bool runThreads = true;
|
volatile bool runThreads = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the current key mappings to stdio.
|
||||||
|
*/
|
||||||
|
static void showControls(void)
|
||||||
|
{
|
||||||
|
printf("Button mappings:\n"
|
||||||
|
"Pause: L+R or L+Up\n"
|
||||||
|
"Stop: L+B\n"
|
||||||
|
"A: Open File\n"
|
||||||
|
"B: Go up folder\n"
|
||||||
|
"Start: Exit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows the playback thread to return any error messages that it may
|
||||||
|
* encounter.
|
||||||
|
*
|
||||||
|
* \param infoIn Struct containing addresses of the event, the error code,
|
||||||
|
* and an optional error string.
|
||||||
|
*/
|
||||||
|
void playbackWatchdog(void* infoIn)
|
||||||
|
{
|
||||||
|
struct watchdogInfo* info = infoIn;
|
||||||
|
|
||||||
|
while(runThreads)
|
||||||
|
{
|
||||||
|
svcWaitSynchronization(*info->errInfo->failEvent, U64_MAX);
|
||||||
|
svcClearEvent(*info->errInfo->failEvent);
|
||||||
|
consoleSelect(info->screen);
|
||||||
|
|
||||||
|
if(*info->errInfo->error != 0)
|
||||||
|
{
|
||||||
|
printf("Error %d: %s", *info->errInfo->error,
|
||||||
|
ctrmus_strerror(*info->errInfo->error));
|
||||||
|
|
||||||
|
if(info->errInfo->errstr != NULL)
|
||||||
|
{
|
||||||
|
printf(" %s", info->errInfo->errstr);
|
||||||
|
delete(info->errInfo->errstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the currently playing file (if there is one) and play another file.
|
||||||
|
*
|
||||||
|
* \param ep_file File to play.
|
||||||
|
* \param playbackInfo Information that the playback thread requires to
|
||||||
|
* play file.
|
||||||
|
*/
|
||||||
|
static int changeFile(const char* ep_file, struct playbackInfo_t* playbackInfo)
|
||||||
|
{
|
||||||
|
s32 prio;
|
||||||
|
static Thread thread = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If music is playing, stop it. Only one playback thread should be playing
|
||||||
|
* at any time.
|
||||||
|
*/
|
||||||
|
if(thread != NULL)
|
||||||
|
{
|
||||||
|
/* Tell the thread to stop playback before we join it */
|
||||||
|
stopPlayback();
|
||||||
|
|
||||||
|
threadJoin(thread, U64_MAX);
|
||||||
|
threadFree(thread);
|
||||||
|
thread = NULL;
|
||||||
|
|
||||||
|
/* free allocated file string */
|
||||||
|
delete(playbackInfo->file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ep_file == NULL || playbackInfo == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
playbackInfo->file = strdup(ep_file);
|
||||||
|
printf("Playing: %s\n", playbackInfo->file);
|
||||||
|
|
||||||
|
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
|
||||||
|
thread = threadCreate(playFile, playbackInfo, 32 * 1024, prio - 1, -2, false);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List current directory.
|
||||||
|
*
|
||||||
|
* \param from First entry in directory to list.
|
||||||
|
* \param max Maximum number of entries to list. Must be > 0.
|
||||||
|
* \param select File to show as selected. Must be > 0.
|
||||||
|
* \return Number of entries listed or negative on error.
|
||||||
|
*/
|
||||||
|
static int listDir(int from, int max, int select)
|
||||||
|
{
|
||||||
|
DIR *dp;
|
||||||
|
struct dirent *ep;
|
||||||
|
int fileNum = 0;
|
||||||
|
int listed = 0;
|
||||||
|
char* wd = getcwd(NULL, 0);
|
||||||
|
|
||||||
|
if(wd == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
consoleClear();
|
||||||
|
printf("Dir: %.33s\n", wd);
|
||||||
|
|
||||||
|
if((dp = opendir(wd)) == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if(from == 0)
|
||||||
|
{
|
||||||
|
printf("%c../\n", select == 0 ? '>' : ' ');
|
||||||
|
listed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while((ep = readdir(dp)) != NULL)
|
||||||
|
{
|
||||||
|
fileNum++;
|
||||||
|
|
||||||
|
if(fileNum <= from)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
listed++;
|
||||||
|
|
||||||
|
printf("%c%s%.37s%s\n",
|
||||||
|
select == fileNum ? '>' : ' ',
|
||||||
|
ep->d_type == DT_DIR ? "\x1b[34;1m" : "",
|
||||||
|
ep->d_name,
|
||||||
|
ep->d_type == DT_DIR ? "/\x1b[0m" : "");
|
||||||
|
|
||||||
|
if(fileNum == max + from)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(closedir(dp) != 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
out:
|
||||||
|
free(wd);
|
||||||
|
return listed;
|
||||||
|
|
||||||
|
err:
|
||||||
|
listed = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get number of files in current working folder
|
||||||
|
*
|
||||||
|
* \return Number of files in current working folder, -1 on failure with
|
||||||
|
* errno set.
|
||||||
|
*/
|
||||||
|
int getNumberFiles(void)
|
||||||
|
{
|
||||||
|
DIR *dp;
|
||||||
|
struct dirent *ep;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if((dp = opendir(".")) == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
while((ep = readdir(dp)) != NULL)
|
||||||
|
ret++;
|
||||||
|
|
||||||
|
closedir(dp);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
err:
|
||||||
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
PrintConsole topScreen;
|
PrintConsole topScreen;
|
||||||
@@ -262,164 +441,3 @@ err:
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void showControls(void)
|
|
||||||
{
|
|
||||||
printf("Button mappings:\n"
|
|
||||||
"Pause: L+R or L+Up\n"
|
|
||||||
"Stop: L+B\n"
|
|
||||||
"A: Open File\n"
|
|
||||||
"B: Go up folder\n"
|
|
||||||
"Start: Exit\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void playbackWatchdog(void* infoIn)
|
|
||||||
{
|
|
||||||
struct watchdogInfo* info = infoIn;
|
|
||||||
|
|
||||||
while(runThreads)
|
|
||||||
{
|
|
||||||
svcWaitSynchronization(*info->errInfo->failEvent, U64_MAX);
|
|
||||||
svcClearEvent(*info->errInfo->failEvent);
|
|
||||||
consoleSelect(info->screen);
|
|
||||||
|
|
||||||
if(*info->errInfo->error != 0)
|
|
||||||
{
|
|
||||||
printf("Error %d: %s", *info->errInfo->error,
|
|
||||||
ctrmus_strerror(*info->errInfo->error));
|
|
||||||
|
|
||||||
if(info->errInfo->errstr != NULL)
|
|
||||||
{
|
|
||||||
printf(" %s", info->errInfo->errstr);
|
|
||||||
delete(info->errInfo->errstr);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int changeFile(const char* ep_file, struct playbackInfo_t* playbackInfo)
|
|
||||||
{
|
|
||||||
s32 prio;
|
|
||||||
static Thread thread = NULL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If music is playing, stop it. Only one playback thread should be playing
|
|
||||||
* at any time.
|
|
||||||
*/
|
|
||||||
if(thread != NULL)
|
|
||||||
{
|
|
||||||
/* Tell the thread to stop playback before we join it */
|
|
||||||
stopPlayback();
|
|
||||||
|
|
||||||
threadJoin(thread, U64_MAX);
|
|
||||||
threadFree(thread);
|
|
||||||
thread = NULL;
|
|
||||||
|
|
||||||
/* free allocated file string */
|
|
||||||
delete(playbackInfo->file);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ep_file == NULL || playbackInfo == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
playbackInfo->file = strdup(ep_file);
|
|
||||||
printf("Playing: %s\n", playbackInfo->file);
|
|
||||||
|
|
||||||
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
|
|
||||||
thread = threadCreate(playFile, playbackInfo, 32 * 1024, prio - 1, -2, false);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List current directory.
|
|
||||||
*
|
|
||||||
* \param from First entry in directory to list.
|
|
||||||
* \param max Maximum number of entries to list. Must be > 0.
|
|
||||||
* \param select File to show as selected. Must be > 0.
|
|
||||||
* \return Number of entries listed or negative on error.
|
|
||||||
*/
|
|
||||||
int listDir(int from, int max, int select)
|
|
||||||
{
|
|
||||||
DIR *dp;
|
|
||||||
struct dirent *ep;
|
|
||||||
int fileNum = 0;
|
|
||||||
int listed = 0;
|
|
||||||
char* wd = getcwd(NULL, 0);
|
|
||||||
|
|
||||||
if(wd == NULL)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
consoleClear();
|
|
||||||
printf("Dir: %.33s\n", wd);
|
|
||||||
|
|
||||||
if((dp = opendir(wd)) == NULL)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if(from == 0)
|
|
||||||
{
|
|
||||||
printf("%c../\n", select == 0 ? '>' : ' ');
|
|
||||||
listed++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while((ep = readdir(dp)) != NULL)
|
|
||||||
{
|
|
||||||
fileNum++;
|
|
||||||
|
|
||||||
if(fileNum <= from)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
listed++;
|
|
||||||
|
|
||||||
printf("%c%s%.37s%s\n",
|
|
||||||
select == fileNum ? '>' : ' ',
|
|
||||||
ep->d_type == DT_DIR ? "\x1b[34;1m" : "",
|
|
||||||
ep->d_name,
|
|
||||||
ep->d_type == DT_DIR ? "/\x1b[0m" : "");
|
|
||||||
|
|
||||||
if(fileNum == max + from)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(closedir(dp) != 0)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
out:
|
|
||||||
free(wd);
|
|
||||||
return listed;
|
|
||||||
|
|
||||||
err:
|
|
||||||
listed = -1;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get number of files in current working folder
|
|
||||||
*
|
|
||||||
* \return Number of files in current working folder, -1 on failure with
|
|
||||||
* errno set.
|
|
||||||
*/
|
|
||||||
int getNumberFiles(void)
|
|
||||||
{
|
|
||||||
DIR *dp;
|
|
||||||
struct dirent *ep;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if((dp = opendir(".")) == NULL)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
while((ep = readdir(dp)) != NULL)
|
|
||||||
ret++;
|
|
||||||
|
|
||||||
closedir(dp);
|
|
||||||
|
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
err:
|
|
||||||
ret = -1;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
#ifndef ctrmus_main_h
|
#ifndef ctrmus_main_h
|
||||||
#define ctrmus_main_h
|
#define ctrmus_main_h
|
||||||
|
|
||||||
#include "playback.h"
|
|
||||||
|
|
||||||
/* Default folder */
|
/* Default folder */
|
||||||
#define DEFAULT_DIR "sdmc:/"
|
#define DEFAULT_DIR "sdmc:/"
|
||||||
|
|
||||||
@@ -24,12 +22,15 @@ struct watchdogInfo
|
|||||||
struct errInfo_t* errInfo;
|
struct errInfo_t* errInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows the playback thread to return any error messages that it may
|
||||||
|
* encounter.
|
||||||
|
*
|
||||||
|
* \param infoIn Struct containing addresses of the event, the error code,
|
||||||
|
* and an optional error string.
|
||||||
|
*/
|
||||||
void playbackWatchdog(void* infoIn);
|
void playbackWatchdog(void* infoIn);
|
||||||
|
|
||||||
static void showControls(void);
|
|
||||||
|
|
||||||
static int changeFile(const char* ep_file, struct playbackInfo_t* playbackInfo);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get number of files in current working folder
|
* Get number of files in current working folder
|
||||||
*
|
*
|
||||||
@@ -38,14 +39,4 @@ static int changeFile(const char* ep_file, struct playbackInfo_t* playbackInfo);
|
|||||||
*/
|
*/
|
||||||
int getNumberFiles(void);
|
int getNumberFiles(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* List current directory.
|
|
||||||
*
|
|
||||||
* \param from First entry in directory to list.
|
|
||||||
* \param max Maximum number of entries to list. Must be > 0.
|
|
||||||
* \param select File to show as selected. Must be > 0.
|
|
||||||
* \return Number of entries listed or negative on error.
|
|
||||||
*/
|
|
||||||
int listDir(int from, int max, int select);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -71,7 +71,8 @@ uint8_t channelOpus(void)
|
|||||||
* Decode part of open Opus file.
|
* Decode part of open Opus file.
|
||||||
*
|
*
|
||||||
* \param buffer Decoded output.
|
* \param buffer Decoded output.
|
||||||
* \return Samples read for each channel.
|
* \return Samples read for each channel. 0 for end of file, negative
|
||||||
|
* for error.
|
||||||
*/
|
*/
|
||||||
uint64_t decodeOpus(void* buffer)
|
uint64_t decodeOpus(void* buffer)
|
||||||
{
|
{
|
||||||
@@ -104,11 +105,7 @@ uint64_t fillOpusBuffer(OggOpusFile* opusFile, int16_t* bufferOut)
|
|||||||
samplesToRead > 120*48*2 ? 120*48*2 : samplesToRead);
|
samplesToRead > 120*48*2 ? 120*48*2 : samplesToRead);
|
||||||
|
|
||||||
if(samplesJustRead < 0)
|
if(samplesJustRead < 0)
|
||||||
{
|
return samplesJustRead;
|
||||||
/* TODO: Printing should not be done here. */
|
|
||||||
printf("\nFatal error decoding Opus: %d.", samplesJustRead);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if(samplesJustRead == 0)
|
else if(samplesJustRead == 0)
|
||||||
{
|
{
|
||||||
/* End of file reached. */
|
/* End of file reached. */
|
||||||
|
|||||||
@@ -12,10 +12,118 @@
|
|||||||
|
|
||||||
static volatile bool stop = false;
|
static volatile bool stop = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pause or play current file.
|
||||||
|
*
|
||||||
|
* \return True if paused.
|
||||||
|
*/
|
||||||
|
bool togglePlayback(void)
|
||||||
|
{
|
||||||
|
bool paused = ndspChnIsPaused(CHANNEL);
|
||||||
|
ndspChnSetPaused(CHANNEL, !paused);
|
||||||
|
return !paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops current playback. Playback thread should exit as a result.
|
||||||
|
*/
|
||||||
|
void stopPlayback(void)
|
||||||
|
{
|
||||||
|
stop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether music is playing or paused.
|
||||||
|
*/
|
||||||
|
bool isPlaying(void)
|
||||||
|
{
|
||||||
|
return !stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains file type.
|
||||||
|
*
|
||||||
|
* \param file File location.
|
||||||
|
* \return File type, else negative and errno set.
|
||||||
|
*/
|
||||||
|
static int getFileType(const char *file)
|
||||||
|
{
|
||||||
|
FILE* ftest = fopen(file, "rb");
|
||||||
|
int fileSig = 0;
|
||||||
|
enum file_types file_type = FILE_TYPE_ERROR;
|
||||||
|
|
||||||
|
/* Failure opening file */
|
||||||
|
if(ftest == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(fread(&fileSig, 4, 1, ftest) == 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
switch(fileSig)
|
||||||
|
{
|
||||||
|
// "RIFF"
|
||||||
|
case 0x46464952:
|
||||||
|
if(fseek(ftest, 4, SEEK_CUR) != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// "WAVE"
|
||||||
|
// Check required as AVI file format also uses "RIFF".
|
||||||
|
if(fread(&fileSig, 4, 1, ftest) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(fileSig != 0x45564157)
|
||||||
|
break;
|
||||||
|
|
||||||
|
file_type = FILE_TYPE_WAV;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// "fLaC"
|
||||||
|
case 0x43614c66:
|
||||||
|
file_type = FILE_TYPE_FLAC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// "OggS"
|
||||||
|
case 0x5367674f:
|
||||||
|
if(isOpus(file) == 0)
|
||||||
|
file_type = FILE_TYPE_OPUS;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//file_type = FILE_TYPE_OGG;
|
||||||
|
errno = FILE_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* MP3 without ID3 tag, ID3v1 tag is at the end of file, or MP3
|
||||||
|
* with ID3 tag at the beginning of the file.
|
||||||
|
*/
|
||||||
|
if((fileSig << 16) == 0xFBFF0000 ||
|
||||||
|
(fileSig << 16) == 0xFAFF0000 ||
|
||||||
|
(fileSig << 8) == 0x33444900)
|
||||||
|
{
|
||||||
|
file_type = FILE_TYPE_MP3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Add this again at some point */
|
||||||
|
//printf("Unknown magic number: %#010x\n.", fileSig);
|
||||||
|
errno = FILE_NOT_SUPPORTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
fclose(ftest);
|
||||||
|
return file_type;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should only be called from a new thread only, and have only one playback
|
* Should only be called from a new thread only, and have only one playback
|
||||||
* thread at time. This function has not been written for more than one
|
* thread at time. This function has not been written for more than one
|
||||||
* playback thread in mind.
|
* playback thread in mind.
|
||||||
|
*
|
||||||
|
* \param infoIn Playback information.
|
||||||
*/
|
*/
|
||||||
void playFile(void* infoIn)
|
void playFile(void* infoIn)
|
||||||
{
|
{
|
||||||
@@ -28,10 +136,6 @@ void playFile(void* infoIn)
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
const char* file = info->file;
|
const char* file = info->file;
|
||||||
|
|
||||||
|
|
||||||
//info->errInfo->errstr = strdup("Testing.");
|
|
||||||
//errno = 1001;
|
|
||||||
//goto err;
|
|
||||||
/* Reset previous stop command */
|
/* Reset previous stop command */
|
||||||
stop = false;
|
stop = false;
|
||||||
|
|
||||||
@@ -116,7 +220,7 @@ void playFile(void* infoIn)
|
|||||||
{
|
{
|
||||||
size_t read = (*decoder.decode)(&buffer1[0]);
|
size_t read = (*decoder.decode)(&buffer1[0]);
|
||||||
|
|
||||||
if(read == 0)
|
if(read <= 0)
|
||||||
{
|
{
|
||||||
lastbuf = true;
|
lastbuf = true;
|
||||||
continue;
|
continue;
|
||||||
@@ -131,7 +235,7 @@ void playFile(void* infoIn)
|
|||||||
{
|
{
|
||||||
size_t read = (*decoder.decode)(&buffer2[0]);
|
size_t read = (*decoder.decode)(&buffer2[0]);
|
||||||
|
|
||||||
if(read == 0)
|
if(read <= 0)
|
||||||
{
|
{
|
||||||
lastbuf = true;
|
lastbuf = true;
|
||||||
continue;
|
continue;
|
||||||
@@ -157,107 +261,6 @@ out:
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
*info->errInfo->error = errno;
|
*info->errInfo->error = errno;
|
||||||
printf("%s:%d errno:%d %d\n", __func__, __LINE__, errno, *info->errInfo->error);
|
|
||||||
svcSignalEvent(*info->errInfo->failEvent);
|
svcSignalEvent(*info->errInfo->failEvent);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Pause or play current file.
|
|
||||||
*
|
|
||||||
* \return True if paused.
|
|
||||||
*/
|
|
||||||
bool togglePlayback(void)
|
|
||||||
{
|
|
||||||
bool paused = ndspChnIsPaused(CHANNEL);
|
|
||||||
ndspChnSetPaused(CHANNEL, !paused);
|
|
||||||
return !paused;
|
|
||||||
}
|
|
||||||
|
|
||||||
void stopPlayback(void)
|
|
||||||
{
|
|
||||||
stop = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isPlaying(void)
|
|
||||||
{
|
|
||||||
return !stop;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtains file type.
|
|
||||||
*
|
|
||||||
* \param file File location.
|
|
||||||
* \return File type, else negative and errno set.
|
|
||||||
*/
|
|
||||||
int getFileType(const char *file)
|
|
||||||
{
|
|
||||||
FILE* ftest = fopen(file, "rb");
|
|
||||||
int fileSig = 0;
|
|
||||||
enum file_types file_type = FILE_TYPE_ERROR;
|
|
||||||
|
|
||||||
/* Failure opening file */
|
|
||||||
if(ftest == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if(fread(&fileSig, 4, 1, ftest) == 0)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
switch(fileSig)
|
|
||||||
{
|
|
||||||
// "RIFF"
|
|
||||||
case 0x46464952:
|
|
||||||
if(fseek(ftest, 4, SEEK_CUR) != 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// "WAVE"
|
|
||||||
// Check required as AVI file format also uses "RIFF".
|
|
||||||
if(fread(&fileSig, 4, 1, ftest) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if(fileSig != 0x45564157)
|
|
||||||
break;
|
|
||||||
|
|
||||||
file_type = FILE_TYPE_WAV;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// "fLaC"
|
|
||||||
case 0x43614c66:
|
|
||||||
file_type = FILE_TYPE_FLAC;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// "OggS"
|
|
||||||
case 0x5367674f:
|
|
||||||
if(isOpus(file) == 0)
|
|
||||||
file_type = FILE_TYPE_OPUS;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//file_type = FILE_TYPE_OGG;
|
|
||||||
errno = FILE_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
/*
|
|
||||||
* MP3 without ID3 tag, ID3v1 tag is at the end of file, or MP3
|
|
||||||
* with ID3 tag at the beginning of the file.
|
|
||||||
*/
|
|
||||||
if((fileSig << 16) == 0xFBFF0000 ||
|
|
||||||
(fileSig << 16) == 0xFAFF0000 ||
|
|
||||||
(fileSig << 8) == 0x33444900)
|
|
||||||
{
|
|
||||||
file_type = FILE_TYPE_MP3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: Add this again at some point */
|
|
||||||
//printf("Unknown magic number: %#010x\n.", fileSig);
|
|
||||||
errno = FILE_NOT_SUPPORTED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
err:
|
|
||||||
fclose(ftest);
|
|
||||||
return file_type;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -17,6 +17,13 @@ struct playbackInfo_t
|
|||||||
struct errInfo_t* errInfo;
|
struct errInfo_t* errInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should only be called from a new thread only, and have only one playback
|
||||||
|
* thread at time. This function has not been written for more than one
|
||||||
|
* playback thread in mind.
|
||||||
|
*
|
||||||
|
* \param infoIn Playback information.
|
||||||
|
*/
|
||||||
void playFile(void* infoIn);
|
void playFile(void* infoIn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,16 +33,14 @@ void playFile(void* infoIn);
|
|||||||
*/
|
*/
|
||||||
bool togglePlayback(void);
|
bool togglePlayback(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops current playback. Playback thread should exit as a result.
|
||||||
|
*/
|
||||||
void stopPlayback(void);
|
void stopPlayback(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether music is playing or paused.
|
||||||
|
*/
|
||||||
bool isPlaying(void);
|
bool isPlaying(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtains file type.
|
|
||||||
*
|
|
||||||
* \param file File location.
|
|
||||||
* \return File type, else negative.
|
|
||||||
*/
|
|
||||||
int getFileType(const char *file);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user